Skip to content

Commit

Permalink
fix(): resolve merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec committed Feb 23, 2020
2 parents 0d7363a + 48ff69c commit 6d37373
Show file tree
Hide file tree
Showing 73 changed files with 2,901 additions and 576 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"trailingComma": "all",
"singleQuote": true
}
}
1 change: 1 addition & 0 deletions lib/decorators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './mutation.decorator';
export * from './parent.decorator';
export * from './query.decorator';
export * from './resolve-property.decorator';
export * from './resolve-reference.decorator';
export * from './resolver.decorator';
export * from './root.decorator';
export * from './scalar.decorator';
Expand Down
12 changes: 12 additions & 0 deletions lib/decorators/resolve-reference.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { RESOLVER_REFERENCE_METADATA } from '../graphql.constants';
import { SetMetadata } from '@nestjs/common';

export function ResolveReference(): MethodDecorator {
return (
target: Function | Object,
key?: string | symbol,
descriptor?: any,
) => {
SetMetadata(RESOLVER_REFERENCE_METADATA, true)(target, key, descriptor);
};
}
6 changes: 5 additions & 1 deletion lib/external/type-graphql.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Type } from '@nestjs/common';
import { GraphQLScalarType } from 'graphql';
import { GraphQLDirective, GraphQLScalarType } from 'graphql';

/**
* Some external types have to be included in order to provide types safety
Expand Down Expand Up @@ -41,9 +41,13 @@ export type BasicOptions = DecoratorTypeOptions & DescriptionOptions;
export type AdvancedOptions = BasicOptions &
DepreciationOptions &
SchemaNameOptions;

export interface BuildSchemaOptions {
dateScalarMode?: DateScalarMode;
scalarsMap?: ScalarsTypeMap[];
/** Any types that are not directly referenced or returned by resolvers */
orphanedTypes?: Function[];
directives?: GraphQLDirective[];
}
export type DateScalarMode = 'isoDate' | 'timestamp';
export interface ScalarsTypeMap {
Expand Down
69 changes: 68 additions & 1 deletion lib/graphql-definitions.factory.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { isEmpty } from '@nestjs/common/utils/shared.utils';
import { loadPackage } from '@nestjs/common/utils/load-package.util';
import { gql } from 'apollo-server-core';
import { makeExecutableSchema } from 'graphql-tools';
import * as chokidar from 'chokidar';
import { printSchema } from 'graphql';
import { GraphQLAstExplorer } from './graphql-ast.explorer';
import { GraphQLTypesLoader } from './graphql-types.loader';
import { removeTempField } from './utils/remove-temp.util';
import { removeTempField, extend } from './utils';

export class GraphQLDefinitionsFactory {
private readonly gqlAstExplorer = new GraphQLAstExplorer();
Expand All @@ -17,9 +18,11 @@ export class GraphQLDefinitionsFactory {
outputAs?: 'class' | 'interface';
watch?: boolean;
debug?: boolean;
federation?: boolean;
}) {
const isDebugEnabled = !(options && options.debug === false);
const typePathsExists = options.typePaths && !isEmpty(options.typePaths);
const isFederation = options && options.federation;
if (!typePathsExists) {
throw new Error(`"typePaths" property cannot be empty.`);
}
Expand All @@ -38,6 +41,7 @@ export class GraphQLDefinitionsFactory {
options.typePaths,
options.path,
options.outputAs,
isFederation,
isDebugEnabled,
);
});
Expand All @@ -46,11 +50,74 @@ export class GraphQLDefinitionsFactory {
options.typePaths,
options.path,
options.outputAs,
isFederation,
isDebugEnabled,
);
}

private async exploreAndEmit(
typePaths: string[],
path: string,
outputAs: 'class' | 'interface',
isFederation: boolean,
isDebugEnabled: boolean,
) {
if (isFederation) {
return this.exploreAndEmitFederation(
typePaths,
path,
outputAs,
isDebugEnabled,
);
}
return this.exploreAndEmitRegular(
typePaths,
path,
outputAs,
isDebugEnabled,
);
}

private async exploreAndEmitFederation(
typePaths: string[],
path: string,
outputAs: 'class' | 'interface',
isDebugEnabled: boolean,
) {
const typeDefs = await this.gqlTypesLoader.mergeTypesByPaths(typePaths);

const { buildFederatedSchema } = loadPackage(
'@apollo/federation',
'ApolloFederation',
);
const { printSchema } = loadPackage(
'@apollo/federation',
'ApolloFederation',
);

const schema = buildFederatedSchema([
{
typeDefs: gql`
${typeDefs}
`,
resolvers: {},
},
]);
const tsFile = await this.gqlAstExplorer.explore(
gql`
${printSchema(schema)}
`,
path,
outputAs,
);
await tsFile.save();
this.printMessage(
`[${new Date().toLocaleTimeString()}] The definitions have been updated.`,
isDebugEnabled,
);
}

private async exploreAndEmitRegular(
typePaths: string[],
path: string,
outputAs: 'class' | 'interface',
Expand Down
110 changes: 110 additions & 0 deletions lib/graphql-federation.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { Injectable } from '@nestjs/common';
import { gql } from 'apollo-server-core';
import { loadPackage } from '@nestjs/common/utils/load-package.util';
import { extend } from './utils';
import { isEmpty, forEach } from 'lodash';
import {
ScalarsExplorerService,
DelegatesExplorerService,
ResolversExplorerService,
} from './services';
import { mergeSchemas } from 'graphql-tools';
import { GqlModuleOptions } from './interfaces';
import { GraphQLSchemaBuilder } from './graphql-schema-builder';
import { GraphQLFactory } from './graphql.factory';
import { GraphQLSchema, GraphQLSchemaConfig } from 'graphql';
import { GraphQLObjectType } from 'graphql';

@Injectable()
export class GraphQLFederationFactory {
constructor(
private readonly resolversExplorerService: ResolversExplorerService,
private readonly delegatesExplorerService: DelegatesExplorerService,
private readonly scalarsExplorerService: ScalarsExplorerService,
private readonly gqlSchemaBuilder: GraphQLSchemaBuilder,
private readonly graphqlFactory: GraphQLFactory,
) {}

async mergeOptions(
options: GqlModuleOptions = {},
): Promise<GqlModuleOptions> {
const transformSchema = async s =>
options.transformSchema ? options.transformSchema(s) : s;

let schema: GraphQLSchema;
if (options.autoSchemaFile) {
// Enable support when Directive support in type-graphql goes stable
throw new Error('Code-first not supported yet');
schema = await this.generateSchema(options);
} else if (isEmpty(options.typeDefs)) {
schema = options.schema;
} else {
schema = this.buildSchemaFromTypeDefs(options);
}

return {
...options,
schema: await transformSchema(schema),
typeDefs: undefined,
};
}

private buildSchemaFromTypeDefs(options: GqlModuleOptions) {
const { buildFederatedSchema } = loadPackage(
'@apollo/federation',
'ApolloFederation',
);

return buildFederatedSchema([
{
typeDefs: gql`
${options.typeDefs}
`,
resolvers: this.getResolvers(options.resolvers),
},
]);
}

private async generateSchema(
options: GqlModuleOptions,
): Promise<GraphQLSchema> {
const { buildFederatedSchema, printSchema } = loadPackage(
'@apollo/federation',
'ApolloFederation',
);

const autoGeneratedSchema: GraphQLSchema = await this.gqlSchemaBuilder.buildFederatedSchema(
options.autoSchemaFile,
options.buildSchemaOptions,
this.resolversExplorerService.getAllCtors(),
);
const executableSchema = buildFederatedSchema({
typeDefs: gql(printSchema(autoGeneratedSchema)),
resolvers: this.getResolvers(options.resolvers),
});

const schema = options.schema
? mergeSchemas({
schemas: [options.schema, executableSchema],
})
: executableSchema;

return schema;
}

private getResolvers(optionResolvers) {
optionResolvers = Array.isArray(optionResolvers)
? optionResolvers
: [optionResolvers];
return this.extendResolvers([
this.resolversExplorerService.explore(),
this.delegatesExplorerService.explore(),
...this.scalarsExplorerService.explore(),
...optionResolvers,
]);
}

private extendResolvers(resolvers: any[]) {
return resolvers.reduce((prev, curr) => extend(prev, curr), {});
}
}
Loading

0 comments on commit 6d37373

Please sign in to comment.