feat(sdk): add developer project tooling
docs(rfc): propose SDK developer project tooling feat: rename / docs ci: fix windows gates docs: revert
This commit is contained in:
86
packages/sdk/helper/src/features/resources.ts
Normal file
86
packages/sdk/helper/src/features/resources.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 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'
|
||||
}
|
||||
|
||||
/** 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[]
|
||||
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
|
||||
| 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]))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user