@fluojs/graphql 1.0.0-beta.4 → 1.0.0-beta.6
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 +11 -3
- package/README.md +11 -3
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +2 -2
- package/dist/service.d.ts +1 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +34 -10
- package/dist/transport/transport.d.ts.map +1 -1
- package/dist/transport/transport.js +66 -20
- package/package.json +6 -6
package/README.ko.md
CHANGED
|
@@ -33,6 +33,8 @@ pnpm add @fluojs/graphql graphql graphql-yoga
|
|
|
33
33
|
|
|
34
34
|
`GraphqlModule.forRoot(...)`를 등록하고 표준 데코레이터를 사용하여 resolver를 정의합니다. 현재 `@fluojs/graphql`는 동기 모듈 엔트리포인트만 제공하며 `GraphqlModule.forRootAsync(...)` 계약은 없습니다.
|
|
35
35
|
|
|
36
|
+
Code-first resolver discovery 대신 schema-first 통합을 원하면 executable `GraphQLSchema`를 `schema`로 전달할 수도 있습니다.
|
|
37
|
+
|
|
36
38
|
```typescript
|
|
37
39
|
import { Module } from '@fluojs/core';
|
|
38
40
|
import { bootstrapNodeApplication } from '@fluojs/runtime/node';
|
|
@@ -133,7 +135,7 @@ class RequestResolver {
|
|
|
133
135
|
### 프로토콜 지원
|
|
134
136
|
- **HTTP**: 표준 GET/POST 쿼리 및 뮤테이션.
|
|
135
137
|
- **SSE**: Server-Sent Events를 통한 구독(기본값).
|
|
136
|
-
- **WebSockets**:
|
|
138
|
+
- **WebSockets**: 활성 adapter가 upgrade listener를 지원하는 Node HTTP/S 서버를 노출할 때(예: Node HTTP adapter) 사용할 수 있는 선택적 `graphql-ws` 실시간 구독 지원.
|
|
137
139
|
|
|
138
140
|
```typescript
|
|
139
141
|
GraphqlModule.forRoot({
|
|
@@ -150,10 +152,13 @@ GraphqlModule.forRoot({
|
|
|
150
152
|
})
|
|
151
153
|
```
|
|
152
154
|
|
|
155
|
+
`@Subscription({ topics })`는 지원하지 않습니다. Subscription resolver는 `AsyncIterable`을 반환해야 합니다.
|
|
156
|
+
|
|
153
157
|
## 운영 가드레일
|
|
154
158
|
|
|
155
159
|
- `graphiql`을 명시적으로 켜거나 `introspection: true`를 설정하지 않으면 스키마 introspection은 기본적으로 비활성화됩니다.
|
|
156
160
|
- 문서 depth, field complexity, aggregate query cost에 대한 request validation budget이 기본적으로 보수적인 값으로 활성화됩니다.
|
|
161
|
+
- Streaming GraphQL 응답은 downstream response stream이 닫히거나 오류를 내면 upstream fetch body를 cancel하므로 SSE subscription 리소스를 즉시 해제합니다.
|
|
157
162
|
- WebSocket 구독 경로에는 별도의 전송 budget이 기본 적용됩니다: 동시 연결 `100`, 최대 payload 크기 `64 KiB`, 연결당 활성 operation `25`개입니다.
|
|
158
163
|
- 무제한 WebSocket 동작이 정말 필요할 때만 `subscriptions.websocket.limits = false`를 사용하고, 그 경우에도 동일한 수준의 외부 제어 수단을 마련해야 합니다.
|
|
159
164
|
- 무제한 동작이 꼭 필요할 때만 `limits: false`를 사용하고, 그 경우에는 외부 제어 수단을 함께 두어야 합니다.
|
|
@@ -186,8 +191,11 @@ GraphqlModule.forRoot({
|
|
|
186
191
|
- `GraphqlModule.forRoot(options)`: GraphQL 통합을 위한 메인 엔트리 포인트.
|
|
187
192
|
- `Resolver`, `Query`, `Mutation`, `Subscription`: 작업 데코레이터.
|
|
188
193
|
- `Arg`: Input DTO 필드를 GraphQL 인자로 매핑하는 데코레이터.
|
|
189
|
-
- `createDataLoader`, `createDataLoaderMap`: DataLoader
|
|
190
|
-
- `
|
|
194
|
+
- `createDataLoader`, `createDataLoaderMap`, `getRequestScopedDataLoader`, `createRequestScopedDataLoaderFactory`, `DataLoader`: DataLoader factory helper와 type.
|
|
195
|
+
- `listOf`, `isGraphqlListTypeRef`: list output type reference helper.
|
|
196
|
+
- `GraphQLContext` 및 export되는 option/metadata type: GraphQL 실행과 module 설정을 위한 타입 정의.
|
|
197
|
+
|
|
198
|
+
지원되는 module option에는 `schema`, `context`, `plugins`, `graphiql`, `introspection`, `limits`, `subscriptions.websocket.enabled`, `subscriptions.websocket.limits`, `connectionInitWaitTimeoutMs`, `keepAliveMs`가 포함됩니다.
|
|
191
199
|
|
|
192
200
|
## 관련 패키지
|
|
193
201
|
|
package/README.md
CHANGED
|
@@ -33,6 +33,8 @@ pnpm add @fluojs/graphql graphql graphql-yoga
|
|
|
33
33
|
|
|
34
34
|
Register `GraphqlModule.forRoot(...)` and define a resolver using standard decorators. `@fluojs/graphql` currently exposes a synchronous module entrypoint only; there is no `GraphqlModule.forRootAsync(...)` contract.
|
|
35
35
|
|
|
36
|
+
You can also pass an executable `GraphQLSchema` via `schema` when you want schema-first integration instead of code-first resolver discovery.
|
|
37
|
+
|
|
36
38
|
```typescript
|
|
37
39
|
import { Module } from '@fluojs/core';
|
|
38
40
|
import { bootstrapNodeApplication } from '@fluojs/runtime/node';
|
|
@@ -133,7 +135,7 @@ class RequestResolver {
|
|
|
133
135
|
### Protocol Support
|
|
134
136
|
- **HTTP**: Standard GET/POST queries and mutations.
|
|
135
137
|
- **SSE**: Subscriptions over Server-Sent Events (default).
|
|
136
|
-
- **WebSockets**: Optional `graphql-ws` support for real-time subscriptions.
|
|
138
|
+
- **WebSockets**: Optional `graphql-ws` support for real-time subscriptions when the active adapter exposes a Node HTTP/S server with upgrade listeners (for example, the Node HTTP adapter).
|
|
137
139
|
|
|
138
140
|
```typescript
|
|
139
141
|
GraphqlModule.forRoot({
|
|
@@ -150,10 +152,13 @@ GraphqlModule.forRoot({
|
|
|
150
152
|
})
|
|
151
153
|
```
|
|
152
154
|
|
|
155
|
+
`@Subscription({ topics })` is not supported. Subscription resolvers must return an `AsyncIterable`.
|
|
156
|
+
|
|
153
157
|
## Operational Guardrails
|
|
154
158
|
|
|
155
159
|
- Schema introspection is disabled by default unless you explicitly enable `graphiql` or set `introspection: true`.
|
|
156
160
|
- Request validation budgets are enabled by default with conservative limits for document depth, field complexity, and aggregate query cost.
|
|
161
|
+
- Streaming GraphQL responses cancel the upstream fetch body when the downstream response stream closes or errors, so SSE subscription resources are released promptly.
|
|
157
162
|
- WebSocket subscriptions use separate transport budgets by default: `100` concurrent connections, `64 KiB` maximum payload size, and `25` active operations per connection.
|
|
158
163
|
- Set `subscriptions.websocket.limits = false` only when you intentionally need unbounded websocket behavior and can enforce equivalent controls elsewhere.
|
|
159
164
|
- Pass `limits: false` only when you intentionally need unbounded behavior and can compensate with external controls.
|
|
@@ -186,8 +191,11 @@ GraphqlModule.forRoot({
|
|
|
186
191
|
- `GraphqlModule.forRoot(options)`: Main entry point for GraphQL integration.
|
|
187
192
|
- `Resolver`, `Query`, `Mutation`, `Subscription`: Operation decorators.
|
|
188
193
|
- `Arg`: Input DTO field-to-GraphQL-argument mapping decorator.
|
|
189
|
-
- `createDataLoader`, `createDataLoaderMap`: DataLoader factory helpers.
|
|
190
|
-
- `
|
|
194
|
+
- `createDataLoader`, `createDataLoaderMap`, `getRequestScopedDataLoader`, `createRequestScopedDataLoaderFactory`, `DataLoader`: DataLoader factory helpers and types.
|
|
195
|
+
- `listOf`, `isGraphqlListTypeRef`: Helpers for list output type references.
|
|
196
|
+
- `GraphQLContext` and exported option/metadata types: Type definitions for GraphQL execution and module configuration.
|
|
197
|
+
|
|
198
|
+
Supported module options include `schema`, `context`, `plugins`, `graphiql`, `introspection`, `limits`, `subscriptions.websocket.enabled`, `subscriptions.websocket.limits`, `connectionInitWaitTimeoutMs`, and `keepAliveMs`.
|
|
191
199
|
|
|
192
200
|
## Related Packages
|
|
193
201
|
|
package/dist/decorators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAoB,cAAc,EAAE,qBAAqB,EAA6C,MAAM,YAAY,CAAC;AAGrI,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,wBAAwB,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;AAE1H;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,qBAAqB,CAAC;CACpC;AAED,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AACnD,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;AACrD,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAoB,cAAc,EAAE,qBAAqB,EAA6C,MAAM,YAAY,CAAC;AAGrI,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,wBAAwB,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC;AAE1H;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,qBAAqB,CAAC;CACpC;AAED,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AACnD,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;AACrD,KAAK,kBAAkB,GAAG,wBAAwB,CAAC;AAyGnD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAQ9D;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAE9F;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAEjG;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,qBAAqB,GAAG,mBAAmB,CAErG;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAmBxD"}
|
package/dist/decorators.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ensureMetadataSymbol } from '@fluojs/core/internal';
|
|
2
2
|
import { argMetadataSymbol, handlerMetadataSymbol, resolverMetadataSymbol } from './metadata.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Describes the resolver method options contract.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
ensureMetadataSymbol();
|
|
8
9
|
function getStandardMetadataBag(metadata) {
|
|
9
|
-
void metadataSymbol;
|
|
10
10
|
return metadata;
|
|
11
11
|
}
|
|
12
12
|
function normalizeResolverTypeName(typeName, fallbackName) {
|
package/dist/service.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare class GraphqlLifecycleService implements OnApplicationBootstrap,
|
|
|
27
27
|
private websocketUpgradeListener;
|
|
28
28
|
private websocketUpgradeServer;
|
|
29
29
|
private executeGraphqlOperation;
|
|
30
|
+
private releaseGraphqlInstanceOfPatch;
|
|
30
31
|
private subscribeGraphqlOperation;
|
|
31
32
|
private yoga;
|
|
32
33
|
private readonly middleware;
|
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,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,iBAAiB,CAAC;AA2BzB,OAAO,KAAK,EAEV,oBAAoB,EAGrB,MAAM,YAAY,CAAC;
|
|
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,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,iBAAiB,CAAC;AA2BzB,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;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAhExB,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,EACjC,OAAO,EAAE,oBAAoB;IAGxC,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAsCvC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5C,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
|
@@ -78,7 +78,8 @@ function closeWebSocketServer(server) {
|
|
|
78
78
|
}
|
|
79
79
|
const graphqlRequestContextStorage = new AsyncLocalStorage();
|
|
80
80
|
const runtimeRequire = createRequire(import.meta.url);
|
|
81
|
-
let
|
|
81
|
+
let graphqlInstanceOfPatchRefCount = 0;
|
|
82
|
+
let restoreGraphqlInstanceOfPatch;
|
|
82
83
|
const allowedCrossRealmGraphqlObjects = new WeakSet();
|
|
83
84
|
|
|
84
85
|
/**
|
|
@@ -149,15 +150,16 @@ function isAllowedCrossRealmGraphqlObject(value, constructor) {
|
|
|
149
150
|
}
|
|
150
151
|
return allowedCrossRealmGraphqlObjects.has(value) && getCrossRealmGraphqlTag(value, constructor) !== undefined;
|
|
151
152
|
}
|
|
152
|
-
function
|
|
153
|
-
if (graphqlInstanceOfPatched) {
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
153
|
+
function installGraphqlInstanceOfPatch() {
|
|
156
154
|
const instanceOfModule = runtimeRequire('graphql/jsutils/instanceOf.js');
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
if (restoreGraphqlInstanceOfPatch) {
|
|
156
|
+
graphqlInstanceOfPatchRefCount += 1;
|
|
157
|
+
return releaseGraphqlInstanceOfPatch;
|
|
158
|
+
}
|
|
159
|
+
const patchedFrom = instanceOfModule.instanceOf;
|
|
160
|
+
const patchedInstanceOf = (value, constructor) => {
|
|
159
161
|
try {
|
|
160
|
-
if (
|
|
162
|
+
if (patchedFrom(value, constructor)) {
|
|
161
163
|
return true;
|
|
162
164
|
}
|
|
163
165
|
} catch (error) {
|
|
@@ -168,7 +170,26 @@ function patchGraphqlInstanceOf() {
|
|
|
168
170
|
}
|
|
169
171
|
return isAllowedCrossRealmGraphqlObject(value, constructor);
|
|
170
172
|
};
|
|
171
|
-
|
|
173
|
+
instanceOfModule.instanceOf = patchedInstanceOf;
|
|
174
|
+
graphqlInstanceOfPatchRefCount = 1;
|
|
175
|
+
restoreGraphqlInstanceOfPatch = () => {
|
|
176
|
+
if (instanceOfModule.instanceOf !== patchedInstanceOf) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
instanceOfModule.instanceOf = patchedFrom;
|
|
180
|
+
};
|
|
181
|
+
return releaseGraphqlInstanceOfPatch;
|
|
182
|
+
}
|
|
183
|
+
function releaseGraphqlInstanceOfPatch() {
|
|
184
|
+
if (graphqlInstanceOfPatchRefCount === 0) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
graphqlInstanceOfPatchRefCount -= 1;
|
|
188
|
+
if (graphqlInstanceOfPatchRefCount > 0) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
restoreGraphqlInstanceOfPatch?.();
|
|
192
|
+
restoreGraphqlInstanceOfPatch = undefined;
|
|
172
193
|
}
|
|
173
194
|
async function loadGraphqlDeps() {
|
|
174
195
|
const graphqlMod = runtimeRequire('graphql');
|
|
@@ -208,6 +229,7 @@ class GraphqlLifecycleService {
|
|
|
208
229
|
websocketUpgradeListener;
|
|
209
230
|
websocketUpgradeServer;
|
|
210
231
|
executeGraphqlOperation;
|
|
232
|
+
releaseGraphqlInstanceOfPatch;
|
|
211
233
|
subscribeGraphqlOperation;
|
|
212
234
|
yoga;
|
|
213
235
|
middleware = {
|
|
@@ -291,6 +313,8 @@ class GraphqlLifecycleService {
|
|
|
291
313
|
this.middlewareRegistered = false;
|
|
292
314
|
this.executeGraphqlOperation = undefined;
|
|
293
315
|
this.graphQLErrorConstructor = undefined;
|
|
316
|
+
this.releaseGraphqlInstanceOfPatch?.();
|
|
317
|
+
this.releaseGraphqlInstanceOfPatch = undefined;
|
|
294
318
|
this.subscribeGraphqlOperation = undefined;
|
|
295
319
|
this.yoga = undefined;
|
|
296
320
|
}
|
|
@@ -312,7 +336,7 @@ class GraphqlLifecycleService {
|
|
|
312
336
|
};
|
|
313
337
|
}
|
|
314
338
|
resolveSchema(deps) {
|
|
315
|
-
|
|
339
|
+
this.releaseGraphqlInstanceOfPatch ??= installGraphqlInstanceOfPatch();
|
|
316
340
|
return resolveSchema(deps, this.options.schema, () => this.createCodeFirstSchema(deps), markAllowedCrossRealmGraphqlObjects);
|
|
317
341
|
}
|
|
318
342
|
createCodeFirstSchema(deps) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAA2B,MAAM,cAAc,CAAC;AAEjG;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAsED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAUjE;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAA2B,MAAM,cAAc,CAAC;AAEjG;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAsED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAUjE;AAgGD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BrH"}
|
|
@@ -89,6 +89,71 @@ function readSetCookieValues(headers) {
|
|
|
89
89
|
}
|
|
90
90
|
return values;
|
|
91
91
|
}
|
|
92
|
+
async function writeFetchResponseStream(body, stream) {
|
|
93
|
+
const reader = body.getReader();
|
|
94
|
+
let readerDone = false;
|
|
95
|
+
let cancelPromise;
|
|
96
|
+
let notifyCancellation;
|
|
97
|
+
const cancellationStarted = new Promise(resolve => {
|
|
98
|
+
notifyCancellation = resolve;
|
|
99
|
+
});
|
|
100
|
+
const removeCloseListener = stream.onClose?.(() => {
|
|
101
|
+
if (!readerDone) {
|
|
102
|
+
void cancelUnreadBody().catch(() => {});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
const cancelUnreadBody = () => {
|
|
106
|
+
if (!cancelPromise) {
|
|
107
|
+
readerDone = true;
|
|
108
|
+
notifyCancellation?.();
|
|
109
|
+
cancelPromise = reader.cancel();
|
|
110
|
+
}
|
|
111
|
+
return cancelPromise;
|
|
112
|
+
};
|
|
113
|
+
const readNextChunk = async () => {
|
|
114
|
+
const readPromise = reader.read();
|
|
115
|
+
readPromise.catch(() => {});
|
|
116
|
+
return await Promise.race([readPromise, cancellationStarted.then(async () => {
|
|
117
|
+
await cancelPromise;
|
|
118
|
+
return {
|
|
119
|
+
done: true,
|
|
120
|
+
value: undefined
|
|
121
|
+
};
|
|
122
|
+
})]);
|
|
123
|
+
};
|
|
124
|
+
try {
|
|
125
|
+
while (true) {
|
|
126
|
+
if (stream.closed) {
|
|
127
|
+
await cancelUnreadBody();
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
const {
|
|
131
|
+
done,
|
|
132
|
+
value
|
|
133
|
+
} = await readNextChunk();
|
|
134
|
+
if (done) {
|
|
135
|
+
readerDone = true;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
if (stream.closed) {
|
|
139
|
+
await cancelUnreadBody();
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
const canContinue = stream.write(value);
|
|
143
|
+
if (!canContinue && !stream.closed) {
|
|
144
|
+
await stream.waitForDrain?.();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
await cancelUnreadBody();
|
|
149
|
+
throw error;
|
|
150
|
+
} finally {
|
|
151
|
+
removeCloseListener?.();
|
|
152
|
+
}
|
|
153
|
+
if (!stream.closed) {
|
|
154
|
+
stream.close();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
92
157
|
|
|
93
158
|
/**
|
|
94
159
|
* Write fetch response.
|
|
@@ -113,26 +178,7 @@ export async function writeFetchResponse(fetchResponse, frameworkResponse) {
|
|
|
113
178
|
if (fetchResponse.body && stream) {
|
|
114
179
|
frameworkResponse.committed = true;
|
|
115
180
|
stream.flush?.();
|
|
116
|
-
|
|
117
|
-
while (true) {
|
|
118
|
-
const {
|
|
119
|
-
done,
|
|
120
|
-
value
|
|
121
|
-
} = await reader.read();
|
|
122
|
-
if (done) {
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
if (stream.closed) {
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
const canContinue = stream.write(value);
|
|
129
|
-
if (!canContinue && !stream.closed) {
|
|
130
|
-
await stream.waitForDrain?.();
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (!stream.closed) {
|
|
134
|
-
stream.close();
|
|
135
|
-
}
|
|
181
|
+
await writeFetchResponseStream(fetchResponse.body, stream);
|
|
136
182
|
return;
|
|
137
183
|
}
|
|
138
184
|
const buffer = await fetchResponse.arrayBuffer();
|
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.6",
|
|
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.4",
|
|
45
|
+
"@fluojs/di": "^1.0.0-beta.6",
|
|
46
|
+
"@fluojs/http": "^1.0.0-beta.10",
|
|
47
|
+
"@fluojs/runtime": "^1.0.0-beta.11",
|
|
48
|
+
"@fluojs/validation": "^1.0.0-beta.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/ws": "^8.18.1",
|