@ebay-dt/bonfire-cli 0.1.0 → 0.2.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/branch-prepare.d.ts +1 -0
- package/dist/branch-prepare.d.ts.map +1 -1
- package/dist/branch-prepare.js +24 -1
- package/dist/branch-prepare.js.map +1 -1
- package/dist/convert.d.ts.map +1 -1
- package/dist/convert.js +2 -3
- package/dist/convert.js.map +1 -1
- package/dist/release-versions.d.ts +3 -0
- package/dist/release-versions.d.ts.map +1 -0
- package/dist/release-versions.js +4 -0
- package/dist/release-versions.js.map +1 -0
- package/package.json +5 -5
- 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/context/skills/setup-evomcp/SKILL.md +1 -1
- package/templates/instance/next.config.ts +4 -4
- package/templates/instance/src/actions/agents.ts +5 -5
- package/templates/instance/src/actions/prototypes.ts +14 -10
- package/templates/instance/src/actions/repository.ts +33 -0
- 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 +3 -0
- package/templates/instance/src/app/(system)/api/repository/retry/route.ts +3 -0
- package/templates/instance/src/app/(system)/api/repository/summary/route.ts +3 -0
- package/templates/instance/src/app/(system)/api/repository/update/route.ts +3 -0
- 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 +38 -16
- package/templates/instance/src/bonfire.ts +11 -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/branch-prepare.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type BranchPrepareDependencies = {
|
|
|
6
6
|
loadEnvironment?: CliEnvironmentLoader;
|
|
7
7
|
githubCli?: GitHubCliClientLike;
|
|
8
8
|
lifecycle?: Pick<PrototypeLifecycle, "prepareBranch">;
|
|
9
|
+
installDependencies?: (root: string) => Promise<void>;
|
|
9
10
|
};
|
|
10
11
|
export declare class BranchPrepareError extends Error {
|
|
11
12
|
constructor(message: string);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-prepare.d.ts","sourceRoot":"","sources":["../src/branch-prepare.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"branch-prepare.d.ts","sourceRoot":"","sources":["../src/branch-prepare.ts"],"names":[],"mappings":"AASA,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAIhE,MAAM,MAAM,oBAAoB,GAAG,CACjC,IAAI,EAAE,MAAM,KACT,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAElD,MAAM,MAAM,yBAAyB,GAAG;IACtC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IACtD,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAMD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,2BAA2B,EACpC,YAAY,EAAE,yBAAyB,GACtC,OAAO,CAAC,MAAM,CAAC,CA8EjB","sourcesContent":["import { execFile as execFileCallback } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport nextEnv from \"@next/env\";\nimport {\n MANAGED_REPOSITORY_PATHS,\n parseAutomaticBranchSwitchSetting,\n parseGitModeSetting,\n parseHostname,\n} from \"@ebay-dt/bonfire-core\";\nimport {\n GitHubCliClient,\n GitHubCliError,\n LocalPrototypeLifecycle,\n type GitHubCliClientLike,\n type PrototypeLifecycle,\n} from \"@ebay-dt/bonfire-node\";\nimport { resolve } from \"node:path\";\nimport type { BranchPrepareCommandOptions } from \"./command.js\";\n\nconst execFile = promisify(execFileCallback);\n\nexport type CliEnvironmentLoader = (\n root: string,\n) => Readonly<Record<string, string | undefined>>;\n\nexport type BranchPrepareDependencies = {\n environment?: Readonly<Record<string, string | undefined>>;\n loadEnvironment?: CliEnvironmentLoader;\n githubCli?: GitHubCliClientLike;\n lifecycle?: Pick<PrototypeLifecycle, \"prepareBranch\">;\n installDependencies?: (root: string) => Promise<void>;\n};\n\nexport class BranchPrepareError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BranchPrepareError\";\n }\n}\n\nfunction loadEnvironment(root: string) {\n return nextEnv.loadEnvConfig(root, true, undefined, false).combinedEnv;\n}\n\nexport async function runBranchPrepare(\n options: BranchPrepareCommandOptions,\n dependencies: BranchPrepareDependencies,\n): Promise<number> {\n const root = resolve(options.root);\n const environment =\n dependencies.environment ??\n dependencies.loadEnvironment?.(root) ??\n loadEnvironment(root);\n const mode = parseAutomaticBranchSwitchSetting(\n environment.BF_DISABLE_AUTO_BRANCH_SWITCH,\n );\n const gitMode = parseGitModeSetting(environment.BF_GIT_MODE);\n const hostname = parseHostname(options.hostname);\n\n if (gitMode === \"manual\") {\n console.log(\"Git management is in manual mode.\");\n return 0;\n }\n\n if (mode === \"disabled\") {\n console.log(\"Automatic branch switching is disabled.\");\n return 0;\n }\n\n const githubCli = dependencies.githubCli ?? new GitHubCliClient({ hostname });\n let identity;\n try {\n identity = await githubCli.getUser();\n } catch (error) {\n if (\n error instanceof GitHubCliError &&\n (error.reason === \"missing\" || error.reason === \"unauthenticated\")\n ) {\n console.log(\n \"Branch preparation deferred; GitHub CLI authentication is not available.\",\n );\n return 0;\n }\n throw new BranchPrepareError(\"Unable to resolve GitHub CLI identity.\");\n }\n\n const lifecycle =\n dependencies.lifecycle ??\n new LocalPrototypeLifecycle({\n repositoryRoot: root,\n primaryBranch: environment.BF_PROTOTYPE_BASE_BRANCH,\n automaticBranchSwitch: mode,\n gitMode,\n });\n const result = await lifecycle.prepareBranch(identity);\n if (!result.ok) {\n throw new BranchPrepareError(\n `Branch preparation failed with ${result.error.code}.`,\n );\n }\n\n if (result.value.status === \"deferred\") {\n console.log(\n `Branch preparation deferred; repository attention: ${result.value.reason ?? \"unknown\"}.`,\n );\n return 0;\n }\n if (result.value.status === \"unsafe\") {\n console.log(\n `Branch preparation requires repository attention: ${result.value.reason ?? \"unknown\"}.`,\n );\n return 0;\n }\n\n const managedPathChanged = result.value.affectedPaths?.some((path) =>\n MANAGED_REPOSITORY_PATHS.some((managedPath) => managedPath === path),\n );\n if (managedPathChanged) {\n console.log(\"Installing updated project dependencies...\");\n await (dependencies.installDependencies?.(root) ??\n execFile(\"pnpm\", [\"install\"], { cwd: root }).then(() => undefined));\n }\n\n console.log(\"Branch preparation complete.\");\n return 0;\n}\n"]}
|
package/dist/branch-prepare.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { execFile as execFileCallback } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
1
3
|
import nextEnv from "@next/env";
|
|
2
|
-
import { parseAutomaticBranchSwitchSetting, parseHostname, } from "@ebay-dt/bonfire-core";
|
|
4
|
+
import { MANAGED_REPOSITORY_PATHS, parseAutomaticBranchSwitchSetting, parseGitModeSetting, parseHostname, } from "@ebay-dt/bonfire-core";
|
|
3
5
|
import { GitHubCliClient, GitHubCliError, LocalPrototypeLifecycle, } from "@ebay-dt/bonfire-node";
|
|
4
6
|
import { resolve } from "node:path";
|
|
7
|
+
const execFile = promisify(execFileCallback);
|
|
5
8
|
export class BranchPrepareError extends Error {
|
|
6
9
|
constructor(message) {
|
|
7
10
|
super(message);
|
|
@@ -17,7 +20,12 @@ export async function runBranchPrepare(options, dependencies) {
|
|
|
17
20
|
dependencies.loadEnvironment?.(root) ??
|
|
18
21
|
loadEnvironment(root);
|
|
19
22
|
const mode = parseAutomaticBranchSwitchSetting(environment.BF_DISABLE_AUTO_BRANCH_SWITCH);
|
|
23
|
+
const gitMode = parseGitModeSetting(environment.BF_GIT_MODE);
|
|
20
24
|
const hostname = parseHostname(options.hostname);
|
|
25
|
+
if (gitMode === "manual") {
|
|
26
|
+
console.log("Git management is in manual mode.");
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
21
29
|
if (mode === "disabled") {
|
|
22
30
|
console.log("Automatic branch switching is disabled.");
|
|
23
31
|
return 0;
|
|
@@ -40,11 +48,26 @@ export async function runBranchPrepare(options, dependencies) {
|
|
|
40
48
|
repositoryRoot: root,
|
|
41
49
|
primaryBranch: environment.BF_PROTOTYPE_BASE_BRANCH,
|
|
42
50
|
automaticBranchSwitch: mode,
|
|
51
|
+
gitMode,
|
|
43
52
|
});
|
|
44
53
|
const result = await lifecycle.prepareBranch(identity);
|
|
45
54
|
if (!result.ok) {
|
|
46
55
|
throw new BranchPrepareError(`Branch preparation failed with ${result.error.code}.`);
|
|
47
56
|
}
|
|
57
|
+
if (result.value.status === "deferred") {
|
|
58
|
+
console.log(`Branch preparation deferred; repository attention: ${result.value.reason ?? "unknown"}.`);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
if (result.value.status === "unsafe") {
|
|
62
|
+
console.log(`Branch preparation requires repository attention: ${result.value.reason ?? "unknown"}.`);
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
const managedPathChanged = result.value.affectedPaths?.some((path) => MANAGED_REPOSITORY_PATHS.some((managedPath) => managedPath === path));
|
|
66
|
+
if (managedPathChanged) {
|
|
67
|
+
console.log("Installing updated project dependencies...");
|
|
68
|
+
await (dependencies.installDependencies?.(root) ??
|
|
69
|
+
execFile("pnpm", ["install"], { cwd: root }).then(() => undefined));
|
|
70
|
+
}
|
|
48
71
|
console.log("Branch preparation complete.");
|
|
49
72
|
return 0;
|
|
50
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-prepare.js","sourceRoot":"","sources":["../src/branch-prepare.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,WAAW,CAAC;AAChC,OAAO,EACL,iCAAiC,EACjC,aAAa,GACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,cAAc,EACd,uBAAuB,GAGxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"branch-prepare.js","sourceRoot":"","sources":["../src/branch-prepare.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile as execFileCallback } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport nextEnv from \"@next/env\";\nimport {\n MANAGED_REPOSITORY_PATHS,\n parseAutomaticBranchSwitchSetting,\n parseGitModeSetting,\n parseHostname,\n} from \"@ebay-dt/bonfire-core\";\nimport {\n GitHubCliClient,\n GitHubCliError,\n LocalPrototypeLifecycle,\n type GitHubCliClientLike,\n type PrototypeLifecycle,\n} from \"@ebay-dt/bonfire-node\";\nimport { resolve } from \"node:path\";\nimport type { BranchPrepareCommandOptions } from \"./command.js\";\n\nconst execFile = promisify(execFileCallback);\n\nexport type CliEnvironmentLoader = (\n root: string,\n) => Readonly<Record<string, string | undefined>>;\n\nexport type BranchPrepareDependencies = {\n environment?: Readonly<Record<string, string | undefined>>;\n loadEnvironment?: CliEnvironmentLoader;\n githubCli?: GitHubCliClientLike;\n lifecycle?: Pick<PrototypeLifecycle, \"prepareBranch\">;\n installDependencies?: (root: string) => Promise<void>;\n};\n\nexport class BranchPrepareError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BranchPrepareError\";\n }\n}\n\nfunction loadEnvironment(root: string) {\n return nextEnv.loadEnvConfig(root, true, undefined, false).combinedEnv;\n}\n\nexport async function runBranchPrepare(\n options: BranchPrepareCommandOptions,\n dependencies: BranchPrepareDependencies,\n): Promise<number> {\n const root = resolve(options.root);\n const environment =\n dependencies.environment ??\n dependencies.loadEnvironment?.(root) ??\n loadEnvironment(root);\n const mode = parseAutomaticBranchSwitchSetting(\n environment.BF_DISABLE_AUTO_BRANCH_SWITCH,\n );\n const gitMode = parseGitModeSetting(environment.BF_GIT_MODE);\n const hostname = parseHostname(options.hostname);\n\n if (gitMode === \"manual\") {\n console.log(\"Git management is in manual mode.\");\n return 0;\n }\n\n if (mode === \"disabled\") {\n console.log(\"Automatic branch switching is disabled.\");\n return 0;\n }\n\n const githubCli = dependencies.githubCli ?? new GitHubCliClient({ hostname });\n let identity;\n try {\n identity = await githubCli.getUser();\n } catch (error) {\n if (\n error instanceof GitHubCliError &&\n (error.reason === \"missing\" || error.reason === \"unauthenticated\")\n ) {\n console.log(\n \"Branch preparation deferred; GitHub CLI authentication is not available.\",\n );\n return 0;\n }\n throw new BranchPrepareError(\"Unable to resolve GitHub CLI identity.\");\n }\n\n const lifecycle =\n dependencies.lifecycle ??\n new LocalPrototypeLifecycle({\n repositoryRoot: root,\n primaryBranch: environment.BF_PROTOTYPE_BASE_BRANCH,\n automaticBranchSwitch: mode,\n gitMode,\n });\n const result = await lifecycle.prepareBranch(identity);\n if (!result.ok) {\n throw new BranchPrepareError(\n `Branch preparation failed with ${result.error.code}.`,\n );\n }\n\n if (result.value.status === \"deferred\") {\n console.log(\n `Branch preparation deferred; repository attention: ${result.value.reason ?? \"unknown\"}.`,\n );\n return 0;\n }\n if (result.value.status === \"unsafe\") {\n console.log(\n `Branch preparation requires repository attention: ${result.value.reason ?? \"unknown\"}.`,\n );\n return 0;\n }\n\n const managedPathChanged = result.value.affectedPaths?.some((path) =>\n MANAGED_REPOSITORY_PATHS.some((managedPath) => managedPath === path),\n );\n if (managedPathChanged) {\n console.log(\"Installing updated project dependencies...\");\n await (dependencies.installDependencies?.(root) ??\n execFile(\"pnpm\", [\"install\"], { cwd: root }).then(() => undefined));\n }\n\n console.log(\"Branch preparation complete.\");\n return 0;\n}\n"]}
|
package/dist/convert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AA0BA,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\";\n\nconst execFileAsync = promisify(execFile);\nconst TEMPLATE_ROOT = fileURLToPath(\n new URL(\"../templates/instance/\", import.meta.url),\n);\nconst BONFIRE_VERSION = \"0.1.0\";\nconst PRESET_VERSION = \"0.1.0\";\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 \"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 . --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,10 +4,9 @@ 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 } from "./release-versions.js";
|
|
7
8
|
const execFileAsync = promisify(execFile);
|
|
8
9
|
const TEMPLATE_ROOT = fileURLToPath(new URL("../templates/instance/", import.meta.url));
|
|
9
|
-
const BONFIRE_VERSION = "0.1.0";
|
|
10
|
-
const PRESET_VERSION = "0.1.0";
|
|
11
10
|
const DEFAULT_HOSTNAME = "github.corp.ebay.com";
|
|
12
11
|
const DEFAULT_DEPLOYMENT_ENDPOINT = "https://dtsvc.vip.qa.ebay.com/dt/v1/bonfire-deploy";
|
|
13
12
|
const DEFAULT_PORT = 1995;
|
|
@@ -390,7 +389,7 @@ export async function planConversion(options) {
|
|
|
390
389
|
await planFile(root, join(root, "tsconfig.check.json"), '{\n "extends": "./tsconfig.json",\n "exclude": ["node_modules", ".next"]\n}\n', "add the clean TypeScript check project", writes, changes);
|
|
391
390
|
await planFile(root, join(root, ".prettierrc"), '{\n "semi": false,\n "singleQuote": true,\n "trailingComma": "es5",\n "printWidth": 80\n}\n', "add Bonfire formatting conventions", writes, changes);
|
|
392
391
|
await planFile(root, join(root, ".prettierignore"), "# Generated and external files\n.next/\nnode_modules/\npnpm-lock.yaml\nsrc/app/(prototypes)/**/.claude/settings.json\n", "add formatter exclusions", writes, changes);
|
|
393
|
-
await planFile(root, join(root, ".env.local.example"), "# 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", "document Bonfire environment setup", writes, changes);
|
|
392
|
+
await planFile(root, join(root, ".env.local.example"), "# 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", "document Bonfire environment setup", writes, changes);
|
|
394
393
|
await planFile(root, join(root, "public/.gitkeep"), "", "retain an explicit public directory", writes, changes);
|
|
395
394
|
const gitignorePath = join(root, ".gitignore");
|
|
396
395
|
const gitignore = await fileContent(gitignorePath);
|
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\";\n\nconst execFileAsync = promisify(execFile);\nconst TEMPLATE_ROOT = fileURLToPath(\n new URL(\"../templates/instance/\", import.meta.url),\n);\nconst BONFIRE_VERSION = \"0.1.0\";\nconst PRESET_VERSION = \"0.1.0\";\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 \"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 . --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"]}
|
|
@@ -0,0 +1 @@
|
|
|
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.10\";\nexport const PRESET_VERSION = \"0.1.0\";\n"]}
|
|
@@ -0,0 +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,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.10\";\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.
|
|
3
|
+
"version": "0.2.0-alpha.10",
|
|
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.
|
|
34
|
+
"@ebay-dt/bonfire-context": "0.2.0-alpha.10",
|
|
35
35
|
"@next/env": "16.3.4",
|
|
36
|
-
"@ebay-dt/bonfire-core": "0.
|
|
37
|
-
"@ebay-dt/bonfire-node": "0.
|
|
36
|
+
"@ebay-dt/bonfire-core": "0.2.0-alpha.10",
|
|
37
|
+
"@ebay-dt/bonfire-node": "0.2.0-alpha.10"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@repo/eslint-config": "0.0.0",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"vitest": "^5.0.0"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "tsc -p tsconfig.build.json && node ../../scripts/embed-source-map-sources.mjs dist && node scripts/set-bin-mode.mjs",
|
|
48
|
+
"build": "node scripts/generate-release-versions.mjs && tsc -p tsconfig.build.json && node ../../scripts/embed-source-map-sources.mjs dist && node scripts/set-bin-mode.mjs",
|
|
49
49
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
50
50
|
"lint": "eslint .",
|
|
51
51
|
"pretest": "pnpm build",
|
|
@@ -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.
|