@zuplo/cli 6.64.12 → 6.64.14

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.
@@ -1 +1 @@
1
- {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../../src/cmds/open-api/convert.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAOV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBA8Ef,OAAO;;AAjF/B,wBAqFE"}
1
+ {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../../src/cmds/open-api/convert.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAOV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAuFf,OAAO;;AA1F/B,wBA8FE"}
@@ -36,6 +36,11 @@ export default {
36
36
  alias: "o",
37
37
  describe: "Output file path (if not specified, generates based on input)",
38
38
  normalize: true,
39
+ })
40
+ .option("watch", {
41
+ type: "boolean",
42
+ describe: "Watch input file for changes and automatically re-convert",
43
+ default: false,
39
44
  })
40
45
  .example([
41
46
  [
@@ -50,6 +55,10 @@ export default {
50
55
  "$0 oas convert --input api.yaml --format json",
51
56
  "Convert using --format flag instead of --json/--yaml",
52
57
  ],
58
+ [
59
+ "$0 oas convert --input openapi.yaml --json --watch",
60
+ "Watch the input file for changes and automatically re-convert",
61
+ ],
53
62
  ])
54
63
  .check((argv) => {
55
64
  if (!argv.input) {
@@ -1 +1 @@
1
- {"version":3,"file":"convert.js","sourceRoot":"","sources":["../../../src/cmds/open-api/convert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAa,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAE9E,eAAe;IACb,IAAI,EAAE,qDAAqD;IAC3D,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CACJ,2EAA2E,CAC5E;aACA,MAAM,CAAC,OAAO,EAAE;YACf,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,uCAAuC;YACjD,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,IAAI;SACnB,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,eAAe;YACzB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;SAC1B,CAAC;aACD,MAAM,CAAC,MAAM,EAAE;YACd,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,wBAAwB;YAClC,SAAS,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;SAC9B,CAAC;aACD,MAAM,CAAC,MAAM,EAAE;YACd,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,wBAAwB;YAClC,SAAS,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;SAC9B,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ,EACN,+DAA+D;YACjE,SAAS,EAAE,IAAI;SAChB,CAAC;aACD,OAAO,CAAC;YACP;gBACE,4CAA4C;gBAC5C,4CAA4C;aAC7C;YACD;gBACE,wDAAwD;gBACxD,6DAA6D;aAC9D;YACD;gBACE,+CAA+C;gBAC/C,sDAAsD;aACvD;SACF,CAAC;aACD,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;YACd,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC5C,CAAC;YAGD,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YACnD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC,WAAW,EAAE,CAAC;YAC7D,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CACb,iCAAiC,GAAG,iCAAiC,CACtE,CAAC;YACJ,CAAC;YAGD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAe,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;YACzD,CAAC;YAGD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC7C,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACzD,MAAM,cAAc,CAAC,IAAiB,CAAC,CAAC;IAC1C,CAAC;CACF,CAAC","sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { Arguments, convertOpenAPI } from \"../../open-api/convert/handler.js\";\n\nexport default {\n desc: \"Convert OpenAPI files between JSON and YAML formats\",\n command: \"convert\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\n \"$0 oas convert --input <file> (--json|--yaml|--format <format>) [options]\"\n )\n .option(\"input\", {\n type: \"string\",\n alias: \"i\",\n describe: \"The input OpenAPI file (JSON or YAML)\",\n normalize: true,\n demandOption: true,\n })\n .option(\"format\", {\n type: \"string\",\n alias: \"f\",\n describe: \"Output format\",\n choices: [\"json\", \"yaml\"],\n })\n .option(\"json\", {\n type: \"boolean\",\n describe: \"Convert to JSON format\",\n conflicts: [\"yaml\", \"format\"],\n })\n .option(\"yaml\", {\n type: \"boolean\",\n describe: \"Convert to YAML format\",\n conflicts: [\"json\", \"format\"],\n })\n .option(\"output\", {\n type: \"string\",\n alias: \"o\",\n describe:\n \"Output file path (if not specified, generates based on input)\",\n normalize: true,\n })\n .example([\n [\n \"$0 oas convert --input openapi.yaml --json\",\n \"Convert a YAML OpenAPI file to JSON format\",\n ],\n [\n \"$0 oas convert -i openapi.json --yaml -o api-spec.yaml\",\n \"Convert a JSON OpenAPI file to YAML with custom output path\",\n ],\n [\n \"$0 oas convert --input api.yaml --format json\",\n \"Convert using --format flag instead of --json/--yaml\",\n ],\n ])\n .check((argv) => {\n if (!argv.input) {\n throw new Error(\"Input file is required\");\n }\n\n // Validate file extension\n const validExtensions = [\".json\", \".yaml\", \".yml\"];\n const ext = path.extname(argv.input as string).toLowerCase();\n if (!validExtensions.includes(ext)) {\n throw new Error(\n `Invalid input file extension: ${ext}. Must be .json, .yaml, or .yml`\n );\n }\n\n // Validate input file exists\n if (!fs.existsSync(argv.input as string)) {\n throw new Error(`Input file not found: ${argv.input}`);\n }\n\n // Validate output format is specified\n if (!argv.format && !argv.json && !argv.yaml) {\n throw new Error(\n \"Output format must be specified using --format, --json, or --yaml\"\n );\n }\n\n return true;\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo oas convert\" });\n await convertOpenAPI(argv as Arguments);\n },\n};\n"]}
1
+ {"version":3,"file":"convert.js","sourceRoot":"","sources":["../../../src/cmds/open-api/convert.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { Arguments, convertOpenAPI } from \"../../open-api/convert/handler.js\";\n\nexport default {\n desc: \"Convert OpenAPI files between JSON and YAML formats\",\n command: \"convert\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\n \"$0 oas convert --input <file> (--json|--yaml|--format <format>) [options]\"\n )\n .option(\"input\", {\n type: \"string\",\n alias: \"i\",\n describe: \"The input OpenAPI file (JSON or YAML)\",\n normalize: true,\n demandOption: true,\n })\n .option(\"format\", {\n type: \"string\",\n alias: \"f\",\n describe: \"Output format\",\n choices: [\"json\", \"yaml\"],\n })\n .option(\"json\", {\n type: \"boolean\",\n describe: \"Convert to JSON format\",\n conflicts: [\"yaml\", \"format\"],\n })\n .option(\"yaml\", {\n type: \"boolean\",\n describe: \"Convert to YAML format\",\n conflicts: [\"json\", \"format\"],\n })\n .option(\"output\", {\n type: \"string\",\n alias: \"o\",\n describe:\n \"Output file path (if not specified, generates based on input)\",\n normalize: true,\n })\n .option(\"watch\", {\n type: \"boolean\",\n describe: \"Watch input file for changes and automatically re-convert\",\n default: false,\n })\n .example([\n [\n \"$0 oas convert --input openapi.yaml --json\",\n \"Convert a YAML OpenAPI file to JSON format\",\n ],\n [\n \"$0 oas convert -i openapi.json --yaml -o api-spec.yaml\",\n \"Convert a JSON OpenAPI file to YAML with custom output path\",\n ],\n [\n \"$0 oas convert --input api.yaml --format json\",\n \"Convert using --format flag instead of --json/--yaml\",\n ],\n [\n \"$0 oas convert --input openapi.yaml --json --watch\",\n \"Watch the input file for changes and automatically re-convert\",\n ],\n ])\n .check((argv) => {\n if (!argv.input) {\n throw new Error(\"Input file is required\");\n }\n\n // Validate file extension\n const validExtensions = [\".json\", \".yaml\", \".yml\"];\n const ext = path.extname(argv.input as string).toLowerCase();\n if (!validExtensions.includes(ext)) {\n throw new Error(\n `Invalid input file extension: ${ext}. Must be .json, .yaml, or .yml`\n );\n }\n\n // Validate input file exists\n if (!fs.existsSync(argv.input as string)) {\n throw new Error(`Input file not found: ${argv.input}`);\n }\n\n // Validate output format is specified\n if (!argv.format && !argv.json && !argv.yaml) {\n throw new Error(\n \"Output format must be specified using --format, --json, or --yaml\"\n );\n }\n\n return true;\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo oas convert\" });\n await convertOpenAPI(argv as Arguments);\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../../src/cmds/open-api/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAOV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBA8Ef,OAAO;;AAjF/B,wBAqFE"}
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../../src/cmds/open-api/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAOV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBA2Ef,OAAO;;AA9E/B,wBAkFE"}
@@ -74,9 +74,6 @@ export default {
74
74
  if (!argv.destination) {
75
75
  throw new Error("Destination is required");
76
76
  }
77
- if (!argv.destination.endsWith(".oas.json")) {
78
- throw new Error("Destination file name must end with '.oas.json'");
79
- }
80
77
  return true;
81
78
  });
82
79
  },
@@ -1 +1 @@
1
- {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../../src/cmds/open-api/merge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAa,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAE3E,eAAe;IACb,IAAI,EAAE,+CAA+C;IACrD,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,iEAAiE,CAAC;aACxE,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,8CAA8C;SACzD,CAAC;aACD,MAAM,CAAC,aAAa,EAAE;YACrB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,OAAO,EAAE,0BAA0B;YACnC,QAAQ,EAAE,qDAAqD;SAChE,CAAC;aACD,MAAM,CAAC,YAAY,EAAE;YACpB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,qDAAqD;YAC/D,OAAO,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC;YACxC,OAAO,EAAE,aAAa;SACvB,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,wCAAwC;YAClD,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;SACb,CAAC;aACD,MAAM,CAAC,cAAc,EAAE;YACtB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,6DAA6D;YACvE,OAAO,EAAE,IAAI;SACd,CAAC;aACD,MAAM,CAAC,cAAc,EAAE;YACtB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,+DAA+D;SAClE,CAAC;aACD,MAAM,CAAC,OAAO,EAAE;YACf,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,0DAA0D;YACpE,OAAO,EAAE,KAAK;SACf,CAAC;aACD,OAAO,CAAC;YACP;gBACE,2EAA2E;gBAC3E,+CAA+C;aAChD;YACD;gBACE,+EAA+E;gBAC/E,kCAAkC;aACnC;YACD;gBACE,qGAAqG;gBACrG,0DAA0D;aAC3D;YACD;gBACE,8FAA8F;gBAC9F,sCAAsC;aACvC;YACD;gBACE,mFAAmF;gBACnF,8DAA8D;aAC/D;SACF,CAAC;aACD,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;YACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACxC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC7C,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC5C,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACvD,MAAM,aAAa,CAAC,IAAiB,CAAC,CAAC;IACzC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { Arguments, importOpenApi } from \"../../open-api/merge/handler.js\";\n\nexport default {\n desc: \"Merge an OpenAPI file into your Zuplo project\",\n command: \"merge\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 oas merge --source <file|url> --destination <file> [options]\")\n .option(\"source\", {\n type: \"string\",\n alias: \"s\",\n demandOption: true,\n describe: \"The OpenAPI file to merge (file path or URL)\",\n })\n .option(\"destination\", {\n type: \"string\",\n alias: \"d\",\n default: \"./config/routes.oas.json\",\n describe: \"The destination file name (must end with .oas.json)\",\n })\n .option(\"merge-mode\", {\n type: \"string\",\n alias: \"m\",\n describe: \"The merge mode to use when merging the OpenAPI file\",\n choices: [\"path-method\", \"operation-id\"],\n default: \"path-method\",\n })\n .option(\"prompt\", {\n type: \"boolean\",\n describe: \"Prompt for confirmation before merging\",\n default: false,\n hidden: true,\n })\n .option(\"server-paths\", {\n type: \"boolean\",\n describe: \"Prepend the pathname from the first server URL to all paths\",\n default: true,\n })\n .option(\"prepend-path\", {\n type: \"string\",\n describe:\n \"Directly provide a path to prepend to all paths (e.g., '/v1')\",\n })\n .option(\"watch\", {\n type: \"boolean\",\n describe: \"Watch source file for changes and automatically re-merge\",\n default: false,\n })\n .example([\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json\",\n \"Merge an OpenAPI file into your Zuplo project\",\n ],\n [\n \"$0 oas merge -s https://api.example.com/openapi.json -d ./config/api.oas.json\",\n \"Merge an OpenAPI file from a URL\",\n ],\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json --merge-mode operation-id\",\n \"Merge using operation-id instead of path-method matching\",\n ],\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json --prepend-path /v1\",\n \"Merge and prepend '/v1' to all paths\",\n ],\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json --watch\",\n \"Watch the source file for changes and automatically re-merge\",\n ],\n ])\n .check((argv) => {\n if (!argv.source) {\n throw new Error(\"Source is required\");\n }\n if (!argv.destination) {\n throw new Error(\"Destination is required\");\n }\n if (!argv.destination.endsWith(\".oas.json\")) {\n throw new Error(\"Destination file name must end with '.oas.json'\");\n }\n return true;\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo oas merge\" });\n await importOpenApi(argv as Arguments);\n },\n};\n"]}
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../../src/cmds/open-api/merge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAa,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAE3E,eAAe;IACb,IAAI,EAAE,+CAA+C;IACrD,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK;aACT,KAAK,CAAC,iEAAiE,CAAC;aACxE,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,8CAA8C;SACzD,CAAC;aACD,MAAM,CAAC,aAAa,EAAE;YACrB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,OAAO,EAAE,0BAA0B;YACnC,QAAQ,EAAE,qDAAqD;SAChE,CAAC;aACD,MAAM,CAAC,YAAY,EAAE;YACpB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;YACV,QAAQ,EAAE,qDAAqD;YAC/D,OAAO,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC;YACxC,OAAO,EAAE,aAAa;SACvB,CAAC;aACD,MAAM,CAAC,QAAQ,EAAE;YAChB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,wCAAwC;YAClD,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;SACb,CAAC;aACD,MAAM,CAAC,cAAc,EAAE;YACtB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,6DAA6D;YACvE,OAAO,EAAE,IAAI;SACd,CAAC;aACD,MAAM,CAAC,cAAc,EAAE;YACtB,IAAI,EAAE,QAAQ;YACd,QAAQ,EACN,+DAA+D;SAClE,CAAC;aACD,MAAM,CAAC,OAAO,EAAE;YACf,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,0DAA0D;YACpE,OAAO,EAAE,KAAK;SACf,CAAC;aACD,OAAO,CAAC;YACP;gBACE,2EAA2E;gBAC3E,+CAA+C;aAChD;YACD;gBACE,+EAA+E;gBAC/E,kCAAkC;aACnC;YACD;gBACE,qGAAqG;gBACrG,0DAA0D;aAC3D;YACD;gBACE,8FAA8F;gBAC9F,sCAAsC;aACvC;YACD;gBACE,mFAAmF;gBACnF,8DAA8D;aAC/D;SACF,CAAC;aACD,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;YACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACxC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACvD,MAAM,aAAa,CAAC,IAAiB,CAAC,CAAC;IACzC,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { Arguments, importOpenApi } from \"../../open-api/merge/handler.js\";\n\nexport default {\n desc: \"Merge an OpenAPI file into your Zuplo project\",\n command: \"merge\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\"$0 oas merge --source <file|url> --destination <file> [options]\")\n .option(\"source\", {\n type: \"string\",\n alias: \"s\",\n demandOption: true,\n describe: \"The OpenAPI file to merge (file path or URL)\",\n })\n .option(\"destination\", {\n type: \"string\",\n alias: \"d\",\n default: \"./config/routes.oas.json\",\n describe: \"The destination file name (must end with .oas.json)\",\n })\n .option(\"merge-mode\", {\n type: \"string\",\n alias: \"m\",\n describe: \"The merge mode to use when merging the OpenAPI file\",\n choices: [\"path-method\", \"operation-id\"],\n default: \"path-method\",\n })\n .option(\"prompt\", {\n type: \"boolean\",\n describe: \"Prompt for confirmation before merging\",\n default: false,\n hidden: true,\n })\n .option(\"server-paths\", {\n type: \"boolean\",\n describe: \"Prepend the pathname from the first server URL to all paths\",\n default: true,\n })\n .option(\"prepend-path\", {\n type: \"string\",\n describe:\n \"Directly provide a path to prepend to all paths (e.g., '/v1')\",\n })\n .option(\"watch\", {\n type: \"boolean\",\n describe: \"Watch source file for changes and automatically re-merge\",\n default: false,\n })\n .example([\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json\",\n \"Merge an OpenAPI file into your Zuplo project\",\n ],\n [\n \"$0 oas merge -s https://api.example.com/openapi.json -d ./config/api.oas.json\",\n \"Merge an OpenAPI file from a URL\",\n ],\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json --merge-mode operation-id\",\n \"Merge using operation-id instead of path-method matching\",\n ],\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json --prepend-path /v1\",\n \"Merge and prepend '/v1' to all paths\",\n ],\n [\n \"$0 oas merge --source openapi.yaml --destination ./config/routes.oas.json --watch\",\n \"Watch the source file for changes and automatically re-merge\",\n ],\n ])\n .check((argv) => {\n if (!argv.source) {\n throw new Error(\"Source is required\");\n }\n if (!argv.destination) {\n throw new Error(\"Destination is required\");\n }\n return true;\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo oas merge\" });\n await importOpenApi(argv as Arguments);\n },\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../../src/cmds/open-api/overlay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAOV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBA2Ff,OAAO;;AA9F/B,wBAkGE"}
1
+ {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../../src/cmds/open-api/overlay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAOV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAqGf,OAAO;;AAxG/B,wBA4GE"}
@@ -44,6 +44,11 @@ export default {
44
44
  type: "boolean",
45
45
  describe: "Output in YAML format",
46
46
  conflicts: ["json", "format"],
47
+ })
48
+ .option("watch", {
49
+ type: "boolean",
50
+ describe: "Watch input and overlay files for changes and automatically re-apply",
51
+ default: false,
47
52
  })
48
53
  .example([
49
54
  [
@@ -58,6 +63,10 @@ export default {
58
63
  "$0 oas overlay --input openapi.json --overlay overlay.json --output result.yaml --format yaml",
59
64
  "Apply overlay and convert format in one step",
60
65
  ],
66
+ [
67
+ "$0 oas overlay --input openapi.json --overlay changes.json --output result.json --watch",
68
+ "Watch input and overlay files for changes and automatically re-apply",
69
+ ],
61
70
  ])
62
71
  .check((argv) => {
63
72
  if (!argv.input || !argv.overlay || !argv.output) {
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../src/cmds/open-api/overlay.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { Arguments, applyOverlay } from \"../../open-api/overlay/handler.js\";\n\nexport default {\n desc: \"Apply an OpenAPI Overlay to an OpenAPI document\",\n command: \"overlay\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\n \"$0 oas overlay --input <file> --overlay <file> --output <file> [options]\"\n )\n .option(\"input\", {\n type: \"string\",\n alias: \"i\",\n describe: \"The input OpenAPI file\",\n normalize: true,\n demandOption: true,\n })\n .option(\"overlay\", {\n type: \"string\",\n alias: \"l\",\n describe: \"The overlay file\",\n normalize: true,\n demandOption: true,\n })\n .option(\"output\", {\n type: \"string\",\n alias: \"o\",\n describe: \"The output OpenAPI file path\",\n normalize: true,\n demandOption: true,\n })\n .option(\"format\", {\n type: \"string\",\n alias: \"f\",\n describe: \"Output format\",\n choices: [\"json\", \"yaml\"],\n })\n .option(\"json\", {\n type: \"boolean\",\n describe: \"Output in JSON format\",\n conflicts: [\"yaml\", \"format\"],\n })\n .option(\"yaml\", {\n type: \"boolean\",\n describe: \"Output in YAML format\",\n conflicts: [\"json\", \"format\"],\n })\n .example([\n [\n \"$0 oas overlay --input openapi.json --overlay changes.json --output result.json\",\n \"Apply an overlay to an OpenAPI document\",\n ],\n [\n \"$0 oas overlay -i api.yaml -v overlay.yaml -o result.yaml --yaml\",\n \"Apply overlay and output in YAML format\",\n ],\n [\n \"$0 oas overlay --input openapi.json --overlay overlay.json --output result.yaml --format yaml\",\n \"Apply overlay and convert format in one step\",\n ],\n ])\n .check((argv) => {\n if (!argv.input || !argv.overlay || !argv.output) {\n throw new Error(\n \"All three arguments are required: input, overlay, and output\"\n );\n }\n\n // Validate output file has an extension for format detection\n const outputExt = path.extname(argv.output as string).toLowerCase();\n const validExtensions = [\".json\", \".yaml\", \".yml\"];\n\n // Only require extension if format not explicitly specified\n if (\n !argv.format &&\n !argv.json &&\n !argv.yaml &&\n !validExtensions.includes(outputExt)\n ) {\n throw new Error(\n `Output file must have a .json, .yaml, or .yml extension, or specify output format with --format, --json, or --yaml`\n );\n }\n\n // Validate input files exist\n if (!fs.existsSync(argv.input as string)) {\n throw new Error(`Input file not found: ${argv.input}`);\n }\n\n if (!fs.existsSync(argv.overlay as string)) {\n throw new Error(`Overlay file not found: ${argv.overlay}`);\n }\n\n return true;\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo oas overlay\" });\n await applyOverlay(argv as Arguments);\n },\n};\n"]}
1
+ {"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../src/cmds/open-api/overlay.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Argv } from \"yargs\";\nimport { captureEvent } from \"../../common/analytics/lib.js\";\nimport { Arguments, applyOverlay } from \"../../open-api/overlay/handler.js\";\n\nexport default {\n desc: \"Apply an OpenAPI Overlay to an OpenAPI document\",\n command: \"overlay\",\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs\n .usage(\n \"$0 oas overlay --input <file> --overlay <file> --output <file> [options]\"\n )\n .option(\"input\", {\n type: \"string\",\n alias: \"i\",\n describe: \"The input OpenAPI file\",\n normalize: true,\n demandOption: true,\n })\n .option(\"overlay\", {\n type: \"string\",\n alias: \"l\",\n describe: \"The overlay file\",\n normalize: true,\n demandOption: true,\n })\n .option(\"output\", {\n type: \"string\",\n alias: \"o\",\n describe: \"The output OpenAPI file path\",\n normalize: true,\n demandOption: true,\n })\n .option(\"format\", {\n type: \"string\",\n alias: \"f\",\n describe: \"Output format\",\n choices: [\"json\", \"yaml\"],\n })\n .option(\"json\", {\n type: \"boolean\",\n describe: \"Output in JSON format\",\n conflicts: [\"yaml\", \"format\"],\n })\n .option(\"yaml\", {\n type: \"boolean\",\n describe: \"Output in YAML format\",\n conflicts: [\"json\", \"format\"],\n })\n .option(\"watch\", {\n type: \"boolean\",\n describe:\n \"Watch input and overlay files for changes and automatically re-apply\",\n default: false,\n })\n .example([\n [\n \"$0 oas overlay --input openapi.json --overlay changes.json --output result.json\",\n \"Apply an overlay to an OpenAPI document\",\n ],\n [\n \"$0 oas overlay -i api.yaml -v overlay.yaml -o result.yaml --yaml\",\n \"Apply overlay and output in YAML format\",\n ],\n [\n \"$0 oas overlay --input openapi.json --overlay overlay.json --output result.yaml --format yaml\",\n \"Apply overlay and convert format in one step\",\n ],\n [\n \"$0 oas overlay --input openapi.json --overlay changes.json --output result.json --watch\",\n \"Watch input and overlay files for changes and automatically re-apply\",\n ],\n ])\n .check((argv) => {\n if (!argv.input || !argv.overlay || !argv.output) {\n throw new Error(\n \"All three arguments are required: input, overlay, and output\"\n );\n }\n\n // Validate output file has an extension for format detection\n const outputExt = path.extname(argv.output as string).toLowerCase();\n const validExtensions = [\".json\", \".yaml\", \".yml\"];\n\n // Only require extension if format not explicitly specified\n if (\n !argv.format &&\n !argv.json &&\n !argv.yaml &&\n !validExtensions.includes(outputExt)\n ) {\n throw new Error(\n `Output file must have a .json, .yaml, or .yml extension, or specify output format with --format, --json, or --yaml`\n );\n }\n\n // Validate input files exist\n if (!fs.existsSync(argv.input as string)) {\n throw new Error(`Input file not found: ${argv.input}`);\n }\n\n if (!fs.existsSync(argv.overlay as string)) {\n throw new Error(`Overlay file not found: ${argv.overlay}`);\n }\n\n return true;\n });\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo oas overlay\" });\n await applyOverlay(argv as Arguments);\n },\n};\n"]}
@@ -4,6 +4,7 @@ export interface Arguments {
4
4
  json?: boolean;
5
5
  yaml?: boolean;
6
6
  output?: string;
7
+ watch?: boolean;
7
8
  }
8
9
  export declare function convertOpenAPI(args: Arguments): Promise<void>;
9
10
  //# sourceMappingURL=handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/open-api/convert/handler.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAsB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA0EnE"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/open-api/convert/handler.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAgGD,wBAAsB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEnE"}
@@ -1,9 +1,10 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import chokidar from "chokidar";
3
4
  import { logger } from "../../common/logger.js";
4
5
  import { printDiagnosticsToConsole } from "../../common/output.js";
5
6
  import { convertDocument, detectFormat, generateOutputPath, } from "./convert-engine.js";
6
- export async function convertOpenAPI(args) {
7
+ async function performConversion(args) {
7
8
  const inputPath = path.resolve(args.input);
8
9
  const outputPath = args.output ? path.resolve(args.output) : undefined;
9
10
  const { format, json, yaml } = args;
@@ -25,16 +26,20 @@ export async function convertOpenAPI(args) {
25
26
  throw new Error(`Unable to determine input format from extension: ${path.extname(inputPath)}`);
26
27
  }
27
28
  if (inputFormat === outputFormat) {
28
- console.log(`Input file is already in ${outputFormat.toUpperCase()} format. No conversion needed.`);
29
+ if (!args.watch) {
30
+ printDiagnosticsToConsole(`Input file is already in ${outputFormat.toUpperCase()} format. No conversion needed.`);
31
+ }
29
32
  return;
30
33
  }
31
- console.log("OpenAPI Format Converter");
32
- console.log("========================");
33
- console.log(`Input file: ${inputPath}`);
34
- console.log(`Input format: ${inputFormat.toUpperCase()}`);
35
- console.log(`Output format: ${outputFormat.toUpperCase()}`);
36
- if (outputPath) {
37
- console.log(`Output file: ${outputPath}`);
34
+ if (!args.watch) {
35
+ printDiagnosticsToConsole("OpenAPI Format Converter");
36
+ printDiagnosticsToConsole("========================");
37
+ printDiagnosticsToConsole(`Input file: ${inputPath}`);
38
+ printDiagnosticsToConsole(`Input format: ${inputFormat.toUpperCase()}`);
39
+ printDiagnosticsToConsole(`Output format: ${outputFormat.toUpperCase()}`);
40
+ if (outputPath) {
41
+ printDiagnosticsToConsole(`Output file: ${outputPath}`);
42
+ }
38
43
  }
39
44
  try {
40
45
  const inputContent = fs.readFileSync(inputPath, "utf-8");
@@ -45,7 +50,12 @@ export async function convertOpenAPI(args) {
45
50
  fs.mkdirSync(outputDir, { recursive: true });
46
51
  }
47
52
  fs.writeFileSync(finalOutputPath, outputContent, "utf-8");
48
- console.log(`\n✓ Converted file written to: ${finalOutputPath}`);
53
+ if (!args.watch) {
54
+ printDiagnosticsToConsole(`\n✓ Converted file written to: ${finalOutputPath}`);
55
+ }
56
+ else {
57
+ printDiagnosticsToConsole(`✓ Converted file written to: ${finalOutputPath}`);
58
+ }
49
59
  }
50
60
  catch (error) {
51
61
  logger.error(error, "Error converting OpenAPI file");
@@ -53,4 +63,59 @@ export async function convertOpenAPI(args) {
53
63
  throw error;
54
64
  }
55
65
  }
66
+ export async function convertOpenAPI(args) {
67
+ if (!args.watch) {
68
+ return performConversion(args);
69
+ }
70
+ const inputPath = path.resolve(args.input);
71
+ if (!fs.existsSync(inputPath)) {
72
+ throw new Error(`Input file not found: ${inputPath}`);
73
+ }
74
+ printDiagnosticsToConsole("OpenAPI Format Converter (Watch Mode)");
75
+ printDiagnosticsToConsole("======================================");
76
+ printDiagnosticsToConsole(`Input file: ${inputPath}`);
77
+ printDiagnosticsToConsole("\nStarting watch mode...");
78
+ printDiagnosticsToConsole("Press Ctrl+C to stop watching.\n");
79
+ try {
80
+ await performConversion(args);
81
+ printDiagnosticsToConsole("\nWatching for changes...");
82
+ }
83
+ catch (error) {
84
+ logger.error(error, "Initial conversion failed");
85
+ printDiagnosticsToConsole(`Error during initial conversion: ${error}`);
86
+ printDiagnosticsToConsole("\nWatching for changes...");
87
+ }
88
+ const watcher = chokidar.watch(inputPath, {
89
+ persistent: true,
90
+ ignoreInitial: true,
91
+ });
92
+ watcher.on("change", async () => {
93
+ try {
94
+ const relativePath = path.relative(process.cwd(), inputPath);
95
+ printDiagnosticsToConsole(`\nFile ${relativePath} changed, re-converting...`);
96
+ await performConversion(args);
97
+ printDiagnosticsToConsole("Re-conversion completed successfully.\n");
98
+ }
99
+ catch (error) {
100
+ logger.error(error, "Re-conversion failed");
101
+ printDiagnosticsToConsole(`Error during re-conversion: ${error}\n`);
102
+ }
103
+ });
104
+ watcher.on("error", (error) => {
105
+ logger.error(error, "Watcher error");
106
+ printDiagnosticsToConsole(`Watcher error: ${error}`);
107
+ });
108
+ return new Promise((resolve) => {
109
+ process.once("SIGINT", async () => {
110
+ printDiagnosticsToConsole("\nStopping watch mode...");
111
+ await watcher.close();
112
+ resolve();
113
+ });
114
+ process.once("SIGTERM", async () => {
115
+ printDiagnosticsToConsole("\nStopping watch mode...");
116
+ await watcher.close();
117
+ resolve();
118
+ });
119
+ });
120
+ }
56
121
  //# sourceMappingURL=handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/open-api/convert/handler.ts"],"names":[],"mappings":"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","sourcesContent":["/** biome-ignore-all lint/suspicious/noConsole: CLI output file */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { logger } from \"../../common/logger.js\";\nimport { printDiagnosticsToConsole } from \"../../common/output.js\";\nimport {\n convertDocument,\n detectFormat,\n type FileFormat,\n generateOutputPath,\n} from \"./convert-engine.js\";\n\nexport interface Arguments {\n input: string;\n format?: \"json\" | \"yaml\";\n json?: boolean;\n yaml?: boolean;\n output?: string;\n}\n\n/**\n * Convert OpenAPI document between JSON and YAML formats\n */\nexport async function convertOpenAPI(args: Arguments): Promise<void> {\n const inputPath = path.resolve(args.input);\n const outputPath = args.output ? path.resolve(args.output) : undefined;\n const { format, json, yaml } = args;\n\n // Determine output format\n let outputFormat: FileFormat;\n if (format) {\n outputFormat = format;\n } else if (json) {\n outputFormat = \"json\";\n } else if (yaml) {\n outputFormat = \"yaml\";\n } else {\n throw new Error(\n \"Output format must be specified using --format, --json, or --yaml\"\n );\n }\n\n // Determine input format from extension\n const inputFormat = detectFormat(inputPath);\n if (!inputFormat) {\n throw new Error(\n `Unable to determine input format from extension: ${path.extname(inputPath)}`\n );\n }\n\n // Check if conversion is needed\n if (inputFormat === outputFormat) {\n console.log(\n `Input file is already in ${outputFormat.toUpperCase()} format. No conversion needed.`\n );\n return;\n }\n\n console.log(\"OpenAPI Format Converter\");\n console.log(\"========================\");\n console.log(`Input file: ${inputPath}`);\n console.log(`Input format: ${inputFormat.toUpperCase()}`);\n console.log(`Output format: ${outputFormat.toUpperCase()}`);\n if (outputPath) {\n console.log(`Output file: ${outputPath}`);\n }\n\n try {\n // Load input file\n const inputContent = fs.readFileSync(inputPath, \"utf-8\");\n\n // Convert document\n const { content: outputContent } = convertDocument(\n inputContent,\n inputFormat,\n outputFormat\n );\n\n // Determine output path (use provided path or generate one)\n const finalOutputPath =\n outputPath || generateOutputPath(inputPath, outputFormat);\n\n // Create output directory if it doesn't exist\n const outputDir = path.dirname(finalOutputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n // Write output file\n fs.writeFileSync(finalOutputPath, outputContent, \"utf-8\");\n\n console.log(`\\n✓ Converted file written to: ${finalOutputPath}`);\n } catch (error) {\n logger.error(error, \"Error converting OpenAPI file\");\n printDiagnosticsToConsole(`Error: ${(error as Error).message}`);\n throw error;\n }\n}\n"]}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/open-api/convert/handler.ts"],"names":[],"mappings":"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","sourcesContent":["/** biome-ignore-all lint/suspicious/noConsole: CLI output file */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chokidar from \"chokidar\";\nimport { logger } from \"../../common/logger.js\";\nimport { printDiagnosticsToConsole } from \"../../common/output.js\";\nimport {\n convertDocument,\n detectFormat,\n type FileFormat,\n generateOutputPath,\n} from \"./convert-engine.js\";\n\nexport interface Arguments {\n input: string;\n format?: \"json\" | \"yaml\";\n json?: boolean;\n yaml?: boolean;\n output?: string;\n watch?: boolean;\n}\n\n/**\n * Perform conversion once\n */\nasync function performConversion(args: Arguments): Promise<void> {\n const inputPath = path.resolve(args.input);\n const outputPath = args.output ? path.resolve(args.output) : undefined;\n const { format, json, yaml } = args;\n\n // Determine output format\n let outputFormat: FileFormat;\n if (format) {\n outputFormat = format;\n } else if (json) {\n outputFormat = \"json\";\n } else if (yaml) {\n outputFormat = \"yaml\";\n } else {\n throw new Error(\n \"Output format must be specified using --format, --json, or --yaml\"\n );\n }\n\n // Determine input format from extension\n const inputFormat = detectFormat(inputPath);\n if (!inputFormat) {\n throw new Error(\n `Unable to determine input format from extension: ${path.extname(inputPath)}`\n );\n }\n\n // Check if conversion is needed\n if (inputFormat === outputFormat) {\n if (!args.watch) {\n printDiagnosticsToConsole(\n `Input file is already in ${outputFormat.toUpperCase()} format. No conversion needed.`\n );\n }\n return;\n }\n\n if (!args.watch) {\n printDiagnosticsToConsole(\"OpenAPI Format Converter\");\n printDiagnosticsToConsole(\"========================\");\n printDiagnosticsToConsole(`Input file: ${inputPath}`);\n printDiagnosticsToConsole(`Input format: ${inputFormat.toUpperCase()}`);\n printDiagnosticsToConsole(`Output format: ${outputFormat.toUpperCase()}`);\n if (outputPath) {\n printDiagnosticsToConsole(`Output file: ${outputPath}`);\n }\n }\n\n try {\n // Load input file\n const inputContent = fs.readFileSync(inputPath, \"utf-8\");\n\n // Convert document\n const { content: outputContent } = convertDocument(\n inputContent,\n inputFormat,\n outputFormat\n );\n\n // Determine output path (use provided path or generate one)\n const finalOutputPath =\n outputPath || generateOutputPath(inputPath, outputFormat);\n\n // Create output directory if it doesn't exist\n const outputDir = path.dirname(finalOutputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n // Write output file\n fs.writeFileSync(finalOutputPath, outputContent, \"utf-8\");\n\n if (!args.watch) {\n printDiagnosticsToConsole(\n `\\n✓ Converted file written to: ${finalOutputPath}`\n );\n } else {\n printDiagnosticsToConsole(\n `✓ Converted file written to: ${finalOutputPath}`\n );\n }\n } catch (error) {\n logger.error(error, \"Error converting OpenAPI file\");\n printDiagnosticsToConsole(`Error: ${(error as Error).message}`);\n throw error;\n }\n}\n\n/**\n * Convert OpenAPI document between JSON and YAML formats\n */\nexport async function convertOpenAPI(args: Arguments): Promise<void> {\n // If watch mode is not enabled, just perform the conversion once\n if (!args.watch) {\n return performConversion(args);\n }\n\n const inputPath = path.resolve(args.input);\n\n // Validate input file exists\n if (!fs.existsSync(inputPath)) {\n throw new Error(`Input file not found: ${inputPath}`);\n }\n\n printDiagnosticsToConsole(\"OpenAPI Format Converter (Watch Mode)\");\n printDiagnosticsToConsole(\"======================================\");\n printDiagnosticsToConsole(`Input file: ${inputPath}`);\n printDiagnosticsToConsole(\"\\nStarting watch mode...\");\n printDiagnosticsToConsole(\"Press Ctrl+C to stop watching.\\n\");\n\n // Perform initial conversion\n try {\n await performConversion(args);\n printDiagnosticsToConsole(\"\\nWatching for changes...\");\n } catch (error) {\n logger.error(error, \"Initial conversion failed\");\n printDiagnosticsToConsole(`Error during initial conversion: ${error}`);\n printDiagnosticsToConsole(\"\\nWatching for changes...\");\n }\n\n // Set up file watcher\n const watcher = chokidar.watch(inputPath, {\n persistent: true,\n ignoreInitial: true,\n });\n\n watcher.on(\"change\", async () => {\n try {\n const relativePath = path.relative(process.cwd(), inputPath);\n printDiagnosticsToConsole(\n `\\nFile ${relativePath} changed, re-converting...`\n );\n await performConversion(args);\n printDiagnosticsToConsole(\"Re-conversion completed successfully.\\n\");\n } catch (error) {\n logger.error(error, \"Re-conversion failed\");\n printDiagnosticsToConsole(`Error during re-conversion: ${error}\\n`);\n }\n });\n\n watcher.on(\"error\", (error) => {\n logger.error(error, \"Watcher error\");\n printDiagnosticsToConsole(`Watcher error: ${error}`);\n });\n\n // Return a promise that never resolves to keep the process alive\n // The promise will only resolve when SIGINT/SIGTERM is received\n return new Promise<void>((resolve) => {\n // Handle graceful shutdown\n process.once(\"SIGINT\", async () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n await watcher.close();\n resolve();\n });\n\n process.once(\"SIGTERM\", async () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n await watcher.close();\n resolve();\n });\n });\n}\n"]}
@@ -287,5 +287,15 @@ paths: {}`;
287
287
  assert.strictEqual(outputContent.includes("title: Test API"), true);
288
288
  });
289
289
  });
290
+ describe("watch flag", () => {
291
+ it("should reject watch mode with non-existent input file", async () => {
292
+ const inputPath = path.join(testTmpPath, "nonexistent.json");
293
+ await assert.rejects(() => convertOpenAPI({
294
+ input: inputPath,
295
+ format: "yaml",
296
+ watch: true,
297
+ }), /Input file not found/);
298
+ });
299
+ });
290
300
  });
291
301
  //# sourceMappingURL=handler.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.spec.js","sourceRoot":"","sources":["../../../src/open-api/convert/handler.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { fileURLToPath } from \"node:url\";\nimport { convertOpenAPI } from \"./handler.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst testTmpPath = path.join(\n __dirname,\n \"..\",\n \"..\",\n \"__tests__\",\n \"test-tmp\",\n \"convert-handler\"\n);\n\ndescribe(\"Convert Handler\", () => {\n beforeEach(async () => {\n // Ensure test-tmp directory exists\n await fs.mkdir(testTmpPath, { recursive: true });\n });\n\n afterEach(async () => {\n // Clean up test files\n try {\n await fs.rm(testTmpPath, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n });\n\n describe(\"convertOpenAPI\", () => {\n it(\"should convert JSON to YAML using --format yaml\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const expectedOutputPath = path.join(testTmpPath, \"api.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(outputContent.includes(\"title: Test API\"), true);\n });\n\n it(\"should convert JSON to YAML using --yaml\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const expectedOutputPath = path.join(testTmpPath, \"api.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n yaml: true,\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should convert YAML to JSON using --format json\", async () => {\n const inputPath = path.join(testTmpPath, \"api.yaml\");\n const expectedOutputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Test API\n version: 1.0.0\npaths: {}`;\n\n await fs.writeFile(inputPath, inputDoc);\n\n await convertOpenAPI({\n input: inputPath,\n format: \"json\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n const parsed = JSON.parse(outputContent);\n assert.strictEqual(parsed.openapi, \"3.1.0\");\n assert.strictEqual(parsed.info.title, \"Test API\");\n });\n\n it(\"should convert YAML to JSON using --json\", async () => {\n const inputPath = path.join(testTmpPath, \"api.yml\");\n const expectedOutputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Test API\n version: 1.0.0\npaths: {}`;\n\n await fs.writeFile(inputPath, inputDoc);\n\n await convertOpenAPI({\n input: inputPath,\n json: true,\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n const parsed = JSON.parse(outputContent);\n assert.strictEqual(parsed.openapi, \"3.1.0\");\n });\n\n it(\"should handle files with multiple dots in name\", async () => {\n const inputPath = path.join(testTmpPath, \"api.v1.0.json\");\n const expectedOutputPath = path.join(testTmpPath, \"api.v1.0.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should preserve complex nested structures\", async () => {\n const inputPath = path.join(testTmpPath, \"complex.json\");\n const expectedOutputPath = path.join(testTmpPath, \"complex.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Complex API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users/{id}\": {\n get: {\n parameters: [\n { name: \"id\", in: \"path\", required: true },\n { name: \"fields\", in: \"query\", required: false },\n ],\n responses: {\n \"200\": {\n description: \"Success\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: {\n id: { type: \"string\" },\n name: { type: \"string\" },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n // Convert back to verify data preservation\n await convertOpenAPI({\n input: expectedOutputPath,\n format: \"json\",\n });\n\n const finalContent = await fs.readFile(inputPath, \"utf-8\");\n const finalDoc = JSON.parse(finalContent);\n assert.deepStrictEqual(finalDoc, inputDoc);\n });\n\n it(\"should create output directory if it doesn't exist\", async () => {\n const inputPath = path.join(testTmpPath, \"nested\", \"dir\", \"api.json\");\n const expectedOutputPath = path.join(\n testTmpPath,\n \"nested\",\n \"dir\",\n \"api.yaml\"\n );\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.mkdir(path.dirname(inputPath), { recursive: true });\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should throw error when no format is specified\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await assert.rejects(\n () =>\n convertOpenAPI({\n input: inputPath,\n }),\n /Output format must be specified/\n );\n });\n\n it(\"should throw error when input format cannot be determined\", async () => {\n const inputPath = path.join(testTmpPath, \"api.txt\");\n\n await fs.writeFile(inputPath, \"content\");\n\n await assert.rejects(\n () =>\n convertOpenAPI({\n input: inputPath,\n format: \"json\",\n }),\n /Unable to determine input format/\n );\n });\n\n it(\"should not convert if input and output formats are the same\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n // Should complete without error and not create output file\n await convertOpenAPI({\n input: inputPath,\n format: \"json\",\n });\n\n // Verify original file still exists\n const content = await fs.readFile(inputPath, \"utf-8\");\n const parsed = JSON.parse(content);\n assert.deepStrictEqual(parsed, inputDoc);\n });\n\n it(\"should use custom output path when specified\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const customOutputPath = path.join(testTmpPath, \"custom-name.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n output: customOutputPath,\n });\n\n const outputContent = await fs.readFile(customOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(outputContent.includes(\"title: Test API\"), true);\n });\n\n it(\"should create output directory when using custom output path\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const customOutputPath = path.join(\n testTmpPath,\n \"custom\",\n \"output\",\n \"dir\",\n \"result.yaml\"\n );\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n output: customOutputPath,\n });\n\n const outputContent = await fs.readFile(customOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should use custom output path with different location\", async () => {\n const inputPath = path.join(testTmpPath, \"source\", \"api.json\");\n const customOutputPath = path.join(testTmpPath, \"output\", \"api.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.mkdir(path.dirname(inputPath), { recursive: true });\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n output: customOutputPath,\n });\n\n const outputContent = await fs.readFile(customOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(outputContent.includes(\"title: Test API\"), true);\n });\n });\n});\n"]}
1
+ {"version":3,"file":"handler.spec.js","sourceRoot":"","sources":["../../../src/open-api/convert/handler.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { fileURLToPath } from \"node:url\";\nimport { convertOpenAPI } from \"./handler.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst testTmpPath = path.join(\n __dirname,\n \"..\",\n \"..\",\n \"__tests__\",\n \"test-tmp\",\n \"convert-handler\"\n);\n\ndescribe(\"Convert Handler\", () => {\n beforeEach(async () => {\n // Ensure test-tmp directory exists\n await fs.mkdir(testTmpPath, { recursive: true });\n });\n\n afterEach(async () => {\n // Clean up test files\n try {\n await fs.rm(testTmpPath, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n });\n\n describe(\"convertOpenAPI\", () => {\n it(\"should convert JSON to YAML using --format yaml\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const expectedOutputPath = path.join(testTmpPath, \"api.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(outputContent.includes(\"title: Test API\"), true);\n });\n\n it(\"should convert JSON to YAML using --yaml\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const expectedOutputPath = path.join(testTmpPath, \"api.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n yaml: true,\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should convert YAML to JSON using --format json\", async () => {\n const inputPath = path.join(testTmpPath, \"api.yaml\");\n const expectedOutputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Test API\n version: 1.0.0\npaths: {}`;\n\n await fs.writeFile(inputPath, inputDoc);\n\n await convertOpenAPI({\n input: inputPath,\n format: \"json\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n const parsed = JSON.parse(outputContent);\n assert.strictEqual(parsed.openapi, \"3.1.0\");\n assert.strictEqual(parsed.info.title, \"Test API\");\n });\n\n it(\"should convert YAML to JSON using --json\", async () => {\n const inputPath = path.join(testTmpPath, \"api.yml\");\n const expectedOutputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Test API\n version: 1.0.0\npaths: {}`;\n\n await fs.writeFile(inputPath, inputDoc);\n\n await convertOpenAPI({\n input: inputPath,\n json: true,\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n const parsed = JSON.parse(outputContent);\n assert.strictEqual(parsed.openapi, \"3.1.0\");\n });\n\n it(\"should handle files with multiple dots in name\", async () => {\n const inputPath = path.join(testTmpPath, \"api.v1.0.json\");\n const expectedOutputPath = path.join(testTmpPath, \"api.v1.0.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should preserve complex nested structures\", async () => {\n const inputPath = path.join(testTmpPath, \"complex.json\");\n const expectedOutputPath = path.join(testTmpPath, \"complex.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Complex API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users/{id}\": {\n get: {\n parameters: [\n { name: \"id\", in: \"path\", required: true },\n { name: \"fields\", in: \"query\", required: false },\n ],\n responses: {\n \"200\": {\n description: \"Success\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: {\n id: { type: \"string\" },\n name: { type: \"string\" },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n // Convert back to verify data preservation\n await convertOpenAPI({\n input: expectedOutputPath,\n format: \"json\",\n });\n\n const finalContent = await fs.readFile(inputPath, \"utf-8\");\n const finalDoc = JSON.parse(finalContent);\n assert.deepStrictEqual(finalDoc, inputDoc);\n });\n\n it(\"should create output directory if it doesn't exist\", async () => {\n const inputPath = path.join(testTmpPath, \"nested\", \"dir\", \"api.json\");\n const expectedOutputPath = path.join(\n testTmpPath,\n \"nested\",\n \"dir\",\n \"api.yaml\"\n );\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.mkdir(path.dirname(inputPath), { recursive: true });\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n });\n\n const outputContent = await fs.readFile(expectedOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should throw error when no format is specified\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await assert.rejects(\n () =>\n convertOpenAPI({\n input: inputPath,\n }),\n /Output format must be specified/\n );\n });\n\n it(\"should throw error when input format cannot be determined\", async () => {\n const inputPath = path.join(testTmpPath, \"api.txt\");\n\n await fs.writeFile(inputPath, \"content\");\n\n await assert.rejects(\n () =>\n convertOpenAPI({\n input: inputPath,\n format: \"json\",\n }),\n /Unable to determine input format/\n );\n });\n\n it(\"should not convert if input and output formats are the same\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n // Should complete without error and not create output file\n await convertOpenAPI({\n input: inputPath,\n format: \"json\",\n });\n\n // Verify original file still exists\n const content = await fs.readFile(inputPath, \"utf-8\");\n const parsed = JSON.parse(content);\n assert.deepStrictEqual(parsed, inputDoc);\n });\n\n it(\"should use custom output path when specified\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const customOutputPath = path.join(testTmpPath, \"custom-name.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n output: customOutputPath,\n });\n\n const outputContent = await fs.readFile(customOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(outputContent.includes(\"title: Test API\"), true);\n });\n\n it(\"should create output directory when using custom output path\", async () => {\n const inputPath = path.join(testTmpPath, \"api.json\");\n const customOutputPath = path.join(\n testTmpPath,\n \"custom\",\n \"output\",\n \"dir\",\n \"result.yaml\"\n );\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n output: customOutputPath,\n });\n\n const outputContent = await fs.readFile(customOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should use custom output path with different location\", async () => {\n const inputPath = path.join(testTmpPath, \"source\", \"api.json\");\n const customOutputPath = path.join(testTmpPath, \"output\", \"api.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Test API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.mkdir(path.dirname(inputPath), { recursive: true });\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n output: customOutputPath,\n });\n\n const outputContent = await fs.readFile(customOutputPath, \"utf-8\");\n assert.strictEqual(outputContent.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(outputContent.includes(\"title: Test API\"), true);\n });\n });\n\n describe(\"watch flag\", () => {\n it(\"should reject watch mode with non-existent input file\", async () => {\n const inputPath = path.join(testTmpPath, \"nonexistent.json\");\n\n await assert.rejects(\n () =>\n convertOpenAPI({\n input: inputPath,\n format: \"yaml\",\n watch: true,\n }),\n /Input file not found/\n );\n });\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/open-api/merge/handler.ts"],"names":[],"mappings":"AAeA,OAAO,EAML,KAAK,SAAS,EAGf,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA4KD,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAkElE"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/open-api/merge/handler.ts"],"names":[],"mappings":"AAeA,OAAO,EAML,KAAK,SAAS,EAGf,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA+JD,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA+ElE"}
@@ -20,7 +20,7 @@ async function performMerge(argv) {
20
20
  try {
21
21
  const response = await fetch(parsedUrl);
22
22
  if (!response.ok) {
23
- await printCriticalFailureToConsoleAndExit(`Failed to download the remote OpenAPI file. Server responded with ${response.status} ${response.statusText}`);
23
+ throw new Error(`Failed to download the remote OpenAPI file. Server responded with ${response.status} ${response.statusText}`);
24
24
  }
25
25
  const text = await response.text();
26
26
  try {
@@ -30,29 +30,27 @@ async function performMerge(argv) {
30
30
  }
31
31
  catch (err) {
32
32
  logger.error(err, "Failed to parse the remote OpenAPI file");
33
- await printCriticalFailureToConsoleAndExit("Failed to parse the remote OpenAPI file as either JSON or YAML.");
33
+ throw new Error("Failed to parse the remote OpenAPI file as either JSON or YAML.", { cause: err });
34
34
  }
35
35
  }
36
36
  catch (err) {
37
37
  logger.error(err, "Failed to download the remote OpenAPI file");
38
- await printCriticalFailureToConsoleAndExit("Failed to download the remote OpenAPI file.");
38
+ throw new Error("Failed to download the remote OpenAPI file.", {
39
+ cause: err,
40
+ });
39
41
  }
40
42
  }
41
43
  else {
42
44
  normalizedFilePath = path.resolve(argv.source);
43
45
  if (!existsSync(normalizedFilePath)) {
44
- await printCriticalFailureToConsoleAndExit(`The file ${normalizedFilePath} to import does not exist.`);
46
+ throw new Error(`The file ${normalizedFilePath} to import does not exist.`);
45
47
  }
46
48
  }
47
49
  const rawOpenApiSpec = await readFile(normalizedFilePath);
48
50
  const extName = path.extname(normalizedFilePath);
49
51
  const fileContent = rawOpenApiSpec.toString();
50
52
  const parsedOpenApiSpec = await parseOpenApiFile(extName, fileContent);
51
- const destination = argv.destination;
52
- if (!destination.endsWith(".oas.json")) {
53
- await printCriticalFailureToConsoleAndExit("Destination file name must end with '.oas.json'");
54
- }
55
- const destinationFilePath = path.resolve(destination);
53
+ const destinationFilePath = path.resolve(argv.destination);
56
54
  let originalDocument;
57
55
  if (!existsSync(destinationFilePath)) {
58
56
  originalDocument = (await parseOpenApiFile(".json", BASE_TEMPLATE));
@@ -100,7 +98,7 @@ async function performMerge(argv) {
100
98
  printDiagnosticsToConsole("");
101
99
  const answer = await confirm({ message: "Proceed?", default: true });
102
100
  if (!answer) {
103
- await printResultToConsoleAndExitGracefully("Import cancelled.");
101
+ throw new Error("Import cancelled.");
104
102
  }
105
103
  }
106
104
  addOperationIdsAsNecessary(mergedDocument);
@@ -114,32 +112,37 @@ async function performMerge(argv) {
114
112
  writeFileSync(destinationFilePath, formattedOpenApi, {
115
113
  flag: "w",
116
114
  });
117
- if (!argv.watch) {
118
- await printResultToConsoleAndExitGracefully(`Import successful. File written to ${destinationFilePath}`);
119
- }
120
- else {
121
- printDiagnosticsToConsole(`Import successful. File written to ${destinationFilePath}`);
122
- }
115
+ printDiagnosticsToConsole(`Import successful. File written to ${destinationFilePath}`);
123
116
  }
124
117
  export async function importOpenApi(argv) {
125
118
  if (!argv.watch) {
126
- return performMerge(argv);
119
+ try {
120
+ await performMerge(argv);
121
+ await printResultToConsoleAndExitGracefully(`Import successful. File written to ${path.resolve(argv.destination)}`);
122
+ }
123
+ catch (error) {
124
+ logger.error(error, "Merge failed");
125
+ await printCriticalFailureToConsoleAndExit(`${error.message}`);
126
+ }
127
+ return;
127
128
  }
128
129
  if (isUrl(argv.source)) {
129
- await printCriticalFailureToConsoleAndExit("Watch mode is not supported for URL sources. Please use a local file.");
130
+ throw new Error("Watch mode is not supported for URL sources. Please use a local file.");
130
131
  }
131
132
  const sourcePath = path.resolve(argv.source);
132
133
  if (!existsSync(sourcePath)) {
133
- await printCriticalFailureToConsoleAndExit(`The file ${sourcePath} to import does not exist.`);
134
+ throw new Error(`The file ${sourcePath} to import does not exist.`);
134
135
  }
135
136
  printDiagnosticsToConsole(`Starting watch mode for ${sourcePath}...`);
136
137
  printDiagnosticsToConsole("Press Ctrl+C to stop watching.\n");
137
138
  try {
138
139
  await performMerge(argv);
140
+ printDiagnosticsToConsole("\nWatching for changes...");
139
141
  }
140
142
  catch (error) {
141
143
  logger.error(error, "Initial merge failed");
142
144
  printDiagnosticsToConsole(`Error during initial merge: ${error}`);
145
+ printDiagnosticsToConsole("\nWatching for changes...");
143
146
  }
144
147
  const watcher = chokidar.watch(sourcePath, {
145
148
  persistent: true,
@@ -160,15 +163,17 @@ export async function importOpenApi(argv) {
160
163
  logger.error(error, "Watcher error");
161
164
  printDiagnosticsToConsole(`Watcher error: ${error}`);
162
165
  });
163
- process.once("SIGINT", () => {
164
- printDiagnosticsToConsole("\nStopping watch mode...");
165
- watcher.close();
166
- process.exit(0);
167
- });
168
- process.once("SIGTERM", () => {
169
- printDiagnosticsToConsole("\nStopping watch mode...");
170
- watcher.close();
171
- process.exit(0);
166
+ return new Promise((resolve) => {
167
+ process.once("SIGINT", async () => {
168
+ printDiagnosticsToConsole("\nStopping watch mode...");
169
+ await watcher.close();
170
+ resolve();
171
+ });
172
+ process.once("SIGTERM", async () => {
173
+ printDiagnosticsToConsole("\nStopping watch mode...");
174
+ await watcher.close();
175
+ resolve();
176
+ });
172
177
  });
173
178
  }
174
179
  //# sourceMappingURL=handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/open-api/merge/handler.ts"],"names":[],"mappings":"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","sourcesContent":["/** biome-ignore-all lint/suspicious/noConsole: CLI output file */\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { confirm } from \"@inquirer/prompts\";\nimport { mergeOpenApiDocuments } from \"@zuplo/openapi-tools\";\nimport chokidar from \"chokidar\";\nimport { format } from \"prettier\";\nimport { logger } from \"../../common/logger.js\";\nimport {\n printCriticalFailureToConsoleAndExit,\n printDiagnosticsToConsole,\n printResultToConsoleAndExitGracefully,\n} from \"../../common/output.js\";\nimport {\n addOperationIdsAsNecessary,\n BASE_TEMPLATE,\n detectFormatFromContent,\n guessFileNameFromUrl,\n isUrl,\n type MergeMode,\n parseOpenApiFile,\n type ZuploOpenApiDocument,\n} from \"./merge-engine.js\";\n\nexport interface Arguments {\n prompt?: boolean;\n source: string;\n destination: string;\n \"merge-mode\"?: MergeMode;\n \"server-paths\"?: boolean;\n \"prepend-path\"?: string;\n watch?: boolean;\n}\n\nasync function performMerge(argv: Arguments): Promise<void> {\n let normalizedFilePath: string;\n\n // Check if source is a URL\n if (isUrl(argv.source)) {\n const parsedUrl = new URL(argv.source);\n const tempDir = tmpdir();\n const guessedFileName = guessFileNameFromUrl(argv.source);\n normalizedFilePath = path.join(tempDir, guessedFileName);\n await mkdir(path.dirname(normalizedFilePath), { recursive: true });\n\n try {\n const response = await fetch(parsedUrl);\n if (!response.ok) {\n await printCriticalFailureToConsoleAndExit(\n `Failed to download the remote OpenAPI file. Server responded with ${response.status} ${response.statusText}`\n );\n }\n\n const text = await response.text();\n\n try {\n const format = detectFormatFromContent(text);\n normalizedFilePath = `${normalizedFilePath}.${format === \"json\" ? \"json\" : \"yaml\"}`;\n await writeFile(normalizedFilePath, text, { flag: \"w+\" });\n } catch (err) {\n logger.error(err, \"Failed to parse the remote OpenAPI file\");\n await printCriticalFailureToConsoleAndExit(\n \"Failed to parse the remote OpenAPI file as either JSON or YAML.\"\n );\n }\n } catch (err) {\n logger.error(err, \"Failed to download the remote OpenAPI file\");\n await printCriticalFailureToConsoleAndExit(\n \"Failed to download the remote OpenAPI file.\"\n );\n }\n } else {\n // This is a normal file\n normalizedFilePath = path.resolve(argv.source);\n\n if (!existsSync(normalizedFilePath)) {\n await printCriticalFailureToConsoleAndExit(\n `The file ${normalizedFilePath} to import does not exist.`\n );\n }\n }\n\n const rawOpenApiSpec = await readFile(normalizedFilePath);\n const extName = path.extname(normalizedFilePath);\n const fileContent = rawOpenApiSpec.toString();\n const parsedOpenApiSpec = await parseOpenApiFile(extName, fileContent);\n\n const destination = argv.destination;\n\n if (!destination.endsWith(\".oas.json\")) {\n await printCriticalFailureToConsoleAndExit(\n \"Destination file name must end with '.oas.json'\"\n );\n }\n\n const destinationFilePath = path.resolve(destination);\n\n let originalDocument: ZuploOpenApiDocument;\n if (!existsSync(destinationFilePath)) {\n // This is an initial import\n originalDocument = (await parseOpenApiFile(\n \".json\",\n BASE_TEMPLATE\n )) as ZuploOpenApiDocument;\n } else {\n const existingOpenApiSpec = await readFile(destinationFilePath);\n const existingFileContent = existingOpenApiSpec.toString();\n originalDocument = (await parseOpenApiFile(\n extName,\n existingFileContent\n )) as ZuploOpenApiDocument;\n }\n\n // Prepare merge options\n // If prepend-path is provided, disable server-paths to avoid conflict\n const mergeMode = argv[\"merge-mode\"] || \"path-method\";\n const prependPath = argv[\"prepend-path\"];\n const prependServerPath = prependPath ? false : argv[\"server-paths\"];\n\n const { created, merged, retained, mergedDocument } = mergeOpenApiDocuments(\n originalDocument,\n parsedOpenApiSpec,\n {\n mergeMode,\n prependServerPath,\n prependPath,\n }\n );\n\n // Present the changes\n printDiagnosticsToConsole(\"This import will...\");\n printDiagnosticsToConsole(\"\");\n\n if (created.size > 0) {\n printDiagnosticsToConsole(\n `Create ${created.size} new ${created.size > 1 ? \"operations\" : \"operation\"}`\n );\n printDiagnosticsToConsole(\"\");\n created.forEach((operation) => {\n printDiagnosticsToConsole(operation);\n });\n printDiagnosticsToConsole(\"\");\n }\n\n if (merged.size > 0) {\n printDiagnosticsToConsole(\n `Merge ${merged.size} ${merged.size > 1 ? \"operations\" : \"operation\"}`\n );\n printDiagnosticsToConsole(\"\");\n merged.forEach((operation) => {\n printDiagnosticsToConsole(operation);\n });\n printDiagnosticsToConsole(\"\");\n }\n\n if (retained.size > 0) {\n printDiagnosticsToConsole(\n `Retain ${retained.size} ${retained.size > 1 ? \"operations\" : \"operation\"}`\n );\n printDiagnosticsToConsole(\"\");\n retained.forEach((operation) => {\n printDiagnosticsToConsole(operation);\n });\n printDiagnosticsToConsole(\"\");\n }\n\n if (argv.prompt) {\n printDiagnosticsToConsole(\"\");\n const answer = await confirm({ message: \"Proceed?\", default: true });\n if (!answer) {\n await printResultToConsoleAndExitGracefully(\"Import cancelled.\");\n }\n }\n\n addOperationIdsAsNecessary(mergedDocument);\n\n const formattedOpenApi = await format(JSON.stringify(mergedDocument), {\n parser: \"json-stringify\",\n });\n\n // Create folder structure if needed\n if (!existsSync(destinationFilePath)) {\n // Get the directory path of the file\n const dir = path.dirname(destinationFilePath);\n\n // Ensure that the directory exists (creates parent directories if necessary)\n await mkdir(dir, { recursive: true });\n }\n\n writeFileSync(destinationFilePath, formattedOpenApi, {\n flag: \"w\",\n });\n\n if (!argv.watch) {\n await printResultToConsoleAndExitGracefully(\n `Import successful. File written to ${destinationFilePath}`\n );\n } else {\n printDiagnosticsToConsole(\n `Import successful. File written to ${destinationFilePath}`\n );\n }\n}\n\nexport async function importOpenApi(argv: Arguments): Promise<void> {\n // If watch mode is not enabled, just perform the merge once\n if (!argv.watch) {\n return performMerge(argv);\n }\n\n // Check if source is a URL - watch mode doesn't support URLs\n if (isUrl(argv.source)) {\n await printCriticalFailureToConsoleAndExit(\n \"Watch mode is not supported for URL sources. Please use a local file.\"\n );\n }\n\n const sourcePath = path.resolve(argv.source);\n\n if (!existsSync(sourcePath)) {\n await printCriticalFailureToConsoleAndExit(\n `The file ${sourcePath} to import does not exist.`\n );\n }\n\n printDiagnosticsToConsole(`Starting watch mode for ${sourcePath}...`);\n printDiagnosticsToConsole(\"Press Ctrl+C to stop watching.\\n\");\n\n // Perform initial merge\n try {\n await performMerge(argv);\n } catch (error) {\n logger.error(error, \"Initial merge failed\");\n printDiagnosticsToConsole(`Error during initial merge: ${error}`);\n }\n\n // Set up file watcher\n const watcher = chokidar.watch(sourcePath, {\n persistent: true,\n ignoreInitial: true,\n });\n\n watcher.on(\"change\", async () => {\n try {\n printDiagnosticsToConsole(`\\nFile ${sourcePath} changed, re-merging...`);\n await performMerge(argv);\n printDiagnosticsToConsole(\"Re-merge completed successfully.\\n\");\n } catch (error) {\n logger.error(error, \"Re-merge failed\");\n printDiagnosticsToConsole(`Error during re-merge: ${error}\\n`);\n }\n });\n\n watcher.on(\"error\", (error) => {\n logger.error(error, \"Watcher error\");\n printDiagnosticsToConsole(`Watcher error: ${error}`);\n });\n\n // Handle graceful shutdown\n process.once(\"SIGINT\", () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n watcher.close();\n process.exit(0);\n });\n\n process.once(\"SIGTERM\", () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n watcher.close();\n process.exit(0);\n });\n}\n"]}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/open-api/merge/handler.ts"],"names":[],"mappings":"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","sourcesContent":["/** biome-ignore-all lint/suspicious/noConsole: CLI output file */\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { confirm } from \"@inquirer/prompts\";\nimport { mergeOpenApiDocuments } from \"@zuplo/openapi-tools\";\nimport chokidar from \"chokidar\";\nimport { format } from \"prettier\";\nimport { logger } from \"../../common/logger.js\";\nimport {\n printCriticalFailureToConsoleAndExit,\n printDiagnosticsToConsole,\n printResultToConsoleAndExitGracefully,\n} from \"../../common/output.js\";\nimport {\n addOperationIdsAsNecessary,\n BASE_TEMPLATE,\n detectFormatFromContent,\n guessFileNameFromUrl,\n isUrl,\n type MergeMode,\n parseOpenApiFile,\n type ZuploOpenApiDocument,\n} from \"./merge-engine.js\";\n\nexport interface Arguments {\n prompt?: boolean;\n source: string;\n destination: string;\n \"merge-mode\"?: MergeMode;\n \"server-paths\"?: boolean;\n \"prepend-path\"?: string;\n watch?: boolean;\n}\n\nasync function performMerge(argv: Arguments): Promise<void> {\n let normalizedFilePath: string;\n\n // Check if source is a URL\n if (isUrl(argv.source)) {\n const parsedUrl = new URL(argv.source);\n const tempDir = tmpdir();\n const guessedFileName = guessFileNameFromUrl(argv.source);\n normalizedFilePath = path.join(tempDir, guessedFileName);\n await mkdir(path.dirname(normalizedFilePath), { recursive: true });\n\n try {\n const response = await fetch(parsedUrl);\n if (!response.ok) {\n throw new Error(\n `Failed to download the remote OpenAPI file. Server responded with ${response.status} ${response.statusText}`\n );\n }\n\n const text = await response.text();\n\n try {\n const format = detectFormatFromContent(text);\n normalizedFilePath = `${normalizedFilePath}.${format === \"json\" ? \"json\" : \"yaml\"}`;\n await writeFile(normalizedFilePath, text, { flag: \"w+\" });\n } catch (err) {\n logger.error(err, \"Failed to parse the remote OpenAPI file\");\n throw new Error(\n \"Failed to parse the remote OpenAPI file as either JSON or YAML.\",\n { cause: err }\n );\n }\n } catch (err) {\n logger.error(err, \"Failed to download the remote OpenAPI file\");\n throw new Error(\"Failed to download the remote OpenAPI file.\", {\n cause: err,\n });\n }\n } else {\n // This is a normal file\n normalizedFilePath = path.resolve(argv.source);\n\n if (!existsSync(normalizedFilePath)) {\n throw new Error(\n `The file ${normalizedFilePath} to import does not exist.`\n );\n }\n }\n\n const rawOpenApiSpec = await readFile(normalizedFilePath);\n const extName = path.extname(normalizedFilePath);\n const fileContent = rawOpenApiSpec.toString();\n const parsedOpenApiSpec = await parseOpenApiFile(extName, fileContent);\n\n const destinationFilePath = path.resolve(argv.destination);\n\n let originalDocument: ZuploOpenApiDocument;\n if (!existsSync(destinationFilePath)) {\n // This is an initial import\n originalDocument = (await parseOpenApiFile(\n \".json\",\n BASE_TEMPLATE\n )) as ZuploOpenApiDocument;\n } else {\n const existingOpenApiSpec = await readFile(destinationFilePath);\n const existingFileContent = existingOpenApiSpec.toString();\n originalDocument = (await parseOpenApiFile(\n extName,\n existingFileContent\n )) as ZuploOpenApiDocument;\n }\n\n // Prepare merge options\n // If prepend-path is provided, disable server-paths to avoid conflict\n const mergeMode = argv[\"merge-mode\"] || \"path-method\";\n const prependPath = argv[\"prepend-path\"];\n const prependServerPath = prependPath ? false : argv[\"server-paths\"];\n\n const { created, merged, retained, mergedDocument } = mergeOpenApiDocuments(\n originalDocument,\n parsedOpenApiSpec,\n {\n mergeMode,\n prependServerPath,\n prependPath,\n }\n );\n\n // Present the changes\n printDiagnosticsToConsole(\"This import will...\");\n printDiagnosticsToConsole(\"\");\n\n if (created.size > 0) {\n printDiagnosticsToConsole(\n `Create ${created.size} new ${created.size > 1 ? \"operations\" : \"operation\"}`\n );\n printDiagnosticsToConsole(\"\");\n created.forEach((operation) => {\n printDiagnosticsToConsole(operation);\n });\n printDiagnosticsToConsole(\"\");\n }\n\n if (merged.size > 0) {\n printDiagnosticsToConsole(\n `Merge ${merged.size} ${merged.size > 1 ? \"operations\" : \"operation\"}`\n );\n printDiagnosticsToConsole(\"\");\n merged.forEach((operation) => {\n printDiagnosticsToConsole(operation);\n });\n printDiagnosticsToConsole(\"\");\n }\n\n if (retained.size > 0) {\n printDiagnosticsToConsole(\n `Retain ${retained.size} ${retained.size > 1 ? \"operations\" : \"operation\"}`\n );\n printDiagnosticsToConsole(\"\");\n retained.forEach((operation) => {\n printDiagnosticsToConsole(operation);\n });\n printDiagnosticsToConsole(\"\");\n }\n\n if (argv.prompt) {\n printDiagnosticsToConsole(\"\");\n const answer = await confirm({ message: \"Proceed?\", default: true });\n if (!answer) {\n throw new Error(\"Import cancelled.\");\n }\n }\n\n addOperationIdsAsNecessary(mergedDocument);\n\n const formattedOpenApi = await format(JSON.stringify(mergedDocument), {\n parser: \"json-stringify\",\n });\n\n // Create folder structure if needed\n if (!existsSync(destinationFilePath)) {\n // Get the directory path of the file\n const dir = path.dirname(destinationFilePath);\n\n // Ensure that the directory exists (creates parent directories if necessary)\n await mkdir(dir, { recursive: true });\n }\n\n writeFileSync(destinationFilePath, formattedOpenApi, {\n flag: \"w\",\n });\n\n printDiagnosticsToConsole(\n `Import successful. File written to ${destinationFilePath}`\n );\n}\n\nexport async function importOpenApi(argv: Arguments): Promise<void> {\n // If watch mode is not enabled, just perform the merge once\n if (!argv.watch) {\n try {\n await performMerge(argv);\n await printResultToConsoleAndExitGracefully(\n `Import successful. File written to ${path.resolve(argv.destination)}`\n );\n } catch (error) {\n logger.error(error, \"Merge failed\");\n await printCriticalFailureToConsoleAndExit(`${(error as Error).message}`);\n }\n return;\n }\n\n // Check if source is a URL - watch mode doesn't support URLs\n if (isUrl(argv.source)) {\n throw new Error(\n \"Watch mode is not supported for URL sources. Please use a local file.\"\n );\n }\n\n const sourcePath = path.resolve(argv.source);\n\n if (!existsSync(sourcePath)) {\n throw new Error(`The file ${sourcePath} to import does not exist.`);\n }\n\n printDiagnosticsToConsole(`Starting watch mode for ${sourcePath}...`);\n printDiagnosticsToConsole(\"Press Ctrl+C to stop watching.\\n\");\n\n // Perform initial merge\n try {\n await performMerge(argv);\n printDiagnosticsToConsole(\"\\nWatching for changes...\");\n } catch (error) {\n logger.error(error, \"Initial merge failed\");\n printDiagnosticsToConsole(`Error during initial merge: ${error}`);\n printDiagnosticsToConsole(\"\\nWatching for changes...\");\n }\n\n // Set up file watcher\n const watcher = chokidar.watch(sourcePath, {\n persistent: true,\n ignoreInitial: true,\n });\n\n watcher.on(\"change\", async () => {\n try {\n printDiagnosticsToConsole(`\\nFile ${sourcePath} changed, re-merging...`);\n await performMerge(argv);\n printDiagnosticsToConsole(\"Re-merge completed successfully.\\n\");\n } catch (error) {\n logger.error(error, \"Re-merge failed\");\n printDiagnosticsToConsole(`Error during re-merge: ${error}\\n`);\n }\n });\n\n watcher.on(\"error\", (error) => {\n logger.error(error, \"Watcher error\");\n printDiagnosticsToConsole(`Watcher error: ${error}`);\n });\n\n // Return a promise that never resolves to keep the process alive\n // The promise will only resolve when SIGINT/SIGTERM is received\n return new Promise<void>((resolve) => {\n // Handle graceful shutdown\n process.once(\"SIGINT\", async () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n await watcher.close();\n resolve();\n });\n\n process.once(\"SIGTERM\", async () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n await watcher.close();\n resolve();\n });\n });\n}\n"]}
@@ -5,6 +5,7 @@ export interface Arguments {
5
5
  format?: "json" | "yaml";
6
6
  json?: boolean;
7
7
  yaml?: boolean;
8
+ watch?: boolean;
8
9
  }
9
10
  export declare function applyOverlay(args: Arguments): Promise<void>;
10
11
  //# sourceMappingURL=handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA6CD,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFjE"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA8ID,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA8EjE"}
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import chokidar from "chokidar";
3
4
  import { detectFormatFromExtension, parseFile, serializeContent, } from "../../common/file-format.js";
4
5
  import { logger } from "../../common/logger.js";
5
6
  import { printDiagnosticsToConsole } from "../../common/output.js";
@@ -24,7 +25,7 @@ function applyOverlayWithProgress(openapi, overlay) {
24
25
  }
25
26
  return result;
26
27
  }
27
- export async function applyOverlay(args) {
28
+ async function performOverlay(args) {
28
29
  const openapiPath = path.resolve(args.input);
29
30
  const overlayPath = path.resolve(args.overlay);
30
31
  const outputPath = path.resolve(args.output);
@@ -34,11 +35,13 @@ export async function applyOverlay(args) {
34
35
  if (!fs.existsSync(overlayPath)) {
35
36
  throw new Error(`Overlay file not found: ${overlayPath}`);
36
37
  }
37
- printDiagnosticsToConsole("OpenAPI Overlay Applicator");
38
- printDiagnosticsToConsole("===========================");
39
- printDiagnosticsToConsole(`OpenAPI file: ${openapiPath}`);
40
- printDiagnosticsToConsole(`Overlay file: ${overlayPath}`);
41
- printDiagnosticsToConsole(`Output file: ${outputPath}`);
38
+ if (!args.watch) {
39
+ printDiagnosticsToConsole("OpenAPI Overlay Applicator");
40
+ printDiagnosticsToConsole("===========================");
41
+ printDiagnosticsToConsole(`OpenAPI file: ${openapiPath}`);
42
+ printDiagnosticsToConsole(`Overlay file: ${overlayPath}`);
43
+ printDiagnosticsToConsole(`Output file: ${outputPath}`);
44
+ }
42
45
  try {
43
46
  const openapiContent = fs.readFileSync(openapiPath, "utf-8");
44
47
  const overlayContent = fs.readFileSync(overlayPath, "utf-8");
@@ -83,7 +86,12 @@ export async function applyOverlay(args) {
83
86
  fs.mkdirSync(outputDir, { recursive: true });
84
87
  }
85
88
  fs.writeFileSync(outputPath, outputContent, "utf-8");
86
- printDiagnosticsToConsole(`\n✓ Output written to: ${outputPath} (${outputFormat.toUpperCase()})`);
89
+ if (!args.watch) {
90
+ printDiagnosticsToConsole(`\n✓ Output written to: ${outputPath} (${outputFormat.toUpperCase()})`);
91
+ }
92
+ else {
93
+ printDiagnosticsToConsole(`✓ Output written to: ${outputPath} (${outputFormat.toUpperCase()})`);
94
+ }
87
95
  }
88
96
  catch (error) {
89
97
  logger.error(error, "Error applying overlay");
@@ -91,4 +99,66 @@ export async function applyOverlay(args) {
91
99
  throw error;
92
100
  }
93
101
  }
102
+ export async function applyOverlay(args) {
103
+ if (!args.watch) {
104
+ return performOverlay(args);
105
+ }
106
+ const openapiPath = path.resolve(args.input);
107
+ const overlayPath = path.resolve(args.overlay);
108
+ const outputPath = path.resolve(args.output);
109
+ if (!fs.existsSync(openapiPath)) {
110
+ throw new Error(`OpenAPI file not found: ${openapiPath}`);
111
+ }
112
+ if (!fs.existsSync(overlayPath)) {
113
+ throw new Error(`Overlay file not found: ${overlayPath}`);
114
+ }
115
+ printDiagnosticsToConsole("OpenAPI Overlay Applicator (Watch Mode)");
116
+ printDiagnosticsToConsole("========================================");
117
+ printDiagnosticsToConsole(`OpenAPI file: ${openapiPath}`);
118
+ printDiagnosticsToConsole(`Overlay file: ${overlayPath}`);
119
+ printDiagnosticsToConsole(`Output file: ${outputPath}`);
120
+ printDiagnosticsToConsole("\nStarting watch mode...");
121
+ printDiagnosticsToConsole("Press Ctrl+C to stop watching.\n");
122
+ try {
123
+ await performOverlay(args);
124
+ printDiagnosticsToConsole("\nWatching for changes...");
125
+ }
126
+ catch (error) {
127
+ logger.error(error, "Initial overlay application failed");
128
+ printDiagnosticsToConsole(`Error during initial overlay: ${error}`);
129
+ printDiagnosticsToConsole("\nWatching for changes...");
130
+ }
131
+ const watcher = chokidar.watch([openapiPath, overlayPath], {
132
+ persistent: true,
133
+ ignoreInitial: true,
134
+ });
135
+ watcher.on("change", async (changedPath) => {
136
+ try {
137
+ const relativePath = path.relative(process.cwd(), changedPath);
138
+ printDiagnosticsToConsole(`\nFile ${relativePath} changed, re-applying overlay...`);
139
+ await performOverlay(args);
140
+ printDiagnosticsToConsole("Re-apply completed successfully.\n");
141
+ }
142
+ catch (error) {
143
+ logger.error(error, "Re-apply failed");
144
+ printDiagnosticsToConsole(`Error during re-apply: ${error}\n`);
145
+ }
146
+ });
147
+ watcher.on("error", (error) => {
148
+ logger.error(error, "Watcher error");
149
+ printDiagnosticsToConsole(`Watcher error: ${error}`);
150
+ });
151
+ return new Promise((resolve) => {
152
+ process.once("SIGINT", async () => {
153
+ printDiagnosticsToConsole("\nStopping watch mode...");
154
+ await watcher.close();
155
+ resolve();
156
+ });
157
+ process.once("SIGTERM", async () => {
158
+ printDiagnosticsToConsole("\nStopping watch mode...");
159
+ await watcher.close();
160
+ resolve();
161
+ });
162
+ });
163
+ }
94
164
  //# sourceMappingURL=handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.ts"],"names":[],"mappings":"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","sourcesContent":["/** biome-ignore-all lint/suspicious/noConsole: CLI output file */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n detectFormatFromExtension,\n type FileFormat,\n parseFile,\n serializeContent,\n} from \"../../common/file-format.js\";\nimport { logger } from \"../../common/logger.js\";\nimport { printDiagnosticsToConsole } from \"../../common/output.js\";\nimport { applyOverlay as applyOverlayEngine } from \"./overlay-engine.js\";\n\nexport interface Arguments {\n overlay: string;\n input: string;\n output: string;\n format?: \"json\" | \"yaml\";\n json?: boolean;\n yaml?: boolean;\n}\n\n/**\n * Apply overlay to OpenAPI document with console output\n * Validates inputs and provides progress feedback\n */\nfunction applyOverlayWithProgress(\n openapi: unknown,\n overlay: unknown\n): Record<string, unknown> {\n // Apply overlay (includes validation)\n let validatedOverlay: ReturnType<typeof applyOverlayEngine>;\n\n try {\n validatedOverlay = applyOverlayEngine(openapi, overlay);\n } catch (error) {\n // Re-throw with better context for CLI users\n if (error instanceof Error) {\n printDiagnosticsToConsole(`\\n${error.message}`);\n }\n throw error;\n }\n\n const { result, stats } = validatedOverlay;\n\n // Show summary\n printDiagnosticsToConsole(`\\n=== Summary ===`);\n printDiagnosticsToConsole(\n `Applied: ${stats.applied} action${stats.applied !== 1 ? \"s\" : \"\"}`\n );\n printDiagnosticsToConsole(\n `Modified: ${stats.totalNodes} node${stats.totalNodes !== 1 ? \"s\" : \"\"}`\n );\n if (stats.skipped > 0) {\n printDiagnosticsToConsole(\n `Skipped: ${stats.skipped} action${stats.skipped !== 1 ? \"s\" : \"\"}`\n );\n }\n\n return result;\n}\n\n/**\n * Main handler function\n */\nexport async function applyOverlay(args: Arguments): Promise<void> {\n const openapiPath = path.resolve(args.input);\n const overlayPath = path.resolve(args.overlay);\n const outputPath = path.resolve(args.output);\n\n // Validate input files exist\n if (!fs.existsSync(openapiPath)) {\n throw new Error(`OpenAPI file not found: ${openapiPath}`);\n }\n\n if (!fs.existsSync(overlayPath)) {\n throw new Error(`Overlay file not found: ${overlayPath}`);\n }\n\n printDiagnosticsToConsole(\"OpenAPI Overlay Applicator\");\n printDiagnosticsToConsole(\"===========================\");\n printDiagnosticsToConsole(`OpenAPI file: ${openapiPath}`);\n printDiagnosticsToConsole(`Overlay file: ${overlayPath}`);\n printDiagnosticsToConsole(`Output file: ${outputPath}`);\n\n try {\n // Load files with flexible parsing\n const openapiContent = fs.readFileSync(openapiPath, \"utf-8\");\n const overlayContent = fs.readFileSync(overlayPath, \"utf-8\");\n\n // Parse with automatic format detection\n let openapi: unknown;\n let overlay: unknown;\n\n try {\n const parsed = parseFile(openapiContent, openapiPath);\n openapi = parsed.document;\n } catch (error) {\n throw new Error(`Failed to parse OpenAPI file '${openapiPath}'`, {\n cause: error,\n });\n }\n\n try {\n const parsed = parseFile(overlayContent, overlayPath);\n overlay = parsed.document;\n } catch (error) {\n throw new Error(`Failed to parse overlay file '${overlayPath}'`, {\n cause: error,\n });\n }\n\n // Apply overlay with progress output\n // Validation happens inside applyOverlayWithProgress\n const result = applyOverlayWithProgress(openapi, overlay);\n\n // Determine output format\n let outputFormat: FileFormat;\n if (args.format) {\n outputFormat = args.format;\n } else if (args.json) {\n outputFormat = \"json\";\n } else if (args.yaml) {\n outputFormat = \"yaml\";\n } else {\n // Try to detect from output file extension\n const formatFromExt = detectFormatFromExtension(outputPath);\n outputFormat = formatFromExt || \"json\"; // Default to JSON if no extension\n }\n\n // Serialize output\n const outputContent = serializeContent(result, outputFormat);\n\n // Create output directory if it doesn't exist\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n fs.writeFileSync(outputPath, outputContent, \"utf-8\");\n\n printDiagnosticsToConsole(\n `\\n✓ Output written to: ${outputPath} (${outputFormat.toUpperCase()})`\n );\n } catch (error) {\n logger.error(error, \"Error applying overlay\");\n printDiagnosticsToConsole(`Error: ${(error as Error).message}`);\n throw error;\n }\n}\n"]}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.ts"],"names":[],"mappings":"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","sourcesContent":["/** biome-ignore-all lint/suspicious/noConsole: CLI output file */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport chokidar from \"chokidar\";\nimport {\n detectFormatFromExtension,\n type FileFormat,\n parseFile,\n serializeContent,\n} from \"../../common/file-format.js\";\nimport { logger } from \"../../common/logger.js\";\nimport { printDiagnosticsToConsole } from \"../../common/output.js\";\nimport { applyOverlay as applyOverlayEngine } from \"./overlay-engine.js\";\n\nexport interface Arguments {\n overlay: string;\n input: string;\n output: string;\n format?: \"json\" | \"yaml\";\n json?: boolean;\n yaml?: boolean;\n watch?: boolean;\n}\n\n/**\n * Apply overlay to OpenAPI document with console output\n * Validates inputs and provides progress feedback\n */\nfunction applyOverlayWithProgress(\n openapi: unknown,\n overlay: unknown\n): Record<string, unknown> {\n // Apply overlay (includes validation)\n let validatedOverlay: ReturnType<typeof applyOverlayEngine>;\n\n try {\n validatedOverlay = applyOverlayEngine(openapi, overlay);\n } catch (error) {\n // Re-throw with better context for CLI users\n if (error instanceof Error) {\n printDiagnosticsToConsole(`\\n${error.message}`);\n }\n throw error;\n }\n\n const { result, stats } = validatedOverlay;\n\n // Show summary\n printDiagnosticsToConsole(`\\n=== Summary ===`);\n printDiagnosticsToConsole(\n `Applied: ${stats.applied} action${stats.applied !== 1 ? \"s\" : \"\"}`\n );\n printDiagnosticsToConsole(\n `Modified: ${stats.totalNodes} node${stats.totalNodes !== 1 ? \"s\" : \"\"}`\n );\n if (stats.skipped > 0) {\n printDiagnosticsToConsole(\n `Skipped: ${stats.skipped} action${stats.skipped !== 1 ? \"s\" : \"\"}`\n );\n }\n\n return result;\n}\n\n/**\n * Perform overlay application once\n */\nasync function performOverlay(args: Arguments): Promise<void> {\n const openapiPath = path.resolve(args.input);\n const overlayPath = path.resolve(args.overlay);\n const outputPath = path.resolve(args.output);\n\n // Validate input files exist\n if (!fs.existsSync(openapiPath)) {\n throw new Error(`OpenAPI file not found: ${openapiPath}`);\n }\n\n if (!fs.existsSync(overlayPath)) {\n throw new Error(`Overlay file not found: ${overlayPath}`);\n }\n\n if (!args.watch) {\n printDiagnosticsToConsole(\"OpenAPI Overlay Applicator\");\n printDiagnosticsToConsole(\"===========================\");\n printDiagnosticsToConsole(`OpenAPI file: ${openapiPath}`);\n printDiagnosticsToConsole(`Overlay file: ${overlayPath}`);\n printDiagnosticsToConsole(`Output file: ${outputPath}`);\n }\n\n try {\n // Load files with flexible parsing\n const openapiContent = fs.readFileSync(openapiPath, \"utf-8\");\n const overlayContent = fs.readFileSync(overlayPath, \"utf-8\");\n\n // Parse with automatic format detection\n let openapi: unknown;\n let overlay: unknown;\n\n try {\n const parsed = parseFile(openapiContent, openapiPath);\n openapi = parsed.document;\n } catch (error) {\n throw new Error(`Failed to parse OpenAPI file '${openapiPath}'`, {\n cause: error,\n });\n }\n\n try {\n const parsed = parseFile(overlayContent, overlayPath);\n overlay = parsed.document;\n } catch (error) {\n throw new Error(`Failed to parse overlay file '${overlayPath}'`, {\n cause: error,\n });\n }\n\n // Apply overlay with progress output\n // Validation happens inside applyOverlayWithProgress\n const result = applyOverlayWithProgress(openapi, overlay);\n\n // Determine output format\n let outputFormat: FileFormat;\n if (args.format) {\n outputFormat = args.format;\n } else if (args.json) {\n outputFormat = \"json\";\n } else if (args.yaml) {\n outputFormat = \"yaml\";\n } else {\n // Try to detect from output file extension\n const formatFromExt = detectFormatFromExtension(outputPath);\n outputFormat = formatFromExt || \"json\"; // Default to JSON if no extension\n }\n\n // Serialize output\n const outputContent = serializeContent(result, outputFormat);\n\n // Create output directory if it doesn't exist\n const outputDir = path.dirname(outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n fs.writeFileSync(outputPath, outputContent, \"utf-8\");\n\n if (!args.watch) {\n printDiagnosticsToConsole(\n `\\n✓ Output written to: ${outputPath} (${outputFormat.toUpperCase()})`\n );\n } else {\n printDiagnosticsToConsole(\n `✓ Output written to: ${outputPath} (${outputFormat.toUpperCase()})`\n );\n }\n } catch (error) {\n logger.error(error, \"Error applying overlay\");\n printDiagnosticsToConsole(`Error: ${(error as Error).message}`);\n throw error;\n }\n}\n\n/**\n * Main handler function\n */\nexport async function applyOverlay(args: Arguments): Promise<void> {\n // If watch mode is not enabled, just perform the overlay once\n if (!args.watch) {\n return performOverlay(args);\n }\n\n const openapiPath = path.resolve(args.input);\n const overlayPath = path.resolve(args.overlay);\n const outputPath = path.resolve(args.output);\n\n // Validate input files exist\n if (!fs.existsSync(openapiPath)) {\n throw new Error(`OpenAPI file not found: ${openapiPath}`);\n }\n\n if (!fs.existsSync(overlayPath)) {\n throw new Error(`Overlay file not found: ${overlayPath}`);\n }\n\n printDiagnosticsToConsole(\"OpenAPI Overlay Applicator (Watch Mode)\");\n printDiagnosticsToConsole(\"========================================\");\n printDiagnosticsToConsole(`OpenAPI file: ${openapiPath}`);\n printDiagnosticsToConsole(`Overlay file: ${overlayPath}`);\n printDiagnosticsToConsole(`Output file: ${outputPath}`);\n printDiagnosticsToConsole(\"\\nStarting watch mode...\");\n printDiagnosticsToConsole(\"Press Ctrl+C to stop watching.\\n\");\n\n // Perform initial overlay\n try {\n await performOverlay(args);\n printDiagnosticsToConsole(\"\\nWatching for changes...\");\n } catch (error) {\n logger.error(error, \"Initial overlay application failed\");\n printDiagnosticsToConsole(`Error during initial overlay: ${error}`);\n printDiagnosticsToConsole(\"\\nWatching for changes...\");\n }\n\n // Set up file watcher for both input and overlay files\n const watcher = chokidar.watch([openapiPath, overlayPath], {\n persistent: true,\n ignoreInitial: true,\n });\n\n watcher.on(\"change\", async (changedPath) => {\n try {\n const relativePath = path.relative(process.cwd(), changedPath);\n printDiagnosticsToConsole(\n `\\nFile ${relativePath} changed, re-applying overlay...`\n );\n await performOverlay(args);\n printDiagnosticsToConsole(\"Re-apply completed successfully.\\n\");\n } catch (error) {\n logger.error(error, \"Re-apply failed\");\n printDiagnosticsToConsole(`Error during re-apply: ${error}\\n`);\n }\n });\n\n watcher.on(\"error\", (error) => {\n logger.error(error, \"Watcher error\");\n printDiagnosticsToConsole(`Watcher error: ${error}`);\n });\n\n // Return a promise that never resolves to keep the process alive\n // The promise will only resolve when SIGINT/SIGTERM is received\n return new Promise<void>((resolve) => {\n // Handle graceful shutdown\n process.once(\"SIGINT\", async () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n await watcher.close();\n resolve();\n });\n\n process.once(\"SIGTERM\", async () => {\n printDiagnosticsToConsole(\"\\nStopping watch mode...\");\n await watcher.close();\n resolve();\n });\n });\n}\n"]}
@@ -300,5 +300,47 @@ actions: []`;
300
300
  }), /Invalid overlay format/);
301
301
  });
302
302
  });
303
+ describe("watch flag", () => {
304
+ it("should reject watch mode with non-existent input file", async () => {
305
+ const inputPath = path.join(testTmpPath, "nonexistent.json");
306
+ const overlayPath = path.join(testTmpPath, "overlay.json");
307
+ const outputPath = path.join(testTmpPath, "output.json");
308
+ const overlayDoc = {
309
+ overlay: "1.0.0",
310
+ info: {
311
+ title: "Test Overlay",
312
+ version: "1.0.0",
313
+ },
314
+ actions: [],
315
+ };
316
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
317
+ await assert.rejects(() => applyOverlay({
318
+ input: inputPath,
319
+ overlay: overlayPath,
320
+ output: outputPath,
321
+ watch: true,
322
+ }), /OpenAPI file not found/);
323
+ });
324
+ it("should reject watch mode with non-existent overlay file", async () => {
325
+ const inputPath = path.join(testTmpPath, "input.json");
326
+ const overlayPath = path.join(testTmpPath, "nonexistent.json");
327
+ const outputPath = path.join(testTmpPath, "output.json");
328
+ const inputDoc = {
329
+ openapi: "3.1.0",
330
+ info: {
331
+ title: "Original API",
332
+ version: "1.0.0",
333
+ },
334
+ paths: {},
335
+ };
336
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
337
+ await assert.rejects(() => applyOverlay({
338
+ input: inputPath,
339
+ overlay: overlayPath,
340
+ output: outputPath,
341
+ watch: true,
342
+ }), /Overlay file not found/);
343
+ });
344
+ });
303
345
  });
304
346
  //# sourceMappingURL=handler.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.spec.js","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { fileURLToPath } from \"node:url\";\nimport { applyOverlay } from \"./handler.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst testTmpPath = path.join(\n __dirname,\n \"..\",\n \"..\",\n \"__tests__\",\n \"test-tmp\",\n \"overlay-handler\"\n);\n\ndescribe(\"Overlay Handler\", () => {\n beforeEach(async () => {\n // Ensure test-tmp directory exists\n await fs.mkdir(testTmpPath, { recursive: true });\n });\n\n afterEach(async () => {\n // Clean up test files\n try {\n await fs.rm(testTmpPath, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n });\n\n describe(\"applyOverlay\", () => {\n it(\"should apply overlay to OpenAPI document (JSON to JSON)\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [\n {\n target: \"$.info.title\",\n update: \"Updated API\",\n },\n ],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = JSON.parse(await fs.readFile(outputPath, \"utf-8\"));\n assert.strictEqual(result.info.title, \"Updated API\");\n assert.strictEqual(result.openapi, \"3.1.0\");\n });\n\n it(\"should support YAML input and JSON output\", async () => {\n const inputPath = path.join(testTmpPath, \"input.yaml\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Original API\n version: 1.0.0\npaths: {}`;\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [\n {\n target: \"$.info.version\",\n update: \"2.0.0\",\n },\n ],\n };\n\n await fs.writeFile(inputPath, inputDoc);\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = JSON.parse(await fs.readFile(outputPath, \"utf-8\"));\n assert.strictEqual(result.info.version, \"2.0.0\");\n });\n\n it(\"should support JSON input and YAML output\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n assert.strictEqual(result.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(result.includes(\"title: Original API\"), true);\n });\n\n it(\"should support --format flag to override output format\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.txt\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n format: \"yaml\",\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n assert.strictEqual(result.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should support --json flag\", async () => {\n const inputPath = path.join(testTmpPath, \"input.yaml\");\n const overlayPath = path.join(testTmpPath, \"overlay.yaml\");\n const outputPath = path.join(testTmpPath, \"output.txt\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Original API\n version: 1.0.0\npaths: {}`;\n\n const overlayDoc = `overlay: 1.0.0\ninfo:\n title: Test Overlay\n version: 1.0.0\nactions: []`;\n\n await fs.writeFile(inputPath, inputDoc);\n await fs.writeFile(overlayPath, overlayDoc);\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n json: true,\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n const parsed = JSON.parse(result);\n assert.strictEqual(parsed.openapi, \"3.1.0\");\n });\n\n it(\"should support --yaml flag\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.txt\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n yaml: true,\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n assert.strictEqual(result.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should create output directory if it doesn't exist\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"nested\", \"dir\", \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = JSON.parse(await fs.readFile(outputPath, \"utf-8\"));\n assert.strictEqual(result.openapi, \"3.1.0\");\n });\n\n it(\"should throw error when input file does not exist\", async () => {\n const inputPath = path.join(testTmpPath, \"nonexistent.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n }),\n /OpenAPI file not found/\n );\n });\n\n it(\"should throw error when overlay file does not exist\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"nonexistent.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n }),\n /Overlay file not found/\n );\n });\n\n it(\"should throw error when overlay is invalid\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const invalidOverlay = {\n info: {\n title: \"Missing overlay version\",\n },\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(invalidOverlay, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n }),\n /Invalid overlay format/\n );\n });\n });\n});\n"]}
1
+ {"version":3,"file":"handler.spec.js","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { fileURLToPath } from \"node:url\";\nimport { applyOverlay } from \"./handler.js\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst testTmpPath = path.join(\n __dirname,\n \"..\",\n \"..\",\n \"__tests__\",\n \"test-tmp\",\n \"overlay-handler\"\n);\n\ndescribe(\"Overlay Handler\", () => {\n beforeEach(async () => {\n // Ensure test-tmp directory exists\n await fs.mkdir(testTmpPath, { recursive: true });\n });\n\n afterEach(async () => {\n // Clean up test files\n try {\n await fs.rm(testTmpPath, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n });\n\n describe(\"applyOverlay\", () => {\n it(\"should apply overlay to OpenAPI document (JSON to JSON)\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [\n {\n target: \"$.info.title\",\n update: \"Updated API\",\n },\n ],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = JSON.parse(await fs.readFile(outputPath, \"utf-8\"));\n assert.strictEqual(result.info.title, \"Updated API\");\n assert.strictEqual(result.openapi, \"3.1.0\");\n });\n\n it(\"should support YAML input and JSON output\", async () => {\n const inputPath = path.join(testTmpPath, \"input.yaml\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Original API\n version: 1.0.0\npaths: {}`;\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [\n {\n target: \"$.info.version\",\n update: \"2.0.0\",\n },\n ],\n };\n\n await fs.writeFile(inputPath, inputDoc);\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = JSON.parse(await fs.readFile(outputPath, \"utf-8\"));\n assert.strictEqual(result.info.version, \"2.0.0\");\n });\n\n it(\"should support JSON input and YAML output\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.yaml\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n assert.strictEqual(result.includes(\"openapi: 3.1.0\"), true);\n assert.strictEqual(result.includes(\"title: Original API\"), true);\n });\n\n it(\"should support --format flag to override output format\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.txt\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n format: \"yaml\",\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n assert.strictEqual(result.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should support --json flag\", async () => {\n const inputPath = path.join(testTmpPath, \"input.yaml\");\n const overlayPath = path.join(testTmpPath, \"overlay.yaml\");\n const outputPath = path.join(testTmpPath, \"output.txt\");\n\n const inputDoc = `openapi: 3.1.0\ninfo:\n title: Original API\n version: 1.0.0\npaths: {}`;\n\n const overlayDoc = `overlay: 1.0.0\ninfo:\n title: Test Overlay\n version: 1.0.0\nactions: []`;\n\n await fs.writeFile(inputPath, inputDoc);\n await fs.writeFile(overlayPath, overlayDoc);\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n json: true,\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n const parsed = JSON.parse(result);\n assert.strictEqual(parsed.openapi, \"3.1.0\");\n });\n\n it(\"should support --yaml flag\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.txt\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n yaml: true,\n });\n\n const result = await fs.readFile(outputPath, \"utf-8\");\n assert.strictEqual(result.includes(\"openapi: 3.1.0\"), true);\n });\n\n it(\"should create output directory if it doesn't exist\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"nested\", \"dir\", \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n });\n\n const result = JSON.parse(await fs.readFile(outputPath, \"utf-8\"));\n assert.strictEqual(result.openapi, \"3.1.0\");\n });\n\n it(\"should throw error when input file does not exist\", async () => {\n const inputPath = path.join(testTmpPath, \"nonexistent.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n }),\n /OpenAPI file not found/\n );\n });\n\n it(\"should throw error when overlay file does not exist\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"nonexistent.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n }),\n /Overlay file not found/\n );\n });\n\n it(\"should throw error when overlay is invalid\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n const invalidOverlay = {\n info: {\n title: \"Missing overlay version\",\n },\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n await fs.writeFile(overlayPath, JSON.stringify(invalidOverlay, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n }),\n /Invalid overlay format/\n );\n });\n });\n\n describe(\"watch flag\", () => {\n it(\"should reject watch mode with non-existent input file\", async () => {\n const inputPath = path.join(testTmpPath, \"nonexistent.json\");\n const overlayPath = path.join(testTmpPath, \"overlay.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const overlayDoc = {\n overlay: \"1.0.0\",\n info: {\n title: \"Test Overlay\",\n version: \"1.0.0\",\n },\n actions: [],\n };\n\n await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n watch: true,\n }),\n /OpenAPI file not found/\n );\n });\n\n it(\"should reject watch mode with non-existent overlay file\", async () => {\n const inputPath = path.join(testTmpPath, \"input.json\");\n const overlayPath = path.join(testTmpPath, \"nonexistent.json\");\n const outputPath = path.join(testTmpPath, \"output.json\");\n\n const inputDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Original API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));\n\n await assert.rejects(\n () =>\n applyOverlay({\n input: inputPath,\n overlay: overlayPath,\n output: outputPath,\n watch: true,\n }),\n /Overlay file not found/\n );\n });\n });\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/cli",
3
- "version": "6.64.12",
3
+ "version": "6.64.14",
4
4
  "repository": "https://github.com/zuplo/zuplo",
5
5
  "author": "Zuplo, Inc.",
6
6
  "type": "module",
@@ -29,10 +29,10 @@
29
29
  "@opentelemetry/api": "1.9.0",
30
30
  "@sentry/node": "9.22.0",
31
31
  "@swc/core": "1.10.18",
32
- "@zuplo/core": "6.64.12",
32
+ "@zuplo/core": "6.64.14",
33
33
  "@zuplo/editor": "~1.0.0",
34
- "@zuplo/openapi-tools": "6.64.12",
35
- "@zuplo/runtime": "6.64.12",
34
+ "@zuplo/openapi-tools": "6.64.14",
35
+ "@zuplo/runtime": "6.64.14",
36
36
  "as-table": "1.0.55",
37
37
  "chalk": "5.4.1",
38
38
  "chokidar": "3.5.3",