diff --git a/src/context.ts b/src/context.ts index 9f717075..25ed14d7 100644 --- a/src/context.ts +++ b/src/context.ts @@ -32,6 +32,8 @@ export function createContext>( return resolveRef.call(this, target); } catch { return target; + } finally { + this.parentId = this.ids[context]; } } diff --git a/src/oas/__tests__/__snapshots__/operation.test.ts.snap b/src/oas/__tests__/__snapshots__/operation.test.ts.snap index 9dcc4f4c..6dc6bea5 100644 --- a/src/oas/__tests__/__snapshots__/operation.test.ts.snap +++ b/src/oas/__tests__/__snapshots__/operation.test.ts.snap @@ -580,7 +580,7 @@ Array [ ], "type": "object", "x-stoplight": Object { - "id": "b3c54fc227df9", + "id": "d1d03adc8237d", }, }, }, @@ -603,7 +603,7 @@ Array [ ], "type": "object", "x-stoplight": Object { - "id": "b3c54fc227df9", + "id": "d1d03adc8237d", }, }, }, @@ -743,7 +743,7 @@ Array [ ], "type": "object", "x-stoplight": Object { - "id": "849b52cd05782", + "id": "2b4cfd51fbcde", }, "xml": Object { "name": "Pet", @@ -799,7 +799,7 @@ Array [ ], "type": "object", "x-stoplight": Object { - "id": "849b52cd05782", + "id": "2b4cfd51fbcde", }, "xml": Object { "name": "Pet", @@ -1020,7 +1020,7 @@ Array [ ], "type": "object", "x-stoplight": Object { - "id": "849b52cd05782", + "id": "2b4cfd51fbcde", }, "xml": Object { "name": "Pet", @@ -1076,7 +1076,7 @@ Array [ ], "type": "object", "x-stoplight": Object { - "id": "849b52cd05782", + "id": "2b4cfd51fbcde", }, "xml": Object { "name": "Pet", @@ -1139,7 +1139,7 @@ Array [ ], "type": "object", "x-stoplight": Object { - "id": "b9501a9ded2c5", + "id": "d1d03adc8237d", }, }, }, diff --git a/src/oas3/__fixtures__/id.json b/src/oas3/__tests__/__fixtures__/id/input.json similarity index 100% rename from src/oas3/__fixtures__/id.json rename to src/oas3/__tests__/__fixtures__/id/input.json diff --git a/src/oas3/__fixtures__/output.ts b/src/oas3/__tests__/__fixtures__/id/output.ts similarity index 99% rename from src/oas3/__fixtures__/output.ts rename to src/oas3/__tests__/__fixtures__/id/output.ts index ad23cb03..394c4137 100644 --- a/src/oas3/__fixtures__/output.ts +++ b/src/oas3/__tests__/__fixtures__/id/output.ts @@ -1,5 +1,5 @@ /** - NOTE that if any object anywhere ever has an `x-stoplight-id` on it, prefer that + NOTE that if any object anywhere ever has an `x-stoplight.id` on it, prefer that over calling the generate function. Used https://md5calc.com/hash/fnv1a32 to hash the ids. diff --git a/src/oas3/__tests__/__fixtures__/shared-components/input.json b/src/oas3/__tests__/__fixtures__/shared-components/input.json new file mode 100644 index 00000000..cb96f404 --- /dev/null +++ b/src/oas3/__tests__/__fixtures__/shared-components/input.json @@ -0,0 +1,66 @@ +{ + "x-stoplight": { + "id": "service_abc" + }, + "openapi": "3.0.3", + "info": { + "version": "0.0.3", + "title": "GitHub v3 REST API", + "description": "GitHub's v3 REST API." + }, + "paths": { + "/orgs/{org}/repos": { + "get": { + "summary": "Get a organization repository", + "responses": { + "403": { + "$ref": "#/components/responses/forbidden" + } + } + } + } + }, + "components": { + "schemas": { + "basic-error": { + "title": "Basic Error", + "description": "Basic Error", + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "rate-limit": { + "title": "Rate Limit", + "description": "The number of allowed requests in the current period", + "type": "integer" + } + }, + "headers": { + "X-Rate-Limit": { + "schema": { + "$ref": "#/components/schemas/rate-limit" + } + } + }, + "responses": { + "forbidden": { + "headers": { + "X-Rate-Limit": { + "$ref": "#/components/headers/X-Rate-Limit" + } + }, + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/basic-error" + } + } + } + } + } + } +} diff --git a/src/oas3/__tests__/__fixtures__/shared-components/output.ts b/src/oas3/__tests__/__fixtures__/shared-components/output.ts new file mode 100644 index 00000000..f7cd9c0d --- /dev/null +++ b/src/oas3/__tests__/__fixtures__/shared-components/output.ts @@ -0,0 +1,105 @@ +/** + NOTE that if any object anywhere ever has a `x-stoplight.id` on it, prefer that + over calling the generate function. + */ +export default [ + /** + * The http_service + */ + { + // hash(document id - end user needs to be able to customize this.) + // this example has a x-stoplight.id prop on the root though, so using that + id: 'service_abc', + version: '0.0.3', + name: 'GitHub v3 REST API', + description: "GitHub's v3 REST API.", + }, + + /** + * http_operation 1 of 1 (the GET operation) + */ + { + // hash(`http_operation-${parentId}-${method}-${pathWithParamNamesEmpty}`) + // for pathWithParamNamesEmpty, remove all characters between {} segments + // closest parent with an id is the service, so ends up being... + // hash('http_operation-service_abc-get-/orgs/{}/repos') + id: '376a534068842', + method: 'get', + path: '/orgs/{org}/repos', + summary: 'Get a organization repository', + responses: [ + { + // hash(`http_response-${parentId}-${response.code || response key (for shared response)}`) + // closest parent with an id is the operation, so ends up being... + // hash('http_response-service_abc-forbidden') + id: 'c73bfcb376d49', + code: '403', + description: 'Forbidden', + headers: [ + { + // hash(`http_header-${parentId}-${header key}`) + // it's a shared header, so the closest parent is the service. + // hash('http_header-service_abc-X-Rate-Limit') + id: '96620a275464f', + name: 'X-Rate-Limit', + style: 'simple', + encodings: [], + examples: [], + schema: { + $schema: 'http://json-schema.org/draft-07/schema#', + // hash(`http_header-${parentId}-${header key}`) + // it's a shared header, so the closest parent is the service. + // hash('schema-service_abc-rate-limit') + 'x-stoplight': { + id: '72da152ada960', + }, + type: 'integer', + description: 'The number of allowed requests in the current period', + title: 'Rate Limit', + }, + }, + ], + contents: [ + { + // hash(`http_media-${parentId}-${mediaType}`) + // closest parent with an id is the response, so ends up being... + // hash('http_media-c73bfcb376d49-application/json') + id: '4143bd61bfef9', + mediaType: 'application/json', + schema: { + $schema: 'http://json-schema.org/draft-07/schema#', + 'x-stoplight': { + // hash('schema-service_abc-basic-error') + id: '5cbb77597a983', + }, + title: 'Basic Error', + description: 'Basic Error', + type: 'object', + properties: { + message: { + type: 'string', + }, + }, + }, + examples: [], + encodings: [], + }, + ], + }, + ], + servers: [], + request: { + body: { + id: '913ab62a764b4', + contents: [], + }, + headers: [], + query: [], + cookie: [], + path: [], + }, + tags: [], + security: [], + extensions: {}, + }, +]; diff --git a/src/oas3/__tests__/ids.test.ts b/src/oas3/__tests__/ids.test.ts index 7aa3126b..583d5cbd 100644 --- a/src/oas3/__tests__/ids.test.ts +++ b/src/oas3/__tests__/ids.test.ts @@ -4,9 +4,14 @@ import * as path from 'path'; import { transformOas3Operations } from '../operation'; import { transformOas3Service } from '../service'; -test('should generate proper ids', async () => { - const document = JSON.parse(await fs.promises.readFile(path.join(__dirname, '../__fixtures__/id.json'), 'utf8')); - const { default: output } = await import('../__fixtures__/output'); +test.each(fs.readdirSync(path.join(__dirname, './__fixtures__')))( + 'given %s, should generate proper ids', + async name => { + const document = JSON.parse( + await fs.promises.readFile(path.join(__dirname, './__fixtures__', name, 'input.json'), 'utf8'), + ); + const { default: output } = await import(`./__fixtures__/${name}/output`); - expect([transformOas3Service({ document }), ...transformOas3Operations(document)]).toEqual(output); -}); + expect([transformOas3Service({ document }), ...transformOas3Operations(document)]).toEqual(output); + }, +);