实现小游戏与小程序项目创建发布

This commit is contained in:
2026-08-09 13:31:06 +08:00
parent a6fe14a8d6
commit 493b31cff0
26 changed files with 1827 additions and 39 deletions

View File

@@ -2,11 +2,14 @@ import path from 'node:path';
import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
import {
createProjectConfig,
isProjectType,
validateAgentConfigs,
validateAgentNames,
type ProjectAgentConfig,
type ProjectConfig,
type ProjectType,
} from '../../shared/project-config';
import { createPublishableProjectTemplate } from './project-template';
export const PROJECT_CONFIG_PATH = '.niancode/project.json';
@@ -22,6 +25,12 @@ function normalizeStringList(value: unknown): string[] {
.filter(Boolean))];
}
function normalizeProjectType(value: unknown): ProjectType {
if (value === undefined) return 'custom';
if (isProjectType(value)) return value;
throw new Error('Invalid project type');
}
function normalizeAgent(value: unknown): ProjectAgentConfig | null {
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
const raw = value as Partial<ProjectAgentConfig>;
@@ -86,6 +95,7 @@ export function normalizeProjectConfig(value: unknown): ProjectConfig {
}
return {
schemaVersion: 1,
projectType: normalizeProjectType(raw.projectType),
initialized,
superpowersEnabled: raw.superpowersEnabled === true,
defaultModel: typeof raw.defaultModel === 'string' && raw.defaultModel.trim()
@@ -231,9 +241,9 @@ Last Updated By: user
export async function createInitialProjectConfig(
projectPath: string,
options?: { defaultModel?: string | null },
options?: { defaultModel?: string | null; projectType?: ProjectType },
): Promise<ProjectConfig> {
const config = createProjectConfig();
const config = createProjectConfig(new Date().toISOString(), options?.projectType ?? 'custom');
if (typeof options?.defaultModel === 'string' && options.defaultModel.trim()) {
config.defaultModel = options.defaultModel.trim();
}
@@ -242,15 +252,25 @@ export async function createInitialProjectConfig(
await writeFile(configPath(projectPath), `${JSON.stringify(config, null, 2)}\n`, { encoding: 'utf8', flag: 'wx' });
await writeFile(path.join(projectPath, 'VERSION.md'), initialVersionDocument(config.createdAt), { encoding: 'utf8', flag: 'wx' });
await writeFile(path.join(projectPath, 'TASKS.md'), initialTaskDocument(), { encoding: 'utf8', flag: 'wx' });
if (config.projectType !== 'custom') {
await createPublishableProjectTemplate(projectPath, config.projectType);
}
return config;
}
export async function writeProjectConfig(projectPath: string, value: unknown): Promise<ProjectConfig> {
const previous = await readProjectConfig(projectPath);
if (previous.status !== 'valid') throw new Error('Project configuration is missing or invalid');
const requestedProjectType = value && typeof value === 'object' && !Array.isArray(value)
? (value as { projectType?: unknown }).projectType
: undefined;
if (requestedProjectType !== undefined && requestedProjectType !== previous.config.projectType) {
throw new Error('已有项目类型不可更改');
}
const config = normalizeProjectConfig({
...(value as object),
schemaVersion: 1,
projectType: previous.config.projectType,
createdAt: previous.config.createdAt,
updatedAt: new Date().toISOString(),
});