@ebay-dt/bonfire-cli 0.2.0-alpha.0 → 0.2.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/dist/branch-prepare.d.ts +6 -2
- package/dist/branch-prepare.d.ts.map +1 -1
- package/dist/branch-prepare.js +69 -11
- package/dist/branch-prepare.js.map +1 -1
- package/dist/command.d.ts +5 -1
- package/dist/command.d.ts.map +1 -1
- package/dist/command.js +62 -12
- package/dist/command.js.map +1 -1
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +2 -2
- package/dist/convert.js.map +1 -1
- package/dist/release-versions.d.ts +1 -1
- package/dist/release-versions.d.ts.map +1 -1
- package/dist/release-versions.js +1 -1
- package/dist/release-versions.js.map +1 -1
- package/package.json +4 -4
- package/templates/instance/context/PROTOTYPE.md +2 -2
- package/templates/instance/context/skills/color-scheme/SKILL.md +4 -4
- package/templates/instance/context/skills/item-data/SKILL.md +21 -21
- package/templates/instance/next.config.ts +4 -4
- package/templates/instance/src/actions/agents.ts +5 -5
- package/templates/instance/src/actions/prototypes.ts +22 -10
- package/templates/instance/src/actions/repository.ts +12 -2
- package/templates/instance/src/app/(prototypes)/layout.tsx +11 -11
- package/templates/instance/src/app/(system)/api/prototype-dirty/route.ts +3 -3
- package/templates/instance/src/app/(system)/api/repository/check/route.ts +2 -2
- package/templates/instance/src/app/(system)/api/repository/preparation/retry/route.ts +3 -0
- package/templates/instance/src/app/(system)/api/repository/retry/route.ts +2 -2
- package/templates/instance/src/app/(system)/api/repository/summary/route.ts +2 -2
- package/templates/instance/src/app/(system)/api/repository/update/route.ts +2 -2
- package/templates/instance/src/app/(system)/auth/login/route.ts +3 -3
- package/templates/instance/src/app/(system)/auth/logout/route.ts +3 -3
- package/templates/instance/src/app/(system)/auth/status/route.ts +3 -3
- package/templates/instance/src/app/(system)/layout.tsx +6 -6
- package/templates/instance/src/app/(system)/login/page.tsx +8 -8
- package/templates/instance/src/app/(system)/page.tsx +9 -9
- package/templates/instance/src/app/api/items/[itemId]/route.ts +7 -7
- package/templates/instance/src/app/api/items/route.ts +4 -4
- package/templates/instance/src/app/layout.tsx +29 -17
- package/templates/instance/src/bonfire.ts +19 -11
- package/templates/instance/src/lib/items/gateway-schemas.ts +12 -12
- package/templates/instance/src/lib/items/server.ts +52 -52
- package/templates/instance/src/proxy.ts +4 -4
package/dist/convert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC,CAAC;AAEH,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,aAAa,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAClC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC,CAAC;AAEH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,UAS1C;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AA2cD,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAsPzB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBA0DpD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,SAAgB,GAAG,cAAc,CAa1E;AAED,eAAO,MAAM,eAAe;;;;CAI3B,CAAC","sourcesContent":["import { execFile } from \"node:child_process\";\nimport {\n chmod,\n lstat,\n mkdir,\n readFile,\n readdir,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { fileURLToPath } from \"node:url\";\nimport { syncContext } from \"@ebay-dt/bonfire-context\";\nimport {\n BONFIRE_VERSION,\n PRESET_VERSION,\n} from \"./release-versions.js\";\n\nconst execFileAsync = promisify(execFile);\nconst TEMPLATE_ROOT = fileURLToPath(\n new URL(\"../templates/instance/\", import.meta.url),\n);\nconst DEFAULT_HOSTNAME = \"github.corp.ebay.com\";\nconst DEFAULT_DEPLOYMENT_ENDPOINT =\n \"https://dtsvc.vip.qa.ebay.com/dt/v1/bonfire-deploy\";\nconst DEFAULT_PORT = 1995;\n\nexport type ConvertOptions = Readonly<{\n root: string;\n appId: string;\n name: string;\n packageName?: string;\n hostname: string;\n port: number;\n deploymentEndpoint: string;\n withItemData: boolean;\n dryRun: boolean;\n skipInstall: boolean;\n}>;\n\ntype PackageJson = {\n name?: unknown;\n scripts?: Record<string, unknown>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n engines?: Record<string, string>;\n packageManager?: unknown;\n [key: string]: unknown;\n};\n\ntype PlannedChange = Readonly<{\n kind: \"add\" | \"update\" | \"remove\";\n path: string;\n reason: string;\n}>;\n\ntype ConversionPlan = Readonly<{\n root: string;\n changes: readonly PlannedChange[];\n writes: ReadonlyMap<string, string>;\n removals: readonly string[];\n packageJson: PackageJson;\n}>;\n\nexport function humanizeAppId(appId: string) {\n return appId\n .replace(/([a-z0-9])([A-Z])/gu, \"$1 $2\")\n .replace(/[._-]+/gu, \" \")\n .trim()\n .split(/\\s+/u)\n .filter(Boolean)\n .map((word) => `${word.slice(0, 1).toUpperCase()}${word.slice(1)}`)\n .join(\" \");\n}\n\nexport class ConvertError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConvertError\";\n }\n}\n\nfunction displayPath(root: string, path: string) {\n return relative(root, path) || \".\";\n}\n\nfunction parseVersion(value: unknown, label: string) {\n if (typeof value !== \"string\") {\n throw new ConvertError(`${label} must be declared in package.json`);\n }\n const match = value.match(/(\\d+)\\.(\\d+)\\.(\\d+)/u);\n if (!match) {\n throw new ConvertError(`${label} has an unsupported version: ${value}`);\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n };\n}\n\nfunction dependencyVersion(packageJson: PackageJson, name: string) {\n return (\n packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name]\n );\n}\n\nfunction validateStartingScaffold(packageJson: PackageJson) {\n const next = parseVersion(dependencyVersion(packageJson, \"next\"), \"next\");\n if (next.major !== 16 || next.minor < 2) {\n throw new ConvertError(\n `next must be 16.2 or newer within the 16.x line (found ${next.major}.${next.minor}.${next.patch})`,\n );\n }\n const react = parseVersion(dependencyVersion(packageJson, \"react\"), \"react\");\n if (react.major !== 19 || react.minor < 2) {\n throw new ConvertError(\n `react must be 19.2 or newer within the 19.x line (found ${react.major}.${react.minor}.${react.patch})`,\n );\n }\n if (!dependencyVersion(packageJson, \"typescript\")) {\n throw new ConvertError(\"typescript must be declared in package.json\");\n }\n\n if (Number(process.versions.node.split(\".\")[0]) < 24) {\n throw new ConvertError(\n \"Bonfire instance conversion requires Node.js 24 or newer\",\n );\n }\n return next;\n}\n\nasync function readJson(path: string) {\n try {\n return JSON.parse(await readFile(path, \"utf8\")) as PackageJson;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new ConvertError(\n `${displayPath(dirname(path), path)} is not valid JSON`,\n );\n }\n throw error;\n }\n}\n\nasync function exists(path: string) {\n try {\n await lstat(path);\n return true;\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return false;\n }\n throw error;\n }\n}\n\nasync function fileContent(path: string) {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction addChange(\n changes: PlannedChange[],\n root: string,\n path: string,\n kind: PlannedChange[\"kind\"],\n reason: string,\n) {\n changes.push({ kind, path: displayPath(root, path), reason });\n}\n\nasync function planFile(\n root: string,\n path: string,\n content: string,\n reason: string,\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const existing = await fileContent(path);\n if (existing === undefined) {\n writes.set(path, content);\n addChange(changes, root, path, \"add\", reason);\n return;\n }\n if (existing === content) return;\n throw new ConvertError(\n `${displayPath(root, path)} already exists and differs from the Bonfire scaffold; resolve it before converting`,\n );\n}\n\nfunction looksLikeNextStarter(path: string, content: string) {\n if (path.endsWith(\"/page.tsx\")) {\n return /Create Next App|[Gg]et started|Looking for a starting point|create-next-app/u.test(\n content,\n );\n }\n if (path.endsWith(\"/layout.tsx\")) {\n return /next\\/font|Geist|Create Next App/u.test(content);\n }\n if (path.endsWith(\"/page.module.css\")) {\n return /\\.page|\\.main|\\.footer|\\.grid/u.test(content);\n }\n if (path.endsWith(\"/globals.css\")) {\n return /--background|--foreground|@import [\"']tailwindcss/u.test(content);\n }\n if (path.endsWith(\"/README.md\")) {\n return /bootstrapped with[\\s\\S]*create-next-app/u.test(content);\n }\n if (path.endsWith(\"/next.config.ts\")) {\n return /config options here/u.test(content);\n }\n return false;\n}\n\nfunction looksLikeStarterAsset(path: string, content: string) {\n const name = path.slice(path.lastIndexOf(\"/\") + 1);\n if (\n ![\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].includes(\n name,\n )\n ) {\n return false;\n }\n return /<svg[\\s\\S]*viewBox=/u.test(content);\n}\n\nasync function planRemoveStarter(\n root: string,\n path: string,\n reason: string,\n removals: string[],\n changes: PlannedChange[],\n) {\n const content = await fileContent(path);\n if (content === undefined) return;\n if (\n content.includes(\"@ebay-dt/bonfire-next\") ||\n content.includes(\"A Bonfire instance for creating\") ||\n content.includes(\"outputFileTracingIncludes\")\n ) {\n return;\n }\n if (\n !looksLikeNextStarter(path, content) &&\n !looksLikeStarterAsset(path, content)\n ) {\n throw new ConvertError(\n `${displayPath(root, path)} is customized; it will not be removed automatically`,\n );\n }\n removals.push(path);\n addChange(changes, root, path, \"remove\", reason);\n}\n\nfunction replaceIdentity(content: string, options: ConvertOptions) {\n return content\n .replaceAll(\"design-sandbox-next\", () => options.appId)\n .replaceAll(\"Design Sandbox\", () => options.name)\n .replaceAll(\"github.corp.ebay.com\", () => options.hostname)\n .replaceAll(DEFAULT_DEPLOYMENT_ENDPOINT, () => options.deploymentEndpoint);\n}\n\nfunction withoutItemGuidance(content: string) {\n const start = content.indexOf(\"### Data fetching\");\n const end = content.indexOf(\"### Viewport sizing\");\n if (start < 0 || end < 0 || end <= start) return content;\n return `${content.slice(0, start)}${content.slice(end)}`;\n}\n\nasync function templateFiles(options: ConvertOptions) {\n const files: Array<{ relativePath: string; content: string }> = [];\n async function visit(directory: string) {\n const entries = await readdir(directory, { withFileTypes: true });\n for (const entry of entries.sort((left, right) =>\n left.name.localeCompare(right.name),\n )) {\n const path = join(directory, entry.name);\n const relativePath = relative(TEMPLATE_ROOT, path);\n if (\n !options.withItemData &&\n (relativePath.startsWith(\"src/app/api/items/\") ||\n relativePath.startsWith(\"src/lib/items/\") ||\n relativePath === \"context/skills/item-data/SKILL.md\")\n ) {\n continue;\n }\n if (entry.isDirectory()) {\n await visit(path);\n } else if (entry.isFile()) {\n let content = await readFile(path, \"utf8\");\n content = replaceIdentity(content, options);\n if (!options.withItemData && relativePath === \"context/PROTOTYPE.md\") {\n content = withoutItemGuidance(content);\n }\n files.push({ relativePath, content });\n }\n }\n }\n await visit(TEMPLATE_ROOT);\n return files;\n}\n\nfunction starterReadme(options: ConvertOptions) {\n return `# ${options.name}\\n\\nA Bonfire instance for creating, editing, and sharing prototypes.\\n\\n## Development\\n\\nUse Node.js 24+, install dependencies with pnpm, then run:\\n\\n~~~sh\\npnpm dev\\n~~~\\n\\nThe development command prepares the Bonfire session secret and the local identity branch before starting Next.js on port ${options.port}.\\n\\nRun pnpm context:install once on a machine where agent tooling is desired.\\n`;\n}\n\nfunction addDependency(\n packageJson: PackageJson,\n section: \"dependencies\" | \"devDependencies\",\n name: string,\n version: string,\n) {\n const target = (packageJson[section] ??= {});\n const existing = target[name];\n if (existing !== undefined) {\n if (existing !== version && name.startsWith(\"@ebay-dt/bonfire-\")) {\n throw new ConvertError(\n `${name} is already declared as ${existing}; expected ${version}. Update it explicitly before converting`,\n );\n }\n return;\n }\n target[name] = version;\n}\n\nfunction addScript(\n packageJson: PackageJson,\n name: string,\n value: string,\n allowedExisting: readonly string[] = [],\n) {\n const scripts = (packageJson.scripts ??= {});\n const existing = scripts[name];\n if (existing !== undefined) {\n if (existing !== value && !allowedExisting.includes(String(existing))) {\n throw new ConvertError(\n `package.json script ${name} is customized (${String(existing)}); resolve it before converting`,\n );\n }\n scripts[name] = value;\n return;\n }\n scripts[name] = value;\n}\n\nfunction mergeLines(existing: string | undefined, required: readonly string[]) {\n let result = existing ?? \"\";\n for (const line of required) {\n if (result.split(/\\r?\\n/u).some((entry) => entry.trim() === line)) continue;\n if (result.length > 0 && !result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n return result;\n}\n\nfunction mergeWorkspace(existing: string | undefined) {\n let result = existing ?? \"\";\n if (!/^minimumReleaseAge:/mu.test(result)) {\n result = `# Bonfire publishes lockstep alpha packages that must be installable immediately.\\nminimumReleaseAge: 0\\n${result}`;\n } else if (!/^minimumReleaseAge:\\s*0\\s*$/mu.test(result)) {\n throw new ConvertError(\n \"pnpm-workspace.yaml has a conflicting minimumReleaseAge\",\n );\n }\n const required = [\n \" esbuild: true\",\n \" sharp: true\",\n \" unrs-resolver: true\",\n ];\n for (const line of required) {\n const key = line.trim().split(\":\")[0] ?? \"\";\n const match = result.match(new RegExp(`^\\\\s+${key}:\\\\s*(\\\\S+)\\\\s*$`, \"mu\"));\n if (match && match[1] !== \"true\") {\n // create-next-app currently writes these two false entries. They are\n // starter policy, not an instance decision, so normalize them to the\n // Bonfire installation policy.\n if (match[1] !== \"false\" || ![\"sharp\", \"unrs-resolver\"].includes(key)) {\n throw new ConvertError(\n `pnpm-workspace.yaml has a conflicting allowBuilds.${key} setting`,\n );\n }\n result = result.replace(\n new RegExp(`(^\\\\s+${key}:\\\\s*)false(\\\\s*$)`, \"mu\"),\n \"$1true$2\",\n );\n }\n if (!match) {\n if (!result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n }\n return result;\n}\n\nasync function planPackageJson(\n root: string,\n options: ConvertOptions,\n packageJson: PackageJson,\n nextVersion: { major: number; minor: number; patch: number },\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const packageName =\n options.packageName ??\n (typeof packageJson.name === \"string\" ? packageJson.name : options.appId);\n if (!/^[a-z0-9][a-z0-9._-]*$/u.test(packageName)) {\n throw new ConvertError(`package name is invalid: ${packageName}`);\n }\n packageJson.name = packageName;\n const engines = (packageJson.engines ??= {});\n if (\n engines.node !== undefined &&\n !/^(?:\\^|~|>=)?\\s*2[4-9]|[3-9]\\d/u.test(engines.node)\n ) {\n throw new ConvertError(\n \"package.json engines.node must allow Node.js 24 or newer\",\n );\n }\n engines.node = \">=24\";\n packageJson.packageManager ??= \"pnpm@11.25.0\";\n\n const dev = `bonfire prepare --root . && bonfire branch prepare --root . --hostname ${options.hostname} && next dev -p ${options.port}`;\n addScript(packageJson, \"dev\", dev, [\"next dev\"]);\n addScript(packageJson, \"context:sync\", \"bonfire context sync\");\n addScript(\n packageJson,\n \"context:install\",\n `bonfire context install --app-id ${options.appId}`,\n );\n addScript(\n packageJson,\n \"check\",\n \"tsc --noEmit --project tsconfig.check.json && pnpm context:sync --check\",\n );\n addScript(packageJson, \"format\", \"prettier --write .\");\n addScript(packageJson, \"build\", \"next build\", [\"next build\"]);\n addScript(packageJson, \"start\", \"next start\", [\"next start\"]);\n addScript(packageJson, \"lint\", \"eslint\", [\"eslint\", \"eslint .\"]);\n\n const nextExact = `${nextVersion.major}.${nextVersion.minor}.${nextVersion.patch}`;\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-context\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-core\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-next\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-preset-ebay\",\n PRESET_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-react\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"dependencies\", \"@ebay/ui-core-react\", \"9.13.0\");\n addDependency(packageJson, \"dependencies\", \"@evo-web/react\", \"0.4.4\");\n addDependency(\n packageJson,\n \"dependencies\",\n \"react-dom\",\n dependencyVersion(packageJson, \"react-dom\") ?? \"19.2.8\",\n );\n addDependency(packageJson, \"dependencies\", \"server-only\", \"^0.0.1\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"@ebay-dt/bonfire-cli\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"devDependencies\", \"@types/node\", \"^20\");\n addDependency(packageJson, \"devDependencies\", \"@types/react\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"@types/react-dom\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"eslint\", \"^9\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"eslint-config-next\",\n nextExact,\n );\n addDependency(packageJson, \"devDependencies\", \"prettier\", \"^3.9.5\");\n if (options.withItemData) {\n addDependency(\n packageJson,\n \"dependencies\",\n \"@tanstack/react-query\",\n \"^5.104.0\",\n );\n addDependency(packageJson, \"dependencies\", \"zod\", \"^4.4.3\");\n }\n\n const path = join(root, \"package.json\");\n const content = `${JSON.stringify(packageJson, null, 2)}\\n`;\n const existing = await readFile(path, \"utf8\");\n if (JSON.stringify(JSON.parse(existing)) !== JSON.stringify(packageJson)) {\n writes.set(path, content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"merge Bonfire scripts and dependencies\",\n );\n }\n}\n\nexport async function planConversion(\n options: ConvertOptions,\n): Promise<ConversionPlan> {\n const root = resolve(options.root);\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(options.appId)) {\n throw new ConvertError(\n \"app id must contain only letters, numbers, dots, underscores, and hyphens\",\n );\n }\n if (!options.name.trim())\n throw new ConvertError(\"display name must not be empty\");\n const packagePath = join(root, \"package.json\");\n const packageJson = await readJson(packagePath);\n const nextVersion = validateStartingScaffold(packageJson);\n if (!(await exists(join(root, \"src\", \"app\")))) {\n throw new ConvertError(\n \"the starting scaffold must use the src/app App Router\",\n );\n }\n\n const writes = new Map<string, string>();\n const changes: PlannedChange[] = [];\n const removals: string[] = [];\n\n const starterPaths = [\n join(root, \"src/app/layout.tsx\"),\n join(root, \"src/app/page.tsx\"),\n join(root, \"src/app/page.module.css\"),\n join(root, \"src/app/globals.css\"),\n join(root, \"next.config.ts\"),\n join(root, \"README.md\"),\n ...[\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].map(\n (name) => join(root, \"public\", name),\n ),\n ];\n for (const path of starterPaths) {\n await planRemoveStarter(\n root,\n path,\n \"remove unmodified create-next-app content\",\n removals,\n changes,\n );\n }\n const nextBuildDirectory = join(root, \".next\");\n if (await exists(nextBuildDirectory)) {\n removals.push(nextBuildDirectory);\n addChange(\n changes,\n root,\n nextBuildDirectory,\n \"remove\",\n \"clear generated Next.js output\",\n );\n }\n\n const resolvedOptions = { ...options, root };\n const templates = await templateFiles(resolvedOptions);\n for (const file of templates) {\n const path = join(root, file.relativePath);\n if (removals.includes(path)) {\n writes.set(path, file.content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"replace unmodified create-next-app content\",\n );\n continue;\n }\n await planFile(\n root,\n path,\n file.content,\n \"add Bonfire instance scaffold\",\n writes,\n changes,\n );\n }\n\n await planPackageJson(\n root,\n options,\n packageJson,\n nextVersion,\n writes,\n changes,\n );\n\n const tsconfigPath = join(root, \"tsconfig.json\");\n const existingTsconfig = await readFile(tsconfigPath, \"utf8\");\n const tsconfig = await readJson(tsconfigPath);\n const compilerOptions = (tsconfig.compilerOptions ?? {}) as Record<\n string,\n unknown\n >;\n tsconfig.compilerOptions = compilerOptions;\n const paths = compilerOptions[\"paths\"] as Record<string, unknown> | undefined;\n if (paths && JSON.stringify(paths[\"@/*\"]) !== JSON.stringify([\"./src/*\"])) {\n throw new ConvertError(\"tsconfig.json has a conflicting @/* path alias\");\n }\n compilerOptions[\"paths\"] = { ...(paths ?? {}), \"@/*\": [\"./src/*\"] };\n const nextTsconfig = `${JSON.stringify(tsconfig, null, 2)}\\n`;\n if (\n JSON.stringify(JSON.parse(existingTsconfig)) !== JSON.stringify(tsconfig)\n ) {\n writes.set(tsconfigPath, nextTsconfig);\n addChange(\n changes,\n root,\n tsconfigPath,\n \"update\",\n \"retain the Bonfire @/* source alias\",\n );\n }\n\n await planFile(\n root,\n join(root, \"tsconfig.check.json\"),\n '{\\n \"extends\": \"./tsconfig.json\",\\n \"exclude\": [\"node_modules\", \".next\"]\\n}\\n',\n \"add the clean TypeScript check project\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierrc\"),\n '{\\n \"semi\": false,\\n \"singleQuote\": true,\\n \"trailingComma\": \"es5\",\\n \"printWidth\": 80\\n}\\n',\n \"add Bonfire formatting conventions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierignore\"),\n \"# Generated and external files\\n.next/\\nnode_modules/\\npnpm-lock.yaml\\nsrc/app/(prototypes)/**/.claude/settings.json\\n\",\n \"add formatter exclusions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".env.local.example\"),\n \"# Bonfire generates this secret during `pnpm dev`.\\n# Do NOT manually modify or remove this variable.\\nBF_SESSION_SECRET=\\n\\n# Set exactly to lowercase `true` to skip automatic identity-branch preparation.\\nBF_DISABLE_AUTO_BRANCH_SWITCH=\\n\\n# Set to `managed` or `manual` for Bonfire Git management.\\nBF_GIT_MODE=\\n\",\n \"document Bonfire environment setup\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \"public/.gitkeep\"),\n \"\",\n \"retain an explicit public directory\",\n writes,\n changes,\n );\n\n const gitignorePath = join(root, \".gitignore\");\n const gitignore = await fileContent(gitignorePath);\n const mergedGitignore = mergeLines(gitignore, [\n \"# Bonfire local secrets\",\n \".env.local\",\n ]);\n if (mergedGitignore !== (gitignore ?? \"\")) {\n writes.set(gitignorePath, mergedGitignore);\n addChange(\n changes,\n root,\n gitignorePath,\n \"update\",\n \"ignore the generated local session secret\",\n );\n }\n\n const workspacePath = join(root, \"pnpm-workspace.yaml\");\n const workspace = await fileContent(workspacePath);\n const mergedWorkspace = mergeWorkspace(workspace);\n if (mergedWorkspace !== (workspace ?? \"\")) {\n writes.set(workspacePath, mergedWorkspace);\n addChange(\n changes,\n root,\n workspacePath,\n \"update\",\n \"retain the Bonfire pnpm installation policy\",\n );\n }\n const npmrcPath = join(root, \".npmrc\");\n const npmrc = await fileContent(npmrcPath);\n if (\n npmrc &&\n /@ebay-dt:\\s*registry=/u.test(npmrc) &&\n !npmrc.includes(\"@ebay-dt:registry=https://registry.npmjs.org/\")\n ) {\n throw new ConvertError(\".npmrc has a conflicting @ebay-dt registry\");\n }\n const mergedNpmrc = mergeLines(npmrc, [\n \"@ebay-dt:registry=https://registry.npmjs.org/\",\n ]);\n if (mergedNpmrc !== (npmrc ?? \"\")) {\n writes.set(npmrcPath, mergedNpmrc);\n addChange(\n changes,\n root,\n npmrcPath,\n \"update\",\n \"resolve Bonfire packages from public npm\",\n );\n }\n const nvmrcPath = join(root, \".nvmrc\");\n const nvmrc = await fileContent(nvmrcPath);\n if (nvmrc === undefined) {\n await planFile(\n root,\n nvmrcPath,\n \"24\\n\",\n \"select Node.js 24 or newer\",\n writes,\n changes,\n );\n }\n\n const readmePath = join(root, \"README.md\");\n if (removals.includes(readmePath)) {\n writes.set(readmePath, starterReadme(options));\n addChange(\n changes,\n root,\n readmePath,\n \"update\",\n \"replace unmodified create-next-app documentation\",\n );\n } else if (\n !writes.has(readmePath) &&\n (await fileContent(readmePath)) === undefined\n ) {\n await planFile(\n root,\n readmePath,\n starterReadme(options),\n \"add instance setup documentation\",\n writes,\n changes,\n );\n }\n\n return { root, changes, writes, removals, packageJson };\n}\n\nexport async function convert(options: ConvertOptions) {\n const plan = await planConversion(options);\n for (const change of plan.changes) {\n console.log(\n `${options.dryRun ? \"Would \" : \"\"}${change.kind} ${change.path} (${change.reason})`,\n );\n }\n if (options.dryRun) return;\n\n for (const path of plan.removals) {\n await rm(path, {\n force: true,\n recursive: path === join(plan.root, \".next\"),\n });\n }\n for (const [path, content] of plan.writes) {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content);\n if (path.endsWith(\"context/hooks/block-env-reads.mjs\")) {\n await chmod(path, 0o755);\n }\n }\n\n if (!options.skipInstall) {\n console.log(\"Installing dependencies and updating pnpm-lock.yaml...\");\n await execFileAsync(\"pnpm\", [\"install\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n if (!options.skipInstall) {\n const formatPaths = [...plan.writes.keys()]\n .map((path) => displayPath(plan.root, path))\n .filter((path) => /\\.(?:json|mjs|md|ts|tsx|yaml|yml)$/u.test(path));\n if (formatPaths.length > 0) {\n await execFileAsync(\n \"pnpm\",\n [\"exec\", \"prettier\", \"--write\", ...formatPaths],\n {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n },\n );\n }\n await execFileAsync(\"pnpm\", [\"exec\", \"next\", \"typegen\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n const contextResult = await syncContext({ repositoryRoot: plan.root });\n if (contextResult.written.length > 0 || contextResult.removed.length > 0) {\n console.log(\n `Context synchronized (${contextResult.written.length} written, ${contextResult.removed.length} removed).`,\n );\n }\n console.log(\"Bonfire instance conversion complete.\");\n}\n\nexport function defaultConvertOptions(root = process.cwd()): ConvertOptions {\n const appId = \"bonfire-instance\";\n return {\n root,\n appId,\n name: \"Bonfire Instance\",\n hostname: DEFAULT_HOSTNAME,\n port: DEFAULT_PORT,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n withItemData: true,\n dryRun: false,\n skipInstall: false,\n };\n}\n\nexport const convertDefaults = {\n hostname: DEFAULT_HOSTNAME,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n port: DEFAULT_PORT,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC,CAAC;AAEH,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,aAAa,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAClC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC,CAAC;AAEH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,UAS1C;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AA2cD,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAsPzB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBA0DpD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,SAAgB,GAAG,cAAc,CAa1E;AAED,eAAO,MAAM,eAAe;;;;CAI3B,CAAC","sourcesContent":["import { execFile } from \"node:child_process\";\nimport {\n chmod,\n lstat,\n mkdir,\n readFile,\n readdir,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { fileURLToPath } from \"node:url\";\nimport { syncContext } from \"@ebay-dt/bonfire-context\";\nimport { BONFIRE_VERSION, PRESET_VERSION } from \"./release-versions.js\";\n\nconst execFileAsync = promisify(execFile);\nconst TEMPLATE_ROOT = fileURLToPath(\n new URL(\"../templates/instance/\", import.meta.url),\n);\nconst DEFAULT_HOSTNAME = \"github.corp.ebay.com\";\nconst DEFAULT_DEPLOYMENT_ENDPOINT =\n \"https://dtsvc.vip.qa.ebay.com/dt/v1/bonfire-deploy\";\nconst DEFAULT_PORT = 1995;\n\nexport type ConvertOptions = Readonly<{\n root: string;\n appId: string;\n name: string;\n packageName?: string;\n hostname: string;\n port: number;\n deploymentEndpoint: string;\n withItemData: boolean;\n dryRun: boolean;\n skipInstall: boolean;\n}>;\n\ntype PackageJson = {\n name?: unknown;\n scripts?: Record<string, unknown>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n engines?: Record<string, string>;\n packageManager?: unknown;\n [key: string]: unknown;\n};\n\ntype PlannedChange = Readonly<{\n kind: \"add\" | \"update\" | \"remove\";\n path: string;\n reason: string;\n}>;\n\ntype ConversionPlan = Readonly<{\n root: string;\n changes: readonly PlannedChange[];\n writes: ReadonlyMap<string, string>;\n removals: readonly string[];\n packageJson: PackageJson;\n}>;\n\nexport function humanizeAppId(appId: string) {\n return appId\n .replace(/([a-z0-9])([A-Z])/gu, \"$1 $2\")\n .replace(/[._-]+/gu, \" \")\n .trim()\n .split(/\\s+/u)\n .filter(Boolean)\n .map((word) => `${word.slice(0, 1).toUpperCase()}${word.slice(1)}`)\n .join(\" \");\n}\n\nexport class ConvertError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConvertError\";\n }\n}\n\nfunction displayPath(root: string, path: string) {\n return relative(root, path) || \".\";\n}\n\nfunction parseVersion(value: unknown, label: string) {\n if (typeof value !== \"string\") {\n throw new ConvertError(`${label} must be declared in package.json`);\n }\n const match = value.match(/(\\d+)\\.(\\d+)\\.(\\d+)/u);\n if (!match) {\n throw new ConvertError(`${label} has an unsupported version: ${value}`);\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n };\n}\n\nfunction dependencyVersion(packageJson: PackageJson, name: string) {\n return (\n packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name]\n );\n}\n\nfunction validateStartingScaffold(packageJson: PackageJson) {\n const next = parseVersion(dependencyVersion(packageJson, \"next\"), \"next\");\n if (next.major !== 16 || next.minor < 2) {\n throw new ConvertError(\n `next must be 16.2 or newer within the 16.x line (found ${next.major}.${next.minor}.${next.patch})`,\n );\n }\n const react = parseVersion(dependencyVersion(packageJson, \"react\"), \"react\");\n if (react.major !== 19 || react.minor < 2) {\n throw new ConvertError(\n `react must be 19.2 or newer within the 19.x line (found ${react.major}.${react.minor}.${react.patch})`,\n );\n }\n if (!dependencyVersion(packageJson, \"typescript\")) {\n throw new ConvertError(\"typescript must be declared in package.json\");\n }\n\n if (Number(process.versions.node.split(\".\")[0]) < 24) {\n throw new ConvertError(\n \"Bonfire instance conversion requires Node.js 24 or newer\",\n );\n }\n return next;\n}\n\nasync function readJson(path: string) {\n try {\n return JSON.parse(await readFile(path, \"utf8\")) as PackageJson;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new ConvertError(\n `${displayPath(dirname(path), path)} is not valid JSON`,\n );\n }\n throw error;\n }\n}\n\nasync function exists(path: string) {\n try {\n await lstat(path);\n return true;\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return false;\n }\n throw error;\n }\n}\n\nasync function fileContent(path: string) {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction addChange(\n changes: PlannedChange[],\n root: string,\n path: string,\n kind: PlannedChange[\"kind\"],\n reason: string,\n) {\n changes.push({ kind, path: displayPath(root, path), reason });\n}\n\nasync function planFile(\n root: string,\n path: string,\n content: string,\n reason: string,\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const existing = await fileContent(path);\n if (existing === undefined) {\n writes.set(path, content);\n addChange(changes, root, path, \"add\", reason);\n return;\n }\n if (existing === content) return;\n throw new ConvertError(\n `${displayPath(root, path)} already exists and differs from the Bonfire scaffold; resolve it before converting`,\n );\n}\n\nfunction looksLikeNextStarter(path: string, content: string) {\n if (path.endsWith(\"/page.tsx\")) {\n return /Create Next App|[Gg]et started|Looking for a starting point|create-next-app/u.test(\n content,\n );\n }\n if (path.endsWith(\"/layout.tsx\")) {\n return /next\\/font|Geist|Create Next App/u.test(content);\n }\n if (path.endsWith(\"/page.module.css\")) {\n return /\\.page|\\.main|\\.footer|\\.grid/u.test(content);\n }\n if (path.endsWith(\"/globals.css\")) {\n return /--background|--foreground|@import [\"']tailwindcss/u.test(content);\n }\n if (path.endsWith(\"/README.md\")) {\n return /bootstrapped with[\\s\\S]*create-next-app/u.test(content);\n }\n if (path.endsWith(\"/next.config.ts\")) {\n return /config options here/u.test(content);\n }\n return false;\n}\n\nfunction looksLikeStarterAsset(path: string, content: string) {\n const name = path.slice(path.lastIndexOf(\"/\") + 1);\n if (\n ![\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].includes(\n name,\n )\n ) {\n return false;\n }\n return /<svg[\\s\\S]*viewBox=/u.test(content);\n}\n\nasync function planRemoveStarter(\n root: string,\n path: string,\n reason: string,\n removals: string[],\n changes: PlannedChange[],\n) {\n const content = await fileContent(path);\n if (content === undefined) return;\n if (\n content.includes(\"@ebay-dt/bonfire-next\") ||\n content.includes(\"A Bonfire instance for creating\") ||\n content.includes(\"outputFileTracingIncludes\")\n ) {\n return;\n }\n if (\n !looksLikeNextStarter(path, content) &&\n !looksLikeStarterAsset(path, content)\n ) {\n throw new ConvertError(\n `${displayPath(root, path)} is customized; it will not be removed automatically`,\n );\n }\n removals.push(path);\n addChange(changes, root, path, \"remove\", reason);\n}\n\nfunction replaceIdentity(content: string, options: ConvertOptions) {\n return content\n .replaceAll(\"design-sandbox-next\", () => options.appId)\n .replaceAll(\"Design Sandbox\", () => options.name)\n .replaceAll(\"github.corp.ebay.com\", () => options.hostname)\n .replaceAll(DEFAULT_DEPLOYMENT_ENDPOINT, () => options.deploymentEndpoint);\n}\n\nfunction withoutItemGuidance(content: string) {\n const start = content.indexOf(\"### Data fetching\");\n const end = content.indexOf(\"### Viewport sizing\");\n if (start < 0 || end < 0 || end <= start) return content;\n return `${content.slice(0, start)}${content.slice(end)}`;\n}\n\nasync function templateFiles(options: ConvertOptions) {\n const files: Array<{ relativePath: string; content: string }> = [];\n async function visit(directory: string) {\n const entries = await readdir(directory, { withFileTypes: true });\n for (const entry of entries.sort((left, right) =>\n left.name.localeCompare(right.name),\n )) {\n const path = join(directory, entry.name);\n const relativePath = relative(TEMPLATE_ROOT, path);\n if (\n !options.withItemData &&\n (relativePath.startsWith(\"src/app/api/items/\") ||\n relativePath.startsWith(\"src/lib/items/\") ||\n relativePath === \"context/skills/item-data/SKILL.md\")\n ) {\n continue;\n }\n if (entry.isDirectory()) {\n await visit(path);\n } else if (entry.isFile()) {\n let content = await readFile(path, \"utf8\");\n content = replaceIdentity(content, options);\n if (!options.withItemData && relativePath === \"context/PROTOTYPE.md\") {\n content = withoutItemGuidance(content);\n }\n files.push({ relativePath, content });\n }\n }\n }\n await visit(TEMPLATE_ROOT);\n return files;\n}\n\nfunction starterReadme(options: ConvertOptions) {\n return `# ${options.name}\\n\\nA Bonfire instance for creating, editing, and sharing prototypes.\\n\\n## Development\\n\\nUse Node.js 24+, install dependencies with pnpm, then run:\\n\\n~~~sh\\npnpm dev\\n~~~\\n\\nThe development command prepares the Bonfire session secret and the local identity branch before starting Next.js on port ${options.port}.\\n\\nRun pnpm context:install once on a machine where agent tooling is desired.\\n`;\n}\n\nfunction addDependency(\n packageJson: PackageJson,\n section: \"dependencies\" | \"devDependencies\",\n name: string,\n version: string,\n) {\n const target = (packageJson[section] ??= {});\n const existing = target[name];\n if (existing !== undefined) {\n if (existing !== version && name.startsWith(\"@ebay-dt/bonfire-\")) {\n throw new ConvertError(\n `${name} is already declared as ${existing}; expected ${version}. Update it explicitly before converting`,\n );\n }\n return;\n }\n target[name] = version;\n}\n\nfunction addScript(\n packageJson: PackageJson,\n name: string,\n value: string,\n allowedExisting: readonly string[] = [],\n) {\n const scripts = (packageJson.scripts ??= {});\n const existing = scripts[name];\n if (existing !== undefined) {\n if (existing !== value && !allowedExisting.includes(String(existing))) {\n throw new ConvertError(\n `package.json script ${name} is customized (${String(existing)}); resolve it before converting`,\n );\n }\n scripts[name] = value;\n return;\n }\n scripts[name] = value;\n}\n\nfunction mergeLines(existing: string | undefined, required: readonly string[]) {\n let result = existing ?? \"\";\n for (const line of required) {\n if (result.split(/\\r?\\n/u).some((entry) => entry.trim() === line)) continue;\n if (result.length > 0 && !result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n return result;\n}\n\nfunction mergeWorkspace(existing: string | undefined) {\n let result = existing ?? \"\";\n if (!/^minimumReleaseAge:/mu.test(result)) {\n result = `# Bonfire publishes lockstep alpha packages that must be installable immediately.\\nminimumReleaseAge: 0\\n${result}`;\n } else if (!/^minimumReleaseAge:\\s*0\\s*$/mu.test(result)) {\n throw new ConvertError(\n \"pnpm-workspace.yaml has a conflicting minimumReleaseAge\",\n );\n }\n const required = [\n \" esbuild: true\",\n \" sharp: true\",\n \" unrs-resolver: true\",\n ];\n for (const line of required) {\n const key = line.trim().split(\":\")[0] ?? \"\";\n const match = result.match(new RegExp(`^\\\\s+${key}:\\\\s*(\\\\S+)\\\\s*$`, \"mu\"));\n if (match && match[1] !== \"true\") {\n // create-next-app currently writes these two false entries. They are\n // starter policy, not an instance decision, so normalize them to the\n // Bonfire installation policy.\n if (match[1] !== \"false\" || ![\"sharp\", \"unrs-resolver\"].includes(key)) {\n throw new ConvertError(\n `pnpm-workspace.yaml has a conflicting allowBuilds.${key} setting`,\n );\n }\n result = result.replace(\n new RegExp(`(^\\\\s+${key}:\\\\s*)false(\\\\s*$)`, \"mu\"),\n \"$1true$2\",\n );\n }\n if (!match) {\n if (!result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n }\n return result;\n}\n\nasync function planPackageJson(\n root: string,\n options: ConvertOptions,\n packageJson: PackageJson,\n nextVersion: { major: number; minor: number; patch: number },\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const packageName =\n options.packageName ??\n (typeof packageJson.name === \"string\" ? packageJson.name : options.appId);\n if (!/^[a-z0-9][a-z0-9._-]*$/u.test(packageName)) {\n throw new ConvertError(`package name is invalid: ${packageName}`);\n }\n packageJson.name = packageName;\n const engines = (packageJson.engines ??= {});\n if (\n engines.node !== undefined &&\n !/^(?:\\^|~|>=)?\\s*2[4-9]|[3-9]\\d/u.test(engines.node)\n ) {\n throw new ConvertError(\n \"package.json engines.node must allow Node.js 24 or newer\",\n );\n }\n engines.node = \">=24\";\n packageJson.packageManager ??= \"pnpm@11.25.0\";\n\n const dev = `bonfire prepare --root . && bonfire branch prepare --root . --default-hostname \"${options.hostname}\" && next dev -p ${options.port}`;\n addScript(packageJson, \"dev\", dev, [\"next dev\"]);\n addScript(packageJson, \"context:sync\", \"bonfire context sync\");\n addScript(\n packageJson,\n \"context:install\",\n `bonfire context install --app-id ${options.appId}`,\n );\n addScript(\n packageJson,\n \"check\",\n \"tsc --noEmit --project tsconfig.check.json && pnpm context:sync --check\",\n );\n addScript(packageJson, \"format\", \"prettier --write .\");\n addScript(packageJson, \"build\", \"next build\", [\"next build\"]);\n addScript(packageJson, \"start\", \"next start\", [\"next start\"]);\n addScript(packageJson, \"lint\", \"eslint\", [\"eslint\", \"eslint .\"]);\n\n const nextExact = `${nextVersion.major}.${nextVersion.minor}.${nextVersion.patch}`;\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-context\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-core\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-next\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-preset-ebay\",\n PRESET_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-react\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"dependencies\", \"@ebay/ui-core-react\", \"9.13.0\");\n addDependency(packageJson, \"dependencies\", \"@evo-web/react\", \"0.4.4\");\n addDependency(\n packageJson,\n \"dependencies\",\n \"react-dom\",\n dependencyVersion(packageJson, \"react-dom\") ?? \"19.2.8\",\n );\n addDependency(packageJson, \"dependencies\", \"server-only\", \"^0.0.1\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"@ebay-dt/bonfire-cli\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"devDependencies\", \"@types/node\", \"^20\");\n addDependency(packageJson, \"devDependencies\", \"@types/react\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"@types/react-dom\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"eslint\", \"^9\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"eslint-config-next\",\n nextExact,\n );\n addDependency(packageJson, \"devDependencies\", \"prettier\", \"^3.9.5\");\n if (options.withItemData) {\n addDependency(\n packageJson,\n \"dependencies\",\n \"@tanstack/react-query\",\n \"^5.104.0\",\n );\n addDependency(packageJson, \"dependencies\", \"zod\", \"^4.4.3\");\n }\n\n const path = join(root, \"package.json\");\n const content = `${JSON.stringify(packageJson, null, 2)}\\n`;\n const existing = await readFile(path, \"utf8\");\n if (JSON.stringify(JSON.parse(existing)) !== JSON.stringify(packageJson)) {\n writes.set(path, content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"merge Bonfire scripts and dependencies\",\n );\n }\n}\n\nexport async function planConversion(\n options: ConvertOptions,\n): Promise<ConversionPlan> {\n const root = resolve(options.root);\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(options.appId)) {\n throw new ConvertError(\n \"app id must contain only letters, numbers, dots, underscores, and hyphens\",\n );\n }\n if (!options.name.trim())\n throw new ConvertError(\"display name must not be empty\");\n const packagePath = join(root, \"package.json\");\n const packageJson = await readJson(packagePath);\n const nextVersion = validateStartingScaffold(packageJson);\n if (!(await exists(join(root, \"src\", \"app\")))) {\n throw new ConvertError(\n \"the starting scaffold must use the src/app App Router\",\n );\n }\n\n const writes = new Map<string, string>();\n const changes: PlannedChange[] = [];\n const removals: string[] = [];\n\n const starterPaths = [\n join(root, \"src/app/layout.tsx\"),\n join(root, \"src/app/page.tsx\"),\n join(root, \"src/app/page.module.css\"),\n join(root, \"src/app/globals.css\"),\n join(root, \"next.config.ts\"),\n join(root, \"README.md\"),\n ...[\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].map(\n (name) => join(root, \"public\", name),\n ),\n ];\n for (const path of starterPaths) {\n await planRemoveStarter(\n root,\n path,\n \"remove unmodified create-next-app content\",\n removals,\n changes,\n );\n }\n const nextBuildDirectory = join(root, \".next\");\n if (await exists(nextBuildDirectory)) {\n removals.push(nextBuildDirectory);\n addChange(\n changes,\n root,\n nextBuildDirectory,\n \"remove\",\n \"clear generated Next.js output\",\n );\n }\n\n const resolvedOptions = { ...options, root };\n const templates = await templateFiles(resolvedOptions);\n for (const file of templates) {\n const path = join(root, file.relativePath);\n if (removals.includes(path)) {\n writes.set(path, file.content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"replace unmodified create-next-app content\",\n );\n continue;\n }\n await planFile(\n root,\n path,\n file.content,\n \"add Bonfire instance scaffold\",\n writes,\n changes,\n );\n }\n\n await planPackageJson(\n root,\n options,\n packageJson,\n nextVersion,\n writes,\n changes,\n );\n\n const tsconfigPath = join(root, \"tsconfig.json\");\n const existingTsconfig = await readFile(tsconfigPath, \"utf8\");\n const tsconfig = await readJson(tsconfigPath);\n const compilerOptions = (tsconfig.compilerOptions ?? {}) as Record<\n string,\n unknown\n >;\n tsconfig.compilerOptions = compilerOptions;\n const paths = compilerOptions[\"paths\"] as Record<string, unknown> | undefined;\n if (paths && JSON.stringify(paths[\"@/*\"]) !== JSON.stringify([\"./src/*\"])) {\n throw new ConvertError(\"tsconfig.json has a conflicting @/* path alias\");\n }\n compilerOptions[\"paths\"] = { ...(paths ?? {}), \"@/*\": [\"./src/*\"] };\n const nextTsconfig = `${JSON.stringify(tsconfig, null, 2)}\\n`;\n if (\n JSON.stringify(JSON.parse(existingTsconfig)) !== JSON.stringify(tsconfig)\n ) {\n writes.set(tsconfigPath, nextTsconfig);\n addChange(\n changes,\n root,\n tsconfigPath,\n \"update\",\n \"retain the Bonfire @/* source alias\",\n );\n }\n\n await planFile(\n root,\n join(root, \"tsconfig.check.json\"),\n '{\\n \"extends\": \"./tsconfig.json\",\\n \"exclude\": [\"node_modules\", \".next\"]\\n}\\n',\n \"add the clean TypeScript check project\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierrc\"),\n '{\\n \"semi\": false,\\n \"singleQuote\": true,\\n \"trailingComma\": \"es5\",\\n \"printWidth\": 80\\n}\\n',\n \"add Bonfire formatting conventions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierignore\"),\n \"# Generated and external files\\n.next/\\nnode_modules/\\npnpm-lock.yaml\\nsrc/app/(prototypes)/**/.claude/settings.json\\n\",\n \"add formatter exclusions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".env.local.example\"),\n \"# Bonfire generates this secret during `pnpm dev`.\\n# Do NOT manually modify or remove this variable.\\nBF_SESSION_SECRET=\\n\\n# Set exactly to lowercase `true` to skip automatic identity-branch preparation.\\nBF_DISABLE_AUTO_BRANCH_SWITCH=\\n\\n# Set to `managed` or `manual` for Bonfire Git management.\\nBF_GIT_MODE=\\n\",\n \"document Bonfire environment setup\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \"public/.gitkeep\"),\n \"\",\n \"retain an explicit public directory\",\n writes,\n changes,\n );\n\n const gitignorePath = join(root, \".gitignore\");\n const gitignore = await fileContent(gitignorePath);\n const mergedGitignore = mergeLines(gitignore, [\n \"# Bonfire local secrets\",\n \".env.local\",\n ]);\n if (mergedGitignore !== (gitignore ?? \"\")) {\n writes.set(gitignorePath, mergedGitignore);\n addChange(\n changes,\n root,\n gitignorePath,\n \"update\",\n \"ignore the generated local session secret\",\n );\n }\n\n const workspacePath = join(root, \"pnpm-workspace.yaml\");\n const workspace = await fileContent(workspacePath);\n const mergedWorkspace = mergeWorkspace(workspace);\n if (mergedWorkspace !== (workspace ?? \"\")) {\n writes.set(workspacePath, mergedWorkspace);\n addChange(\n changes,\n root,\n workspacePath,\n \"update\",\n \"retain the Bonfire pnpm installation policy\",\n );\n }\n const npmrcPath = join(root, \".npmrc\");\n const npmrc = await fileContent(npmrcPath);\n if (\n npmrc &&\n /@ebay-dt:\\s*registry=/u.test(npmrc) &&\n !npmrc.includes(\"@ebay-dt:registry=https://registry.npmjs.org/\")\n ) {\n throw new ConvertError(\".npmrc has a conflicting @ebay-dt registry\");\n }\n const mergedNpmrc = mergeLines(npmrc, [\n \"@ebay-dt:registry=https://registry.npmjs.org/\",\n ]);\n if (mergedNpmrc !== (npmrc ?? \"\")) {\n writes.set(npmrcPath, mergedNpmrc);\n addChange(\n changes,\n root,\n npmrcPath,\n \"update\",\n \"resolve Bonfire packages from public npm\",\n );\n }\n const nvmrcPath = join(root, \".nvmrc\");\n const nvmrc = await fileContent(nvmrcPath);\n if (nvmrc === undefined) {\n await planFile(\n root,\n nvmrcPath,\n \"24\\n\",\n \"select Node.js 24 or newer\",\n writes,\n changes,\n );\n }\n\n const readmePath = join(root, \"README.md\");\n if (removals.includes(readmePath)) {\n writes.set(readmePath, starterReadme(options));\n addChange(\n changes,\n root,\n readmePath,\n \"update\",\n \"replace unmodified create-next-app documentation\",\n );\n } else if (\n !writes.has(readmePath) &&\n (await fileContent(readmePath)) === undefined\n ) {\n await planFile(\n root,\n readmePath,\n starterReadme(options),\n \"add instance setup documentation\",\n writes,\n changes,\n );\n }\n\n return { root, changes, writes, removals, packageJson };\n}\n\nexport async function convert(options: ConvertOptions) {\n const plan = await planConversion(options);\n for (const change of plan.changes) {\n console.log(\n `${options.dryRun ? \"Would \" : \"\"}${change.kind} ${change.path} (${change.reason})`,\n );\n }\n if (options.dryRun) return;\n\n for (const path of plan.removals) {\n await rm(path, {\n force: true,\n recursive: path === join(plan.root, \".next\"),\n });\n }\n for (const [path, content] of plan.writes) {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content);\n if (path.endsWith(\"context/hooks/block-env-reads.mjs\")) {\n await chmod(path, 0o755);\n }\n }\n\n if (!options.skipInstall) {\n console.log(\"Installing dependencies and updating pnpm-lock.yaml...\");\n await execFileAsync(\"pnpm\", [\"install\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n if (!options.skipInstall) {\n const formatPaths = [...plan.writes.keys()]\n .map((path) => displayPath(plan.root, path))\n .filter((path) => /\\.(?:json|mjs|md|ts|tsx|yaml|yml)$/u.test(path));\n if (formatPaths.length > 0) {\n await execFileAsync(\n \"pnpm\",\n [\"exec\", \"prettier\", \"--write\", ...formatPaths],\n {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n },\n );\n }\n await execFileAsync(\"pnpm\", [\"exec\", \"next\", \"typegen\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n const contextResult = await syncContext({ repositoryRoot: plan.root });\n if (contextResult.written.length > 0 || contextResult.removed.length > 0) {\n console.log(\n `Context synchronized (${contextResult.written.length} written, ${contextResult.removed.length} removed).`,\n );\n }\n console.log(\"Bonfire instance conversion complete.\");\n}\n\nexport function defaultConvertOptions(root = process.cwd()): ConvertOptions {\n const appId = \"bonfire-instance\";\n return {\n root,\n appId,\n name: \"Bonfire Instance\",\n hostname: DEFAULT_HOSTNAME,\n port: DEFAULT_PORT,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n withItemData: true,\n dryRun: false,\n skipInstall: false,\n };\n}\n\nexport const convertDefaults = {\n hostname: DEFAULT_HOSTNAME,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n port: DEFAULT_PORT,\n};\n"]}
|
package/dist/convert.js
CHANGED
|
@@ -4,7 +4,7 @@ import { dirname, join, relative, resolve } from "node:path";
|
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { syncContext } from "@ebay-dt/bonfire-context";
|
|
7
|
-
import { BONFIRE_VERSION, PRESET_VERSION
|
|
7
|
+
import { BONFIRE_VERSION, PRESET_VERSION } from "./release-versions.js";
|
|
8
8
|
const execFileAsync = promisify(execFile);
|
|
9
9
|
const TEMPLATE_ROOT = fileURLToPath(new URL("../templates/instance/", import.meta.url));
|
|
10
10
|
const DEFAULT_HOSTNAME = "github.corp.ebay.com";
|
|
@@ -288,7 +288,7 @@ async function planPackageJson(root, options, packageJson, nextVersion, writes,
|
|
|
288
288
|
}
|
|
289
289
|
engines.node = ">=24";
|
|
290
290
|
packageJson.packageManager ??= "pnpm@11.25.0";
|
|
291
|
-
const dev = `bonfire prepare --root . && bonfire branch prepare --root . --hostname ${options.hostname} && next dev -p ${options.port}`;
|
|
291
|
+
const dev = `bonfire prepare --root . && bonfire branch prepare --root . --default-hostname "${options.hostname}" && next dev -p ${options.port}`;
|
|
292
292
|
addScript(packageJson, "dev", dev, ["next dev"]);
|
|
293
293
|
addScript(packageJson, "context:sync", "bonfire context sync");
|
|
294
294
|
addScript(packageJson, "context:install", `bonfire context install --app-id ${options.appId}`);
|
package/dist/convert.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport {\n chmod,\n lstat,\n mkdir,\n readFile,\n readdir,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { fileURLToPath } from \"node:url\";\nimport { syncContext } from \"@ebay-dt/bonfire-context\";\nimport {\n BONFIRE_VERSION,\n PRESET_VERSION,\n} from \"./release-versions.js\";\n\nconst execFileAsync = promisify(execFile);\nconst TEMPLATE_ROOT = fileURLToPath(\n new URL(\"../templates/instance/\", import.meta.url),\n);\nconst DEFAULT_HOSTNAME = \"github.corp.ebay.com\";\nconst DEFAULT_DEPLOYMENT_ENDPOINT =\n \"https://dtsvc.vip.qa.ebay.com/dt/v1/bonfire-deploy\";\nconst DEFAULT_PORT = 1995;\n\nexport type ConvertOptions = Readonly<{\n root: string;\n appId: string;\n name: string;\n packageName?: string;\n hostname: string;\n port: number;\n deploymentEndpoint: string;\n withItemData: boolean;\n dryRun: boolean;\n skipInstall: boolean;\n}>;\n\ntype PackageJson = {\n name?: unknown;\n scripts?: Record<string, unknown>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n engines?: Record<string, string>;\n packageManager?: unknown;\n [key: string]: unknown;\n};\n\ntype PlannedChange = Readonly<{\n kind: \"add\" | \"update\" | \"remove\";\n path: string;\n reason: string;\n}>;\n\ntype ConversionPlan = Readonly<{\n root: string;\n changes: readonly PlannedChange[];\n writes: ReadonlyMap<string, string>;\n removals: readonly string[];\n packageJson: PackageJson;\n}>;\n\nexport function humanizeAppId(appId: string) {\n return appId\n .replace(/([a-z0-9])([A-Z])/gu, \"$1 $2\")\n .replace(/[._-]+/gu, \" \")\n .trim()\n .split(/\\s+/u)\n .filter(Boolean)\n .map((word) => `${word.slice(0, 1).toUpperCase()}${word.slice(1)}`)\n .join(\" \");\n}\n\nexport class ConvertError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConvertError\";\n }\n}\n\nfunction displayPath(root: string, path: string) {\n return relative(root, path) || \".\";\n}\n\nfunction parseVersion(value: unknown, label: string) {\n if (typeof value !== \"string\") {\n throw new ConvertError(`${label} must be declared in package.json`);\n }\n const match = value.match(/(\\d+)\\.(\\d+)\\.(\\d+)/u);\n if (!match) {\n throw new ConvertError(`${label} has an unsupported version: ${value}`);\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n };\n}\n\nfunction dependencyVersion(packageJson: PackageJson, name: string) {\n return (\n packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name]\n );\n}\n\nfunction validateStartingScaffold(packageJson: PackageJson) {\n const next = parseVersion(dependencyVersion(packageJson, \"next\"), \"next\");\n if (next.major !== 16 || next.minor < 2) {\n throw new ConvertError(\n `next must be 16.2 or newer within the 16.x line (found ${next.major}.${next.minor}.${next.patch})`,\n );\n }\n const react = parseVersion(dependencyVersion(packageJson, \"react\"), \"react\");\n if (react.major !== 19 || react.minor < 2) {\n throw new ConvertError(\n `react must be 19.2 or newer within the 19.x line (found ${react.major}.${react.minor}.${react.patch})`,\n );\n }\n if (!dependencyVersion(packageJson, \"typescript\")) {\n throw new ConvertError(\"typescript must be declared in package.json\");\n }\n\n if (Number(process.versions.node.split(\".\")[0]) < 24) {\n throw new ConvertError(\n \"Bonfire instance conversion requires Node.js 24 or newer\",\n );\n }\n return next;\n}\n\nasync function readJson(path: string) {\n try {\n return JSON.parse(await readFile(path, \"utf8\")) as PackageJson;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new ConvertError(\n `${displayPath(dirname(path), path)} is not valid JSON`,\n );\n }\n throw error;\n }\n}\n\nasync function exists(path: string) {\n try {\n await lstat(path);\n return true;\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return false;\n }\n throw error;\n }\n}\n\nasync function fileContent(path: string) {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction addChange(\n changes: PlannedChange[],\n root: string,\n path: string,\n kind: PlannedChange[\"kind\"],\n reason: string,\n) {\n changes.push({ kind, path: displayPath(root, path), reason });\n}\n\nasync function planFile(\n root: string,\n path: string,\n content: string,\n reason: string,\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const existing = await fileContent(path);\n if (existing === undefined) {\n writes.set(path, content);\n addChange(changes, root, path, \"add\", reason);\n return;\n }\n if (existing === content) return;\n throw new ConvertError(\n `${displayPath(root, path)} already exists and differs from the Bonfire scaffold; resolve it before converting`,\n );\n}\n\nfunction looksLikeNextStarter(path: string, content: string) {\n if (path.endsWith(\"/page.tsx\")) {\n return /Create Next App|[Gg]et started|Looking for a starting point|create-next-app/u.test(\n content,\n );\n }\n if (path.endsWith(\"/layout.tsx\")) {\n return /next\\/font|Geist|Create Next App/u.test(content);\n }\n if (path.endsWith(\"/page.module.css\")) {\n return /\\.page|\\.main|\\.footer|\\.grid/u.test(content);\n }\n if (path.endsWith(\"/globals.css\")) {\n return /--background|--foreground|@import [\"']tailwindcss/u.test(content);\n }\n if (path.endsWith(\"/README.md\")) {\n return /bootstrapped with[\\s\\S]*create-next-app/u.test(content);\n }\n if (path.endsWith(\"/next.config.ts\")) {\n return /config options here/u.test(content);\n }\n return false;\n}\n\nfunction looksLikeStarterAsset(path: string, content: string) {\n const name = path.slice(path.lastIndexOf(\"/\") + 1);\n if (\n ![\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].includes(\n name,\n )\n ) {\n return false;\n }\n return /<svg[\\s\\S]*viewBox=/u.test(content);\n}\n\nasync function planRemoveStarter(\n root: string,\n path: string,\n reason: string,\n removals: string[],\n changes: PlannedChange[],\n) {\n const content = await fileContent(path);\n if (content === undefined) return;\n if (\n content.includes(\"@ebay-dt/bonfire-next\") ||\n content.includes(\"A Bonfire instance for creating\") ||\n content.includes(\"outputFileTracingIncludes\")\n ) {\n return;\n }\n if (\n !looksLikeNextStarter(path, content) &&\n !looksLikeStarterAsset(path, content)\n ) {\n throw new ConvertError(\n `${displayPath(root, path)} is customized; it will not be removed automatically`,\n );\n }\n removals.push(path);\n addChange(changes, root, path, \"remove\", reason);\n}\n\nfunction replaceIdentity(content: string, options: ConvertOptions) {\n return content\n .replaceAll(\"design-sandbox-next\", () => options.appId)\n .replaceAll(\"Design Sandbox\", () => options.name)\n .replaceAll(\"github.corp.ebay.com\", () => options.hostname)\n .replaceAll(DEFAULT_DEPLOYMENT_ENDPOINT, () => options.deploymentEndpoint);\n}\n\nfunction withoutItemGuidance(content: string) {\n const start = content.indexOf(\"### Data fetching\");\n const end = content.indexOf(\"### Viewport sizing\");\n if (start < 0 || end < 0 || end <= start) return content;\n return `${content.slice(0, start)}${content.slice(end)}`;\n}\n\nasync function templateFiles(options: ConvertOptions) {\n const files: Array<{ relativePath: string; content: string }> = [];\n async function visit(directory: string) {\n const entries = await readdir(directory, { withFileTypes: true });\n for (const entry of entries.sort((left, right) =>\n left.name.localeCompare(right.name),\n )) {\n const path = join(directory, entry.name);\n const relativePath = relative(TEMPLATE_ROOT, path);\n if (\n !options.withItemData &&\n (relativePath.startsWith(\"src/app/api/items/\") ||\n relativePath.startsWith(\"src/lib/items/\") ||\n relativePath === \"context/skills/item-data/SKILL.md\")\n ) {\n continue;\n }\n if (entry.isDirectory()) {\n await visit(path);\n } else if (entry.isFile()) {\n let content = await readFile(path, \"utf8\");\n content = replaceIdentity(content, options);\n if (!options.withItemData && relativePath === \"context/PROTOTYPE.md\") {\n content = withoutItemGuidance(content);\n }\n files.push({ relativePath, content });\n }\n }\n }\n await visit(TEMPLATE_ROOT);\n return files;\n}\n\nfunction starterReadme(options: ConvertOptions) {\n return `# ${options.name}\\n\\nA Bonfire instance for creating, editing, and sharing prototypes.\\n\\n## Development\\n\\nUse Node.js 24+, install dependencies with pnpm, then run:\\n\\n~~~sh\\npnpm dev\\n~~~\\n\\nThe development command prepares the Bonfire session secret and the local identity branch before starting Next.js on port ${options.port}.\\n\\nRun pnpm context:install once on a machine where agent tooling is desired.\\n`;\n}\n\nfunction addDependency(\n packageJson: PackageJson,\n section: \"dependencies\" | \"devDependencies\",\n name: string,\n version: string,\n) {\n const target = (packageJson[section] ??= {});\n const existing = target[name];\n if (existing !== undefined) {\n if (existing !== version && name.startsWith(\"@ebay-dt/bonfire-\")) {\n throw new ConvertError(\n `${name} is already declared as ${existing}; expected ${version}. Update it explicitly before converting`,\n );\n }\n return;\n }\n target[name] = version;\n}\n\nfunction addScript(\n packageJson: PackageJson,\n name: string,\n value: string,\n allowedExisting: readonly string[] = [],\n) {\n const scripts = (packageJson.scripts ??= {});\n const existing = scripts[name];\n if (existing !== undefined) {\n if (existing !== value && !allowedExisting.includes(String(existing))) {\n throw new ConvertError(\n `package.json script ${name} is customized (${String(existing)}); resolve it before converting`,\n );\n }\n scripts[name] = value;\n return;\n }\n scripts[name] = value;\n}\n\nfunction mergeLines(existing: string | undefined, required: readonly string[]) {\n let result = existing ?? \"\";\n for (const line of required) {\n if (result.split(/\\r?\\n/u).some((entry) => entry.trim() === line)) continue;\n if (result.length > 0 && !result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n return result;\n}\n\nfunction mergeWorkspace(existing: string | undefined) {\n let result = existing ?? \"\";\n if (!/^minimumReleaseAge:/mu.test(result)) {\n result = `# Bonfire publishes lockstep alpha packages that must be installable immediately.\\nminimumReleaseAge: 0\\n${result}`;\n } else if (!/^minimumReleaseAge:\\s*0\\s*$/mu.test(result)) {\n throw new ConvertError(\n \"pnpm-workspace.yaml has a conflicting minimumReleaseAge\",\n );\n }\n const required = [\n \" esbuild: true\",\n \" sharp: true\",\n \" unrs-resolver: true\",\n ];\n for (const line of required) {\n const key = line.trim().split(\":\")[0] ?? \"\";\n const match = result.match(new RegExp(`^\\\\s+${key}:\\\\s*(\\\\S+)\\\\s*$`, \"mu\"));\n if (match && match[1] !== \"true\") {\n // create-next-app currently writes these two false entries. They are\n // starter policy, not an instance decision, so normalize them to the\n // Bonfire installation policy.\n if (match[1] !== \"false\" || ![\"sharp\", \"unrs-resolver\"].includes(key)) {\n throw new ConvertError(\n `pnpm-workspace.yaml has a conflicting allowBuilds.${key} setting`,\n );\n }\n result = result.replace(\n new RegExp(`(^\\\\s+${key}:\\\\s*)false(\\\\s*$)`, \"mu\"),\n \"$1true$2\",\n );\n }\n if (!match) {\n if (!result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n }\n return result;\n}\n\nasync function planPackageJson(\n root: string,\n options: ConvertOptions,\n packageJson: PackageJson,\n nextVersion: { major: number; minor: number; patch: number },\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const packageName =\n options.packageName ??\n (typeof packageJson.name === \"string\" ? packageJson.name : options.appId);\n if (!/^[a-z0-9][a-z0-9._-]*$/u.test(packageName)) {\n throw new ConvertError(`package name is invalid: ${packageName}`);\n }\n packageJson.name = packageName;\n const engines = (packageJson.engines ??= {});\n if (\n engines.node !== undefined &&\n !/^(?:\\^|~|>=)?\\s*2[4-9]|[3-9]\\d/u.test(engines.node)\n ) {\n throw new ConvertError(\n \"package.json engines.node must allow Node.js 24 or newer\",\n );\n }\n engines.node = \">=24\";\n packageJson.packageManager ??= \"pnpm@11.25.0\";\n\n const dev = `bonfire prepare --root . && bonfire branch prepare --root . --hostname ${options.hostname} && next dev -p ${options.port}`;\n addScript(packageJson, \"dev\", dev, [\"next dev\"]);\n addScript(packageJson, \"context:sync\", \"bonfire context sync\");\n addScript(\n packageJson,\n \"context:install\",\n `bonfire context install --app-id ${options.appId}`,\n );\n addScript(\n packageJson,\n \"check\",\n \"tsc --noEmit --project tsconfig.check.json && pnpm context:sync --check\",\n );\n addScript(packageJson, \"format\", \"prettier --write .\");\n addScript(packageJson, \"build\", \"next build\", [\"next build\"]);\n addScript(packageJson, \"start\", \"next start\", [\"next start\"]);\n addScript(packageJson, \"lint\", \"eslint\", [\"eslint\", \"eslint .\"]);\n\n const nextExact = `${nextVersion.major}.${nextVersion.minor}.${nextVersion.patch}`;\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-context\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-core\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-next\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-preset-ebay\",\n PRESET_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-react\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"dependencies\", \"@ebay/ui-core-react\", \"9.13.0\");\n addDependency(packageJson, \"dependencies\", \"@evo-web/react\", \"0.4.4\");\n addDependency(\n packageJson,\n \"dependencies\",\n \"react-dom\",\n dependencyVersion(packageJson, \"react-dom\") ?? \"19.2.8\",\n );\n addDependency(packageJson, \"dependencies\", \"server-only\", \"^0.0.1\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"@ebay-dt/bonfire-cli\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"devDependencies\", \"@types/node\", \"^20\");\n addDependency(packageJson, \"devDependencies\", \"@types/react\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"@types/react-dom\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"eslint\", \"^9\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"eslint-config-next\",\n nextExact,\n );\n addDependency(packageJson, \"devDependencies\", \"prettier\", \"^3.9.5\");\n if (options.withItemData) {\n addDependency(\n packageJson,\n \"dependencies\",\n \"@tanstack/react-query\",\n \"^5.104.0\",\n );\n addDependency(packageJson, \"dependencies\", \"zod\", \"^4.4.3\");\n }\n\n const path = join(root, \"package.json\");\n const content = `${JSON.stringify(packageJson, null, 2)}\\n`;\n const existing = await readFile(path, \"utf8\");\n if (JSON.stringify(JSON.parse(existing)) !== JSON.stringify(packageJson)) {\n writes.set(path, content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"merge Bonfire scripts and dependencies\",\n );\n }\n}\n\nexport async function planConversion(\n options: ConvertOptions,\n): Promise<ConversionPlan> {\n const root = resolve(options.root);\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(options.appId)) {\n throw new ConvertError(\n \"app id must contain only letters, numbers, dots, underscores, and hyphens\",\n );\n }\n if (!options.name.trim())\n throw new ConvertError(\"display name must not be empty\");\n const packagePath = join(root, \"package.json\");\n const packageJson = await readJson(packagePath);\n const nextVersion = validateStartingScaffold(packageJson);\n if (!(await exists(join(root, \"src\", \"app\")))) {\n throw new ConvertError(\n \"the starting scaffold must use the src/app App Router\",\n );\n }\n\n const writes = new Map<string, string>();\n const changes: PlannedChange[] = [];\n const removals: string[] = [];\n\n const starterPaths = [\n join(root, \"src/app/layout.tsx\"),\n join(root, \"src/app/page.tsx\"),\n join(root, \"src/app/page.module.css\"),\n join(root, \"src/app/globals.css\"),\n join(root, \"next.config.ts\"),\n join(root, \"README.md\"),\n ...[\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].map(\n (name) => join(root, \"public\", name),\n ),\n ];\n for (const path of starterPaths) {\n await planRemoveStarter(\n root,\n path,\n \"remove unmodified create-next-app content\",\n removals,\n changes,\n );\n }\n const nextBuildDirectory = join(root, \".next\");\n if (await exists(nextBuildDirectory)) {\n removals.push(nextBuildDirectory);\n addChange(\n changes,\n root,\n nextBuildDirectory,\n \"remove\",\n \"clear generated Next.js output\",\n );\n }\n\n const resolvedOptions = { ...options, root };\n const templates = await templateFiles(resolvedOptions);\n for (const file of templates) {\n const path = join(root, file.relativePath);\n if (removals.includes(path)) {\n writes.set(path, file.content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"replace unmodified create-next-app content\",\n );\n continue;\n }\n await planFile(\n root,\n path,\n file.content,\n \"add Bonfire instance scaffold\",\n writes,\n changes,\n );\n }\n\n await planPackageJson(\n root,\n options,\n packageJson,\n nextVersion,\n writes,\n changes,\n );\n\n const tsconfigPath = join(root, \"tsconfig.json\");\n const existingTsconfig = await readFile(tsconfigPath, \"utf8\");\n const tsconfig = await readJson(tsconfigPath);\n const compilerOptions = (tsconfig.compilerOptions ?? {}) as Record<\n string,\n unknown\n >;\n tsconfig.compilerOptions = compilerOptions;\n const paths = compilerOptions[\"paths\"] as Record<string, unknown> | undefined;\n if (paths && JSON.stringify(paths[\"@/*\"]) !== JSON.stringify([\"./src/*\"])) {\n throw new ConvertError(\"tsconfig.json has a conflicting @/* path alias\");\n }\n compilerOptions[\"paths\"] = { ...(paths ?? {}), \"@/*\": [\"./src/*\"] };\n const nextTsconfig = `${JSON.stringify(tsconfig, null, 2)}\\n`;\n if (\n JSON.stringify(JSON.parse(existingTsconfig)) !== JSON.stringify(tsconfig)\n ) {\n writes.set(tsconfigPath, nextTsconfig);\n addChange(\n changes,\n root,\n tsconfigPath,\n \"update\",\n \"retain the Bonfire @/* source alias\",\n );\n }\n\n await planFile(\n root,\n join(root, \"tsconfig.check.json\"),\n '{\\n \"extends\": \"./tsconfig.json\",\\n \"exclude\": [\"node_modules\", \".next\"]\\n}\\n',\n \"add the clean TypeScript check project\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierrc\"),\n '{\\n \"semi\": false,\\n \"singleQuote\": true,\\n \"trailingComma\": \"es5\",\\n \"printWidth\": 80\\n}\\n',\n \"add Bonfire formatting conventions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierignore\"),\n \"# Generated and external files\\n.next/\\nnode_modules/\\npnpm-lock.yaml\\nsrc/app/(prototypes)/**/.claude/settings.json\\n\",\n \"add formatter exclusions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".env.local.example\"),\n \"# Bonfire generates this secret during `pnpm dev`.\\n# Do NOT manually modify or remove this variable.\\nBF_SESSION_SECRET=\\n\\n# Set exactly to lowercase `true` to skip automatic identity-branch preparation.\\nBF_DISABLE_AUTO_BRANCH_SWITCH=\\n\\n# Set to `managed` or `manual` for Bonfire Git management.\\nBF_GIT_MODE=\\n\",\n \"document Bonfire environment setup\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \"public/.gitkeep\"),\n \"\",\n \"retain an explicit public directory\",\n writes,\n changes,\n );\n\n const gitignorePath = join(root, \".gitignore\");\n const gitignore = await fileContent(gitignorePath);\n const mergedGitignore = mergeLines(gitignore, [\n \"# Bonfire local secrets\",\n \".env.local\",\n ]);\n if (mergedGitignore !== (gitignore ?? \"\")) {\n writes.set(gitignorePath, mergedGitignore);\n addChange(\n changes,\n root,\n gitignorePath,\n \"update\",\n \"ignore the generated local session secret\",\n );\n }\n\n const workspacePath = join(root, \"pnpm-workspace.yaml\");\n const workspace = await fileContent(workspacePath);\n const mergedWorkspace = mergeWorkspace(workspace);\n if (mergedWorkspace !== (workspace ?? \"\")) {\n writes.set(workspacePath, mergedWorkspace);\n addChange(\n changes,\n root,\n workspacePath,\n \"update\",\n \"retain the Bonfire pnpm installation policy\",\n );\n }\n const npmrcPath = join(root, \".npmrc\");\n const npmrc = await fileContent(npmrcPath);\n if (\n npmrc &&\n /@ebay-dt:\\s*registry=/u.test(npmrc) &&\n !npmrc.includes(\"@ebay-dt:registry=https://registry.npmjs.org/\")\n ) {\n throw new ConvertError(\".npmrc has a conflicting @ebay-dt registry\");\n }\n const mergedNpmrc = mergeLines(npmrc, [\n \"@ebay-dt:registry=https://registry.npmjs.org/\",\n ]);\n if (mergedNpmrc !== (npmrc ?? \"\")) {\n writes.set(npmrcPath, mergedNpmrc);\n addChange(\n changes,\n root,\n npmrcPath,\n \"update\",\n \"resolve Bonfire packages from public npm\",\n );\n }\n const nvmrcPath = join(root, \".nvmrc\");\n const nvmrc = await fileContent(nvmrcPath);\n if (nvmrc === undefined) {\n await planFile(\n root,\n nvmrcPath,\n \"24\\n\",\n \"select Node.js 24 or newer\",\n writes,\n changes,\n );\n }\n\n const readmePath = join(root, \"README.md\");\n if (removals.includes(readmePath)) {\n writes.set(readmePath, starterReadme(options));\n addChange(\n changes,\n root,\n readmePath,\n \"update\",\n \"replace unmodified create-next-app documentation\",\n );\n } else if (\n !writes.has(readmePath) &&\n (await fileContent(readmePath)) === undefined\n ) {\n await planFile(\n root,\n readmePath,\n starterReadme(options),\n \"add instance setup documentation\",\n writes,\n changes,\n );\n }\n\n return { root, changes, writes, removals, packageJson };\n}\n\nexport async function convert(options: ConvertOptions) {\n const plan = await planConversion(options);\n for (const change of plan.changes) {\n console.log(\n `${options.dryRun ? \"Would \" : \"\"}${change.kind} ${change.path} (${change.reason})`,\n );\n }\n if (options.dryRun) return;\n\n for (const path of plan.removals) {\n await rm(path, {\n force: true,\n recursive: path === join(plan.root, \".next\"),\n });\n }\n for (const [path, content] of plan.writes) {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content);\n if (path.endsWith(\"context/hooks/block-env-reads.mjs\")) {\n await chmod(path, 0o755);\n }\n }\n\n if (!options.skipInstall) {\n console.log(\"Installing dependencies and updating pnpm-lock.yaml...\");\n await execFileAsync(\"pnpm\", [\"install\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n if (!options.skipInstall) {\n const formatPaths = [...plan.writes.keys()]\n .map((path) => displayPath(plan.root, path))\n .filter((path) => /\\.(?:json|mjs|md|ts|tsx|yaml|yml)$/u.test(path));\n if (formatPaths.length > 0) {\n await execFileAsync(\n \"pnpm\",\n [\"exec\", \"prettier\", \"--write\", ...formatPaths],\n {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n },\n );\n }\n await execFileAsync(\"pnpm\", [\"exec\", \"next\", \"typegen\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n const contextResult = await syncContext({ repositoryRoot: plan.root });\n if (contextResult.written.length > 0 || contextResult.removed.length > 0) {\n console.log(\n `Context synchronized (${contextResult.written.length} written, ${contextResult.removed.length} removed).`,\n );\n }\n console.log(\"Bonfire instance conversion complete.\");\n}\n\nexport function defaultConvertOptions(root = process.cwd()): ConvertOptions {\n const appId = \"bonfire-instance\";\n return {\n root,\n appId,\n name: \"Bonfire Instance\",\n hostname: DEFAULT_HOSTNAME,\n port: DEFAULT_PORT,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n withItemData: true,\n dryRun: false,\n skipInstall: false,\n };\n}\n\nexport const convertDefaults = {\n hostname: DEFAULT_HOSTNAME,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n port: DEFAULT_PORT,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport {\n chmod,\n lstat,\n mkdir,\n readFile,\n readdir,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { fileURLToPath } from \"node:url\";\nimport { syncContext } from \"@ebay-dt/bonfire-context\";\nimport { BONFIRE_VERSION, PRESET_VERSION } from \"./release-versions.js\";\n\nconst execFileAsync = promisify(execFile);\nconst TEMPLATE_ROOT = fileURLToPath(\n new URL(\"../templates/instance/\", import.meta.url),\n);\nconst DEFAULT_HOSTNAME = \"github.corp.ebay.com\";\nconst DEFAULT_DEPLOYMENT_ENDPOINT =\n \"https://dtsvc.vip.qa.ebay.com/dt/v1/bonfire-deploy\";\nconst DEFAULT_PORT = 1995;\n\nexport type ConvertOptions = Readonly<{\n root: string;\n appId: string;\n name: string;\n packageName?: string;\n hostname: string;\n port: number;\n deploymentEndpoint: string;\n withItemData: boolean;\n dryRun: boolean;\n skipInstall: boolean;\n}>;\n\ntype PackageJson = {\n name?: unknown;\n scripts?: Record<string, unknown>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n engines?: Record<string, string>;\n packageManager?: unknown;\n [key: string]: unknown;\n};\n\ntype PlannedChange = Readonly<{\n kind: \"add\" | \"update\" | \"remove\";\n path: string;\n reason: string;\n}>;\n\ntype ConversionPlan = Readonly<{\n root: string;\n changes: readonly PlannedChange[];\n writes: ReadonlyMap<string, string>;\n removals: readonly string[];\n packageJson: PackageJson;\n}>;\n\nexport function humanizeAppId(appId: string) {\n return appId\n .replace(/([a-z0-9])([A-Z])/gu, \"$1 $2\")\n .replace(/[._-]+/gu, \" \")\n .trim()\n .split(/\\s+/u)\n .filter(Boolean)\n .map((word) => `${word.slice(0, 1).toUpperCase()}${word.slice(1)}`)\n .join(\" \");\n}\n\nexport class ConvertError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConvertError\";\n }\n}\n\nfunction displayPath(root: string, path: string) {\n return relative(root, path) || \".\";\n}\n\nfunction parseVersion(value: unknown, label: string) {\n if (typeof value !== \"string\") {\n throw new ConvertError(`${label} must be declared in package.json`);\n }\n const match = value.match(/(\\d+)\\.(\\d+)\\.(\\d+)/u);\n if (!match) {\n throw new ConvertError(`${label} has an unsupported version: ${value}`);\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n };\n}\n\nfunction dependencyVersion(packageJson: PackageJson, name: string) {\n return (\n packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name]\n );\n}\n\nfunction validateStartingScaffold(packageJson: PackageJson) {\n const next = parseVersion(dependencyVersion(packageJson, \"next\"), \"next\");\n if (next.major !== 16 || next.minor < 2) {\n throw new ConvertError(\n `next must be 16.2 or newer within the 16.x line (found ${next.major}.${next.minor}.${next.patch})`,\n );\n }\n const react = parseVersion(dependencyVersion(packageJson, \"react\"), \"react\");\n if (react.major !== 19 || react.minor < 2) {\n throw new ConvertError(\n `react must be 19.2 or newer within the 19.x line (found ${react.major}.${react.minor}.${react.patch})`,\n );\n }\n if (!dependencyVersion(packageJson, \"typescript\")) {\n throw new ConvertError(\"typescript must be declared in package.json\");\n }\n\n if (Number(process.versions.node.split(\".\")[0]) < 24) {\n throw new ConvertError(\n \"Bonfire instance conversion requires Node.js 24 or newer\",\n );\n }\n return next;\n}\n\nasync function readJson(path: string) {\n try {\n return JSON.parse(await readFile(path, \"utf8\")) as PackageJson;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new ConvertError(\n `${displayPath(dirname(path), path)} is not valid JSON`,\n );\n }\n throw error;\n }\n}\n\nasync function exists(path: string) {\n try {\n await lstat(path);\n return true;\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return false;\n }\n throw error;\n }\n}\n\nasync function fileContent(path: string) {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction addChange(\n changes: PlannedChange[],\n root: string,\n path: string,\n kind: PlannedChange[\"kind\"],\n reason: string,\n) {\n changes.push({ kind, path: displayPath(root, path), reason });\n}\n\nasync function planFile(\n root: string,\n path: string,\n content: string,\n reason: string,\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const existing = await fileContent(path);\n if (existing === undefined) {\n writes.set(path, content);\n addChange(changes, root, path, \"add\", reason);\n return;\n }\n if (existing === content) return;\n throw new ConvertError(\n `${displayPath(root, path)} already exists and differs from the Bonfire scaffold; resolve it before converting`,\n );\n}\n\nfunction looksLikeNextStarter(path: string, content: string) {\n if (path.endsWith(\"/page.tsx\")) {\n return /Create Next App|[Gg]et started|Looking for a starting point|create-next-app/u.test(\n content,\n );\n }\n if (path.endsWith(\"/layout.tsx\")) {\n return /next\\/font|Geist|Create Next App/u.test(content);\n }\n if (path.endsWith(\"/page.module.css\")) {\n return /\\.page|\\.main|\\.footer|\\.grid/u.test(content);\n }\n if (path.endsWith(\"/globals.css\")) {\n return /--background|--foreground|@import [\"']tailwindcss/u.test(content);\n }\n if (path.endsWith(\"/README.md\")) {\n return /bootstrapped with[\\s\\S]*create-next-app/u.test(content);\n }\n if (path.endsWith(\"/next.config.ts\")) {\n return /config options here/u.test(content);\n }\n return false;\n}\n\nfunction looksLikeStarterAsset(path: string, content: string) {\n const name = path.slice(path.lastIndexOf(\"/\") + 1);\n if (\n ![\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].includes(\n name,\n )\n ) {\n return false;\n }\n return /<svg[\\s\\S]*viewBox=/u.test(content);\n}\n\nasync function planRemoveStarter(\n root: string,\n path: string,\n reason: string,\n removals: string[],\n changes: PlannedChange[],\n) {\n const content = await fileContent(path);\n if (content === undefined) return;\n if (\n content.includes(\"@ebay-dt/bonfire-next\") ||\n content.includes(\"A Bonfire instance for creating\") ||\n content.includes(\"outputFileTracingIncludes\")\n ) {\n return;\n }\n if (\n !looksLikeNextStarter(path, content) &&\n !looksLikeStarterAsset(path, content)\n ) {\n throw new ConvertError(\n `${displayPath(root, path)} is customized; it will not be removed automatically`,\n );\n }\n removals.push(path);\n addChange(changes, root, path, \"remove\", reason);\n}\n\nfunction replaceIdentity(content: string, options: ConvertOptions) {\n return content\n .replaceAll(\"design-sandbox-next\", () => options.appId)\n .replaceAll(\"Design Sandbox\", () => options.name)\n .replaceAll(\"github.corp.ebay.com\", () => options.hostname)\n .replaceAll(DEFAULT_DEPLOYMENT_ENDPOINT, () => options.deploymentEndpoint);\n}\n\nfunction withoutItemGuidance(content: string) {\n const start = content.indexOf(\"### Data fetching\");\n const end = content.indexOf(\"### Viewport sizing\");\n if (start < 0 || end < 0 || end <= start) return content;\n return `${content.slice(0, start)}${content.slice(end)}`;\n}\n\nasync function templateFiles(options: ConvertOptions) {\n const files: Array<{ relativePath: string; content: string }> = [];\n async function visit(directory: string) {\n const entries = await readdir(directory, { withFileTypes: true });\n for (const entry of entries.sort((left, right) =>\n left.name.localeCompare(right.name),\n )) {\n const path = join(directory, entry.name);\n const relativePath = relative(TEMPLATE_ROOT, path);\n if (\n !options.withItemData &&\n (relativePath.startsWith(\"src/app/api/items/\") ||\n relativePath.startsWith(\"src/lib/items/\") ||\n relativePath === \"context/skills/item-data/SKILL.md\")\n ) {\n continue;\n }\n if (entry.isDirectory()) {\n await visit(path);\n } else if (entry.isFile()) {\n let content = await readFile(path, \"utf8\");\n content = replaceIdentity(content, options);\n if (!options.withItemData && relativePath === \"context/PROTOTYPE.md\") {\n content = withoutItemGuidance(content);\n }\n files.push({ relativePath, content });\n }\n }\n }\n await visit(TEMPLATE_ROOT);\n return files;\n}\n\nfunction starterReadme(options: ConvertOptions) {\n return `# ${options.name}\\n\\nA Bonfire instance for creating, editing, and sharing prototypes.\\n\\n## Development\\n\\nUse Node.js 24+, install dependencies with pnpm, then run:\\n\\n~~~sh\\npnpm dev\\n~~~\\n\\nThe development command prepares the Bonfire session secret and the local identity branch before starting Next.js on port ${options.port}.\\n\\nRun pnpm context:install once on a machine where agent tooling is desired.\\n`;\n}\n\nfunction addDependency(\n packageJson: PackageJson,\n section: \"dependencies\" | \"devDependencies\",\n name: string,\n version: string,\n) {\n const target = (packageJson[section] ??= {});\n const existing = target[name];\n if (existing !== undefined) {\n if (existing !== version && name.startsWith(\"@ebay-dt/bonfire-\")) {\n throw new ConvertError(\n `${name} is already declared as ${existing}; expected ${version}. Update it explicitly before converting`,\n );\n }\n return;\n }\n target[name] = version;\n}\n\nfunction addScript(\n packageJson: PackageJson,\n name: string,\n value: string,\n allowedExisting: readonly string[] = [],\n) {\n const scripts = (packageJson.scripts ??= {});\n const existing = scripts[name];\n if (existing !== undefined) {\n if (existing !== value && !allowedExisting.includes(String(existing))) {\n throw new ConvertError(\n `package.json script ${name} is customized (${String(existing)}); resolve it before converting`,\n );\n }\n scripts[name] = value;\n return;\n }\n scripts[name] = value;\n}\n\nfunction mergeLines(existing: string | undefined, required: readonly string[]) {\n let result = existing ?? \"\";\n for (const line of required) {\n if (result.split(/\\r?\\n/u).some((entry) => entry.trim() === line)) continue;\n if (result.length > 0 && !result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n return result;\n}\n\nfunction mergeWorkspace(existing: string | undefined) {\n let result = existing ?? \"\";\n if (!/^minimumReleaseAge:/mu.test(result)) {\n result = `# Bonfire publishes lockstep alpha packages that must be installable immediately.\\nminimumReleaseAge: 0\\n${result}`;\n } else if (!/^minimumReleaseAge:\\s*0\\s*$/mu.test(result)) {\n throw new ConvertError(\n \"pnpm-workspace.yaml has a conflicting minimumReleaseAge\",\n );\n }\n const required = [\n \" esbuild: true\",\n \" sharp: true\",\n \" unrs-resolver: true\",\n ];\n for (const line of required) {\n const key = line.trim().split(\":\")[0] ?? \"\";\n const match = result.match(new RegExp(`^\\\\s+${key}:\\\\s*(\\\\S+)\\\\s*$`, \"mu\"));\n if (match && match[1] !== \"true\") {\n // create-next-app currently writes these two false entries. They are\n // starter policy, not an instance decision, so normalize them to the\n // Bonfire installation policy.\n if (match[1] !== \"false\" || ![\"sharp\", \"unrs-resolver\"].includes(key)) {\n throw new ConvertError(\n `pnpm-workspace.yaml has a conflicting allowBuilds.${key} setting`,\n );\n }\n result = result.replace(\n new RegExp(`(^\\\\s+${key}:\\\\s*)false(\\\\s*$)`, \"mu\"),\n \"$1true$2\",\n );\n }\n if (!match) {\n if (!result.endsWith(\"\\n\")) result += \"\\n\";\n result += `${line}\\n`;\n }\n }\n return result;\n}\n\nasync function planPackageJson(\n root: string,\n options: ConvertOptions,\n packageJson: PackageJson,\n nextVersion: { major: number; minor: number; patch: number },\n writes: Map<string, string>,\n changes: PlannedChange[],\n) {\n const packageName =\n options.packageName ??\n (typeof packageJson.name === \"string\" ? packageJson.name : options.appId);\n if (!/^[a-z0-9][a-z0-9._-]*$/u.test(packageName)) {\n throw new ConvertError(`package name is invalid: ${packageName}`);\n }\n packageJson.name = packageName;\n const engines = (packageJson.engines ??= {});\n if (\n engines.node !== undefined &&\n !/^(?:\\^|~|>=)?\\s*2[4-9]|[3-9]\\d/u.test(engines.node)\n ) {\n throw new ConvertError(\n \"package.json engines.node must allow Node.js 24 or newer\",\n );\n }\n engines.node = \">=24\";\n packageJson.packageManager ??= \"pnpm@11.25.0\";\n\n const dev = `bonfire prepare --root . && bonfire branch prepare --root . --default-hostname \"${options.hostname}\" && next dev -p ${options.port}`;\n addScript(packageJson, \"dev\", dev, [\"next dev\"]);\n addScript(packageJson, \"context:sync\", \"bonfire context sync\");\n addScript(\n packageJson,\n \"context:install\",\n `bonfire context install --app-id ${options.appId}`,\n );\n addScript(\n packageJson,\n \"check\",\n \"tsc --noEmit --project tsconfig.check.json && pnpm context:sync --check\",\n );\n addScript(packageJson, \"format\", \"prettier --write .\");\n addScript(packageJson, \"build\", \"next build\", [\"next build\"]);\n addScript(packageJson, \"start\", \"next start\", [\"next start\"]);\n addScript(packageJson, \"lint\", \"eslint\", [\"eslint\", \"eslint .\"]);\n\n const nextExact = `${nextVersion.major}.${nextVersion.minor}.${nextVersion.patch}`;\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-context\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-core\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-next\",\n BONFIRE_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-preset-ebay\",\n PRESET_VERSION,\n );\n addDependency(\n packageJson,\n \"dependencies\",\n \"@ebay-dt/bonfire-react\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"dependencies\", \"@ebay/ui-core-react\", \"9.13.0\");\n addDependency(packageJson, \"dependencies\", \"@evo-web/react\", \"0.4.4\");\n addDependency(\n packageJson,\n \"dependencies\",\n \"react-dom\",\n dependencyVersion(packageJson, \"react-dom\") ?? \"19.2.8\",\n );\n addDependency(packageJson, \"dependencies\", \"server-only\", \"^0.0.1\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"@ebay-dt/bonfire-cli\",\n BONFIRE_VERSION,\n );\n addDependency(packageJson, \"devDependencies\", \"@types/node\", \"^20\");\n addDependency(packageJson, \"devDependencies\", \"@types/react\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"@types/react-dom\", \"^19\");\n addDependency(packageJson, \"devDependencies\", \"eslint\", \"^9\");\n addDependency(\n packageJson,\n \"devDependencies\",\n \"eslint-config-next\",\n nextExact,\n );\n addDependency(packageJson, \"devDependencies\", \"prettier\", \"^3.9.5\");\n if (options.withItemData) {\n addDependency(\n packageJson,\n \"dependencies\",\n \"@tanstack/react-query\",\n \"^5.104.0\",\n );\n addDependency(packageJson, \"dependencies\", \"zod\", \"^4.4.3\");\n }\n\n const path = join(root, \"package.json\");\n const content = `${JSON.stringify(packageJson, null, 2)}\\n`;\n const existing = await readFile(path, \"utf8\");\n if (JSON.stringify(JSON.parse(existing)) !== JSON.stringify(packageJson)) {\n writes.set(path, content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"merge Bonfire scripts and dependencies\",\n );\n }\n}\n\nexport async function planConversion(\n options: ConvertOptions,\n): Promise<ConversionPlan> {\n const root = resolve(options.root);\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(options.appId)) {\n throw new ConvertError(\n \"app id must contain only letters, numbers, dots, underscores, and hyphens\",\n );\n }\n if (!options.name.trim())\n throw new ConvertError(\"display name must not be empty\");\n const packagePath = join(root, \"package.json\");\n const packageJson = await readJson(packagePath);\n const nextVersion = validateStartingScaffold(packageJson);\n if (!(await exists(join(root, \"src\", \"app\")))) {\n throw new ConvertError(\n \"the starting scaffold must use the src/app App Router\",\n );\n }\n\n const writes = new Map<string, string>();\n const changes: PlannedChange[] = [];\n const removals: string[] = [];\n\n const starterPaths = [\n join(root, \"src/app/layout.tsx\"),\n join(root, \"src/app/page.tsx\"),\n join(root, \"src/app/page.module.css\"),\n join(root, \"src/app/globals.css\"),\n join(root, \"next.config.ts\"),\n join(root, \"README.md\"),\n ...[\"file.svg\", \"globe.svg\", \"next.svg\", \"vercel.svg\", \"window.svg\"].map(\n (name) => join(root, \"public\", name),\n ),\n ];\n for (const path of starterPaths) {\n await planRemoveStarter(\n root,\n path,\n \"remove unmodified create-next-app content\",\n removals,\n changes,\n );\n }\n const nextBuildDirectory = join(root, \".next\");\n if (await exists(nextBuildDirectory)) {\n removals.push(nextBuildDirectory);\n addChange(\n changes,\n root,\n nextBuildDirectory,\n \"remove\",\n \"clear generated Next.js output\",\n );\n }\n\n const resolvedOptions = { ...options, root };\n const templates = await templateFiles(resolvedOptions);\n for (const file of templates) {\n const path = join(root, file.relativePath);\n if (removals.includes(path)) {\n writes.set(path, file.content);\n addChange(\n changes,\n root,\n path,\n \"update\",\n \"replace unmodified create-next-app content\",\n );\n continue;\n }\n await planFile(\n root,\n path,\n file.content,\n \"add Bonfire instance scaffold\",\n writes,\n changes,\n );\n }\n\n await planPackageJson(\n root,\n options,\n packageJson,\n nextVersion,\n writes,\n changes,\n );\n\n const tsconfigPath = join(root, \"tsconfig.json\");\n const existingTsconfig = await readFile(tsconfigPath, \"utf8\");\n const tsconfig = await readJson(tsconfigPath);\n const compilerOptions = (tsconfig.compilerOptions ?? {}) as Record<\n string,\n unknown\n >;\n tsconfig.compilerOptions = compilerOptions;\n const paths = compilerOptions[\"paths\"] as Record<string, unknown> | undefined;\n if (paths && JSON.stringify(paths[\"@/*\"]) !== JSON.stringify([\"./src/*\"])) {\n throw new ConvertError(\"tsconfig.json has a conflicting @/* path alias\");\n }\n compilerOptions[\"paths\"] = { ...(paths ?? {}), \"@/*\": [\"./src/*\"] };\n const nextTsconfig = `${JSON.stringify(tsconfig, null, 2)}\\n`;\n if (\n JSON.stringify(JSON.parse(existingTsconfig)) !== JSON.stringify(tsconfig)\n ) {\n writes.set(tsconfigPath, nextTsconfig);\n addChange(\n changes,\n root,\n tsconfigPath,\n \"update\",\n \"retain the Bonfire @/* source alias\",\n );\n }\n\n await planFile(\n root,\n join(root, \"tsconfig.check.json\"),\n '{\\n \"extends\": \"./tsconfig.json\",\\n \"exclude\": [\"node_modules\", \".next\"]\\n}\\n',\n \"add the clean TypeScript check project\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierrc\"),\n '{\\n \"semi\": false,\\n \"singleQuote\": true,\\n \"trailingComma\": \"es5\",\\n \"printWidth\": 80\\n}\\n',\n \"add Bonfire formatting conventions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".prettierignore\"),\n \"# Generated and external files\\n.next/\\nnode_modules/\\npnpm-lock.yaml\\nsrc/app/(prototypes)/**/.claude/settings.json\\n\",\n \"add formatter exclusions\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \".env.local.example\"),\n \"# Bonfire generates this secret during `pnpm dev`.\\n# Do NOT manually modify or remove this variable.\\nBF_SESSION_SECRET=\\n\\n# Set exactly to lowercase `true` to skip automatic identity-branch preparation.\\nBF_DISABLE_AUTO_BRANCH_SWITCH=\\n\\n# Set to `managed` or `manual` for Bonfire Git management.\\nBF_GIT_MODE=\\n\",\n \"document Bonfire environment setup\",\n writes,\n changes,\n );\n await planFile(\n root,\n join(root, \"public/.gitkeep\"),\n \"\",\n \"retain an explicit public directory\",\n writes,\n changes,\n );\n\n const gitignorePath = join(root, \".gitignore\");\n const gitignore = await fileContent(gitignorePath);\n const mergedGitignore = mergeLines(gitignore, [\n \"# Bonfire local secrets\",\n \".env.local\",\n ]);\n if (mergedGitignore !== (gitignore ?? \"\")) {\n writes.set(gitignorePath, mergedGitignore);\n addChange(\n changes,\n root,\n gitignorePath,\n \"update\",\n \"ignore the generated local session secret\",\n );\n }\n\n const workspacePath = join(root, \"pnpm-workspace.yaml\");\n const workspace = await fileContent(workspacePath);\n const mergedWorkspace = mergeWorkspace(workspace);\n if (mergedWorkspace !== (workspace ?? \"\")) {\n writes.set(workspacePath, mergedWorkspace);\n addChange(\n changes,\n root,\n workspacePath,\n \"update\",\n \"retain the Bonfire pnpm installation policy\",\n );\n }\n const npmrcPath = join(root, \".npmrc\");\n const npmrc = await fileContent(npmrcPath);\n if (\n npmrc &&\n /@ebay-dt:\\s*registry=/u.test(npmrc) &&\n !npmrc.includes(\"@ebay-dt:registry=https://registry.npmjs.org/\")\n ) {\n throw new ConvertError(\".npmrc has a conflicting @ebay-dt registry\");\n }\n const mergedNpmrc = mergeLines(npmrc, [\n \"@ebay-dt:registry=https://registry.npmjs.org/\",\n ]);\n if (mergedNpmrc !== (npmrc ?? \"\")) {\n writes.set(npmrcPath, mergedNpmrc);\n addChange(\n changes,\n root,\n npmrcPath,\n \"update\",\n \"resolve Bonfire packages from public npm\",\n );\n }\n const nvmrcPath = join(root, \".nvmrc\");\n const nvmrc = await fileContent(nvmrcPath);\n if (nvmrc === undefined) {\n await planFile(\n root,\n nvmrcPath,\n \"24\\n\",\n \"select Node.js 24 or newer\",\n writes,\n changes,\n );\n }\n\n const readmePath = join(root, \"README.md\");\n if (removals.includes(readmePath)) {\n writes.set(readmePath, starterReadme(options));\n addChange(\n changes,\n root,\n readmePath,\n \"update\",\n \"replace unmodified create-next-app documentation\",\n );\n } else if (\n !writes.has(readmePath) &&\n (await fileContent(readmePath)) === undefined\n ) {\n await planFile(\n root,\n readmePath,\n starterReadme(options),\n \"add instance setup documentation\",\n writes,\n changes,\n );\n }\n\n return { root, changes, writes, removals, packageJson };\n}\n\nexport async function convert(options: ConvertOptions) {\n const plan = await planConversion(options);\n for (const change of plan.changes) {\n console.log(\n `${options.dryRun ? \"Would \" : \"\"}${change.kind} ${change.path} (${change.reason})`,\n );\n }\n if (options.dryRun) return;\n\n for (const path of plan.removals) {\n await rm(path, {\n force: true,\n recursive: path === join(plan.root, \".next\"),\n });\n }\n for (const [path, content] of plan.writes) {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content);\n if (path.endsWith(\"context/hooks/block-env-reads.mjs\")) {\n await chmod(path, 0o755);\n }\n }\n\n if (!options.skipInstall) {\n console.log(\"Installing dependencies and updating pnpm-lock.yaml...\");\n await execFileAsync(\"pnpm\", [\"install\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n if (!options.skipInstall) {\n const formatPaths = [...plan.writes.keys()]\n .map((path) => displayPath(plan.root, path))\n .filter((path) => /\\.(?:json|mjs|md|ts|tsx|yaml|yml)$/u.test(path));\n if (formatPaths.length > 0) {\n await execFileAsync(\n \"pnpm\",\n [\"exec\", \"prettier\", \"--write\", ...formatPaths],\n {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n },\n );\n }\n await execFileAsync(\"pnpm\", [\"exec\", \"next\", \"typegen\"], {\n cwd: plan.root,\n maxBuffer: 10 * 1024 * 1024,\n });\n }\n\n const contextResult = await syncContext({ repositoryRoot: plan.root });\n if (contextResult.written.length > 0 || contextResult.removed.length > 0) {\n console.log(\n `Context synchronized (${contextResult.written.length} written, ${contextResult.removed.length} removed).`,\n );\n }\n console.log(\"Bonfire instance conversion complete.\");\n}\n\nexport function defaultConvertOptions(root = process.cwd()): ConvertOptions {\n const appId = \"bonfire-instance\";\n return {\n root,\n appId,\n name: \"Bonfire Instance\",\n hostname: DEFAULT_HOSTNAME,\n port: DEFAULT_PORT,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n withItemData: true,\n dryRun: false,\n skipInstall: false,\n };\n}\n\nexport const convertDefaults = {\n hostname: DEFAULT_HOSTNAME,\n deploymentEndpoint: DEFAULT_DEPLOYMENT_ENDPOINT,\n port: DEFAULT_PORT,\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-versions.d.ts","sourceRoot":"","sources":["../src/release-versions.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"release-versions.d.ts","sourceRoot":"","sources":["../src/release-versions.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAChD,eAAO,MAAM,cAAc,UAAU,CAAC","sourcesContent":["// Generated by scripts/generate-release-versions.mjs during the package build.\nexport const BONFIRE_VERSION = \"0.2.0-alpha.11\";\nexport const PRESET_VERSION = \"0.1.0\";\n"]}
|
package/dist/release-versions.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-versions.js","sourceRoot":"","sources":["../src/release-versions.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,
|
|
1
|
+
{"version":3,"file":"release-versions.js","sourceRoot":"","sources":["../src/release-versions.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC","sourcesContent":["// Generated by scripts/generate-release-versions.mjs during the package build.\nexport const BONFIRE_VERSION = \"0.2.0-alpha.11\";\nexport const PRESET_VERSION = \"0.1.0\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ebay-dt/bonfire-cli",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.11",
|
|
4
4
|
"description": "The Bonfire command-line tool.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ebay-dt/bonfire-context": "0.2.0-alpha.
|
|
34
|
+
"@ebay-dt/bonfire-context": "0.2.0-alpha.11",
|
|
35
35
|
"@next/env": "16.3.4",
|
|
36
|
-
"@ebay-dt/bonfire-core": "0.2.0-alpha.
|
|
37
|
-
"@ebay-dt/bonfire-node": "0.2.0-alpha.
|
|
36
|
+
"@ebay-dt/bonfire-core": "0.2.0-alpha.11",
|
|
37
|
+
"@ebay-dt/bonfire-node": "0.2.0-alpha.11"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@repo/eslint-config": "0.0.0",
|
|
@@ -35,8 +35,8 @@ or duplicate global CSS for Evo components.
|
|
|
35
35
|
Preserve the component's intended semantics and accessibility behavior. Do not replace a design-system component with custom markup solely to make styling easier. Import icons directly from the selected library:
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
|
-
import { EvoIconSettings16 } from
|
|
39
|
-
import { EbayIconArrowRight16 } from
|
|
38
|
+
import { EvoIconSettings16 } from "@evo-web/react/icons/settings-16";
|
|
39
|
+
import { EbayIconArrowRight16 } from "@ebay/ui-core-react/icons/ebay-icon-arrow-right-16";
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Keep prototype-specific composition helpers—such as item-tile price, media, or treatment mappings—inside the prototype that owns them. They may compose upstream components, but they must not become shared compatibility wrappers or substitute exports for the design-system packages.
|
|
@@ -8,12 +8,12 @@ description: Implement visitor-facing Light and Dark color-scheme controls in De
|
|
|
8
8
|
Use the published Bonfire hook for prototype-authored controls that let visitors switch between Light and Dark:
|
|
9
9
|
|
|
10
10
|
```tsx
|
|
11
|
-
|
|
11
|
+
"use client";
|
|
12
12
|
|
|
13
|
-
import { useColorSchemeToggle } from
|
|
13
|
+
import { useColorSchemeToggle } from "@ebay-dt/bonfire-react";
|
|
14
14
|
|
|
15
15
|
export function ColorSchemeToggle() {
|
|
16
|
-
const { canToggle, toggle } = useColorSchemeToggle()
|
|
16
|
+
const { canToggle, toggle } = useColorSchemeToggle();
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
19
|
<button
|
|
@@ -24,7 +24,7 @@ export function ColorSchemeToggle() {
|
|
|
24
24
|
>
|
|
25
25
|
Toggle color scheme
|
|
26
26
|
</button>
|
|
27
|
-
)
|
|
27
|
+
);
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -26,15 +26,15 @@ Normalized types such as `SearchItem`, `ItemSearchPage`, and `ItemDetail` are ex
|
|
|
26
26
|
The application root does not supply a React Query provider. Mount the preset's `QueryProvider` around the prototype's item UI, normally in its `page.tsx`:
|
|
27
27
|
|
|
28
28
|
```tsx
|
|
29
|
-
import { QueryProvider } from
|
|
30
|
-
import App from
|
|
29
|
+
import { QueryProvider } from "@ebay-dt/bonfire-preset-ebay/data/items/react";
|
|
30
|
+
import App from "./app";
|
|
31
31
|
|
|
32
32
|
export default function Page() {
|
|
33
33
|
return (
|
|
34
34
|
<QueryProvider>
|
|
35
35
|
<App />
|
|
36
36
|
</QueryProvider>
|
|
37
|
-
)
|
|
37
|
+
);
|
|
38
38
|
}
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -55,19 +55,19 @@ Gateway endpoints, GraphQL documents, credentials, wire schemas, and normalizati
|
|
|
55
55
|
## Numbered pagination
|
|
56
56
|
|
|
57
57
|
```tsx
|
|
58
|
-
|
|
58
|
+
"use client";
|
|
59
59
|
|
|
60
|
-
import { useItemsSearch } from
|
|
60
|
+
import { useItemsSearch } from "@ebay-dt/bonfire-preset-ebay/data/items/react";
|
|
61
61
|
|
|
62
62
|
export function Results({ query, page }: { query: string; page: number }) {
|
|
63
|
-
const search = useItemsSearch(query, { page, pageSize: 20 })
|
|
64
|
-
const items = search.data ?? []
|
|
65
|
-
const isCurrentResult = search.resultQuery === search.debouncedQuery
|
|
63
|
+
const search = useItemsSearch(query, { page, pageSize: 20 });
|
|
64
|
+
const items = search.data ?? [];
|
|
65
|
+
const isCurrentResult = search.resultQuery === search.debouncedQuery;
|
|
66
66
|
|
|
67
67
|
// Render search.isIdle, search.isPending, search.isError, and items here.
|
|
68
68
|
// Use search.hasPreviousPage, search.hasNextPage, and search.totalPages
|
|
69
69
|
// for controls. Disable or label controls while !isCurrentResult.
|
|
70
|
-
return null
|
|
70
|
+
return null;
|
|
71
71
|
}
|
|
72
72
|
```
|
|
73
73
|
|
|
@@ -83,17 +83,17 @@ Keep page state in the component or URL. Reset it to page 1 when a current query
|
|
|
83
83
|
## Infinite results
|
|
84
84
|
|
|
85
85
|
```tsx
|
|
86
|
-
|
|
86
|
+
"use client";
|
|
87
87
|
|
|
88
|
-
import { useInfiniteItemsSearch } from
|
|
88
|
+
import { useInfiniteItemsSearch } from "@ebay-dt/bonfire-preset-ebay/data/items/react";
|
|
89
89
|
|
|
90
90
|
export function Results({ query }: { query: string }) {
|
|
91
|
-
const search = useInfiniteItemsSearch(query, { pageSize: 20 })
|
|
92
|
-
const items = search.data ?? []
|
|
91
|
+
const search = useInfiniteItemsSearch(query, { pageSize: 20 });
|
|
92
|
+
const items = search.data ?? [];
|
|
93
93
|
|
|
94
94
|
// Render items, then call search.loadMore() from a button or observer.
|
|
95
95
|
// Disable the trigger while search.isLoadingMore or when !search.hasMore.
|
|
96
|
-
return null
|
|
96
|
+
return null;
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
@@ -104,15 +104,15 @@ Prefer an explicit, accessible “Load more” button unless the prototype speci
|
|
|
104
104
|
## Item details
|
|
105
105
|
|
|
106
106
|
```tsx
|
|
107
|
-
|
|
107
|
+
"use client";
|
|
108
108
|
|
|
109
|
-
import { useItemById } from
|
|
109
|
+
import { useItemById } from "@ebay-dt/bonfire-preset-ebay/data/items/react";
|
|
110
110
|
|
|
111
111
|
export function ItemDetails({ itemId }: { itemId: string | null }) {
|
|
112
|
-
const detail = useItemById(itemId)
|
|
112
|
+
const detail = useItemById(itemId);
|
|
113
113
|
|
|
114
|
-
if (!itemId) return null
|
|
115
|
-
if (detail.isPending) return <p role="status">Loading item details…</p
|
|
114
|
+
if (!itemId) return null;
|
|
115
|
+
if (detail.isPending) return <p role="status">Loading item details…</p>;
|
|
116
116
|
if (detail.isError) {
|
|
117
117
|
return (
|
|
118
118
|
<div role="alert">
|
|
@@ -121,10 +121,10 @@ export function ItemDetails({ itemId }: { itemId: string | null }) {
|
|
|
121
121
|
Try again
|
|
122
122
|
</button>
|
|
123
123
|
</div>
|
|
124
|
-
)
|
|
124
|
+
);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
return detail.data ? <h2>{detail.data.title}</h2> : null
|
|
127
|
+
return detail.data ? <h2>{detail.data.title}</h2> : null;
|
|
128
128
|
}
|
|
129
129
|
```
|
|
130
130
|
|