Skip to content

Commit

Permalink
feat(typegraphql): update code to use typegraphql 2.0.0
Browse files Browse the repository at this point in the history
BREAKING CHANGE: @tsed/typegraphql use new @tsed/apollo package and support Apollo v4
  • Loading branch information
Romakita committed Sep 11, 2024
1 parent 5fb2433 commit e45d54b
Show file tree
Hide file tree
Showing 24 changed files with 2,146 additions and 807 deletions.
27 changes: 0 additions & 27 deletions packages/graphql/typegraphql/.nycrc

This file was deleted.

18 changes: 12 additions & 6 deletions packages/graphql/typegraphql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,30 @@
"tslib": "2.6.1"
},
"devDependencies": {
"@graphql-yoga/subscription": "5.0.0",
"@tsed/barrels": "workspace:*",
"@tsed/common": "workspace:*",
"@tsed/core": "workspace:*",
"@tsed/platform-express": "workspace:*",
"@tsed/typescript": "workspace:*",
"@types/graphql": "^14.5.0",
"class-validator": "~0.14.1",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"graphql-passport": "0.6.8",
"type-graphql": "^1.1.1",
"graphql": "16.8.2",
"graphql-passport": "^0.6.8",
"graphql-scalars": "1.23.0",
"jest": "^29.7.0",
"ts-node": "10.9.2",
"type-graphql": ">=2.0.0-rc.2",
"typescript": "4.9.5",
"vitest": "2.0.4"
},
"peerDependencies": {
"apollo-datasource": ">=3.0.0",
"apollo-datasource-rest": ">=3.0.0",
"@apollo/datasource-rest": ">=6.2.2",
"class-validator": ">=0.13.1",
"graphql": ">=15.0.0",
"type-graphql": ">=1.0.0"
"graphql": ">=16.0.0",
"graphql-scalars": ">=1.23.0",
"type-graphql": ">=2.0.0-rc.2"
}
}
11 changes: 5 additions & 6 deletions packages/graphql/typegraphql/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,16 @@ GraphQL is a query language for APIs and a runtime for fulfilling those queries
## Feature

Currently, `@tsed/typegraphql` allows you to configure a graphql server in your project.
This package use [`apollo-server-express`](https://www.apollographql.com/docs/apollo-server/api/apollo-server.html) to create GraphQL server and [`type-graphql`](https://19majkel94.github.io/type-graphql/)
This package use [`@apollo/server`](https://www.apollographql.com/) to create GraphQL server and [`type-graphql`](https://19majkel94.github.io/type-graphql/)
for the decorators.

## Installation

To begin, install the TypeGraphQL module for TS.ED:

```bash
npm install --save @tsed/typegraphql type-graphql graphql@15
npm install --save apollo-datasource apollo-datasource-rest apollo-server-express
npm install --save-dev apollo-server-testing
npm install --save @tsed/typegraphql type-graphql graphql@15 @apollo/server @apollo/datasource-rest
npm install --save-dev apollo-server-testing
```

Now, we can configure the Ts.ED server by importing `@tsed/typegraphql` in your Server:
Expand All @@ -64,7 +63,7 @@ export class Server {}

## TypeGraphQlService

TypeGraphQlService let you to retrieve an instance of ApolloServer.
TypeGraphQlService let you retrieve an instance of ApolloServer.

```typescript
import {Service, AfterRoutesInit} from "@tsed/common";
Expand All @@ -84,7 +83,7 @@ export class UsersService implements AfterRoutesInit {
}
```

For more information about ApolloServer look his documentation [here](https://www.apollographql.com/docs/apollo-server/api/apollo-server.html);
For more information about ApolloServer look his documentation [here](https://www.apollographql.com/);

## Type-graphql

Expand Down
74 changes: 41 additions & 33 deletions packages/graphql/typegraphql/src/TypeGraphQLModule.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,61 @@
import {AlterApolloSettings, ApolloSettingsWithID} from "@tsed/apollo";
import {isClass, Type} from "@tsed/core";
import {Configuration, Inject, InjectorService, Module} from "@tsed/di";
import {TypeGraphQLSettings} from "./interfaces/interfaces.js";
import {TypeGraphQLService} from "./services/TypeGraphQLService.js";
import {buildSchema} from "type-graphql";
import {RESOLVERS_PROVIDERS} from "./constants/constants.js";
import "./interfaces/interfaces.js";
import {ContextMiddleware} from "./middlewares/ContextMiddleware.js";

/**
* @ignore
*/
@Module()
export class TypeGraphQLModule {
@Inject()
protected service: TypeGraphQLService;

export class TypeGraphQLModule implements AlterApolloSettings {
@Inject()
protected injector: InjectorService;

@Configuration()
protected configuration: Configuration;

get settings(): {[key: string]: TypeGraphQLSettings} | undefined {
return this.configuration.get("graphql") || this.configuration.get("typegraphql");
}

$onRoutesInit(): Promise<any> | void {
const {settings} = this;
if (settings) {
const promises = Object.entries(settings).map(([key, options]) => {
return this.service.createServer(key, options);
});

return Promise.all(promises);
}
}

$afterListen(): Promise<any> | void {
const host = this.configuration.getBestHost();
async $alterApolloSettings(settings: ApolloSettingsWithID): Promise<ApolloSettingsWithID> {
const {resolvers: initialResolvers = [], buildSchemaOptions = {}, ...serverOptions} = settings;

const displayLog = (key: string, path: string) => {
const url = typeof host.port === "number" ? `${host.protocol}://${host.address}:${host.port}` : "";
const resolvers: any = this.getResolvers(settings.id, [...(initialResolvers as any[]), ...(buildSchemaOptions.resolvers || [])]);

this.injector.logger.info(`[${key}] GraphQL server is available on ${url}/${path.replace(/^\//, "")}`);
};
serverOptions.schema = await buildSchema({
container: this.injector as never,
...buildSchemaOptions,
resolvers,
globalMiddlewares: [ContextMiddleware, ...(buildSchemaOptions.globalMiddlewares || [])]
});

const {settings} = this;
return serverOptions;
}

if (settings) {
Object.entries(settings).map(([key, options]) => {
const {path} = options;
protected getResolvers(id: string, resolvers: Type<any>[]): Type<any>[] {
const globalResolvers = this.injector
.getProviders(RESOLVERS_PROVIDERS)
.filter((provider) => {
const opts = provider.store.get("graphql");

displayLog(key, path);
return !opts?.id || opts?.id === id;
})
.map((provider) => {
return provider.useClass;
});
}

return resolvers
.map((resolver) => {
if (!(this.injector.has(resolver) || !isClass(resolver))) {
this.injector
.addProvider(resolver, {
useClass: resolver
})
.invoke(resolver);
}

return resolver;
})
.concat(globalResolvers);
}
}
23 changes: 4 additions & 19 deletions packages/graphql/typegraphql/src/decorators/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import {StoreSet, useDecorators} from "@tsed/core";
import {Injectable} from "@tsed/di";
import {ClassType, Resolver} from "type-graphql";
import {AbstractClassOptions, ClassTypeResolver} from "type-graphql/dist/decorators/types";
import {RESOLVERS_PROVIDERS} from "../constants/constants.js";

export interface ResolverControllerOptions extends AbstractClassOptions {
export interface ResolverControllerOptions {
id?: string;
}

export function ResolverController(path?: string): ClassDecorator;
export function ResolverController(options: ResolverControllerOptions): ClassDecorator;
export function ResolverController(typeFunc: ClassTypeResolver, options?: ResolverControllerOptions): ClassDecorator;
export function ResolverController(): ClassDecorator;
export function ResolverController(path: string): ClassDecorator;
export function ResolverController(typeFunc: (of?: void) => ClassType | Function, options?: ResolverControllerOptions): ClassDecorator;
export function ResolverController(objectType: ClassType, options?: ResolverControllerOptions): ClassDecorator;
export function ResolverController(...args: any[]): ClassDecorator {
let id = undefined;
Expand Down Expand Up @@ -38,17 +37,3 @@ export function ResolverController(...args: any[]): ClassDecorator {
})
);
}

/**
* @deprecated Use ResolverController instead
*/
export function ResolverService(): ClassDecorator;
export function ResolverService(options: AbstractClassOptions): ClassDecorator;
export function ResolverService(typeFunc: ClassTypeResolver, options?: AbstractClassOptions): ClassDecorator;
export function ResolverService(objectType: ClassType, options?: AbstractClassOptions): ClassDecorator;
/**
* @deprecated Use ResolverController instead
*/
export function ResolverService(...args: any[]): ClassDecorator {
return (ResolverController as any)(...args);
}
1 change: 0 additions & 1 deletion packages/graphql/typegraphql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ export * from "./exports.js";
export * from "./interfaces/interfaces.js";
export * from "./interfaces/TypeGraphQLSettings.js";
export * from "./middlewares/ContextMiddleware.js";
export * from "./services/TypeGraphQLService.js";
export * from "./TypeGraphQLModule.js";
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
import {ApolloConfig, ApolloSettings} from "@tsed/apollo";
import {BuildSchemaOptions} from "type-graphql";

export interface TypeGraphQLSettings extends ApolloSettings {
// TypeGraphQL options
buildSchemaOptions?: Partial<BuildSchemaOptions>;
// apollo-server-express options
// See options descriptions on https://www.apollographql.com/docs/apollo-server/api/apollo-server.html
serverConfig?: ApolloConfig;
}
19 changes: 14 additions & 5 deletions packages/graphql/typegraphql/src/interfaces/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import {TypeGraphQLSettings} from "./TypeGraphQLSettings.js";
import {BuildSchemaOptions} from "type-graphql";
import type {ApolloSettings as AS} from "@tsed/apollo";

declare global {
namespace TsED {
interface ApolloSettings {
buildSchemaOptions?: Partial<BuildSchemaOptions>;
}

interface Configuration {
graphql: {[key: string]: TypeGraphQLSettings};
typegraphql: {[key: string]: TypeGraphQLSettings};
/**
* @deprecated Use apollo instead
*/
graphql: {[key: string]: AS};
/**
* @deprecated Use apollo instead
*/
typegraphql: {[key: string]: AS};
}
}
}

export * from "./TypeGraphQLSettings.js";

This file was deleted.

Loading

0 comments on commit e45d54b

Please sign in to comment.