@zuplo/cli 6.64.4 → 6.64.6

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 (85) hide show
  1. package/dist/cmds/delete.d.ts.map +1 -1
  2. package/dist/cmds/delete.js +1 -0
  3. package/dist/cmds/delete.js.map +1 -1
  4. package/dist/cmds/deploy.d.ts.map +1 -1
  5. package/dist/cmds/deploy.js +1 -0
  6. package/dist/cmds/deploy.js.map +1 -1
  7. package/dist/cmds/link.d.ts.map +1 -1
  8. package/dist/cmds/link.js +1 -0
  9. package/dist/cmds/link.js.map +1 -1
  10. package/dist/cmds/list.d.ts.map +1 -1
  11. package/dist/cmds/list.js +1 -0
  12. package/dist/cmds/list.js.map +1 -1
  13. package/dist/cmds/mtls-certificates/create.d.ts.map +1 -1
  14. package/dist/cmds/mtls-certificates/create.js +1 -0
  15. package/dist/cmds/mtls-certificates/create.js.map +1 -1
  16. package/dist/cmds/mtls-certificates/delete.d.ts.map +1 -1
  17. package/dist/cmds/mtls-certificates/delete.js +1 -0
  18. package/dist/cmds/mtls-certificates/delete.js.map +1 -1
  19. package/dist/cmds/mtls-certificates/describe.d.ts.map +1 -1
  20. package/dist/cmds/mtls-certificates/describe.js +1 -0
  21. package/dist/cmds/mtls-certificates/describe.js.map +1 -1
  22. package/dist/cmds/mtls-certificates/disable.d.ts.map +1 -1
  23. package/dist/cmds/mtls-certificates/disable.js +1 -0
  24. package/dist/cmds/mtls-certificates/disable.js.map +1 -1
  25. package/dist/cmds/mtls-certificates/list.d.ts.map +1 -1
  26. package/dist/cmds/mtls-certificates/list.js +1 -0
  27. package/dist/cmds/mtls-certificates/list.js.map +1 -1
  28. package/dist/cmds/mtls-certificates/update.d.ts.map +1 -1
  29. package/dist/cmds/mtls-certificates/update.js +1 -0
  30. package/dist/cmds/mtls-certificates/update.js.map +1 -1
  31. package/dist/cmds/open-api/merge.d.ts.map +1 -1
  32. package/dist/cmds/open-api/merge.js +22 -0
  33. package/dist/cmds/open-api/merge.js.map +1 -1
  34. package/dist/cmds/project/create.d.ts.map +1 -1
  35. package/dist/cmds/project/create.js +1 -0
  36. package/dist/cmds/project/create.js.map +1 -1
  37. package/dist/cmds/proxies/create.d.ts.map +1 -1
  38. package/dist/cmds/proxies/create.js +1 -0
  39. package/dist/cmds/proxies/create.js.map +1 -1
  40. package/dist/cmds/proxies/delete.d.ts.map +1 -1
  41. package/dist/cmds/proxies/delete.js +1 -0
  42. package/dist/cmds/proxies/delete.js.map +1 -1
  43. package/dist/cmds/proxies/describe.d.ts.map +1 -1
  44. package/dist/cmds/proxies/describe.js +1 -0
  45. package/dist/cmds/proxies/describe.js.map +1 -1
  46. package/dist/cmds/proxies/update.d.ts.map +1 -1
  47. package/dist/cmds/proxies/update.js +1 -0
  48. package/dist/cmds/proxies/update.js.map +1 -1
  49. package/dist/cmds/tunnel/create.d.ts.map +1 -1
  50. package/dist/cmds/tunnel/create.js +1 -0
  51. package/dist/cmds/tunnel/create.js.map +1 -1
  52. package/dist/cmds/tunnel/delete.d.ts.map +1 -1
  53. package/dist/cmds/tunnel/delete.js +1 -0
  54. package/dist/cmds/tunnel/delete.js.map +1 -1
  55. package/dist/cmds/tunnel/describe.d.ts.map +1 -1
  56. package/dist/cmds/tunnel/describe.js +1 -0
  57. package/dist/cmds/tunnel/describe.js.map +1 -1
  58. package/dist/cmds/tunnel/list.d.ts.map +1 -1
  59. package/dist/cmds/tunnel/list.js +1 -0
  60. package/dist/cmds/tunnel/list.js.map +1 -1
  61. package/dist/cmds/tunnel/rotate-token.d.ts.map +1 -1
  62. package/dist/cmds/tunnel/rotate-token.js +1 -0
  63. package/dist/cmds/tunnel/rotate-token.js.map +1 -1
  64. package/dist/cmds/tunnel/services/describe.d.ts.map +1 -1
  65. package/dist/cmds/tunnel/services/describe.js +1 -0
  66. package/dist/cmds/tunnel/services/describe.js.map +1 -1
  67. package/dist/cmds/tunnel/services/update.d.ts.map +1 -1
  68. package/dist/cmds/tunnel/services/update.js +1 -0
  69. package/dist/cmds/tunnel/services/update.js.map +1 -1
  70. package/dist/cmds/variable/create.d.ts.map +1 -1
  71. package/dist/cmds/variable/create.js +1 -0
  72. package/dist/cmds/variable/create.js.map +1 -1
  73. package/dist/cmds/variable/update.d.ts.map +1 -1
  74. package/dist/cmds/variable/update.js +1 -0
  75. package/dist/cmds/variable/update.js.map +1 -1
  76. package/dist/common/middleware/authentication.d.ts.map +1 -1
  77. package/dist/common/middleware/authentication.js +15 -0
  78. package/dist/common/middleware/authentication.js.map +1 -1
  79. package/dist/open-api/merge/handler.d.ts +3 -0
  80. package/dist/open-api/merge/handler.d.ts.map +1 -1
  81. package/dist/open-api/merge/handler.js +67 -5
  82. package/dist/open-api/merge/handler.js.map +1 -1
  83. package/dist/open-api/merge/handler.spec.js +338 -0
  84. package/dist/open-api/merge/handler.spec.js.map +1 -1
  85. package/package.json +4 -4
@@ -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 { 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}\n\nexport async function importOpenApi(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);\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);\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 // Default to path-method merging\n const mergeMode = argv[\"merge-mode\"] || \"path-method\";\n\n const { created, merged, retained, mergedDocument } = mergeOpenApiDocuments(\n originalDocument,\n parsedOpenApiSpec,\n mergeMode\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 await printResultToConsoleAndExitGracefully(\n `Import successful. File written to ${destinationFilePath}`\n );\n}\n"]}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../src/open-api/merge/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EACL,oCAAoC,EACpC,yBAAyB,EACzB,qCAAqC,GACtC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,0BAA0B,EAC1B,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,EAEL,gBAAgB,GAEjB,MAAM,mBAAmB,CAAC;AAY3B,KAAK,UAAU,YAAY,CAAC,IAAe;IACzC,IAAI,kBAA0B,CAAC;IAG/B,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;QACzB,MAAM,eAAe,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1D,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QACzD,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEnE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;YACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,oCAAoC,CACxC,qEAAqE,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC9G,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEnC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;gBAC7C,kBAAkB,GAAG,GAAG,kBAAkB,IAAI,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;gBACpF,MAAM,SAAS,CAAC,kBAAkB,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,yCAAyC,CAAC,CAAC;gBAC7D,MAAM,oCAAoC,CACxC,iEAAiE,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,4CAA4C,CAAC,CAAC;YAChE,MAAM,oCAAoC,CACxC,6CAA6C,CAC9C,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QAEN,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE/C,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACpC,MAAM,oCAAoC,CACxC,YAAY,kBAAkB,4BAA4B,CAC3D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;IAC9C,MAAM,iBAAiB,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAEvE,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IAErC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACvC,MAAM,oCAAoC,CACxC,iDAAiD,CAClD,CAAC;IACJ,CAAC;IAED,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAEtD,IAAI,gBAAsC,CAAC;IAC3C,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAErC,gBAAgB,GAAG,CAAC,MAAM,gBAAgB,CACxC,OAAO,EACP,aAAa,CACd,CAAyB,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,MAAM,mBAAmB,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAChE,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,QAAQ,EAAE,CAAC;QAC3D,gBAAgB,GAAG,CAAC,MAAM,gBAAgB,CACxC,OAAO,EACP,mBAAmB,CACpB,CAAyB,CAAC;IAC7B,CAAC;IAID,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,aAAa,CAAC;IACtD,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC;IACzC,MAAM,iBAAiB,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAErE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,qBAAqB,CACzE,gBAAgB,EAChB,iBAAiB,EACjB;QACE,SAAS;QACT,iBAAiB;QACjB,WAAW;KACZ,CACF,CAAC;IAGF,yBAAyB,CAAC,qBAAqB,CAAC,CAAC;IACjD,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAE9B,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACrB,yBAAyB,CACvB,UAAU,OAAO,CAAC,IAAI,QAAQ,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CAC9E,CAAC;QACF,yBAAyB,CAAC,EAAE,CAAC,CAAC;QAC9B,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAC5B,yBAAyB,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACpB,yBAAyB,CACvB,SAAS,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CACvE,CAAC;QACF,yBAAyB,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAC3B,yBAAyB,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACtB,yBAAyB,CACvB,UAAU,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CAC5E,CAAC;QACF,yBAAyB,CAAC,EAAE,CAAC,CAAC;QAC9B,QAAQ,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAC7B,yBAAyB,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACH,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,yBAAyB,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,qCAAqC,CAAC,mBAAmB,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,0BAA0B,CAAC,cAAc,CAAC,CAAC;IAE3C,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE;QACpE,MAAM,EAAE,gBAAgB;KACzB,CAAC,CAAC;IAGH,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAErC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAG9C,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,aAAa,CAAC,mBAAmB,EAAE,gBAAgB,EAAE;QACnD,IAAI,EAAE,GAAG;KACV,CAAC,CAAC;IAEH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,qCAAqC,CACzC,sCAAsC,mBAAmB,EAAE,CAC5D,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,yBAAyB,CACvB,sCAAsC,mBAAmB,EAAE,CAC5D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAe;IAEjD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAGD,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,oCAAoC,CACxC,uEAAuE,CACxE,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE7C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,oCAAoC,CACxC,YAAY,UAAU,4BAA4B,CACnD,CAAC;IACJ,CAAC;IAED,yBAAyB,CAAC,2BAA2B,UAAU,KAAK,CAAC,CAAC;IACtE,yBAAyB,CAAC,kCAAkC,CAAC,CAAC;IAG9D,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;QAC5C,yBAAyB,CAAC,+BAA+B,KAAK,EAAE,CAAC,CAAC;IACpE,CAAC;IAGD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE;QACzC,UAAU,EAAE,IAAI;QAChB,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,IAAI,CAAC;YACH,yBAAyB,CAAC,UAAU,UAAU,yBAAyB,CAAC,CAAC;YACzE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;YACzB,yBAAyB,CAAC,oCAAoC,CAAC,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;YACvC,yBAAyB,CAAC,0BAA0B,KAAK,IAAI,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC5B,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACrC,yBAAyB,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAGH,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC1B,yBAAyB,CAAC,0BAA0B,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;QAC3B,yBAAyB,CAAC,0BAA0B,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC","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"]}
@@ -331,5 +331,343 @@ paths:
331
331
  }), /must end with '.oas.json'/);
332
332
  });
333
333
  });
334
+ describe("server-paths flag", () => {
335
+ it("should apply server-paths transformation by default", async () => {
336
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
337
+ const destPath = path.join(testTmpPath, "dest.oas.json");
338
+ const sourceDoc = {
339
+ openapi: "3.1.0",
340
+ info: {
341
+ title: "Source API",
342
+ version: "1.0.0",
343
+ },
344
+ servers: [
345
+ {
346
+ url: "https://api.example.com/v2",
347
+ description: "Production server",
348
+ },
349
+ ],
350
+ paths: {
351
+ "/products": {
352
+ get: {
353
+ summary: "Get products",
354
+ operationId: "getProducts",
355
+ responses: {
356
+ "200": {
357
+ description: "Success",
358
+ },
359
+ },
360
+ },
361
+ },
362
+ },
363
+ };
364
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
365
+ await importOpenApi({
366
+ source: sourcePath,
367
+ destination: destPath,
368
+ prompt: false,
369
+ });
370
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
371
+ assert.strictEqual(result.paths["/v2/products"].get.summary, "Get products");
372
+ assert.strictEqual(result.paths["/products"], undefined);
373
+ });
374
+ it("should apply server-paths transformation when explicitly enabled", async () => {
375
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
376
+ const destPath = path.join(testTmpPath, "dest.oas.json");
377
+ const sourceDoc = {
378
+ openapi: "3.1.0",
379
+ info: {
380
+ title: "Source API",
381
+ version: "1.0.0",
382
+ },
383
+ servers: [
384
+ {
385
+ url: "https://api.example.com/v1",
386
+ description: "Production server",
387
+ },
388
+ ],
389
+ paths: {
390
+ "/accounts": {
391
+ get: {
392
+ summary: "Get accounts",
393
+ operationId: "getAccounts",
394
+ responses: {
395
+ "200": {
396
+ description: "Success",
397
+ },
398
+ },
399
+ },
400
+ },
401
+ },
402
+ };
403
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
404
+ await importOpenApi({
405
+ source: sourcePath,
406
+ destination: destPath,
407
+ prompt: false,
408
+ "server-paths": true,
409
+ });
410
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
411
+ assert.strictEqual(result.paths["/v1/accounts"].get.summary, "Get accounts");
412
+ assert.strictEqual(result.paths["/accounts"], undefined);
413
+ });
414
+ it("should not transform paths when server-paths is disabled", async () => {
415
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
416
+ const destPath = path.join(testTmpPath, "dest.oas.json");
417
+ const sourceDoc = {
418
+ openapi: "3.1.0",
419
+ info: {
420
+ title: "Source API",
421
+ version: "1.0.0",
422
+ },
423
+ servers: [
424
+ {
425
+ url: "https://api.example.com/v1",
426
+ description: "Production server",
427
+ },
428
+ ],
429
+ paths: {
430
+ "/accounts": {
431
+ get: {
432
+ summary: "Get accounts",
433
+ operationId: "getAccounts",
434
+ responses: {
435
+ "200": {
436
+ description: "Success",
437
+ },
438
+ },
439
+ },
440
+ },
441
+ },
442
+ };
443
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
444
+ await importOpenApi({
445
+ source: sourcePath,
446
+ destination: destPath,
447
+ prompt: false,
448
+ "server-paths": false,
449
+ });
450
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
451
+ assert.strictEqual(result.paths["/accounts"].get.summary, "Get accounts");
452
+ assert.strictEqual(result.paths["/v1/accounts"], undefined);
453
+ });
454
+ it("should handle servers with no pathname gracefully", async () => {
455
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
456
+ const destPath = path.join(testTmpPath, "dest.oas.json");
457
+ const sourceDoc = {
458
+ openapi: "3.1.0",
459
+ info: {
460
+ title: "Source API",
461
+ version: "1.0.0",
462
+ },
463
+ servers: [
464
+ {
465
+ url: "https://api.example.com",
466
+ description: "Production server",
467
+ },
468
+ ],
469
+ paths: {
470
+ "/accounts": {
471
+ get: {
472
+ summary: "Get accounts",
473
+ operationId: "getAccounts",
474
+ responses: {
475
+ "200": {
476
+ description: "Success",
477
+ },
478
+ },
479
+ },
480
+ },
481
+ },
482
+ };
483
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
484
+ await importOpenApi({
485
+ source: sourcePath,
486
+ destination: destPath,
487
+ prompt: false,
488
+ "server-paths": true,
489
+ });
490
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
491
+ assert.strictEqual(result.paths["/accounts"].get.summary, "Get accounts");
492
+ });
493
+ it("should handle missing servers gracefully", async () => {
494
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
495
+ const destPath = path.join(testTmpPath, "dest.oas.json");
496
+ const sourceDoc = {
497
+ openapi: "3.1.0",
498
+ info: {
499
+ title: "Source API",
500
+ version: "1.0.0",
501
+ },
502
+ paths: {
503
+ "/accounts": {
504
+ get: {
505
+ summary: "Get accounts",
506
+ operationId: "getAccounts",
507
+ responses: {
508
+ "200": {
509
+ description: "Success",
510
+ },
511
+ },
512
+ },
513
+ },
514
+ },
515
+ };
516
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
517
+ await importOpenApi({
518
+ source: sourcePath,
519
+ destination: destPath,
520
+ prompt: false,
521
+ "server-paths": true,
522
+ });
523
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
524
+ assert.strictEqual(result.paths["/accounts"].get.summary, "Get accounts");
525
+ });
526
+ });
527
+ describe("prepend-path flag", () => {
528
+ it("should apply prepend-path transformation", async () => {
529
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
530
+ const destPath = path.join(testTmpPath, "dest.oas.json");
531
+ const sourceDoc = {
532
+ openapi: "3.1.0",
533
+ info: {
534
+ title: "Source API",
535
+ version: "1.0.0",
536
+ },
537
+ paths: {
538
+ "/accounts": {
539
+ get: {
540
+ summary: "Get accounts",
541
+ operationId: "getAccounts",
542
+ responses: {
543
+ "200": {
544
+ description: "Success",
545
+ },
546
+ },
547
+ },
548
+ },
549
+ "/users": {
550
+ get: {
551
+ summary: "Get users",
552
+ operationId: "getUsers",
553
+ responses: {
554
+ "200": {
555
+ description: "Success",
556
+ },
557
+ },
558
+ },
559
+ },
560
+ },
561
+ };
562
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
563
+ await importOpenApi({
564
+ source: sourcePath,
565
+ destination: destPath,
566
+ prompt: false,
567
+ "prepend-path": "/api/v2",
568
+ });
569
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
570
+ assert.strictEqual(result.paths["/api/v2/accounts"].get.summary, "Get accounts");
571
+ assert.strictEqual(result.paths["/api/v2/users"].get.summary, "Get users");
572
+ assert.strictEqual(result.paths["/accounts"], undefined);
573
+ assert.strictEqual(result.paths["/users"], undefined);
574
+ });
575
+ it("should handle prepend-path with various formats", async () => {
576
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
577
+ const destPath = path.join(testTmpPath, "dest.oas.json");
578
+ const sourceDoc = {
579
+ openapi: "3.1.0",
580
+ info: {
581
+ title: "Source API",
582
+ version: "1.0.0",
583
+ },
584
+ paths: {
585
+ "/test": {
586
+ get: {
587
+ summary: "Test endpoint",
588
+ operationId: "test",
589
+ responses: {
590
+ "200": {
591
+ description: "Success",
592
+ },
593
+ },
594
+ },
595
+ },
596
+ },
597
+ };
598
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
599
+ await importOpenApi({
600
+ source: sourcePath,
601
+ destination: destPath,
602
+ prompt: false,
603
+ "prepend-path": "/v1/",
604
+ });
605
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
606
+ assert.strictEqual(result.paths["/v1/test"].get.summary, "Test endpoint");
607
+ });
608
+ it("should prioritize prepend-path over server-paths", async () => {
609
+ const sourcePath = path.join(testTmpPath, "source.oas.json");
610
+ const destPath = path.join(testTmpPath, "dest.oas.json");
611
+ const sourceDoc = {
612
+ openapi: "3.1.0",
613
+ info: {
614
+ title: "Source API",
615
+ version: "1.0.0",
616
+ },
617
+ servers: [
618
+ {
619
+ url: "https://api.example.com/v1",
620
+ description: "Has a pathname that should be ignored",
621
+ },
622
+ ],
623
+ paths: {
624
+ "/orders": {
625
+ get: {
626
+ summary: "Get orders",
627
+ operationId: "getOrders",
628
+ responses: {
629
+ "200": {
630
+ description: "Success",
631
+ },
632
+ },
633
+ },
634
+ },
635
+ },
636
+ };
637
+ await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));
638
+ await importOpenApi({
639
+ source: sourcePath,
640
+ destination: destPath,
641
+ prompt: false,
642
+ "server-paths": true,
643
+ "prepend-path": "/custom/path",
644
+ });
645
+ const result = JSON.parse(await fs.readFile(destPath, "utf-8"));
646
+ assert.strictEqual(result.paths["/custom/path/orders"].get.summary, "Get orders");
647
+ assert.strictEqual(result.paths["/v1/orders"], undefined);
648
+ assert.strictEqual(result.paths["/orders"], undefined);
649
+ });
650
+ });
651
+ describe("watch flag", () => {
652
+ it("should reject watch mode with URL sources", async () => {
653
+ const destPath = path.join(testTmpPath, "dest.oas.json");
654
+ await assert.rejects(() => importOpenApi({
655
+ source: "https://example.com/api.json",
656
+ destination: destPath,
657
+ prompt: false,
658
+ watch: true,
659
+ }), /Watch mode is not supported for URL sources/);
660
+ });
661
+ it("should reject watch mode with non-existent files", async () => {
662
+ const sourcePath = path.join(testTmpPath, "nonexistent.oas.json");
663
+ const destPath = path.join(testTmpPath, "dest.oas.json");
664
+ await assert.rejects(() => importOpenApi({
665
+ source: sourcePath,
666
+ destination: destPath,
667
+ prompt: false,
668
+ watch: true,
669
+ }), /does not exist/);
670
+ });
671
+ });
334
672
  });
335
673
  //# sourceMappingURL=handler.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.spec.js","sourceRoot":"","sources":["../../../src/open-api/merge/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 { importOpenApi } 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 \"merge-handler\"\n);\n\ndescribe(\"Merge 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(\"importOpenApi\", () => {\n it(\"should merge source into new destination file\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.openapi, \"3.1.0\");\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n assert.strictEqual(result.paths[\"/users\"].get.operationId, \"getUsers\");\n });\n\n it(\"should merge source into existing destination file\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const existingDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Existing API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/products\": {\n get: {\n summary: \"Get products\",\n operationId: \"getProducts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(destPath, JSON.stringify(existingDoc, null, 2));\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/products\"].get.summary, \"Get products\");\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n });\n\n it(\"should support YAML source files\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.yaml\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = `openapi: 3.1.0\ninfo:\n title: Source API\n version: 1.0.0\npaths:\n /users:\n get:\n summary: Get users\n operationId: getUsers\n responses:\n '200':\n description: Success`;\n\n await fs.writeFile(sourcePath, sourceDoc);\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n });\n\n it(\"should use path-method merge mode by default\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const existingDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Existing API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Original summary\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Updated summary\",\n operationId: \"getUsersUpdated\",\n responses: {\n \"200\": {\n description: \"Updated Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(destPath, JSON.stringify(existingDoc, null, 2));\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n // In path-method mode, matching path+method should be merged\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Updated summary\");\n });\n\n it(\"should support operation-id merge mode\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const existingDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Existing API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Original summary\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/v2/users\": {\n get: {\n summary: \"Updated summary\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Updated Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(destPath, JSON.stringify(existingDoc, null, 2));\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"merge-mode\": \"operation-id\",\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n // In operation-id mode, matching operationId should be merged\n // Original path should be removed, new path should exist\n assert.strictEqual(result.paths[\"/users\"], undefined);\n assert.strictEqual(\n result.paths[\"/v2/users\"].get.summary,\n \"Updated summary\"\n );\n });\n\n it(\"should create output directory if it doesn't exist\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"nested\", \"dir\", \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n });\n\n it(\"should add operation IDs if missing\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n // No operationId\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n // Operation ID should be auto-generated\n assert.strictEqual(\n typeof result.paths[\"/users\"].get.operationId,\n \"string\"\n );\n assert.strictEqual(\n result.paths[\"/users\"].get.operationId.length > 0,\n true\n );\n });\n\n it(\"should throw error when source file does not exist\", async () => {\n const sourcePath = path.join(testTmpPath, \"nonexistent.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n await assert.rejects(\n () =>\n importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n }),\n /does not exist/\n );\n });\n\n it(\"should throw error when destination doesn't end with .oas.json\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await assert.rejects(\n () =>\n importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n }),\n /must end with '.oas.json'/\n );\n });\n });\n});\n"]}
1
+ {"version":3,"file":"handler.spec.js","sourceRoot":"","sources":["../../../src/open-api/merge/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 { importOpenApi } 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 \"merge-handler\"\n);\n\ndescribe(\"Merge 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(\"importOpenApi\", () => {\n it(\"should merge source into new destination file\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.openapi, \"3.1.0\");\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n assert.strictEqual(result.paths[\"/users\"].get.operationId, \"getUsers\");\n });\n\n it(\"should merge source into existing destination file\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const existingDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Existing API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/products\": {\n get: {\n summary: \"Get products\",\n operationId: \"getProducts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(destPath, JSON.stringify(existingDoc, null, 2));\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/products\"].get.summary, \"Get products\");\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n });\n\n it(\"should support YAML source files\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.yaml\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = `openapi: 3.1.0\ninfo:\n title: Source API\n version: 1.0.0\npaths:\n /users:\n get:\n summary: Get users\n operationId: getUsers\n responses:\n '200':\n description: Success`;\n\n await fs.writeFile(sourcePath, sourceDoc);\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n });\n\n it(\"should use path-method merge mode by default\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const existingDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Existing API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Original summary\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Updated summary\",\n operationId: \"getUsersUpdated\",\n responses: {\n \"200\": {\n description: \"Updated Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(destPath, JSON.stringify(existingDoc, null, 2));\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n // In path-method mode, matching path+method should be merged\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Updated summary\");\n });\n\n it(\"should support operation-id merge mode\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const existingDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Existing API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Original summary\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/v2/users\": {\n get: {\n summary: \"Updated summary\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Updated Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(destPath, JSON.stringify(existingDoc, null, 2));\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"merge-mode\": \"operation-id\",\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n // In operation-id mode, matching operationId should be merged\n // Original path should be removed, new path should exist\n assert.strictEqual(result.paths[\"/users\"], undefined);\n assert.strictEqual(\n result.paths[\"/v2/users\"].get.summary,\n \"Updated summary\"\n );\n });\n\n it(\"should create output directory if it doesn't exist\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"nested\", \"dir\", \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/users\"].get.summary, \"Get users\");\n });\n\n it(\"should add operation IDs if missing\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/users\": {\n get: {\n summary: \"Get users\",\n // No operationId\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n // Operation ID should be auto-generated\n assert.strictEqual(\n typeof result.paths[\"/users\"].get.operationId,\n \"string\"\n );\n assert.strictEqual(\n result.paths[\"/users\"].get.operationId.length > 0,\n true\n );\n });\n\n it(\"should throw error when source file does not exist\", async () => {\n const sourcePath = path.join(testTmpPath, \"nonexistent.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n await assert.rejects(\n () =>\n importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n }),\n /does not exist/\n );\n });\n\n it(\"should throw error when destination doesn't end with .oas.json\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {},\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await assert.rejects(\n () =>\n importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n }),\n /must end with '.oas.json'/\n );\n });\n });\n\n describe(\"server-paths flag\", () => {\n it(\"should apply server-paths transformation by default\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"https://api.example.com/v2\",\n description: \"Production server\",\n },\n ],\n paths: {\n \"/products\": {\n get: {\n summary: \"Get products\",\n operationId: \"getProducts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(\n result.paths[\"/v2/products\"].get.summary,\n \"Get products\"\n );\n assert.strictEqual(result.paths[\"/products\"], undefined);\n });\n\n it(\"should apply server-paths transformation when explicitly enabled\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"https://api.example.com/v1\",\n description: \"Production server\",\n },\n ],\n paths: {\n \"/accounts\": {\n get: {\n summary: \"Get accounts\",\n operationId: \"getAccounts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"server-paths\": true,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(\n result.paths[\"/v1/accounts\"].get.summary,\n \"Get accounts\"\n );\n assert.strictEqual(result.paths[\"/accounts\"], undefined);\n });\n\n it(\"should not transform paths when server-paths is disabled\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"https://api.example.com/v1\",\n description: \"Production server\",\n },\n ],\n paths: {\n \"/accounts\": {\n get: {\n summary: \"Get accounts\",\n operationId: \"getAccounts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"server-paths\": false,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/accounts\"].get.summary, \"Get accounts\");\n assert.strictEqual(result.paths[\"/v1/accounts\"], undefined);\n });\n\n it(\"should handle servers with no pathname gracefully\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"https://api.example.com\",\n description: \"Production server\",\n },\n ],\n paths: {\n \"/accounts\": {\n get: {\n summary: \"Get accounts\",\n operationId: \"getAccounts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"server-paths\": true,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/accounts\"].get.summary, \"Get accounts\");\n });\n\n it(\"should handle missing servers gracefully\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/accounts\": {\n get: {\n summary: \"Get accounts\",\n operationId: \"getAccounts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"server-paths\": true,\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/accounts\"].get.summary, \"Get accounts\");\n });\n });\n\n describe(\"prepend-path flag\", () => {\n it(\"should apply prepend-path transformation\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/accounts\": {\n get: {\n summary: \"Get accounts\",\n operationId: \"getAccounts\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n \"/users\": {\n get: {\n summary: \"Get users\",\n operationId: \"getUsers\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"prepend-path\": \"/api/v2\",\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(\n result.paths[\"/api/v2/accounts\"].get.summary,\n \"Get accounts\"\n );\n assert.strictEqual(\n result.paths[\"/api/v2/users\"].get.summary,\n \"Get users\"\n );\n assert.strictEqual(result.paths[\"/accounts\"], undefined);\n assert.strictEqual(result.paths[\"/users\"], undefined);\n });\n\n it(\"should handle prepend-path with various formats\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n paths: {\n \"/test\": {\n get: {\n summary: \"Test endpoint\",\n operationId: \"test\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"prepend-path\": \"/v1/\",\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(result.paths[\"/v1/test\"].get.summary, \"Test endpoint\");\n });\n\n it(\"should prioritize prepend-path over server-paths\", async () => {\n const sourcePath = path.join(testTmpPath, \"source.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n const sourceDoc = {\n openapi: \"3.1.0\",\n info: {\n title: \"Source API\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"https://api.example.com/v1\",\n description: \"Has a pathname that should be ignored\",\n },\n ],\n paths: {\n \"/orders\": {\n get: {\n summary: \"Get orders\",\n operationId: \"getOrders\",\n responses: {\n \"200\": {\n description: \"Success\",\n },\n },\n },\n },\n },\n };\n\n await fs.writeFile(sourcePath, JSON.stringify(sourceDoc, null, 2));\n\n await importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n \"server-paths\": true,\n \"prepend-path\": \"/custom/path\",\n });\n\n const result = JSON.parse(await fs.readFile(destPath, \"utf-8\"));\n assert.strictEqual(\n result.paths[\"/custom/path/orders\"].get.summary,\n \"Get orders\"\n );\n assert.strictEqual(result.paths[\"/v1/orders\"], undefined);\n assert.strictEqual(result.paths[\"/orders\"], undefined);\n });\n });\n\n describe(\"watch flag\", () => {\n it(\"should reject watch mode with URL sources\", async () => {\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n await assert.rejects(\n () =>\n importOpenApi({\n source: \"https://example.com/api.json\",\n destination: destPath,\n prompt: false,\n watch: true,\n }),\n /Watch mode is not supported for URL sources/\n );\n });\n\n it(\"should reject watch mode with non-existent files\", async () => {\n const sourcePath = path.join(testTmpPath, \"nonexistent.oas.json\");\n const destPath = path.join(testTmpPath, \"dest.oas.json\");\n\n await assert.rejects(\n () =>\n importOpenApi({\n source: sourcePath,\n destination: destPath,\n prompt: false,\n watch: true,\n }),\n /does not exist/\n );\n });\n });\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/cli",
3
- "version": "6.64.4",
3
+ "version": "6.64.6",
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.4",
32
+ "@zuplo/core": "6.64.6",
33
33
  "@zuplo/editor": "~1.0.0",
34
- "@zuplo/openapi-tools": "6.64.4",
35
- "@zuplo/runtime": "6.64.4",
34
+ "@zuplo/openapi-tools": "6.64.6",
35
+ "@zuplo/runtime": "6.64.6",
36
36
  "as-table": "1.0.55",
37
37
  "chalk": "5.4.1",
38
38
  "chokidar": "3.5.3",