@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.
- package/dist/constants.d.ts +13 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +25 -0
- package/dist/constants.js.map +1 -0
- package/dist/file-format.d.ts +59 -0
- package/dist/file-format.d.ts.map +1 -0
- package/dist/file-format.js +142 -0
- package/dist/file-format.js.map +1 -0
- package/dist/file-format.spec.d.ts +2 -0
- package/dist/file-format.spec.d.ts.map +1 -0
- package/dist/file-format.spec.js +289 -0
- package/dist/file-format.spec.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +32 -5
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js +0 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/merge-fixtures.spec.d.ts +2 -0
- package/dist/merge-fixtures.spec.d.ts.map +1 -0
- package/dist/merge-fixtures.spec.js +181 -0
- package/dist/merge-fixtures.spec.js.map +1 -0
- package/dist/{openapi-utils.d.ts → merge.d.ts} +2 -22
- package/dist/merge.d.ts.map +1 -0
- package/dist/{openapi-utils.js → merge.js} +6 -186
- package/dist/merge.js.map +1 -0
- package/dist/merge.spec.d.ts +2 -0
- package/dist/merge.spec.d.ts.map +1 -0
- package/dist/merge.spec.js +399 -0
- package/dist/merge.spec.js.map +1 -0
- package/dist/operation-utils.d.ts +29 -0
- package/dist/operation-utils.d.ts.map +1 -0
- package/dist/operation-utils.js +123 -0
- package/dist/operation-utils.js.map +1 -0
- package/dist/overlay.d.ts +78 -0
- package/dist/overlay.d.ts.map +1 -0
- package/dist/overlay.js +477 -0
- package/dist/overlay.js.map +1 -0
- package/dist/overlay.spec.d.ts +2 -0
- package/dist/overlay.spec.d.ts.map +1 -0
- package/dist/overlay.spec.js +697 -0
- package/dist/overlay.spec.js.map +1 -0
- package/dist/parsing.d.ts +17 -0
- package/dist/parsing.d.ts.map +1 -0
- package/dist/parsing.js +32 -0
- package/dist/parsing.js.map +1 -0
- package/dist/path-transform.d.ts +11 -0
- package/dist/path-transform.d.ts.map +1 -0
- package/dist/path-transform.js +51 -0
- package/dist/path-transform.js.map +1 -0
- package/dist/path-transform.spec.d.ts +2 -0
- package/dist/path-transform.spec.d.ts.map +1 -0
- package/dist/path-transform.spec.js +269 -0
- package/dist/path-transform.spec.js.map +1 -0
- package/dist/url-utils.d.ts +14 -0
- package/dist/url-utils.d.ts.map +1 -0
- package/dist/url-utils.js +40 -0
- package/dist/url-utils.js.map +1 -0
- package/dist/url-utils.spec.d.ts +2 -0
- package/dist/url-utils.spec.d.ts.map +1 -0
- package/dist/url-utils.spec.js +93 -0
- package/dist/url-utils.spec.js.map +1 -0
- package/dist/validation.d.ts +210 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +119 -0
- package/dist/validation.js.map +1 -0
- package/package.json +9 -10
- package/dist/index.spec.d.ts +0 -2
- package/dist/index.spec.d.ts.map +0 -1
- package/dist/index.spec.js +0 -526
- package/dist/index.spec.js.map +0 -1
- package/dist/openapi-utils.d.ts.map +0 -1
- 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
|