@zuplo/cli 7.9.12 → 7.9.13

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.
Files changed (51) hide show
  1. package/dist/__tests__/integration/source-upgrade.integration.test.d.ts +2 -0
  2. package/dist/__tests__/integration/source-upgrade.integration.test.d.ts.map +1 -0
  3. package/dist/__tests__/integration/source-upgrade.integration.test.js +100 -0
  4. package/dist/__tests__/integration/source-upgrade.integration.test.js.map +1 -0
  5. package/dist/cmds/source/upgrade.d.ts.map +1 -1
  6. package/dist/cmds/source/upgrade.js +45 -2
  7. package/dist/cmds/source/upgrade.js.map +1 -1
  8. package/dist/source/ai-gateway/catalog.json +411 -0
  9. package/dist/source/ai-gateway/files.d.ts +16 -0
  10. package/dist/source/ai-gateway/files.d.ts.map +1 -0
  11. package/dist/source/ai-gateway/files.js +174 -0
  12. package/dist/source/ai-gateway/files.js.map +1 -0
  13. package/dist/source/ai-gateway/files.test.d.ts +2 -0
  14. package/dist/source/ai-gateway/files.test.d.ts.map +1 -0
  15. package/dist/source/ai-gateway/files.test.js +135 -0
  16. package/dist/source/ai-gateway/files.test.js.map +1 -0
  17. package/dist/source/ai-gateway/handler.d.ts +31 -0
  18. package/dist/source/ai-gateway/handler.d.ts.map +1 -0
  19. package/dist/source/ai-gateway/handler.js +140 -0
  20. package/dist/source/ai-gateway/handler.js.map +1 -0
  21. package/dist/source/ai-gateway/handler.test.d.ts +2 -0
  22. package/dist/source/ai-gateway/handler.test.d.ts.map +1 -0
  23. package/dist/source/ai-gateway/handler.test.js +113 -0
  24. package/dist/source/ai-gateway/handler.test.js.map +1 -0
  25. package/dist/source/ai-gateway/package.test.d.ts +2 -0
  26. package/dist/source/ai-gateway/package.test.d.ts.map +1 -0
  27. package/dist/source/ai-gateway/package.test.js +30 -0
  28. package/dist/source/ai-gateway/package.test.js.map +1 -0
  29. package/dist/source/ai-gateway/planner.d.ts +132 -0
  30. package/dist/source/ai-gateway/planner.d.ts.map +1 -0
  31. package/dist/source/ai-gateway/planner.js +365 -0
  32. package/dist/source/ai-gateway/planner.js.map +1 -0
  33. package/dist/source/ai-gateway/planner.test.d.ts +2 -0
  34. package/dist/source/ai-gateway/planner.test.d.ts.map +1 -0
  35. package/dist/source/ai-gateway/planner.test.js +282 -0
  36. package/dist/source/ai-gateway/planner.test.js.map +1 -0
  37. package/dist/source/ai-gateway/release.d.ts +19 -0
  38. package/dist/source/ai-gateway/release.d.ts.map +1 -0
  39. package/dist/source/ai-gateway/release.js +75 -0
  40. package/dist/source/ai-gateway/release.js.map +1 -0
  41. package/dist/source/ai-gateway/release.test.d.ts +2 -0
  42. package/dist/source/ai-gateway/release.test.d.ts.map +1 -0
  43. package/dist/source/ai-gateway/release.test.js +62 -0
  44. package/dist/source/ai-gateway/release.test.js.map +1 -0
  45. package/dist/tsconfig.tsbuildinfo +1 -1
  46. package/node_modules/@zuplo/core/package.json +1 -1
  47. package/node_modules/@zuplo/graphql/package.json +1 -1
  48. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  49. package/node_modules/@zuplo/otel/package.json +1 -1
  50. package/node_modules/@zuplo/runtime/package.json +1 -1
  51. package/package.json +11 -11
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=source-upgrade.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-upgrade.integration.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/source-upgrade.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,100 @@
1
+ import yargs from "yargs/yargs";
2
+ import upgrade from "../../cmds/source/upgrade.js";
3
+ import { shutdownAnalytics } from "../../common/analytics/lib.js";
4
+ import { upgradeGateway } from "../../source/ai-gateway/handler.js";
5
+ import { update } from "../../source/update/handler.js";
6
+ jest.mock("../../source/update/handler.js", () => ({
7
+ update: jest.fn().mockResolvedValue(undefined),
8
+ }));
9
+ jest.mock("../../source/ai-gateway/handler.js", () => ({
10
+ upgradeGateway: jest.fn().mockResolvedValue(0),
11
+ }));
12
+ jest.mock("../../common/analytics/lib.js", () => ({
13
+ captureEvent: jest.fn().mockResolvedValue(undefined),
14
+ shutdownAnalytics: jest.fn().mockResolvedValue(undefined),
15
+ }));
16
+ jest.mock("../../common/middleware/user-identification.js", () => ({
17
+ identify: jest.fn(),
18
+ }));
19
+ jest.mock("../../common/validators/file-system-validator.js", () => ({
20
+ ZuploProjectValidator: jest.fn().mockImplementation(() => ({
21
+ validate: jest.fn().mockResolvedValue({ ok: true }),
22
+ })),
23
+ }));
24
+ const originalArgv = process.argv;
25
+ const originalEnv = { ...process.env };
26
+ afterEach(() => {
27
+ process.argv = originalArgv;
28
+ for (const key of Object.keys(process.env))
29
+ if (!(key in originalEnv))
30
+ delete process.env[key];
31
+ Object.assign(process.env, originalEnv);
32
+ jest.clearAllMocks();
33
+ });
34
+ async function run(args) {
35
+ process.argv = ["node", "zuplo", "source", ...args];
36
+ return yargs(args)
37
+ .env("ZUPLO")
38
+ .option("prompt", { type: "boolean", default: true })
39
+ .command(upgrade)
40
+ .exitProcess(false)
41
+ .fail((message, error) => {
42
+ throw error ?? new Error(message);
43
+ })
44
+ .parseAsync();
45
+ }
46
+ describe("source upgrade command compatibility", () => {
47
+ it("preserves the existing invocation and explicit api type", async () => {
48
+ await run(["upgrade"]);
49
+ expect(update).toHaveBeenCalledWith(expect.objectContaining({ dir: ".", prompt: true }));
50
+ expect(upgradeGateway).not.toHaveBeenCalled();
51
+ await run(["upgrade", "--type", "api"]);
52
+ expect(update).toHaveBeenCalledTimes(2);
53
+ });
54
+ it.each([["--type", "ai-gateway"], ["--type=ai-gateway"]])("routes type spelling %j to preview only", async (...args) => {
55
+ await run(["upgrade", ...args]);
56
+ expect(upgradeGateway).toHaveBeenCalledWith(expect.objectContaining({ type: "ai-gateway", apply: false }));
57
+ expect(update).not.toHaveBeenCalled();
58
+ });
59
+ it("supports the type environment variable without enabling application", async () => {
60
+ process.env.ZUPLO_TYPE = "ai-gateway";
61
+ await run(["upgrade"]);
62
+ expect(upgradeGateway).toHaveBeenCalledWith(expect.objectContaining({ apply: false }));
63
+ });
64
+ it.each(["--apply", "--apply=true"])("accepts explicit %s and noninteractive confirmation", async (apply) => {
65
+ await run(["upgrade", "--type=ai-gateway", apply, "--prompt=false"]);
66
+ expect(upgradeGateway).toHaveBeenCalledWith(expect.objectContaining({ apply: true, prompt: false }));
67
+ });
68
+ it("rejects an environment-only apply and unsupported types", async () => {
69
+ process.env.ZUPLO_APPLY = "true";
70
+ await expect(run(["upgrade", "--type", "ai-gateway"])).rejects.toThrow(/explicitly supplied/);
71
+ delete process.env.ZUPLO_APPLY;
72
+ await expect(run(["upgrade", "--type", "unknown"])).rejects.toThrow();
73
+ await expect(run(["upgrade", "--apply"])).rejects.toThrow(/requires --type/);
74
+ expect(update).not.toHaveBeenCalled();
75
+ expect(upgradeGateway).not.toHaveBeenCalled();
76
+ });
77
+ it("keeps existing dir and prompt flag spellings", async () => {
78
+ for (const args of [
79
+ ["--dir", "./example", "--prompt", "false"],
80
+ ["--dir=./example", "--prompt=false"],
81
+ ]) {
82
+ await run(["upgrade", ...args]);
83
+ expect(update).toHaveBeenLastCalledWith(expect.objectContaining({ dir: "example", prompt: false }));
84
+ }
85
+ });
86
+ it.each([false, true])("preserves the blocked exit code with analytics rejection=%s", async (reject) => {
87
+ if (reject)
88
+ jest
89
+ .mocked(shutdownAnalytics)
90
+ .mockRejectedValueOnce(new Error("analytics failed"));
91
+ jest.mocked(upgradeGateway).mockResolvedValueOnce(2);
92
+ const exit = jest.spyOn(process, "exit").mockImplementation(() => {
93
+ throw new Error("exit");
94
+ });
95
+ await expect(run(["upgrade", "--type=ai-gateway"])).rejects.toThrow("exit");
96
+ expect(exit).toHaveBeenCalledWith(2);
97
+ exit.mockRestore();
98
+ });
99
+ });
100
+ //# sourceMappingURL=source-upgrade.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-upgrade.integration.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/source-upgrade.integration.test.ts"],"names":[],"mappings":"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","sourcesContent":["import yargs from \"yargs/yargs\";\nimport upgrade from \"../../cmds/source/upgrade.js\";\nimport { shutdownAnalytics } from \"../../common/analytics/lib.js\";\nimport { upgradeGateway } from \"../../source/ai-gateway/handler.js\";\nimport { update } from \"../../source/update/handler.js\";\n\njest.mock(\"../../source/update/handler.js\", () => ({\n update: jest.fn().mockResolvedValue(undefined),\n}));\njest.mock(\"../../source/ai-gateway/handler.js\", () => ({\n upgradeGateway: jest.fn().mockResolvedValue(0),\n}));\njest.mock(\"../../common/analytics/lib.js\", () => ({\n captureEvent: jest.fn().mockResolvedValue(undefined),\n shutdownAnalytics: jest.fn().mockResolvedValue(undefined),\n}));\njest.mock(\"../../common/middleware/user-identification.js\", () => ({\n identify: jest.fn(),\n}));\njest.mock(\"../../common/validators/file-system-validator.js\", () => ({\n ZuploProjectValidator: jest.fn().mockImplementation(() => ({\n validate: jest.fn().mockResolvedValue({ ok: true }),\n })),\n}));\n\nconst originalArgv = process.argv;\nconst originalEnv = { ...process.env };\nafterEach(() => {\n process.argv = originalArgv;\n for (const key of Object.keys(process.env))\n if (!(key in originalEnv)) delete process.env[key];\n Object.assign(process.env, originalEnv);\n jest.clearAllMocks();\n});\nasync function run(args: string[]) {\n process.argv = [\"node\", \"zuplo\", \"source\", ...args];\n return yargs(args)\n .env(\"ZUPLO\")\n .option(\"prompt\", { type: \"boolean\", default: true })\n .command(upgrade)\n .exitProcess(false)\n .fail((message, error) => {\n throw error ?? new Error(message);\n })\n .parseAsync();\n}\n\ndescribe(\"source upgrade command compatibility\", () => {\n it(\"preserves the existing invocation and explicit api type\", async () => {\n await run([\"upgrade\"]);\n expect(update).toHaveBeenCalledWith(\n expect.objectContaining({ dir: \".\", prompt: true })\n );\n expect(upgradeGateway).not.toHaveBeenCalled();\n await run([\"upgrade\", \"--type\", \"api\"]);\n expect(update).toHaveBeenCalledTimes(2);\n });\n it.each([[\"--type\", \"ai-gateway\"], [\"--type=ai-gateway\"]])(\n \"routes type spelling %j to preview only\",\n async (...args) => {\n await run([\"upgrade\", ...args]);\n expect(upgradeGateway).toHaveBeenCalledWith(\n expect.objectContaining({ type: \"ai-gateway\", apply: false })\n );\n expect(update).not.toHaveBeenCalled();\n }\n );\n it(\"supports the type environment variable without enabling application\", async () => {\n process.env.ZUPLO_TYPE = \"ai-gateway\";\n await run([\"upgrade\"]);\n expect(upgradeGateway).toHaveBeenCalledWith(\n expect.objectContaining({ apply: false })\n );\n });\n it.each([\"--apply\", \"--apply=true\"])(\n \"accepts explicit %s and noninteractive confirmation\",\n async (apply) => {\n await run([\"upgrade\", \"--type=ai-gateway\", apply, \"--prompt=false\"]);\n expect(upgradeGateway).toHaveBeenCalledWith(\n expect.objectContaining({ apply: true, prompt: false })\n );\n }\n );\n it(\"rejects an environment-only apply and unsupported types\", async () => {\n process.env.ZUPLO_APPLY = \"true\";\n await expect(run([\"upgrade\", \"--type\", \"ai-gateway\"])).rejects.toThrow(\n /explicitly supplied/\n );\n delete process.env.ZUPLO_APPLY;\n await expect(run([\"upgrade\", \"--type\", \"unknown\"])).rejects.toThrow();\n await expect(run([\"upgrade\", \"--apply\"])).rejects.toThrow(\n /requires --type/\n );\n expect(update).not.toHaveBeenCalled();\n expect(upgradeGateway).not.toHaveBeenCalled();\n });\n it(\"keeps existing dir and prompt flag spellings\", async () => {\n for (const args of [\n [\"--dir\", \"./example\", \"--prompt\", \"false\"],\n [\"--dir=./example\", \"--prompt=false\"],\n ]) {\n await run([\"upgrade\", ...args]);\n expect(update).toHaveBeenLastCalledWith(\n expect.objectContaining({ dir: \"example\", prompt: false })\n );\n }\n });\n it.each([false, true])(\n \"preserves the blocked exit code with analytics rejection=%s\",\n async (reject) => {\n if (reject)\n jest\n .mocked(shutdownAnalytics)\n .mockRejectedValueOnce(new Error(\"analytics failed\"));\n jest.mocked(upgradeGateway).mockResolvedValueOnce(2);\n const exit = jest.spyOn(process, \"exit\").mockImplementation(() => {\n throw new Error(\"exit\");\n });\n await expect(run([\"upgrade\", \"--type=ai-gateway\"])).rejects.toThrow(\n \"exit\"\n );\n expect(exit).toHaveBeenCalledWith(2);\n exit.mockRestore();\n }\n );\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../../src/cmds/source/upgrade.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAUV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBA2Bf,OAAO;;AA9B/B,wBAkCE"}
1
+ {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../../src/cmds/source/upgrade.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAWV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAgEf,OAAO;;AAnE/B,wBAiFE"}
@@ -1,7 +1,8 @@
1
- import { captureEvent } from "../../common/analytics/lib.js";
1
+ import { captureEvent, shutdownAnalytics } from "../../common/analytics/lib.js";
2
2
  import { identify } from "../../common/middleware/user-identification.js";
3
3
  import { ZuploProjectValidator } from "../../common/validators/file-system-validator.js";
4
4
  import { YargsChecker } from "../../common/validators/lib.js";
5
+ import { upgradeGateway } from "../../source/ai-gateway/handler.js";
5
6
  import { update } from "../../source/update/handler.js";
6
7
  export default {
7
8
  desc: "Updates your project structure to the latest conventions",
@@ -9,6 +10,17 @@ export default {
9
10
  builder: (yargs) => {
10
11
  return yargs
11
12
  .usage("$0 source upgrade [options]")
13
+ .option("type", {
14
+ type: "string",
15
+ choices: ["api", "ai-gateway"],
16
+ default: "api",
17
+ describe: "Upgrade project scaffolding (api) or preview AI Gateway template additions",
18
+ })
19
+ .option("apply", {
20
+ type: "boolean",
21
+ default: false,
22
+ describe: "Apply verified AI Gateway additions after preview and confirmation",
23
+ })
12
24
  .option("dir", {
13
25
  type: "string",
14
26
  describe: "The directory containing your Zuplo API",
@@ -25,15 +37,46 @@ export default {
25
37
  "$0 source upgrade --dir ./my-zuplo-project",
26
38
  "Specify the project directory path",
27
39
  ],
40
+ [
41
+ "$0 source upgrade --type ai-gateway",
42
+ "Preview versioned AI Gateway additions without changing files",
43
+ ],
44
+ [
45
+ "$0 source upgrade --type ai-gateway --apply",
46
+ "Validate, preview, and confirm AI Gateway additions",
47
+ ],
28
48
  ])
29
49
  .middleware([identify])
30
50
  .check(async (argv) => {
51
+ if (typeof argv.type !== "string" || typeof argv.apply !== "boolean") {
52
+ throw new Error("Supply --type and --apply at most once.");
53
+ }
54
+ if (argv.apply && argv.type !== "ai-gateway") {
55
+ throw new Error("--apply requires --type ai-gateway.");
56
+ }
57
+ if (argv.apply &&
58
+ !process.argv.some((arg) => arg === "--apply" || arg === "--apply=true")) {
59
+ throw new Error("Applying an upgrade requires an explicitly supplied --apply flag; ZUPLO_APPLY cannot enable writes.");
60
+ }
31
61
  return await new YargsChecker(new ZuploProjectValidator()).check(argv);
32
62
  });
33
63
  },
34
64
  handler: async (argv) => {
35
65
  await captureEvent({ argv, event: "zuplo source upgrade" });
36
- await update(argv);
66
+ const args = argv;
67
+ if (args.type === "ai-gateway") {
68
+ const exitCode = await upgradeGateway(args);
69
+ if (exitCode !== 0) {
70
+ try {
71
+ await shutdownAnalytics();
72
+ }
73
+ finally {
74
+ process.exit(exitCode);
75
+ }
76
+ }
77
+ }
78
+ else
79
+ await update(args);
37
80
  },
38
81
  };
39
82
  //# sourceMappingURL=upgrade.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../../src/cmds/source/upgrade.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kDAAkD,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAa,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAEnE,eAAe;IACb,IAAI,EAAE,0DAA0D;IAChE,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,6BAA6B,CAAC;aACpC,MAAM,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,yCAAyC;YACnD,OAAO,EAAE,GAAG;YACZ,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,IAAI;SACb,CAAC;aACD,OAAO,CAAC;YACP;gBACE,mBAAmB;gBACnB,0DAA0D;aAC3D;YACD;gBACE,4CAA4C;gBAC5C,oCAAoC;aACrC;SACF,CAAC;aACD,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC;aACtB,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACpB,OAAO,MAAM,IAAI,YAAY,CAC3B,IAAI,qBAAqB,EAAE,CAC5B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QAC5D,MAAM,MAAM,CAAC,IAAiB,CAAC,CAAC;IAClC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { identify } from \"../../common/middleware/user-identification.js\";\nimport { ZuploProjectValidator } from \"../../common/validators/file-system-validator.js\";\nimport { YargsChecker } from \"../../common/validators/lib.js\";\nimport { Arguments, update } from \"../../source/update/handler.js\";\n\nexport default {\n desc: \"Updates your project structure to the latest conventions\",\n command: \"upgrade\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 source upgrade [options]\")\n .option(\"dir\", {\n type: \"string\",\n describe: \"The directory containing your Zuplo API\",\n default: \".\",\n normalize: true,\n hidden: true,\n })\n .example([\n [\n \"$0 source upgrade\",\n \"Upgrade your project structure to the latest conventions\",\n ],\n [\n \"$0 source upgrade --dir ./my-zuplo-project\",\n \"Specify the project directory path\",\n ],\n ])\n .middleware([identify])\n .check(async (argv) => {\n return await new YargsChecker<typeof argv>(\n new ZuploProjectValidator()\n ).check(argv);\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo source upgrade\" });\n await update(argv as Arguments);\n },\n};\n"]}
1
+ {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../../src/cmds/source/upgrade.ts"],"names":[],"mappings":"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","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent, shutdownAnalytics } from \"../../common/analytics/lib.js\";\nimport { identify } from \"../../common/middleware/user-identification.js\";\nimport { ZuploProjectValidator } from \"../../common/validators/file-system-validator.js\";\nimport { YargsChecker } from \"../../common/validators/lib.js\";\nimport { upgradeGateway } from \"../../source/ai-gateway/handler.js\";\nimport { Arguments, update } from \"../../source/update/handler.js\";\n\nexport default {\n desc: \"Updates your project structure to the latest conventions\",\n command: \"upgrade\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 source upgrade [options]\")\n .option(\"type\", {\n type: \"string\",\n choices: [\"api\", \"ai-gateway\"],\n default: \"api\",\n describe:\n \"Upgrade project scaffolding (api) or preview AI Gateway template additions\",\n })\n .option(\"apply\", {\n type: \"boolean\",\n default: false,\n describe:\n \"Apply verified AI Gateway additions after preview and confirmation\",\n })\n .option(\"dir\", {\n type: \"string\",\n describe: \"The directory containing your Zuplo API\",\n default: \".\",\n normalize: true,\n hidden: true,\n })\n .example([\n [\n \"$0 source upgrade\",\n \"Upgrade your project structure to the latest conventions\",\n ],\n [\n \"$0 source upgrade --dir ./my-zuplo-project\",\n \"Specify the project directory path\",\n ],\n [\n \"$0 source upgrade --type ai-gateway\",\n \"Preview versioned AI Gateway additions without changing files\",\n ],\n [\n \"$0 source upgrade --type ai-gateway --apply\",\n \"Validate, preview, and confirm AI Gateway additions\",\n ],\n ])\n .middleware([identify])\n .check(async (argv) => {\n if (typeof argv.type !== \"string\" || typeof argv.apply !== \"boolean\") {\n throw new Error(\"Supply --type and --apply at most once.\");\n }\n if (argv.apply && argv.type !== \"ai-gateway\") {\n throw new Error(\"--apply requires --type ai-gateway.\");\n }\n if (\n argv.apply &&\n !process.argv.some(\n (arg) => arg === \"--apply\" || arg === \"--apply=true\"\n )\n ) {\n throw new Error(\n \"Applying an upgrade requires an explicitly supplied --apply flag; ZUPLO_APPLY cannot enable writes.\"\n );\n }\n return await new YargsChecker<typeof argv>(\n new ZuploProjectValidator()\n ).check(argv);\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo source upgrade\" });\n const args = argv as Arguments & { type?: string; apply?: boolean };\n if (args.type === \"ai-gateway\") {\n const exitCode = await upgradeGateway(args);\n if (exitCode !== 0) {\n try {\n await shutdownAnalytics();\n } finally {\n process.exit(exitCode);\n }\n }\n } else await update(args);\n },\n};\n"]}