@zuplo/openapi-tools 6.65.9 → 6.66.2

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 (75) hide show
  1. package/dist/constants.d.ts +13 -0
  2. package/dist/constants.d.ts.map +1 -0
  3. package/dist/constants.js +25 -0
  4. package/dist/constants.js.map +1 -0
  5. package/dist/file-format.d.ts +59 -0
  6. package/dist/file-format.d.ts.map +1 -0
  7. package/dist/file-format.js +142 -0
  8. package/dist/file-format.js.map +1 -0
  9. package/dist/file-format.spec.d.ts +2 -0
  10. package/dist/file-format.spec.d.ts.map +1 -0
  11. package/dist/file-format.spec.js +289 -0
  12. package/dist/file-format.spec.js.map +1 -0
  13. package/dist/index.d.ts +10 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +10 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/interfaces.d.ts +32 -5
  18. package/dist/interfaces.d.ts.map +1 -1
  19. package/dist/interfaces.js +0 -1
  20. package/dist/interfaces.js.map +1 -1
  21. package/dist/merge-fixtures.spec.d.ts +2 -0
  22. package/dist/merge-fixtures.spec.d.ts.map +1 -0
  23. package/dist/merge-fixtures.spec.js +181 -0
  24. package/dist/merge-fixtures.spec.js.map +1 -0
  25. package/dist/{openapi-utils.d.ts → merge.d.ts} +2 -22
  26. package/dist/merge.d.ts.map +1 -0
  27. package/dist/{openapi-utils.js → merge.js} +6 -186
  28. package/dist/merge.js.map +1 -0
  29. package/dist/merge.spec.d.ts +2 -0
  30. package/dist/merge.spec.d.ts.map +1 -0
  31. package/dist/merge.spec.js +399 -0
  32. package/dist/merge.spec.js.map +1 -0
  33. package/dist/operation-utils.d.ts +29 -0
  34. package/dist/operation-utils.d.ts.map +1 -0
  35. package/dist/operation-utils.js +123 -0
  36. package/dist/operation-utils.js.map +1 -0
  37. package/dist/overlay.d.ts +78 -0
  38. package/dist/overlay.d.ts.map +1 -0
  39. package/dist/overlay.js +477 -0
  40. package/dist/overlay.js.map +1 -0
  41. package/dist/overlay.spec.d.ts +2 -0
  42. package/dist/overlay.spec.d.ts.map +1 -0
  43. package/dist/overlay.spec.js +697 -0
  44. package/dist/overlay.spec.js.map +1 -0
  45. package/dist/parsing.d.ts +17 -0
  46. package/dist/parsing.d.ts.map +1 -0
  47. package/dist/parsing.js +32 -0
  48. package/dist/parsing.js.map +1 -0
  49. package/dist/path-transform.d.ts +11 -0
  50. package/dist/path-transform.d.ts.map +1 -0
  51. package/dist/path-transform.js +51 -0
  52. package/dist/path-transform.js.map +1 -0
  53. package/dist/path-transform.spec.d.ts +2 -0
  54. package/dist/path-transform.spec.d.ts.map +1 -0
  55. package/dist/path-transform.spec.js +269 -0
  56. package/dist/path-transform.spec.js.map +1 -0
  57. package/dist/url-utils.d.ts +14 -0
  58. package/dist/url-utils.d.ts.map +1 -0
  59. package/dist/url-utils.js +40 -0
  60. package/dist/url-utils.js.map +1 -0
  61. package/dist/url-utils.spec.d.ts +2 -0
  62. package/dist/url-utils.spec.d.ts.map +1 -0
  63. package/dist/url-utils.spec.js +93 -0
  64. package/dist/url-utils.spec.js.map +1 -0
  65. package/dist/validation.d.ts +210 -0
  66. package/dist/validation.d.ts.map +1 -0
  67. package/dist/validation.js +119 -0
  68. package/dist/validation.js.map +1 -0
  69. package/package.json +9 -10
  70. package/dist/index.spec.d.ts +0 -2
  71. package/dist/index.spec.d.ts.map +0 -1
  72. package/dist/index.spec.js +0 -526
  73. package/dist/index.spec.js.map +0 -1
  74. package/dist/openapi-utils.d.ts.map +0 -1
  75. package/dist/openapi-utils.js.map +0 -1
@@ -0,0 +1,399 @@
1
+ import assert from "node:assert";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { describe, it } from "node:test";
5
+ import { fileURLToPath } from "node:url";
6
+ import { ZUPLO_OPEN_API_ROUTE_KEY, } from "./interfaces.js";
7
+ import { mergeOpenApiDocumentOnOperationId, mergeOpenApiDocuments, } from "./merge.js";
8
+ import { addOperationIdsAsNecessary, getOperationKey, } from "./operation-utils.js";
9
+ import { parseOpenApiFileFromString } from "./parsing.js";
10
+ import { BASE_TEMPLATE } from "./url-utils.js";
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+ // Test fixtures are in the package root
14
+ // When running from dist/, __dirname is packages/openapi-tools/dist
15
+ // so we go up one level to get to packages/openapi-tools, then into test-fixtures
16
+ const testFixturesPath = path.join(__dirname, "..", "test-fixtures");
17
+ describe("OpenAPI Merge Utils", () => {
18
+ it("should generate merge changes between two different oas files", async () => {
19
+ const toImportPath = path.join(testFixturesPath, "toimport.oas.json");
20
+ const toImportContent = await fs.readFile(toImportPath, "utf-8");
21
+ const toImportOpenApiSpec = parseOpenApiFileFromString(".json", toImportContent);
22
+ const baseRoutesPath = path.join(testFixturesPath, "base-routes-on-import-tests.oas.json");
23
+ const baseRoutesContent = await fs.readFile(baseRoutesPath, "utf-8");
24
+ const originalDocument = parseOpenApiFileFromString(".json", baseRoutesContent);
25
+ const { created, merged, retained } = mergeOpenApiDocuments(originalDocument, toImportOpenApiSpec, "path-method");
26
+ const expectedMergedResult = new Set().add("post>/v2/second/{userUid}/nature");
27
+ const expectedRetainedResult = new Set().add("post>/v1/second/{userUid}/nature");
28
+ assert.deepStrictEqual(created, new Set());
29
+ assert.deepStrictEqual(merged, expectedMergedResult);
30
+ assert.deepStrictEqual(retained, expectedRetainedResult);
31
+ });
32
+ it("should generate merge changes between a oas file and the default base template", async () => {
33
+ const toImportPath = path.join(testFixturesPath, "toimport.oas.json");
34
+ const toImportContent = await fs.readFile(toImportPath, "utf-8");
35
+ const toImportOpenApiSpec = parseOpenApiFileFromString(".json", toImportContent);
36
+ const originalDocument = parseOpenApiFileFromString(".json", BASE_TEMPLATE);
37
+ const { created, merged, retained } = mergeOpenApiDocuments(originalDocument, toImportOpenApiSpec, "path-method");
38
+ assert.deepStrictEqual(created, new Set().add("post>/v2/second/{userUid}/nature"));
39
+ assert.deepStrictEqual(merged, new Set());
40
+ assert.deepStrictEqual(retained, new Set());
41
+ });
42
+ it("should generate missing operation ids", async () => {
43
+ const woOperationIdsPath = path.join(testFixturesPath, "base-routes-wo-operation-ids.oas.json");
44
+ const woOperationIdsContent = await fs.readFile(woOperationIdsPath, "utf-8");
45
+ const oasDocument = parseOpenApiFileFromString(".json", woOperationIdsContent);
46
+ addOperationIdsAsNecessary(oasDocument);
47
+ assert.ok(oasDocument.paths);
48
+ assert.ok(oasDocument.paths["/v2/second/{userUid}/nature"]?.post?.operationId);
49
+ });
50
+ it("should not change existing operation ids", async () => {
51
+ const baseRoutesPath = path.join(testFixturesPath, "base-routes-on-import-tests.oas.json");
52
+ const baseRoutesContent = await fs.readFile(baseRoutesPath, "utf-8");
53
+ const oasDocument = parseOpenApiFileFromString(".json", baseRoutesContent);
54
+ addOperationIdsAsNecessary(oasDocument);
55
+ assert.ok(oasDocument.paths);
56
+ const paths = oasDocument.paths;
57
+ assert.strictEqual(paths["/v1/second/{userUid}/nature"]?.post?.operationId, "12345");
58
+ assert.strictEqual(paths["/v2/second/{userUid}/nature"]?.post?.operationId, "67920");
59
+ });
60
+ it("should successfully parse a yaml open api file", async () => {
61
+ const toImportPath = path.join(testFixturesPath, "toimportv2.yaml");
62
+ const toImportContent = await fs.readFile(toImportPath, "utf-8");
63
+ const toImportOpenApiSpec = parseOpenApiFileFromString(".yaml", toImportContent);
64
+ assert.ok(toImportOpenApiSpec);
65
+ assert.deepStrictEqual(toImportOpenApiSpec.info, {
66
+ title: "Protect API",
67
+ description: "Buy & sell",
68
+ version: "0.2.0",
69
+ contact: {
70
+ name: "Zuplo YAML Test",
71
+ url: "https://zuplo.com/",
72
+ email: "test@example.com",
73
+ },
74
+ });
75
+ assert.deepStrictEqual(toImportOpenApiSpec.servers, [
76
+ {
77
+ url: "https://api.zuplo.com",
78
+ description: "Production",
79
+ },
80
+ ]);
81
+ assert.deepStrictEqual(toImportOpenApiSpec.tags, [
82
+ { name: "Order" },
83
+ { name: "Organization" },
84
+ { name: "Site" },
85
+ { name: "Supervisor" },
86
+ ]);
87
+ assert.ok(toImportOpenApiSpec.paths);
88
+ const paths = toImportOpenApiSpec.paths;
89
+ assert.ok(paths["/v1/orders"]);
90
+ assert.ok(paths["/v1/orders/wa/{waaaa}"]);
91
+ assert.ok(paths["/v1/orders/{order}"]);
92
+ assert.ok(paths["/v1/orgs/{organization}"]);
93
+ assert.deepStrictEqual(paths["/v1/sites"], {
94
+ get: {
95
+ operationId: "get-sites",
96
+ summary: "Get Sites",
97
+ description: "Sites are locations",
98
+ tags: ["Site"],
99
+ responses: {
100
+ "200": {
101
+ description: "OK",
102
+ content: {
103
+ "application/json": {
104
+ schema: {
105
+ type: "array",
106
+ items: {
107
+ $ref: "#/components/schemas/Site",
108
+ },
109
+ },
110
+ },
111
+ },
112
+ headers: {
113
+ "Cache-Control": {
114
+ required: true,
115
+ schema: {
116
+ type: "string",
117
+ },
118
+ description: "Responses are cacheable following standard HTTP headers.",
119
+ },
120
+ },
121
+ },
122
+ },
123
+ },
124
+ });
125
+ assert.ok(toImportOpenApiSpec.components);
126
+ });
127
+ });
128
+ // Test fixtures for OperationID merge tests
129
+ const emptyOpenApi = {
130
+ openapi: "3.0.0",
131
+ info: {
132
+ title: "Test",
133
+ version: "1.0.0",
134
+ },
135
+ paths: {},
136
+ };
137
+ const basicOpenApi = {
138
+ openapi: "3.0.0",
139
+ info: {
140
+ title: "Test",
141
+ version: "1.0.0",
142
+ },
143
+ paths: {
144
+ "/test": {
145
+ get: {
146
+ operationId: "getTest",
147
+ },
148
+ },
149
+ },
150
+ };
151
+ const openApiWithOperationIdsMissing = {
152
+ openapi: "3.0.0",
153
+ info: {
154
+ title: "Test",
155
+ version: "1.0.0",
156
+ },
157
+ components: {},
158
+ paths: {
159
+ "/test": {
160
+ get: {
161
+ responses: {
162
+ "200": {
163
+ description: "OK",
164
+ },
165
+ },
166
+ },
167
+ },
168
+ },
169
+ };
170
+ const openApiWithMatchingPathMethodButDifferentOperationId = {
171
+ openapi: "3.0.0",
172
+ info: {
173
+ title: "Test",
174
+ version: "1.0.0",
175
+ },
176
+ paths: {
177
+ "/test": {
178
+ get: {
179
+ operationId: "get_test",
180
+ },
181
+ },
182
+ },
183
+ };
184
+ const openApiWithSomePathsAndMethods = {
185
+ openapi: "3.0.0",
186
+ info: {
187
+ title: "Test",
188
+ version: "1.0.0",
189
+ },
190
+ paths: {
191
+ "/test": {
192
+ get: {
193
+ operationId: "getTest",
194
+ deprecated: true,
195
+ "x-zuplo-route": {
196
+ corsPolicy: "none",
197
+ handler: {
198
+ export: "urlForwardHandler",
199
+ module: "$import(@zuplo/runtime)",
200
+ options: {
201
+ baseUrl: "https://echo.zuplo.io",
202
+ },
203
+ },
204
+ },
205
+ },
206
+ delete: {
207
+ operationId: "deleteTest",
208
+ "x-zuplo-route": {
209
+ corsPolicy: "none",
210
+ handler: {
211
+ export: "urlForwardHandler",
212
+ module: "$import(@zuplo/runtime)",
213
+ options: {
214
+ baseUrl: "https://echo.zuplo.io",
215
+ },
216
+ },
217
+ },
218
+ },
219
+ post: {
220
+ operationId: "postTest",
221
+ "x-zuplo-route": {
222
+ corsPolicy: "none",
223
+ handler: {
224
+ export: "urlForwardHandler",
225
+ module: "$import(@zuplo/runtime)",
226
+ options: {
227
+ baseUrl: "https://echo.zuplo.io",
228
+ },
229
+ },
230
+ },
231
+ },
232
+ },
233
+ "/humans": {
234
+ delete: {
235
+ operationId: "deleteHuman",
236
+ "x-zuplo-route": {
237
+ corsPolicy: "none",
238
+ handler: {
239
+ export: "urlForwardHandler",
240
+ module: "$import(@zuplo/runtime)",
241
+ options: {
242
+ baseUrl: "https://echo.zuplo.io",
243
+ },
244
+ },
245
+ },
246
+ },
247
+ },
248
+ "/humans/{id}": {
249
+ parameters: [
250
+ {
251
+ name: "id",
252
+ in: "path",
253
+ required: true,
254
+ schema: {
255
+ type: "string",
256
+ },
257
+ },
258
+ ],
259
+ get: {
260
+ operationId: "getHuman",
261
+ "x-zuplo-route": {
262
+ corsPolicy: "none",
263
+ handler: {
264
+ export: "urlForwardHandler",
265
+ module: "$import(@zuplo/runtime)",
266
+ options: {
267
+ baseUrl: "https://echo.zuplo.io",
268
+ },
269
+ },
270
+ },
271
+ },
272
+ },
273
+ },
274
+ };
275
+ const newOpenApiWithSomePathsAndMethods = {
276
+ openapi: "3.0.0",
277
+ info: {
278
+ title: "Test",
279
+ version: "1.0.0",
280
+ },
281
+ paths: {
282
+ "/test": {
283
+ get: {
284
+ operationId: "getTest",
285
+ deprecated: false, // Changed deprecated to false
286
+ },
287
+ post: {
288
+ operationId: "postTest",
289
+ summary: "Create a new test", // Added summary
290
+ // route definition is missing
291
+ },
292
+ },
293
+ "/humans": {
294
+ post: {
295
+ operationId: "createHuman",
296
+ },
297
+ delete: {
298
+ operationId: "deleteHuman",
299
+ },
300
+ },
301
+ "/humans/{humanId}": {
302
+ // Changed path parameter name
303
+ parameters: [
304
+ {
305
+ name: "humanId",
306
+ in: "path",
307
+ required: true,
308
+ schema: {
309
+ type: "string",
310
+ },
311
+ },
312
+ ],
313
+ get: {
314
+ operationId: "getHuman",
315
+ },
316
+ },
317
+ },
318
+ };
319
+ describe("OpenAPI OperationID Merge Tests", () => {
320
+ it("Doesn't change the original document when merging two empty OpenAPI files", () => {
321
+ const { mergedDocument, created, merged, retained } = mergeOpenApiDocumentOnOperationId(emptyOpenApi, emptyOpenApi);
322
+ assert.strictEqual(created.size, 0, "No operations should be created");
323
+ assert.strictEqual(merged.size, 0, "No operations should be merged");
324
+ assert.strictEqual(retained.size, 0, "No operations should be retained");
325
+ assert.deepStrictEqual(mergedDocument, emptyOpenApi, "The original document should not be changed");
326
+ });
327
+ it("Retains existing operations when merging in an empty OpenAPI file", () => {
328
+ const { mergedDocument, created, merged, retained } = mergeOpenApiDocumentOnOperationId(basicOpenApi, emptyOpenApi);
329
+ assert.strictEqual(created.size, 0, "No operations should be created");
330
+ assert.strictEqual(merged.size, 0, "No operations should be merged");
331
+ assert.deepStrictEqual(retained, new Set(["getTest"]), "The existing operation should be retained");
332
+ assert.deepStrictEqual(mergedDocument, basicOpenApi, "The original document should not be changed");
333
+ });
334
+ it("Creates new operations when merging into an empty OpenAPI file", () => {
335
+ const { mergedDocument, created, merged, retained } = mergeOpenApiDocumentOnOperationId(emptyOpenApi, basicOpenApi);
336
+ assert.strictEqual(merged.size, 0, "No operations should be merged");
337
+ assert.strictEqual(retained.size, 0, "No operations should be retained");
338
+ assert.deepStrictEqual(created, new Set(["getTest"]), "The new operation should be created");
339
+ assert.deepStrictEqual(mergedDocument, basicOpenApi, "The merged document should match the new document");
340
+ });
341
+ it("Throws when operations are missing operationId", () => {
342
+ assert.throws(() => {
343
+ mergeOpenApiDocumentOnOperationId(basicOpenApi, openApiWithOperationIdsMissing);
344
+ }, {
345
+ message: `OperationId is required for all operations. OperationId missing on ${getOperationKey("get", "/test")}. Please add an operationId to all operations before merging.`,
346
+ });
347
+ });
348
+ it("Throws when operation already exists at path+method and operationIds do not match", () => {
349
+ assert.throws(() => {
350
+ mergeOpenApiDocumentOnOperationId(basicOpenApi, openApiWithMatchingPathMethodButDifferentOperationId);
351
+ }, {
352
+ message: `Operation 'get_test' has a matching path/method to an existing operation at ${getOperationKey("get", "/test")}, but a different operationId. Either update the operationId on the existing operation or remove it entirely.`,
353
+ });
354
+ });
355
+ it("Creates new operations when merging into an OpenAPI file with operations", () => {
356
+ const { mergedDocument, created } = mergeOpenApiDocumentOnOperationId(openApiWithSomePathsAndMethods, newOpenApiWithSomePathsAndMethods);
357
+ assert.deepStrictEqual(created, new Set(["createHuman"]), "The new operations should be created");
358
+ assert.deepStrictEqual(mergedDocument?.paths?.["/humans"]?.post, { operationId: "createHuman" }, "The new operation should be created");
359
+ });
360
+ it("Retains old operations when new document does not include those operations", () => {
361
+ const { mergedDocument, retained } = mergeOpenApiDocumentOnOperationId(openApiWithSomePathsAndMethods, newOpenApiWithSomePathsAndMethods);
362
+ assert.deepStrictEqual(retained, new Set(["deleteTest"]), "The existing operations should be retained");
363
+ assert.deepStrictEqual(mergedDocument?.paths?.["/test"]?.delete, openApiWithSomePathsAndMethods?.paths?.["/test"]?.delete, "The existing operation should be retained");
364
+ });
365
+ it("Merges operations and updates properties", () => {
366
+ const { mergedDocument, merged } = mergeOpenApiDocumentOnOperationId(openApiWithSomePathsAndMethods, newOpenApiWithSomePathsAndMethods);
367
+ assert.deepStrictEqual(merged, new Set(["getTest", "postTest", "deleteHuman", "getHuman"]), "The operations should be merged");
368
+ assert.strictEqual(mergedDocument?.paths?.["/test"]?.get?.deprecated, false, "The operation's 'deprecated' property should be updated");
369
+ assert.deepStrictEqual(mergedDocument?.paths?.["/test"]?.post?.summary, "Create a new test", "The operation's 'summary' property should be updated");
370
+ assert.deepStrictEqual(mergedDocument?.paths?.["/humans"]?.delete?.[ZUPLO_OPEN_API_ROUTE_KEY], openApiWithSomePathsAndMethods?.paths?.["/humans"]?.delete?.[ZUPLO_OPEN_API_ROUTE_KEY], "Merged operation with no changes should be the same");
371
+ assert.strictEqual(mergedDocument?.paths?.["/humans/{id}"]?.get, undefined, "The old operation should not exist in the merged document");
372
+ // NOTE: Parameters at the path level are not merged since operationId
373
+ // merging implies only operations are merged
374
+ assert.deepStrictEqual(mergedDocument?.paths?.["/humans/{humanId}"], {
375
+ get: {
376
+ operationId: "getHuman",
377
+ "x-zuplo-route": {
378
+ corsPolicy: "none",
379
+ handler: {
380
+ export: "urlForwardHandler",
381
+ module: "$import(@zuplo/runtime)",
382
+ options: {
383
+ baseUrl: "https://echo.zuplo.io",
384
+ },
385
+ },
386
+ },
387
+ },
388
+ }, "The new operation should exist in the merged document");
389
+ });
390
+ it("Retains zuplo config when merging operations", () => {
391
+ const { mergedDocument, merged } = mergeOpenApiDocumentOnOperationId(openApiWithSomePathsAndMethods, newOpenApiWithSomePathsAndMethods);
392
+ assert.deepStrictEqual(merged, new Set(["getTest", "postTest", "deleteHuman", "getHuman"]), "The operations should be merged");
393
+ assert.deepStrictEqual(mergedDocument?.paths?.["/test"]?.get?.[ZUPLO_OPEN_API_ROUTE_KEY], openApiWithSomePathsAndMethods?.paths?.["/test"]?.get?.[ZUPLO_OPEN_API_ROUTE_KEY], "The existing zuplo config should be retained");
394
+ assert.deepStrictEqual(mergedDocument?.paths?.["/test"]?.post?.[ZUPLO_OPEN_API_ROUTE_KEY], openApiWithSomePathsAndMethods?.paths?.["/test"]?.post?.[ZUPLO_OPEN_API_ROUTE_KEY], "The existing zuplo config should be retained");
395
+ assert.deepStrictEqual(mergedDocument?.paths?.["/humans"]?.delete?.[ZUPLO_OPEN_API_ROUTE_KEY], openApiWithSomePathsAndMethods?.paths?.["/humans"]?.delete?.[ZUPLO_OPEN_API_ROUTE_KEY], "The existing zuplo config should be retained");
396
+ assert.deepStrictEqual(mergedDocument?.paths?.["/humans/{humanId}"]?.get?.[ZUPLO_OPEN_API_ROUTE_KEY], openApiWithSomePathsAndMethods?.paths?.["/humans/{id}"]?.get?.[ZUPLO_OPEN_API_ROUTE_KEY], "The existing zuplo config should be retained");
397
+ });
398
+ });
399
+ //# sourceMappingURL=merge.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.spec.js","sourceRoot":"","sources":["../src/merge.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { OpenAPIV3_1 } from "openapi-types";
2
+ import { type HttpMethod } from "./constants.js";
3
+ import type { ZuploOpenApiDocument, ZuploOpenApiPathsObject } from "./interfaces.js";
4
+ export declare const OPERATION_PATH_MERGE_DELIMITER = ">";
5
+ export declare const getOperationKey: (method: string, path: string) => string;
6
+ /**
7
+ * Get all operation keys (method + path) from a paths object
8
+ */
9
+ export declare const getAllOperationKeys: (pathsObject: ZuploOpenApiPathsObject | OpenAPIV3_1.PathsObject) => string[];
10
+ /**
11
+ * Create an index of operations by their operationId
12
+ *
13
+ * @param openapiSpec The OpenAPI specification object
14
+ * @returns A map of operationId -> { path, method }
15
+ */
16
+ export declare const indexOperationsById: (openapiSpec: ZuploOpenApiDocument | OpenAPIV3_1.Document) => Record<string, {
17
+ path: string;
18
+ method: HttpMethod;
19
+ }>;
20
+ /**
21
+ * Add operation ID to any operations that don't have one, this makes
22
+ * onboarding smoother for new users
23
+ */
24
+ export declare const addOperationIdsAsNecessary: (openApi: OpenAPIV3_1.Document | ZuploOpenApiDocument) => ZuploOpenApiDocument;
25
+ /**
26
+ * Remove operations that don't have an operationId
27
+ */
28
+ export declare const removeOperationsWithoutAnId: (openApi: OpenAPIV3_1.Document | ZuploOpenApiDocument) => ZuploOpenApiDocument;
29
+ //# sourceMappingURL=operation-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-utils.d.ts","sourceRoot":"","sources":["../src/operation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EACV,oBAAoB,EAGpB,uBAAuB,EACxB,MAAM,iBAAiB,CAAC;AAIzB,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAElD,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,WACP,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC9B,aAAa,uBAAuB,GAAG,WAAW,CAAC,WAAW,aA2C/D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,aAAa,oBAAoB,GAAG,WAAW,CAAC,QAAQ,KACvD,MAAM,CACP,MAAM,EACN;IACE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;CACpB,CAyBF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GACrC,SAAS,WAAW,CAAC,QAAQ,GAAG,oBAAoB,KACnD,oBA4BF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B,GACtC,SAAS,WAAW,CAAC,QAAQ,GAAG,oBAAoB,KACnD,oBAmBF,CAAC"}
@@ -0,0 +1,123 @@
1
+ import { v4 } from "uuid";
2
+ import { HTTP_METHODS } from "./constants.js";
3
+ const METHODS = HTTP_METHODS;
4
+ export const OPERATION_PATH_MERGE_DELIMITER = ">";
5
+ export const getOperationKey = (method, path) => `${method}${OPERATION_PATH_MERGE_DELIMITER}${path}`;
6
+ /**
7
+ * Get all operation keys (method + path) from a paths object
8
+ */
9
+ export const getAllOperationKeys = (pathsObject) => {
10
+ return Object.entries(pathsObject).flatMap(([path, pathObject]) => {
11
+ const pathItemObject = pathObject;
12
+ const { get, put, post, delete: deleteOperation, options, head, patch, trace, } = pathItemObject;
13
+ const methods = [];
14
+ if (get) {
15
+ methods.push("get");
16
+ }
17
+ if (put) {
18
+ methods.push("put");
19
+ }
20
+ if (post) {
21
+ methods.push("post");
22
+ }
23
+ if (deleteOperation) {
24
+ methods.push("delete");
25
+ }
26
+ if (options) {
27
+ methods.push("options");
28
+ }
29
+ if (head) {
30
+ methods.push("head");
31
+ }
32
+ if (patch) {
33
+ methods.push("patch");
34
+ }
35
+ if (trace) {
36
+ methods.push("trace");
37
+ }
38
+ return methods.map((method) => getOperationKey(method, path));
39
+ });
40
+ };
41
+ /**
42
+ * Create an index of operations by their operationId
43
+ *
44
+ * @param openapiSpec The OpenAPI specification object
45
+ * @returns A map of operationId -> { path, method }
46
+ */
47
+ export const indexOperationsById = (openapiSpec) => {
48
+ const operationsIndex = {};
49
+ const paths = openapiSpec.paths;
50
+ if (paths) {
51
+ Object.entries(paths).forEach(([path, pathItem]) => {
52
+ if (pathItem) {
53
+ METHODS.forEach((method) => {
54
+ const operation = pathItem[method];
55
+ if (operation?.operationId) {
56
+ operationsIndex[operation.operationId] = {
57
+ path,
58
+ method,
59
+ };
60
+ }
61
+ });
62
+ }
63
+ });
64
+ }
65
+ return operationsIndex;
66
+ };
67
+ /**
68
+ * Add operation ID to any operations that don't have one, this makes
69
+ * onboarding smoother for new users
70
+ */
71
+ export const addOperationIdsAsNecessary = (openApi) => {
72
+ const paths = openApi.paths;
73
+ if (!paths) {
74
+ return openApi;
75
+ }
76
+ for (const path of Object.keys(paths)) {
77
+ const pathItem = paths[path];
78
+ if (!pathItem) {
79
+ continue;
80
+ }
81
+ const methods = [
82
+ "get",
83
+ "put",
84
+ "post",
85
+ "delete",
86
+ "options",
87
+ "head",
88
+ "patch",
89
+ "trace",
90
+ ];
91
+ for (const method of methods) {
92
+ const operation = pathItem[method];
93
+ if (operation && !operation.operationId) {
94
+ operation.operationId = v4();
95
+ }
96
+ }
97
+ }
98
+ return openApi;
99
+ };
100
+ /**
101
+ * Remove operations that don't have an operationId
102
+ */
103
+ export const removeOperationsWithoutAnId = (openApi) => {
104
+ const newDocument = { ...openApi };
105
+ const paths = newDocument.paths;
106
+ if (!paths) {
107
+ return openApi;
108
+ }
109
+ for (const path of Object.keys(paths)) {
110
+ const pathItem = paths[path];
111
+ if (!pathItem) {
112
+ continue;
113
+ }
114
+ for (const method of METHODS) {
115
+ const operation = pathItem[method];
116
+ if (operation && !operation.operationId) {
117
+ delete pathItem[method];
118
+ }
119
+ }
120
+ }
121
+ return openApi;
122
+ };
123
+ //# sourceMappingURL=operation-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-utils.js","sourceRoot":"","sources":["../src/operation-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * OpenAPI Overlay implementation
3
+ * Applies overlay modifications to OpenAPI documents following the OpenAPI Overlay Specification
4
+ */
5
+ import { type OverlayAction, type OverlayDocument, type RemoveCondition } from "./validation.js";
6
+ export interface ApplyResult {
7
+ applied: boolean;
8
+ count: number;
9
+ }
10
+ export interface OverlayStats {
11
+ applied: number;
12
+ skipped: number;
13
+ totalNodes: number;
14
+ }
15
+ /**
16
+ * Deep clone an object using structuredClone for better performance and correctness
17
+ * Falls back to JSON parse/stringify for environments without structuredClone
18
+ */
19
+ export declare function deepClone<T>(obj: T): T;
20
+ /**
21
+ * Deep merge two objects
22
+ * Special handling for OpenAPI parameters (merge by name+in)
23
+ * Returns the merged result, which will have the shape of source if target is not an object,
24
+ * or a merged object/array if both are objects/arrays
25
+ */
26
+ export declare function deepMerge(target: unknown, source: unknown): unknown;
27
+ /**
28
+ * Check if a condition is met for conditional removal
29
+ */
30
+ export declare function checkCondition(value: unknown, condition: RemoveCondition): boolean;
31
+ export declare function setValueAtPath(doc: unknown, target: string, value: unknown): void;
32
+ /**
33
+ * Apply a single overlay action to the document
34
+ */
35
+ export declare function applyAction(doc: unknown, action: OverlayAction): ApplyResult;
36
+ /**
37
+ * Extract path order from overlay actions
38
+ * Returns array of paths in the order they appear in overlay
39
+ */
40
+ export declare function extractPathOrder(overlay: OverlayDocument): string[];
41
+ /**
42
+ * Reorder operation properties so summary, description, operationId come first
43
+ * Returns a new object with reordered keys
44
+ */
45
+ export declare function reorderOperationProperties(operation: unknown): Record<string, unknown>;
46
+ /**
47
+ * Reorder paths object to match the order from overlay
48
+ * Modifies the document in place and returns it
49
+ */
50
+ export declare function reorderPaths<T>(doc: T, pathOrder: string[]): T;
51
+ /**
52
+ * Reorder top-level document properties to ensure proper ordering
53
+ * OpenAPI spec should have: openapi, info, tags, servers, paths, components, etc.
54
+ * Returns a new object with reordered keys
55
+ */
56
+ export declare function reorderDocumentProperties(doc: unknown): Record<string, unknown>;
57
+ /**
58
+ * Apply overlay to OpenAPI document
59
+ *
60
+ * Validates both the OpenAPI document and overlay upfront, then applies
61
+ * all actions defined in the overlay to produce a modified OpenAPI document.
62
+ *
63
+ * @param openapi The OpenAPI document to modify (will be validated)
64
+ * @param overlay The overlay document to apply (will be validated)
65
+ * @returns The modified OpenAPI document and statistics about what was applied
66
+ * @throws {Error} if either document is invalid, with actionable error messages
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const result = applyOverlay(openapiDoc, overlayDoc);
71
+ * console.log(`Applied ${result.stats.applied} actions`);
72
+ * ```
73
+ */
74
+ export declare function applyOverlay(openapi: unknown, overlay: unknown): {
75
+ result: Record<string, unknown>;
76
+ stats: OverlayStats;
77
+ };
78
+ //# sourceMappingURL=overlay.d.ts.map