@percepta/create 4.1.8 → 4.1.9
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/dist/index.js +80 -15
- package/dist/index.js.map +1 -1
- package/dist/{register-app-mNc1oYVK.js → register-app-B9vKTkoI.js} +87 -33
- package/dist/register-app-B9vKTkoI.js.map +1 -0
- package/package.json +1 -1
- package/templates/infra/os.blueprint.yaml.template +13 -0
- package/templates/monorepo/auth/README.md +2 -2
- package/templates/monorepo/auth/package.json +1 -1
- package/templates/monorepo/pnpm-workspace.yaml +8 -0
- package/templates/webapp/AGENTS.md +1 -1
- package/templates/webapp/README.md +2 -1
- package/templates/webapp/agent-skills/access-control.md +3 -3
- package/templates/webapp/agent-skills/database.md +2 -1
- package/templates/webapp/next.config.ts +1 -1
- package/templates/webapp/package.json.template +2 -2
- package/templates/webapp/scripts/seed.ts +3 -3
- package/templates/webapp/src/app/(settings)/settings/page.tsx +1 -1
- package/templates/webapp/src/drizzle/schema/index.ts +1 -1
- package/templates/webapp/src/lib/auth/index.ts +2 -2
- package/templates/webapp/src/startup-checks.ts +1 -1
- package/dist/register-app-mNc1oYVK.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["SKIP_DIRS","SKIP_FILES","exhaustiveCheck"],"sources":["../src/utils/case-converters.ts","../src/utils/copy-template.ts","../src/utils/design-theme.ts","../src/utils/detect-monorepo.ts","../src/utils/env-local.ts","../src/utils/manifest.ts","../src/utils/package-metadata.ts","../src/utils/validate.ts","../src/utils/prompts.ts","../src/utils/relocate-workflows.ts","../src/utils/replace-placeholders.ts","../src/utils/template-versions.ts","../src/utils/workspace-manifest.ts","../src/commands/create.ts","../src/index.ts"],"sourcesContent":["/** Lowercase, hyphenated, npm-package-name-safe form: \"My Cool App\" → \"my-cool-app\". */\nexport function toKebabCase(str: string): string {\n return str\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/** Display form derived from a kebab-case name: \"my-cool-app\" → \"My Cool App\". */\nexport function toTitleCase(str: string): string {\n return str\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\n/** Identifier form for env vars and DB names: \"my-cool-app\" → \"my_cool_app\". */\nexport function toSnakeCase(str: string): string {\n return str.replace(/-/g, \"_\");\n}\n","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 // Source tests resolve from src/utils; bundled CLI output resolves from dist.\n const candidates = [\n path.resolve(__dirname, \"../templates\", templateType),\n path.resolve(__dirname, \"../../templates\", templateType),\n ];\n return (\n candidates.find((candidate) => fs.existsSync(candidate)) ?? candidates[0]\n );\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","export const VALID_MOSAIC_DESIGN_THEMES = [\"paper\", \"modern\", \"dense\"] as const;\n\nexport type MosaicDesignTheme = (typeof VALID_MOSAIC_DESIGN_THEMES)[number];\n\nexport const DEFAULT_MOSAIC_DESIGN_THEME: MosaicDesignTheme = \"modern\";\n\nexport function isValidMosaicDesignTheme(\n value: unknown,\n): value is MosaicDesignTheme {\n return (\n typeof value === \"string\" &&\n VALID_MOSAIC_DESIGN_THEMES.includes(value as MosaicDesignTheme)\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 fs from \"fs-extra\";\nimport {\n DEFAULT_MOSAIC_DESIGN_THEME,\n type MosaicDesignTheme,\n} from \"./design-theme.js\";\n\nexport interface MosaicManifest {\n templateType: string;\n templateVersion: string;\n templateCommit: string;\n createdAt: string;\n lastSyncedAt?: string;\n placeholders: Record<string, string>;\n source: {\n templatePath: string;\n };\n}\n\nconst MANIFEST_FILENAME = \".mosaic-template.json\";\n\nexport function getManifestPath(dir: string): string {\n return path.join(dir, MANIFEST_FILENAME);\n}\n\nexport async function readManifest(dir: string): Promise<MosaicManifest> {\n const manifestPath = getManifestPath(dir);\n if (!(await fs.pathExists(manifestPath))) {\n throw new Error(\n `No ${MANIFEST_FILENAME} found in ${dir}. Run 'create init' to create one.`,\n );\n }\n const content = await fs.readFile(manifestPath, \"utf-8\");\n try {\n return JSON.parse(content) as MosaicManifest;\n } catch (error) {\n throw new Error(\n `Invalid JSON in ${MANIFEST_FILENAME}: ${(error as Error).message}`,\n );\n }\n}\n\nexport async function writeManifest(\n dir: string,\n manifest: MosaicManifest,\n): Promise<void> {\n const manifestPath = getManifestPath(dir);\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n}\n\nexport async function manifestExists(dir: string): Promise<boolean> {\n return fs.pathExists(getManifestPath(dir));\n}\n\nexport function derivePlaceholders(\n appName: string,\n appTitle: string,\n repoName = appName,\n customerSlug = repoName,\n designTheme: MosaicDesignTheme = DEFAULT_MOSAIC_DESIGN_THEME,\n): Record<string, string> {\n const nameSnake = appName.replace(/-/g, \"_\");\n const repoNameSnake = repoName.replace(/-/g, \"_\");\n return {\n __APP_NAME__: appName,\n __APP_TITLE__: appTitle,\n __DB_NAME__: nameSnake + \"_db\",\n __APP_NAME_UPPER__: appName.toUpperCase(),\n __APP_NAME_SNAKE__: nameSnake,\n __REPO_NAME__: repoName,\n __REPO_NAME_SNAKE__: repoNameSnake,\n __CUSTOMER_SLUG__: customerSlug,\n __MOSAIC_DESIGN_THEME__: designTheme,\n };\n}\n\nexport function resolveMosaicTemplatePath(options: {\n mosaicTemplatePath?: string;\n}): string {\n if (options.mosaicTemplatePath)\n return path.resolve(options.mosaicTemplatePath);\n if (process.env.MOSAIC_TEMPLATE_PATH)\n return path.resolve(process.env.MOSAIC_TEMPLATE_PATH);\n throw new Error(\n \"Mosaic repo path required. Use --mosaic-template-path or set MOSAIC_TEMPLATE_PATH.\",\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 validateNpmPackageName from \"validate-npm-package-name\";\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n}\n\nexport function validateProjectName(name: string): ValidationResult {\n const result = validateNpmPackageName(name);\n\n if (!result.validForNewPackages) {\n const errors = [...(result.errors || []), ...(result.warnings || [])];\n return {\n valid: false,\n error: errors[0] || \"Invalid package name\",\n };\n }\n\n return { valid: true };\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 customerSlug: string; // kebab-case npm scope (without the `@`): summa\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 __CUSTOMER_SLUG__: \"customerSlug\",\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 { fileURLToPath } from \"node:url\";\nimport fs from \"fs-extra\";\n\nconst FALLBACK_TEMPLATE_VERSION = \"1.0.0\";\n\nexport function readTemplateVersions(): Record<string, string> {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(currentDir, \"../template-versions.json\"),\n path.resolve(currentDir, \"../../template-versions.json\"),\n ];\n\n for (const versionsPath of candidates) {\n try {\n const content = fs.readFileSync(versionsPath, \"utf-8\");\n return JSON.parse(content);\n } catch {\n // Try the next path. Source tests and bundled CLI resolve differently.\n }\n }\n\n return {};\n}\n\nexport function getTemplateVersion(templateType: string): string {\n return readTemplateVersions()[templateType] ?? FALLBACK_TEMPLATE_VERSION;\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.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\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 customerSlug?: 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.customerSlug,\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 customerSlug = repoName,\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 customerSlug,\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 newWorkspaceCustomerSlug,\n DEFAULT_MOSAIC_DESIGN_THEME,\n );\n const configRepoName = monorepoContext.found\n ? path.basename(monorepoContext.rootDir!)\n : monorepoName;\n // Inside an existing monorepo, customerSlug comes from .mosaic-workspace.json.\n // Old workspaces without the field fall back to the repo dir name.\n const effectiveCustomerSlug = monorepoContext.found\n ? (workspaceManifest?.customerSlug ?? configRepoName)\n : newWorkspaceCustomerSlug;\n const config = buildAppConfig(\n answers.name,\n answers.title,\n configRepoName,\n effectiveCustomerSlug,\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/case-converters.ts","../src/utils/copy-template.ts","../src/utils/design-theme.ts","../src/utils/detect-monorepo.ts","../src/utils/env-local.ts","../src/utils/manifest.ts","../src/utils/package-metadata.ts","../src/utils/validate.ts","../src/utils/prompts.ts","../src/utils/relocate-workflows.ts","../src/utils/replace-placeholders.ts","../src/utils/template-versions.ts","../src/utils/workspace-manifest.ts","../src/commands/create.ts","../src/index.ts"],"sourcesContent":["/** Lowercase, hyphenated, npm-package-name-safe form: \"My Cool App\" → \"my-cool-app\". */\nexport function toKebabCase(str: string): string {\n return str\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/** Display form derived from a kebab-case name: \"my-cool-app\" → \"My Cool App\". */\nexport function toTitleCase(str: string): string {\n return str\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\n/** Identifier form for env vars and DB names: \"my-cool-app\" → \"my_cool_app\". */\nexport function toSnakeCase(str: string): string {\n return str.replace(/-/g, \"_\");\n}\n","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 // Source tests resolve from src/utils; bundled CLI output resolves from dist.\n const candidates = [\n path.resolve(__dirname, \"../templates\", templateType),\n path.resolve(__dirname, \"../../templates\", templateType),\n ];\n return (\n candidates.find((candidate) => fs.existsSync(candidate)) ?? candidates[0]\n );\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","export const VALID_MOSAIC_DESIGN_THEMES = [\"paper\", \"modern\", \"dense\"] as const;\n\nexport type MosaicDesignTheme = (typeof VALID_MOSAIC_DESIGN_THEMES)[number];\n\nexport const DEFAULT_MOSAIC_DESIGN_THEME: MosaicDesignTheme = \"modern\";\n\nexport function isValidMosaicDesignTheme(\n value: unknown,\n): value is MosaicDesignTheme {\n return (\n typeof value === \"string\" &&\n VALID_MOSAIC_DESIGN_THEMES.includes(value as MosaicDesignTheme)\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 fs from \"fs-extra\";\nimport {\n DEFAULT_MOSAIC_DESIGN_THEME,\n type MosaicDesignTheme,\n} from \"./design-theme.js\";\n\nexport interface MosaicManifest {\n templateType: string;\n templateVersion: string;\n templateCommit: string;\n createdAt: string;\n lastSyncedAt?: string;\n placeholders: Record<string, string>;\n source: {\n templatePath: string;\n };\n}\n\nconst MANIFEST_FILENAME = \".mosaic-template.json\";\n\nexport function getManifestPath(dir: string): string {\n return path.join(dir, MANIFEST_FILENAME);\n}\n\nexport async function readManifest(dir: string): Promise<MosaicManifest> {\n const manifestPath = getManifestPath(dir);\n if (!(await fs.pathExists(manifestPath))) {\n throw new Error(\n `No ${MANIFEST_FILENAME} found in ${dir}. Run 'create init' to create one.`,\n );\n }\n const content = await fs.readFile(manifestPath, \"utf-8\");\n try {\n return JSON.parse(content) as MosaicManifest;\n } catch (error) {\n throw new Error(\n `Invalid JSON in ${MANIFEST_FILENAME}: ${(error as Error).message}`,\n );\n }\n}\n\nexport async function writeManifest(\n dir: string,\n manifest: MosaicManifest,\n): Promise<void> {\n const manifestPath = getManifestPath(dir);\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + \"\\n\");\n}\n\nexport async function manifestExists(dir: string): Promise<boolean> {\n return fs.pathExists(getManifestPath(dir));\n}\n\nexport function derivePlaceholders(\n appName: string,\n appTitle: string,\n repoName = appName,\n customerSlug = repoName,\n designTheme: MosaicDesignTheme = DEFAULT_MOSAIC_DESIGN_THEME,\n): Record<string, string> {\n const nameSnake = appName.replace(/-/g, \"_\");\n const repoNameSnake = repoName.replace(/-/g, \"_\");\n return {\n __APP_NAME__: appName,\n __APP_TITLE__: appTitle,\n __DB_NAME__: nameSnake + \"_db\",\n __APP_NAME_UPPER__: appName.toUpperCase(),\n __APP_NAME_SNAKE__: nameSnake,\n __REPO_NAME__: repoName,\n __REPO_NAME_SNAKE__: repoNameSnake,\n __CUSTOMER_SLUG__: customerSlug,\n __MOSAIC_DESIGN_THEME__: designTheme,\n };\n}\n\nexport function resolveMosaicTemplatePath(options: {\n mosaicTemplatePath?: string;\n}): string {\n if (options.mosaicTemplatePath)\n return path.resolve(options.mosaicTemplatePath);\n if (process.env.MOSAIC_TEMPLATE_PATH)\n return path.resolve(process.env.MOSAIC_TEMPLATE_PATH);\n throw new Error(\n \"Mosaic repo path required. Use --mosaic-template-path or set MOSAIC_TEMPLATE_PATH.\",\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 validateNpmPackageName from \"validate-npm-package-name\";\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n}\n\nexport function validateProjectName(name: string): ValidationResult {\n const result = validateNpmPackageName(name);\n\n if (!result.validForNewPackages) {\n const errors = [...(result.errors || []), ...(result.warnings || [])];\n return {\n valid: false,\n error: errors[0] || \"Invalid package name\",\n };\n }\n\n return { valid: true };\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 customerSlug: string; // kebab-case npm scope (without the `@`): summa\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 __CUSTOMER_SLUG__: \"customerSlug\",\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 { fileURLToPath } from \"node:url\";\nimport fs from \"fs-extra\";\n\nconst FALLBACK_TEMPLATE_VERSION = \"1.0.0\";\n\nexport function readTemplateVersions(): Record<string, string> {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(currentDir, \"../template-versions.json\"),\n path.resolve(currentDir, \"../../template-versions.json\"),\n ];\n\n for (const versionsPath of candidates) {\n try {\n const content = fs.readFileSync(versionsPath, \"utf-8\");\n return JSON.parse(content);\n } catch {\n // Try the next path. Source tests and bundled CLI resolve differently.\n }\n }\n\n return {};\n}\n\nexport function getTemplateVersion(templateType: string): string {\n return readTemplateVersions()[templateType] ?? FALLBACK_TEMPLATE_VERSION;\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.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\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_PACKAGE_MANAGER_OUTPUT_CHARS = 64_000;\nconst MAX_PACKAGE_MANAGER_OUTPUT_LINES = 80;\n\nclass PackageManagerCommandError extends Error {\n public constructor(\n message: string,\n public readonly command: 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 package-manager command so ora can animate. */\nfunction runPackageManagerCommand(\n packageManager: string,\n cwd: string,\n args: string[],\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let output = \"\";\n const command = `${packageManager} ${args.join(\" \")}`;\n const appendOutput = (chunk: Buffer) => {\n output += chunk.toString();\n if (output.length > MAX_PACKAGE_MANAGER_OUTPUT_CHARS) {\n output = output.slice(-MAX_PACKAGE_MANAGER_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 `${command} failed: ${error.message}`,\n command,\n output,\n ),\n );\n });\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else\n reject(\n new PackageManagerCommandError(\n `${command} exited with code ${code ?? \"unknown\"}`,\n command,\n output,\n ),\n );\n });\n });\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 runPackageManagerCommand(packageManager, cwd, args);\n}\n\nfunction printPackageManagerFailureOutput(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_PACKAGE_MANAGER_OUTPUT_LINES);\n const visibleLines = lines.slice(-MAX_PACKAGE_MANAGER_OUTPUT_LINES);\n\n console.log();\n console.log(\n chalk.bold(`Last ${visibleLines.length} lines from ${error.command}:`),\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 customerSlug?: 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.customerSlug,\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 customerSlug = repoName,\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 customerSlug,\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 printPackageManagerFailureOutput(error);\n return false;\n }\n}\n\ntype GeneratedProjectCheckScope = \"workspace\" | \"generated-package\";\n\nasync function collectGeneratedFormatTargets(args: {\n monorepoRoot: string;\n packageDir: string;\n projectType: ProjectType;\n}): Promise<string[]> {\n const targets = [path.relative(args.monorepoRoot, args.packageDir) || \".\"];\n if (args.projectType === \"webapp\") {\n const workflowPath = path.join(\n args.monorepoRoot,\n \".github\",\n \"workflows\",\n `${path.basename(args.packageDir)}-ryvn-release.yaml`,\n );\n if (await fs.pathExists(workflowPath)) {\n targets.push(path.relative(args.monorepoRoot, workflowPath));\n }\n }\n return targets.map(shPath);\n}\n\nasync function runGeneratedProjectChecks(args: {\n monorepoRoot: string;\n packageDir: string | null;\n projectType: ProjectType;\n scope: GeneratedProjectCheckScope;\n installSucceeded: boolean;\n}): Promise<boolean> {\n if (!args.installSucceeded) return false;\n\n const formatArgs =\n args.scope === \"workspace\" || !args.packageDir\n ? [\"run\", \"format\"]\n : [\n \"exec\",\n \"oxfmt\",\n ...(await collectGeneratedFormatTargets({\n monorepoRoot: args.monorepoRoot,\n packageDir: args.packageDir,\n projectType: args.projectType,\n })),\n ];\n const lintArgs =\n args.scope === \"workspace\" || !args.packageDir\n ? [\"run\", \"lint\"]\n : [\n \"exec\",\n \"oxlint\",\n shPath(path.relative(args.monorepoRoot, args.packageDir) || \".\"),\n ];\n\n const formatSpinner = ora(\"Formatting generated files...\").start();\n try {\n await runPackageManagerCommand(\n PACKAGE_MANAGER,\n args.monorepoRoot,\n formatArgs,\n );\n formatSpinner.succeed(\"Formatted generated files\");\n } catch (error) {\n formatSpinner.warn(\"Generated formatting failed\");\n printPackageManagerFailureOutput(error);\n return false;\n }\n\n const lintSpinner = ora(\"Linting generated files...\").start();\n try {\n await runPackageManagerCommand(\n PACKAGE_MANAGER,\n args.monorepoRoot,\n lintArgs,\n );\n lintSpinner.succeed(\"Linted generated files\");\n return true;\n } catch (error) {\n lintSpinner.warn(\"Generated lint failed\");\n printPackageManagerFailureOutput(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 newWorkspaceCustomerSlug,\n DEFAULT_MOSAIC_DESIGN_THEME,\n );\n const configRepoName = monorepoContext.found\n ? path.basename(monorepoContext.rootDir!)\n : monorepoName;\n // Inside an existing monorepo, customerSlug comes from .mosaic-workspace.json.\n // Old workspaces without the field fall back to the repo dir name.\n const effectiveCustomerSlug = monorepoContext.found\n ? (workspaceManifest?.customerSlug ?? configRepoName)\n : newWorkspaceCustomerSlug;\n const config = buildAppConfig(\n answers.name,\n answers.title,\n configRepoName,\n effectiveCustomerSlug,\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 const checksSucceeded = await runGeneratedProjectChecks({\n monorepoRoot,\n packageDir,\n projectType: answers.projectType,\n scope: \"generated-package\",\n installSucceeded,\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 && checksSucceeded,\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 const checksSucceeded = await runGeneratedProjectChecks({\n monorepoRoot,\n packageDir,\n projectType: answers.projectType,\n scope: \"workspace\",\n installSucceeded,\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 && checksSucceeded,\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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"}
|