From d63bd93e0feedf7bcdb4dc49c22e3c09d11ee8ea Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Mon, 7 Nov 2022 18:50:12 +0300 Subject: [PATCH] fix(openapi): avoid conflicts with the predefined `Subscription` type definitions (#4792) --- .changeset/late-jeans-begin.md | 7 + .../src/healUntitledDefinitions.ts | 3 + .../src/getComposerFromJSONSchema.ts | 2 +- .../tests/__snapshots__/schemas.test.ts.snap | 311 ++++++++++++++++++ .../tests/fixtures/subscriptionType.yml | 87 +++++ .../loaders/openapi/tests/schemas.test.ts | 1 + 6 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 .changeset/late-jeans-begin.md create mode 100644 packages/loaders/openapi/tests/fixtures/subscriptionType.yml diff --git a/.changeset/late-jeans-begin.md b/.changeset/late-jeans-begin.md new file mode 100644 index 0000000000000..87e4f59f2c278 --- /dev/null +++ b/.changeset/late-jeans-begin.md @@ -0,0 +1,7 @@ +--- +'json-machete': patch +'@omnigraph/json-schema': patch +'@omnigraph/openapi': patch +--- + +Add suffix to the existing "Subscription" types to avoid conflicts diff --git a/packages/json-machete/src/healUntitledDefinitions.ts b/packages/json-machete/src/healUntitledDefinitions.ts index 727bd4c592b17..0cff1005576ae 100644 --- a/packages/json-machete/src/healUntitledDefinitions.ts +++ b/packages/json-machete/src/healUntitledDefinitions.ts @@ -12,6 +12,9 @@ export function handleUntitledDefinitions(schemaDocument: any) { if (!definition.$ref) { if (!definition.title) { definition.title = definitionName; + if (definition.title === 'Subscription') { + definition.title += '_'; + } } else { const seenDefinition = seen.get(definition.title); if (seenDefinition) { diff --git a/packages/loaders/json-schema/src/getComposerFromJSONSchema.ts b/packages/loaders/json-schema/src/getComposerFromJSONSchema.ts index 44b567b978474..2621f13a70eb8 100644 --- a/packages/loaders/json-schema/src/getComposerFromJSONSchema.ts +++ b/packages/loaders/json-schema/src/getComposerFromJSONSchema.ts @@ -664,7 +664,7 @@ export function getComposerFromJSONSchema(schema: JSONSchema, logger: Logger): P ...subSchema, }; case 'Subscription': - if (path.startsWith('/properties/subscription')) { + if (path === '/properties/subscription') { return { output: schemaComposer.Subscription, ...subSchema, diff --git a/packages/loaders/openapi/tests/__snapshots__/schemas.test.ts.snap b/packages/loaders/openapi/tests/__snapshots__/schemas.test.ts.snap index 2dcd3291dd105..f614d6fa3bd38 100644 --- a/packages/loaders/openapi/tests/__snapshots__/schemas.test.ts.snap +++ b/packages/loaders/openapi/tests/__snapshots__/schemas.test.ts.snap @@ -689996,6 +689996,317 @@ enum mutationInput_PostWebhookEndpointsWebhookEndpoint_input_enabled_events_item scalar mutationInput_PostWebhookEndpointsWebhookEndpoint_input_expand_items" `; +exports[`Schemas SubscriptionType should generate the correct bundle: SubscriptionType 1`] = ` +{ + "baseUrl": "http://api.example.com/v1", + "name": "SubscriptionType", + "operationHeaders": {}, + "operations": [ + { + "argTypeMap": { + "company_id": { + "description": "Company ID", + "format": "int64", + "name": "company_id", + "nullable": false, + "type": "integer", + }, + }, + "description": undefined, + "field": "a", + "method": "GET", + "operationHeaders": undefined, + "path": "/a/{args.company_id}/a", + "responseByStatusCode": {}, + "schemaHeaders": undefined, + "type": "query", + }, + { + "description": undefined, + "field": "b", + "headers": { + "Content-Type": "application/json", + }, + "method": "POST", + "operationHeaders": undefined, + "path": "/b", + "requestSchema": { + "format": "int64", + "title": "b_request", + "type": "integer", + }, + "responseByStatusCode": {}, + "schemaHeaders": undefined, + "type": "mutation", + }, + { + "description": undefined, + "field": "bFailed", + "pubsubTopic": "webhook:put:https://url", + "responseSchema": { + "properties": { + "uuid": { + "format": "uuid", + "type": "string", + }, + }, + "required": [ + "uuid", + ], + "title": "subscription_bFailed", + "type": "object", + }, + "type": "subscription", + }, + { + "argTypeMap": { + "company_id": { + "description": "Company ID", + "format": "int64", + "name": "company_id", + "nullable": false, + "type": "integer", + }, + }, + "description": "Get a list of subscriptions", + "field": "listSubscriptions", + "headers": { + "accept": "application/json", + }, + "method": "GET", + "operationHeaders": undefined, + "path": "/subscriptions", + "responseByStatusCode": { + "200": { + "responseSchema": { + "$resolvedRef": "/components/schemas/Subscription", + "properties": { + "id": { + "type": "string", + }, + }, + "required": [ + "id", + ], + "title": "Subscription_", + "type": "object", + }, + }, + }, + "schemaHeaders": undefined, + "type": "query", + }, + ], + "referencedSchema": { + "$ref": "#/definitions/_schema", + "definitions": { + "Any": { + "oneOf": [ + { + "type": "string", + }, + { + "type": "integer", + }, + { + "type": "boolean", + }, + { + "type": "number", + }, + { + "$ref": "#/definitions/query_repos_by_owner_by_repo_by_archive_format_by_path_oneOf_4", + }, + ], + "title": "Any", + }, + "Mutation": { + "properties": { + "b": { + "$ref": "#/definitions/Any", + }, + }, + "readOnly": true, + "title": "Mutation", + "type": "object", + }, + "MutationInput": { + "properties": { + "b": { + "$ref": "#/definitions/mutationInput_b", + }, + }, + "title": "MutationInput", + "type": "object", + "writeOnly": true, + }, + "Query": { + "properties": { + "a": { + "$ref": "#/definitions/Any", + }, + "listSubscriptions": { + "$ref": "#/definitions/Subscription_", + }, + }, + "readOnly": true, + "title": "Query", + "type": "object", + }, + "QueryInput": { + "properties": { + "a": { + "$ref": "#/definitions/queryInput_a", + }, + }, + "title": "QueryInput", + "type": "object", + "writeOnly": true, + }, + "Subscription": { + "properties": { + "bFailed": { + "$ref": "#/definitions/subscription_bFailed", + }, + }, + "readOnly": true, + "title": "Subscription", + "type": "object", + }, + "SubscriptionInput": { + "additionalProperties": true, + "title": "SubscriptionInput", + "type": "object", + "writeOnly": true, + }, + "Subscription_": { + "$resolvedRef": "/components/schemas/Subscription", + "properties": { + "id": { + "type": "string", + }, + }, + "required": [ + "id", + ], + "title": "Subscription_", + "type": "object", + }, + "_schema": { + "properties": { + "mutation": { + "$ref": "#/definitions/Mutation", + }, + "mutationInput": { + "$ref": "#/definitions/MutationInput", + }, + "query": { + "$ref": "#/definitions/Query", + }, + "queryInput": { + "$ref": "#/definitions/QueryInput", + }, + "subscription": { + "$ref": "#/definitions/Subscription", + }, + "subscriptionInput": { + "$ref": "#/definitions/SubscriptionInput", + }, + }, + "required": [ + "query", + ], + "title": "_schema", + "type": "object", + }, + "b_request": { + "format": "int64", + "title": "b_request", + "type": "integer", + }, + "mutationInput_b": { + "properties": { + "input": { + "$ref": "#/definitions/b_request", + }, + }, + "title": "mutationInput_b", + "type": "object", + }, + "queryInput_a": { + "properties": { + "company_id": { + "description": "Company ID", + "format": "int64", + "name": "company_id", + "nullable": false, + "type": "integer", + }, + }, + "title": "queryInput_a", + "type": "object", + }, + "subscription_bFailed": { + "properties": { + "uuid": { + "format": "uuid", + "type": "string", + }, + }, + "required": [ + "uuid", + ], + "title": "subscription_bFailed", + "type": "object", + }, + }, + }, +} +`; + +exports[`Schemas SubscriptionType should generate the correct schema: SubscriptionType 1`] = ` +"schema { + query: Query + mutation: Mutation + subscription: Subscription +} + +type Query { + a( + "Company ID" + company_id: BigInt! + ): JSON + "Get a list of subscriptions" + listSubscriptions: Subscription_ +} + +"The \`JSON\` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)." +scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") + +"The \`BigInt\` scalar type represents non-fractional signed whole numeric values." +scalar BigInt + +type Subscription_ { + id: String! +} + +type Mutation { + b(input: BigInt): JSON +} + +type Subscription { + "PubSub Topic: webhook:put:https://url" + bFailed: subscription_bFailed +} + +type subscription_bFailed { + uuid: UUID! +} + +"A field whose value is a generic Universally Unique Identifier: https://en.wikipedia.org/wiki/Universally_unique_identifier." +scalar UUID" +`; + exports[`Schemas Toto should generate the correct bundle: Toto 1`] = ` { "baseUrl": "https://dev-api.test.com/api/v1", diff --git a/packages/loaders/openapi/tests/fixtures/subscriptionType.yml b/packages/loaders/openapi/tests/fixtures/subscriptionType.yml new file mode 100644 index 0000000000000..25f8c2a3bd29c --- /dev/null +++ b/packages/loaders/openapi/tests/fixtures/subscriptionType.yml @@ -0,0 +1,87 @@ +openapi: 3.0.2 +info: + title: Sample API + description: test + version: 0.1.9 +servers: + - url: http://api.example.com/v1 + description: test +paths: + '/a/{company_id}/a': + get: + operationId: a + parameters: + - name: company_id + in: path + description: Company ID + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: a + /b: + post: + operationId: b + requestBody: + description: b + required: true + content: + application/json: + schema: + type: integer + format: int64 + callbacks: + bFailed: + 'https://url': + put: + operationId: bFailed + requestBody: + content: + application/json: + schema: + type: object + properties: + uuid: + type: string + format: uuid + required: + - uuid + responses: + '200': + description: OK + responses: + '202': + description: b + '/subscriptions': + get: + tags: + - Subscriptions + summary: Get a list of subscriptions + operationId: listSubscriptions + parameters: + - name: company_id + in: path + description: Company ID + required: true + schema: + type: integer + format: int64 + example: 1234 + responses: + '200': + description: List of subscriptions for the company + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' +components: + schemas: + Subscription: + type: object + properties: + id: + type: string + required: + - id diff --git a/packages/loaders/openapi/tests/schemas.test.ts b/packages/loaders/openapi/tests/schemas.test.ts index 2ea0d93ea5a02..cadf48e7d608c 100644 --- a/packages/loaders/openapi/tests/schemas.test.ts +++ b/packages/loaders/openapi/tests/schemas.test.ts @@ -15,6 +15,7 @@ const schemas = { WeatherUnderground: 'weather_underground.json', Dictionary: 'dictionary.json', Headers: 'headers.json', + SubscriptionType: 'subscriptionType.yml', }; describe('Schemas', () => {