mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 02:56:23 +08:00
chore: rename fundamentals to base (#9119)
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import { ApolloDriverConfig } from '@nestjs/apollo';
|
||||
|
||||
import { defineStartupConfig, ModuleConfig } from '../../base/config';
|
||||
|
||||
declare module '../../base/config' {
|
||||
interface AppConfig {
|
||||
graphql: ModuleConfig<ApolloDriverConfig>;
|
||||
}
|
||||
}
|
||||
|
||||
defineStartupConfig('graphql', {
|
||||
buildSchemaOptions: {
|
||||
numberScalarMode: 'integer',
|
||||
},
|
||||
introspection: true,
|
||||
playground: true,
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
import './config';
|
||||
|
||||
import { STATUS_CODES } from 'node:http';
|
||||
import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import type { ApolloDriverConfig } from '@nestjs/apollo';
|
||||
import { ApolloDriver } from '@nestjs/apollo';
|
||||
import { Global, HttpStatus, Module } from '@nestjs/common';
|
||||
import { GraphQLModule } from '@nestjs/graphql';
|
||||
import { Request, Response } from 'express';
|
||||
import { GraphQLError } from 'graphql';
|
||||
|
||||
import { Config } from '../config';
|
||||
import { UserFriendlyError } from '../error';
|
||||
import { GQLLoggerPlugin } from './logger-plugin';
|
||||
|
||||
export type GraphqlContext = {
|
||||
req: Request;
|
||||
res: Response;
|
||||
isAdminQuery: boolean;
|
||||
};
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [
|
||||
GraphQLModule.forRootAsync<ApolloDriverConfig>({
|
||||
driver: ApolloDriver,
|
||||
useFactory: (config: Config) => {
|
||||
return {
|
||||
...config.graphql,
|
||||
path: `${config.server.path}/graphql`,
|
||||
csrfPrevention: {
|
||||
requestHeaders: ['content-type'],
|
||||
},
|
||||
autoSchemaFile: join(
|
||||
fileURLToPath(import.meta.url),
|
||||
config.node.dev
|
||||
? '../../../schema.gql'
|
||||
: '../../../../node_modules/.cache/schema.gql'
|
||||
),
|
||||
sortSchema: true,
|
||||
context: ({
|
||||
req,
|
||||
res,
|
||||
}: {
|
||||
req: Request;
|
||||
res: Response;
|
||||
}): GraphqlContext => ({
|
||||
req,
|
||||
res,
|
||||
isAdminQuery: false,
|
||||
}),
|
||||
includeStacktraceInErrorResponses: !config.node.prod,
|
||||
plugins: [new GQLLoggerPlugin()],
|
||||
formatError: (formattedError, error) => {
|
||||
// @ts-expect-error allow assign
|
||||
formattedError.extensions ??= {};
|
||||
|
||||
if (
|
||||
error instanceof GraphQLError &&
|
||||
error.originalError instanceof UserFriendlyError
|
||||
) {
|
||||
// @ts-expect-error allow assign
|
||||
formattedError.extensions = error.originalError.toJSON();
|
||||
formattedError.extensions.stacktrace = error.originalError.stack;
|
||||
return formattedError;
|
||||
} else {
|
||||
// @ts-expect-error allow assign
|
||||
formattedError.message = 'Internal Server Error';
|
||||
|
||||
formattedError.extensions['status'] =
|
||||
HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
formattedError.extensions['code'] =
|
||||
STATUS_CODES[HttpStatus.INTERNAL_SERVER_ERROR];
|
||||
}
|
||||
|
||||
return formattedError;
|
||||
},
|
||||
};
|
||||
},
|
||||
inject: [Config],
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class GqlModule {}
|
||||
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
ApolloServerPlugin,
|
||||
GraphQLRequestContext,
|
||||
GraphQLRequestListener,
|
||||
} from '@apollo/server';
|
||||
import { Plugin } from '@nestjs/apollo';
|
||||
import { Response } from 'express';
|
||||
|
||||
import { metrics } from '../metrics/metrics';
|
||||
import { mapAnyError } from '../nestjs';
|
||||
|
||||
export interface RequestContext {
|
||||
req: Express.Request & {
|
||||
res: Express.Response;
|
||||
};
|
||||
}
|
||||
|
||||
@Plugin()
|
||||
export class GQLLoggerPlugin implements ApolloServerPlugin {
|
||||
requestDidStart(
|
||||
ctx: GraphQLRequestContext<RequestContext>
|
||||
): Promise<GraphQLRequestListener<GraphQLRequestContext<RequestContext>>> {
|
||||
const res = ctx.contextValue.req.res as Response;
|
||||
const operation = ctx.request.operationName;
|
||||
|
||||
metrics.gql.counter('query_counter').add(1, { operation });
|
||||
const start = Date.now();
|
||||
function endTimer() {
|
||||
return Date.now() - start;
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
willSendResponse: () => {
|
||||
const time = endTimer();
|
||||
res.setHeader('Server-Timing', `gql;dur=${time};desc="GraphQL"`);
|
||||
metrics.gql.histogram('query_duration').record(time, { operation });
|
||||
return Promise.resolve();
|
||||
},
|
||||
didEncounterErrors: ctx => {
|
||||
ctx.errors.forEach(gqlErr => {
|
||||
const error = mapAnyError(
|
||||
gqlErr.originalError ? gqlErr.originalError : gqlErr
|
||||
);
|
||||
error.log('GraphQL');
|
||||
|
||||
metrics.gql.counter('query_error_counter').add(1, {
|
||||
operation,
|
||||
code: error.status,
|
||||
type: error.type,
|
||||
error: error.name,
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user