fix(sdk): address project tooling review findings
This commit is contained in:
@@ -56,6 +56,7 @@ function canUpdateResource(previous: ProjectResource, next: ProjectResource): bo
|
||||
if (previous.kind !== next.kind) return false
|
||||
switch (previous.kind) {
|
||||
case 'npm-dependency': return previous.name === (next as typeof previous).name
|
||||
case 'package-script': return previous.name === (next as typeof previous).name
|
||||
case 'cordis-config-entry': {
|
||||
const candidate = next as typeof previous
|
||||
return previous.entry.name === candidate.entry.name
|
||||
@@ -282,7 +283,10 @@ export class ProjectEditSession implements FeatureProjectView {
|
||||
continue
|
||||
}
|
||||
await mkdir(dirname(absolute), { recursive: true })
|
||||
await writeFile(absolute, document.serialize(), 'utf8')
|
||||
await writeFile(absolute, document.serialize(), {
|
||||
encoding: 'utf8',
|
||||
...document.createMode === undefined ? {} : { mode: document.createMode },
|
||||
})
|
||||
}
|
||||
this.committed = true
|
||||
return { project: await this.source.reopen(), changes }
|
||||
@@ -369,6 +373,21 @@ export class ProjectEditSession implements FeatureProjectView {
|
||||
this.manifest().setNpmDependency(dependency.section, resource.name, dependency.spec)
|
||||
return
|
||||
}
|
||||
case 'package-script': {
|
||||
const manifest = this.manifest()
|
||||
const current = manifest.script(resource.name)
|
||||
if (!previous || previous.kind !== 'package-script') {
|
||||
if (current !== undefined) throw new Error(`feature-owned package script already exists: ${resource.name}`)
|
||||
manifest.setScript(resource.name, resource.command)
|
||||
return
|
||||
}
|
||||
if (current === resource.command) return
|
||||
if (current !== previous.command) {
|
||||
throw new Error(`feature-owned package script was modified: ${resource.name}`)
|
||||
}
|
||||
manifest.setScript(resource.name, resource.command)
|
||||
return
|
||||
}
|
||||
case 'cordis-config-entry': {
|
||||
const current = this.cordis().entry(resource.entry.id)
|
||||
if (!current) this.cordis().addEntry(resource.entry)
|
||||
@@ -412,7 +431,9 @@ export class ProjectEditSession implements FeatureProjectView {
|
||||
if (existing.serialize() !== previous.document.serialize()) {
|
||||
throw new Error(`feature-owned file was modified: ${resource.document.relativePath}`)
|
||||
}
|
||||
throw new Error(`updating feature-owned files is not supported: ${resource.document.relativePath}`)
|
||||
this.documents.set(resource.document.relativePath, resource.document.clone())
|
||||
this.removed.delete(resource.document.relativePath)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,6 +443,16 @@ export class ProjectEditSession implements FeatureProjectView {
|
||||
case 'npm-dependency':
|
||||
this.manifest().removeNpmDependency(resource.section, resource.name)
|
||||
return
|
||||
case 'package-script': {
|
||||
const manifest = this.manifest()
|
||||
const current = manifest.script(resource.name)
|
||||
if (current === undefined) throw new Error(`owned package script is missing: ${resource.name}`)
|
||||
if (resource.removeOnlyWhenUnchanged && current !== resource.command) {
|
||||
throw new Error(`feature-owned package script was modified: ${resource.name}`)
|
||||
}
|
||||
manifest.removeScript(resource.name)
|
||||
return
|
||||
}
|
||||
case 'cordis-config-entry': {
|
||||
const entry = this.cordis().entry(resource.entry.id)
|
||||
if (!entry || entry.name !== resource.entry.name) {
|
||||
|
||||
@@ -18,9 +18,9 @@ import {
|
||||
type PackageManagerName,
|
||||
} from '../package-managers/package-manager.ts'
|
||||
import {
|
||||
createBaselineProjectArtifacts,
|
||||
createPackageJsonDoc,
|
||||
createProjectArtifacts,
|
||||
type ProjectTemplateContext,
|
||||
createProjectTemplateContext,
|
||||
} from '../templates/project-template.ts'
|
||||
import type { ProjectCreationRequest, ProjectProfile, RunInterface } from './types.ts'
|
||||
import type { FeatureRegistry } from '../features/registry.ts'
|
||||
@@ -36,6 +36,8 @@ const OPTIONAL_DOCUMENTS = [
|
||||
'pnpm-workspace.yaml',
|
||||
'hooks.json',
|
||||
'codex-hooks.json',
|
||||
'README.md',
|
||||
'index.ts',
|
||||
] as const
|
||||
|
||||
function runInterface(entries: readonly CordisConfigEntry[]): RunInterface {
|
||||
@@ -113,22 +115,6 @@ function parseOptionalDocument(path: string, text: string): ProjectFile {
|
||||
}
|
||||
}
|
||||
|
||||
function templateContext(profile: ProjectProfile): ProjectTemplateContext {
|
||||
return {
|
||||
name: profile.name,
|
||||
description: profile.description,
|
||||
releaseVersion: profile.releaseVersion,
|
||||
model: profile.runtime.model,
|
||||
modelLiteral: JSON.stringify(profile.runtime.model),
|
||||
isAcp: profile.runInterface === 'acp',
|
||||
isStdio: profile.runInterface === 'stdio',
|
||||
isEmbed: profile.runInterface === 'embed',
|
||||
packageManager: profile.packageManager.name,
|
||||
installArgs: profile.packageManager.installCommand().join(' '),
|
||||
buildArgs: profile.packageManager.buildCommand().join(' '),
|
||||
}
|
||||
}
|
||||
|
||||
/** A project snapshot whose documents can only be changed through {@link ProjectEditSession}. */
|
||||
export class SdkProject {
|
||||
/** Absolute project directory. */
|
||||
@@ -172,7 +158,7 @@ export class SdkProject {
|
||||
releaseVersion: request.releaseVersion,
|
||||
...request.linkWorkspaceRoot ? { linkWorkspaceRoot: resolve(request.linkWorkspaceRoot) } : {},
|
||||
}
|
||||
const templates = templateContext(profile)
|
||||
const templates = createProjectTemplateContext(profile)
|
||||
const manifest = createPackageJsonDoc(templates)
|
||||
const documents = new Map<string, ProjectFile>()
|
||||
documents.set(manifest.relativePath, manifest)
|
||||
@@ -182,7 +168,7 @@ export class SdkProject {
|
||||
for (const document of request.packageManager.configureWorkspace(manifest)) {
|
||||
documents.set(document.relativePath, document)
|
||||
}
|
||||
for (const document of createProjectArtifacts(templates)) {
|
||||
for (const document of createBaselineProjectArtifacts(templates)) {
|
||||
documents.set(document.relativePath, document)
|
||||
}
|
||||
return new SdkProject(root, 'create', profile, documents)
|
||||
|
||||
Reference in New Issue
Block a user