Cache yoga conditional schema (#5170)
In this PR I'm introducing a new patch on @graphql-yoga/nestjs package. This patch overrides a previous patch that was made to compute the conditionnal schema on each request, Here we use a cache map to compute only once per schema workspace cache version. This allows us to have sub 100ms query time.
This commit is contained in:
@ -14,7 +14,7 @@
|
|||||||
"database:migrate:prod": "npx -y typeorm migration:run -d dist/src/database/typeorm/metadata/metadata.datasource && npx -y typeorm migration:run -d dist/src/database/typeorm/core/core.datasource"
|
"database:migrate:prod": "npx -y typeorm migration:run -d dist/src/database/typeorm/metadata/metadata.datasource && npx -y typeorm migration:run -d dist/src/database/typeorm/core/core.datasource"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch",
|
"@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch",
|
||||||
"@nestjs/cache-manager": "^2.2.1",
|
"@nestjs/cache-manager": "^2.2.1",
|
||||||
"@nestjs/devtools-integration": "^0.1.6",
|
"@nestjs/devtools-integration": "^0.1.6",
|
||||||
"@nestjs/graphql": "patch:@nestjs/graphql@12.1.1#./patches/@nestjs+graphql+12.1.1.patch",
|
"@nestjs/graphql": "patch:@nestjs/graphql@12.1.1#./patches/@nestjs+graphql+12.1.1.patch",
|
||||||
|
|||||||
@ -1,16 +1,23 @@
|
|||||||
diff --git a/dist/cjs/index.js b/dist/cjs/index.js
|
diff --git a/dist/cjs/index.js b/dist/cjs/index.js
|
||||||
index 1684394..8a92c3c 100644
|
index 16843949d8589a299d8195b0a349ac4dac0bacbf..21e7fe2bbcba36b04a274be9d2219fd38790b508 100644
|
||||||
--- a/dist/cjs/index.js
|
--- a/dist/cjs/index.js
|
||||||
+++ b/dist/cjs/index.js
|
+++ b/dist/cjs/index.js
|
||||||
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
@@ -3,10 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.YogaDriver = exports.AbstractYogaDriver = void 0;
|
||||||
|
const tslib_1 = require("tslib");
|
||||||
const graphql_1 = require("graphql");
|
const graphql_1 = require("graphql");
|
||||||
|
+const schema_1 = require("@graphql-tools/schema");
|
||||||
const graphql_yoga_1 = require("graphql-yoga");
|
const graphql_yoga_1 = require("graphql-yoga");
|
||||||
const common_1 = require("@nestjs/common");
|
const common_1 = require("@nestjs/common");
|
||||||
+const schema_1 = require("@graphql-tools/schema");
|
|
||||||
const graphql_2 = require("@nestjs/graphql");
|
const graphql_2 = require("@nestjs/graphql");
|
||||||
class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||||
|
+
|
||||||
|
+ schemaCache = new Map();
|
||||||
|
+
|
||||||
async start(options) {
|
async start(options) {
|
||||||
@@ -27,7 +28,7 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
const platformName = this.httpAdapterHost.httpAdapter.getType();
|
||||||
|
options = {
|
||||||
|
@@ -27,7 +31,7 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||||
async stop() {
|
async stop() {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
@ -19,29 +26,47 @@ index 1684394..8a92c3c 100644
|
|||||||
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
||||||
preStartHook?.(app);
|
preStartHook?.(app);
|
||||||
// nest's logger doesnt have the info method
|
// nest's logger doesnt have the info method
|
||||||
@@ -42,6 +43,21 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
@@ -42,6 +46,39 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||||
}
|
}
|
||||||
const yoga = (0, graphql_yoga_1.createYoga)({
|
const yoga = (0, graphql_yoga_1.createYoga)({
|
||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
|
+ const workspaceId = request.req.workspace.id
|
||||||
|
+ const workspaceCacheVersion = request.req.cacheVersion
|
||||||
|
+ const url = request.req.baseUrl
|
||||||
|
+
|
||||||
|
+ const cacheKey = `${workspaceId}-${workspaceCacheVersion}-${url}`
|
||||||
|
+
|
||||||
|
+ if(this.schemaCache.has(cacheKey)) {
|
||||||
|
+ return this.schemaCache.get(cacheKey)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ const schemas = [];
|
+ const schemas = [];
|
||||||
|
+
|
||||||
+ if (options.schema) {
|
+ if (options.schema) {
|
||||||
+ schemas.push(options.schema);
|
+ schemas.push(options.schema);
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
+ if (conditionalSchema) {
|
+ if (conditionalSchema) {
|
||||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||||
+ if (conditionalSchemaResult) {
|
+ if (conditionalSchemaResult) {
|
||||||
+ schemas.push(conditionalSchemaResult);
|
+ schemas.push(conditionalSchemaResult);
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ return (0, schema_1.mergeSchemas)({
|
+
|
||||||
|
+
|
||||||
|
+ const mergedSchemas = (0, schema_1.mergeSchemas)({
|
||||||
+ schemas,
|
+ schemas,
|
||||||
+ });
|
+ });
|
||||||
|
+
|
||||||
|
+ this.schemaCache.set(cacheKey, mergedSchemas)
|
||||||
|
+
|
||||||
|
+ return mergedSchemas;
|
||||||
+ },
|
+ },
|
||||||
graphqlEndpoint: options.path,
|
graphqlEndpoint: options.path,
|
||||||
// disable logging by default
|
// disable logging by default
|
||||||
// however, if `true` use nest logger
|
// however, if `true` use nest logger
|
||||||
@@ -54,11 +70,26 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
@@ -54,11 +91,44 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
||||||
this.yoga = yoga;
|
this.yoga = yoga;
|
||||||
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
||||||
}
|
}
|
||||||
@ -52,36 +77,59 @@ index 1684394..8a92c3c 100644
|
|||||||
const yoga = (0, graphql_yoga_1.createYoga)({
|
const yoga = (0, graphql_yoga_1.createYoga)({
|
||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
|
+ const workspaceId = request.req.workspace.id
|
||||||
|
+ const workspaceCacheVersion = request.req.cacheVersion
|
||||||
|
+ const url = request.req.baseUrl
|
||||||
|
+
|
||||||
|
+ const cacheKey = `${workspaceId}-${workspaceCacheVersion}-${url}`
|
||||||
|
+
|
||||||
|
+ if(this.schemaCache.has(cacheKey)) {
|
||||||
|
+ return this.schemaCache.get(cacheKey)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ const schemas = [];
|
+ const schemas = [];
|
||||||
|
+
|
||||||
+ if (options.schema) {
|
+ if (options.schema) {
|
||||||
+ schemas.push(options.schema);
|
+ schemas.push(options.schema);
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
+ if (conditionalSchema) {
|
+ if (conditionalSchema) {
|
||||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||||
+ if (conditionalSchemaResult) {
|
+ if (conditionalSchemaResult) {
|
||||||
+ schemas.push(conditionalSchemaResult);
|
+ schemas.push(conditionalSchemaResult);
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ return (0, schema_1.mergeSchemas)({
|
+
|
||||||
|
+
|
||||||
|
+ const mergedSchemas = (0, schema_1.mergeSchemas)({
|
||||||
+ schemas,
|
+ schemas,
|
||||||
+ });
|
+ });
|
||||||
|
+
|
||||||
|
+ this.schemaCache.set(cacheKey, mergedSchemas)
|
||||||
|
+
|
||||||
|
+ return mergedSchemas;
|
||||||
+ },
|
+ },
|
||||||
graphqlEndpoint: options.path,
|
graphqlEndpoint: options.path,
|
||||||
// disable logging by default
|
// disable logging by default
|
||||||
// however, if `true` use fastify logger
|
// however, if `true` use fastify logger
|
||||||
diff --git a/dist/esm/index.js b/dist/esm/index.js
|
diff --git a/dist/esm/index.js b/dist/esm/index.js
|
||||||
index 7068c51..8ba5d2a 100644
|
index 7068c519320b379917c46763cd280b1cdd3e48f0..418e1030373fc1e0fb85a932ac8da9b39f580570 100644
|
||||||
--- a/dist/esm/index.js
|
--- a/dist/esm/index.js
|
||||||
+++ b/dist/esm/index.js
|
+++ b/dist/esm/index.js
|
||||||
@@ -2,6 +2,7 @@ import { __decorate } from "tslib";
|
@@ -2,8 +2,12 @@ import { __decorate } from "tslib";
|
||||||
import { printSchema } from 'graphql';
|
import { printSchema } from 'graphql';
|
||||||
import { createYoga, filter, pipe } from 'graphql-yoga';
|
import { createYoga, filter, pipe } from 'graphql-yoga';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
+import { mergeSchemas } from '@graphql-tools/schema';
|
+import { mergeSchemas } from '@graphql-tools/schema';
|
||||||
import { AbstractGraphQLDriver, GqlSubscriptionService, } from '@nestjs/graphql';
|
import { AbstractGraphQLDriver, GqlSubscriptionService, } from '@nestjs/graphql';
|
||||||
export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||||
|
+
|
||||||
|
+ schemaCache = new Map();
|
||||||
|
+
|
||||||
async start(options) {
|
async start(options) {
|
||||||
@@ -24,7 +25,7 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
const platformName = this.httpAdapterHost.httpAdapter.getType();
|
||||||
|
options = {
|
||||||
|
@@ -24,7 +28,7 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||||
async stop() {
|
async stop() {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
@ -90,29 +138,47 @@ index 7068c51..8ba5d2a 100644
|
|||||||
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
||||||
preStartHook?.(app);
|
preStartHook?.(app);
|
||||||
// nest's logger doesnt have the info method
|
// nest's logger doesnt have the info method
|
||||||
@@ -39,6 +40,21 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
@@ -39,6 +43,39 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||||
}
|
}
|
||||||
const yoga = createYoga({
|
const yoga = createYoga({
|
||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
|
+ const workspaceId = request.req.workspace.id
|
||||||
|
+ const workspaceCacheVersion = request.req.cacheVersion
|
||||||
|
+ const url = request.req.baseUrl
|
||||||
|
+
|
||||||
|
+ const cacheKey = `${workspaceId}-${workspaceCacheVersion}-${url}`
|
||||||
|
+
|
||||||
|
+ if (this.schemaCache.has(cacheKey)) {
|
||||||
|
+ return this.schemaCache.get(cacheKey)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ const schemas = [];
|
+ const schemas = [];
|
||||||
|
+
|
||||||
+ if (options.schema) {
|
+ if (options.schema) {
|
||||||
+ schemas.push(options.schema);
|
+ schemas.push(options.schema);
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
+ if (conditionalSchema) {
|
+ if (conditionalSchema) {
|
||||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||||
+ if (conditionalSchemaResult) {
|
+
|
||||||
+ schemas.push(conditionalSchemaResult);
|
+ if (conditionalSchemaResult) {
|
||||||
+ }
|
+ schemas.push(conditionalSchemaResult);
|
||||||
+ }
|
+ }
|
||||||
+ return mergeSchemas({
|
+ }
|
||||||
+ schemas,
|
+
|
||||||
|
+ const mergedSchemas = mergeSchemas({
|
||||||
|
+ schemas,
|
||||||
+ });
|
+ });
|
||||||
|
+
|
||||||
|
+ this.schemaCache.set(cacheKey, mergedSchemas)
|
||||||
|
+
|
||||||
|
+ return mergedSchemas;
|
||||||
+ },
|
+ },
|
||||||
graphqlEndpoint: options.path,
|
graphqlEndpoint: options.path,
|
||||||
// disable logging by default
|
// disable logging by default
|
||||||
// however, if `true` use nest logger
|
// however, if `true` use nest logger
|
||||||
@@ -51,11 +67,26 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
@@ -51,11 +88,44 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
||||||
this.yoga = yoga;
|
this.yoga = yoga;
|
||||||
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
||||||
}
|
}
|
||||||
@ -123,25 +189,43 @@ index 7068c51..8ba5d2a 100644
|
|||||||
const yoga = createYoga({
|
const yoga = createYoga({
|
||||||
...options,
|
...options,
|
||||||
+ schema: async (request) => {
|
+ schema: async (request) => {
|
||||||
|
+ const workspaceId = request.req.workspace.id
|
||||||
|
+ const workspaceCacheVersion = request.req.cacheVersion
|
||||||
|
+ const url = request.req.baseUrl
|
||||||
|
+
|
||||||
|
+ const cacheKey = `${workspaceId}-${workspaceCacheVersion}-${url}`
|
||||||
|
+
|
||||||
|
+ if (this.schemaCache.has(cacheKey)) {
|
||||||
|
+ return this.schemaCache.get(cacheKey)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ const schemas = [];
|
+ const schemas = [];
|
||||||
|
+
|
||||||
+ if (options.schema) {
|
+ if (options.schema) {
|
||||||
+ schemas.push(options.schema);
|
+ schemas.push(options.schema);
|
||||||
+ }
|
+ }
|
||||||
|
+
|
||||||
+ if (conditionalSchema) {
|
+ if (conditionalSchema) {
|
||||||
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
+ const conditionalSchemaResult = typeof conditionalSchema === 'function' ? await conditionalSchema(request) : await conditionalSchema;
|
||||||
+ if (conditionalSchemaResult) {
|
+
|
||||||
+ schemas.push(conditionalSchemaResult);
|
+ if (conditionalSchemaResult) {
|
||||||
+ }
|
+ schemas.push(conditionalSchemaResult);
|
||||||
+ }
|
+ }
|
||||||
+ return mergeSchemas({
|
+ }
|
||||||
+ schemas,
|
+
|
||||||
|
+ const mergedSchemas = mergeSchemas({
|
||||||
|
+ schemas,
|
||||||
+ });
|
+ });
|
||||||
|
+
|
||||||
|
+ this.schemaCache.set(cacheKey, mergedSchemas)
|
||||||
|
+
|
||||||
|
+ return mergedSchemas;
|
||||||
+ },
|
+ },
|
||||||
graphqlEndpoint: options.path,
|
graphqlEndpoint: options.path,
|
||||||
// disable logging by default
|
// disable logging by default
|
||||||
// however, if `true` use fastify logger
|
// however, if `true` use fastify logger
|
||||||
diff --git a/dist/typings/index.d.cts b/dist/typings/index.d.cts
|
diff --git a/dist/typings/index.d.cts b/dist/typings/index.d.cts
|
||||||
index 2c6a965..fd86dac 100644
|
index 2c6a9656193392680121487c7147db459d6b69ab..2f2b59f0e311f0526a7cfdad97372229301aabd7 100644
|
||||||
--- a/dist/typings/index.d.cts
|
--- a/dist/typings/index.d.cts
|
||||||
+++ b/dist/typings/index.d.cts
|
+++ b/dist/typings/index.d.cts
|
||||||
@@ -1,7 +1,8 @@
|
@@ -1,7 +1,8 @@
|
||||||
@ -154,18 +238,19 @@ index 2c6a965..fd86dac 100644
|
|||||||
export type YogaDriverPlatform = 'express' | 'fastify';
|
export type YogaDriverPlatform = 'express' | 'fastify';
|
||||||
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platform extends 'fastify' ? {
|
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platform extends 'fastify' ? {
|
||||||
req: FastifyRequest;
|
req: FastifyRequest;
|
||||||
@@ -10,7 +11,9 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platf
|
@@ -10,7 +11,10 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platf
|
||||||
req: ExpressRequest;
|
req: ExpressRequest;
|
||||||
res: ExpressResponse;
|
res: ExpressResponse;
|
||||||
};
|
};
|
||||||
-export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'>;
|
-export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'>;
|
||||||
|
+
|
||||||
+export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'> & {
|
+export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'> & {
|
||||||
+ conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>> | undefined;
|
+ conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>> | undefined;
|
||||||
+};
|
+};
|
||||||
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<YogaDriverServerContext<Platform>, never>;
|
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<YogaDriverServerContext<Platform>, never>;
|
||||||
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & {
|
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & {
|
||||||
/**
|
/**
|
||||||
@@ -26,10 +29,10 @@ export declare abstract class AbstractYogaDriver<Platform extends YogaDriverPlat
|
@@ -26,10 +30,10 @@ export declare abstract class AbstractYogaDriver<Platform extends YogaDriverPlat
|
||||||
protected yoga: YogaDriverServerInstance<Platform>;
|
protected yoga: YogaDriverServerInstance<Platform>;
|
||||||
start(options: YogaDriverConfig<Platform>): Promise<void>;
|
start(options: YogaDriverConfig<Platform>): Promise<void>;
|
||||||
stop(): Promise<void>;
|
stop(): Promise<void>;
|
||||||
@ -179,7 +264,7 @@ index 2c6a965..fd86dac 100644
|
|||||||
}): void;
|
}): void;
|
||||||
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
||||||
diff --git a/dist/typings/index.d.ts b/dist/typings/index.d.ts
|
diff --git a/dist/typings/index.d.ts b/dist/typings/index.d.ts
|
||||||
index 2c6a965..fd86dac 100644
|
index 2c6a9656193392680121487c7147db459d6b69ab..fd86daccf3e5a93ff44b568c9793c16d761f4f53 100644
|
||||||
--- a/dist/typings/index.d.ts
|
--- a/dist/typings/index.d.ts
|
||||||
+++ b/dist/typings/index.d.ts
|
+++ b/dist/typings/index.d.ts
|
||||||
@@ -1,7 +1,8 @@
|
@@ -1,7 +1,8 @@
|
||||||
@ -217,7 +302,7 @@ index 2c6a965..fd86dac 100644
|
|||||||
}): void;
|
}): void;
|
||||||
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
||||||
diff --git a/src/index.ts b/src/index.ts
|
diff --git a/src/index.ts b/src/index.ts
|
||||||
index ce142f6..cda4117 100644
|
index ce142f61ede52499485b19d8af057f4cb828d0f7..5888d31cae1b7aca57ed0819209812ac941edabb 100644
|
||||||
--- a/src/index.ts
|
--- a/src/index.ts
|
||||||
+++ b/src/index.ts
|
+++ b/src/index.ts
|
||||||
@@ -1,9 +1,10 @@
|
@@ -1,9 +1,10 @@
|
||||||
@ -225,7 +310,7 @@ index ce142f6..cda4117 100644
|
|||||||
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||||
-import { printSchema } from 'graphql';
|
-import { printSchema } from 'graphql';
|
||||||
-import { createYoga, filter, pipe, YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
-import { createYoga, filter, pipe, YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
||||||
+import { GraphQLSchema, printSchema } from 'graphql';
|
+import { printSchema, GraphQLSchema } from 'graphql';
|
||||||
+import { createYoga, filter, pipe, YogaServerInstance, YogaServerOptions, GraphQLSchemaWithContext, PromiseOrValue, YogaInitialContext } from 'graphql-yoga';
|
+import { createYoga, filter, pipe, YogaServerInstance, YogaServerOptions, GraphQLSchemaWithContext, PromiseOrValue, YogaInitialContext } from 'graphql-yoga';
|
||||||
import type { ExecutionParams } from 'subscriptions-transport-ws';
|
import type { ExecutionParams } from 'subscriptions-transport-ws';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
@ -233,20 +318,37 @@ index ce142f6..cda4117 100644
|
|||||||
import {
|
import {
|
||||||
AbstractGraphQLDriver,
|
AbstractGraphQLDriver,
|
||||||
GqlModuleOptions,
|
GqlModuleOptions,
|
||||||
@@ -11,6 +12,12 @@ import {
|
@@ -11,23 +12,31 @@ import {
|
||||||
SubscriptionConfig,
|
SubscriptionConfig,
|
||||||
} from '@nestjs/graphql';
|
} from '@nestjs/graphql';
|
||||||
|
|
||||||
+export type YogaSchemaDefinition<TContext> =
|
+export type YogaSchemaDefinition<TContext> =
|
||||||
+ | PromiseOrValue<GraphQLSchemaWithContext<TContext>>
|
+ | PromiseOrValue<GraphQLSchemaWithContext<TContext>>
|
||||||
+ | ((
|
+ | ((
|
||||||
+ context: TContext & YogaInitialContext,
|
+ context: TContext & YogaInitialContext,
|
||||||
+ ) => PromiseOrValue<GraphQLSchemaWithContext<TContext>>);
|
+ ) => PromiseOrValue<GraphQLSchemaWithContext<TContext>>);
|
||||||
+
|
+
|
||||||
export type YogaDriverPlatform = 'express' | 'fastify';
|
export type YogaDriverPlatform = 'express' | 'fastify';
|
||||||
|
|
||||||
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> =
|
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> =
|
||||||
@@ -27,7 +34,9 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> =
|
Platform extends 'fastify'
|
||||||
|
- ? {
|
||||||
|
- req: FastifyRequest;
|
||||||
|
- reply: FastifyReply;
|
||||||
|
- }
|
||||||
|
- : {
|
||||||
|
- req: ExpressRequest;
|
||||||
|
- res: ExpressResponse;
|
||||||
|
- };
|
||||||
|
+ ? {
|
||||||
|
+ req: FastifyRequest;
|
||||||
|
+ reply: FastifyReply;
|
||||||
|
+ }
|
||||||
|
+ : {
|
||||||
|
+ req: ExpressRequest;
|
||||||
|
+ res: ExpressResponse;
|
||||||
|
+ };
|
||||||
|
|
||||||
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<
|
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<
|
||||||
YogaServerOptions<YogaDriverServerContext<Platform>, never>,
|
YogaServerOptions<YogaDriverServerContext<Platform>, never>,
|
||||||
'context' | 'schema'
|
'context' | 'schema'
|
||||||
@ -257,20 +359,39 @@ index ce142f6..cda4117 100644
|
|||||||
|
|
||||||
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<
|
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<
|
||||||
YogaDriverServerContext<Platform>,
|
YogaDriverServerContext<Platform>,
|
||||||
@@ -78,7 +87,7 @@ export abstract class AbstractYogaDriver<
|
@@ -53,6 +62,8 @@ export type YogaDriverSubscriptionConfig = {
|
||||||
|
export abstract class AbstractYogaDriver<
|
||||||
|
Platform extends YogaDriverPlatform,
|
||||||
|
> extends AbstractGraphQLDriver<YogaDriverConfig<Platform>> {
|
||||||
|
+ schemaCache = new Map();
|
||||||
|
+
|
||||||
|
protected yoga!: YogaDriverServerInstance<Platform>;
|
||||||
|
|
||||||
|
public async start(options: YogaDriverConfig<Platform>) {
|
||||||
|
@@ -78,7 +89,7 @@ export abstract class AbstractYogaDriver<
|
||||||
}
|
}
|
||||||
|
|
||||||
protected registerExpress(
|
protected registerExpress(
|
||||||
- options: YogaDriverConfig<'express'>,
|
- options: YogaDriverConfig<'express'>,
|
||||||
+ { conditionalSchema, ...options}: YogaDriverConfig<'express'>,
|
+ { conditionalSchema, ...options }: YogaDriverConfig<'express'>,
|
||||||
{ preStartHook }: { preStartHook?: (app: Express) => void } = {},
|
{ preStartHook }: { preStartHook?: (app: Express) => void } = {},
|
||||||
) {
|
) {
|
||||||
const app: Express = this.httpAdapterHost.httpAdapter.getInstance();
|
const app: Express = this.httpAdapterHost.httpAdapter.getInstance();
|
||||||
@@ -98,6 +107,25 @@ export abstract class AbstractYogaDriver<
|
@@ -98,6 +109,39 @@ export abstract class AbstractYogaDriver<
|
||||||
|
|
||||||
const yoga = createYoga<YogaDriverServerContext<'express'>>({
|
const yoga = createYoga<YogaDriverServerContext<'express'>>({
|
||||||
...options,
|
...options,
|
||||||
+ schema: async request => {
|
+ schema: async request => {
|
||||||
|
+ const workspaceId = request.req.workspace.id
|
||||||
|
+ const workspaceCacheVersion = request.req.cacheVersion
|
||||||
|
+ const url = request.req.baseUrl
|
||||||
|
+
|
||||||
|
+ const cacheKey = `${workspaceId}-${workspaceCacheVersion}-${url}`
|
||||||
|
+
|
||||||
|
+ if (this.schemaCache.has(cacheKey)) {
|
||||||
|
+ return this.schemaCache.get(cacheKey)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ const schemas: GraphQLSchema[] = [];
|
+ const schemas: GraphQLSchema[] = [];
|
||||||
+
|
+
|
||||||
+ if (options.schema) {
|
+ if (options.schema) {
|
||||||
@ -285,14 +406,29 @@ index ce142f6..cda4117 100644
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ return mergeSchemas({
|
+ const mergedSchemas = mergeSchemas({
|
||||||
+ schemas,
|
+ schemas,
|
||||||
+ });
|
+ });
|
||||||
|
+
|
||||||
|
+ this.schemaCache.set(cacheKey, mergedSchemas)
|
||||||
|
+
|
||||||
|
+ return mergedSchemas;
|
||||||
+ },
|
+ },
|
||||||
graphqlEndpoint: options.path,
|
graphqlEndpoint: options.path,
|
||||||
// disable logging by default
|
// disable logging by default
|
||||||
// however, if `true` use nest logger
|
// however, if `true` use nest logger
|
||||||
@@ -115,7 +143,7 @@ export abstract class AbstractYogaDriver<
|
@@ -105,8 +149,8 @@ export abstract class AbstractYogaDriver<
|
||||||
|
options.logging == null
|
||||||
|
? false
|
||||||
|
: options.logging
|
||||||
|
- ? new LoggerWithInfo('YogaDriver')
|
||||||
|
- : options.logging,
|
||||||
|
+ ? new LoggerWithInfo('YogaDriver')
|
||||||
|
+ : options.logging,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.yoga = yoga as YogaDriverServerInstance<Platform>;
|
||||||
|
@@ -115,7 +159,7 @@ export abstract class AbstractYogaDriver<
|
||||||
}
|
}
|
||||||
|
|
||||||
protected registerFastify(
|
protected registerFastify(
|
||||||
@ -301,11 +437,21 @@ index ce142f6..cda4117 100644
|
|||||||
{ preStartHook }: { preStartHook?: (app: FastifyInstance) => void } = {},
|
{ preStartHook }: { preStartHook?: (app: FastifyInstance) => void } = {},
|
||||||
) {
|
) {
|
||||||
const app: FastifyInstance = this.httpAdapterHost.httpAdapter.getInstance();
|
const app: FastifyInstance = this.httpAdapterHost.httpAdapter.getInstance();
|
||||||
@@ -124,6 +152,25 @@ export abstract class AbstractYogaDriver<
|
@@ -124,6 +168,39 @@ export abstract class AbstractYogaDriver<
|
||||||
|
|
||||||
const yoga = createYoga<YogaDriverServerContext<'fastify'>>({
|
const yoga = createYoga<YogaDriverServerContext<'fastify'>>({
|
||||||
...options,
|
...options,
|
||||||
+ schema: async request => {
|
+ schema: async request => {
|
||||||
|
+ const workspaceId = request.req.workspace.id
|
||||||
|
+ const workspaceCacheVersion = request.req.cacheVersion
|
||||||
|
+ const url = request.req.baseUrl
|
||||||
|
+
|
||||||
|
+ const cacheKey = `${workspaceId}-${workspaceCacheVersion}-${url}`
|
||||||
|
+
|
||||||
|
+ if (this.schemaCache.has(cacheKey)) {
|
||||||
|
+ return this.schemaCache.get(cacheKey)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ const schemas: GraphQLSchema[] = [];
|
+ const schemas: GraphQLSchema[] = [];
|
||||||
+
|
+
|
||||||
+ if (options.schema) {
|
+ if (options.schema) {
|
||||||
@ -320,10 +466,25 @@ index ce142f6..cda4117 100644
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ return mergeSchemas({
|
+ const mergedSchemas = mergeSchemas({
|
||||||
+ schemas,
|
+ schemas,
|
||||||
+ });
|
+ });
|
||||||
|
+
|
||||||
|
+ this.schemaCache.set(cacheKey, mergedSchemas)
|
||||||
|
+
|
||||||
|
+ return mergedSchemas;
|
||||||
+ },
|
+ },
|
||||||
graphqlEndpoint: options.path,
|
graphqlEndpoint: options.path,
|
||||||
// disable logging by default
|
// disable logging by default
|
||||||
// however, if `true` use fastify logger
|
// however, if `true` use fastify logger
|
||||||
|
@@ -191,8 +268,8 @@ export class YogaDriver<
|
||||||
|
const config: SubscriptionConfig =
|
||||||
|
options.subscriptions === true
|
||||||
|
? {
|
||||||
|
- 'graphql-ws': true,
|
||||||
|
- }
|
||||||
|
+ 'graphql-ws': true,
|
||||||
|
+ }
|
||||||
|
: options.subscriptions;
|
||||||
|
|
||||||
|
if (config['graphql-ws']) {
|
||||||
@ -6828,16 +6828,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch::locator=twenty-server%40workspace%3Apackages%2Ftwenty-server":
|
"@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch::locator=twenty-server%40workspace%3Apackages%2Ftwenty-server":
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
resolution: "@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@npm%3A2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch::version=2.1.0&hash=25fc63&locator=twenty-server%40workspace%3Apackages%2Ftwenty-server"
|
resolution: "@graphql-yoga/nestjs@patch:@graphql-yoga/nestjs@npm%3A2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch::version=2.1.0&hash=6db821&locator=twenty-server%40workspace%3Apackages%2Ftwenty-server"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@nestjs/common": ^10.0.0
|
"@nestjs/common": ^10.0.0
|
||||||
"@nestjs/core": ^10.0.0
|
"@nestjs/core": ^10.0.0
|
||||||
"@nestjs/graphql": ^12.0.0
|
"@nestjs/graphql": ^12.0.0
|
||||||
graphql: ^15.0.0 || ^16.0.0
|
graphql: ^15.0.0 || ^16.0.0
|
||||||
graphql-yoga: ^4.0.4
|
graphql-yoga: ^4.0.4
|
||||||
checksum: 333501a04f79ef158cd92e240abecf1056ea12e8f63345758d6f79bbd88d923846fac44940765ae48a1b05d108107e3ba1539eea1092802c5bdf74bf166ea16a
|
checksum: 512ed39d8a0b9e238b31b0a9fc0a4ee2c8980f7f38f218635beede535bcec9fbf11731ff2f986c0d551a003094c6935748cee721d3a46339b3a6e0467a699e1d
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -46272,7 +46272,7 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "twenty-server@workspace:packages/twenty-server"
|
resolution: "twenty-server@workspace:packages/twenty-server"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga+nestjs+2.1.0.patch"
|
"@graphql-yoga/nestjs": "patch:@graphql-yoga/nestjs@2.1.0#./patches/@graphql-yoga-nestjs-npm-2.1.0-cb509e6047.patch"
|
||||||
"@nestjs/cache-manager": "npm:^2.2.1"
|
"@nestjs/cache-manager": "npm:^2.2.1"
|
||||||
"@nestjs/cli": "npm:10.3.0"
|
"@nestjs/cli": "npm:10.3.0"
|
||||||
"@nestjs/devtools-integration": "npm:^0.1.6"
|
"@nestjs/devtools-integration": "npm:^0.1.6"
|
||||||
|
|||||||
Reference in New Issue
Block a user