|
|
@@ -2,18 +2,34 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
|
|
|
import { DynamicModule } from '@nestjs/common';
|
|
|
import { GraphQLModule, GraphQLTypesLoader } from '@nestjs/graphql';
|
|
|
import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
|
|
|
-import { buildSchema, extendSchema, GraphQLSchema, printSchema, ValidationContext } from 'graphql';
|
|
|
+import {
|
|
|
+ buildClientSchema,
|
|
|
+ buildSchema,
|
|
|
+ extendSchema,
|
|
|
+ GraphQLSchema,
|
|
|
+ IntrospectionQuery,
|
|
|
+ IntrospectionSchema,
|
|
|
+ printIntrospectionSchema,
|
|
|
+ printSchema,
|
|
|
+ ValidationContext,
|
|
|
+} from 'graphql';
|
|
|
import path from 'path';
|
|
|
|
|
|
import { ConfigModule } from '../../config/config.module';
|
|
|
import { ConfigService } from '../../config/config.service';
|
|
|
-import { AutoIncrementIdStrategy, EntityIdStrategy, UuidIdStrategy } from '../../config/index';
|
|
|
+import {
|
|
|
+ AutoIncrementIdStrategy,
|
|
|
+ EntityIdStrategy,
|
|
|
+ RuntimeVendureConfig,
|
|
|
+ UuidIdStrategy,
|
|
|
+} from '../../config/index';
|
|
|
import { I18nModule } from '../../i18n/i18n.module';
|
|
|
import { I18nService } from '../../i18n/i18n.service';
|
|
|
import { getPluginAPIExtensions } from '../../plugin/plugin-metadata';
|
|
|
import { ServiceModule } from '../../service/service.module';
|
|
|
import { ApiSharedModule } from '../api-internal-modules';
|
|
|
import { CustomFieldRelationResolverService } from '../common/custom-field-relation-resolver.service';
|
|
|
+import { ApiType } from '../common/get-api-type';
|
|
|
import { IdCodecService } from '../common/id-codec.service';
|
|
|
import { AssetInterceptorPlugin } from '../middleware/asset-interceptor-plugin';
|
|
|
import { IdCodecPlugin } from '../middleware/id-codec-plugin';
|
|
|
@@ -143,43 +159,88 @@ async function createGraphQLOptions(
|
|
|
* 3. any schema extensions defined by plugins
|
|
|
*/
|
|
|
async function buildSchemaForApi(apiType: 'shop' | 'admin'): Promise<GraphQLSchema> {
|
|
|
- const customFields = configService.customFields;
|
|
|
- // Paths must be normalized to use forward-slash separators.
|
|
|
- // See https://github.com/nestjs/graphql/issues/336
|
|
|
- const normalizedPaths = options.typePaths.map(p => p.split(path.sep).join('/'));
|
|
|
- const typeDefs = await typesLoader.mergeTypesByPaths(normalizedPaths);
|
|
|
- const authStrategies =
|
|
|
- apiType === 'shop'
|
|
|
- ? configService.authOptions.shopAuthenticationStrategy
|
|
|
- : configService.authOptions.adminAuthenticationStrategy;
|
|
|
- let schema = buildSchema(typeDefs);
|
|
|
-
|
|
|
- getPluginAPIExtensions(configService.plugins, apiType)
|
|
|
- .map(e => (typeof e.schema === 'function' ? e.schema() : e.schema))
|
|
|
- .filter(notNullOrUndefined)
|
|
|
- .forEach(documentNode => (schema = extendSchema(schema, documentNode)));
|
|
|
- schema = generateListOptions(schema);
|
|
|
- schema = addGraphQLCustomFields(schema, customFields, apiType === 'shop');
|
|
|
- schema = addOrderLineCustomFieldsInput(schema, customFields.OrderLine || [], apiType === 'shop');
|
|
|
- schema = addModifyOrderCustomFields(schema, customFields.Order || []);
|
|
|
- schema = addShippingMethodQuoteCustomFields(schema, customFields.ShippingMethod || []);
|
|
|
- schema = addPaymentMethodQuoteCustomFields(schema, customFields.PaymentMethod || []);
|
|
|
- schema = generateAuthenticationTypes(schema, authStrategies);
|
|
|
- schema = generateErrorCodeEnum(schema);
|
|
|
- if (apiType === 'admin') {
|
|
|
- schema = addServerConfigCustomFields(schema, customFields);
|
|
|
- schema = addActiveAdministratorCustomFields(schema, customFields.Administrator);
|
|
|
- }
|
|
|
- if (apiType === 'shop') {
|
|
|
- schema = addRegisterCustomerCustomFieldsInput(schema, customFields.Customer || []);
|
|
|
- schema = generateActiveOrderTypes(schema, configService.orderOptions.activeOrderStrategy);
|
|
|
- }
|
|
|
- schema = generatePermissionEnum(schema, configService.authOptions.customPermissions);
|
|
|
+ return getFinalVendureSchema({
|
|
|
+ config: configService,
|
|
|
+ typePaths: options.typePaths,
|
|
|
+ typesLoader,
|
|
|
+ apiType,
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+type GetSchemaOptions = {
|
|
|
+ config: RuntimeVendureConfig;
|
|
|
+ typePaths: string[];
|
|
|
+ typesLoader: GraphQLTypesLoader;
|
|
|
+ apiType: 'shop' | 'admin';
|
|
|
+};
|
|
|
+type GetSchemaAsSDLOptions = GetSchemaOptions & { output: 'sdl' };
|
|
|
+
|
|
|
+export async function getFinalVendureSchema(options: GetSchemaOptions): Promise<GraphQLSchema>;
|
|
|
+export async function getFinalVendureSchema(options: GetSchemaAsSDLOptions): Promise<string>;
|
|
|
+export async function getFinalVendureSchema(
|
|
|
+ options: GetSchemaOptions & { output?: 'sdl' },
|
|
|
+): Promise<GraphQLSchema | string> {
|
|
|
+ const { config, typePaths, typesLoader, apiType } = options;
|
|
|
+ // Paths must be normalized to use forward-slash separators.
|
|
|
+ // See https://github.com/nestjs/graphql/issues/336
|
|
|
+ const normalizedPaths = typePaths.map(p => p.split(path.sep).join('/'));
|
|
|
+ const typeDefs = await typesLoader.mergeTypesByPaths(normalizedPaths);
|
|
|
+ let schema = buildSchema(typeDefs);
|
|
|
+ schema = buildSchemaFromVendureConfig(schema, config, apiType);
|
|
|
+ if (options.output === 'sdl') {
|
|
|
+ return printSchema(schema);
|
|
|
+ } else {
|
|
|
return schema;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+export function buildSchemaFromVendureConfig(
|
|
|
+ schema: GraphQLSchema,
|
|
|
+ config: RuntimeVendureConfig,
|
|
|
+ apiType: 'shop' | 'admin',
|
|
|
+): GraphQLSchema {
|
|
|
+ const authStrategies =
|
|
|
+ apiType === 'shop'
|
|
|
+ ? config.authOptions.shopAuthenticationStrategy
|
|
|
+ : config.authOptions.adminAuthenticationStrategy;
|
|
|
+
|
|
|
+ const customFields = config.customFields;
|
|
|
+
|
|
|
+ schema = extendSchemaWithPluginApiExtensions(schema, config.plugins, apiType);
|
|
|
+ schema = generateListOptions(schema);
|
|
|
+ schema = addGraphQLCustomFields(schema, customFields, apiType === 'shop');
|
|
|
+ schema = addOrderLineCustomFieldsInput(schema, customFields.OrderLine || [], apiType === 'shop');
|
|
|
+ schema = addModifyOrderCustomFields(schema, customFields.Order || []);
|
|
|
+ schema = addShippingMethodQuoteCustomFields(schema, customFields.ShippingMethod || []);
|
|
|
+ schema = addPaymentMethodQuoteCustomFields(schema, customFields.PaymentMethod || []);
|
|
|
+ schema = generateAuthenticationTypes(schema, authStrategies);
|
|
|
+ schema = generateErrorCodeEnum(schema);
|
|
|
+ if (apiType === 'admin') {
|
|
|
+ schema = addServerConfigCustomFields(schema, customFields);
|
|
|
+ schema = addActiveAdministratorCustomFields(schema, customFields.Administrator);
|
|
|
+ }
|
|
|
+ if (apiType === 'shop') {
|
|
|
+ schema = addRegisterCustomerCustomFieldsInput(schema, customFields.Customer || []);
|
|
|
+ schema = generateActiveOrderTypes(schema, config.orderOptions.activeOrderStrategy);
|
|
|
+ }
|
|
|
+ schema = generatePermissionEnum(schema, config.authOptions.customPermissions);
|
|
|
+
|
|
|
+ return schema;
|
|
|
+}
|
|
|
+
|
|
|
+function extendSchemaWithPluginApiExtensions(
|
|
|
+ schema: GraphQLSchema,
|
|
|
+ plugins: RuntimeVendureConfig['plugins'],
|
|
|
+ apiType: 'admin' | 'shop',
|
|
|
+) {
|
|
|
+ getPluginAPIExtensions(plugins, apiType)
|
|
|
+ .map(e => (typeof e.schema === 'function' ? e.schema() : e.schema))
|
|
|
+ .filter(notNullOrUndefined)
|
|
|
+ .forEach(documentNode => (schema = extendSchema(schema, documentNode)));
|
|
|
+ return schema;
|
|
|
+}
|
|
|
+
|
|
|
function isUsingDefaultEntityIdStrategy(entityIdStrategy: EntityIdStrategy<any>): boolean {
|
|
|
return (
|
|
|
entityIdStrategy.constructor === AutoIncrementIdStrategy ||
|