@ebay-dt/bonfire-cli 0.1.0-alpha.3 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,6 +33,22 @@ The command never invokes GitHub CLI, loads application configuration, or
33
33
  prints the secret. It exits with `0` on success, `1` on validation or
34
34
  filesystem failure, and `2` for invalid command syntax.
35
35
 
36
+ ## Context repository operations
37
+
38
+ Use the context commands explicitly from an instance repository:
39
+
40
+ ```sh
41
+ bonfire context sync [--check] [--root <root>]
42
+ bonfire context install [--check] --app-id <app-id> [--root <root>]
43
+ ```
44
+
45
+ `sync` writes deterministic repository projections and `sync --check` performs
46
+ the same validation without writing. Both default `--root` to the current
47
+ working directory and print only generated paths and status. `install` installs
48
+ canonical skills and merges MCP definitions into the user's Cursor MCP
49
+ configuration while preserving unrelated entries. `install --check` validates
50
+ machine state without changing it.
51
+
36
52
  ## Branch preparation
37
53
 
38
54
  Before starting Next.js in development, run:
package/dist/command.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type ContextInstallCheckResult, type ContextInstallResult, type ContextInstallOptions } from "@ebay-dt/bonfire-context";
1
2
  import { type BranchPrepareDependencies } from "./branch-prepare.js";
2
3
  export declare class CliSyntaxError extends Error {
3
4
  constructor(message: string);
@@ -9,8 +10,22 @@ export type BranchPrepareCommandOptions = {
9
10
  root: string;
10
11
  hostname: string;
11
12
  };
12
- type CliCommandOptions = PrepareCommandOptions | BranchPrepareCommandOptions;
13
+ export type ContextCommandOptions = {
14
+ context: "sync";
15
+ root: string;
16
+ check: boolean;
17
+ } | {
18
+ context: "install";
19
+ root: string;
20
+ appId: string;
21
+ check: boolean;
22
+ };
23
+ type CliCommandOptions = PrepareCommandOptions | BranchPrepareCommandOptions | ContextCommandOptions;
24
+ export type CliDependencies = BranchPrepareDependencies & {
25
+ contextInstall?: (options: ContextInstallOptions) => Promise<ContextInstallResult>;
26
+ contextInstallCheck?: (options: ContextInstallOptions) => Promise<ContextInstallCheckResult>;
27
+ };
13
28
  export declare function parseArgs(argv: readonly string[]): CliCommandOptions;
14
- export declare function run(argv?: readonly string[], dependencies?: BranchPrepareDependencies): Promise<number>;
29
+ export declare function run(argv?: readonly string[], dependencies?: CliDependencies): Promise<number>;
15
30
  export {};
16
31
  //# sourceMappingURL=command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,iBAAiB,GAAG,qBAAqB,GAAG,2BAA2B,CAAC;AA6E7E,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAQpE;AAED,wBAAsB,GAAG,CACvB,IAAI,GAAE,SAAS,MAAM,EAA0B,EAC/C,YAAY,GAAE,yBAA8B,GAC3C,OAAO,CAAC,MAAM,CAAC,CAuCjB","sourcesContent":["import { prepare, PrepareError } from \"./prepare.js\";\nimport {\n BranchPrepareError,\n runBranchPrepare,\n type BranchPrepareDependencies,\n} from \"./branch-prepare.js\";\n\nexport class CliSyntaxError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliSyntaxError\";\n }\n}\n\nexport type PrepareCommandOptions = {\n root: string;\n};\n\nexport type BranchPrepareCommandOptions = {\n root: string;\n hostname: string;\n};\n\ntype CliCommandOptions = PrepareCommandOptions | BranchPrepareCommandOptions;\n\nfunction parseRootOption(\n argv: readonly string[],\n start: number,\n): { root: string; nextIndex: number } {\n const value = argv[start + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --root option requires a value\");\n }\n return { root: value, nextIndex: start + 2 };\n}\n\nfunction parsePrepareArgs(argv: readonly string[]): PrepareCommandOptions {\n let root = process.cwd();\n let rootProvided = false;\n for (let index = 1; index < argv.length;) {\n if (argv[index] !== \"--root\") {\n throw new CliSyntaxError(`Unknown option: ${argv[index]}`);\n }\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n }\n return { root };\n}\n\nfunction parseBranchPrepareArgs(\n argv: readonly string[],\n): BranchPrepareCommandOptions {\n let root = process.cwd();\n let hostname: string | undefined;\n let rootProvided = false;\n let hostnameProvided = false;\n\n for (let index = 2; index < argv.length;) {\n const option = argv[index];\n if (option === \"--root\") {\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n continue;\n }\n if (option === \"--hostname\") {\n if (hostnameProvided) {\n throw new CliSyntaxError(\n \"The --hostname option may only be provided once\",\n );\n }\n const value = argv[index + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --hostname option requires a value\");\n }\n hostname = value;\n hostnameProvided = true;\n index += 2;\n continue;\n }\n throw new CliSyntaxError(`Unknown option: ${option}`);\n }\n\n if (hostname === undefined) {\n throw new CliSyntaxError(\n \"Usage: bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n }\n return { root, hostname };\n}\n\nexport function parseArgs(argv: readonly string[]): CliCommandOptions {\n if (argv[0] === \"prepare\") return parsePrepareArgs(argv);\n if (argv[0] === \"branch\" && argv[1] === \"prepare\") {\n return parseBranchPrepareArgs(argv);\n }\n throw new CliSyntaxError(\n \"Usage: bonfire prepare [--root <application-root>] | bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n}\n\nexport async function run(\n argv: readonly string[] = process.argv.slice(2),\n dependencies: BranchPrepareDependencies = {},\n): Promise<number> {\n const isBranchPrepare = argv[0] === \"branch\";\n try {\n const options = parseArgs(argv);\n if (\"hostname\" in options) {\n return await runBranchPrepare(options, dependencies);\n }\n\n const result = await prepare(options);\n const descriptions = {\n environment: \"the process environment\",\n existing: \".env.local\",\n generated: \"a newly generated value in .env.local\",\n } as const;\n console.log(\n `Bonfire preparation complete; BF_SESSION_SECRET came from ${descriptions[result.source]}.`,\n );\n return 0;\n } catch (error) {\n if (error instanceof CliSyntaxError) {\n console.error(`bonfire: ${error.message}`);\n return 2;\n }\n if (isBranchPrepare) {\n const message =\n error instanceof BranchPrepareError\n ? error.message\n : \"Unable to load branch preparation configuration.\";\n console.error(`bonfire branch prepare failed: ${message}`);\n return 1;\n }\n\n const message =\n error instanceof PrepareError || error instanceof Error\n ? error.message\n : \"an unknown error occurred\";\n console.error(`bonfire prepare failed: ${message}`);\n return 1;\n }\n}\n"]}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAE3B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B;IACE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB,GACD;IACE,OAAO,EAAE,SAAS,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEN,KAAK,iBAAiB,GACpB,qBAAqB,GAAG,2BAA2B,GAAG,qBAAqB,CAAC;AAE9E,MAAM,MAAM,eAAe,GAAG,yBAAyB,GAAG;IACxD,cAAc,CAAC,EAAE,CACf,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,mBAAmB,CAAC,EAAE,CACpB,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACzC,CAAC;AAmJF,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CASpE;AA+ED,wBAAsB,GAAG,CACvB,IAAI,GAAE,SAAS,MAAM,EAA0B,EAC/C,YAAY,GAAE,eAAoB,GACjC,OAAO,CAAC,MAAM,CAAC,CAiDjB","sourcesContent":["import {\n checkContext,\n checkContextInstallation,\n installContext,\n syncContext,\n type ContextInstallCheckResult,\n type ContextInstallResult,\n type ContextInstallOptions,\n type ContextSyncResult,\n} from \"@ebay-dt/bonfire-context\";\nimport { prepare, PrepareError } from \"./prepare.js\";\nimport {\n BranchPrepareError,\n runBranchPrepare,\n type BranchPrepareDependencies,\n} from \"./branch-prepare.js\";\n\nexport class CliSyntaxError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliSyntaxError\";\n }\n}\n\nexport type PrepareCommandOptions = {\n root: string;\n};\n\nexport type BranchPrepareCommandOptions = {\n root: string;\n hostname: string;\n};\n\nexport type ContextCommandOptions =\n | {\n context: \"sync\";\n root: string;\n check: boolean;\n }\n | {\n context: \"install\";\n root: string;\n appId: string;\n check: boolean;\n };\n\ntype CliCommandOptions =\n PrepareCommandOptions | BranchPrepareCommandOptions | ContextCommandOptions;\n\nexport type CliDependencies = BranchPrepareDependencies & {\n contextInstall?: (\n options: ContextInstallOptions,\n ) => Promise<ContextInstallResult>;\n contextInstallCheck?: (\n options: ContextInstallOptions,\n ) => Promise<ContextInstallCheckResult>;\n};\n\nfunction parseRootOption(\n argv: readonly string[],\n start: number,\n): { root: string; nextIndex: number } {\n const value = argv[start + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --root option requires a value\");\n }\n return { root: value, nextIndex: start + 2 };\n}\n\nfunction parsePrepareArgs(argv: readonly string[]): PrepareCommandOptions {\n let root = process.cwd();\n let rootProvided = false;\n for (let index = 1; index < argv.length;) {\n if (argv[index] !== \"--root\") {\n throw new CliSyntaxError(`Unknown option: ${argv[index]}`);\n }\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n }\n return { root };\n}\n\nfunction parseContextArgs(argv: readonly string[]): ContextCommandOptions {\n const context = argv[1];\n if (context !== \"sync\" && context !== \"install\") {\n throw new CliSyntaxError(\n \"Usage: bonfire context sync [--check] [--root <root>] | bonfire context install [--check] --app-id <app-id> [--root <root>]\",\n );\n }\n\n let root = process.cwd();\n let appId: string | undefined;\n let check = false;\n let rootProvided = false;\n let appIdProvided = false;\n let checkProvided = false;\n\n for (let index = 2; index < argv.length;) {\n const option = argv[index];\n if (option === \"--check\") {\n if (checkProvided) {\n throw new CliSyntaxError(\n \"The --check option may only be provided once\",\n );\n }\n check = true;\n checkProvided = true;\n index += 1;\n continue;\n }\n if (option === \"--root\") {\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n continue;\n }\n if (option === \"--app-id\") {\n if (appIdProvided) {\n throw new CliSyntaxError(\n \"The --app-id option may only be provided once\",\n );\n }\n const value = argv[index + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --app-id option requires a value\");\n }\n appId = value;\n appIdProvided = true;\n index += 2;\n continue;\n }\n throw new CliSyntaxError(`Unknown option: ${option}`);\n }\n\n if (context === \"install\") {\n if (appId === undefined) {\n throw new CliSyntaxError(\n \"Usage: bonfire context install [--check] --app-id <app-id> [--root <root>]\",\n );\n }\n return { context, root, appId, check };\n }\n if (appId !== undefined) {\n throw new CliSyntaxError(\"The --app-id option is only valid for install\");\n }\n return { context, root, check };\n}\n\nfunction parseBranchPrepareArgs(\n argv: readonly string[],\n): BranchPrepareCommandOptions {\n let root = process.cwd();\n let hostname: string | undefined;\n let rootProvided = false;\n let hostnameProvided = false;\n\n for (let index = 2; index < argv.length;) {\n const option = argv[index];\n if (option === \"--root\") {\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n continue;\n }\n if (option === \"--hostname\") {\n if (hostnameProvided) {\n throw new CliSyntaxError(\n \"The --hostname option may only be provided once\",\n );\n }\n const value = argv[index + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --hostname option requires a value\");\n }\n hostname = value;\n hostnameProvided = true;\n index += 2;\n continue;\n }\n throw new CliSyntaxError(`Unknown option: ${option}`);\n }\n\n if (hostname === undefined) {\n throw new CliSyntaxError(\n \"Usage: bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n }\n return { root, hostname };\n}\n\nexport function parseArgs(argv: readonly string[]): CliCommandOptions {\n if (argv[0] === \"context\") return parseContextArgs(argv);\n if (argv[0] === \"prepare\") return parsePrepareArgs(argv);\n if (argv[0] === \"branch\" && argv[1] === \"prepare\") {\n return parseBranchPrepareArgs(argv);\n }\n throw new CliSyntaxError(\n \"Usage: bonfire context sync [--check] [--root <root>] | bonfire context install [--check] --app-id <app-id> [--root <root>] | bonfire prepare [--root <application-root>] | bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n}\n\nfunction printContextIssues(result: {\n issues: readonly { kind: string; path: string }[];\n}) {\n for (const issue of result.issues) {\n console.error(`- ${issue.kind}: ${issue.path}`);\n }\n}\n\nfunction printContextSyncSummary(result: ContextSyncResult) {\n if (result.written.length > 0) {\n console.log(`Written: ${result.written.join(\", \")}`);\n }\n if (result.removed.length > 0) {\n console.log(`Removed: ${result.removed.join(\", \")}`);\n }\n}\n\nasync function runContextCommand(\n options: ContextCommandOptions,\n dependencies: CliDependencies,\n): Promise<number> {\n if (options.context === \"install\") {\n if (options.check) {\n const result = await (\n dependencies.contextInstallCheck ?? checkContextInstallation\n )({\n repositoryRoot: options.root,\n appId: options.appId,\n });\n if (!result.ok) {\n console.error(\"Context install check failed:\");\n printContextIssues(result);\n return 1;\n }\n console.log(\"Context install check passed.\");\n return 0;\n }\n const result = await (dependencies.contextInstall ?? installContext)({\n repositoryRoot: options.root,\n appId: options.appId,\n });\n const skills = result.skills.map(\n (skill) => `${skill.name} (${skill.status})`,\n );\n const mcp = result.mcp.map((server) => `${server.name} (${server.status})`);\n console.log(\n skills.length > 0\n ? `Context skills: ${skills.join(\", \")}`\n : \"No context skills configured.\",\n );\n if (mcp.length > 0) console.log(`Context MCP: ${mcp.join(\", \")}`);\n console.log(\"Context install complete.\");\n return 0;\n }\n\n if (options.check) {\n const result = await checkContext({ repositoryRoot: options.root });\n if (!result.ok) {\n console.error(\"Context sync check failed:\");\n printContextIssues(result);\n return 1;\n }\n console.log(\"Context sync check passed.\");\n return 0;\n }\n\n const result = await syncContext({ repositoryRoot: options.root });\n if (!result.ok) {\n console.error(\"Context sync failed:\");\n printContextIssues(result);\n return 1;\n }\n printContextSyncSummary(result);\n console.log(\"Context sync complete.\");\n return 0;\n}\n\nexport async function run(\n argv: readonly string[] = process.argv.slice(2),\n dependencies: CliDependencies = {},\n): Promise<number> {\n const isBranchPrepare = argv[0] === \"branch\";\n const isContext = argv[0] === \"context\";\n try {\n const options = parseArgs(argv);\n if (\"context\" in options) {\n return await runContextCommand(options, dependencies);\n }\n if (\"hostname\" in options) {\n return await runBranchPrepare(options, dependencies);\n }\n\n const result = await prepare(options);\n const descriptions = {\n environment: \"the process environment\",\n existing: \".env.local\",\n generated: \"a newly generated value in .env.local\",\n } as const;\n console.log(\n `Bonfire preparation complete; BF_SESSION_SECRET came from ${descriptions[result.source]}.`,\n );\n return 0;\n } catch (error) {\n if (error instanceof CliSyntaxError) {\n console.error(`bonfire: ${error.message}`);\n return 2;\n }\n if (isContext) {\n const message =\n error instanceof Error ? error.message : \"an unknown error occurred\";\n console.error(`bonfire context failed: ${message}`);\n return 1;\n }\n if (isBranchPrepare) {\n const message =\n error instanceof BranchPrepareError\n ? error.message\n : \"Unable to load branch preparation configuration.\";\n console.error(`bonfire branch prepare failed: ${message}`);\n return 1;\n }\n\n const message =\n error instanceof PrepareError || error instanceof Error\n ? error.message\n : \"an unknown error occurred\";\n console.error(`bonfire prepare failed: ${message}`);\n return 1;\n }\n}\n"]}
package/dist/command.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { checkContext, checkContextInstallation, installContext, syncContext, } from "@ebay-dt/bonfire-context";
1
2
  import { prepare, PrepareError } from "./prepare.js";
2
3
  import { BranchPrepareError, runBranchPrepare, } from "./branch-prepare.js";
3
4
  export class CliSyntaxError extends Error {
@@ -30,6 +31,64 @@ function parsePrepareArgs(argv) {
30
31
  }
31
32
  return { root };
32
33
  }
34
+ function parseContextArgs(argv) {
35
+ const context = argv[1];
36
+ if (context !== "sync" && context !== "install") {
37
+ throw new CliSyntaxError("Usage: bonfire context sync [--check] [--root <root>] | bonfire context install [--check] --app-id <app-id> [--root <root>]");
38
+ }
39
+ let root = process.cwd();
40
+ let appId;
41
+ let check = false;
42
+ let rootProvided = false;
43
+ let appIdProvided = false;
44
+ let checkProvided = false;
45
+ for (let index = 2; index < argv.length;) {
46
+ const option = argv[index];
47
+ if (option === "--check") {
48
+ if (checkProvided) {
49
+ throw new CliSyntaxError("The --check option may only be provided once");
50
+ }
51
+ check = true;
52
+ checkProvided = true;
53
+ index += 1;
54
+ continue;
55
+ }
56
+ if (option === "--root") {
57
+ if (rootProvided) {
58
+ throw new CliSyntaxError("The --root option may only be provided once");
59
+ }
60
+ const parsed = parseRootOption(argv, index);
61
+ root = parsed.root;
62
+ rootProvided = true;
63
+ index = parsed.nextIndex;
64
+ continue;
65
+ }
66
+ if (option === "--app-id") {
67
+ if (appIdProvided) {
68
+ throw new CliSyntaxError("The --app-id option may only be provided once");
69
+ }
70
+ const value = argv[index + 1];
71
+ if (!value || value.startsWith("--")) {
72
+ throw new CliSyntaxError("The --app-id option requires a value");
73
+ }
74
+ appId = value;
75
+ appIdProvided = true;
76
+ index += 2;
77
+ continue;
78
+ }
79
+ throw new CliSyntaxError(`Unknown option: ${option}`);
80
+ }
81
+ if (context === "install") {
82
+ if (appId === undefined) {
83
+ throw new CliSyntaxError("Usage: bonfire context install [--check] --app-id <app-id> [--root <root>]");
84
+ }
85
+ return { context, root, appId, check };
86
+ }
87
+ if (appId !== undefined) {
88
+ throw new CliSyntaxError("The --app-id option is only valid for install");
89
+ }
90
+ return { context, root, check };
91
+ }
33
92
  function parseBranchPrepareArgs(argv) {
34
93
  let root = process.cwd();
35
94
  let hostname;
@@ -68,17 +127,85 @@ function parseBranchPrepareArgs(argv) {
68
127
  return { root, hostname };
69
128
  }
70
129
  export function parseArgs(argv) {
130
+ if (argv[0] === "context")
131
+ return parseContextArgs(argv);
71
132
  if (argv[0] === "prepare")
72
133
  return parsePrepareArgs(argv);
73
134
  if (argv[0] === "branch" && argv[1] === "prepare") {
74
135
  return parseBranchPrepareArgs(argv);
75
136
  }
76
- throw new CliSyntaxError("Usage: bonfire prepare [--root <application-root>] | bonfire branch prepare --root <application-root> --hostname <hostname>");
137
+ throw new CliSyntaxError("Usage: bonfire context sync [--check] [--root <root>] | bonfire context install [--check] --app-id <app-id> [--root <root>] | bonfire prepare [--root <application-root>] | bonfire branch prepare --root <application-root> --hostname <hostname>");
138
+ }
139
+ function printContextIssues(result) {
140
+ for (const issue of result.issues) {
141
+ console.error(`- ${issue.kind}: ${issue.path}`);
142
+ }
143
+ }
144
+ function printContextSyncSummary(result) {
145
+ if (result.written.length > 0) {
146
+ console.log(`Written: ${result.written.join(", ")}`);
147
+ }
148
+ if (result.removed.length > 0) {
149
+ console.log(`Removed: ${result.removed.join(", ")}`);
150
+ }
151
+ }
152
+ async function runContextCommand(options, dependencies) {
153
+ if (options.context === "install") {
154
+ if (options.check) {
155
+ const result = await (dependencies.contextInstallCheck ?? checkContextInstallation)({
156
+ repositoryRoot: options.root,
157
+ appId: options.appId,
158
+ });
159
+ if (!result.ok) {
160
+ console.error("Context install check failed:");
161
+ printContextIssues(result);
162
+ return 1;
163
+ }
164
+ console.log("Context install check passed.");
165
+ return 0;
166
+ }
167
+ const result = await (dependencies.contextInstall ?? installContext)({
168
+ repositoryRoot: options.root,
169
+ appId: options.appId,
170
+ });
171
+ const skills = result.skills.map((skill) => `${skill.name} (${skill.status})`);
172
+ const mcp = result.mcp.map((server) => `${server.name} (${server.status})`);
173
+ console.log(skills.length > 0
174
+ ? `Context skills: ${skills.join(", ")}`
175
+ : "No context skills configured.");
176
+ if (mcp.length > 0)
177
+ console.log(`Context MCP: ${mcp.join(", ")}`);
178
+ console.log("Context install complete.");
179
+ return 0;
180
+ }
181
+ if (options.check) {
182
+ const result = await checkContext({ repositoryRoot: options.root });
183
+ if (!result.ok) {
184
+ console.error("Context sync check failed:");
185
+ printContextIssues(result);
186
+ return 1;
187
+ }
188
+ console.log("Context sync check passed.");
189
+ return 0;
190
+ }
191
+ const result = await syncContext({ repositoryRoot: options.root });
192
+ if (!result.ok) {
193
+ console.error("Context sync failed:");
194
+ printContextIssues(result);
195
+ return 1;
196
+ }
197
+ printContextSyncSummary(result);
198
+ console.log("Context sync complete.");
199
+ return 0;
77
200
  }
78
201
  export async function run(argv = process.argv.slice(2), dependencies = {}) {
79
202
  const isBranchPrepare = argv[0] === "branch";
203
+ const isContext = argv[0] === "context";
80
204
  try {
81
205
  const options = parseArgs(argv);
206
+ if ("context" in options) {
207
+ return await runContextCommand(options, dependencies);
208
+ }
82
209
  if ("hostname" in options) {
83
210
  return await runBranchPrepare(options, dependencies);
84
211
  }
@@ -96,6 +223,11 @@ export async function run(argv = process.argv.slice(2), dependencies = {}) {
96
223
  console.error(`bonfire: ${error.message}`);
97
224
  return 2;
98
225
  }
226
+ if (isContext) {
227
+ const message = error instanceof Error ? error.message : "an unknown error occurred";
228
+ console.error(`bonfire context failed: ${message}`);
229
+ return 1;
230
+ }
99
231
  if (isBranchPrepare) {
100
232
  const message = error instanceof BranchPrepareError
101
233
  ? error.message
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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","sourcesContent":["import { prepare, PrepareError } from \"./prepare.js\";\nimport {\n BranchPrepareError,\n runBranchPrepare,\n type BranchPrepareDependencies,\n} from \"./branch-prepare.js\";\n\nexport class CliSyntaxError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliSyntaxError\";\n }\n}\n\nexport type PrepareCommandOptions = {\n root: string;\n};\n\nexport type BranchPrepareCommandOptions = {\n root: string;\n hostname: string;\n};\n\ntype CliCommandOptions = PrepareCommandOptions | BranchPrepareCommandOptions;\n\nfunction parseRootOption(\n argv: readonly string[],\n start: number,\n): { root: string; nextIndex: number } {\n const value = argv[start + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --root option requires a value\");\n }\n return { root: value, nextIndex: start + 2 };\n}\n\nfunction parsePrepareArgs(argv: readonly string[]): PrepareCommandOptions {\n let root = process.cwd();\n let rootProvided = false;\n for (let index = 1; index < argv.length;) {\n if (argv[index] !== \"--root\") {\n throw new CliSyntaxError(`Unknown option: ${argv[index]}`);\n }\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n }\n return { root };\n}\n\nfunction parseBranchPrepareArgs(\n argv: readonly string[],\n): BranchPrepareCommandOptions {\n let root = process.cwd();\n let hostname: string | undefined;\n let rootProvided = false;\n let hostnameProvided = false;\n\n for (let index = 2; index < argv.length;) {\n const option = argv[index];\n if (option === \"--root\") {\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n continue;\n }\n if (option === \"--hostname\") {\n if (hostnameProvided) {\n throw new CliSyntaxError(\n \"The --hostname option may only be provided once\",\n );\n }\n const value = argv[index + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --hostname option requires a value\");\n }\n hostname = value;\n hostnameProvided = true;\n index += 2;\n continue;\n }\n throw new CliSyntaxError(`Unknown option: ${option}`);\n }\n\n if (hostname === undefined) {\n throw new CliSyntaxError(\n \"Usage: bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n }\n return { root, hostname };\n}\n\nexport function parseArgs(argv: readonly string[]): CliCommandOptions {\n if (argv[0] === \"prepare\") return parsePrepareArgs(argv);\n if (argv[0] === \"branch\" && argv[1] === \"prepare\") {\n return parseBranchPrepareArgs(argv);\n }\n throw new CliSyntaxError(\n \"Usage: bonfire prepare [--root <application-root>] | bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n}\n\nexport async function run(\n argv: readonly string[] = process.argv.slice(2),\n dependencies: BranchPrepareDependencies = {},\n): Promise<number> {\n const isBranchPrepare = argv[0] === \"branch\";\n try {\n const options = parseArgs(argv);\n if (\"hostname\" in options) {\n return await runBranchPrepare(options, dependencies);\n }\n\n const result = await prepare(options);\n const descriptions = {\n environment: \"the process environment\",\n existing: \".env.local\",\n generated: \"a newly generated value in .env.local\",\n } as const;\n console.log(\n `Bonfire preparation complete; BF_SESSION_SECRET came from ${descriptions[result.source]}.`,\n );\n return 0;\n } catch (error) {\n if (error instanceof CliSyntaxError) {\n console.error(`bonfire: ${error.message}`);\n return 2;\n }\n if (isBranchPrepare) {\n const message =\n error instanceof BranchPrepareError\n ? error.message\n : \"Unable to load branch preparation configuration.\";\n console.error(`bonfire branch prepare failed: ${message}`);\n return 1;\n }\n\n const message =\n error instanceof PrepareError || error instanceof Error\n ? error.message\n : \"an unknown error occurred\";\n console.error(`bonfire prepare failed: ${message}`);\n return 1;\n }\n}\n"]}
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n checkContext,\n checkContextInstallation,\n installContext,\n syncContext,\n type ContextInstallCheckResult,\n type ContextInstallResult,\n type ContextInstallOptions,\n type ContextSyncResult,\n} from \"@ebay-dt/bonfire-context\";\nimport { prepare, PrepareError } from \"./prepare.js\";\nimport {\n BranchPrepareError,\n runBranchPrepare,\n type BranchPrepareDependencies,\n} from \"./branch-prepare.js\";\n\nexport class CliSyntaxError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CliSyntaxError\";\n }\n}\n\nexport type PrepareCommandOptions = {\n root: string;\n};\n\nexport type BranchPrepareCommandOptions = {\n root: string;\n hostname: string;\n};\n\nexport type ContextCommandOptions =\n | {\n context: \"sync\";\n root: string;\n check: boolean;\n }\n | {\n context: \"install\";\n root: string;\n appId: string;\n check: boolean;\n };\n\ntype CliCommandOptions =\n PrepareCommandOptions | BranchPrepareCommandOptions | ContextCommandOptions;\n\nexport type CliDependencies = BranchPrepareDependencies & {\n contextInstall?: (\n options: ContextInstallOptions,\n ) => Promise<ContextInstallResult>;\n contextInstallCheck?: (\n options: ContextInstallOptions,\n ) => Promise<ContextInstallCheckResult>;\n};\n\nfunction parseRootOption(\n argv: readonly string[],\n start: number,\n): { root: string; nextIndex: number } {\n const value = argv[start + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --root option requires a value\");\n }\n return { root: value, nextIndex: start + 2 };\n}\n\nfunction parsePrepareArgs(argv: readonly string[]): PrepareCommandOptions {\n let root = process.cwd();\n let rootProvided = false;\n for (let index = 1; index < argv.length;) {\n if (argv[index] !== \"--root\") {\n throw new CliSyntaxError(`Unknown option: ${argv[index]}`);\n }\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n }\n return { root };\n}\n\nfunction parseContextArgs(argv: readonly string[]): ContextCommandOptions {\n const context = argv[1];\n if (context !== \"sync\" && context !== \"install\") {\n throw new CliSyntaxError(\n \"Usage: bonfire context sync [--check] [--root <root>] | bonfire context install [--check] --app-id <app-id> [--root <root>]\",\n );\n }\n\n let root = process.cwd();\n let appId: string | undefined;\n let check = false;\n let rootProvided = false;\n let appIdProvided = false;\n let checkProvided = false;\n\n for (let index = 2; index < argv.length;) {\n const option = argv[index];\n if (option === \"--check\") {\n if (checkProvided) {\n throw new CliSyntaxError(\n \"The --check option may only be provided once\",\n );\n }\n check = true;\n checkProvided = true;\n index += 1;\n continue;\n }\n if (option === \"--root\") {\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n continue;\n }\n if (option === \"--app-id\") {\n if (appIdProvided) {\n throw new CliSyntaxError(\n \"The --app-id option may only be provided once\",\n );\n }\n const value = argv[index + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --app-id option requires a value\");\n }\n appId = value;\n appIdProvided = true;\n index += 2;\n continue;\n }\n throw new CliSyntaxError(`Unknown option: ${option}`);\n }\n\n if (context === \"install\") {\n if (appId === undefined) {\n throw new CliSyntaxError(\n \"Usage: bonfire context install [--check] --app-id <app-id> [--root <root>]\",\n );\n }\n return { context, root, appId, check };\n }\n if (appId !== undefined) {\n throw new CliSyntaxError(\"The --app-id option is only valid for install\");\n }\n return { context, root, check };\n}\n\nfunction parseBranchPrepareArgs(\n argv: readonly string[],\n): BranchPrepareCommandOptions {\n let root = process.cwd();\n let hostname: string | undefined;\n let rootProvided = false;\n let hostnameProvided = false;\n\n for (let index = 2; index < argv.length;) {\n const option = argv[index];\n if (option === \"--root\") {\n if (rootProvided) {\n throw new CliSyntaxError(\"The --root option may only be provided once\");\n }\n const parsed = parseRootOption(argv, index);\n root = parsed.root;\n rootProvided = true;\n index = parsed.nextIndex;\n continue;\n }\n if (option === \"--hostname\") {\n if (hostnameProvided) {\n throw new CliSyntaxError(\n \"The --hostname option may only be provided once\",\n );\n }\n const value = argv[index + 1];\n if (!value || value.startsWith(\"--\")) {\n throw new CliSyntaxError(\"The --hostname option requires a value\");\n }\n hostname = value;\n hostnameProvided = true;\n index += 2;\n continue;\n }\n throw new CliSyntaxError(`Unknown option: ${option}`);\n }\n\n if (hostname === undefined) {\n throw new CliSyntaxError(\n \"Usage: bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n }\n return { root, hostname };\n}\n\nexport function parseArgs(argv: readonly string[]): CliCommandOptions {\n if (argv[0] === \"context\") return parseContextArgs(argv);\n if (argv[0] === \"prepare\") return parsePrepareArgs(argv);\n if (argv[0] === \"branch\" && argv[1] === \"prepare\") {\n return parseBranchPrepareArgs(argv);\n }\n throw new CliSyntaxError(\n \"Usage: bonfire context sync [--check] [--root <root>] | bonfire context install [--check] --app-id <app-id> [--root <root>] | bonfire prepare [--root <application-root>] | bonfire branch prepare --root <application-root> --hostname <hostname>\",\n );\n}\n\nfunction printContextIssues(result: {\n issues: readonly { kind: string; path: string }[];\n}) {\n for (const issue of result.issues) {\n console.error(`- ${issue.kind}: ${issue.path}`);\n }\n}\n\nfunction printContextSyncSummary(result: ContextSyncResult) {\n if (result.written.length > 0) {\n console.log(`Written: ${result.written.join(\", \")}`);\n }\n if (result.removed.length > 0) {\n console.log(`Removed: ${result.removed.join(\", \")}`);\n }\n}\n\nasync function runContextCommand(\n options: ContextCommandOptions,\n dependencies: CliDependencies,\n): Promise<number> {\n if (options.context === \"install\") {\n if (options.check) {\n const result = await (\n dependencies.contextInstallCheck ?? checkContextInstallation\n )({\n repositoryRoot: options.root,\n appId: options.appId,\n });\n if (!result.ok) {\n console.error(\"Context install check failed:\");\n printContextIssues(result);\n return 1;\n }\n console.log(\"Context install check passed.\");\n return 0;\n }\n const result = await (dependencies.contextInstall ?? installContext)({\n repositoryRoot: options.root,\n appId: options.appId,\n });\n const skills = result.skills.map(\n (skill) => `${skill.name} (${skill.status})`,\n );\n const mcp = result.mcp.map((server) => `${server.name} (${server.status})`);\n console.log(\n skills.length > 0\n ? `Context skills: ${skills.join(\", \")}`\n : \"No context skills configured.\",\n );\n if (mcp.length > 0) console.log(`Context MCP: ${mcp.join(\", \")}`);\n console.log(\"Context install complete.\");\n return 0;\n }\n\n if (options.check) {\n const result = await checkContext({ repositoryRoot: options.root });\n if (!result.ok) {\n console.error(\"Context sync check failed:\");\n printContextIssues(result);\n return 1;\n }\n console.log(\"Context sync check passed.\");\n return 0;\n }\n\n const result = await syncContext({ repositoryRoot: options.root });\n if (!result.ok) {\n console.error(\"Context sync failed:\");\n printContextIssues(result);\n return 1;\n }\n printContextSyncSummary(result);\n console.log(\"Context sync complete.\");\n return 0;\n}\n\nexport async function run(\n argv: readonly string[] = process.argv.slice(2),\n dependencies: CliDependencies = {},\n): Promise<number> {\n const isBranchPrepare = argv[0] === \"branch\";\n const isContext = argv[0] === \"context\";\n try {\n const options = parseArgs(argv);\n if (\"context\" in options) {\n return await runContextCommand(options, dependencies);\n }\n if (\"hostname\" in options) {\n return await runBranchPrepare(options, dependencies);\n }\n\n const result = await prepare(options);\n const descriptions = {\n environment: \"the process environment\",\n existing: \".env.local\",\n generated: \"a newly generated value in .env.local\",\n } as const;\n console.log(\n `Bonfire preparation complete; BF_SESSION_SECRET came from ${descriptions[result.source]}.`,\n );\n return 0;\n } catch (error) {\n if (error instanceof CliSyntaxError) {\n console.error(`bonfire: ${error.message}`);\n return 2;\n }\n if (isContext) {\n const message =\n error instanceof Error ? error.message : \"an unknown error occurred\";\n console.error(`bonfire context failed: ${message}`);\n return 1;\n }\n if (isBranchPrepare) {\n const message =\n error instanceof BranchPrepareError\n ? error.message\n : \"Unable to load branch preparation configuration.\";\n console.error(`bonfire branch prepare failed: ${message}`);\n return 1;\n }\n\n const message =\n error instanceof PrepareError || error instanceof Error\n ? error.message\n : \"an unknown error occurred\";\n console.error(`bonfire prepare failed: ${message}`);\n return 1;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ebay-dt/bonfire-cli",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
4
4
  "description": "The Bonfire command-line tool.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,9 +30,10 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
+ "@ebay-dt/bonfire-context": "0.1.0-alpha.4",
33
34
  "@next/env": "16.3.4",
34
- "@ebay-dt/bonfire-core": "0.1.0-alpha.3",
35
- "@ebay-dt/bonfire-node": "0.1.0-alpha.3"
35
+ "@ebay-dt/bonfire-core": "0.1.0-alpha.4",
36
+ "@ebay-dt/bonfire-node": "0.1.0-alpha.4"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@repo/eslint-config": "0.0.0",