diff --git a/packages/openapi-to-graphql/README.md b/packages/openapi-to-graphql/README.md index 04af3766..63ea5798 100644 --- a/packages/openapi-to-graphql/README.md +++ b/packages/openapi-to-graphql/README.md @@ -171,6 +171,7 @@ Schema options: - `createSubscriptionsFromCallbacks` (type: `boolean`, default: `false`): Generates subscription fields from [callback objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#CallbackObject). The keys ([runtime expressions](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#runtimeExpression)) of the callback objects will be interpolated as the topic of a publish/subscription connection using [graphql-subscriptions](https://github.com/apollographql/graphql-subscriptions). Read the [doc](./docs/subscriptions.md) for explanations and examples regarding its usage. +- `graphQLSchemaPrefix` (type: `string`, default: `''`): For add a constants prefix for each generated GraphQL schema, i.e. passing `CustomName` for this option, generated `Product` type will be change to `CustomNameProduct`. *** Resolver options: diff --git a/packages/openapi-to-graphql/src/auth_builder.ts b/packages/openapi-to-graphql/src/auth_builder.ts index 950f4358..daf61433 100644 --- a/packages/openapi-to-graphql/src/auth_builder.ts +++ b/packages/openapi-to-graphql/src/auth_builder.ts @@ -30,6 +30,7 @@ import debug from 'debug' import { handleWarning, sortObject, MitigationTypes } from './utils' import { createDataDef } from './preprocessor' import crossFetch from 'cross-fetch' +import {InternalOptions} from './types/options'; const translationLog = debug('translation') @@ -43,7 +44,8 @@ export function createAndLoadViewer( queryFields: object, operationType: GraphQLOperationType, data: PreprocessingData, - fetch: typeof crossFetch + fetch: typeof crossFetch, + options: InternalOptions ): { [key: string]: GraphQLFieldConfig } { const results = {} /** @@ -153,7 +155,8 @@ export function createAndLoadViewer( anyAuthObjectName, anyAuthFields, data, - fetch + fetch, + options, ) return results @@ -252,7 +255,8 @@ function getViewerAnyAuthOT( name: string, queryFields: GraphQLFieldConfigMap, data: PreprocessingData, - fetch: typeof crossFetch + fetch: typeof crossFetch, + options: InternalOptions ): GraphQLFieldConfig { // Resolve function: const resolve: GraphQLFieldResolver = ( @@ -277,14 +281,16 @@ function getViewerAnyAuthOT( data.security[protocolName].schema, true, data, - data.security[protocolName].oas + data.security[protocolName].oas, + options, ) const type = getGraphQLType({ def, data, isInputObjectType: true, - fetch + fetch, + options }) const saneProtocolName = Oas3Tools.sanitize( diff --git a/packages/openapi-to-graphql/src/index.ts b/packages/openapi-to-graphql/src/index.ts index 05a5c01e..6edee732 100644 --- a/packages/openapi-to-graphql/src/index.ts +++ b/packages/openapi-to-graphql/src/index.ts @@ -127,7 +127,10 @@ const DEFAULT_OPTIONS: InternalOptions = { provideErrorExtensions: true, equivalentToMessages: true, - fetch: crossFetch + fetch: crossFetch, + + // Add prefix for each schema generated + graphQLSchemaPrefix: '' } /** @@ -214,7 +217,9 @@ export function translateOpenAPIToGraphQL( provideErrorExtensions, equivalentToMessages, - fetch + fetch, + + graphQLSchemaPrefix }: InternalOptions ): Result { const options = { @@ -256,7 +261,9 @@ export function translateOpenAPIToGraphQL( provideErrorExtensions, equivalentToMessages, - fetch + fetch, + + graphQLSchemaPrefix, } translationLog(`Options: ${JSON.stringify(options)}`) @@ -383,7 +390,8 @@ export function translateOpenAPIToGraphQL( authQueryFields, GraphQLOperationType.Query, data, - fetch + fetch, + options ) ) } @@ -395,7 +403,8 @@ export function translateOpenAPIToGraphQL( authMutationFields, GraphQLOperationType.Mutation, data, - fetch + fetch, + options ) ) } @@ -407,7 +416,8 @@ export function translateOpenAPIToGraphQL( authSubscriptionFields, GraphQLOperationType.Subscription, data, - fetch + fetch, + options ) ) } @@ -493,7 +503,8 @@ function addQueryFields({ requestOptions, fileUploadOptions, connectOptions, - fetch + fetch, + options ) const saneOperationId = Oas3Tools.sanitize( @@ -672,7 +683,8 @@ function addMutationFields({ requestOptions, fileUploadOptions, connectOptions, - fetch + fetch, + options, ) const saneOperationId = Oas3Tools.sanitize( @@ -819,7 +831,8 @@ function addSubscriptionFields({ requestOptions, fileUploadOptions, connectOptions, - fetch + fetch, + options ) const saneOperationId = Oas3Tools.sanitize( @@ -923,14 +936,16 @@ function getFieldForOperation( requestOptions: Partial>, fileUploadOptions: FileUploadOptions, connectOptions: ConnectOptions, - fetch: typeof crossFetch + fetch: typeof crossFetch, + options: InternalOptions ): GraphQLFieldConfig { // Create GraphQL Type for response: const type = getGraphQLType({ def: operation.responseDefinition, data, operation, - fetch + fetch, + options }) as GraphQLOutputType const payloadSchemaName = operation.payloadDefinition @@ -948,7 +963,8 @@ function getFieldForOperation( parameters: operation.parameters, operation, data, - fetch + fetch, + options }) // Get resolver and subscribe function for Subscription fields diff --git a/packages/openapi-to-graphql/src/preprocessor.ts b/packages/openapi-to-graphql/src/preprocessor.ts index defcfe2e..8647a613 100644 --- a/packages/openapi-to-graphql/src/preprocessor.ts +++ b/packages/openapi-to-graphql/src/preprocessor.ts @@ -118,7 +118,8 @@ function processOperation( payloadSchema as SchemaObject, true, data, - oas + oas, + options ) : undefined @@ -132,6 +133,7 @@ function processOperation( false, data, oas, + options, links ) @@ -675,6 +677,7 @@ export function createDataDef( isInputObjectType: boolean, data: PreprocessingData, oas: Oas3, + options: InternalOptions, links?: { [key: string]: LinkObject } ): DataDefinition { const preferredName = getPreferredName(names) @@ -747,14 +750,24 @@ export function createDataDef( return existingDataDef } + let namesFormSchema: Oas3Tools.SchemaNames = names + // Add the prefix to the name + if (options.graphQLSchemaPrefix) { + namesFormSchema = Object.fromEntries( + Object.entries(names).map(([key, value]) => + [key, value ? options.graphQLSchemaPrefix + '-' + value : value] + ) + ) + } + // There is no preexisting data definition, so create a new one - const name = getSchemaName(names, data.usedTypeNames) + const name = getSchemaName(namesFormSchema, data.usedTypeNames) let saneInputName: string let saneName: string - if (name === names.fromExtension) { + if (name === namesFormSchema.fromExtension) { saneName = name saneInputName = name + 'Input' } else { @@ -828,7 +841,8 @@ export function createDataDef( def.required, isInputObjectType, data, - oas + oas, + options ) } else { handleWarning({ @@ -869,7 +883,8 @@ export function createDataDef( itemsSchema as SchemaObject, isInputObjectType, data, - oas + oas, + options ) // Add list item reference @@ -893,7 +908,8 @@ export function createDataDef( isInputObjectType, def, data, - oas + oas, + options ) } else { throw new Error( @@ -919,7 +935,8 @@ export function createDataDef( isInputObjectType, def, data, - oas + oas, + options ) } else { throw new Error( @@ -1226,7 +1243,8 @@ function addObjectPropertiesToDataDef( required: string[], isInputObjectType: boolean, data: PreprocessingData, - oas: Oas3 + oas: Oas3, + options: InternalOptions ) { /** * Resolve all required properties @@ -1268,7 +1286,8 @@ function addObjectPropertiesToDataDef( propSchema, isInputObjectType, data, - oas + oas, + options ) // Add field type references @@ -1351,7 +1370,8 @@ function createAnyOfObject( isInputObjectType: boolean, def: DataDefinition, data: PreprocessingData, - oas: Oas3 + oas: Oas3, + options: InternalOptions ) { /** * Used to find incompatible properties @@ -1481,7 +1501,8 @@ function createAnyOfObject( def.required, isInputObjectType, data, - oas + oas, + options ) } @@ -1503,7 +1524,8 @@ function createAnyOfObject( propertySchema, isInputObjectType, data, - oas + oas, + options, ) /** @@ -1540,7 +1562,8 @@ function createOneOfUnion( isInputObjectType: boolean, def: DataDefinition, data: PreprocessingData, - oas: Oas3 + oas: Oas3, + options: InternalOptions ) { if (isInputObjectType) { handleWarning({ @@ -1584,6 +1607,7 @@ function createOneOfUnion( isInputObjectType, data, oas, + options, def.links ) ;(def.subDefinitions as DataDefinition[]).push(subDefinition) diff --git a/packages/openapi-to-graphql/src/schema_builder.ts b/packages/openapi-to-graphql/src/schema_builder.ts index 0475f456..cfd3f5aa 100644 --- a/packages/openapi-to-graphql/src/schema_builder.ts +++ b/packages/openapi-to-graphql/src/schema_builder.ts @@ -46,13 +46,15 @@ import { createDataDef } from './preprocessor' import debug from 'debug' import { handleWarning, sortObject, MitigationTypes } from './utils' import crossFetch from 'cross-fetch' +import {InternalOptions} from './types/options'; type GetArgsParams = { requestPayloadDef?: DataDefinition parameters: ParameterObject[] operation?: Operation data: PreprocessingData - fetch: typeof crossFetch + fetch: typeof crossFetch, + options: InternalOptions } type CreateOrReuseComplexTypeParams = { @@ -61,7 +63,8 @@ type CreateOrReuseComplexTypeParams = { iteration?: number // Count of recursions used to create type isInputObjectType?: boolean // Does not require isInputObjectType because unions must be composed of objects data: PreprocessingData // Data produced by preprocessing - fetch: typeof crossFetch + fetch: typeof crossFetch, + options: InternalOptions } type CreateOrReuseSimpleTypeParams = { @@ -76,7 +79,8 @@ type CreateFieldsParams = { iteration: number isInputObjectType: boolean data: PreprocessingData - fetch: typeof crossFetch + fetch: typeof crossFetch, + options: InternalOptions } type LinkOpRefToOpIdParams = { @@ -141,7 +145,8 @@ export function getGraphQLType({ data, iteration = 0, isInputObjectType = false, - fetch + fetch, + options }: CreateOrReuseComplexTypeParams): | GraphQLOutputType | GraphQLInputType { @@ -164,7 +169,8 @@ export function getGraphQLType({ data, iteration, isInputObjectType, - fetch + fetch, + options }) // CASE: union - create union type @@ -174,7 +180,8 @@ export function getGraphQLType({ operation, data, iteration, - fetch + fetch, + options }) // CASE: list - create list type @@ -185,7 +192,8 @@ export function getGraphQLType({ data, iteration, isInputObjectType, - fetch + fetch, + options }) // CASE: enum - create enum type @@ -225,7 +233,7 @@ export function getGraphQLType({ return def.graphQLType case TargetGraphQLType.upload: - def.graphQLType = GraphQLUpload + def.graphQLType = GraphQLUpload as any return def.graphQLType } } @@ -251,7 +259,8 @@ function createOrReuseOt({ data, iteration, isInputObjectType, - fetch + fetch, + options }: CreateOrReuseComplexTypeParams): | GraphQLObjectType | GraphQLInputObjectType { @@ -311,7 +320,8 @@ function createOrReuseOt({ data, iteration, isInputObjectType: false, - fetch + fetch, + options }) as GraphQLFieldConfigMap } }) @@ -338,7 +348,8 @@ function createOrReuseOt({ data, iteration, isInputObjectType: true, - fetch + fetch, + options }) as GraphQLInputFieldConfigMap } }) @@ -355,7 +366,8 @@ function createOrReuseUnion({ operation, data, iteration, - fetch + fetch, + options }: CreateOrReuseComplexTypeParams): GraphQLUnionType { // Try to reuse existing union type if (typeof def.graphQLType !== 'undefined') { @@ -391,7 +403,8 @@ function createOrReuseUnion({ data, iteration: iteration + 1, isInputObjectType: false, - fetch + fetch, + options }) as GraphQLObjectType } ) @@ -501,7 +514,8 @@ function createOrReuseList({ iteration, isInputObjectType, data, - fetch + fetch, + options }: CreateOrReuseComplexTypeParams): GraphQLList { const name = isInputObjectType ? def.graphQLInputObjectTypeName @@ -541,7 +555,8 @@ function createOrReuseList({ operation, iteration: iteration + 1, isInputObjectType, - fetch + fetch, + options }) if (itemsType !== null) { @@ -639,7 +654,8 @@ function createFields({ data, iteration, isInputObjectType, - fetch + fetch, + options }: CreateFieldsParams): | GraphQLFieldConfigMap | GraphQLInputFieldConfigMap { @@ -661,7 +677,8 @@ function createFields({ data, iteration: iteration + 1, isInputObjectType, - fetch + fetch, + options }) const requiredProperty = @@ -794,7 +811,8 @@ function createFields({ parameters: dynamicParams, operation: linkedOp, data, - fetch + fetch, + options, }) // Get response object type @@ -807,7 +825,8 @@ function createFields({ data, iteration: iteration + 1, isInputObjectType: false, - fetch + fetch, + options }) as GraphQLOutputType) let description = link.description @@ -1183,7 +1202,8 @@ export function getArgs({ parameters, operation, data, - fetch + fetch, + options }: GetArgsParams): Args { let args = {} @@ -1265,7 +1285,8 @@ export function getArgs({ schema as SchemaObject, true, data, - operation.oas + operation.oas, + options ) const type = getGraphQLType({ @@ -1274,7 +1295,8 @@ export function getArgs({ data, iteration: 0, isInputObjectType: true, - fetch + fetch, + options }) /** @@ -1349,7 +1371,8 @@ export function getArgs({ data, operation, isInputObjectType: true, // Request payloads will always be an input object type, - fetch + fetch, + options }) // Sanitize the argument name diff --git a/packages/openapi-to-graphql/src/types/options.ts b/packages/openapi-to-graphql/src/types/options.ts index 3722bcd0..867e7efa 100644 --- a/packages/openapi-to-graphql/src/types/options.ts +++ b/packages/openapi-to-graphql/src/types/options.ts @@ -93,6 +93,7 @@ export type Options = Partial< > export type InternalOptions = { + graphQLSchemaPrefix: string; /* * Adhere to the OAS as closely as possible. If set to true, any deviation * from the OAS will lead OpenAPI-to-GraphQL to throw.