mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 11:06:25 +08:00
26db1d436d
standardize the error raising in both GraphQL Resolvers and Controllers.
Now, All user aware errors should be throwed with `HttpException`'s variants, for example `NotFoundException`.
> Directly throwing `GraphQLError` are forbidden.
The GraphQL errorFormatter will handle it automatically and set `code`, `status` in error extensions.
At the same time, the frontend `GraphQLError` should be imported from `@affine/graphql`, which introduce a better error extensions type.
----
controller example:
```js
@Get('/docs/${id}')
doc() {
// ...
// imported from '@nestjs/common'
throw new NotFoundException('Doc is not found.');
// ...
}
```
the above will response as:
```
status: 404 Not Found
{
"message": "Doc is not found.",
"statusCode": 404,
"error": "Not Found"
}
```
resolver example:
```js
@Mutation()
invite() {
// ...
throw new PayloadTooLargeException('Workspace seats is full.')
// ...
}
```
the above will response as:
```
status: 200 Ok
{
"data": null,
"errors": [
{
"message": "Workspace seats is full.",
"extensions": {
"code": 404,
"status": "Not Found"
}
}
]
}
```
for frontend GraphQLError user-friend, a helper function introduced:
```js
import { findGraphQLError } from '@affine/graphql'
fetch(query)
.catch(errOrArr => {
const e = findGraphQLError(errOrArr, e => e.extensions.code === 404)
if (e) {
// handle
}
})
```
48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
import { Type } from '@nestjs/common';
|
|
import { NestFactory } from '@nestjs/core';
|
|
import type { NestExpressApplication } from '@nestjs/platform-express';
|
|
import cookieParser from 'cookie-parser';
|
|
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
|
|
|
|
import { GlobalExceptionFilter } from './fundamentals';
|
|
import { SocketIoAdapter, SocketIoAdapterImpl } from './fundamentals/websocket';
|
|
import { serverTimingAndCache } from './middleware/timing';
|
|
|
|
export async function createApp() {
|
|
const { AppModule } = await import('./app.module');
|
|
|
|
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
|
|
cors: true,
|
|
rawBody: true,
|
|
bodyParser: true,
|
|
logger: AFFiNE.affine.stable ? ['log'] : ['verbose'],
|
|
});
|
|
|
|
app.use(serverTimingAndCache);
|
|
|
|
app.use(
|
|
graphqlUploadExpress({
|
|
// TODO: dynamic limit by quota
|
|
maxFileSize: 100 * 1024 * 1024,
|
|
maxFiles: 5,
|
|
})
|
|
);
|
|
|
|
app.useGlobalFilters(new GlobalExceptionFilter(app.getHttpAdapter()));
|
|
app.use(cookieParser());
|
|
|
|
if (AFFiNE.flavor.sync) {
|
|
const SocketIoAdapter = app.get<Type<SocketIoAdapter>>(
|
|
SocketIoAdapterImpl,
|
|
{
|
|
strict: false,
|
|
}
|
|
);
|
|
|
|
const adapter = new SocketIoAdapter(app);
|
|
app.useWebSocketAdapter(adapter);
|
|
}
|
|
|
|
return app;
|
|
}
|