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 12, 2024
1 parent ed3a9f2 commit 96957eb
Show file tree
Hide file tree
Showing 9 changed files with 584 additions and 394 deletions.
33 changes: 17 additions & 16 deletions docs/tutorials/graphql-typegraphql.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ To begin, install the `@tsed/typegraphql` package:
<Tab label="Express.js">

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

</Tab>
<Tab label="Koa.js">

```bash
npm install --save @tsed/apollo graphql type-graphql @apollo/server @as-integration/koa @apollo/datasource-rest
npm install --save @tsed/apollo graphql type-graphql @apollo/server @as-integration/koa @apollo/datasource-rest graphql-scalars
npm install --save-dev apollo-server-testing
```

Expand All @@ -37,8 +37,8 @@ npm install --save-dev apollo-server-testing

Now, we can configure the Ts.ED server by importing `@tsed/typegraphql` in your Server:

<Tabs class="-code">
<Tab label="Configuration" icon="bx-code-alt">
[//]: # '<Tabs class="-code">'
[//]: # ' <Tab label="Configuration" icon="bx-code-alt">'

```ts
import {Configuration} from "@tsed/di";
Expand Down Expand Up @@ -70,18 +70,19 @@ import "./resolvers/index"; // barrel file with all resolvers
export class Server {}
```

</Tab>
<Tab label="CodeSandbox" icon="bxl-codepen">

<iframe src="https://codesandbox.io/embed/tsed-graphql-pgvfz?fontsize=14&hidenavigation=1&theme=dark"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
title="TsED Graphql"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi;
payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>

</Tab>
</Tabs>
[//]: #
[//]: # " </Tab>"
[//]: # ' <Tab label="CodeSandbox" icon="bxl-codepen">'
[//]: #
[//]: # '<iframe src="https://codesandbox.io/embed/tsed-graphql-pgvfz?fontsize=14&hidenavigation=1&theme=dark"'
[//]: # 'style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"'
[//]: # 'title="TsED Graphql"'
[//]: # 'allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi;'
[//]: # 'payment; usb; vr; xr-spatial-tracking"'
[//]: # 'sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>'
[//]: #
[//]: # " </Tab>"
[//]: # "</Tabs>"

## Types

Expand Down
36 changes: 33 additions & 3 deletions packages/di/src/node/utils/asyncHookContext.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {DITest} from "../services/DITest.js";
import {runInContext, setContext, getContext} from "./asyncHookContext.js";
import {getContext, runInContext, setContext, useContext} from "./asyncHookContext.js";

describe("asyncHookContext", () => {
beforeEach(() => DITest.create());
Expand All @@ -9,7 +9,7 @@ describe("asyncHookContext", () => {
const res = {type: "res"};

function next(res: any, req: any) {
return Promise.resolve(getContext());
return Promise.resolve(useContext());
}

function nextContext(res: any, req: any, next: any) {
Expand Down Expand Up @@ -45,7 +45,7 @@ describe("asyncHookContext", () => {
const res = {type: "res"};

function next(res: any, req: any) {
return Promise.resolve(getContext());
return Promise.resolve(useContext());
}

function nextContext(res: any, req: any, next: any) {
Expand Down Expand Up @@ -74,6 +74,36 @@ describe("asyncHookContext", () => {
}
});
});
it("should initiate the async hook context - promise (initialValue)", async () => {
const req = {type: "req"};
const res = {type: "res"};

function next(res: any, req: any) {
return Promise.resolve(useContext({id: "id2"}));

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-graphql (20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-integration (ubuntu-latest, 20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-core (20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-integration (ubuntu-latest, 22.x)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-integration (macos-latest, 22.x)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-orm (20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-platform (20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-security (20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-specs (20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.

Check failure on line 82 in packages/di/src/node/utils/asyncHookContext.spec.ts

View workflow job for this annotation

GitHub Actions / test-third-parties (20.12.2)

Argument of type '{ id: string; }' is not assignable to parameter of type 'DIContext'.
}

function nextContext(res: any, req: any, next: any) {
const $ctx: any = {
id: "id",
req,
res
};

setContext($ctx);

return next();
}

function app(req: any, res: any) {
return runInContext(undefined, () => nextContext(req, res, () => next(req, res)), DITest.injector);
}

const result = await app(req, res);

expect(result).toEqual({
id: "id2"
});
});
it("should initiate the async hook context - promise + setTimeout", async () => {
const req = {type: "req"};
const res = {type: "res"};
Expand Down
6 changes: 4 additions & 2 deletions packages/di/src/node/utils/asyncHookContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export function useContextRef() {
return getAsyncStore().getStore();
}

export function getContext<Context = DIContext>(): Context | undefined {
return useContextRef()?.current as any;
export function useContext<Context = DIContext>(initialValue?: DIContext): Context | undefined {
return initialValue || (useContextRef()?.current as any);
}

export const getContext = useContext;

export async function runInContext<Result = unknown>(
ctx: DIContext | undefined,
cb: (...args: unknown[]) => Result,
Expand Down
7 changes: 4 additions & 3 deletions packages/graphql/apollo/src/services/ApolloService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {ApolloServerPluginLandingPageDisabled} from "@apollo/server/plugin/disab
import {ApolloServerPluginDrainHttpServer} from "@apollo/server/plugin/drainHttpServer";
import {ApolloServerPluginLandingPageLocalDefault} from "@apollo/server/plugin/landingPage/default";
import type {IExecutableSchemaDefinition} from "@graphql-tools/schema";
import {getContext, InjectorService, LocalsContainer, PlatformApplication, PlatformContext, Provider} from "@tsed/common";
import {useContext, InjectorService, LocalsContainer, PlatformApplication, PlatformContext, Provider} from "@tsed/common";
import {Constant, Inject, Service} from "@tsed/di";
import {Logger} from "@tsed/logger";
import type {GraphQLSchema} from "graphql";
Expand Down Expand Up @@ -176,15 +176,16 @@ export class ApolloService {
}, new Map<string, Provider>());

return async () => {
const $ctx = getContext() as PlatformContext;
const $ctx = useContext<PlatformContext>();
const context: ApolloContext = {
dataSources: {
...(settings.dataSources?.() || {})
}
};

const alteredContext = await this.injector.alterAsync("$alterApolloContext", context, $ctx);
$ctx.set(APOLLO_CONTEXT, alteredContext);

$ctx!.set(APOLLO_CONTEXT, alteredContext);

const locals = new LocalsContainer();
locals.set(APOLLO_CONTEXT, alteredContext);
Expand Down
1 change: 0 additions & 1 deletion packages/graphql/typegraphql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"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",
Expand Down
57 changes: 29 additions & 28 deletions packages/graphql/typegraphql/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,51 +40,52 @@ for the decorators.

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

Express.js:

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

Koa.js

```bash
npm install --save @tsed/typegraphql type-graphql graphql@15 @apollo/server @apollo/datasource-rest
npm install --save @tsed/apollo graphql type-graphql @apollo/server @as-integration/koa @apollo/datasource-rest graphql-scalars
npm install --save-dev apollo-server-testing
```

Now, we can configure the Ts.ED server by importing `@tsed/typegraphql` in your Server:

```typescript
import {Configuration} from "@tsed/common";
import {Configuration} from "@tsed/di";
import "@tsed/platform-express";
import "@tsed/typegraphql";
import "./resolvers/index"; // barrel file with all resolvers

@Configuration({
graphql: {
apollo: {
server1: {
resolvers: []
}
}
})
export class Server {}
```

## TypeGraphQlService

TypeGraphQlService let you retrieve an instance of ApolloServer.

```typescript
import {Service, AfterRoutesInit} from "@tsed/common";
import {TypeGraphQLService} from "@tsed/typegraphql";
import {ApolloServer} from "apollo-server-express";
// GraphQL server configuration
// See options descriptions on https://www.apollographql.com/docs/apollo-server/api/apollo-server.html
path: "/",
playground: true // enable playground GraphQL IDE. Set false to use Apollo Studio

@Service()
export class UsersService implements AfterRoutesInit {
private server: ApolloServer;
// resolvers?: (Function | string)[];
// dataSources?: Function;
// server?: (config: Config) => ApolloServer;

@Inject()
typeGraphQLService: TypeGraphQLService;
// plugins: []
// middlewareOptions?: ServerRegistration;

$afterRoutesInit() {
this.server = this.typeGraphQLService.get("server1");
// type-graphql
// See options descriptions on https://19majkel94.github.io/type-graphql/
// buildSchemaOptions?: Partial<BuildSchemaOptions>;
}
}
}
})
export class Server {}
```

For more information about ApolloServer look his documentation [here](https://www.apollographql.com/);

## Type-graphql

### Types
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {getContext, PlatformContext, runInContext} from "@tsed/common";
import {type DIContext, runInContext, useContext} from "@tsed/di";
import {MiddlewareFn} from "type-graphql";

export const ContextMiddleware: MiddlewareFn<{req: {$ctx: PlatformContext}}> = (_, next) => {
return runInContext(getContext(), next);
export const ContextMiddleware: MiddlewareFn<{req: {$ctx: DIContext}}> = (action, next) => {
const $ctx = useContext(action.context?.req?.$ctx);
return runInContext($ctx, next);
};
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,7 @@ describe("TypeGraphQL", () => {
errors: [
{
extensions: {
code: "INTERNAL_SERVER_ERROR",
exception: {
headers: {},
// message: "Wrong credentials",
name: "UNAUTHORIZED",
status: 401,
type: "HTTP_EXCEPTION"
}
code: "INTERNAL_SERVER_ERROR"
},
locations: [
{
Expand Down
Loading

0 comments on commit 96957eb

Please sign in to comment.