@zuplo/cli 6.62.7 → 6.62.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +36 -4
  2. package/dist/__tests__/import-openapi-utils.test.js +1 -2
  3. package/dist/__tests__/import-openapi-utils.test.js.map +1 -1
  4. package/dist/__tests__/import-openapi.test.js +1 -5
  5. package/dist/__tests__/import-openapi.test.js.map +1 -1
  6. package/dist/cli.js +2 -0
  7. package/dist/cli.js.map +1 -1
  8. package/dist/cmds/open-api/convert.d.ts +9 -0
  9. package/dist/cmds/open-api/convert.d.ts.map +1 -0
  10. package/dist/cmds/open-api/convert.js +66 -0
  11. package/dist/cmds/open-api/convert.js.map +1 -0
  12. package/dist/cmds/open-api/index.d.ts +4 -0
  13. package/dist/cmds/open-api/index.d.ts.map +1 -0
  14. package/dist/cmds/open-api/index.js +15 -0
  15. package/dist/cmds/open-api/index.js.map +1 -0
  16. package/dist/cmds/open-api/merge.d.ts +9 -0
  17. package/dist/cmds/open-api/merge.d.ts.map +1 -0
  18. package/dist/cmds/open-api/merge.js +57 -0
  19. package/dist/cmds/open-api/merge.js.map +1 -0
  20. package/dist/cmds/open-api/overlay.d.ts +9 -0
  21. package/dist/cmds/open-api/overlay.d.ts.map +1 -0
  22. package/dist/cmds/open-api/overlay.js +85 -0
  23. package/dist/cmds/open-api/overlay.js.map +1 -0
  24. package/dist/cmds/source/import-openapi.d.ts +1 -0
  25. package/dist/cmds/source/import-openapi.d.ts.map +1 -1
  26. package/dist/cmds/source/import-openapi.js +6 -9
  27. package/dist/cmds/source/import-openapi.js.map +1 -1
  28. package/dist/cmds/source/migrate.js +1 -1
  29. package/dist/cmds/source/migrate.js.map +1 -1
  30. package/dist/common/file-format.d.ts +25 -0
  31. package/dist/common/file-format.d.ts.map +1 -0
  32. package/dist/common/file-format.js +72 -0
  33. package/dist/common/file-format.js.map +1 -0
  34. package/dist/common/runner.d.ts.map +1 -0
  35. package/dist/common/runner.js.map +1 -0
  36. package/dist/common/utils/stringify-config.d.ts.map +1 -0
  37. package/dist/common/utils/stringify-config.js.map +1 -0
  38. package/dist/common/utils/stringify-config.test.d.ts.map +1 -0
  39. package/dist/common/utils/stringify-config.test.js.map +1 -0
  40. package/dist/open-api/convert/convert-engine.d.ts +26 -0
  41. package/dist/open-api/convert/convert-engine.d.ts.map +1 -0
  42. package/dist/open-api/convert/convert-engine.js +20 -0
  43. package/dist/open-api/convert/convert-engine.js.map +1 -0
  44. package/dist/open-api/convert/convert-engine.spec.d.ts +2 -0
  45. package/dist/open-api/convert/convert-engine.spec.d.ts.map +1 -0
  46. package/dist/open-api/convert/convert-engine.spec.js +268 -0
  47. package/dist/open-api/convert/convert-engine.spec.js.map +1 -0
  48. package/dist/open-api/convert/handler.d.ts +9 -0
  49. package/dist/open-api/convert/handler.d.ts.map +1 -0
  50. package/dist/open-api/convert/handler.js +54 -0
  51. package/dist/open-api/convert/handler.js.map +1 -0
  52. package/dist/open-api/convert/handler.spec.d.ts +2 -0
  53. package/dist/open-api/convert/handler.spec.d.ts.map +1 -0
  54. package/dist/open-api/convert/handler.spec.js +291 -0
  55. package/dist/open-api/convert/handler.spec.js.map +1 -0
  56. package/dist/open-api/merge/ajv.d.ts.map +1 -0
  57. package/dist/open-api/merge/ajv.js.map +1 -0
  58. package/dist/open-api/merge/handler.d.ts +9 -0
  59. package/dist/open-api/merge/handler.d.ts.map +1 -0
  60. package/dist/{source/import-openapi → open-api/merge}/handler.js +16 -42
  61. package/dist/open-api/merge/handler.js.map +1 -0
  62. package/dist/open-api/merge/handler.spec.d.ts +2 -0
  63. package/dist/open-api/merge/handler.spec.d.ts.map +1 -0
  64. package/dist/open-api/merge/handler.spec.js +335 -0
  65. package/dist/open-api/merge/handler.spec.js.map +1 -0
  66. package/dist/open-api/merge/interfaces.d.ts.map +1 -0
  67. package/dist/open-api/merge/interfaces.js.map +1 -0
  68. package/dist/open-api/merge/merge-engine.d.ts +23 -0
  69. package/dist/open-api/merge/merge-engine.d.ts.map +1 -0
  70. package/dist/open-api/merge/merge-engine.js +33 -0
  71. package/dist/open-api/merge/merge-engine.js.map +1 -0
  72. package/dist/open-api/merge/merge-engine.spec.d.ts +2 -0
  73. package/dist/open-api/merge/merge-engine.spec.d.ts.map +1 -0
  74. package/dist/open-api/merge/merge-engine.spec.js +117 -0
  75. package/dist/open-api/merge/merge-engine.spec.js.map +1 -0
  76. package/dist/open-api/merge/utils.d.ts.map +1 -0
  77. package/dist/open-api/merge/utils.js.map +1 -0
  78. package/dist/open-api/overlay/handler.d.ts +10 -0
  79. package/dist/open-api/overlay/handler.d.ts.map +1 -0
  80. package/dist/open-api/overlay/handler.js +92 -0
  81. package/dist/open-api/overlay/handler.js.map +1 -0
  82. package/dist/open-api/overlay/handler.spec.d.ts +2 -0
  83. package/dist/open-api/overlay/handler.spec.d.ts.map +1 -0
  84. package/dist/open-api/overlay/handler.spec.js +304 -0
  85. package/dist/open-api/overlay/handler.spec.js.map +1 -0
  86. package/dist/open-api/overlay/overlay-engine.d.ts +55 -0
  87. package/dist/open-api/overlay/overlay-engine.d.ts.map +1 -0
  88. package/dist/open-api/overlay/overlay-engine.js +280 -0
  89. package/dist/open-api/overlay/overlay-engine.js.map +1 -0
  90. package/dist/open-api/overlay/overlay-engine.spec.d.ts +2 -0
  91. package/dist/open-api/overlay/overlay-engine.spec.d.ts.map +1 -0
  92. package/dist/open-api/overlay/overlay-engine.spec.js +609 -0
  93. package/dist/open-api/overlay/overlay-engine.spec.js.map +1 -0
  94. package/dist/source/migrate/dev-portal/handler.d.ts.map +1 -0
  95. package/dist/{cmds/source/migrate → source/migrate/dev-portal}/handler.js +53 -4
  96. package/dist/source/migrate/dev-portal/handler.js.map +1 -0
  97. package/dist/{cmds/source/migrate → source/migrate/dev-portal}/types.d.ts +12 -1
  98. package/dist/source/migrate/dev-portal/types.d.ts.map +1 -0
  99. package/dist/source/migrate/dev-portal/types.js.map +1 -0
  100. package/dist/tsconfig.tsbuildinfo +1 -1
  101. package/package.json +5 -4
  102. package/dist/cmds/source/migrate/handler.d.ts.map +0 -1
  103. package/dist/cmds/source/migrate/handler.js.map +0 -1
  104. package/dist/cmds/source/migrate/runner.d.ts.map +0 -1
  105. package/dist/cmds/source/migrate/runner.js.map +0 -1
  106. package/dist/cmds/source/migrate/stringify-config.d.ts.map +0 -1
  107. package/dist/cmds/source/migrate/stringify-config.js.map +0 -1
  108. package/dist/cmds/source/migrate/stringify-config.test.d.ts.map +0 -1
  109. package/dist/cmds/source/migrate/stringify-config.test.js.map +0 -1
  110. package/dist/cmds/source/migrate/types.d.ts.map +0 -1
  111. package/dist/cmds/source/migrate/types.js.map +0 -1
  112. package/dist/source/import-openapi/ajv.d.ts.map +0 -1
  113. package/dist/source/import-openapi/ajv.js.map +0 -1
  114. package/dist/source/import-openapi/handler.d.ts +0 -13
  115. package/dist/source/import-openapi/handler.d.ts.map +0 -1
  116. package/dist/source/import-openapi/handler.js.map +0 -1
  117. package/dist/source/import-openapi/interfaces.d.ts.map +0 -1
  118. package/dist/source/import-openapi/interfaces.js.map +0 -1
  119. package/dist/source/import-openapi/utils.d.ts.map +0 -1
  120. package/dist/source/import-openapi/utils.js.map +0 -1
  121. /package/dist/{cmds/source/migrate → common}/runner.d.ts +0 -0
  122. /package/dist/{cmds/source/migrate → common}/runner.js +0 -0
  123. /package/dist/{cmds/source/migrate → common/utils}/stringify-config.d.ts +0 -0
  124. /package/dist/{cmds/source/migrate → common/utils}/stringify-config.js +0 -0
  125. /package/dist/{cmds/source/migrate → common/utils}/stringify-config.test.d.ts +0 -0
  126. /package/dist/{cmds/source/migrate → common/utils}/stringify-config.test.js +0 -0
  127. /package/dist/{source/import-openapi → open-api/merge}/ajv.d.ts +0 -0
  128. /package/dist/{source/import-openapi → open-api/merge}/ajv.js +0 -0
  129. /package/dist/{source/import-openapi → open-api/merge}/interfaces.d.ts +0 -0
  130. /package/dist/{source/import-openapi → open-api/merge}/interfaces.js +0 -0
  131. /package/dist/{source/import-openapi → open-api/merge}/utils.d.ts +0 -0
  132. /package/dist/{source/import-openapi → open-api/merge}/utils.js +0 -0
  133. /package/dist/{cmds/source/migrate → source/migrate/dev-portal}/handler.d.ts +0 -0
  134. /package/dist/{cmds/source/migrate → source/migrate/dev-portal}/types.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-engine.spec.js","sourceRoot":"","sources":["../../../src/open-api/merge/merge-engine.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert\";\nimport {\n isUrl,\n guessFileNameFromUrl,\n detectFormat,\n detectFormatFromContent,\n} from \"./merge-engine.js\";\n\ndescribe(\"Merge Engine\", () => {\n describe(\"isUrl\", () => {\n it(\"should return true for valid HTTP URLs\", () => {\n assert.strictEqual(isUrl(\"http://example.com\"), true);\n assert.strictEqual(isUrl(\"http://example.com/api.json\"), true);\n assert.strictEqual(isUrl(\"http://api.example.com/v1/openapi.yaml\"), true);\n });\n\n it(\"should return true for valid HTTPS URLs\", () => {\n assert.strictEqual(isUrl(\"https://example.com\"), true);\n assert.strictEqual(isUrl(\"https://example.com/api.json\"), true);\n assert.strictEqual(\n isUrl(\"https://api.example.com/v1/openapi.yaml\"),\n true\n );\n });\n\n it(\"should return true for URLs with query parameters\", () => {\n assert.strictEqual(isUrl(\"https://example.com/api?version=1.0\"), true);\n assert.strictEqual(\n isUrl(\"https://example.com/api?format=json&version=2\"),\n true\n );\n });\n\n it(\"should return true for URLs with fragments\", () => {\n assert.strictEqual(isUrl(\"https://example.com/api#section\"), true);\n assert.strictEqual(\n isUrl(\"https://example.com/api.json#definitions\"),\n true\n );\n });\n\n it(\"should return true for URLs with ports\", () => {\n assert.strictEqual(isUrl(\"https://example.com:8080/api\"), true);\n assert.strictEqual(isUrl(\"http://localhost:3000/openapi.json\"), true);\n });\n\n it(\"should return false for relative file paths\", () => {\n assert.strictEqual(isUrl(\"./api.json\"), false);\n assert.strictEqual(isUrl(\"../specs/openapi.yaml\"), false);\n assert.strictEqual(isUrl(\"docs/api.json\"), false);\n });\n\n it(\"should return false for absolute file paths\", () => {\n assert.strictEqual(isUrl(\"/path/to/api.json\"), false);\n assert.strictEqual(isUrl(\"/Users/name/docs/openapi.yaml\"), false);\n // Windows absolute paths with drive letters may be interpreted as URLs with protocol\n // This is expected behavior from the URL constructor\n });\n\n it(\"should return false for filenames without paths\", () => {\n assert.strictEqual(isUrl(\"api.json\"), false);\n assert.strictEqual(isUrl(\"openapi.yaml\"), false);\n });\n\n it(\"should return false for empty strings\", () => {\n assert.strictEqual(isUrl(\"\"), false);\n });\n });\n\n describe(\"guessFileNameFromUrl\", () => {\n it(\"should extract filename from URL path\", () => {\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/api.json\"),\n \"api\"\n );\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/openapi.yaml\"),\n \"openapi\"\n );\n });\n\n it(\"should extract filename from URL with multiple path segments\", () => {\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/v1/specs/api.json\"),\n \"api\"\n );\n assert.strictEqual(\n guessFileNameFromUrl(\"https://api.example.com/docs/v2/openapi.yaml\"),\n \"openapi\"\n );\n });\n\n it(\"should extract filename from URL with query parameters\", () => {\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/api.json?version=1\"),\n \"api\"\n );\n assert.strictEqual(\n guessFileNameFromUrl(\n \"https://example.com/openapi.yaml?format=json&v=2\"\n ),\n \"openapi\"\n );\n });\n\n it(\"should extract filename from URL with fragments\", () => {\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/api.json#section\"),\n \"api\"\n );\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/spec.yaml#definitions\"),\n \"spec\"\n );\n });\n\n it(\"should handle URLs with no file extension\", () => {\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/api\"),\n \"api\"\n );\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/v1/openapi\"),\n \"openapi\"\n );\n });\n\n it(\"should handle URLs ending with slash\", () => {\n // When URL ends with slash, pop() returns empty string, should use base64\n const result = guessFileNameFromUrl(\"https://example.com/api/\");\n assert.strictEqual(result.startsWith(\"imported-\"), true);\n });\n\n it(\"should generate base64 name for root URLs\", () => {\n const result = guessFileNameFromUrl(\"https://example.com/\");\n assert.strictEqual(result.startsWith(\"imported-\"), true);\n assert.strictEqual(result.length > 9, true); // \"imported-\" is 9 chars\n });\n\n it(\"should handle filenames with multiple dots\", () => {\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/api.v1.0.json\"),\n \"api.v1.0\"\n );\n assert.strictEqual(\n guessFileNameFromUrl(\"https://example.com/my.api.spec.yaml\"),\n \"my.api.spec\"\n );\n });\n\n it(\"should handle complex URLs\", () => {\n assert.strictEqual(\n guessFileNameFromUrl(\n \"https://api.example.com:8080/v2/specs/openapi.json?auth=token#info\"\n ),\n \"openapi\"\n );\n });\n\n it(\"should generate consistent base64 names for same URL\", () => {\n const url = \"https://example.com/\";\n const name1 = guessFileNameFromUrl(url);\n const name2 = guessFileNameFromUrl(url);\n assert.strictEqual(name1, name2);\n });\n });\n\n describe(\"detectFormat (re-exported from common)\", () => {\n it(\"should detect JSON format\", () => {\n assert.strictEqual(detectFormat(\"api.json\"), \"json\");\n assert.strictEqual(detectFormat(\"/path/to/api.json\"), \"json\");\n });\n\n it(\"should detect YAML format\", () => {\n assert.strictEqual(detectFormat(\"api.yaml\"), \"yaml\");\n assert.strictEqual(detectFormat(\"api.yml\"), \"yaml\");\n });\n\n it(\"should return null for unknown extensions\", () => {\n assert.strictEqual(detectFormat(\"api.txt\"), null);\n });\n });\n\n describe(\"detectFormatFromContent (re-exported from common)\", () => {\n it(\"should detect JSON content\", () => {\n const content = '{\"openapi\": \"3.1.0\"}';\n assert.strictEqual(detectFormatFromContent(content), \"json\");\n });\n\n it(\"should detect YAML content\", () => {\n const content = \"openapi: 3.1.0\\ninfo:\\n title: Test\";\n assert.strictEqual(detectFormatFromContent(content), \"yaml\");\n });\n\n it(\"should throw error for invalid content\", () => {\n const content = \"not valid json or yaml: : :\";\n assert.throws(\n () => detectFormatFromContent(content),\n /Failed to parse content/\n );\n });\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/open-api/merge/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,mBAAmB,UAA6B,CAAC;AAE9D,eAAO,MAAM,gBAAgB,GAAU,SAAS,MAAM,EAAE,UAAU,MAAM,6DAYvE,CAAC;AAMF,eAAO,MAAM,0BAA0B,GACrC,SAAS,WAAW,CAAC,QAAQ,GAAG,oBAAoB,SA4BrD,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/open-api/merge/utils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,OAAO,EAAE,EAAE,EAAE,MAAM,MAAM,CAAC;AAG1B,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAClD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAe,EAAE,QAAgB,EAAE,EAAE;IAC1E,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,gDAAgD,mBAAmB,CAAC,IAAI,CACtE,IAAI,CACL,EAAE,CACJ,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAgD,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAgD,CAAC;AAC5E,CAAC,CAAC;AAMF,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,OAAoD,EACpD,EAAE;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG;YACd,KAAK;YACL,KAAK;YACL,MAAM;YACN,QAAQ;YACR,SAAS;YACT,MAAM;YACN,OAAO;YACP,OAAO;SACqB,CAAC;QAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,SAAS,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;gBACxC,SAAS,CAAC,WAAW,GAAG,EAAE,EAAE,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAC","sourcesContent":["import yaml from \"js-yaml\";\nimport { OpenAPIV3_1 } from \"openapi-types\";\nimport { v4 } from \"uuid\";\nimport { ZuploOpenApiDocument } from \"./interfaces.js\";\n\nexport const OPERATION_PATH_MERGE_DELIMITER = \">\";\nexport const OPEN_API_FILE_TYPES = [\".json\", \".yml\", \".yaml\"];\n\nexport const parseOpenApiFile = async (extName: string, fileText: string) => {\n if (!OPEN_API_FILE_TYPES.includes(extName)) {\n throw new Error(\n `Invalid file type. Supported file types are: ${OPEN_API_FILE_TYPES.join(\n \", \"\n )}`\n );\n }\n if (extName.includes(\"json\")) {\n return JSON.parse(fileText) as OpenAPIV3_1.Document | ZuploOpenApiDocument;\n }\n return yaml.load(fileText) as OpenAPIV3_1.Document | ZuploOpenApiDocument;\n};\n\n/**\n * Add operation ID to any operations that don't have one, this makes\n * onboarding smoother for new users\n */\nexport const addOperationIdsAsNecessary = (\n openApi: OpenAPIV3_1.Document | ZuploOpenApiDocument\n) => {\n const paths = openApi.paths;\n if (!paths) {\n return;\n }\n for (const path of Object.keys(paths)) {\n const pathItem = paths[path];\n if (!pathItem) {\n continue;\n }\n const methods = [\n \"get\",\n \"put\",\n \"post\",\n \"delete\",\n \"options\",\n \"head\",\n \"patch\",\n \"trace\",\n ] as OpenAPIV3_1.HttpMethods[];\n for (const method of methods) {\n const operation = pathItem[method];\n if (operation && !operation.operationId) {\n operation.operationId = v4();\n }\n }\n }\n};\n"]}
@@ -0,0 +1,10 @@
1
+ export interface Arguments {
2
+ overlay: string;
3
+ input: string;
4
+ output: string;
5
+ format?: "json" | "yaml";
6
+ json?: boolean;
7
+ yaml?: boolean;
8
+ }
9
+ export declare function applyOverlay(args: Arguments): Promise<void>;
10
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.ts"],"names":[],"mappings":"AAkBA,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;AA2DD,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEjE"}
@@ -0,0 +1,92 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { detectFormatFromExtension, parseFile, serializeContent, } from "../../common/file-format.js";
4
+ import { printDiagnosticsToConsole } from "../../common/output.js";
5
+ import { logger } from "../../common/logger.js";
6
+ import { applyOverlay as applyOverlayEngine, applyAction, deepClone, } from "./overlay-engine.js";
7
+ function applyOverlayWithProgress(openapi, overlay) {
8
+ printDiagnosticsToConsole(`\nApplying overlay: ${overlay.info?.title || "Unnamed"}`);
9
+ printDiagnosticsToConsole(`Version: ${overlay.overlay || "unknown"}\n`);
10
+ const result = deepClone(openapi);
11
+ const stats = { applied: 0, skipped: 0, totalNodes: 0 };
12
+ for (const [index, action] of overlay.actions.entries()) {
13
+ const desc = action.description || `Action ${index + 1}`;
14
+ process.stdout.write(` [${index + 1}/${overlay.actions.length}] ${desc}... `);
15
+ try {
16
+ const { applied, count } = applyAction(result, action);
17
+ if (applied) {
18
+ printDiagnosticsToConsole(`✓ (${count} node${count !== 1 ? "s" : ""})`);
19
+ stats.applied++;
20
+ stats.totalNodes += count;
21
+ }
22
+ else {
23
+ printDiagnosticsToConsole("⊘ skipped");
24
+ stats.skipped++;
25
+ }
26
+ }
27
+ catch (error) {
28
+ printDiagnosticsToConsole(`✗ failed`);
29
+ logger.warn(error, `Failed to apply action: ${desc}`);
30
+ stats.skipped++;
31
+ }
32
+ }
33
+ printDiagnosticsToConsole(`\n=== Summary ===`);
34
+ printDiagnosticsToConsole(`Applied: ${stats.applied}/${overlay.actions.length} actions`);
35
+ printDiagnosticsToConsole(`Modified: ${stats.totalNodes} nodes`);
36
+ if (stats.skipped > 0) {
37
+ printDiagnosticsToConsole(`Skipped: ${stats.skipped} actions`);
38
+ }
39
+ const { result: finalResult } = applyOverlayEngine(openapi, overlay);
40
+ return finalResult;
41
+ }
42
+ export async function applyOverlay(args) {
43
+ const { overlay: overlayPath, input: openapiPath, output: outputPath } = args;
44
+ if (!fs.existsSync(openapiPath)) {
45
+ throw new Error(`OpenAPI file not found: ${openapiPath}`);
46
+ }
47
+ if (!fs.existsSync(overlayPath)) {
48
+ throw new Error(`Overlay file not found: ${overlayPath}`);
49
+ }
50
+ printDiagnosticsToConsole("OpenAPI Overlay Applicator");
51
+ printDiagnosticsToConsole("===========================");
52
+ printDiagnosticsToConsole(`OpenAPI file: ${openapiPath}`);
53
+ printDiagnosticsToConsole(`Overlay file: ${overlayPath}`);
54
+ printDiagnosticsToConsole(`Output file: ${outputPath}`);
55
+ try {
56
+ const openapiContent = fs.readFileSync(openapiPath, "utf-8");
57
+ const overlayContent = fs.readFileSync(overlayPath, "utf-8");
58
+ const { document: openapi } = parseFile(openapiContent, openapiPath);
59
+ const { document: overlay } = parseFile(overlayContent, overlayPath);
60
+ if (!overlay.overlay || !overlay.actions) {
61
+ throw new Error("Invalid overlay format. Must include 'overlay' version and 'actions' array.");
62
+ }
63
+ const result = applyOverlayWithProgress(openapi, overlay);
64
+ let outputFormat;
65
+ if (args.format) {
66
+ outputFormat = args.format;
67
+ }
68
+ else if (args.json) {
69
+ outputFormat = "json";
70
+ }
71
+ else if (args.yaml) {
72
+ outputFormat = "yaml";
73
+ }
74
+ else {
75
+ const formatFromExt = detectFormatFromExtension(outputPath);
76
+ outputFormat = formatFromExt || "json";
77
+ }
78
+ const outputContent = serializeContent(result, outputFormat);
79
+ const outputDir = path.dirname(outputPath);
80
+ if (!fs.existsSync(outputDir)) {
81
+ fs.mkdirSync(outputDir, { recursive: true });
82
+ }
83
+ fs.writeFileSync(outputPath, outputContent, "utf-8");
84
+ printDiagnosticsToConsole(`\n✓ Output written to: ${outputPath} (${outputFormat.toUpperCase()})`);
85
+ }
86
+ catch (error) {
87
+ logger.error(error, "Error applying overlay");
88
+ printDiagnosticsToConsole(`Error: ${error.message}`);
89
+ throw error;
90
+ }
91
+ }
92
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +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 parseFile,\n serializeContent,\n type FileFormat,\n} from \"../../common/file-format.js\";\nimport { printDiagnosticsToConsole } from \"../../common/output.js\";\nimport { logger } from \"../../common/logger.js\";\nimport {\n applyOverlay as applyOverlayEngine,\n applyAction,\n deepClone,\n type OverlayDocument,\n} 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 */\n// biome-ignore lint/suspicious/noExplicitAny: Working with dynamic JSON structures\nfunction applyOverlayWithProgress(openapi: any, overlay: OverlayDocument): any {\n printDiagnosticsToConsole(\n `\\nApplying overlay: ${overlay.info?.title || \"Unnamed\"}`\n );\n printDiagnosticsToConsole(`Version: ${overlay.overlay || \"unknown\"}\\n`);\n\n // Clone the document for modification\n const result = deepClone(openapi);\n const stats = { applied: 0, skipped: 0, totalNodes: 0 };\n\n // Apply actions with progress reporting\n for (const [index, action] of overlay.actions.entries()) {\n const desc = action.description || `Action ${index + 1}`;\n process.stdout.write(\n ` [${index + 1}/${overlay.actions.length}] ${desc}... `\n );\n\n try {\n const { applied, count } = applyAction(result, action);\n\n if (applied) {\n printDiagnosticsToConsole(`✓ (${count} node${count !== 1 ? \"s\" : \"\"})`);\n stats.applied++;\n stats.totalNodes += count;\n } else {\n printDiagnosticsToConsole(\"⊘ skipped\");\n stats.skipped++;\n }\n } catch (error) {\n printDiagnosticsToConsole(`✗ failed`);\n logger.warn(error, `Failed to apply action: ${desc}`);\n stats.skipped++;\n }\n }\n\n printDiagnosticsToConsole(`\\n=== Summary ===`);\n printDiagnosticsToConsole(\n `Applied: ${stats.applied}/${overlay.actions.length} actions`\n );\n printDiagnosticsToConsole(`Modified: ${stats.totalNodes} nodes`);\n if (stats.skipped > 0) {\n printDiagnosticsToConsole(`Skipped: ${stats.skipped} actions`);\n }\n\n // Use the engine's reordering functions\n const { result: finalResult } = applyOverlayEngine(openapi, overlay);\n\n return finalResult;\n}\n\n/**\n * Main handler function\n */\nexport async function applyOverlay(args: Arguments): Promise<void> {\n const { overlay: overlayPath, input: openapiPath, output: outputPath } = args;\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 const { document: openapi } = parseFile(openapiContent, openapiPath);\n const { document: overlay } = parseFile(overlayContent, overlayPath);\n\n // Validate overlay format\n if (!overlay.overlay || !overlay.actions) {\n throw new Error(\n \"Invalid overlay format. Must include 'overlay' version and 'actions' array.\"\n );\n }\n\n // Apply overlay with progress output\n const result = applyOverlayWithProgress(\n openapi,\n overlay as OverlayDocument\n );\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"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=handler.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.spec.d.ts","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,304 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { afterEach, beforeEach, describe, it } from "node:test";
4
+ import { fileURLToPath } from "node:url";
5
+ import assert from "node:assert";
6
+ import { applyOverlay } from "./handler.js";
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const testTmpPath = path.join(__dirname, "..", "..", "__tests__", "test-tmp", "overlay-handler");
10
+ describe("Overlay Handler", () => {
11
+ beforeEach(async () => {
12
+ await fs.mkdir(testTmpPath, { recursive: true });
13
+ });
14
+ afterEach(async () => {
15
+ try {
16
+ await fs.rm(testTmpPath, { recursive: true, force: true });
17
+ }
18
+ catch {
19
+ }
20
+ });
21
+ describe("applyOverlay", () => {
22
+ it("should apply overlay to OpenAPI document (JSON to JSON)", async () => {
23
+ const inputPath = path.join(testTmpPath, "input.json");
24
+ const overlayPath = path.join(testTmpPath, "overlay.json");
25
+ const outputPath = path.join(testTmpPath, "output.json");
26
+ const inputDoc = {
27
+ openapi: "3.1.0",
28
+ info: {
29
+ title: "Original API",
30
+ version: "1.0.0",
31
+ },
32
+ paths: {},
33
+ };
34
+ const overlayDoc = {
35
+ overlay: "1.0.0",
36
+ info: {
37
+ title: "Test Overlay",
38
+ version: "1.0.0",
39
+ },
40
+ actions: [
41
+ {
42
+ target: "$.info.title",
43
+ update: "Updated API",
44
+ },
45
+ ],
46
+ };
47
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
48
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
49
+ await applyOverlay({
50
+ input: inputPath,
51
+ overlay: overlayPath,
52
+ output: outputPath,
53
+ });
54
+ const result = JSON.parse(await fs.readFile(outputPath, "utf-8"));
55
+ assert.strictEqual(result.info.title, "Updated API");
56
+ assert.strictEqual(result.openapi, "3.1.0");
57
+ });
58
+ it("should support YAML input and JSON output", async () => {
59
+ const inputPath = path.join(testTmpPath, "input.yaml");
60
+ const overlayPath = path.join(testTmpPath, "overlay.json");
61
+ const outputPath = path.join(testTmpPath, "output.json");
62
+ const inputDoc = `openapi: 3.1.0
63
+ info:
64
+ title: Original API
65
+ version: 1.0.0
66
+ paths: {}`;
67
+ const overlayDoc = {
68
+ overlay: "1.0.0",
69
+ info: {
70
+ title: "Test Overlay",
71
+ version: "1.0.0",
72
+ },
73
+ actions: [
74
+ {
75
+ target: "$.info.version",
76
+ update: "2.0.0",
77
+ },
78
+ ],
79
+ };
80
+ await fs.writeFile(inputPath, inputDoc);
81
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
82
+ await applyOverlay({
83
+ input: inputPath,
84
+ overlay: overlayPath,
85
+ output: outputPath,
86
+ });
87
+ const result = JSON.parse(await fs.readFile(outputPath, "utf-8"));
88
+ assert.strictEqual(result.info.version, "2.0.0");
89
+ });
90
+ it("should support JSON input and YAML output", async () => {
91
+ const inputPath = path.join(testTmpPath, "input.json");
92
+ const overlayPath = path.join(testTmpPath, "overlay.json");
93
+ const outputPath = path.join(testTmpPath, "output.yaml");
94
+ const inputDoc = {
95
+ openapi: "3.1.0",
96
+ info: {
97
+ title: "Original API",
98
+ version: "1.0.0",
99
+ },
100
+ paths: {},
101
+ };
102
+ const overlayDoc = {
103
+ overlay: "1.0.0",
104
+ info: {
105
+ title: "Test Overlay",
106
+ version: "1.0.0",
107
+ },
108
+ actions: [],
109
+ };
110
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
111
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
112
+ await applyOverlay({
113
+ input: inputPath,
114
+ overlay: overlayPath,
115
+ output: outputPath,
116
+ });
117
+ const result = await fs.readFile(outputPath, "utf-8");
118
+ assert.strictEqual(result.includes("openapi: 3.1.0"), true);
119
+ assert.strictEqual(result.includes("title: Original API"), true);
120
+ });
121
+ it("should support --format flag to override output format", async () => {
122
+ const inputPath = path.join(testTmpPath, "input.json");
123
+ const overlayPath = path.join(testTmpPath, "overlay.json");
124
+ const outputPath = path.join(testTmpPath, "output.txt");
125
+ const inputDoc = {
126
+ openapi: "3.1.0",
127
+ info: {
128
+ title: "Original API",
129
+ version: "1.0.0",
130
+ },
131
+ paths: {},
132
+ };
133
+ const overlayDoc = {
134
+ overlay: "1.0.0",
135
+ info: {
136
+ title: "Test Overlay",
137
+ version: "1.0.0",
138
+ },
139
+ actions: [],
140
+ };
141
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
142
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
143
+ await applyOverlay({
144
+ input: inputPath,
145
+ overlay: overlayPath,
146
+ output: outputPath,
147
+ format: "yaml",
148
+ });
149
+ const result = await fs.readFile(outputPath, "utf-8");
150
+ assert.strictEqual(result.includes("openapi: 3.1.0"), true);
151
+ });
152
+ it("should support --json flag", async () => {
153
+ const inputPath = path.join(testTmpPath, "input.yaml");
154
+ const overlayPath = path.join(testTmpPath, "overlay.yaml");
155
+ const outputPath = path.join(testTmpPath, "output.txt");
156
+ const inputDoc = `openapi: 3.1.0
157
+ info:
158
+ title: Original API
159
+ version: 1.0.0
160
+ paths: {}`;
161
+ const overlayDoc = `overlay: 1.0.0
162
+ info:
163
+ title: Test Overlay
164
+ version: 1.0.0
165
+ actions: []`;
166
+ await fs.writeFile(inputPath, inputDoc);
167
+ await fs.writeFile(overlayPath, overlayDoc);
168
+ await applyOverlay({
169
+ input: inputPath,
170
+ overlay: overlayPath,
171
+ output: outputPath,
172
+ json: true,
173
+ });
174
+ const result = await fs.readFile(outputPath, "utf-8");
175
+ const parsed = JSON.parse(result);
176
+ assert.strictEqual(parsed.openapi, "3.1.0");
177
+ });
178
+ it("should support --yaml flag", async () => {
179
+ const inputPath = path.join(testTmpPath, "input.json");
180
+ const overlayPath = path.join(testTmpPath, "overlay.json");
181
+ const outputPath = path.join(testTmpPath, "output.txt");
182
+ const inputDoc = {
183
+ openapi: "3.1.0",
184
+ info: {
185
+ title: "Original API",
186
+ version: "1.0.0",
187
+ },
188
+ paths: {},
189
+ };
190
+ const overlayDoc = {
191
+ overlay: "1.0.0",
192
+ info: {
193
+ title: "Test Overlay",
194
+ version: "1.0.0",
195
+ },
196
+ actions: [],
197
+ };
198
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
199
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
200
+ await applyOverlay({
201
+ input: inputPath,
202
+ overlay: overlayPath,
203
+ output: outputPath,
204
+ yaml: true,
205
+ });
206
+ const result = await fs.readFile(outputPath, "utf-8");
207
+ assert.strictEqual(result.includes("openapi: 3.1.0"), true);
208
+ });
209
+ it("should create output directory if it doesn't exist", async () => {
210
+ const inputPath = path.join(testTmpPath, "input.json");
211
+ const overlayPath = path.join(testTmpPath, "overlay.json");
212
+ const outputPath = path.join(testTmpPath, "nested", "dir", "output.json");
213
+ const inputDoc = {
214
+ openapi: "3.1.0",
215
+ info: {
216
+ title: "Original API",
217
+ version: "1.0.0",
218
+ },
219
+ paths: {},
220
+ };
221
+ const overlayDoc = {
222
+ overlay: "1.0.0",
223
+ info: {
224
+ title: "Test Overlay",
225
+ version: "1.0.0",
226
+ },
227
+ actions: [],
228
+ };
229
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
230
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
231
+ await applyOverlay({
232
+ input: inputPath,
233
+ overlay: overlayPath,
234
+ output: outputPath,
235
+ });
236
+ const result = JSON.parse(await fs.readFile(outputPath, "utf-8"));
237
+ assert.strictEqual(result.openapi, "3.1.0");
238
+ });
239
+ it("should throw error when input file does not exist", async () => {
240
+ const inputPath = path.join(testTmpPath, "nonexistent.json");
241
+ const overlayPath = path.join(testTmpPath, "overlay.json");
242
+ const outputPath = path.join(testTmpPath, "output.json");
243
+ const overlayDoc = {
244
+ overlay: "1.0.0",
245
+ info: {
246
+ title: "Test Overlay",
247
+ version: "1.0.0",
248
+ },
249
+ actions: [],
250
+ };
251
+ await fs.writeFile(overlayPath, JSON.stringify(overlayDoc, null, 2));
252
+ await assert.rejects(() => applyOverlay({
253
+ input: inputPath,
254
+ overlay: overlayPath,
255
+ output: outputPath,
256
+ }), /OpenAPI file not found/);
257
+ });
258
+ it("should throw error when overlay file does not exist", async () => {
259
+ const inputPath = path.join(testTmpPath, "input.json");
260
+ const overlayPath = path.join(testTmpPath, "nonexistent.json");
261
+ const outputPath = path.join(testTmpPath, "output.json");
262
+ const inputDoc = {
263
+ openapi: "3.1.0",
264
+ info: {
265
+ title: "Original API",
266
+ version: "1.0.0",
267
+ },
268
+ paths: {},
269
+ };
270
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
271
+ await assert.rejects(() => applyOverlay({
272
+ input: inputPath,
273
+ overlay: overlayPath,
274
+ output: outputPath,
275
+ }), /Overlay file not found/);
276
+ });
277
+ it("should throw error when overlay is invalid", async () => {
278
+ const inputPath = path.join(testTmpPath, "input.json");
279
+ const overlayPath = path.join(testTmpPath, "overlay.json");
280
+ const outputPath = path.join(testTmpPath, "output.json");
281
+ const inputDoc = {
282
+ openapi: "3.1.0",
283
+ info: {
284
+ title: "Original API",
285
+ version: "1.0.0",
286
+ },
287
+ paths: {},
288
+ };
289
+ const invalidOverlay = {
290
+ info: {
291
+ title: "Missing overlay version",
292
+ },
293
+ };
294
+ await fs.writeFile(inputPath, JSON.stringify(inputDoc, null, 2));
295
+ await fs.writeFile(overlayPath, JSON.stringify(invalidOverlay, null, 2));
296
+ await assert.rejects(() => applyOverlay({
297
+ input: inputPath,
298
+ overlay: overlayPath,
299
+ output: outputPath,
300
+ }), /Invalid overlay format/);
301
+ });
302
+ });
303
+ });
304
+ //# sourceMappingURL=handler.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.spec.js","sourceRoot":"","sources":["../../../src/open-api/overlay/handler.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAC3B,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,UAAU,EACV,iBAAiB,CAClB,CAAC;AAEF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,UAAU,CAAC,KAAK,IAAI,EAAE;QAEpB,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QAEnB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,QAAQ,GAAG;gBACf,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,KAAK,EAAE,EAAE;aACV,CAAC;YAEF,MAAM,UAAU,GAAG;gBACjB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,OAAO,EAAE;oBACP;wBACE,MAAM,EAAE,cAAc;wBACtB,MAAM,EAAE,aAAa;qBACtB;iBACF;aACF,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAErE,MAAM,YAAY,CAAC;gBACjB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;aACnB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAClE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YACrD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,QAAQ,GAAG;;;;UAIb,CAAC;YAEL,MAAM,UAAU,GAAG;gBACjB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,OAAO,EAAE;oBACP;wBACE,MAAM,EAAE,gBAAgB;wBACxB,MAAM,EAAE,OAAO;qBAChB;iBACF;aACF,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACxC,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAErE,MAAM,YAAY,CAAC;gBACjB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;aACnB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAClE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,QAAQ,GAAG;gBACf,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,KAAK,EAAE,EAAE;aACV,CAAC;YAEF,MAAM,UAAU,GAAG;gBACjB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,OAAO,EAAE,EAAE;aACZ,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAErE,MAAM,YAAY,CAAC;gBACjB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;aACnB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC;YAC5D,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,IAAI,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;YACtE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAExD,MAAM,QAAQ,GAAG;gBACf,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,KAAK,EAAE,EAAE;aACV,CAAC;YAEF,MAAM,UAAU,GAAG;gBACjB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,OAAO,EAAE,EAAE;aACZ,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAErE,MAAM,YAAY,CAAC;gBACjB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;gBAClB,MAAM,EAAE,MAAM;aACf,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAExD,MAAM,QAAQ,GAAG;;;;UAIb,CAAC;YAEL,MAAM,UAAU,GAAG;;;;YAIb,CAAC;YAEP,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YACxC,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YAE5C,MAAM,YAAY,CAAC;gBACjB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;gBAClB,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAExD,MAAM,QAAQ,GAAG;gBACf,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,KAAK,EAAE,EAAE;aACV,CAAC;YAEF,MAAM,UAAU,GAAG;gBACjB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,OAAO,EAAE,EAAE;aACZ,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAErE,MAAM,YAAY,CAAC;gBACjB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;gBAClB,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;YAE1E,MAAM,QAAQ,GAAG;gBACf,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,KAAK,EAAE,EAAE;aACV,CAAC;YAEF,MAAM,UAAU,GAAG;gBACjB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,OAAO,EAAE,EAAE;aACZ,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAErE,MAAM,YAAY,CAAC;gBACjB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;aACnB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAClE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;YAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,UAAU,GAAG;gBACjB,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,OAAO,EAAE,EAAE;aACZ,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAErE,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CACH,YAAY,CAAC;gBACX,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;aACnB,CAAC,EACJ,wBAAwB,CACzB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;YAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,QAAQ,GAAG;gBACf,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,KAAK,EAAE,EAAE;aACV,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAEjE,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CACH,YAAY,CAAC;gBACX,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;aACnB,CAAC,EACJ,wBAAwB,CACzB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;YAEzD,MAAM,QAAQ,GAAG;gBACf,OAAO,EAAE,OAAO;gBAChB,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,OAAO,EAAE,OAAO;iBACjB;gBACD,KAAK,EAAE,EAAE;aACV,CAAC;YAEF,MAAM,cAAc,GAAG;gBACrB,IAAI,EAAE;oBACJ,KAAK,EAAE,yBAAyB;iBACjC;aACF,CAAC;YAEF,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAEzE,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CACH,YAAY,CAAC;gBACX,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,UAAU;aACnB,CAAC,EACJ,wBAAwB,CACzB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { fileURLToPath } from \"node:url\";\nimport assert from \"node:assert\";\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"]}
@@ -0,0 +1,55 @@
1
+ export interface OverlayDocument {
2
+ overlay: string;
3
+ info: {
4
+ title: string;
5
+ version: string;
6
+ };
7
+ actions: OverlayAction[];
8
+ extends?: string;
9
+ }
10
+ export interface OverlayAction {
11
+ target: string;
12
+ description?: string;
13
+ update?: any;
14
+ remove?: boolean | RemoveCondition;
15
+ }
16
+ export interface RemoveCondition {
17
+ empty?: boolean;
18
+ missing?: string;
19
+ }
20
+ export interface ApplyResult {
21
+ applied: boolean;
22
+ count: number;
23
+ }
24
+ export interface OverlayStats {
25
+ applied: number;
26
+ skipped: number;
27
+ totalNodes: number;
28
+ }
29
+ export declare function deepClone<T>(obj: T): T;
30
+ export declare function deepMerge(target: any, source: any): any;
31
+ export declare function checkCondition(
32
+ value: any,
33
+ condition: RemoveCondition
34
+ ): boolean;
35
+ export declare function setValueAtPath(
36
+ doc: any,
37
+ target: string,
38
+ value: any
39
+ ): void;
40
+ export declare function applyAction(
41
+ doc: any,
42
+ action: OverlayAction
43
+ ): ApplyResult;
44
+ export declare function extractPathOrder(overlay: OverlayDocument): string[];
45
+ export declare function reorderOperationProperties(operation: any): any;
46
+ export declare function reorderPaths(doc: any, pathOrder: string[]): any;
47
+ export declare function reorderDocumentProperties(doc: any): any;
48
+ export declare function applyOverlay(
49
+ openapi: any,
50
+ overlay: OverlayDocument
51
+ ): {
52
+ result: any;
53
+ stats: OverlayStats;
54
+ };
55
+ //# sourceMappingURL=overlay-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-engine.d.ts","sourceRoot":"","sources":["../../../src/open-api/overlay/overlay-engine.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAKtC;AAMD,wBAAgB,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,GAAG,CAgDvD;AAKD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,GAAG,EACV,SAAS,EAAE,eAAe,GACzB,OAAO,CA2BT;AAyCD,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAuCzE;AAKD,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,aAAa,GAAG,WAAW,CA+ExE;AAMD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,EAAE,CAiBnE;AAKD,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,GAAG,GAAG,GAAG,CAmB9D;AAKD,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,CAiD/D;AAMD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAmBvD;AAQD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,eAAe,GACvB;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CA8BtC"}