Files
deepseek-harness/packages/scaffold/helper/src/features/resources.ts
Tianyi Cui 3fc35c91ff refactor(packages): dissolve ui/ and rename sdk/ to scaffold/
git mv per the regrouping RFC: the five human-collaboration seams and
tui join packages/interaction/, app-boot becomes packages/boot/, and
jsonrpc joins the renamed scaffold/ (formerly sdk/) as its server half
beside client/protocol/create-sdk/helper/scripts/telemetry, whose
folders drop the legacy sdk- prefix. Three new group README triplets
replace the ui/ and sdk/ ones; tsconfig references/paths/globs,
knip keys, vitest globs, gate scripts, catalogs, docs, and the
lockfile follow. Adds the four settled FIXME rename markers
(dsh-sdk-server, dsh-sdk-telemetry, dsh-sdk-helper, dsh-sdk-scripts).

The scaffold folders diverge from their npm names until those renames
land, so tsconfig.base.json maps the three affected names explicitly
beside the group wildcard. Also repairs two pre-existing stale-path
classes the strengthened sweep surfaced: docs/web-styling.md's retired
web-ui host package and type-model spec fixture-literal joins.

app-boot's three Loader-composition specs time out at the default 5s
under full-suite parallel load on this filesystem (pre-existing;
pass isolated with --testTimeout=30000); interaction/scaffold/boot
suites otherwise green (687 passed).
2026-08-09 01:21:12 +08:00

98 lines
3.0 KiB
TypeScript

/**
* Resource vocabulary contributed by builtin SDK features.
*
* @module @deepseek-ai/dsh-helper/features/resources
*/
import type { CordisConfigEntry } from '../documents/cordis-yaml-file.ts'
import type { ProjectFile } from '../documents/project-file.ts'
import type { ResourceKey } from '../ids.ts'
/** Runtime or development NPM dependency contribution. */
export interface NpmDependencyResource {
kind: 'npm-dependency'
key: ResourceKey
name: string
section: 'dependencies' | 'devDependencies'
}
/** Feature-owned package script. */
export interface PackageScriptResource {
kind: 'package-script'
key: ResourceKey
name: string
command: string
removeOnlyWhenUnchanged: boolean
}
/** Owned Cordis config entry plus the config keys safe to update in place. */
export interface CordisConfigEntryResource {
kind: 'cordis-config-entry'
key: ResourceKey
entry: CordisConfigEntry
ownedConfigKeys: readonly string[]
commentedExample?: string
validateConfig?: (config: Readonly<Record<string, unknown>>) => readonly string[]
}
/** Environment variable reference and dotenv material. */
export interface EnvironmentResource {
kind: 'environment'
key: ResourceKey
name: string
value?: string
exampleValue: string
comment?: string
}
/** Feature-exclusive complete file. */
export interface OwnedFileResource {
kind: 'owned-file'
key: ResourceKey
document: ProjectFile
removeOnlyWhenUnchanged: boolean
}
/** Any resource a feature can add to a project. */
export type ProjectResource =
| NpmDependencyResource
| PackageScriptResource
| CordisConfigEntryResource
| EnvironmentResource
| OwnedFileResource
/** Complete resource contribution for one selected feature state. */
export class ProjectContribution {
readonly resources: readonly ProjectResource[]
/** Validate and retain one feature-owned resource set. */
constructor(resources: readonly ProjectResource[]) {
const seen = new Set<ResourceKey>()
for (const resource of resources) {
if (seen.has(resource.key)) throw new Error(`duplicate contribution resource key: ${resource.key}`)
seen.add(resource.key)
}
this.resources = resources
}
/** Merge base and option contributions by stable key. */
static merge(...contributions: readonly ProjectContribution[]): ProjectContribution {
const resources = new Map<ResourceKey, ProjectResource>()
for (const contribution of contributions) {
for (const resource of contribution.resources) {
const previous = resources.get(resource.key)
if (previous && JSON.stringify(previous) !== JSON.stringify(resource)) {
throw new Error(`resource ${resource.key} has conflicting definitions inside one feature`)
}
resources.set(resource.key, resource)
}
}
return new ProjectContribution([...resources.values()])
}
/** Index resources by stable key. */
byKey(): ReadonlyMap<ResourceKey, ProjectResource> {
return new Map(this.resources.map(resource => [resource.key, resource]))
}
}