@fluojs/graphql 1.0.0-beta.6 → 1.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +3 -2
- package/README.md +3 -2
- package/dist/service.d.ts +2 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +34 -22
- package/package.json +6 -6
package/README.ko.md
CHANGED
|
@@ -159,6 +159,7 @@ GraphqlModule.forRoot({
|
|
|
159
159
|
- `graphiql`을 명시적으로 켜거나 `introspection: true`를 설정하지 않으면 스키마 introspection은 기본적으로 비활성화됩니다.
|
|
160
160
|
- 문서 depth, field complexity, aggregate query cost에 대한 request validation budget이 기본적으로 보수적인 값으로 활성화됩니다.
|
|
161
161
|
- Streaming GraphQL 응답은 downstream response stream이 닫히거나 오류를 내면 upstream fetch body를 cancel하므로 SSE subscription 리소스를 즉시 해제합니다.
|
|
162
|
+
- GraphQL 스키마 해석 이후 bootstrap이 실패하면 임시 `graphql/jsutils/instanceOf` 패치를 원복한 뒤 원래 오류를 다시 던지므로, 실패한 시작 시도가 이후 애플리케이션 시작의 process-wide GraphQL 동작을 오염시키지 않습니다.
|
|
162
163
|
- WebSocket 구독 경로에는 별도의 전송 budget이 기본 적용됩니다: 동시 연결 `100`, 최대 payload 크기 `64 KiB`, 연결당 활성 operation `25`개입니다.
|
|
163
164
|
- 무제한 WebSocket 동작이 정말 필요할 때만 `subscriptions.websocket.limits = false`를 사용하고, 그 경우에도 동일한 수준의 외부 제어 수단을 마련해야 합니다.
|
|
164
165
|
- 무제한 동작이 꼭 필요할 때만 `limits: false`를 사용하고, 그 경우에는 외부 제어 수단을 함께 두어야 합니다.
|
|
@@ -205,5 +206,5 @@ GraphqlModule.forRoot({
|
|
|
205
206
|
|
|
206
207
|
## 예제 소스
|
|
207
208
|
|
|
208
|
-
- `packages/graphql/src/module.test.ts`: 통합 테스트 및 사용 예제.
|
|
209
|
-
- `
|
|
209
|
+
- `packages/graphql/src/module.test.ts`: 모듈 등록, resolver 실행, request-scoped container, subscription, guardrail 기본값을 다루는 통합 테스트 및 사용 예제.
|
|
210
|
+
- `packages/graphql/field-resolver-rfc.md`: 현재 런타임 계약에 포함되지 않는 field-resolver 패턴의 설계 노트.
|
package/README.md
CHANGED
|
@@ -159,6 +159,7 @@ GraphqlModule.forRoot({
|
|
|
159
159
|
- Schema introspection is disabled by default unless you explicitly enable `graphiql` or set `introspection: true`.
|
|
160
160
|
- Request validation budgets are enabled by default with conservative limits for document depth, field complexity, and aggregate query cost.
|
|
161
161
|
- Streaming GraphQL responses cancel the upstream fetch body when the downstream response stream closes or errors, so SSE subscription resources are released promptly.
|
|
162
|
+
- Bootstrap failures after GraphQL schema resolution restore the package's temporary `graphql/jsutils/instanceOf` patch before rethrowing, so failed startups do not leak process-wide GraphQL behavior into later app attempts.
|
|
162
163
|
- WebSocket subscriptions use separate transport budgets by default: `100` concurrent connections, `64 KiB` maximum payload size, and `25` active operations per connection.
|
|
163
164
|
- Set `subscriptions.websocket.limits = false` only when you intentionally need unbounded websocket behavior and can enforce equivalent controls elsewhere.
|
|
164
165
|
- Pass `limits: false` only when you intentionally need unbounded behavior and can compensate with external controls.
|
|
@@ -205,5 +206,5 @@ Supported module options include `schema`, `context`, `plugins`, `graphiql`, `in
|
|
|
205
206
|
|
|
206
207
|
## Example Sources
|
|
207
208
|
|
|
208
|
-
- `packages/graphql/src/module.test.ts`: Integration tests and usage examples.
|
|
209
|
-
- `
|
|
209
|
+
- `packages/graphql/src/module.test.ts`: Integration tests and usage examples for module registration, resolver execution, request-scoped containers, subscriptions, and guardrail defaults.
|
|
210
|
+
- `packages/graphql/field-resolver-rfc.md`: Design notes for field-resolver patterns that are not part of the current runtime contract.
|
package/dist/service.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type HttpApplicationAdapter } from '@fluojs/http';
|
|
2
2
|
import type { Container } from '@fluojs/di';
|
|
3
|
-
import {
|
|
3
|
+
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown } from '@fluojs/runtime';
|
|
4
4
|
import type { GraphqlModuleOptions } from './types.js';
|
|
5
5
|
/**
|
|
6
6
|
* Declares the HTTP endpoints that receive GraphQL GET and POST requests.
|
|
@@ -34,6 +34,7 @@ export declare class GraphqlLifecycleService implements OnApplicationBootstrap,
|
|
|
34
34
|
constructor(runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, adapter: HttpApplicationAdapter, options: GraphqlModuleOptions);
|
|
35
35
|
onApplicationBootstrap(): Promise<void>;
|
|
36
36
|
onApplicationShutdown(): Promise<void>;
|
|
37
|
+
private resetGraphqlRuntimeState;
|
|
37
38
|
private resolveGraphiqlEnabled;
|
|
38
39
|
private resolveIntrospectionEnabled;
|
|
39
40
|
private resolveWebSocketLimits;
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAKA,OAAO,EAAgD,KAAK,sBAAsB,EAAsD,MAAM,cAAc,CAAC;AAE7J,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAKA,OAAO,EAAgD,KAAK,sBAAsB,EAAsD,MAAM,cAAc,CAAC;AAE7J,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA2BxH,OAAO,KAAK,EAEV,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAmIpB;;GAEG;AACH,qBACa,yBAAyB;IAEpC,SAAS,IAAI,SAAS;IAKtB,UAAU,IAAI,SAAS;CAGxB;AA+ID;;GAEG;AACH,qBACa,uBAAwB,YAAW,sBAAsB,EAAE,qBAAqB;IA6DzF,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhE1B,OAAO,CAAC,uBAAuB,CAAsC;IACrE,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqC;IACzE,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAA6C;IAC1F,OAAO,CAAC,mBAAmB,CAAkD;IAC7E,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,wBAAwB,CAAkC;IAClE,OAAO,CAAC,sBAAsB,CAAgC;IAC9D,OAAO,CAAC,uBAAuB,CAAyD;IACxF,OAAO,CAAC,6BAA6B,CAA2B;IAChE,OAAO,CAAC,yBAAyB,CAAyD;IAC1F,OAAO,CAAC,IAAI,CAAuB;IAEnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CA4CzB;gBAGiB,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,oBAAoB;IAG1C,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgDvC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;YAI9B,wBAAwB;IAYtC,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,sBAAsB;IAe9B,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,mBAAmB;IAyB3B,OAAO,CAAC,0BAA0B;YAuEpB,4BAA4B;IAuC1C,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,oBAAoB;YAkBd,wBAAwB;IAwDtC,OAAO,CAAC,kCAAkC;IAwB1C,OAAO,CAAC,sBAAsB;IAoB9B,OAAO,CAAC,sCAAsC;YAchC,kCAAkC;YAqBlC,sCAAsC;IAkBpD,OAAO,CAAC,6BAA6B;YAYvB,yBAAyB;CAexC"}
|
package/dist/service.js
CHANGED
|
@@ -284,30 +284,42 @@ class GraphqlLifecycleService {
|
|
|
284
284
|
if (this.middlewareRegistered) {
|
|
285
285
|
return;
|
|
286
286
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
287
|
+
try {
|
|
288
|
+
const deps = await loadGraphqlDeps();
|
|
289
|
+
const schema = this.resolveSchema(deps);
|
|
290
|
+
this.executeGraphqlOperation = deps.execute;
|
|
291
|
+
this.graphQLErrorConstructor = deps.GraphQLError;
|
|
292
|
+
this.subscribeGraphqlOperation = deps.subscribe;
|
|
293
|
+
const requestLimits = resolveGraphqlRequestLimits(this.options.limits);
|
|
294
|
+
const validationPlugin = createGraphqlValidationPlugin({
|
|
295
|
+
introspection: this.resolveIntrospectionEnabled(),
|
|
296
|
+
limits: requestLimits
|
|
297
|
+
});
|
|
298
|
+
this.yoga = deps.createYoga({
|
|
299
|
+
context: contextValue => contextValue[GRAPHQL_CONTEXT_OVERRIDE] ?? this.buildGraphqlContext(contextValue.request),
|
|
300
|
+
graphqlEndpoint: '/graphql',
|
|
301
|
+
graphiql: this.resolveGraphiqlEnabled(),
|
|
302
|
+
...(validationPlugin || this.options.plugins && this.options.plugins.length > 0 ? {
|
|
303
|
+
plugins: [...(validationPlugin ? [validationPlugin] : []), ...(this.options.plugins ?? [])]
|
|
304
|
+
} : {}),
|
|
305
|
+
schema
|
|
306
|
+
});
|
|
307
|
+
this.registerWebSocketTransport();
|
|
308
|
+
this.registerMiddleware();
|
|
309
|
+
this.middlewareRegistered = true;
|
|
310
|
+
} catch (error) {
|
|
311
|
+
try {
|
|
312
|
+
await this.resetGraphqlRuntimeState();
|
|
313
|
+
} catch (cleanupError) {
|
|
314
|
+
this.logger.error('Failed to clean up GraphQL runtime after bootstrap failure.', cleanupError, 'GraphqlLifecycleService');
|
|
315
|
+
}
|
|
316
|
+
throw error;
|
|
317
|
+
}
|
|
309
318
|
}
|
|
310
319
|
async onApplicationShutdown() {
|
|
320
|
+
await this.resetGraphqlRuntimeState();
|
|
321
|
+
}
|
|
322
|
+
async resetGraphqlRuntimeState() {
|
|
311
323
|
await this.unregisterWebSocketTransport();
|
|
312
324
|
this.unregisterMiddleware();
|
|
313
325
|
this.middlewareRegistered = false;
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"yoga",
|
|
10
10
|
"api"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.0-beta.
|
|
12
|
+
"version": "1.0.0-beta.7",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"graphql-ws": "^5.16.2",
|
|
42
42
|
"graphql-yoga": "^5.18.1",
|
|
43
43
|
"ws": "^8.18.3",
|
|
44
|
-
"@fluojs/core": "^1.0.0-beta.
|
|
45
|
-
"@fluojs/di": "^1.0.0-beta.
|
|
46
|
-
"@fluojs/http": "^1.0.0-beta.
|
|
47
|
-
"@fluojs/runtime": "^1.0.0-beta.
|
|
48
|
-
"@fluojs/validation": "^1.0.0-beta.
|
|
44
|
+
"@fluojs/core": "^1.0.0-beta.6",
|
|
45
|
+
"@fluojs/di": "^1.0.0-beta.8",
|
|
46
|
+
"@fluojs/http": "^1.0.0-beta.11",
|
|
47
|
+
"@fluojs/runtime": "^1.0.0-beta.12",
|
|
48
|
+
"@fluojs/validation": "^1.0.0-beta.4"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/ws": "^8.18.1",
|