diff --git a/projects/openapi-io/src/denormalizers/__tests__/__snapshots__/denormalize.test.ts.snap b/projects/openapi-io/src/denormalizers/__tests__/__snapshots__/denormalize.test.ts.snap index ec5ade7c5e..2529aebabd 100644 --- a/projects/openapi-io/src/denormalizers/__tests__/__snapshots__/denormalize.test.ts.snap +++ b/projects/openapi-io/src/denormalizers/__tests__/__snapshots__/denormalize.test.ts.snap @@ -1,6 +1,199 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`denormalize allOf merging does not merge allOf when all items are not all objects 1`] = ` +exports[`denormalize v2 denormalizes shared path parameters 1`] = ` +{ + "jsonLike": { + "info": { + "title": "some thing", + "version": "v0", + }, + "paths": { + "/example": { + "get": { + "parameters": [ + { + "description": "something here", + "in": "query", + "name": "something-else", + "required": true, + "schema": { + "example": "d5b640e5-d88c-4c17-9bf0-93597b7a1ce2", + "format": "uuid", + "type": "string", + }, + }, + { + "description": "should-not-override", + "in": "query", + "name": "should-not-override", + "required": true, + "schema": { + "example": "d5b640e5-d88c-4c17-9bf0-93597b7a1ce2", + "format": "uuid", + "type": "string", + }, + }, + { + "description": "something here", + "in": "query", + "name": "something", + "required": true, + "schema": { + "example": "d5b640e5-d88c-4c17-9bf0-93597b7a1ce2", + "format": "uuid", + "type": "string", + }, + }, + ], + "responses": { + "200": { + "description": "some thing", + }, + }, + }, + "post": { + "parameters": [ + { + "description": "should not be overriden", + "in": "query", + "name": "should-not-override", + "required": true, + "schema": { + "example": "d5b640e5-d88c-4c17-9bf0-93597b7a1ce2", + "format": "uuid", + "type": "string", + }, + }, + { + "description": "something here", + "in": "query", + "name": "something-else", + "required": true, + "schema": { + "example": "d5b640e5-d88c-4c17-9bf0-93597b7a1ce2", + "format": "uuid", + "type": "string", + }, + }, + { + "description": "something here", + "in": "query", + "name": "something", + "required": true, + "schema": { + "example": "d5b640e5-d88c-4c17-9bf0-93597b7a1ce2", + "format": "uuid", + "type": "string", + }, + }, + ], + "responses": { + "200": { + "description": "some thing", + }, + }, + }, + }, + }, + "swagger": "2.0.1", + }, + "sourcemap": JsonSchemaSourcemap { + "files": [ + { + "contents": "swagger: '2.0.1' +info: + title: 'some thing' + version: 'v0' +paths: + /example: + parameters: + - name: something-else + in: query + required: true + description: something here + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 + - name: should-not-override + in: query + required: true + description: should-not-override + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 + - $ref: parameters.yml#/something + get: + responses: + 200: + description: 'some thing' + post: + parameters: + - name: should-not-override + in: query + required: true + description: should not be overriden + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 + responses: + 200: + description: 'some thing' +", + "index": null, + "path": "/src/denormalizers/__tests__/specs/v2/openapi.yaml", + "sha256": "42778528330e8611b2fe132c99dc7c5f8d92663b6a06d8f7b1d0ec226cc929b6", + }, + { + "contents": "something: + name: something + in: query + required: true + description: something here + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 +", + "index": null, + "path": "/src/denormalizers/__tests__/specs/v2/parameters.yml", + "sha256": "85d23de44c126a054df04ca9720a69b0842935868c6d0a771baa37f0bee832ba", + }, + ], + "refMappings": { + "/paths/~1example/get/parameters/0": [ + 0, + "/paths/~1example/parameters/0", + ], + "/paths/~1example/get/parameters/1": [ + 0, + "/paths/~1example/parameters/1", + ], + "/paths/~1example/get/parameters/2": [ + 1, + "/paths/~1example/parameters/2", + ], + "/paths/~1example/parameters/2": [ + 1, + "/something", + ], + "/paths/~1example/post/parameters/1": [ + 0, + "/paths/~1example/parameters/0", + ], + "/paths/~1example/post/parameters/2": [ + 1, + "/paths/~1example/parameters/2", + ], + }, + "rootFilePath": "/src/denormalizers/__tests__/specs/v2/openapi.yaml", + }, +} +`; + +exports[`denormalize v3 allOf merging does not merge allOf when all items are not all objects 1`] = ` { "jsonLike": { "info": { @@ -95,7 +288,7 @@ paths: type: 'string' ", "index": null, - "path": "/src/denormalizers/__tests__/specs/allOf/no-merge.yaml", + "path": "/src/denormalizers/__tests__/specs/v3/allOf/no-merge.yaml", "sha256": "4921acb94767de410927bd6751ac8d9f712c11dc70dcb260236a6684df8dcdb2", }, ], @@ -105,18 +298,18 @@ paths: "/paths/~1example/get/requestBody/content/application~1json/schema/properties/d/allOf/0/properties/a", ], }, - "rootFilePath": "/src/denormalizers/__tests__/specs/allOf/no-merge.yaml", + "rootFilePath": "/src/denormalizers/__tests__/specs/v3/allOf/no-merge.yaml", }, } `; -exports[`denormalize allOf merging does not merge allOf when all items are not all objects: warnings 1`] = ` +exports[`denormalize v3 allOf merging does not merge allOf when all items are not all objects: warnings 1`] = ` [ - "invalid allOf variant at src/denormalizers/__tests__/specs/allOf/no-merge.yaml:26:578 (/paths/~1example/get/requestBody/content/application~1json/schema/properties/d/allOf/1)", + "invalid allOf variant at src/denormalizers/__tests__/specs/v3/allOf/no-merge.yaml:26:578 (/paths/~1example/get/requestBody/content/application~1json/schema/properties/d/allOf/1)", ] `; -exports[`denormalize allOf merging merges allOf when all items are objects 1`] = ` +exports[`denormalize v3 allOf merging merges allOf when all items are objects 1`] = ` { "jsonLike": { "info": { @@ -213,7 +406,7 @@ paths: type: string ", "index": null, - "path": "/src/denormalizers/__tests__/specs/allOf/single-allof.yaml", + "path": "/src/denormalizers/__tests__/specs/v3/allOf/single-allof.yaml", "sha256": "16eba8b2fa4bae164c1443f0bdccaa8cdf1482e2a0a805bb215c0e219348455a", }, ], @@ -243,14 +436,14 @@ paths: "/paths/~1example/get/responses/200/content/application~1json/schema/allOf/1/required/0", ], }, - "rootFilePath": "/src/denormalizers/__tests__/specs/allOf/single-allof.yaml", + "rootFilePath": "/src/denormalizers/__tests__/specs/v3/allOf/single-allof.yaml", }, } `; -exports[`denormalize allOf merging merges allOf when all items are objects: warnings 1`] = `[]`; +exports[`denormalize v3 allOf merging merges allOf when all items are objects: warnings 1`] = `[]`; -exports[`denormalize allOf merging merges allOf with only one item 1`] = ` +exports[`denormalize v3 allOf merging merges allOf with only one item 1`] = ` { "jsonLike": { "info": { @@ -303,19 +496,19 @@ paths: format: uuid ", "index": null, - "path": "/src/denormalizers/__tests__/specs/allOf/single-child.yaml", + "path": "/src/denormalizers/__tests__/specs/v3/allOf/single-child.yaml", "sha256": "6536b93a83f2b2a5d776abac8830ba6750e4ba08056b78096b9c7ebf5653849c", }, ], "refMappings": {}, - "rootFilePath": "/src/denormalizers/__tests__/specs/allOf/single-child.yaml", + "rootFilePath": "/src/denormalizers/__tests__/specs/v3/allOf/single-child.yaml", }, } `; -exports[`denormalize allOf merging merges allOf with only one item: warnings 1`] = `[]`; +exports[`denormalize v3 allOf merging merges allOf with only one item: warnings 1`] = `[]`; -exports[`denormalize allOf merging merges allOfs in type array object / items 1`] = ` +exports[`denormalize v3 allOf merging merges allOfs in type array object / items 1`] = ` { "jsonLike": { "info": { @@ -479,7 +672,7 @@ paths: type: string ", "index": null, - "path": "/src/denormalizers/__tests__/specs/allOf/in-type-array.yaml", + "path": "/src/denormalizers/__tests__/specs/v3/allOf/in-type-array.yaml", "sha256": "06b1b6e709c37580805955ed027bd8c659bf85e9a8b2333c7d6e21475f10687e", }, ], @@ -541,14 +734,14 @@ paths: "/paths/~1example/get/responses/200/content/application~1json/schema/properties/inside_object/allOf/2/properties/e", ], }, - "rootFilePath": "/src/denormalizers/__tests__/specs/allOf/in-type-array.yaml", + "rootFilePath": "/src/denormalizers/__tests__/specs/v3/allOf/in-type-array.yaml", }, } `; -exports[`denormalize allOf merging merges allOfs in type array object / items: warnings 1`] = `[]`; +exports[`denormalize v3 allOf merging merges allOfs in type array object / items: warnings 1`] = `[]`; -exports[`denormalize allOf merging merges nested allOf 1`] = ` +exports[`denormalize v3 allOf merging merges nested allOf 1`] = ` { "jsonLike": { "info": { @@ -656,7 +849,7 @@ paths: type: string ", "index": null, - "path": "/src/denormalizers/__tests__/specs/allOf/nested.yaml", + "path": "/src/denormalizers/__tests__/specs/v3/allOf/nested.yaml", "sha256": "f40a14b89b16b1dbccde926823ead4a870178e400878f5114b21936725d99527", }, ], @@ -698,14 +891,14 @@ paths: "/paths/~1example/get/responses/200/content/application~1json/schema/allOf/0/properties/x", ], }, - "rootFilePath": "/src/denormalizers/__tests__/specs/allOf/nested.yaml", + "rootFilePath": "/src/denormalizers/__tests__/specs/v3/allOf/nested.yaml", }, } `; -exports[`denormalize allOf merging merges nested allOf: warnings 1`] = `[]`; +exports[`denormalize v3 allOf merging merges nested allOf: warnings 1`] = `[]`; -exports[`denormalize denormalizes shared path parameters 1`] = ` +exports[`denormalize v3 denormalizes shared path parameters 1`] = ` { "jsonLike": { "info": { @@ -872,7 +1065,7 @@ paths: type: 'string' ", "index": null, - "path": "/src/denormalizers/__tests__/specs/openapi.yaml", + "path": "/src/denormalizers/__tests__/specs/v3/openapi.yaml", "sha256": "44bb048800379bdd9651daa9c6a380dbd68232443881cbbaa0c155240e45c001", }, { @@ -887,7 +1080,7 @@ paths: example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 ", "index": null, - "path": "/src/denormalizers/__tests__/specs/parameters.yml", + "path": "/src/denormalizers/__tests__/specs/v3/parameters.yml", "sha256": "85d23de44c126a054df04ca9720a69b0842935868c6d0a771baa37f0bee832ba", }, ], @@ -917,7 +1110,7 @@ paths: "/paths/~1example/parameters/2", ], }, - "rootFilePath": "/src/denormalizers/__tests__/specs/openapi.yaml", + "rootFilePath": "/src/denormalizers/__tests__/specs/v3/openapi.yaml", }, } `; diff --git a/projects/openapi-io/src/denormalizers/__tests__/denormalize.test.ts b/projects/openapi-io/src/denormalizers/__tests__/denormalize.test.ts index 4f9de8873e..b8988b2191 100644 --- a/projects/openapi-io/src/denormalizers/__tests__/denormalize.test.ts +++ b/projects/openapi-io/src/denormalizers/__tests__/denormalize.test.ts @@ -22,14 +22,28 @@ function prepSnapshot(result: ParseOpenAPIResult) { ); return result; } -describe('denormalize', () => { + +describe('denormalize v2', () => { + test('denormalizes shared path parameters', async () => { + const specPath = path.resolve( + 'src/denormalizers/__tests__/specs/v2/openapi.yaml' + ); + const spec = await parseOpenAPIWithSourcemap(specPath); + + const denormalized = denormalize(spec, '2.x.x'); + + expect(prepSnapshot(denormalized)).toMatchSnapshot(); + }); +}); + +describe('denormalize v3', () => { test('denormalizes shared path parameters', async () => { const specPath = path.resolve( - 'src/denormalizers/__tests__/specs/openapi.yaml' + 'src/denormalizers/__tests__/specs/v3/openapi.yaml' ); const spec = await parseOpenAPIWithSourcemap(specPath); - const denormalized = denormalize(spec); + const denormalized = denormalize(spec, '3.0.x'); expect(prepSnapshot(denormalized)).toMatchSnapshot(); }); @@ -38,30 +52,30 @@ describe('denormalize', () => { test.each([ [ 'merges allOf when all items are objects', - 'src/denormalizers/__tests__/specs/allOf/single-allof.yaml', + 'src/denormalizers/__tests__/specs/v3/allOf/single-allof.yaml', ], [ 'does not merge allOf when all items are not all objects', - 'src/denormalizers/__tests__/specs/allOf/no-merge.yaml', + 'src/denormalizers/__tests__/specs/v3/allOf/no-merge.yaml', ], [ 'merges nested allOf', - 'src/denormalizers/__tests__/specs/allOf/nested.yaml', + 'src/denormalizers/__tests__/specs/v3/allOf/nested.yaml', ], [ 'merges allOfs in type array object / items', - 'src/denormalizers/__tests__/specs/allOf/in-type-array.yaml', + 'src/denormalizers/__tests__/specs/v3/allOf/in-type-array.yaml', ], [ 'merges allOf with only one item', - 'src/denormalizers/__tests__/specs/allOf/single-child.yaml', + 'src/denormalizers/__tests__/specs/v3/allOf/single-child.yaml', ], ])('%s', async (_, openapiFilePath) => { const spec = await parseOpenAPIWithSourcemap( path.resolve(openapiFilePath) ); const warnings: string[] = []; - const denormalized = denormalize(spec, warnings); + const denormalized = denormalize(spec, '3.0.x', warnings); expect(prepSnapshot(denormalized)).toMatchSnapshot(); expect(warnings).toMatchSnapshot('warnings'); diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/v2/openapi.yaml b/projects/openapi-io/src/denormalizers/__tests__/specs/v2/openapi.yaml new file mode 100644 index 0000000000..e64fd18486 --- /dev/null +++ b/projects/openapi-io/src/denormalizers/__tests__/specs/v2/openapi.yaml @@ -0,0 +1,41 @@ +swagger: '2.0.1' +info: + title: 'some thing' + version: 'v0' +paths: + /example: + parameters: + - name: something-else + in: query + required: true + description: something here + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 + - name: should-not-override + in: query + required: true + description: should-not-override + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 + - $ref: parameters.yml#/something + get: + responses: + 200: + description: 'some thing' + post: + parameters: + - name: should-not-override + in: query + required: true + description: should not be overriden + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 + responses: + 200: + description: 'some thing' diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/parameters.yml b/projects/openapi-io/src/denormalizers/__tests__/specs/v2/parameters.yml similarity index 100% rename from projects/openapi-io/src/denormalizers/__tests__/specs/parameters.yml rename to projects/openapi-io/src/denormalizers/__tests__/specs/v2/parameters.yml diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/allOf/in-type-array.yaml b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/in-type-array.yaml similarity index 100% rename from projects/openapi-io/src/denormalizers/__tests__/specs/allOf/in-type-array.yaml rename to projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/in-type-array.yaml diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/allOf/nested.yaml b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/nested.yaml similarity index 100% rename from projects/openapi-io/src/denormalizers/__tests__/specs/allOf/nested.yaml rename to projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/nested.yaml diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/allOf/no-merge.yaml b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/no-merge.yaml similarity index 100% rename from projects/openapi-io/src/denormalizers/__tests__/specs/allOf/no-merge.yaml rename to projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/no-merge.yaml diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/allOf/single-allof.yaml b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/single-allof.yaml similarity index 100% rename from projects/openapi-io/src/denormalizers/__tests__/specs/allOf/single-allof.yaml rename to projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/single-allof.yaml diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/allOf/single-child.yaml b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/single-child.yaml similarity index 100% rename from projects/openapi-io/src/denormalizers/__tests__/specs/allOf/single-child.yaml rename to projects/openapi-io/src/denormalizers/__tests__/specs/v3/allOf/single-child.yaml diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/openapi.yaml b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/openapi.yaml similarity index 100% rename from projects/openapi-io/src/denormalizers/__tests__/specs/openapi.yaml rename to projects/openapi-io/src/denormalizers/__tests__/specs/v3/openapi.yaml diff --git a/projects/openapi-io/src/denormalizers/__tests__/specs/v3/parameters.yml b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/parameters.yml new file mode 100644 index 0000000000..4950a3e9ad --- /dev/null +++ b/projects/openapi-io/src/denormalizers/__tests__/specs/v3/parameters.yml @@ -0,0 +1,9 @@ +something: + name: something + in: query + required: true + description: something here + schema: + type: string + format: uuid + example: d5b640e5-d88c-4c17-9bf0-93597b7a1ce2 diff --git a/projects/openapi-io/src/denormalizers/denormalize.ts b/projects/openapi-io/src/denormalizers/denormalize.ts index 7f71b42339..9df612d3b4 100644 --- a/projects/openapi-io/src/denormalizers/denormalize.ts +++ b/projects/openapi-io/src/denormalizers/denormalize.ts @@ -4,6 +4,7 @@ import { FlatOpenAPIV3, FlatOpenAPIV3_1, OpenAPIV3, + SWAGGER2_HTTP_METHODS, } from '@useoptic/openapi-utilities'; import { jsonPointerHelpers } from '@useoptic/json-pointer-helpers'; import { logPointer } from './pointer'; @@ -25,32 +26,54 @@ export function denormalize< jsonLike: ParseOpenAPIResult['jsonLike']; sourcemap?: ParseOpenAPIResult['sourcemap']; }, ->(parse: T, warnings?: string[]): T { +>(parse: T, version: '2.x.x' | '3.0.x' | '3.1.x', warnings?: string[]): T { parse = { ...parse, jsonLike: JSON.parse(JSON.stringify(parse.jsonLike)), } as T; - // TODO handle denormalize for swagger2 - for (const [pathKey, path] of Object.entries(parse.jsonLike.paths ?? {})) { - if (path) { - denormalizePaths( - path as FlatOpenAPIV3.PathItemObject, - pathKey, - parse.sourcemap, - warnings - ); - - for (const method of Object.values(OpenAPIV3.HttpMethods)) { - const operation = path?.[method] as - | FlatOpenAPIV3.OperationObject - | undefined; - if (operation) { - denormalizeOperation( - operation, - { path: pathKey, method }, - parse.sourcemap, - warnings - ); + + if (version === '2.x.x') { + for (const [pathKey, path] of Object.entries(parse.jsonLike.paths ?? {})) { + if (path) { + denormalizePathsV2(path, pathKey, parse.sourcemap, warnings); + + for (const method of Object.values(OpenAPIV3.HttpMethods)) { + const operation = path?.[method] as + | FlatOpenAPIV2.OperationObject + | undefined; + if (operation) { + denormalizeOperationV2( + operation, + { path: pathKey, method }, + parse.sourcemap, + warnings + ); + } + } + } + } + } else { + for (const [pathKey, path] of Object.entries(parse.jsonLike.paths ?? {})) { + if (path) { + denormalizePathsV3( + path as FlatOpenAPIV3.PathItemObject, + pathKey, + parse.sourcemap, + warnings + ); + + for (const method of Object.values(OpenAPIV3.HttpMethods)) { + const operation = path?.[method] as + | FlatOpenAPIV3.OperationObject + | undefined; + if (operation) { + denormalizeOperationV3( + operation, + { path: pathKey, method }, + parse.sourcemap, + warnings + ); + } } } } @@ -59,7 +82,76 @@ export function denormalize< return parse; } -export function denormalizePaths( +export function denormalizePathsV2( + path: FlatOpenAPIV2.PathItemObject, + pathKey: string, + sourcemap?: JsonSchemaSourcemap, + warnings?: string[] +) { + if (path.parameters) { + for (const method of SWAGGER2_HTTP_METHODS) { + const operation = path[method]; + if (operation) { + // Merge in parameters + for (const [idx, parameter] of path.parameters.entries()) { + if ('$ref' in parameter) { + continue; + } + // Look for an existing parameter, if it exists, we should keep the more specific parameter + const hasParameter = operation.parameters?.find( + (p) => + !('$ref' in p) && + p.in === parameter.in && + p.name === parameter.name + ); + if (!hasParameter) { + if (!operation.parameters) { + operation.parameters = []; + } + + const oldPointer = jsonPointerHelpers.compile([ + 'paths', + pathKey, + 'parameters', + String(idx), + ]); + const newPointer = jsonPointerHelpers.compile([ + 'paths', + pathKey, + method, + 'parameters', + String(operation.parameters.length), + ]); + + sourcemap && + logPointer(sourcemap, { old: oldPointer, new: newPointer }); + + operation.parameters.push(parameter); + } + } + } + } + } + // Finally, we remove the parameter on the path level + delete path.parameters; +} + +export function denormalizeOperationV2( + operation: FlatOpenAPIV2.OperationObject, + { + path, + method, + }: { + path: string; + method: string; + }, + sourcemap?: JsonSchemaSourcemap, + warnings?: string[] +) { + // Nothing to denormalize for v2 yet +} + +export function denormalizePathsV3( path: FlatOpenAPIV3.PathItemObject, pathKey: string, sourcemap?: JsonSchemaSourcemap, @@ -114,7 +206,7 @@ export function denormalizePaths( } } -export function denormalizeOperation( +export function denormalizeOperationV3( operation: FlatOpenAPIV3.OperationObject, { path, diff --git a/projects/openapi-io/src/index.ts b/projects/openapi-io/src/index.ts index fba9654385..26c4679bff 100644 --- a/projects/openapi-io/src/index.ts +++ b/projects/openapi-io/src/index.ts @@ -24,8 +24,10 @@ import { applyOperationsToYamlString } from './write/yaml-roundtrip'; export { denormalize, - denormalizePaths, - denormalizeOperation, + denormalizePathsV2, + denormalizePathsV3, + denormalizeOperationV2, + denormalizeOperationV3, } from './denormalizers/denormalize'; export { applyOperationsToYamlString, diff --git a/projects/openapi-utilities/src/index.ts b/projects/openapi-utilities/src/index.ts index b7da2f826b..413fa36de4 100644 --- a/projects/openapi-utilities/src/index.ts +++ b/projects/openapi-utilities/src/index.ts @@ -81,7 +81,7 @@ export { getOperationsChanged, getOperationsChangedLabel, } from './utilities/count-changed-operations'; - +export * from './swagger2'; export { compareSpecs, CompareSpecResults, diff --git a/projects/openapi-utilities/src/swagger2/index.ts b/projects/openapi-utilities/src/swagger2/index.ts new file mode 100644 index 0000000000..a92dc2c795 --- /dev/null +++ b/projects/openapi-utilities/src/swagger2/index.ts @@ -0,0 +1,9 @@ +export const SWAGGER2_HTTP_METHODS = [ + 'get', + 'put', + 'post', + 'delete', + 'options', + 'head', + 'patch', +] as const; diff --git a/projects/optic/src/commands/capture/capture.ts b/projects/optic/src/commands/capture/capture.ts index 32ae21db73..3370fc07ae 100644 --- a/projects/optic/src/commands/capture/capture.ts +++ b/projects/optic/src/commands/capture/capture.ts @@ -308,7 +308,7 @@ const getCaptureAction = return; } // We need to load the spec as is with denormalize=true so that the endpoint shas match - spec = denormalize(spec); + spec = denormalize(spec, spec.version); const opticUrlDetails = await getOpticUrlDetails(config, { filePath: path.relative(config.root, path.resolve(filePath)), @@ -479,7 +479,9 @@ export async function processCaptures( } // update existing endpoints - const coverage = new ApiCoverageCounter(denormalize(spec).jsonLike); + const coverage = new ApiCoverageCounter( + denormalize(spec, spec.version).jsonLike + ); let hasAnyDiffs = false; let diffCount = 0; let endpointsAdded = 0; diff --git a/projects/optic/src/commands/capture/coverage/api-coverage.ts b/projects/optic/src/commands/capture/coverage/api-coverage.ts index c93990f6a2..986211c60a 100644 --- a/projects/optic/src/commands/capture/coverage/api-coverage.ts +++ b/projects/optic/src/commands/capture/coverage/api-coverage.ts @@ -21,9 +21,12 @@ export class ApiCoverageCounter { this.coverage = { paths: {}, }; - const { jsonLike: denormalizedSpec } = denormalize({ - jsonLike: JSON.parse(JSON.stringify(spec)), - }); + const { jsonLike: denormalizedSpec } = denormalize( + { + jsonLike: JSON.parse(JSON.stringify(spec)), + }, + '3.0.x' + ); Object.entries(denormalizedSpec.paths ?? {}).forEach(([path, methods]) => { this.coverage.paths[path] = {}; diff --git a/projects/optic/src/utils/spec-loaders.ts b/projects/optic/src/utils/spec-loaders.ts index 95deb4c4e3..bd055a2a7a 100644 --- a/projects/optic/src/utils/spec-loaders.ts +++ b/projects/optic/src/utils/spec-loaders.ts @@ -332,7 +332,7 @@ function validateAndDenormalize( } const warnings = []; const result = options.denormalize - ? denormalize(parseResult, warnings) + ? denormalize(parseResult, parseResult.version, warnings) : parseResult; if (warnings.length !== 0) logger.warn(...warnings);