@percepta/create 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,9 +8,9 @@ Scaffold and manage Mosaic packages.
8
8
  npx @percepta/create
9
9
  ```
10
10
 
11
- That's it. The CLI prompts you for the package type, repo name, customer slug,
12
- and package name as needed. Defaults yield a running app — sign in as
13
- `app-admin@example.com` / `password`.
11
+ That's it. Outside a monorepo, the CLI prompts you for the customer slug, repo
12
+ name, package type, and package name as needed. Defaults yield a running app —
13
+ sign in as `app-admin@example.com` / `password`.
14
14
 
15
15
  ## Options (mostly for automation)
16
16
 
@@ -41,7 +41,7 @@ The bare command above is the canonical UX. The flags below exist for tests and
41
41
 
42
42
  `create` auto-detects whether you're inside an existing pnpm monorepo (by walking up for `pnpm-workspace.yaml`) and changes its prompts accordingly:
43
43
 
44
- - **Outside a monorepo** — you're asked for the repo name, whether to initialize with a webapp (Y/n, default Y), and the customer slug stored in `.mosaic-workspace.json`. Picking the webapp option also asks for the webapp name and scaffolds it inside `packages/<webapp-name>/`. Declining gives you an empty monorepo.
44
+ - **Outside a monorepo** — you're asked for the customer slug, then the repo name, which defaults to `<customer>-os`. Then choose whether to initialize with a webapp (Y/n, default Y). Picking the webapp option also asks for the webapp name and scaffolds it inside `packages/<webapp-name>/`. Declining gives you an empty monorepo.
45
45
  - **Inside a monorepo** — pick `Webapp` (default) or `Library` to add a new package under the workspace pattern.
46
46
 
47
47
  Generated monorepos include a root `.mosaic-workspace.json` with the customer
package/dist/index.js CHANGED
@@ -152,11 +152,12 @@ const VALID_PROJECT_TYPES = [
152
152
  function isValidProjectType(value) {
153
153
  return typeof value === "string" && VALID_PROJECT_TYPES.includes(value);
154
154
  }
155
- async function promptName(message) {
155
+ async function promptName(message, defaultName) {
156
156
  const { name } = await inquirer.prompt([{
157
157
  type: "input",
158
158
  name: "name",
159
159
  message,
160
+ default: defaultName,
160
161
  filter: toKebabCase,
161
162
  validate: (input) => {
162
163
  const result = validateProjectName(toKebabCase(input));
@@ -165,12 +166,11 @@ async function promptName(message) {
165
166
  }]);
166
167
  return name;
167
168
  }
168
- async function promptCustomerSlug(defaultCustomerSlug) {
169
+ async function promptCustomerSlug() {
169
170
  const { customerSlug } = await inquirer.prompt([{
170
171
  type: "input",
171
172
  name: "customerSlug",
172
173
  message: "Customer slug?",
173
- default: defaultCustomerSlug,
174
174
  filter: toKebabCase,
175
175
  validate: (input) => {
176
176
  const result = validateProjectName(toKebabCase(input));
@@ -179,10 +179,11 @@ async function promptCustomerSlug(defaultCustomerSlug) {
179
179
  }]);
180
180
  return customerSlug;
181
181
  }
182
- async function resolveCustomerSlug(repoName, defaults) {
182
+ async function resolveCustomerSlug(defaults) {
183
183
  if (defaults.customerSlug) return defaults.customerSlug;
184
- if (defaults.projectType && defaults.name) return repoName;
185
- return promptCustomerSlug(repoName);
184
+ if (defaults.projectType === "monorepo" && defaults.name) return defaults.name;
185
+ if (defaults.projectType && defaults.name && defaults.repoName) return defaults.repoName;
186
+ return promptCustomerSlug();
186
187
  }
187
188
  async function promptDesignTheme() {
188
189
  const { designTheme } = await inquirer.prompt([{
@@ -250,11 +251,11 @@ async function promptProjectDetails(defaults) {
250
251
  await defaults.beforeNamePrompt?.(projectType);
251
252
  finalName = defaults.name || await promptName("Package name?");
252
253
  } else {
253
- const repoName = defaults.repoName || (defaults.projectType === "monorepo" ? defaults.name : void 0) || await promptName("Repo name?");
254
+ const customerSlug = await resolveCustomerSlug(defaults);
255
+ const repoName = defaults.repoName || (defaults.projectType === "monorepo" ? defaults.name : void 0) || await promptName("Repo name?", `${customerSlug}-os`);
254
256
  const repoTitle = toTitleCase(repoName);
255
257
  projectType = defaults.projectType ?? await promptOutsideMonorepoType();
256
258
  await defaults.beforeNamePrompt?.(projectType);
257
- const customerSlug = await resolveCustomerSlug(repoName, defaults);
258
259
  if (projectType === "monorepo") {
259
260
  finalName = repoName;
260
261
  const finalTitle = repoTitle;
@@ -908,7 +909,7 @@ async function createProject(options) {
908
909
  ensureWorkspaceCreateVersionCompatible(workspaceManifest, projectType);
909
910
  requireNpmTokenForWebappInstall(projectType, !options.skipInstall);
910
911
  const kebabName = toKebabCase(projectName);
911
- const kebabRepoName = repoName ? toKebabCase(repoName) : kebabName;
912
+ const kebabRepoName = repoName ? toKebabCase(repoName) : customerSlug ? `${customerSlug}-os` : kebabName;
912
913
  answers = {
913
914
  projectType,
914
915
  directory: monorepoContext.found && monorepoContext.packageDir ? path.join(monorepoContext.packageDir, kebabName) : path.resolve(cwd, kebabRepoName),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["SKIP_DIRS","SKIP_FILES","exhaustiveCheck"],"sources":["../src/utils/copy-template.ts","../src/utils/detect-monorepo.ts","../src/utils/env-local.ts","../src/utils/package-metadata.ts","../src/utils/prompts.ts","../src/utils/relocate-workflows.ts","../src/utils/replace-placeholders.ts","../src/utils/workspace-manifest.ts","../src/commands/create.ts","../src/index.ts"],"sourcesContent":["import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport fs from \"fs-extra\";\n\n// Template type includes \"monorepo\" for internal use even though\n// it's no longer a user-facing choice\nexport type TemplateType = \"monorepo\" | \"webapp\" | \"library\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Directories to skip during copy\nconst SKIP_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \"dist\",\n \".turbo\",\n \".vercel\",\n \".cursor\",\n]);\n\n// Files to skip during copy\nconst SKIP_FILES = new Set([\n \"pnpm-lock.yaml\",\n \"package-lock.json\",\n \"yarn.lock\",\n \".DS_Store\",\n]);\n\n// Files that have .template extension that should be renamed\nconst TEMPLATE_FILE_MAPPINGS: Record<string, string> = {\n \"package.json.template\": \"package.json\",\n \"gitignore.template\": \".gitignore\",\n \"env.example.template\": \".env.example\",\n \"npmrc.template\": \".npmrc\",\n // Suffixed so mosaic's own oxlint/oxfmt don't discover these as nested\n // configs (a scaffolded monorepo's root config is invalid as a nested one).\n \"oxlint.config.ts.template\": \"oxlint.config.ts\",\n \"oxfmt.config.ts.template\": \"oxfmt.config.ts\",\n};\n\nfunction shouldSkip(src: string): boolean {\n const basename = path.basename(src);\n\n if (SKIP_DIRS.has(basename)) return true;\n if (SKIP_FILES.has(basename)) return true;\n\n return false;\n}\n\nfunction getTemplateDir(templateType: TemplateType): string {\n // Templates are located relative to the bundled output at ../templates/<type>\n // When bundled, __dirname is dist/, so we go up one level to find templates/\n return path.resolve(__dirname, \"../templates\", templateType);\n}\n\nexport async function copyTemplate(\n targetDir: string,\n templateType: TemplateType,\n): Promise<void> {\n const templateDir = getTemplateDir(templateType);\n\n // Ensure template directory exists\n if (!(await fs.pathExists(templateDir))) {\n throw new Error(`Template directory not found: ${templateDir}`);\n }\n\n // Create target directory\n await fs.ensureDir(targetDir);\n\n // Copy template with filtering\n await fs.copy(templateDir, targetDir, {\n filter: (src) => !shouldSkip(src),\n });\n\n // Rename .template files\n for (const [templateName, targetName] of Object.entries(\n TEMPLATE_FILE_MAPPINGS,\n )) {\n const templatePath = path.join(targetDir, templateName);\n const targetPath = path.join(targetDir, targetName);\n\n if (await fs.pathExists(templatePath)) {\n await fs.move(templatePath, targetPath, { overwrite: true });\n }\n }\n\n // Recreate the Claude symlink after copy because published packages\n // cannot rely on template symlinks being preserved.\n if (templateType === \"webapp\") {\n const agentsPath = path.join(targetDir, \"AGENTS.md\");\n const claudePath = path.join(targetDir, \"CLAUDE.md\");\n\n if (await fs.pathExists(agentsPath)) {\n if (await fs.pathExists(claudePath)) {\n await fs.remove(claudePath);\n }\n await fs.ensureSymlink(\"AGENTS.md\", claudePath);\n }\n }\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport { parse } from \"yaml\";\n\nexport interface MonorepoContext {\n found: boolean;\n rootDir: string | null;\n workspacePatterns: string[];\n packageDir: string | null; // e.g., \"/abs/path/to/monorepo/packages\"\n}\n\nconst NOT_FOUND: MonorepoContext = {\n found: false,\n rootDir: null,\n workspacePatterns: [],\n packageDir: null,\n};\n\n/**\n * Walk up from `startDir` looking for pnpm-workspace.yaml.\n * If found, parse it and derive the package directory.\n */\nexport async function detectMonorepo(\n startDir: string,\n): Promise<MonorepoContext> {\n let current = path.resolve(startDir);\n const root = path.parse(current).root;\n\n while (current !== root) {\n const workspaceFile = path.join(current, \"pnpm-workspace.yaml\");\n\n if (await fs.pathExists(workspaceFile)) {\n try {\n const content = await fs.readFile(workspaceFile, \"utf-8\");\n const parsed = parse(content) as { packages?: string[] } | null;\n\n if (!parsed?.packages || !Array.isArray(parsed.packages)) {\n return NOT_FOUND;\n }\n\n const workspacePatterns = parsed.packages;\n\n // Derive package directory from the first pattern\n // e.g., \"packages/*\" → \"packages\"\n const firstPattern = workspacePatterns[0];\n if (!firstPattern) {\n return NOT_FOUND;\n }\n\n const baseDir = firstPattern.replace(/\\/?\\*.*$/, \"\").trim();\n const packageDir = path.join(current, baseDir);\n\n return {\n found: true,\n rootDir: current,\n workspacePatterns,\n packageDir,\n };\n } catch {\n return NOT_FOUND;\n }\n }\n\n current = path.dirname(current);\n }\n\n return NOT_FOUND;\n}\n","import { randomBytes } from \"node:crypto\";\nimport path from \"node:path\";\nimport fs from \"fs-extra\";\n\n/**\n * Writes .env.local for the webapp template with real generated values for\n * BETTER_AUTH_SECRET and ENCRYPTION_SECRET_KEY so the user can run dev/seed\n * immediately. The .env.example file remains the documentation source.\n *\n * This is a no-op if .env.local already exists.\n */\nexport async function generateEnvLocal(packageDir: string): Promise<void> {\n const examplePath = path.join(packageDir, \".env.example\");\n const localPath = path.join(packageDir, \".env.local\");\n if (!(await fs.pathExists(examplePath))) return;\n\n if (!(await fs.pathExists(localPath))) {\n const authSecret = randomBytes(32).toString(\"base64\");\n const encKey = randomBytes(16).toString(\"hex\");\n\n const content = (await fs.readFile(examplePath, \"utf-8\"))\n .replace(/^BETTER_AUTH_SECRET=.*$/m, `BETTER_AUTH_SECRET=${authSecret}`)\n .replace(\n /^ENCRYPTION_SECRET_KEY=.*$/m,\n `ENCRYPTION_SECRET_KEY=${encKey}`,\n );\n\n await fs.writeFile(localPath, content);\n }\n}\n","import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport fs from \"fs-extra\";\n\nexport interface CreatePackageMetadata {\n name: string;\n version: string;\n}\n\nconst FALLBACK_METADATA: CreatePackageMetadata = {\n name: \"@percepta/create\",\n version: \"0.0.0\",\n};\n\nexport function readCreatePackageMetadata(): CreatePackageMetadata {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(currentDir, \"../package.json\"),\n path.resolve(currentDir, \"../../package.json\"),\n ];\n\n for (const packageJsonPath of candidates) {\n try {\n const pkg = fs.readJsonSync(packageJsonPath) as {\n name?: unknown;\n version?: unknown;\n };\n if (typeof pkg.name === \"string\" && typeof pkg.version === \"string\") {\n return { name: pkg.name, version: pkg.version };\n }\n } catch {\n // Source tests and bundled CLI resolve from different directories.\n }\n }\n\n return FALLBACK_METADATA;\n}\n","import path from \"node:path\";\nimport inquirer from \"inquirer\";\nimport { toKebabCase, toTitleCase } from \"./case-converters.js\";\nimport {\n DEFAULT_MOSAIC_DESIGN_THEME,\n type MosaicDesignTheme,\n VALID_MOSAIC_DESIGN_THEMES,\n} from \"./design-theme.js\";\nimport type { MonorepoContext } from \"./detect-monorepo.js\";\nimport { validateProjectName } from \"./validate.js\";\n\nexport const VALID_PROJECT_TYPES = [\"monorepo\", \"webapp\", \"library\"] as const;\nexport type ProjectType = (typeof VALID_PROJECT_TYPES)[number];\n\nexport function isValidProjectType(value: unknown): value is ProjectType {\n return (\n typeof value === \"string\" &&\n VALID_PROJECT_TYPES.includes(value as ProjectType)\n );\n}\n\nexport interface ProjectAnswers {\n projectType: ProjectType;\n directory: string;\n name: string;\n title: string;\n installDeps: boolean;\n customerSlug?: string;\n designTheme?: MosaicDesignTheme;\n monorepoName?: string;\n monorepoTitle?: string;\n}\n\ninterface PromptDefaults {\n projectType?: ProjectType;\n name?: string;\n customerSlug?: string;\n designTheme?: MosaicDesignTheme;\n repoName?: string;\n skipInstall?: boolean;\n monorepoContext?: MonorepoContext;\n cwd?: string;\n beforeNamePrompt?: (projectType: ProjectType) => void | Promise<void>;\n}\n\nasync function promptName(message: string): Promise<string> {\n // We kebab-case both inside `validate` (inquirer runs validate on the raw\n // input, before filter) and via `filter` (so the stored answer is also\n // kebab-cased). That way \"My App\" → \"my-app\" without bouncing the user with\n // a capital-letters error.\n const { name } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"name\",\n message,\n filter: toKebabCase,\n validate: (input: string) => {\n const result = validateProjectName(toKebabCase(input));\n return result.valid || result.error || \"Invalid project name\";\n },\n },\n ]);\n return name;\n}\n\nasync function promptCustomerSlug(\n defaultCustomerSlug: string,\n): Promise<string> {\n const { customerSlug } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"customerSlug\",\n message: \"Customer slug?\",\n default: defaultCustomerSlug,\n filter: toKebabCase,\n validate: (input: string) => {\n const result = validateProjectName(toKebabCase(input));\n return result.valid || result.error || \"Invalid customer slug\";\n },\n },\n ]);\n return customerSlug;\n}\n\nasync function resolveCustomerSlug(\n repoName: string,\n defaults: PromptDefaults,\n): Promise<string> {\n if (defaults.customerSlug) return defaults.customerSlug;\n\n // Automation commonly provides the package/repo flags without `--yes`.\n // Keep that flow prompt-free and use the repo name as the customer slug\n // unless the caller provided --customer.\n if (defaults.projectType && defaults.name) return repoName;\n\n return promptCustomerSlug(repoName);\n}\n\nasync function promptDesignTheme(): Promise<MosaicDesignTheme> {\n const { designTheme } = await inquirer.prompt([\n {\n type: \"rawlist\",\n name: \"designTheme\",\n message: \"Design theme?\",\n default: DEFAULT_MOSAIC_DESIGN_THEME,\n choices: VALID_MOSAIC_DESIGN_THEMES.map((theme) => ({\n name: theme,\n value: theme,\n })),\n },\n ]);\n return designTheme;\n}\n\nasync function resolveDesignTheme(\n projectType: ProjectType,\n defaults: PromptDefaults,\n): Promise<MosaicDesignTheme | undefined> {\n if (projectType !== \"webapp\") return undefined;\n if (defaults.designTheme) return defaults.designTheme;\n\n // Automation commonly provides both --type and --name without --yes. Keep\n // that flow prompt-free and use the canonical default theme.\n if (defaults.projectType && defaults.name) return DEFAULT_MOSAIC_DESIGN_THEME;\n\n return promptDesignTheme();\n}\n\n/**\n * Outside a monorepo we collect the repo name first, then ask a single\n * \"is it a webapp?\" Y/n. Yes (default) → monorepo + webapp, no → bare\n * monorepo. Library at the top level is rare enough that we leave it as a\n * `--type library` flag rather than a third prompt option. The repo name is\n * collected separately from any initial package name so a customer monorepo\n * is not forced to share its first app's name.\n */\nasync function promptOutsideMonorepoType(): Promise<ProjectType> {\n const { webapp } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"webapp\",\n message: \"Initialize with a webapp?\",\n default: true,\n },\n ]);\n return webapp ? \"webapp\" : \"monorepo\";\n}\n\n/**\n * Inside a monorepo, both webapp and library are common, so present them as\n * a numbered rawlist — user presses 1 or 2 + Enter. Defaults to webapp.\n */\nasync function promptInsideMonorepoType(): Promise<ProjectType> {\n const { projectType } = await inquirer.prompt([\n {\n type: \"rawlist\",\n name: \"projectType\",\n message: \"What kind of package?\",\n // inquirer v12 / @inquirer/rawlist v5 matches `default` against the\n // choice's `value`, not its index. `default: 0` would be a no-op.\n default: \"webapp\",\n choices: [\n { name: \"Webapp — A Next.js webapp\", value: \"webapp\" },\n { name: \"Library — A TypeScript library\", value: \"library\" },\n ],\n },\n ]);\n return projectType;\n}\n\nexport async function promptProjectDetails(\n defaults: PromptDefaults,\n): Promise<ProjectAnswers> {\n const inMonorepo = defaults.monorepoContext?.found ?? false;\n const cwd = defaults.cwd ?? process.cwd();\n\n let projectType: ProjectType;\n let finalName: string;\n if (inMonorepo) {\n // Resolve type before name so webapp preflights (notably NPM_TOKEN) can\n // fail before the user spends time naming a package.\n projectType = defaults.projectType ?? (await promptInsideMonorepoType());\n await defaults.beforeNamePrompt?.(projectType);\n finalName = defaults.name || (await promptName(\"Package name?\"));\n } else {\n const repoName =\n defaults.repoName ||\n (defaults.projectType === \"monorepo\" ? defaults.name : undefined) ||\n (await promptName(\"Repo name?\"));\n const repoTitle = toTitleCase(repoName);\n\n projectType = defaults.projectType ?? (await promptOutsideMonorepoType());\n await defaults.beforeNamePrompt?.(projectType);\n const customerSlug = await resolveCustomerSlug(repoName, defaults);\n\n if (projectType === \"monorepo\") {\n finalName = repoName;\n const finalTitle = repoTitle;\n const finalDirectory = path.resolve(cwd, repoName);\n\n return {\n projectType,\n directory: finalDirectory,\n name: finalName,\n title: finalTitle,\n installDeps: !defaults.skipInstall,\n customerSlug,\n monorepoName: repoName,\n monorepoTitle: repoTitle,\n };\n }\n\n const packageNamePrompt =\n projectType === \"webapp\" ? \"Webapp name?\" : \"Library name?\";\n finalName = defaults.name || (await promptName(packageNamePrompt));\n const designTheme = await resolveDesignTheme(projectType, defaults);\n const finalTitle = toTitleCase(finalName);\n const finalDirectory = path.resolve(cwd, repoName);\n\n return {\n projectType,\n directory: finalDirectory,\n name: finalName,\n title: finalTitle,\n installDeps: !defaults.skipInstall,\n customerSlug,\n designTheme,\n monorepoName: repoName,\n monorepoTitle: repoTitle,\n };\n }\n\n // Inside a monorepo the directory is empty here — create.ts derives it from\n // the workspace pattern.\n const finalTitle = finalName ? toTitleCase(finalName) : \"\";\n const designTheme = await resolveDesignTheme(projectType, defaults);\n const finalDirectory =\n !inMonorepo && finalName ? path.resolve(cwd, finalName) : \"\";\n\n return {\n projectType,\n directory: finalDirectory,\n name: finalName,\n title: finalTitle,\n installDeps: !defaults.skipInstall,\n designTheme,\n };\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\n\n/**\n * Moves per-app GitHub Actions workflows from the package's .github/workflows\n * directory to the monorepo root, where GitHub Actions actually picks them up.\n *\n * Only moves files whose names start with the app name (e.g.\n * `myapp-ryvn-release.yaml`). Any other (generic) workflow a package happens\n * to ship is left in place — CI lives at the monorepo root, not per-package.\n *\n * Cleans up an empty `.github/workflows` (and empty parent `.github`) after\n * the move.\n */\nexport async function relocateWorkflowsToRoot(\n packageDir: string,\n monorepoRoot: string,\n appName: string,\n): Promise<void> {\n const sourceDir = path.join(packageDir, \".github\", \"workflows\");\n if (!(await fs.pathExists(sourceDir))) return;\n\n const targetDir = path.join(monorepoRoot, \".github\", \"workflows\");\n await fs.ensureDir(targetDir);\n\n const entries = await fs.readdir(sourceDir);\n for (const name of entries) {\n if (!name.startsWith(`${appName}-`)) continue;\n if (!/\\.(ya?ml)$/.test(name)) continue;\n await fs.move(path.join(sourceDir, name), path.join(targetDir, name), {\n overwrite: true,\n });\n }\n\n // Tidy up empty directories left behind in the package.\n if ((await fs.readdir(sourceDir)).length === 0) {\n await fs.rmdir(sourceDir);\n const packageGithub = path.join(packageDir, \".github\");\n if ((await fs.readdir(packageGithub)).length === 0) {\n await fs.rmdir(packageGithub);\n }\n }\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport type { MosaicDesignTheme } from \"./design-theme.js\";\n\nexport interface AppConfig {\n name: string; // kebab-case: my-awesome-app\n title: string; // Title Case: My Awesome App\n dbName: string; // snake_case: my_awesome_app_db\n nameUpper: string; // UPPER-CASE: MY-AWESOME-APP\n nameSnake: string; // snake_case: my_awesome_app\n repoName: string; // kebab-case GitHub repo name\n repoNameSnake: string; // snake_case GitHub repo name\n createPackage: string; // package used by generated monorepo helper scripts\n createVersion: string; // exact create package version pinned by generated monorepos\n designTheme: MosaicDesignTheme; // Mosaic design theme: modern, paper, dense\n}\n\nexport interface ReplaceStats {\n processed: number;\n modified: number;\n}\n\nconst PLACEHOLDERS = {\n __APP_NAME__: \"name\",\n __APP_TITLE__: \"title\",\n __DB_NAME__: \"dbName\",\n __APP_NAME_UPPER__: \"nameUpper\",\n __APP_NAME_SNAKE__: \"nameSnake\",\n __REPO_NAME__: \"repoName\",\n __REPO_NAME_SNAKE__: \"repoNameSnake\",\n __CREATE_PACKAGE__: \"createPackage\",\n __CREATE_VERSION__: \"createVersion\",\n __MOSAIC_DESIGN_THEME__: \"designTheme\",\n} as const;\n\n// Directories to skip\nconst SKIP_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \"dist\",\n \".turbo\",\n \".vercel\",\n]);\n\n// Files to skip\nconst SKIP_FILES = new Set([\n \"pnpm-lock.yaml\",\n \"package-lock.json\",\n \"yarn.lock\",\n]);\n\n// File extensions to process\nconst PROCESSABLE_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".yml\",\n \".yaml\",\n \".md\",\n \".env\",\n \".sql\",\n \".tf\",\n \".tfvars\",\n \".sh\",\n \".zed\",\n \".mjs\",\n \".cjs\",\n]);\n\n// Specific filenames to process (without extensions)\nconst PROCESSABLE_FILENAMES = new Set([\n \"Dockerfile\",\n \".env.example\",\n \".env.local\",\n \"terraform.tfvars.example\",\n]);\n\nfunction shouldProcessFile(filePath: string): boolean {\n const fileName = path.basename(filePath);\n const ext = path.extname(filePath);\n\n if (SKIP_FILES.has(fileName)) return false;\n if (PROCESSABLE_FILENAMES.has(fileName)) return true;\n\n return PROCESSABLE_EXTENSIONS.has(ext);\n}\n\nasync function replaceInFile(\n filePath: string,\n config: AppConfig,\n): Promise<boolean> {\n let content: string;\n try {\n content = await fs.readFile(filePath, \"utf-8\");\n } catch {\n return false;\n }\n\n let modified = false;\n let newContent = content;\n\n // Sort placeholders by length descending to prevent prefix collisions\n // (e.g., __APP_NAME__ must not be replaced before __APP_NAME_UPPER__)\n const sortedEntries = Object.entries(PLACEHOLDERS).sort(\n (a, b) => b[0].length - a[0].length,\n );\n\n for (const [placeholder, configKey] of sortedEntries) {\n const value = config[configKey as keyof AppConfig];\n if (newContent.includes(placeholder)) {\n newContent = newContent.split(placeholder).join(value);\n modified = true;\n }\n }\n\n if (modified) {\n await fs.writeFile(filePath, newContent);\n return true;\n }\n\n return false;\n}\n\nfunction substituteName(name: string, config: AppConfig): string {\n // Same precedence rule as content substitution: longer placeholders first\n // so __APP_NAME_UPPER__ is replaced before __APP_NAME__.\n const sortedEntries = Object.entries(PLACEHOLDERS).sort(\n (a, b) => b[0].length - a[0].length,\n );\n let result = name;\n for (const [placeholder, configKey] of sortedEntries) {\n if (result.includes(placeholder)) {\n result = result\n .split(placeholder)\n .join(config[configKey as keyof AppConfig]);\n }\n }\n return result;\n}\n\nasync function processDirectory(\n dirPath: string,\n config: AppConfig,\n stats: ReplaceStats,\n): Promise<void> {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n if (!SKIP_DIRS.has(entry.name)) {\n await processDirectory(fullPath, config, stats);\n }\n } else if (entry.isFile() && shouldProcessFile(fullPath)) {\n stats.processed++;\n if (await replaceInFile(fullPath, config)) {\n stats.modified++;\n }\n const renamed = substituteName(entry.name, config);\n if (renamed !== entry.name) {\n await fs.move(fullPath, path.join(dirPath, renamed), {\n overwrite: true,\n });\n }\n }\n }\n}\n\nexport async function replacePlaceholders(\n targetDir: string,\n config: AppConfig,\n): Promise<ReplaceStats> {\n const stats: ReplaceStats = { processed: 0, modified: 0 };\n await processDirectory(targetDir, config, stats);\n return stats;\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport { readCreatePackageMetadata } from \"./package-metadata.js\";\nimport { getTemplateVersion } from \"./template-versions.js\";\n\nexport const WORKSPACE_MANIFEST_FILENAME = \".mosaic-workspace.json\";\nexport const WORKSPACE_MANIFEST_SCHEMA_VERSION = 1;\n\nexport interface MosaicWorkspaceManifest {\n schemaVersion: typeof WORKSPACE_MANIFEST_SCHEMA_VERSION;\n customerSlug: string;\n createPackage: string;\n createVersion: string;\n monorepoTemplateVersion: string;\n compatibleTemplates: Record<string, string>;\n createdAt: string;\n}\n\nexport interface CreateWorkspaceManifestOptions {\n customerSlug: string;\n createdAt?: string;\n}\n\nexport function getWorkspaceManifestPath(rootDir: string): string {\n return path.join(rootDir, WORKSPACE_MANIFEST_FILENAME);\n}\n\nexport function createWorkspaceManifest({\n customerSlug,\n createdAt = new Date().toISOString(),\n}: CreateWorkspaceManifestOptions): MosaicWorkspaceManifest {\n const createPackage = readCreatePackageMetadata();\n return {\n schemaVersion: WORKSPACE_MANIFEST_SCHEMA_VERSION,\n customerSlug,\n createPackage: createPackage.name,\n createVersion: createPackage.version,\n monorepoTemplateVersion: getTemplateVersion(\"monorepo\"),\n compatibleTemplates: {\n webapp: getTemplateVersion(\"webapp\"),\n library: getTemplateVersion(\"library\"),\n },\n createdAt,\n };\n}\n\nexport async function readWorkspaceManifest(\n rootDir: string,\n): Promise<MosaicWorkspaceManifest | null> {\n const manifestPath = getWorkspaceManifestPath(rootDir);\n if (!(await fs.pathExists(manifestPath))) return null;\n\n const content = await fs.readFile(manifestPath, \"utf-8\");\n try {\n return JSON.parse(content) as MosaicWorkspaceManifest;\n } catch (error) {\n throw new Error(\n `Invalid JSON in ${WORKSPACE_MANIFEST_FILENAME}: ${(error as Error).message}`,\n );\n }\n}\n\nexport async function writeWorkspaceManifest(\n rootDir: string,\n manifest: MosaicWorkspaceManifest,\n): Promise<void> {\n const manifestPath = getWorkspaceManifestPath(rootDir);\n await fs.writeJson(manifestPath, manifest, { spaces: 2 });\n await fs.appendFile(manifestPath, \"\\n\");\n}\n\nexport function getCompatibleTemplateVersion(\n manifest: MosaicWorkspaceManifest | null,\n templateType: string,\n): string {\n return (\n manifest?.compatibleTemplates[templateType] ??\n getTemplateVersion(templateType)\n );\n}\n","import { execSync, spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport ora from \"ora\";\nimport {\n toKebabCase,\n toTitleCase,\n toSnakeCase,\n} from \"../utils/case-converters.js\";\nimport { copyTemplate, type TemplateType } from \"../utils/copy-template.js\";\nimport {\n DEFAULT_MOSAIC_DESIGN_THEME,\n isValidMosaicDesignTheme,\n type MosaicDesignTheme,\n VALID_MOSAIC_DESIGN_THEMES,\n} from \"../utils/design-theme.js\";\nimport { detectMonorepo } from \"../utils/detect-monorepo.js\";\nimport { generateEnvLocal } from \"../utils/env-local.js\";\nimport {\n writeManifest,\n derivePlaceholders,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\nimport { readCreatePackageMetadata } from \"../utils/package-metadata.js\";\nimport {\n promptProjectDetails,\n type ProjectAnswers,\n type ProjectType,\n isValidProjectType,\n VALID_PROJECT_TYPES,\n} from \"../utils/prompts.js\";\nimport { relocateWorkflowsToRoot } from \"../utils/relocate-workflows.js\";\nimport {\n replacePlaceholders,\n type AppConfig,\n} from \"../utils/replace-placeholders.js\";\nimport { getTemplateVersion } from \"../utils/template-versions.js\";\nimport { validateProjectName } from \"../utils/validate.js\";\nimport {\n createWorkspaceManifest,\n getCompatibleTemplateVersion,\n readWorkspaceManifest,\n writeWorkspaceManifest,\n type MosaicWorkspaceManifest,\n} from \"../utils/workspace-manifest.js\";\n\nexport interface CreateOptions {\n type?: string;\n name?: string;\n customer?: string;\n theme?: string;\n repoName?: string;\n cwd?: string;\n skipInstall: boolean;\n yes: boolean;\n addOnly?: boolean;\n}\n\n// The webapp template enforces pnpm via `only-allow pnpm`; the monorepo and\n// library templates also assume pnpm. Hardcoding it removes a layer of\n// configuration that didn't reflect any real flexibility.\nconst PACKAGE_MANAGER = \"pnpm\";\nconst MAX_INSTALL_OUTPUT_CHARS = 64_000;\nconst MAX_INSTALL_OUTPUT_LINES = 80;\n\nclass PackageManagerCommandError extends Error {\n public constructor(\n message: string,\n public readonly output: string,\n ) {\n super(message);\n this.name = \"PackageManagerCommandError\";\n }\n}\n\n/** Paths in copy-paste shell commands (POSIX-style). */\nfunction shPath(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\n/** Non-blocking install so ora can animate (execSync would block timers). */\nfunction runPackageManagerInstall(\n packageManager: string,\n cwd: string,\n args: string[] = [\"install\"],\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let output = \"\";\n const appendOutput = (chunk: Buffer) => {\n output += chunk.toString();\n if (output.length > MAX_INSTALL_OUTPUT_CHARS) {\n output = output.slice(-MAX_INSTALL_OUTPUT_CHARS);\n }\n };\n const child = spawn(packageManager, args, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n child.stdout?.on(\"data\", appendOutput);\n child.stderr?.on(\"data\", appendOutput);\n child.on(\"error\", (error) => {\n reject(\n new PackageManagerCommandError(\n `${packageManager} ${args.join(\" \")} failed: ${error.message}`,\n output,\n ),\n );\n });\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else\n reject(\n new PackageManagerCommandError(\n `${packageManager} ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`,\n output,\n ),\n );\n });\n });\n}\n\nfunction printInstallFailureOutput(error: unknown): void {\n if (!(error instanceof PackageManagerCommandError)) return;\n const output = error.output.trim();\n if (!output) return;\n\n const lines = output.split(/\\r?\\n/);\n const omitted = Math.max(0, lines.length - MAX_INSTALL_OUTPUT_LINES);\n const visibleLines = lines.slice(-MAX_INSTALL_OUTPUT_LINES);\n\n console.log();\n console.log(\n chalk.bold(`Last ${visibleLines.length} lines from pnpm install:`),\n );\n if (omitted > 0) {\n console.log(chalk.dim(`... omitted ${omitted} earlier lines ...`));\n }\n console.log(visibleLines.join(\"\\n\"));\n}\n\n/**\n * Runs the monorepo-root `setup` script (local services + dbs + access + seed).\n * Uses `pnpm run setup` (not `pnpm setup`) because `pnpm setup` is a pnpm builtin that configures\n * PNPM_HOME in the user's shell rc — it ignores the package.json script of the same name.\n */\nfunction runWebappSetup(\n packageManager: string,\n monorepoRoot: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(packageManager, [\"run\", \"setup\"], {\n cwd: monorepoRoot,\n stdio: \"inherit\",\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else\n reject(\n new Error(\n `${packageManager} run setup exited with code ${code ?? \"unknown\"}`,\n ),\n );\n });\n });\n}\n\n/**\n * Spawns `pnpm dev` in the package directory and resolves once Next reports\n * \"Ready in\" (so we know the server is accepting requests). Returns the child\n * process so the caller can await its exit when the user hits Ctrl+C.\n *\n * Captures the actual URL Next picked (Next falls back to 3001+ if 3000 is\n * taken) so the caller can open the right one in the browser.\n */\n// ANSI CSI sequences (color/control codes Next emits to TTY-detected stdout).\n// eslint-disable-next-line no-control-regex\nconst ANSI_PATTERN = /\\u001b\\[[0-9;]*[a-zA-Z]/g;\n\nfunction spawnDevServer(\n packageManager: string,\n cwd: string,\n): { child: ReturnType<typeof spawn>; ready: Promise<{ url: string }> } {\n // Use `run dev` rather than `<pm> dev` because npm has no `dev` shorthand\n // (it only aliases test/start/stop/restart). `run <script>` works uniformly\n // across pnpm/npm/yarn — same reason runWebappSetup uses `run setup`.\n const child = spawn(packageManager, [\"run\", \"dev\"], {\n cwd,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n const ready = new Promise<{ url: string }>((resolve, reject) => {\n let resolved = false;\n let detectedUrl = \"http://localhost:3000\";\n // Pipe chunks aren't line-aligned, so accumulate stdout into a rolling\n // buffer and re-scan after each chunk. We trim aggressively to avoid\n // unbounded growth on a server that runs for hours.\n let buffer = \"\";\n const onChunk = (chunk: Buffer) => {\n const text = chunk.toString();\n process.stdout.write(text);\n buffer = (buffer + text).slice(-4096).replace(ANSI_PATTERN, \"\");\n const urlMatch = buffer.match(/Local:\\s+(https?:\\/\\/\\S+?)(?:\\s|$)/i);\n if (urlMatch?.[1]) detectedUrl = urlMatch[1].trim();\n if (!resolved && /Ready in /i.test(buffer)) {\n resolved = true;\n resolve({ url: detectedUrl });\n }\n };\n child.stdout?.on(\"data\", onChunk);\n child.stderr?.on(\"data\", (chunk) => process.stderr.write(chunk));\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (!resolved) {\n reject(\n new Error(\n `${packageManager} run dev exited with code ${code ?? \"unknown\"} before becoming ready`,\n ),\n );\n }\n });\n });\n\n return { child, ready };\n}\n\n/**\n * Cross-platform \"open this URL in the user's default browser\". Returns true\n * if the launcher process spawned, false on synchronous failure. The empty\n * `error` listener swallows the asynchronous error event that fires when the\n * launcher binary is missing (e.g. minimal Linux without `xdg-open`) — without\n * it, that event becomes an uncaught exception that kills the CLI mid-run.\n */\nfunction openInBrowser(url: string): boolean {\n const cmd =\n process.platform === \"darwin\"\n ? [\"open\", url]\n : process.platform === \"win32\"\n ? [\"cmd\", \"/c\", \"start\", \"\", url]\n : [\"xdg-open\", url];\n try {\n const child = spawn(cmd[0]!, cmd.slice(1), {\n stdio: \"ignore\",\n detached: true,\n });\n child.on(\"error\", () => {});\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Post-scaffold orchestration for webapps: run root setup (local services + dbs + access + seed),\n * start the dev server, open the served URL in the user's browser, then hand\n * control to the dev server until the user exits with Ctrl+C.\n *\n * Returns true if the dev server got running (caller should NOT print next\n * steps in that case — the user is already in the running app). Returns\n * false on any failure so the caller can print manual fallback steps.\n *\n * Callers should only invoke this when install actually succeeded —\n * starting setup without node_modules will leave an orphan Docker container.\n */\nasync function autoRunWebapp(\n packageDir: string,\n monorepoRoot: string,\n): Promise<boolean> {\n const packageManager = PACKAGE_MANAGER;\n\n console.log();\n console.log(\n chalk.bold(\"Running setup (local services, dbs, access, seed)...\"),\n );\n console.log();\n try {\n await runWebappSetup(packageManager, monorepoRoot);\n } catch (error) {\n console.log();\n console.log(\n chalk.yellow(\"!\"),\n \"Setup failed. You can re-run it manually:\",\n chalk.cyan(`cd ${monorepoRoot} && ${packageManager} run setup`),\n );\n console.log(chalk.dim((error as Error).message));\n return false;\n }\n\n console.log();\n console.log(chalk.bold(\"Starting dev server...\"));\n console.log();\n const { child, ready } = spawnDevServer(packageManager, packageDir);\n\n // Register the \"dev server has exited\" listener BEFORE we await `ready`.\n // If the child exits during that await and we attached the listener\n // afterwards, we'd miss the event (Node EventEmitter doesn't replay past\n // events) and hang forever on the final `await closed`.\n const closed = new Promise<void>((resolve) => {\n child.on(\"close\", () => resolve());\n });\n\n let url = \"http://localhost:3000\";\n try {\n ({ url } = await ready);\n } catch (error) {\n console.log();\n console.log(chalk.yellow(\"!\"), \"Dev server failed to become ready.\");\n console.log(chalk.dim((error as Error).message));\n return false;\n }\n\n if (openInBrowser(url)) {\n console.log();\n console.log(chalk.green(\"✔\"), \"Opened\", chalk.cyan(url));\n } else {\n console.log();\n console.log(\n chalk.dim(\"Open\"),\n chalk.cyan(url),\n chalk.dim(\"in your browser.\"),\n );\n }\n\n // Hand control to the dev server until the user exits.\n await closed;\n return true;\n}\n\nasync function writeMosaicFiles(\n packageDir: string,\n config: {\n name: string;\n title: string;\n designTheme?: MosaicDesignTheme;\n repoName?: string;\n },\n projectType: string,\n templateVersion = getTemplateVersion(projectType),\n templateCommit = \"npm\",\n): Promise<void> {\n const manifest: MosaicManifest = {\n templateType: projectType,\n templateVersion,\n templateCommit,\n createdAt: new Date().toISOString(),\n placeholders: derivePlaceholders(\n config.name,\n config.title,\n config.repoName,\n config.designTheme,\n ),\n source: {\n templatePath: `packages/blueberry/templates/${projectType}`,\n },\n };\n\n await writeManifest(packageDir, manifest);\n\n // Write starter mosaic-template-notes.md\n const notesPath = path.join(packageDir, \"mosaic-template-notes.md\");\n await fs.writeFile(\n notesPath,\n `# Mosaic Divergence Notes\\n\\nDocument intentional differences from the ${projectType} template here.\\nClaude reads this file during sync to preserve your customizations.\\n\\n## Intentional Divergences\\n\\n_None yet — freshly created from template._\\n`,\n );\n}\n\nfunction buildAppConfig(\n name: string,\n title = toTitleCase(name),\n repoName = name,\n designTheme = DEFAULT_MOSAIC_DESIGN_THEME,\n): AppConfig {\n const createPackage = readCreatePackageMetadata();\n return {\n name,\n title,\n dbName: `${toSnakeCase(name)}_db`,\n nameUpper: name.toUpperCase(),\n nameSnake: toSnakeCase(name),\n repoName,\n repoNameSnake: toSnakeCase(repoName),\n createPackage: createPackage.name,\n createVersion: createPackage.version,\n designTheme,\n };\n}\n\n/** Copy the monorepo template into `targetDir` and replace its placeholders. */\nasync function scaffoldMonorepo(\n targetDir: string,\n config: AppConfig,\n): Promise<void> {\n const monoSpinner = ora(\"Copying monorepo template...\").start();\n try {\n await copyTemplate(targetDir, \"monorepo\" satisfies TemplateType);\n monoSpinner.succeed(\"Copied monorepo template\");\n } catch (error) {\n monoSpinner.fail(\"Failed to copy monorepo template\");\n console.error(error);\n process.exit(1);\n }\n\n const replaceSpinner = ora(\"Replacing monorepo placeholders...\").start();\n try {\n const stats = await replacePlaceholders(targetDir, config);\n replaceSpinner.succeed(\n `Replaced placeholders in ${stats.modified} monorepo files`,\n );\n } catch (error) {\n replaceSpinner.fail(\"Failed to replace monorepo placeholders\");\n console.error(error);\n process.exit(1);\n }\n}\n\n/**\n * Add a package (webapp or library) to a monorepo: copy the template into\n * `packageDir`, replace placeholders, write the Mosaic manifest, and run the\n * webapp-only post-copy steps (.env.local, workflow relocation) when applicable.\n */\nasync function addPackageToMonorepo(args: {\n packageDir: string;\n monorepoRoot: string;\n projectType: \"webapp\" | \"library\";\n config: AppConfig;\n templateVersion: string;\n templateCommit: string;\n}): Promise<void> {\n const {\n packageDir,\n monorepoRoot,\n projectType,\n config,\n templateVersion,\n templateCommit,\n } = args;\n\n const copySpinner = ora(\"Copying package template...\").start();\n try {\n await copyTemplate(packageDir, projectType);\n copySpinner.succeed(\"Copied package template\");\n } catch (error) {\n copySpinner.fail(\"Failed to copy package template\");\n console.error(error);\n process.exit(1);\n }\n\n const replaceSpinner = ora(\"Replacing package placeholders...\").start();\n try {\n const stats = await replacePlaceholders(packageDir, config);\n replaceSpinner.succeed(\n `Replaced placeholders in ${stats.modified} package files`,\n );\n } catch (error) {\n replaceSpinner.fail(\"Failed to replace package placeholders\");\n console.error(error);\n process.exit(1);\n }\n\n await writeMosaicFiles(\n packageDir,\n config,\n projectType,\n templateVersion,\n templateCommit,\n );\n\n if (projectType === \"webapp\") {\n await generateEnvLocal(packageDir);\n await relocateWorkflowsToRoot(packageDir, monorepoRoot, config.name);\n }\n}\n\n/** Initialize a git repo at `targetDir` with an initial commit. Best-effort. */\nfunction initGitRepo(targetDir: string): void {\n const gitSpinner = ora(\"Initializing git repository...\").start();\n try {\n execSync(\"git init\", { cwd: targetDir, stdio: \"ignore\" });\n execSync(\"git add -A\", { cwd: targetDir, stdio: \"ignore\" });\n execSync('git commit -m \"Initial commit from @percepta/create\"', {\n cwd: targetDir,\n stdio: \"ignore\",\n });\n gitSpinner.succeed(\"Initialized git repository\");\n } catch {\n gitSpinner.warn(\"Failed to initialize git repository\");\n }\n}\n\n/**\n * Run `pnpm install` at the monorepo root with a spinner. Returns true if\n * install ran successfully; false if it failed or was skipped.\n */\nasync function installAtMonorepoRoot(\n monorepoRoot: string,\n installDeps: boolean,\n): Promise<boolean> {\n if (!installDeps) return false;\n const spinner = ora(\n `Installing dependencies with ${PACKAGE_MANAGER}...`,\n ).start();\n try {\n await runPackageManagerInstall(PACKAGE_MANAGER, monorepoRoot);\n spinner.succeed(\"Installed dependencies\");\n return true;\n } catch (error) {\n spinner.warn(\n `Failed to install dependencies. Run '${PACKAGE_MANAGER} install' from monorepo root.`,\n );\n printInstallFailureOutput(error);\n return false;\n }\n}\n\n/**\n * For webapp scaffolds with a successful install, hand off to autoRunWebapp\n * (setup → dev → open browser). No-op otherwise. Returns true if the dev\n * server actually started — caller skips manual next-steps in that case.\n *\n * Gated on `installSucceeded` because starting setup without node_modules\n * leaves an orphan Docker container.\n */\nasync function maybeAutoRunWebapp(\n packageDir: string | null,\n monorepoRoot: string,\n projectType: ProjectType,\n installSucceeded: boolean,\n): Promise<boolean> {\n if (!packageDir || projectType !== \"webapp\" || !installSucceeded)\n return false;\n return autoRunWebapp(packageDir, monorepoRoot);\n}\n\nfunction getProjectTypeLabel(projectType: ProjectType): string {\n switch (projectType) {\n case \"monorepo\":\n return \"pnpm monorepo\";\n case \"webapp\":\n return \"Next.js webapp\";\n case \"library\":\n return \"TypeScript library\";\n default: {\n const exhaustiveCheck: never = projectType;\n throw new Error(`Unknown project type: ${String(exhaustiveCheck)}`);\n }\n }\n}\n\nfunction requireNpmTokenForWebappInstall(\n projectType: ProjectType,\n installDeps: boolean,\n): void {\n // The webapp template depends on private `@percepta/*` packages whose .npmrc\n // resolves auth from `${NPM_TOKEN}`. If the env var is empty, `pnpm install`\n // dies deep in cryptic 401/404 logs. Catch it before asking for names.\n if (projectType !== \"webapp\" || !installDeps || process.env.NPM_TOKEN) {\n return;\n }\n\n console.log();\n console.error(chalk.red(\"Error: NPM_TOKEN environment variable is not set.\"));\n console.error(\n chalk.dim(\" Required to install private @percepta/* packages.\"),\n );\n console.error();\n console.error(\" 1. Grab the npm token from 1Password:\");\n console.error(\n chalk.cyan(\n \" https://start.1password.com/open/i?a=5TX2B4O3QNE4FNQ2A7ZJZDRRBI&v=j7trpyuqh7gt635dtuj6y4pwjm&i=cmmdi5trji7ctkn3fseakf4mgi&h=aitco.1password.com\",\n ),\n );\n console.error(\" 2. Add to ~/.zshrc:\");\n console.error(chalk.cyan(' export NPM_TOKEN=\"<paste-token>\"'));\n console.error(\n \" 3. Open a new terminal (or \" +\n chalk.cyan(\"source ~/.zshrc\") +\n \") and re-run.\",\n );\n console.error();\n console.error(\n chalk.dim(\" Or pass --skip-install to scaffold without running install.\"),\n );\n process.exit(1);\n}\n\nfunction ensureWorkspaceCreateVersionCompatible(\n workspaceManifest: MosaicWorkspaceManifest | null,\n projectType: ProjectType,\n): void {\n if (!workspaceManifest || projectType === \"monorepo\") return;\n\n const createPackage = readCreatePackageMetadata();\n if (\n workspaceManifest.createPackage === createPackage.name &&\n workspaceManifest.createVersion === createPackage.version\n ) {\n return;\n }\n\n console.log();\n console.error(\n chalk.red(\n `Error: This workspace is pinned to ${workspaceManifest.createPackage}@${workspaceManifest.createVersion}, ` +\n `but you are running ${createPackage.name}@${createPackage.version}.`,\n ),\n );\n console.error();\n console.error(\n chalk.dim(\n \" Run the workspace-owned command so new packages match this monorepo:\",\n ),\n );\n console.error(chalk.cyan(` pnpm mosaic add ${projectType} <name>`));\n console.error();\n console.error(\n chalk.dim(\n \" To adopt newer templates, upgrade the workspace manifest first.\",\n ),\n );\n process.exit(1);\n}\n\nfunction getTemplateCommitSource(\n workspaceManifest: MosaicWorkspaceManifest | null,\n): string {\n if (!workspaceManifest) return \"npm\";\n return `${workspaceManifest.createPackage}@${workspaceManifest.createVersion}`;\n}\n\nexport async function createProject(options: CreateOptions): Promise<void> {\n const cwd = await resolveCreateCwd(options.cwd);\n\n // Validate --type if provided\n if (options.type !== undefined && !isValidProjectType(options.type)) {\n console.error(\n chalk.red(\n `Error: Invalid package type \"${options.type}\". Valid types are: ${VALID_PROJECT_TYPES.join(\", \")}`,\n ),\n );\n process.exit(1);\n }\n\n if (options.theme !== undefined && !isValidMosaicDesignTheme(options.theme)) {\n console.error(\n chalk.red(\n `Error: Invalid design theme \"${options.theme}\". Valid themes are: ${VALID_MOSAIC_DESIGN_THEMES.join(\", \")}`,\n ),\n );\n process.exit(1);\n }\n\n console.log();\n console.log(chalk.bold(\"Creating a new Mosaic package...\"));\n console.log();\n\n // Step 1: Detect monorepo context\n const monorepoContext = await detectMonorepo(cwd);\n\n if (options.addOnly && !monorepoContext.found) {\n console.error(\n chalk.red(\n \"Error: 'create add' must be run inside an existing pnpm monorepo.\",\n ),\n );\n process.exit(1);\n }\n\n // Bare monorepo only makes sense outside an existing monorepo.\n if (options.type === \"monorepo\" && monorepoContext.found) {\n console.error(\n chalk.red(\n `Error: Already inside a monorepo at ${monorepoContext.rootDir}. ` +\n `Choose 'webapp' or 'library' to add a package, or run from outside the monorepo.`,\n ),\n );\n process.exit(1);\n }\n\n if (monorepoContext.found) {\n console.log(\n chalk.dim(\" Detected monorepo at\"),\n chalk.cyan(monorepoContext.rootDir),\n );\n } else {\n console.log(\n chalk.dim(\" No monorepo detected. A new monorepo will be created.\"),\n );\n }\n console.log();\n\n const workspaceManifest = monorepoContext.found\n ? await readWorkspaceManifest(monorepoContext.rootDir!)\n : null;\n\n if (workspaceManifest) {\n console.log(\n chalk.dim(\" Workspace create version:\"),\n chalk.cyan(\n `${workspaceManifest.createPackage}@${workspaceManifest.createVersion}`,\n ),\n );\n console.log();\n } else if (monorepoContext.found) {\n console.log(\n chalk.yellow(\"!\"),\n \"No .mosaic-workspace.json found; using this CLI's bundled templates.\",\n );\n console.log();\n }\n\n // --name skips the package-name prompt; --repo-name skips the new-monorepo\n // repo-name prompt. Both are used by automation but are not the canonical\n // CLI UX.\n const projectName = options.name;\n const repoName = options.repoName;\n if (options.yes && !projectName) {\n console.error(chalk.red(\"Error: --name is required when using --yes flag\"));\n process.exit(1);\n }\n\n if (projectName) {\n const validation = validateProjectName(toKebabCase(projectName));\n if (!validation.valid) {\n console.error(chalk.red(`Invalid project name: ${validation.error}`));\n process.exit(1);\n }\n }\n\n if (repoName) {\n const validation = validateProjectName(toKebabCase(repoName));\n if (!validation.valid) {\n console.error(chalk.red(`Invalid repo name: ${validation.error}`));\n process.exit(1);\n }\n }\n\n const customerSlug = options.customer\n ? toKebabCase(options.customer)\n : undefined;\n\n if (customerSlug) {\n const validation = validateProjectName(customerSlug);\n if (!validation.valid) {\n console.error(chalk.red(`Invalid customer slug: ${validation.error}`));\n process.exit(1);\n }\n }\n\n // Step 2 & 3: Get project details from prompts or options\n let answers: ProjectAnswers;\n\n if (options.yes) {\n // Non-interactive mode (used by automation). Defaults: type=webapp.\n const projectType: ProjectType = (options.type as ProjectType) || \"webapp\";\n ensureWorkspaceCreateVersionCompatible(workspaceManifest, projectType);\n requireNpmTokenForWebappInstall(projectType, !options.skipInstall);\n const kebabName = toKebabCase(projectName!);\n const kebabRepoName = repoName ? toKebabCase(repoName) : kebabName;\n const directory =\n monorepoContext.found && monorepoContext.packageDir\n ? path.join(monorepoContext.packageDir, kebabName)\n : path.resolve(cwd, kebabRepoName);\n\n answers = {\n projectType,\n directory,\n name: kebabName,\n title: toTitleCase(kebabName),\n installDeps: !options.skipInstall,\n customerSlug: monorepoContext.found\n ? undefined\n : (customerSlug ?? kebabRepoName),\n designTheme:\n projectType === \"webapp\"\n ? ((options.theme as MosaicDesignTheme | undefined) ??\n DEFAULT_MOSAIC_DESIGN_THEME)\n : undefined,\n monorepoName: monorepoContext.found ? undefined : kebabRepoName,\n monorepoTitle: monorepoContext.found\n ? undefined\n : toTitleCase(kebabRepoName),\n };\n } else {\n answers = await promptProjectDetails({\n projectType: options.type as ProjectType | undefined,\n name: projectName ? toKebabCase(projectName) : undefined,\n customerSlug,\n designTheme: options.theme as MosaicDesignTheme | undefined,\n repoName: repoName ? toKebabCase(repoName) : undefined,\n skipInstall: options.skipInstall,\n monorepoContext,\n cwd,\n beforeNamePrompt: (projectType) => {\n ensureWorkspaceCreateVersionCompatible(workspaceManifest, projectType);\n requireNpmTokenForWebappInstall(projectType, !options.skipInstall);\n },\n });\n\n // If inside monorepo, compute directory from workspace pattern + name\n if (\n monorepoContext.found &&\n monorepoContext.packageDir &&\n !answers.directory\n ) {\n answers.directory = path.join(monorepoContext.packageDir, answers.name);\n }\n }\n\n const monorepoName = answers.monorepoName ?? answers.name;\n const monorepoTitle = answers.monorepoTitle ?? toTitleCase(monorepoName);\n const newWorkspaceCustomerSlug = answers.customerSlug ?? monorepoName;\n const monorepoConfig = buildAppConfig(\n monorepoName,\n monorepoTitle,\n monorepoName,\n DEFAULT_MOSAIC_DESIGN_THEME,\n );\n const configRepoName = monorepoContext.found\n ? path.basename(monorepoContext.rootDir!)\n : monorepoName;\n const config = buildAppConfig(\n answers.name,\n answers.title,\n configRepoName,\n answers.designTheme,\n );\n\n const typeLabel = getProjectTypeLabel(answers.projectType);\n\n if (monorepoContext.found) {\n // --- ADDING TO EXISTING MONOREPO ---\n const monorepoRoot = monorepoContext.rootDir!;\n const packageDir = monorepoContext.packageDir\n ? path.join(monorepoContext.packageDir, answers.name)\n : answers.directory;\n\n console.log(chalk.dim(\" Package type:\"), typeLabel);\n console.log(chalk.dim(\" Target:\"), packageDir);\n console.log(chalk.dim(\" Name:\"), config.name);\n console.log(chalk.dim(\" Title:\"), config.title);\n if (answers.projectType === \"webapp\") {\n console.log(chalk.dim(\" Database:\"), config.dbName);\n console.log(chalk.dim(\" Design theme:\"), config.designTheme);\n }\n console.log();\n\n // Check if directory already exists and is not empty\n if (await fs.pathExists(packageDir)) {\n const files = await fs.readdir(packageDir);\n if (files.length > 0) {\n console.error(\n chalk.red(`Error: Directory ${packageDir} is not empty.`),\n );\n process.exit(1);\n }\n }\n\n if (answers.projectType !== \"monorepo\") {\n await addPackageToMonorepo({\n packageDir,\n monorepoRoot,\n projectType: answers.projectType,\n config,\n templateVersion: getCompatibleTemplateVersion(\n workspaceManifest,\n answers.projectType,\n ),\n templateCommit: getTemplateCommitSource(workspaceManifest),\n });\n }\n\n // pnpm reads .npmrc from the workspace root, not package dirs. If the\n // root .npmrc is missing the @percepta registry config, downstream\n // `pnpm install` won't authenticate.\n await warnIfMissingRootNpmrc(monorepoRoot);\n\n const installSucceeded = await installAtMonorepoRoot(\n monorepoRoot,\n answers.installDeps,\n );\n\n // Success\n console.log();\n console.log(\n chalk.green(\"\\u2714\"),\n chalk.bold(`Created ${typeLabel} at`),\n chalk.cyan(path.relative(monorepoRoot, packageDir)),\n );\n console.log();\n\n const devStarted = await maybeAutoRunWebapp(\n packageDir,\n monorepoRoot,\n answers.projectType,\n installSucceeded,\n );\n if (devStarted) return;\n\n printNextStepsExisting(answers, packageDir, !installSucceeded);\n } else {\n // --- CREATING NEW MONOREPO (with optional package inside) ---\n const isBareMonorepo = answers.projectType === \"monorepo\";\n const monorepoRoot = answers.directory;\n const packageDir = isBareMonorepo\n ? null\n : path.join(monorepoRoot, \"packages\", answers.name);\n\n if (isBareMonorepo) {\n console.log(chalk.dim(\" Type:\"), typeLabel);\n console.log(chalk.dim(\" Directory:\"), monorepoRoot);\n console.log(chalk.dim(\" Customer:\"), newWorkspaceCustomerSlug);\n console.log(chalk.dim(\" Repo name:\"), monorepoConfig.name);\n console.log(chalk.dim(\" Title:\"), monorepoConfig.title);\n } else {\n console.log(chalk.dim(\" Package type:\"), typeLabel);\n console.log(chalk.dim(\" Monorepo directory:\"), monorepoRoot);\n console.log(chalk.dim(\" Customer:\"), newWorkspaceCustomerSlug);\n console.log(chalk.dim(\" Repo name:\"), monorepoConfig.name);\n console.log(chalk.dim(\" Package:\"), `packages/${answers.name}/`);\n console.log(chalk.dim(\" Name:\"), config.name);\n console.log(chalk.dim(\" Title:\"), config.title);\n if (answers.projectType === \"webapp\") {\n console.log(chalk.dim(\" Database:\"), config.dbName);\n console.log(chalk.dim(\" Design theme:\"), config.designTheme);\n }\n }\n console.log();\n\n // Check if directory exists and is not empty.\n if (await fs.pathExists(monorepoRoot)) {\n const files = await fs.readdir(monorepoRoot);\n if (files.length > 0) {\n console.error(\n chalk.red(`Error: Directory ${monorepoRoot} is not empty.`),\n );\n process.exit(1);\n }\n }\n\n await scaffoldMonorepo(monorepoRoot, monorepoConfig);\n const newWorkspaceManifest = createWorkspaceManifest({\n customerSlug: newWorkspaceCustomerSlug,\n });\n await writeWorkspaceManifest(monorepoRoot, newWorkspaceManifest);\n\n if (packageDir && answers.projectType !== \"monorepo\") {\n await addPackageToMonorepo({\n packageDir,\n monorepoRoot,\n projectType: answers.projectType,\n config,\n templateVersion: getCompatibleTemplateVersion(\n newWorkspaceManifest,\n answers.projectType,\n ),\n templateCommit: getTemplateCommitSource(newWorkspaceManifest),\n });\n }\n\n const installSucceeded = await installAtMonorepoRoot(\n monorepoRoot,\n answers.installDeps,\n );\n\n // Initialize after install so generated lockfiles land in the first commit.\n initGitRepo(monorepoRoot);\n\n // Success\n console.log();\n console.log(\n chalk.green(\"\\u2714\"),\n chalk.bold(\n isBareMonorepo ? `Created ${typeLabel} at` : \"Created monorepo at\",\n ),\n chalk.cyan(monorepoRoot),\n );\n if (!isBareMonorepo) {\n console.log(\n chalk.green(\"\\u2714\"),\n chalk.bold(`Created ${typeLabel} at`),\n chalk.cyan(`packages/${answers.name}/`),\n );\n }\n console.log();\n\n const devStarted = await maybeAutoRunWebapp(\n packageDir,\n monorepoRoot,\n answers.projectType,\n installSucceeded,\n );\n if (devStarted) return;\n\n printNextStepsNew(answers, monorepoRoot, !installSucceeded);\n }\n}\n\nasync function resolveCreateCwd(\n cwdOption: string | undefined,\n): Promise<string> {\n const cwd = cwdOption ? path.resolve(cwdOption) : process.cwd();\n let stat;\n try {\n stat = await fs.stat(cwd);\n } catch {\n console.error(chalk.red(`Error: --cwd directory does not exist: ${cwd}`));\n process.exit(1);\n }\n\n if (!stat.isDirectory()) {\n console.error(chalk.red(`Error: --cwd is not a directory: ${cwd}`));\n process.exit(1);\n }\n\n return cwd;\n}\n\nfunction printWebappNextSteps(params: {\n pm: \"pnpm\" | \"npm\" | \"yarn\";\n answers: ProjectAnswers;\n variant: \"new\" | \"existing\";\n /** Whether dependencies still need to be installed before setup/dev. */\n installNeeded: boolean;\n /** Relative path from cwd to monorepo root. */\n monorepoRelativePath: string;\n /** Relative path from monorepo root to the package directory. */\n packageRelativePathFromRoot?: string;\n}): void {\n const {\n pm,\n answers,\n variant,\n installNeeded,\n monorepoRelativePath,\n packageRelativePathFromRoot,\n } = params;\n const repoRel = shPath(monorepoRelativePath) || \".\";\n const pkgFromRoot =\n shPath(packageRelativePathFromRoot ?? `packages/${answers.name}`) || \".\";\n // Use `pnpm run setup` (not `pnpm setup`) — the latter is a pnpm builtin.\n const setupStep = \"pnpm run setup\";\n const devStep = \"pnpm dev\";\n\n if (variant === \"new\") {\n const oneLinerParts: string[] = [];\n if (repoRel !== \".\") oneLinerParts.push(`cd ${repoRel}`);\n if (installNeeded) oneLinerParts.push(`${pm} install`);\n oneLinerParts.push(setupStep);\n oneLinerParts.push(`cd ${pkgFromRoot}`);\n oneLinerParts.push(devStep);\n\n console.log(chalk.bold(\"Copy-paste (from your current directory):\"));\n console.log();\n console.log(chalk.cyan(` ${oneLinerParts.join(\" && \")}`));\n console.log();\n console.log(chalk.bold(\"Or step by step:\"));\n console.log();\n\n let step = 1;\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(chalk.dim(` ${step++}.`), setupStep);\n console.log(chalk.dim(` ${step++}.`), `cd ${pkgFromRoot}`);\n console.log(chalk.dim(` ${step++}.`), devStep);\n return;\n }\n\n const oneLinerParts: string[] = [];\n\n if (repoRel !== \".\") oneLinerParts.push(`cd ${repoRel}`);\n if (installNeeded) {\n oneLinerParts.push(`${pm} install`);\n }\n oneLinerParts.push(setupStep, `cd ${pkgFromRoot}`, devStep);\n\n console.log(chalk.bold(\"Copy-paste (from your current directory):\"));\n console.log();\n console.log(chalk.cyan(` ${oneLinerParts.join(\" && \")}`));\n console.log();\n console.log(chalk.bold(\"Or step by step:\"));\n console.log();\n\n let step = 1;\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(chalk.dim(` ${step++}.`), setupStep);\n console.log(chalk.dim(` ${step++}.`), `cd ${pkgFromRoot}`);\n console.log(chalk.dim(` ${step++}.`), devStep);\n}\n\nasync function warnIfMissingRootNpmrc(rootDir: string): Promise<void> {\n const rootNpmrc = path.join(rootDir, \".npmrc\");\n let contents = \"\";\n if (await fs.pathExists(rootNpmrc)) {\n contents = await fs.readFile(rootNpmrc, \"utf8\");\n }\n if (contents.includes(\"@percepta:registry\")) {\n return;\n }\n\n console.log();\n console.log(\n chalk.yellow(\"!\"),\n chalk.bold(\"Root .npmrc is missing @percepta registry config.\"),\n );\n console.log(\n chalk.dim(\n \" pnpm reads .npmrc from the workspace root, so add these lines to\",\n ),\n );\n console.log(chalk.dim(` ${path.join(rootDir, \".npmrc\")}:`));\n console.log();\n console.log(chalk.cyan(\" @percepta:registry=https://registry.npmjs.org/\"));\n console.log(chalk.cyan(\" //registry.npmjs.org/:_authToken=${NPM_TOKEN}\"));\n console.log();\n}\n\nfunction printNextStepsNew(\n answers: ProjectAnswers,\n targetDir: string,\n installNeeded: boolean,\n): void {\n const pm = PACKAGE_MANAGER;\n const relativePath = path.relative(process.cwd(), targetDir) || \".\";\n\n console.log(\"Next steps:\");\n console.log();\n\n switch (answers.projectType) {\n case \"monorepo\": {\n let step = 1;\n const repoRel = shPath(relativePath);\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(\n chalk.dim(` ${step++}.`),\n `Add a package: ${chalk.cyan(`pnpm mosaic add webapp <name>`)}`,\n );\n break;\n }\n\n case \"webapp\":\n printWebappNextSteps({\n pm,\n answers,\n variant: \"new\",\n installNeeded,\n monorepoRelativePath: relativePath,\n });\n break;\n\n case \"library\": {\n let step = 1;\n const repoRel = shPath(relativePath);\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(chalk.dim(` ${step++}.`), `cd packages/${answers.name}`);\n console.log(chalk.dim(` ${step++}.`), `${pm} dev`);\n console.log(\n chalk.dim(` ${step++}.`),\n `Edit src/index.ts to add your library code`,\n );\n break;\n }\n }\n\n console.log();\n console.log(\n chalk.dim(\"For more information, see the README.md in your project.\"),\n );\n console.log();\n}\n\nfunction printNextStepsExisting(\n answers: ProjectAnswers,\n packageDir: string,\n installNeeded: boolean,\n): void {\n const pm = PACKAGE_MANAGER;\n const packageRelativePath = path.relative(process.cwd(), packageDir) || \".\";\n const monorepoRoot = path.dirname(path.dirname(packageDir));\n const monorepoRelativePath =\n path.relative(process.cwd(), monorepoRoot) || \".\";\n const packageRelativePathFromRoot =\n path.relative(monorepoRoot, packageDir) || \".\";\n\n console.log(\"Next steps:\");\n console.log();\n\n switch (answers.projectType) {\n case \"webapp\":\n printWebappNextSteps({\n pm,\n answers,\n variant: \"existing\",\n installNeeded,\n monorepoRelativePath,\n packageRelativePathFromRoot,\n });\n break;\n\n case \"library\": {\n let step = 1;\n if (installNeeded) {\n const repoRel = shPath(monorepoRelativePath);\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n console.log(\n chalk.dim(` ${step++}.`),\n `cd ${shPath(packageRelativePathFromRoot)}`,\n );\n } else {\n const pkgRel = shPath(packageRelativePath);\n if (pkgRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${pkgRel}`);\n }\n }\n console.log(chalk.dim(` ${step++}.`), `${pm} dev`);\n console.log(\n chalk.dim(` ${step++}.`),\n \"Edit src/index.ts to add your library code\",\n );\n break;\n }\n }\n\n console.log();\n console.log(\n chalk.dim(\"For more information, see the README.md in your project.\"),\n );\n console.log();\n}\n","#!/usr/bin/env node\n\nimport { program } from \"commander\";\nimport { createProject } from \"./commands/create.js\";\nimport { readCreatePackageMetadata } from \"./utils/package-metadata.js\";\n\nconst packageJson = readCreatePackageMetadata();\n\nprogram\n .name(\"create\")\n .description(\"Scaffold and manage Mosaic packages\")\n .version(packageJson.version);\n\n// Default command. Intentionally bare-bones: the canonical incantation is\n// just `npx @percepta/create` with no flags — everything else comes from\n// prompts. The flags below exist for test-template.sh and other automation,\n// not for end-user use.\nprogram\n .command(\"create\", { isDefault: true })\n .description(\"Scaffold a new Mosaic package\")\n .option(\"-t, --type <type>\", \"Package type: monorepo, webapp, or library\")\n .option(\"--name <name>\", \"Package/app name\")\n .option(\"--customer <slug>\", \"Customer slug for the new monorepo\")\n .option(\"--theme <theme>\", \"Webapp design theme: modern, paper, or dense\")\n .option(\"--repo-name <name>\", \"Repository name when creating a new monorepo\")\n .option(\"--cwd <dir>\", \"Run create as if started from this directory\")\n .option(\n \"--skip-install\",\n \"Skip dependency installation (also skips the auto-run setup + dev + browser)\",\n false,\n )\n .option(\"-y, --yes\", \"Skip all prompts and use defaults\", false)\n .action(createProject);\n\nprogram\n .command(\"add\")\n .description(\"Add a Mosaic package to the current monorepo\")\n .argument(\"[typeOrName]\", \"Package type (webapp/library) or package name\")\n .argument(\"[name]\", \"Package/app name\")\n .option(\"-t, --type <type>\", \"Package type: webapp or library\")\n .option(\"--name <name>\", \"Package/app name\")\n .option(\"--theme <theme>\", \"Webapp design theme: modern, paper, or dense\")\n .option(\n \"--skip-install\",\n \"Skip dependency installation (also skips the auto-run setup + dev + browser)\",\n false,\n )\n .option(\"-y, --yes\", \"Skip all prompts and use defaults\", false)\n .action(async (typeOrName, name, options) => {\n let projectType = options.type;\n let projectName = options.name;\n\n if (typeOrName === \"webapp\" || typeOrName === \"library\") {\n projectType = projectType ?? typeOrName;\n projectName = projectName ?? name;\n } else if (typeOrName === \"monorepo\") {\n program.error(\"error: 'add' only supports webapp or library packages\");\n } else if (typeOrName) {\n if (name) {\n program.error(\n `error: unknown package type \"${typeOrName}\". Expected webapp or library.`,\n );\n }\n projectName = projectName ?? typeOrName;\n }\n\n await createProject({\n ...options,\n type: projectType,\n name: projectName,\n addOnly: true,\n });\n });\n\nconst infra = program.command(\"infra\").description(\"Manage Mosaic infra glue\");\n\ninfra\n .command(\"register-os-blueprint\")\n .description(\"Register this customer monorepo's OS blueprint in infra\")\n .action(async () => {\n const { registerOsBlueprintCommand } =\n await import(\"./commands/infra/register-os-blueprint.js\");\n await registerOsBlueprintCommand();\n });\n\ninfra\n .command(\"register-app\")\n .description(\"Register a webapp database in this customer OS blueprint\")\n .argument(\"<app>\", \"Webapp package name\")\n .action(async (appName: string) => {\n const { registerAppCommand } =\n await import(\"./commands/infra/register-app.js\");\n await registerAppCommand(appName);\n });\n\n// Lazy-loaded subcommands\nprogram\n .command(\"status\")\n .description(\"Show template sync status for current app\")\n .option(\"--mosaic-template-path <path>\", \"Path to local mosaic repo checkout\")\n .action(async (options) => {\n const { statusCommand } = await import(\"./commands/status.js\");\n await statusCommand(options);\n });\n\nprogram\n .command(\"sync\")\n .description(\"Generate downstream sync context (template → app)\")\n .option(\"--mosaic-template-path <path>\", \"Path to local mosaic repo checkout\")\n .option(\"--to <version>\", \"Target template version (default: latest)\")\n .action(async (options) => {\n const { syncCommand } = await import(\"./commands/sync.js\");\n await syncCommand(options);\n });\n\nprogram\n .command(\"upstream\")\n .description(\"Generate upstream context (app → template)\")\n .option(\"--mosaic-template-path <path>\", \"Path to local mosaic repo checkout\")\n .option(\"--files <patterns...>\", \"Specific files to propose upstream\")\n .action(async (options) => {\n const { upstreamCommand } = await import(\"./commands/upstream.js\");\n await upstreamCommand(options);\n });\n\nprogram\n .command(\"init\")\n .description(\"Add .mosaic-template.json to an existing app\")\n .option(\"-t, --type <type>\", \"Template type (e.g., webapp, library)\")\n .option(\"--template-version <version>\", \"Template version to set\")\n .action(async (options) => {\n const { initCommand } = await import(\"./commands/init.js\");\n await initCommand(options);\n });\n\nprogram.parse();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["SKIP_DIRS","SKIP_FILES","exhaustiveCheck"],"sources":["../src/utils/copy-template.ts","../src/utils/detect-monorepo.ts","../src/utils/env-local.ts","../src/utils/package-metadata.ts","../src/utils/prompts.ts","../src/utils/relocate-workflows.ts","../src/utils/replace-placeholders.ts","../src/utils/workspace-manifest.ts","../src/commands/create.ts","../src/index.ts"],"sourcesContent":["import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport fs from \"fs-extra\";\n\n// Template type includes \"monorepo\" for internal use even though\n// it's no longer a user-facing choice\nexport type TemplateType = \"monorepo\" | \"webapp\" | \"library\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Directories to skip during copy\nconst SKIP_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \"dist\",\n \".turbo\",\n \".vercel\",\n \".cursor\",\n]);\n\n// Files to skip during copy\nconst SKIP_FILES = new Set([\n \"pnpm-lock.yaml\",\n \"package-lock.json\",\n \"yarn.lock\",\n \".DS_Store\",\n]);\n\n// Files that have .template extension that should be renamed\nconst TEMPLATE_FILE_MAPPINGS: Record<string, string> = {\n \"package.json.template\": \"package.json\",\n \"gitignore.template\": \".gitignore\",\n \"env.example.template\": \".env.example\",\n \"npmrc.template\": \".npmrc\",\n // Suffixed so mosaic's own oxlint/oxfmt don't discover these as nested\n // configs (a scaffolded monorepo's root config is invalid as a nested one).\n \"oxlint.config.ts.template\": \"oxlint.config.ts\",\n \"oxfmt.config.ts.template\": \"oxfmt.config.ts\",\n};\n\nfunction shouldSkip(src: string): boolean {\n const basename = path.basename(src);\n\n if (SKIP_DIRS.has(basename)) return true;\n if (SKIP_FILES.has(basename)) return true;\n\n return false;\n}\n\nfunction getTemplateDir(templateType: TemplateType): string {\n // Templates are located relative to the bundled output at ../templates/<type>\n // When bundled, __dirname is dist/, so we go up one level to find templates/\n return path.resolve(__dirname, \"../templates\", templateType);\n}\n\nexport async function copyTemplate(\n targetDir: string,\n templateType: TemplateType,\n): Promise<void> {\n const templateDir = getTemplateDir(templateType);\n\n // Ensure template directory exists\n if (!(await fs.pathExists(templateDir))) {\n throw new Error(`Template directory not found: ${templateDir}`);\n }\n\n // Create target directory\n await fs.ensureDir(targetDir);\n\n // Copy template with filtering\n await fs.copy(templateDir, targetDir, {\n filter: (src) => !shouldSkip(src),\n });\n\n // Rename .template files\n for (const [templateName, targetName] of Object.entries(\n TEMPLATE_FILE_MAPPINGS,\n )) {\n const templatePath = path.join(targetDir, templateName);\n const targetPath = path.join(targetDir, targetName);\n\n if (await fs.pathExists(templatePath)) {\n await fs.move(templatePath, targetPath, { overwrite: true });\n }\n }\n\n // Recreate the Claude symlink after copy because published packages\n // cannot rely on template symlinks being preserved.\n if (templateType === \"webapp\") {\n const agentsPath = path.join(targetDir, \"AGENTS.md\");\n const claudePath = path.join(targetDir, \"CLAUDE.md\");\n\n if (await fs.pathExists(agentsPath)) {\n if (await fs.pathExists(claudePath)) {\n await fs.remove(claudePath);\n }\n await fs.ensureSymlink(\"AGENTS.md\", claudePath);\n }\n }\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport { parse } from \"yaml\";\n\nexport interface MonorepoContext {\n found: boolean;\n rootDir: string | null;\n workspacePatterns: string[];\n packageDir: string | null; // e.g., \"/abs/path/to/monorepo/packages\"\n}\n\nconst NOT_FOUND: MonorepoContext = {\n found: false,\n rootDir: null,\n workspacePatterns: [],\n packageDir: null,\n};\n\n/**\n * Walk up from `startDir` looking for pnpm-workspace.yaml.\n * If found, parse it and derive the package directory.\n */\nexport async function detectMonorepo(\n startDir: string,\n): Promise<MonorepoContext> {\n let current = path.resolve(startDir);\n const root = path.parse(current).root;\n\n while (current !== root) {\n const workspaceFile = path.join(current, \"pnpm-workspace.yaml\");\n\n if (await fs.pathExists(workspaceFile)) {\n try {\n const content = await fs.readFile(workspaceFile, \"utf-8\");\n const parsed = parse(content) as { packages?: string[] } | null;\n\n if (!parsed?.packages || !Array.isArray(parsed.packages)) {\n return NOT_FOUND;\n }\n\n const workspacePatterns = parsed.packages;\n\n // Derive package directory from the first pattern\n // e.g., \"packages/*\" → \"packages\"\n const firstPattern = workspacePatterns[0];\n if (!firstPattern) {\n return NOT_FOUND;\n }\n\n const baseDir = firstPattern.replace(/\\/?\\*.*$/, \"\").trim();\n const packageDir = path.join(current, baseDir);\n\n return {\n found: true,\n rootDir: current,\n workspacePatterns,\n packageDir,\n };\n } catch {\n return NOT_FOUND;\n }\n }\n\n current = path.dirname(current);\n }\n\n return NOT_FOUND;\n}\n","import { randomBytes } from \"node:crypto\";\nimport path from \"node:path\";\nimport fs from \"fs-extra\";\n\n/**\n * Writes .env.local for the webapp template with real generated values for\n * BETTER_AUTH_SECRET and ENCRYPTION_SECRET_KEY so the user can run dev/seed\n * immediately. The .env.example file remains the documentation source.\n *\n * This is a no-op if .env.local already exists.\n */\nexport async function generateEnvLocal(packageDir: string): Promise<void> {\n const examplePath = path.join(packageDir, \".env.example\");\n const localPath = path.join(packageDir, \".env.local\");\n if (!(await fs.pathExists(examplePath))) return;\n\n if (!(await fs.pathExists(localPath))) {\n const authSecret = randomBytes(32).toString(\"base64\");\n const encKey = randomBytes(16).toString(\"hex\");\n\n const content = (await fs.readFile(examplePath, \"utf-8\"))\n .replace(/^BETTER_AUTH_SECRET=.*$/m, `BETTER_AUTH_SECRET=${authSecret}`)\n .replace(\n /^ENCRYPTION_SECRET_KEY=.*$/m,\n `ENCRYPTION_SECRET_KEY=${encKey}`,\n );\n\n await fs.writeFile(localPath, content);\n }\n}\n","import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport fs from \"fs-extra\";\n\nexport interface CreatePackageMetadata {\n name: string;\n version: string;\n}\n\nconst FALLBACK_METADATA: CreatePackageMetadata = {\n name: \"@percepta/create\",\n version: \"0.0.0\",\n};\n\nexport function readCreatePackageMetadata(): CreatePackageMetadata {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(currentDir, \"../package.json\"),\n path.resolve(currentDir, \"../../package.json\"),\n ];\n\n for (const packageJsonPath of candidates) {\n try {\n const pkg = fs.readJsonSync(packageJsonPath) as {\n name?: unknown;\n version?: unknown;\n };\n if (typeof pkg.name === \"string\" && typeof pkg.version === \"string\") {\n return { name: pkg.name, version: pkg.version };\n }\n } catch {\n // Source tests and bundled CLI resolve from different directories.\n }\n }\n\n return FALLBACK_METADATA;\n}\n","import path from \"node:path\";\nimport inquirer from \"inquirer\";\nimport { toKebabCase, toTitleCase } from \"./case-converters.js\";\nimport {\n DEFAULT_MOSAIC_DESIGN_THEME,\n type MosaicDesignTheme,\n VALID_MOSAIC_DESIGN_THEMES,\n} from \"./design-theme.js\";\nimport type { MonorepoContext } from \"./detect-monorepo.js\";\nimport { validateProjectName } from \"./validate.js\";\n\nexport const VALID_PROJECT_TYPES = [\"monorepo\", \"webapp\", \"library\"] as const;\nexport type ProjectType = (typeof VALID_PROJECT_TYPES)[number];\n\nexport function isValidProjectType(value: unknown): value is ProjectType {\n return (\n typeof value === \"string\" &&\n VALID_PROJECT_TYPES.includes(value as ProjectType)\n );\n}\n\nexport interface ProjectAnswers {\n projectType: ProjectType;\n directory: string;\n name: string;\n title: string;\n installDeps: boolean;\n customerSlug?: string;\n designTheme?: MosaicDesignTheme;\n monorepoName?: string;\n monorepoTitle?: string;\n}\n\ninterface PromptDefaults {\n projectType?: ProjectType;\n name?: string;\n customerSlug?: string;\n designTheme?: MosaicDesignTheme;\n repoName?: string;\n skipInstall?: boolean;\n monorepoContext?: MonorepoContext;\n cwd?: string;\n beforeNamePrompt?: (projectType: ProjectType) => void | Promise<void>;\n}\n\nasync function promptName(\n message: string,\n defaultName?: string,\n): Promise<string> {\n // We kebab-case both inside `validate` (inquirer runs validate on the raw\n // input, before filter) and via `filter` (so the stored answer is also\n // kebab-cased). That way \"My App\" → \"my-app\" without bouncing the user with\n // a capital-letters error.\n const { name } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"name\",\n message,\n default: defaultName,\n filter: toKebabCase,\n validate: (input: string) => {\n const result = validateProjectName(toKebabCase(input));\n return result.valid || result.error || \"Invalid project name\";\n },\n },\n ]);\n return name;\n}\n\nasync function promptCustomerSlug(): Promise<string> {\n const { customerSlug } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"customerSlug\",\n message: \"Customer slug?\",\n filter: toKebabCase,\n validate: (input: string) => {\n const result = validateProjectName(toKebabCase(input));\n return result.valid || result.error || \"Invalid customer slug\";\n },\n },\n ]);\n return customerSlug;\n}\n\nasync function resolveCustomerSlug(defaults: PromptDefaults): Promise<string> {\n if (defaults.customerSlug) return defaults.customerSlug;\n\n // Automation commonly provides the package/repo flags without `--yes`.\n // Keep explicit flag flows prompt-free unless customer input is needed.\n if (defaults.projectType === \"monorepo\" && defaults.name) {\n return defaults.name;\n }\n if (defaults.projectType && defaults.name && defaults.repoName) {\n return defaults.repoName;\n }\n\n return promptCustomerSlug();\n}\n\nasync function promptDesignTheme(): Promise<MosaicDesignTheme> {\n const { designTheme } = await inquirer.prompt([\n {\n type: \"rawlist\",\n name: \"designTheme\",\n message: \"Design theme?\",\n default: DEFAULT_MOSAIC_DESIGN_THEME,\n choices: VALID_MOSAIC_DESIGN_THEMES.map((theme) => ({\n name: theme,\n value: theme,\n })),\n },\n ]);\n return designTheme;\n}\n\nasync function resolveDesignTheme(\n projectType: ProjectType,\n defaults: PromptDefaults,\n): Promise<MosaicDesignTheme | undefined> {\n if (projectType !== \"webapp\") return undefined;\n if (defaults.designTheme) return defaults.designTheme;\n\n // Automation commonly provides both --type and --name without --yes. Keep\n // that flow prompt-free and use the canonical default theme.\n if (defaults.projectType && defaults.name) return DEFAULT_MOSAIC_DESIGN_THEME;\n\n return promptDesignTheme();\n}\n\n/**\n * Outside a monorepo we collect the repo name first, then ask a single\n * \"is it a webapp?\" Y/n. Yes (default) → monorepo + webapp, no → bare\n * monorepo. Library at the top level is rare enough that we leave it as a\n * `--type library` flag rather than a third prompt option. The repo name is\n * collected separately from any initial package name so a customer monorepo\n * is not forced to share its first app's name.\n */\nasync function promptOutsideMonorepoType(): Promise<ProjectType> {\n const { webapp } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"webapp\",\n message: \"Initialize with a webapp?\",\n default: true,\n },\n ]);\n return webapp ? \"webapp\" : \"monorepo\";\n}\n\n/**\n * Inside a monorepo, both webapp and library are common, so present them as\n * a numbered rawlist — user presses 1 or 2 + Enter. Defaults to webapp.\n */\nasync function promptInsideMonorepoType(): Promise<ProjectType> {\n const { projectType } = await inquirer.prompt([\n {\n type: \"rawlist\",\n name: \"projectType\",\n message: \"What kind of package?\",\n // inquirer v12 / @inquirer/rawlist v5 matches `default` against the\n // choice's `value`, not its index. `default: 0` would be a no-op.\n default: \"webapp\",\n choices: [\n { name: \"Webapp — A Next.js webapp\", value: \"webapp\" },\n { name: \"Library — A TypeScript library\", value: \"library\" },\n ],\n },\n ]);\n return projectType;\n}\n\nexport async function promptProjectDetails(\n defaults: PromptDefaults,\n): Promise<ProjectAnswers> {\n const inMonorepo = defaults.monorepoContext?.found ?? false;\n const cwd = defaults.cwd ?? process.cwd();\n\n let projectType: ProjectType;\n let finalName: string;\n if (inMonorepo) {\n // Resolve type before name so webapp preflights (notably NPM_TOKEN) can\n // fail before the user spends time naming a package.\n projectType = defaults.projectType ?? (await promptInsideMonorepoType());\n await defaults.beforeNamePrompt?.(projectType);\n finalName = defaults.name || (await promptName(\"Package name?\"));\n } else {\n const customerSlug = await resolveCustomerSlug(defaults);\n const repoName =\n defaults.repoName ||\n (defaults.projectType === \"monorepo\" ? defaults.name : undefined) ||\n (await promptName(\"Repo name?\", `${customerSlug}-os`));\n const repoTitle = toTitleCase(repoName);\n\n projectType = defaults.projectType ?? (await promptOutsideMonorepoType());\n await defaults.beforeNamePrompt?.(projectType);\n\n if (projectType === \"monorepo\") {\n finalName = repoName;\n const finalTitle = repoTitle;\n const finalDirectory = path.resolve(cwd, repoName);\n\n return {\n projectType,\n directory: finalDirectory,\n name: finalName,\n title: finalTitle,\n installDeps: !defaults.skipInstall,\n customerSlug,\n monorepoName: repoName,\n monorepoTitle: repoTitle,\n };\n }\n\n const packageNamePrompt =\n projectType === \"webapp\" ? \"Webapp name?\" : \"Library name?\";\n finalName = defaults.name || (await promptName(packageNamePrompt));\n const designTheme = await resolveDesignTheme(projectType, defaults);\n const finalTitle = toTitleCase(finalName);\n const finalDirectory = path.resolve(cwd, repoName);\n\n return {\n projectType,\n directory: finalDirectory,\n name: finalName,\n title: finalTitle,\n installDeps: !defaults.skipInstall,\n customerSlug,\n designTheme,\n monorepoName: repoName,\n monorepoTitle: repoTitle,\n };\n }\n\n // Inside a monorepo the directory is empty here — create.ts derives it from\n // the workspace pattern.\n const finalTitle = finalName ? toTitleCase(finalName) : \"\";\n const designTheme = await resolveDesignTheme(projectType, defaults);\n const finalDirectory =\n !inMonorepo && finalName ? path.resolve(cwd, finalName) : \"\";\n\n return {\n projectType,\n directory: finalDirectory,\n name: finalName,\n title: finalTitle,\n installDeps: !defaults.skipInstall,\n designTheme,\n };\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\n\n/**\n * Moves per-app GitHub Actions workflows from the package's .github/workflows\n * directory to the monorepo root, where GitHub Actions actually picks them up.\n *\n * Only moves files whose names start with the app name (e.g.\n * `myapp-ryvn-release.yaml`). Any other (generic) workflow a package happens\n * to ship is left in place — CI lives at the monorepo root, not per-package.\n *\n * Cleans up an empty `.github/workflows` (and empty parent `.github`) after\n * the move.\n */\nexport async function relocateWorkflowsToRoot(\n packageDir: string,\n monorepoRoot: string,\n appName: string,\n): Promise<void> {\n const sourceDir = path.join(packageDir, \".github\", \"workflows\");\n if (!(await fs.pathExists(sourceDir))) return;\n\n const targetDir = path.join(monorepoRoot, \".github\", \"workflows\");\n await fs.ensureDir(targetDir);\n\n const entries = await fs.readdir(sourceDir);\n for (const name of entries) {\n if (!name.startsWith(`${appName}-`)) continue;\n if (!/\\.(ya?ml)$/.test(name)) continue;\n await fs.move(path.join(sourceDir, name), path.join(targetDir, name), {\n overwrite: true,\n });\n }\n\n // Tidy up empty directories left behind in the package.\n if ((await fs.readdir(sourceDir)).length === 0) {\n await fs.rmdir(sourceDir);\n const packageGithub = path.join(packageDir, \".github\");\n if ((await fs.readdir(packageGithub)).length === 0) {\n await fs.rmdir(packageGithub);\n }\n }\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport type { MosaicDesignTheme } from \"./design-theme.js\";\n\nexport interface AppConfig {\n name: string; // kebab-case: my-awesome-app\n title: string; // Title Case: My Awesome App\n dbName: string; // snake_case: my_awesome_app_db\n nameUpper: string; // UPPER-CASE: MY-AWESOME-APP\n nameSnake: string; // snake_case: my_awesome_app\n repoName: string; // kebab-case GitHub repo name\n repoNameSnake: string; // snake_case GitHub repo name\n createPackage: string; // package used by generated monorepo helper scripts\n createVersion: string; // exact create package version pinned by generated monorepos\n designTheme: MosaicDesignTheme; // Mosaic design theme: modern, paper, dense\n}\n\nexport interface ReplaceStats {\n processed: number;\n modified: number;\n}\n\nconst PLACEHOLDERS = {\n __APP_NAME__: \"name\",\n __APP_TITLE__: \"title\",\n __DB_NAME__: \"dbName\",\n __APP_NAME_UPPER__: \"nameUpper\",\n __APP_NAME_SNAKE__: \"nameSnake\",\n __REPO_NAME__: \"repoName\",\n __REPO_NAME_SNAKE__: \"repoNameSnake\",\n __CREATE_PACKAGE__: \"createPackage\",\n __CREATE_VERSION__: \"createVersion\",\n __MOSAIC_DESIGN_THEME__: \"designTheme\",\n} as const;\n\n// Directories to skip\nconst SKIP_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \"dist\",\n \".turbo\",\n \".vercel\",\n]);\n\n// Files to skip\nconst SKIP_FILES = new Set([\n \"pnpm-lock.yaml\",\n \"package-lock.json\",\n \"yarn.lock\",\n]);\n\n// File extensions to process\nconst PROCESSABLE_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".yml\",\n \".yaml\",\n \".md\",\n \".env\",\n \".sql\",\n \".tf\",\n \".tfvars\",\n \".sh\",\n \".zed\",\n \".mjs\",\n \".cjs\",\n]);\n\n// Specific filenames to process (without extensions)\nconst PROCESSABLE_FILENAMES = new Set([\n \"Dockerfile\",\n \".env.example\",\n \".env.local\",\n \"terraform.tfvars.example\",\n]);\n\nfunction shouldProcessFile(filePath: string): boolean {\n const fileName = path.basename(filePath);\n const ext = path.extname(filePath);\n\n if (SKIP_FILES.has(fileName)) return false;\n if (PROCESSABLE_FILENAMES.has(fileName)) return true;\n\n return PROCESSABLE_EXTENSIONS.has(ext);\n}\n\nasync function replaceInFile(\n filePath: string,\n config: AppConfig,\n): Promise<boolean> {\n let content: string;\n try {\n content = await fs.readFile(filePath, \"utf-8\");\n } catch {\n return false;\n }\n\n let modified = false;\n let newContent = content;\n\n // Sort placeholders by length descending to prevent prefix collisions\n // (e.g., __APP_NAME__ must not be replaced before __APP_NAME_UPPER__)\n const sortedEntries = Object.entries(PLACEHOLDERS).sort(\n (a, b) => b[0].length - a[0].length,\n );\n\n for (const [placeholder, configKey] of sortedEntries) {\n const value = config[configKey as keyof AppConfig];\n if (newContent.includes(placeholder)) {\n newContent = newContent.split(placeholder).join(value);\n modified = true;\n }\n }\n\n if (modified) {\n await fs.writeFile(filePath, newContent);\n return true;\n }\n\n return false;\n}\n\nfunction substituteName(name: string, config: AppConfig): string {\n // Same precedence rule as content substitution: longer placeholders first\n // so __APP_NAME_UPPER__ is replaced before __APP_NAME__.\n const sortedEntries = Object.entries(PLACEHOLDERS).sort(\n (a, b) => b[0].length - a[0].length,\n );\n let result = name;\n for (const [placeholder, configKey] of sortedEntries) {\n if (result.includes(placeholder)) {\n result = result\n .split(placeholder)\n .join(config[configKey as keyof AppConfig]);\n }\n }\n return result;\n}\n\nasync function processDirectory(\n dirPath: string,\n config: AppConfig,\n stats: ReplaceStats,\n): Promise<void> {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n if (!SKIP_DIRS.has(entry.name)) {\n await processDirectory(fullPath, config, stats);\n }\n } else if (entry.isFile() && shouldProcessFile(fullPath)) {\n stats.processed++;\n if (await replaceInFile(fullPath, config)) {\n stats.modified++;\n }\n const renamed = substituteName(entry.name, config);\n if (renamed !== entry.name) {\n await fs.move(fullPath, path.join(dirPath, renamed), {\n overwrite: true,\n });\n }\n }\n }\n}\n\nexport async function replacePlaceholders(\n targetDir: string,\n config: AppConfig,\n): Promise<ReplaceStats> {\n const stats: ReplaceStats = { processed: 0, modified: 0 };\n await processDirectory(targetDir, config, stats);\n return stats;\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport { readCreatePackageMetadata } from \"./package-metadata.js\";\nimport { getTemplateVersion } from \"./template-versions.js\";\n\nexport const WORKSPACE_MANIFEST_FILENAME = \".mosaic-workspace.json\";\nexport const WORKSPACE_MANIFEST_SCHEMA_VERSION = 1;\n\nexport interface MosaicWorkspaceManifest {\n schemaVersion: typeof WORKSPACE_MANIFEST_SCHEMA_VERSION;\n customerSlug: string;\n createPackage: string;\n createVersion: string;\n monorepoTemplateVersion: string;\n compatibleTemplates: Record<string, string>;\n createdAt: string;\n}\n\nexport interface CreateWorkspaceManifestOptions {\n customerSlug: string;\n createdAt?: string;\n}\n\nexport function getWorkspaceManifestPath(rootDir: string): string {\n return path.join(rootDir, WORKSPACE_MANIFEST_FILENAME);\n}\n\nexport function createWorkspaceManifest({\n customerSlug,\n createdAt = new Date().toISOString(),\n}: CreateWorkspaceManifestOptions): MosaicWorkspaceManifest {\n const createPackage = readCreatePackageMetadata();\n return {\n schemaVersion: WORKSPACE_MANIFEST_SCHEMA_VERSION,\n customerSlug,\n createPackage: createPackage.name,\n createVersion: createPackage.version,\n monorepoTemplateVersion: getTemplateVersion(\"monorepo\"),\n compatibleTemplates: {\n webapp: getTemplateVersion(\"webapp\"),\n library: getTemplateVersion(\"library\"),\n },\n createdAt,\n };\n}\n\nexport async function readWorkspaceManifest(\n rootDir: string,\n): Promise<MosaicWorkspaceManifest | null> {\n const manifestPath = getWorkspaceManifestPath(rootDir);\n if (!(await fs.pathExists(manifestPath))) return null;\n\n const content = await fs.readFile(manifestPath, \"utf-8\");\n try {\n return JSON.parse(content) as MosaicWorkspaceManifest;\n } catch (error) {\n throw new Error(\n `Invalid JSON in ${WORKSPACE_MANIFEST_FILENAME}: ${(error as Error).message}`,\n );\n }\n}\n\nexport async function writeWorkspaceManifest(\n rootDir: string,\n manifest: MosaicWorkspaceManifest,\n): Promise<void> {\n const manifestPath = getWorkspaceManifestPath(rootDir);\n await fs.writeJson(manifestPath, manifest, { spaces: 2 });\n await fs.appendFile(manifestPath, \"\\n\");\n}\n\nexport function getCompatibleTemplateVersion(\n manifest: MosaicWorkspaceManifest | null,\n templateType: string,\n): string {\n return (\n manifest?.compatibleTemplates[templateType] ??\n getTemplateVersion(templateType)\n );\n}\n","import { execSync, spawn } from \"node:child_process\";\nimport path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport ora from \"ora\";\nimport {\n toKebabCase,\n toTitleCase,\n toSnakeCase,\n} from \"../utils/case-converters.js\";\nimport { copyTemplate, type TemplateType } from \"../utils/copy-template.js\";\nimport {\n DEFAULT_MOSAIC_DESIGN_THEME,\n isValidMosaicDesignTheme,\n type MosaicDesignTheme,\n VALID_MOSAIC_DESIGN_THEMES,\n} from \"../utils/design-theme.js\";\nimport { detectMonorepo } from \"../utils/detect-monorepo.js\";\nimport { generateEnvLocal } from \"../utils/env-local.js\";\nimport {\n writeManifest,\n derivePlaceholders,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\nimport { readCreatePackageMetadata } from \"../utils/package-metadata.js\";\nimport {\n promptProjectDetails,\n type ProjectAnswers,\n type ProjectType,\n isValidProjectType,\n VALID_PROJECT_TYPES,\n} from \"../utils/prompts.js\";\nimport { relocateWorkflowsToRoot } from \"../utils/relocate-workflows.js\";\nimport {\n replacePlaceholders,\n type AppConfig,\n} from \"../utils/replace-placeholders.js\";\nimport { getTemplateVersion } from \"../utils/template-versions.js\";\nimport { validateProjectName } from \"../utils/validate.js\";\nimport {\n createWorkspaceManifest,\n getCompatibleTemplateVersion,\n readWorkspaceManifest,\n writeWorkspaceManifest,\n type MosaicWorkspaceManifest,\n} from \"../utils/workspace-manifest.js\";\n\nexport interface CreateOptions {\n type?: string;\n name?: string;\n customer?: string;\n theme?: string;\n repoName?: string;\n cwd?: string;\n skipInstall: boolean;\n yes: boolean;\n addOnly?: boolean;\n}\n\n// The webapp template enforces pnpm via `only-allow pnpm`; the monorepo and\n// library templates also assume pnpm. Hardcoding it removes a layer of\n// configuration that didn't reflect any real flexibility.\nconst PACKAGE_MANAGER = \"pnpm\";\nconst MAX_INSTALL_OUTPUT_CHARS = 64_000;\nconst MAX_INSTALL_OUTPUT_LINES = 80;\n\nclass PackageManagerCommandError extends Error {\n public constructor(\n message: string,\n public readonly output: string,\n ) {\n super(message);\n this.name = \"PackageManagerCommandError\";\n }\n}\n\n/** Paths in copy-paste shell commands (POSIX-style). */\nfunction shPath(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\n/** Non-blocking install so ora can animate (execSync would block timers). */\nfunction runPackageManagerInstall(\n packageManager: string,\n cwd: string,\n args: string[] = [\"install\"],\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let output = \"\";\n const appendOutput = (chunk: Buffer) => {\n output += chunk.toString();\n if (output.length > MAX_INSTALL_OUTPUT_CHARS) {\n output = output.slice(-MAX_INSTALL_OUTPUT_CHARS);\n }\n };\n const child = spawn(packageManager, args, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n child.stdout?.on(\"data\", appendOutput);\n child.stderr?.on(\"data\", appendOutput);\n child.on(\"error\", (error) => {\n reject(\n new PackageManagerCommandError(\n `${packageManager} ${args.join(\" \")} failed: ${error.message}`,\n output,\n ),\n );\n });\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else\n reject(\n new PackageManagerCommandError(\n `${packageManager} ${args.join(\" \")} exited with code ${code ?? \"unknown\"}`,\n output,\n ),\n );\n });\n });\n}\n\nfunction printInstallFailureOutput(error: unknown): void {\n if (!(error instanceof PackageManagerCommandError)) return;\n const output = error.output.trim();\n if (!output) return;\n\n const lines = output.split(/\\r?\\n/);\n const omitted = Math.max(0, lines.length - MAX_INSTALL_OUTPUT_LINES);\n const visibleLines = lines.slice(-MAX_INSTALL_OUTPUT_LINES);\n\n console.log();\n console.log(\n chalk.bold(`Last ${visibleLines.length} lines from pnpm install:`),\n );\n if (omitted > 0) {\n console.log(chalk.dim(`... omitted ${omitted} earlier lines ...`));\n }\n console.log(visibleLines.join(\"\\n\"));\n}\n\n/**\n * Runs the monorepo-root `setup` script (local services + dbs + access + seed).\n * Uses `pnpm run setup` (not `pnpm setup`) because `pnpm setup` is a pnpm builtin that configures\n * PNPM_HOME in the user's shell rc — it ignores the package.json script of the same name.\n */\nfunction runWebappSetup(\n packageManager: string,\n monorepoRoot: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(packageManager, [\"run\", \"setup\"], {\n cwd: monorepoRoot,\n stdio: \"inherit\",\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else\n reject(\n new Error(\n `${packageManager} run setup exited with code ${code ?? \"unknown\"}`,\n ),\n );\n });\n });\n}\n\n/**\n * Spawns `pnpm dev` in the package directory and resolves once Next reports\n * \"Ready in\" (so we know the server is accepting requests). Returns the child\n * process so the caller can await its exit when the user hits Ctrl+C.\n *\n * Captures the actual URL Next picked (Next falls back to 3001+ if 3000 is\n * taken) so the caller can open the right one in the browser.\n */\n// ANSI CSI sequences (color/control codes Next emits to TTY-detected stdout).\n// eslint-disable-next-line no-control-regex\nconst ANSI_PATTERN = /\\u001b\\[[0-9;]*[a-zA-Z]/g;\n\nfunction spawnDevServer(\n packageManager: string,\n cwd: string,\n): { child: ReturnType<typeof spawn>; ready: Promise<{ url: string }> } {\n // Use `run dev` rather than `<pm> dev` because npm has no `dev` shorthand\n // (it only aliases test/start/stop/restart). `run <script>` works uniformly\n // across pnpm/npm/yarn — same reason runWebappSetup uses `run setup`.\n const child = spawn(packageManager, [\"run\", \"dev\"], {\n cwd,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n\n const ready = new Promise<{ url: string }>((resolve, reject) => {\n let resolved = false;\n let detectedUrl = \"http://localhost:3000\";\n // Pipe chunks aren't line-aligned, so accumulate stdout into a rolling\n // buffer and re-scan after each chunk. We trim aggressively to avoid\n // unbounded growth on a server that runs for hours.\n let buffer = \"\";\n const onChunk = (chunk: Buffer) => {\n const text = chunk.toString();\n process.stdout.write(text);\n buffer = (buffer + text).slice(-4096).replace(ANSI_PATTERN, \"\");\n const urlMatch = buffer.match(/Local:\\s+(https?:\\/\\/\\S+?)(?:\\s|$)/i);\n if (urlMatch?.[1]) detectedUrl = urlMatch[1].trim();\n if (!resolved && /Ready in /i.test(buffer)) {\n resolved = true;\n resolve({ url: detectedUrl });\n }\n };\n child.stdout?.on(\"data\", onChunk);\n child.stderr?.on(\"data\", (chunk) => process.stderr.write(chunk));\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (!resolved) {\n reject(\n new Error(\n `${packageManager} run dev exited with code ${code ?? \"unknown\"} before becoming ready`,\n ),\n );\n }\n });\n });\n\n return { child, ready };\n}\n\n/**\n * Cross-platform \"open this URL in the user's default browser\". Returns true\n * if the launcher process spawned, false on synchronous failure. The empty\n * `error` listener swallows the asynchronous error event that fires when the\n * launcher binary is missing (e.g. minimal Linux without `xdg-open`) — without\n * it, that event becomes an uncaught exception that kills the CLI mid-run.\n */\nfunction openInBrowser(url: string): boolean {\n const cmd =\n process.platform === \"darwin\"\n ? [\"open\", url]\n : process.platform === \"win32\"\n ? [\"cmd\", \"/c\", \"start\", \"\", url]\n : [\"xdg-open\", url];\n try {\n const child = spawn(cmd[0]!, cmd.slice(1), {\n stdio: \"ignore\",\n detached: true,\n });\n child.on(\"error\", () => {});\n child.unref();\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Post-scaffold orchestration for webapps: run root setup (local services + dbs + access + seed),\n * start the dev server, open the served URL in the user's browser, then hand\n * control to the dev server until the user exits with Ctrl+C.\n *\n * Returns true if the dev server got running (caller should NOT print next\n * steps in that case — the user is already in the running app). Returns\n * false on any failure so the caller can print manual fallback steps.\n *\n * Callers should only invoke this when install actually succeeded —\n * starting setup without node_modules will leave an orphan Docker container.\n */\nasync function autoRunWebapp(\n packageDir: string,\n monorepoRoot: string,\n): Promise<boolean> {\n const packageManager = PACKAGE_MANAGER;\n\n console.log();\n console.log(\n chalk.bold(\"Running setup (local services, dbs, access, seed)...\"),\n );\n console.log();\n try {\n await runWebappSetup(packageManager, monorepoRoot);\n } catch (error) {\n console.log();\n console.log(\n chalk.yellow(\"!\"),\n \"Setup failed. You can re-run it manually:\",\n chalk.cyan(`cd ${monorepoRoot} && ${packageManager} run setup`),\n );\n console.log(chalk.dim((error as Error).message));\n return false;\n }\n\n console.log();\n console.log(chalk.bold(\"Starting dev server...\"));\n console.log();\n const { child, ready } = spawnDevServer(packageManager, packageDir);\n\n // Register the \"dev server has exited\" listener BEFORE we await `ready`.\n // If the child exits during that await and we attached the listener\n // afterwards, we'd miss the event (Node EventEmitter doesn't replay past\n // events) and hang forever on the final `await closed`.\n const closed = new Promise<void>((resolve) => {\n child.on(\"close\", () => resolve());\n });\n\n let url = \"http://localhost:3000\";\n try {\n ({ url } = await ready);\n } catch (error) {\n console.log();\n console.log(chalk.yellow(\"!\"), \"Dev server failed to become ready.\");\n console.log(chalk.dim((error as Error).message));\n return false;\n }\n\n if (openInBrowser(url)) {\n console.log();\n console.log(chalk.green(\"✔\"), \"Opened\", chalk.cyan(url));\n } else {\n console.log();\n console.log(\n chalk.dim(\"Open\"),\n chalk.cyan(url),\n chalk.dim(\"in your browser.\"),\n );\n }\n\n // Hand control to the dev server until the user exits.\n await closed;\n return true;\n}\n\nasync function writeMosaicFiles(\n packageDir: string,\n config: {\n name: string;\n title: string;\n designTheme?: MosaicDesignTheme;\n repoName?: string;\n },\n projectType: string,\n templateVersion = getTemplateVersion(projectType),\n templateCommit = \"npm\",\n): Promise<void> {\n const manifest: MosaicManifest = {\n templateType: projectType,\n templateVersion,\n templateCommit,\n createdAt: new Date().toISOString(),\n placeholders: derivePlaceholders(\n config.name,\n config.title,\n config.repoName,\n config.designTheme,\n ),\n source: {\n templatePath: `packages/blueberry/templates/${projectType}`,\n },\n };\n\n await writeManifest(packageDir, manifest);\n\n // Write starter mosaic-template-notes.md\n const notesPath = path.join(packageDir, \"mosaic-template-notes.md\");\n await fs.writeFile(\n notesPath,\n `# Mosaic Divergence Notes\\n\\nDocument intentional differences from the ${projectType} template here.\\nClaude reads this file during sync to preserve your customizations.\\n\\n## Intentional Divergences\\n\\n_None yet — freshly created from template._\\n`,\n );\n}\n\nfunction buildAppConfig(\n name: string,\n title = toTitleCase(name),\n repoName = name,\n designTheme = DEFAULT_MOSAIC_DESIGN_THEME,\n): AppConfig {\n const createPackage = readCreatePackageMetadata();\n return {\n name,\n title,\n dbName: `${toSnakeCase(name)}_db`,\n nameUpper: name.toUpperCase(),\n nameSnake: toSnakeCase(name),\n repoName,\n repoNameSnake: toSnakeCase(repoName),\n createPackage: createPackage.name,\n createVersion: createPackage.version,\n designTheme,\n };\n}\n\n/** Copy the monorepo template into `targetDir` and replace its placeholders. */\nasync function scaffoldMonorepo(\n targetDir: string,\n config: AppConfig,\n): Promise<void> {\n const monoSpinner = ora(\"Copying monorepo template...\").start();\n try {\n await copyTemplate(targetDir, \"monorepo\" satisfies TemplateType);\n monoSpinner.succeed(\"Copied monorepo template\");\n } catch (error) {\n monoSpinner.fail(\"Failed to copy monorepo template\");\n console.error(error);\n process.exit(1);\n }\n\n const replaceSpinner = ora(\"Replacing monorepo placeholders...\").start();\n try {\n const stats = await replacePlaceholders(targetDir, config);\n replaceSpinner.succeed(\n `Replaced placeholders in ${stats.modified} monorepo files`,\n );\n } catch (error) {\n replaceSpinner.fail(\"Failed to replace monorepo placeholders\");\n console.error(error);\n process.exit(1);\n }\n}\n\n/**\n * Add a package (webapp or library) to a monorepo: copy the template into\n * `packageDir`, replace placeholders, write the Mosaic manifest, and run the\n * webapp-only post-copy steps (.env.local, workflow relocation) when applicable.\n */\nasync function addPackageToMonorepo(args: {\n packageDir: string;\n monorepoRoot: string;\n projectType: \"webapp\" | \"library\";\n config: AppConfig;\n templateVersion: string;\n templateCommit: string;\n}): Promise<void> {\n const {\n packageDir,\n monorepoRoot,\n projectType,\n config,\n templateVersion,\n templateCommit,\n } = args;\n\n const copySpinner = ora(\"Copying package template...\").start();\n try {\n await copyTemplate(packageDir, projectType);\n copySpinner.succeed(\"Copied package template\");\n } catch (error) {\n copySpinner.fail(\"Failed to copy package template\");\n console.error(error);\n process.exit(1);\n }\n\n const replaceSpinner = ora(\"Replacing package placeholders...\").start();\n try {\n const stats = await replacePlaceholders(packageDir, config);\n replaceSpinner.succeed(\n `Replaced placeholders in ${stats.modified} package files`,\n );\n } catch (error) {\n replaceSpinner.fail(\"Failed to replace package placeholders\");\n console.error(error);\n process.exit(1);\n }\n\n await writeMosaicFiles(\n packageDir,\n config,\n projectType,\n templateVersion,\n templateCommit,\n );\n\n if (projectType === \"webapp\") {\n await generateEnvLocal(packageDir);\n await relocateWorkflowsToRoot(packageDir, monorepoRoot, config.name);\n }\n}\n\n/** Initialize a git repo at `targetDir` with an initial commit. Best-effort. */\nfunction initGitRepo(targetDir: string): void {\n const gitSpinner = ora(\"Initializing git repository...\").start();\n try {\n execSync(\"git init\", { cwd: targetDir, stdio: \"ignore\" });\n execSync(\"git add -A\", { cwd: targetDir, stdio: \"ignore\" });\n execSync('git commit -m \"Initial commit from @percepta/create\"', {\n cwd: targetDir,\n stdio: \"ignore\",\n });\n gitSpinner.succeed(\"Initialized git repository\");\n } catch {\n gitSpinner.warn(\"Failed to initialize git repository\");\n }\n}\n\n/**\n * Run `pnpm install` at the monorepo root with a spinner. Returns true if\n * install ran successfully; false if it failed or was skipped.\n */\nasync function installAtMonorepoRoot(\n monorepoRoot: string,\n installDeps: boolean,\n): Promise<boolean> {\n if (!installDeps) return false;\n const spinner = ora(\n `Installing dependencies with ${PACKAGE_MANAGER}...`,\n ).start();\n try {\n await runPackageManagerInstall(PACKAGE_MANAGER, monorepoRoot);\n spinner.succeed(\"Installed dependencies\");\n return true;\n } catch (error) {\n spinner.warn(\n `Failed to install dependencies. Run '${PACKAGE_MANAGER} install' from monorepo root.`,\n );\n printInstallFailureOutput(error);\n return false;\n }\n}\n\n/**\n * For webapp scaffolds with a successful install, hand off to autoRunWebapp\n * (setup → dev → open browser). No-op otherwise. Returns true if the dev\n * server actually started — caller skips manual next-steps in that case.\n *\n * Gated on `installSucceeded` because starting setup without node_modules\n * leaves an orphan Docker container.\n */\nasync function maybeAutoRunWebapp(\n packageDir: string | null,\n monorepoRoot: string,\n projectType: ProjectType,\n installSucceeded: boolean,\n): Promise<boolean> {\n if (!packageDir || projectType !== \"webapp\" || !installSucceeded)\n return false;\n return autoRunWebapp(packageDir, monorepoRoot);\n}\n\nfunction getProjectTypeLabel(projectType: ProjectType): string {\n switch (projectType) {\n case \"monorepo\":\n return \"pnpm monorepo\";\n case \"webapp\":\n return \"Next.js webapp\";\n case \"library\":\n return \"TypeScript library\";\n default: {\n const exhaustiveCheck: never = projectType;\n throw new Error(`Unknown project type: ${String(exhaustiveCheck)}`);\n }\n }\n}\n\nfunction requireNpmTokenForWebappInstall(\n projectType: ProjectType,\n installDeps: boolean,\n): void {\n // The webapp template depends on private `@percepta/*` packages whose .npmrc\n // resolves auth from `${NPM_TOKEN}`. If the env var is empty, `pnpm install`\n // dies deep in cryptic 401/404 logs. Catch it before asking for names.\n if (projectType !== \"webapp\" || !installDeps || process.env.NPM_TOKEN) {\n return;\n }\n\n console.log();\n console.error(chalk.red(\"Error: NPM_TOKEN environment variable is not set.\"));\n console.error(\n chalk.dim(\" Required to install private @percepta/* packages.\"),\n );\n console.error();\n console.error(\" 1. Grab the npm token from 1Password:\");\n console.error(\n chalk.cyan(\n \" https://start.1password.com/open/i?a=5TX2B4O3QNE4FNQ2A7ZJZDRRBI&v=j7trpyuqh7gt635dtuj6y4pwjm&i=cmmdi5trji7ctkn3fseakf4mgi&h=aitco.1password.com\",\n ),\n );\n console.error(\" 2. Add to ~/.zshrc:\");\n console.error(chalk.cyan(' export NPM_TOKEN=\"<paste-token>\"'));\n console.error(\n \" 3. Open a new terminal (or \" +\n chalk.cyan(\"source ~/.zshrc\") +\n \") and re-run.\",\n );\n console.error();\n console.error(\n chalk.dim(\" Or pass --skip-install to scaffold without running install.\"),\n );\n process.exit(1);\n}\n\nfunction ensureWorkspaceCreateVersionCompatible(\n workspaceManifest: MosaicWorkspaceManifest | null,\n projectType: ProjectType,\n): void {\n if (!workspaceManifest || projectType === \"monorepo\") return;\n\n const createPackage = readCreatePackageMetadata();\n if (\n workspaceManifest.createPackage === createPackage.name &&\n workspaceManifest.createVersion === createPackage.version\n ) {\n return;\n }\n\n console.log();\n console.error(\n chalk.red(\n `Error: This workspace is pinned to ${workspaceManifest.createPackage}@${workspaceManifest.createVersion}, ` +\n `but you are running ${createPackage.name}@${createPackage.version}.`,\n ),\n );\n console.error();\n console.error(\n chalk.dim(\n \" Run the workspace-owned command so new packages match this monorepo:\",\n ),\n );\n console.error(chalk.cyan(` pnpm mosaic add ${projectType} <name>`));\n console.error();\n console.error(\n chalk.dim(\n \" To adopt newer templates, upgrade the workspace manifest first.\",\n ),\n );\n process.exit(1);\n}\n\nfunction getTemplateCommitSource(\n workspaceManifest: MosaicWorkspaceManifest | null,\n): string {\n if (!workspaceManifest) return \"npm\";\n return `${workspaceManifest.createPackage}@${workspaceManifest.createVersion}`;\n}\n\nexport async function createProject(options: CreateOptions): Promise<void> {\n const cwd = await resolveCreateCwd(options.cwd);\n\n // Validate --type if provided\n if (options.type !== undefined && !isValidProjectType(options.type)) {\n console.error(\n chalk.red(\n `Error: Invalid package type \"${options.type}\". Valid types are: ${VALID_PROJECT_TYPES.join(\", \")}`,\n ),\n );\n process.exit(1);\n }\n\n if (options.theme !== undefined && !isValidMosaicDesignTheme(options.theme)) {\n console.error(\n chalk.red(\n `Error: Invalid design theme \"${options.theme}\". Valid themes are: ${VALID_MOSAIC_DESIGN_THEMES.join(\", \")}`,\n ),\n );\n process.exit(1);\n }\n\n console.log();\n console.log(chalk.bold(\"Creating a new Mosaic package...\"));\n console.log();\n\n // Step 1: Detect monorepo context\n const monorepoContext = await detectMonorepo(cwd);\n\n if (options.addOnly && !monorepoContext.found) {\n console.error(\n chalk.red(\n \"Error: 'create add' must be run inside an existing pnpm monorepo.\",\n ),\n );\n process.exit(1);\n }\n\n // Bare monorepo only makes sense outside an existing monorepo.\n if (options.type === \"monorepo\" && monorepoContext.found) {\n console.error(\n chalk.red(\n `Error: Already inside a monorepo at ${monorepoContext.rootDir}. ` +\n `Choose 'webapp' or 'library' to add a package, or run from outside the monorepo.`,\n ),\n );\n process.exit(1);\n }\n\n if (monorepoContext.found) {\n console.log(\n chalk.dim(\" Detected monorepo at\"),\n chalk.cyan(monorepoContext.rootDir),\n );\n } else {\n console.log(\n chalk.dim(\" No monorepo detected. A new monorepo will be created.\"),\n );\n }\n console.log();\n\n const workspaceManifest = monorepoContext.found\n ? await readWorkspaceManifest(monorepoContext.rootDir!)\n : null;\n\n if (workspaceManifest) {\n console.log(\n chalk.dim(\" Workspace create version:\"),\n chalk.cyan(\n `${workspaceManifest.createPackage}@${workspaceManifest.createVersion}`,\n ),\n );\n console.log();\n } else if (monorepoContext.found) {\n console.log(\n chalk.yellow(\"!\"),\n \"No .mosaic-workspace.json found; using this CLI's bundled templates.\",\n );\n console.log();\n }\n\n // --name skips the package-name prompt; --repo-name skips the new-monorepo\n // repo-name prompt. Both are used by automation but are not the canonical\n // CLI UX.\n const projectName = options.name;\n const repoName = options.repoName;\n if (options.yes && !projectName) {\n console.error(chalk.red(\"Error: --name is required when using --yes flag\"));\n process.exit(1);\n }\n\n if (projectName) {\n const validation = validateProjectName(toKebabCase(projectName));\n if (!validation.valid) {\n console.error(chalk.red(`Invalid project name: ${validation.error}`));\n process.exit(1);\n }\n }\n\n if (repoName) {\n const validation = validateProjectName(toKebabCase(repoName));\n if (!validation.valid) {\n console.error(chalk.red(`Invalid repo name: ${validation.error}`));\n process.exit(1);\n }\n }\n\n const customerSlug = options.customer\n ? toKebabCase(options.customer)\n : undefined;\n\n if (customerSlug) {\n const validation = validateProjectName(customerSlug);\n if (!validation.valid) {\n console.error(chalk.red(`Invalid customer slug: ${validation.error}`));\n process.exit(1);\n }\n }\n\n // Step 2 & 3: Get project details from prompts or options\n let answers: ProjectAnswers;\n\n if (options.yes) {\n // Non-interactive mode (used by automation). Defaults: type=webapp.\n const projectType: ProjectType = (options.type as ProjectType) || \"webapp\";\n ensureWorkspaceCreateVersionCompatible(workspaceManifest, projectType);\n requireNpmTokenForWebappInstall(projectType, !options.skipInstall);\n const kebabName = toKebabCase(projectName!);\n const kebabRepoName = repoName\n ? toKebabCase(repoName)\n : customerSlug\n ? `${customerSlug}-os`\n : kebabName;\n const directory =\n monorepoContext.found && monorepoContext.packageDir\n ? path.join(monorepoContext.packageDir, kebabName)\n : path.resolve(cwd, kebabRepoName);\n\n answers = {\n projectType,\n directory,\n name: kebabName,\n title: toTitleCase(kebabName),\n installDeps: !options.skipInstall,\n customerSlug: monorepoContext.found\n ? undefined\n : (customerSlug ?? kebabRepoName),\n designTheme:\n projectType === \"webapp\"\n ? ((options.theme as MosaicDesignTheme | undefined) ??\n DEFAULT_MOSAIC_DESIGN_THEME)\n : undefined,\n monorepoName: monorepoContext.found ? undefined : kebabRepoName,\n monorepoTitle: monorepoContext.found\n ? undefined\n : toTitleCase(kebabRepoName),\n };\n } else {\n answers = await promptProjectDetails({\n projectType: options.type as ProjectType | undefined,\n name: projectName ? toKebabCase(projectName) : undefined,\n customerSlug,\n designTheme: options.theme as MosaicDesignTheme | undefined,\n repoName: repoName ? toKebabCase(repoName) : undefined,\n skipInstall: options.skipInstall,\n monorepoContext,\n cwd,\n beforeNamePrompt: (projectType) => {\n ensureWorkspaceCreateVersionCompatible(workspaceManifest, projectType);\n requireNpmTokenForWebappInstall(projectType, !options.skipInstall);\n },\n });\n\n // If inside monorepo, compute directory from workspace pattern + name\n if (\n monorepoContext.found &&\n monorepoContext.packageDir &&\n !answers.directory\n ) {\n answers.directory = path.join(monorepoContext.packageDir, answers.name);\n }\n }\n\n const monorepoName = answers.monorepoName ?? answers.name;\n const monorepoTitle = answers.monorepoTitle ?? toTitleCase(monorepoName);\n const newWorkspaceCustomerSlug = answers.customerSlug ?? monorepoName;\n const monorepoConfig = buildAppConfig(\n monorepoName,\n monorepoTitle,\n monorepoName,\n DEFAULT_MOSAIC_DESIGN_THEME,\n );\n const configRepoName = monorepoContext.found\n ? path.basename(monorepoContext.rootDir!)\n : monorepoName;\n const config = buildAppConfig(\n answers.name,\n answers.title,\n configRepoName,\n answers.designTheme,\n );\n\n const typeLabel = getProjectTypeLabel(answers.projectType);\n\n if (monorepoContext.found) {\n // --- ADDING TO EXISTING MONOREPO ---\n const monorepoRoot = monorepoContext.rootDir!;\n const packageDir = monorepoContext.packageDir\n ? path.join(monorepoContext.packageDir, answers.name)\n : answers.directory;\n\n console.log(chalk.dim(\" Package type:\"), typeLabel);\n console.log(chalk.dim(\" Target:\"), packageDir);\n console.log(chalk.dim(\" Name:\"), config.name);\n console.log(chalk.dim(\" Title:\"), config.title);\n if (answers.projectType === \"webapp\") {\n console.log(chalk.dim(\" Database:\"), config.dbName);\n console.log(chalk.dim(\" Design theme:\"), config.designTheme);\n }\n console.log();\n\n // Check if directory already exists and is not empty\n if (await fs.pathExists(packageDir)) {\n const files = await fs.readdir(packageDir);\n if (files.length > 0) {\n console.error(\n chalk.red(`Error: Directory ${packageDir} is not empty.`),\n );\n process.exit(1);\n }\n }\n\n if (answers.projectType !== \"monorepo\") {\n await addPackageToMonorepo({\n packageDir,\n monorepoRoot,\n projectType: answers.projectType,\n config,\n templateVersion: getCompatibleTemplateVersion(\n workspaceManifest,\n answers.projectType,\n ),\n templateCommit: getTemplateCommitSource(workspaceManifest),\n });\n }\n\n // pnpm reads .npmrc from the workspace root, not package dirs. If the\n // root .npmrc is missing the @percepta registry config, downstream\n // `pnpm install` won't authenticate.\n await warnIfMissingRootNpmrc(monorepoRoot);\n\n const installSucceeded = await installAtMonorepoRoot(\n monorepoRoot,\n answers.installDeps,\n );\n\n // Success\n console.log();\n console.log(\n chalk.green(\"\\u2714\"),\n chalk.bold(`Created ${typeLabel} at`),\n chalk.cyan(path.relative(monorepoRoot, packageDir)),\n );\n console.log();\n\n const devStarted = await maybeAutoRunWebapp(\n packageDir,\n monorepoRoot,\n answers.projectType,\n installSucceeded,\n );\n if (devStarted) return;\n\n printNextStepsExisting(answers, packageDir, !installSucceeded);\n } else {\n // --- CREATING NEW MONOREPO (with optional package inside) ---\n const isBareMonorepo = answers.projectType === \"monorepo\";\n const monorepoRoot = answers.directory;\n const packageDir = isBareMonorepo\n ? null\n : path.join(monorepoRoot, \"packages\", answers.name);\n\n if (isBareMonorepo) {\n console.log(chalk.dim(\" Type:\"), typeLabel);\n console.log(chalk.dim(\" Directory:\"), monorepoRoot);\n console.log(chalk.dim(\" Customer:\"), newWorkspaceCustomerSlug);\n console.log(chalk.dim(\" Repo name:\"), monorepoConfig.name);\n console.log(chalk.dim(\" Title:\"), monorepoConfig.title);\n } else {\n console.log(chalk.dim(\" Package type:\"), typeLabel);\n console.log(chalk.dim(\" Monorepo directory:\"), monorepoRoot);\n console.log(chalk.dim(\" Customer:\"), newWorkspaceCustomerSlug);\n console.log(chalk.dim(\" Repo name:\"), monorepoConfig.name);\n console.log(chalk.dim(\" Package:\"), `packages/${answers.name}/`);\n console.log(chalk.dim(\" Name:\"), config.name);\n console.log(chalk.dim(\" Title:\"), config.title);\n if (answers.projectType === \"webapp\") {\n console.log(chalk.dim(\" Database:\"), config.dbName);\n console.log(chalk.dim(\" Design theme:\"), config.designTheme);\n }\n }\n console.log();\n\n // Check if directory exists and is not empty.\n if (await fs.pathExists(monorepoRoot)) {\n const files = await fs.readdir(monorepoRoot);\n if (files.length > 0) {\n console.error(\n chalk.red(`Error: Directory ${monorepoRoot} is not empty.`),\n );\n process.exit(1);\n }\n }\n\n await scaffoldMonorepo(monorepoRoot, monorepoConfig);\n const newWorkspaceManifest = createWorkspaceManifest({\n customerSlug: newWorkspaceCustomerSlug,\n });\n await writeWorkspaceManifest(monorepoRoot, newWorkspaceManifest);\n\n if (packageDir && answers.projectType !== \"monorepo\") {\n await addPackageToMonorepo({\n packageDir,\n monorepoRoot,\n projectType: answers.projectType,\n config,\n templateVersion: getCompatibleTemplateVersion(\n newWorkspaceManifest,\n answers.projectType,\n ),\n templateCommit: getTemplateCommitSource(newWorkspaceManifest),\n });\n }\n\n const installSucceeded = await installAtMonorepoRoot(\n monorepoRoot,\n answers.installDeps,\n );\n\n // Initialize after install so generated lockfiles land in the first commit.\n initGitRepo(monorepoRoot);\n\n // Success\n console.log();\n console.log(\n chalk.green(\"\\u2714\"),\n chalk.bold(\n isBareMonorepo ? `Created ${typeLabel} at` : \"Created monorepo at\",\n ),\n chalk.cyan(monorepoRoot),\n );\n if (!isBareMonorepo) {\n console.log(\n chalk.green(\"\\u2714\"),\n chalk.bold(`Created ${typeLabel} at`),\n chalk.cyan(`packages/${answers.name}/`),\n );\n }\n console.log();\n\n const devStarted = await maybeAutoRunWebapp(\n packageDir,\n monorepoRoot,\n answers.projectType,\n installSucceeded,\n );\n if (devStarted) return;\n\n printNextStepsNew(answers, monorepoRoot, !installSucceeded);\n }\n}\n\nasync function resolveCreateCwd(\n cwdOption: string | undefined,\n): Promise<string> {\n const cwd = cwdOption ? path.resolve(cwdOption) : process.cwd();\n let stat;\n try {\n stat = await fs.stat(cwd);\n } catch {\n console.error(chalk.red(`Error: --cwd directory does not exist: ${cwd}`));\n process.exit(1);\n }\n\n if (!stat.isDirectory()) {\n console.error(chalk.red(`Error: --cwd is not a directory: ${cwd}`));\n process.exit(1);\n }\n\n return cwd;\n}\n\nfunction printWebappNextSteps(params: {\n pm: \"pnpm\" | \"npm\" | \"yarn\";\n answers: ProjectAnswers;\n variant: \"new\" | \"existing\";\n /** Whether dependencies still need to be installed before setup/dev. */\n installNeeded: boolean;\n /** Relative path from cwd to monorepo root. */\n monorepoRelativePath: string;\n /** Relative path from monorepo root to the package directory. */\n packageRelativePathFromRoot?: string;\n}): void {\n const {\n pm,\n answers,\n variant,\n installNeeded,\n monorepoRelativePath,\n packageRelativePathFromRoot,\n } = params;\n const repoRel = shPath(monorepoRelativePath) || \".\";\n const pkgFromRoot =\n shPath(packageRelativePathFromRoot ?? `packages/${answers.name}`) || \".\";\n // Use `pnpm run setup` (not `pnpm setup`) — the latter is a pnpm builtin.\n const setupStep = \"pnpm run setup\";\n const devStep = \"pnpm dev\";\n\n if (variant === \"new\") {\n const oneLinerParts: string[] = [];\n if (repoRel !== \".\") oneLinerParts.push(`cd ${repoRel}`);\n if (installNeeded) oneLinerParts.push(`${pm} install`);\n oneLinerParts.push(setupStep);\n oneLinerParts.push(`cd ${pkgFromRoot}`);\n oneLinerParts.push(devStep);\n\n console.log(chalk.bold(\"Copy-paste (from your current directory):\"));\n console.log();\n console.log(chalk.cyan(` ${oneLinerParts.join(\" && \")}`));\n console.log();\n console.log(chalk.bold(\"Or step by step:\"));\n console.log();\n\n let step = 1;\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(chalk.dim(` ${step++}.`), setupStep);\n console.log(chalk.dim(` ${step++}.`), `cd ${pkgFromRoot}`);\n console.log(chalk.dim(` ${step++}.`), devStep);\n return;\n }\n\n const oneLinerParts: string[] = [];\n\n if (repoRel !== \".\") oneLinerParts.push(`cd ${repoRel}`);\n if (installNeeded) {\n oneLinerParts.push(`${pm} install`);\n }\n oneLinerParts.push(setupStep, `cd ${pkgFromRoot}`, devStep);\n\n console.log(chalk.bold(\"Copy-paste (from your current directory):\"));\n console.log();\n console.log(chalk.cyan(` ${oneLinerParts.join(\" && \")}`));\n console.log();\n console.log(chalk.bold(\"Or step by step:\"));\n console.log();\n\n let step = 1;\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(chalk.dim(` ${step++}.`), setupStep);\n console.log(chalk.dim(` ${step++}.`), `cd ${pkgFromRoot}`);\n console.log(chalk.dim(` ${step++}.`), devStep);\n}\n\nasync function warnIfMissingRootNpmrc(rootDir: string): Promise<void> {\n const rootNpmrc = path.join(rootDir, \".npmrc\");\n let contents = \"\";\n if (await fs.pathExists(rootNpmrc)) {\n contents = await fs.readFile(rootNpmrc, \"utf8\");\n }\n if (contents.includes(\"@percepta:registry\")) {\n return;\n }\n\n console.log();\n console.log(\n chalk.yellow(\"!\"),\n chalk.bold(\"Root .npmrc is missing @percepta registry config.\"),\n );\n console.log(\n chalk.dim(\n \" pnpm reads .npmrc from the workspace root, so add these lines to\",\n ),\n );\n console.log(chalk.dim(` ${path.join(rootDir, \".npmrc\")}:`));\n console.log();\n console.log(chalk.cyan(\" @percepta:registry=https://registry.npmjs.org/\"));\n console.log(chalk.cyan(\" //registry.npmjs.org/:_authToken=${NPM_TOKEN}\"));\n console.log();\n}\n\nfunction printNextStepsNew(\n answers: ProjectAnswers,\n targetDir: string,\n installNeeded: boolean,\n): void {\n const pm = PACKAGE_MANAGER;\n const relativePath = path.relative(process.cwd(), targetDir) || \".\";\n\n console.log(\"Next steps:\");\n console.log();\n\n switch (answers.projectType) {\n case \"monorepo\": {\n let step = 1;\n const repoRel = shPath(relativePath);\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(\n chalk.dim(` ${step++}.`),\n `Add a package: ${chalk.cyan(`pnpm mosaic add webapp <name>`)}`,\n );\n break;\n }\n\n case \"webapp\":\n printWebappNextSteps({\n pm,\n answers,\n variant: \"new\",\n installNeeded,\n monorepoRelativePath: relativePath,\n });\n break;\n\n case \"library\": {\n let step = 1;\n const repoRel = shPath(relativePath);\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n if (installNeeded) {\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n }\n console.log(chalk.dim(` ${step++}.`), `cd packages/${answers.name}`);\n console.log(chalk.dim(` ${step++}.`), `${pm} dev`);\n console.log(\n chalk.dim(` ${step++}.`),\n `Edit src/index.ts to add your library code`,\n );\n break;\n }\n }\n\n console.log();\n console.log(\n chalk.dim(\"For more information, see the README.md in your project.\"),\n );\n console.log();\n}\n\nfunction printNextStepsExisting(\n answers: ProjectAnswers,\n packageDir: string,\n installNeeded: boolean,\n): void {\n const pm = PACKAGE_MANAGER;\n const packageRelativePath = path.relative(process.cwd(), packageDir) || \".\";\n const monorepoRoot = path.dirname(path.dirname(packageDir));\n const monorepoRelativePath =\n path.relative(process.cwd(), monorepoRoot) || \".\";\n const packageRelativePathFromRoot =\n path.relative(monorepoRoot, packageDir) || \".\";\n\n console.log(\"Next steps:\");\n console.log();\n\n switch (answers.projectType) {\n case \"webapp\":\n printWebappNextSteps({\n pm,\n answers,\n variant: \"existing\",\n installNeeded,\n monorepoRelativePath,\n packageRelativePathFromRoot,\n });\n break;\n\n case \"library\": {\n let step = 1;\n if (installNeeded) {\n const repoRel = shPath(monorepoRelativePath);\n if (repoRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${repoRel}`);\n }\n console.log(chalk.dim(` ${step++}.`), `${pm} install`);\n console.log(\n chalk.dim(` ${step++}.`),\n `cd ${shPath(packageRelativePathFromRoot)}`,\n );\n } else {\n const pkgRel = shPath(packageRelativePath);\n if (pkgRel !== \".\") {\n console.log(chalk.dim(` ${step++}.`), `cd ${pkgRel}`);\n }\n }\n console.log(chalk.dim(` ${step++}.`), `${pm} dev`);\n console.log(\n chalk.dim(` ${step++}.`),\n \"Edit src/index.ts to add your library code\",\n );\n break;\n }\n }\n\n console.log();\n console.log(\n chalk.dim(\"For more information, see the README.md in your project.\"),\n );\n console.log();\n}\n","#!/usr/bin/env node\n\nimport { program } from \"commander\";\nimport { createProject } from \"./commands/create.js\";\nimport { readCreatePackageMetadata } from \"./utils/package-metadata.js\";\n\nconst packageJson = readCreatePackageMetadata();\n\nprogram\n .name(\"create\")\n .description(\"Scaffold and manage Mosaic packages\")\n .version(packageJson.version);\n\n// Default command. Intentionally bare-bones: the canonical incantation is\n// just `npx @percepta/create` with no flags — everything else comes from\n// prompts. The flags below exist for test-template.sh and other automation,\n// not for end-user use.\nprogram\n .command(\"create\", { isDefault: true })\n .description(\"Scaffold a new Mosaic package\")\n .option(\"-t, --type <type>\", \"Package type: monorepo, webapp, or library\")\n .option(\"--name <name>\", \"Package/app name\")\n .option(\"--customer <slug>\", \"Customer slug for the new monorepo\")\n .option(\"--theme <theme>\", \"Webapp design theme: modern, paper, or dense\")\n .option(\"--repo-name <name>\", \"Repository name when creating a new monorepo\")\n .option(\"--cwd <dir>\", \"Run create as if started from this directory\")\n .option(\n \"--skip-install\",\n \"Skip dependency installation (also skips the auto-run setup + dev + browser)\",\n false,\n )\n .option(\"-y, --yes\", \"Skip all prompts and use defaults\", false)\n .action(createProject);\n\nprogram\n .command(\"add\")\n .description(\"Add a Mosaic package to the current monorepo\")\n .argument(\"[typeOrName]\", \"Package type (webapp/library) or package name\")\n .argument(\"[name]\", \"Package/app name\")\n .option(\"-t, --type <type>\", \"Package type: webapp or library\")\n .option(\"--name <name>\", \"Package/app name\")\n .option(\"--theme <theme>\", \"Webapp design theme: modern, paper, or dense\")\n .option(\n \"--skip-install\",\n \"Skip dependency installation (also skips the auto-run setup + dev + browser)\",\n false,\n )\n .option(\"-y, --yes\", \"Skip all prompts and use defaults\", false)\n .action(async (typeOrName, name, options) => {\n let projectType = options.type;\n let projectName = options.name;\n\n if (typeOrName === \"webapp\" || typeOrName === \"library\") {\n projectType = projectType ?? typeOrName;\n projectName = projectName ?? name;\n } else if (typeOrName === \"monorepo\") {\n program.error(\"error: 'add' only supports webapp or library packages\");\n } else if (typeOrName) {\n if (name) {\n program.error(\n `error: unknown package type \"${typeOrName}\". Expected webapp or library.`,\n );\n }\n projectName = projectName ?? typeOrName;\n }\n\n await createProject({\n ...options,\n type: projectType,\n name: projectName,\n addOnly: true,\n });\n });\n\nconst infra = program.command(\"infra\").description(\"Manage Mosaic infra glue\");\n\ninfra\n .command(\"register-os-blueprint\")\n .description(\"Register this customer monorepo's OS blueprint in infra\")\n .action(async () => {\n const { registerOsBlueprintCommand } =\n await import(\"./commands/infra/register-os-blueprint.js\");\n await registerOsBlueprintCommand();\n });\n\ninfra\n .command(\"register-app\")\n .description(\"Register a webapp database in this customer OS blueprint\")\n .argument(\"<app>\", \"Webapp package name\")\n .action(async (appName: string) => {\n const { registerAppCommand } =\n await import(\"./commands/infra/register-app.js\");\n await registerAppCommand(appName);\n });\n\n// Lazy-loaded subcommands\nprogram\n .command(\"status\")\n .description(\"Show template sync status for current app\")\n .option(\"--mosaic-template-path <path>\", \"Path to local mosaic repo checkout\")\n .action(async (options) => {\n const { statusCommand } = await import(\"./commands/status.js\");\n await statusCommand(options);\n });\n\nprogram\n .command(\"sync\")\n .description(\"Generate downstream sync context (template → app)\")\n .option(\"--mosaic-template-path <path>\", \"Path to local mosaic repo checkout\")\n .option(\"--to <version>\", \"Target template version (default: latest)\")\n .action(async (options) => {\n const { syncCommand } = await import(\"./commands/sync.js\");\n await syncCommand(options);\n });\n\nprogram\n .command(\"upstream\")\n .description(\"Generate upstream context (app → template)\")\n .option(\"--mosaic-template-path <path>\", \"Path to local mosaic repo checkout\")\n .option(\"--files <patterns...>\", \"Specific files to propose upstream\")\n .action(async (options) => {\n const { upstreamCommand } = await import(\"./commands/upstream.js\");\n await upstreamCommand(options);\n });\n\nprogram\n .command(\"init\")\n .description(\"Add .mosaic-template.json to an existing app\")\n .option(\"-t, --type <type>\", \"Template type (e.g., webapp, library)\")\n .option(\"--template-version <version>\", \"Template version to set\")\n .action(async (options) => {\n const { initCommand } = await import(\"./commands/init.js\");\n await initCommand(options);\n });\n\nprogram.parse();\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percepta/create",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Scaffold a new Mosaic package",
5
5
  "keywords": [
6
6
  "cli",