@fluojs/graphql 1.0.2 → 1.0.4
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 +4 -0
- package/README.md +4 -0
- package/dist/service.d.ts +1 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +26 -18
- package/dist/transport/transport.d.ts.map +1 -1
- package/dist/transport/transport.js +8 -3
- package/package.json +6 -6
package/README.ko.md
CHANGED
|
@@ -109,6 +109,7 @@ class UserResolver {
|
|
|
109
109
|
- `@fluojs/graphql`은 HTTP GraphQL 요청 또는 WebSocket subscription operation마다 operation-scoped DI 컨테이너를 하나 만들고, 해당 operation 안의 resolver 호출들이 이를 공유하며, operation 완료 또는 WebSocket operation 종료 시 dispose합니다.
|
|
110
110
|
- Resolver 메서드는 `GraphQLContext`를 받으며, 내장 필드에는 fluo `request`, middleware 또는 guard가 설정한 인증된 HTTP `principal`, WebSocket subscription의 `connectionParams`와 `socket`, 그리고 `GraphqlModule.forRoot({ context })`가 반환한 사용자 정의 필드가 포함됩니다.
|
|
111
111
|
- Request-scoped DataLoader helper는 같은 `GraphQLContext` operation 경계를 사용하므로 loader cache는 하나의 GraphQL operation 안에서만 공유됩니다.
|
|
112
|
+
- 애플리케이션 shutdown은 WebSocket transport를 등록 해제하고, 살아 있는 WebSocket client를 닫으며, 아직 활성 상태인 WebSocket operation container를 정상 operation 완료 때와 같은 request-scoped provider teardown 경로로 dispose합니다.
|
|
112
113
|
|
|
113
114
|
```typescript
|
|
114
115
|
import { Inject, Scope } from '@fluojs/core';
|
|
@@ -161,9 +162,12 @@ GraphqlModule.forRoot({
|
|
|
161
162
|
|
|
162
163
|
- `graphiql`을 명시적으로 켜거나 `introspection: true`를 설정하지 않으면 스키마 introspection은 기본적으로 비활성화됩니다.
|
|
163
164
|
- 문서 depth, field complexity, aggregate query cost에 대한 request validation budget이 기본적으로 보수적인 값으로 활성화됩니다.
|
|
165
|
+
- `graphiql` 기본값은 `false`입니다. `introspection`은 명시하지 않으면 `graphiql` 설정을 따르므로, production 앱은 기본적으로 비공개 상태를 유지하고 로컬 GraphiQL 세션만 opt in할 수 있습니다.
|
|
166
|
+
- `limits`에는 request validation budget을 전달하거나 `false`를 전달할 수 있습니다. `false`는 fluo 밖에서 동등한 제어를 적용할 때만 사용하세요.
|
|
164
167
|
- Streaming GraphQL 응답은 downstream response stream이 닫히거나 오류를 내면 upstream fetch body를 cancel하므로 SSE subscription 리소스를 즉시 해제합니다.
|
|
165
168
|
- GraphQL 스키마 해석 이후 bootstrap이 실패하면 임시 `graphql/jsutils/instanceOf` 패치를 원복한 뒤 원래 오류를 다시 던지므로, 실패한 시작 시도가 이후 애플리케이션 시작의 process-wide GraphQL 동작을 오염시키지 않습니다.
|
|
166
169
|
- WebSocket 구독 경로에는 별도의 전송 budget이 기본 적용됩니다: 동시 연결 `100`, 최대 payload 크기 `64 KiB`, 연결당 활성 operation `25`개입니다.
|
|
170
|
+
- `subscriptions.websocket.enabled` 기본값은 `false`입니다. 활성화하려면 upgrade를 지원하는 Node HTTP/S adapter가 필요합니다. `connectionInitWaitTimeoutMs`는 연결 초기화를 위해 `graphql-ws`로 전달되고, `keepAliveMs`는 설정 시 WebSocket keepalive ping 주기를 제어합니다.
|
|
167
171
|
- 무제한 WebSocket 동작이 정말 필요할 때만 `subscriptions.websocket.limits = false`를 사용하고, 그 경우에도 동일한 수준의 외부 제어 수단을 마련해야 합니다.
|
|
168
172
|
- 무제한 동작이 꼭 필요할 때만 `limits: false`를 사용하고, 그 경우에는 외부 제어 수단을 함께 두어야 합니다.
|
|
169
173
|
|
package/README.md
CHANGED
|
@@ -109,6 +109,7 @@ class UserResolver {
|
|
|
109
109
|
- `@fluojs/graphql` creates one operation-scoped DI container for each HTTP GraphQL request or websocket subscription operation, shares it across resolver calls in that operation, and disposes it when the operation completes or the websocket operation disconnects.
|
|
110
110
|
- Resolver methods receive a `GraphQLContext` whose built-in fields expose the underlying fluo `request`, the authenticated HTTP `principal` when middleware or guards set one, websocket `connectionParams` and `socket` for websocket subscriptions, and any custom fields returned from `GraphqlModule.forRoot({ context })`.
|
|
111
111
|
- Request-scoped DataLoader helpers use the same `GraphQLContext` operation boundary, so loader caches are shared only within one GraphQL operation.
|
|
112
|
+
- Application shutdown unregisters the websocket transport, closes live websocket clients, and disposes any still-active websocket operation containers through the same request-scoped provider teardown path used when an operation completes normally.
|
|
112
113
|
|
|
113
114
|
```typescript
|
|
114
115
|
import { Inject, Scope } from '@fluojs/core';
|
|
@@ -161,9 +162,12 @@ GraphqlModule.forRoot({
|
|
|
161
162
|
|
|
162
163
|
- Schema introspection is disabled by default unless you explicitly enable `graphiql` or set `introspection: true`.
|
|
163
164
|
- Request validation budgets are enabled by default with conservative limits for document depth, field complexity, and aggregate query cost.
|
|
165
|
+
- `graphiql` defaults to `false`. `introspection` follows `graphiql` unless set explicitly, so production apps stay private by default while local GraphiQL sessions can opt in.
|
|
166
|
+
- `limits` accepts request validation budgets or `false`; use `false` only when equivalent controls exist outside fluo.
|
|
164
167
|
- Streaming GraphQL responses cancel the upstream fetch body when the downstream response stream closes or errors, so SSE subscription resources are released promptly.
|
|
165
168
|
- 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.
|
|
166
169
|
- WebSocket subscriptions use separate transport budgets by default: `100` concurrent connections, `64 KiB` maximum payload size, and `25` active operations per connection.
|
|
170
|
+
- `subscriptions.websocket.enabled` defaults to `false`; enabling it requires a Node HTTP/S adapter with upgrade support. `connectionInitWaitTimeoutMs` is forwarded to `graphql-ws` for connection initialization, and `keepAliveMs` controls websocket keepalive pings when configured.
|
|
167
171
|
- Set `subscriptions.websocket.limits = false` only when you intentionally need unbounded websocket behavior and can enforce equivalent controls elsewhere.
|
|
168
172
|
- Pass `limits: false` only when you intentionally need unbounded behavior and can compensate with external controls.
|
|
169
173
|
|
package/dist/service.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare class GraphqlLifecycleService implements OnApplicationBootstrap,
|
|
|
21
21
|
private graphQLErrorConstructor;
|
|
22
22
|
private middlewareRegistered;
|
|
23
23
|
private readonly operationContainers;
|
|
24
|
+
private readonly requestContexts;
|
|
24
25
|
private readonly websocketOperationContainers;
|
|
25
26
|
private websocketDisposable;
|
|
26
27
|
private websocketServer;
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAGA,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;AA0BxH,OAAO,KAAK,EAEV,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAsIpB;;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,eAAe,CAAiD;IACjF,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,CA2CzB;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;YAyBb,0BAA0B;YA4E1B,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
|
@@ -4,14 +4,9 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
4
4
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
5
5
|
function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
|
|
6
6
|
function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
|
|
7
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
8
|
-
import { createRequire } from 'node:module';
|
|
9
7
|
import { Controller, Get, Post } from '@fluojs/http';
|
|
10
8
|
import { Inject } from '@fluojs/core';
|
|
11
9
|
import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
|
|
12
|
-
import { handleProtocols } from 'graphql-ws';
|
|
13
|
-
import { useServer } from 'graphql-ws/lib/use/ws';
|
|
14
|
-
import { WebSocketServer } from 'ws';
|
|
15
10
|
import { discoverResolverDescriptors } from './discovery.js';
|
|
16
11
|
import { createGraphqlValidationPlugin, resolveGraphqlRequestLimits } from './guardrails.js';
|
|
17
12
|
import { GRAPHQL_INTERNAL_MODULE_OPTIONS_TOKEN } from './internal-tokens.js';
|
|
@@ -76,8 +71,6 @@ function closeWebSocketServer(server) {
|
|
|
76
71
|
});
|
|
77
72
|
});
|
|
78
73
|
}
|
|
79
|
-
const graphqlRequestContextStorage = new AsyncLocalStorage();
|
|
80
|
-
const runtimeRequire = createRequire(import.meta.url);
|
|
81
74
|
let graphqlInstanceOfPatchRefCount = 0;
|
|
82
75
|
let restoreGraphqlInstanceOfPatch;
|
|
83
76
|
const allowedCrossRealmGraphqlObjects = new WeakSet();
|
|
@@ -150,8 +143,7 @@ function isAllowedCrossRealmGraphqlObject(value, constructor) {
|
|
|
150
143
|
}
|
|
151
144
|
return allowedCrossRealmGraphqlObjects.has(value) && getCrossRealmGraphqlTag(value, constructor) !== undefined;
|
|
152
145
|
}
|
|
153
|
-
function installGraphqlInstanceOfPatch() {
|
|
154
|
-
const instanceOfModule = runtimeRequire('graphql/jsutils/instanceOf.js');
|
|
146
|
+
function installGraphqlInstanceOfPatch(instanceOfModule) {
|
|
155
147
|
if (restoreGraphqlInstanceOfPatch) {
|
|
156
148
|
graphqlInstanceOfPatchRefCount += 1;
|
|
157
149
|
return releaseGraphqlInstanceOfPatch;
|
|
@@ -192,8 +184,13 @@ function releaseGraphqlInstanceOfPatch() {
|
|
|
192
184
|
restoreGraphqlInstanceOfPatch = undefined;
|
|
193
185
|
}
|
|
194
186
|
async function loadGraphqlDeps() {
|
|
187
|
+
const {
|
|
188
|
+
createRequire
|
|
189
|
+
} = await import('node:module');
|
|
190
|
+
const runtimeRequire = createRequire(import.meta.url);
|
|
195
191
|
const graphqlMod = runtimeRequire('graphql');
|
|
196
192
|
const yogaMod = runtimeRequire('graphql-yoga');
|
|
193
|
+
const instanceOfModule = runtimeRequire('graphql/jsutils/instanceOf.js');
|
|
197
194
|
return {
|
|
198
195
|
GraphQLError: graphqlMod.GraphQLError,
|
|
199
196
|
GraphQLBoolean: graphqlMod.GraphQLBoolean,
|
|
@@ -208,6 +205,7 @@ async function loadGraphqlDeps() {
|
|
|
208
205
|
buildSchema: graphqlMod.buildSchema,
|
|
209
206
|
createYoga: yogaMod.createYoga,
|
|
210
207
|
execute: graphqlMod.execute,
|
|
208
|
+
instanceOfModule,
|
|
211
209
|
subscribe: graphqlMod.subscribe
|
|
212
210
|
};
|
|
213
211
|
}
|
|
@@ -223,6 +221,7 @@ class GraphqlLifecycleService {
|
|
|
223
221
|
graphQLErrorConstructor;
|
|
224
222
|
middlewareRegistered = false;
|
|
225
223
|
operationContainers = new WeakMap();
|
|
224
|
+
requestContexts = new WeakMap();
|
|
226
225
|
websocketOperationContainers = new Map();
|
|
227
226
|
websocketDisposable;
|
|
228
227
|
websocketServer;
|
|
@@ -251,13 +250,15 @@ class GraphqlLifecycleService {
|
|
|
251
250
|
}
|
|
252
251
|
try {
|
|
253
252
|
const fetchRequest = toFetchRequest(context.request);
|
|
253
|
+
this.requestContexts.set(fetchRequest, {
|
|
254
|
+
principal: context.requestContext.principal,
|
|
255
|
+
request: context.request
|
|
256
|
+
});
|
|
254
257
|
try {
|
|
255
|
-
const fetchResponse = await
|
|
256
|
-
principal: context.requestContext.principal,
|
|
257
|
-
request: context.request
|
|
258
|
-
}, () => yoga.fetch(fetchRequest));
|
|
258
|
+
const fetchResponse = await yoga.fetch(fetchRequest);
|
|
259
259
|
await writeFetchResponse(fetchResponse, context.response);
|
|
260
260
|
} finally {
|
|
261
|
+
this.requestContexts.delete(fetchRequest);
|
|
261
262
|
await this.disposeOperationContainer(fetchRequest);
|
|
262
263
|
}
|
|
263
264
|
} catch (error) {
|
|
@@ -304,7 +305,7 @@ class GraphqlLifecycleService {
|
|
|
304
305
|
} : {}),
|
|
305
306
|
schema
|
|
306
307
|
});
|
|
307
|
-
this.registerWebSocketTransport();
|
|
308
|
+
await this.registerWebSocketTransport();
|
|
308
309
|
this.registerMiddleware();
|
|
309
310
|
this.middlewareRegistered = true;
|
|
310
311
|
} catch (error) {
|
|
@@ -348,7 +349,7 @@ class GraphqlLifecycleService {
|
|
|
348
349
|
};
|
|
349
350
|
}
|
|
350
351
|
resolveSchema(deps) {
|
|
351
|
-
this.releaseGraphqlInstanceOfPatch ??= installGraphqlInstanceOfPatch();
|
|
352
|
+
this.releaseGraphqlInstanceOfPatch ??= installGraphqlInstanceOfPatch(deps.instanceOfModule);
|
|
352
353
|
return resolveSchema(deps, this.options.schema, () => this.createCodeFirstSchema(deps), markAllowedCrossRealmGraphqlObjects);
|
|
353
354
|
}
|
|
354
355
|
createCodeFirstSchema(deps) {
|
|
@@ -386,7 +387,7 @@ class GraphqlLifecycleService {
|
|
|
386
387
|
}
|
|
387
388
|
}
|
|
388
389
|
buildGraphqlContext(request, requestContextOverride, operationContainerOverride) {
|
|
389
|
-
const storedContext =
|
|
390
|
+
const storedContext = this.requestContexts.get(request);
|
|
390
391
|
const requestContext = {
|
|
391
392
|
connectionParams: requestContextOverride?.connectionParams,
|
|
392
393
|
principal: requestContextOverride?.principal ?? storedContext?.principal,
|
|
@@ -404,10 +405,17 @@ class GraphqlLifecycleService {
|
|
|
404
405
|
[GRAPHQL_OPERATION_CONTAINER]: operationContainer
|
|
405
406
|
};
|
|
406
407
|
}
|
|
407
|
-
registerWebSocketTransport() {
|
|
408
|
+
async registerWebSocketTransport() {
|
|
408
409
|
if (!this.isWebSocketTransportEnabled() || this.yoga === undefined || this.websocketUpgradeListener !== undefined) {
|
|
409
410
|
return;
|
|
410
411
|
}
|
|
412
|
+
const [{
|
|
413
|
+
handleProtocols
|
|
414
|
+
}, {
|
|
415
|
+
useServer
|
|
416
|
+
}, {
|
|
417
|
+
WebSocketServer
|
|
418
|
+
}] = await Promise.all([import('graphql-ws'), import('graphql-ws/lib/use/ws'), import('ws')]);
|
|
411
419
|
const upgradeServer = this.resolveUpgradeServer();
|
|
412
420
|
const websocketLimits = this.resolveWebSocketLimits();
|
|
413
421
|
const websocketServer = new WebSocketServer({
|
|
@@ -566,7 +574,7 @@ class GraphqlLifecycleService {
|
|
|
566
574
|
return;
|
|
567
575
|
}
|
|
568
576
|
const body = `${message}\n`;
|
|
569
|
-
socket.write([`HTTP/1.1 ${String(statusCode)} ${statusCode === 503 ? 'Service Unavailable' : 'Bad Request'}`, 'Connection: close', 'Content-Type: text/plain; charset=utf-8', `Content-Length: ${String(
|
|
577
|
+
socket.write([`HTTP/1.1 ${String(statusCode)} ${statusCode === 503 ? 'Service Unavailable' : 'Bad Request'}`, 'Connection: close', 'Content-Type: text/plain; charset=utf-8', `Content-Length: ${String(new TextEncoder().encode(body).byteLength)}`, '', body].join('\r\n'));
|
|
570
578
|
socket.destroy();
|
|
571
579
|
}
|
|
572
580
|
getOrCreateWebSocketOperationContainer(socketKey, operationId) {
|
|
@@ -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;
|
|
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;AA6ED;;;;;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"}
|
|
@@ -34,13 +34,18 @@ function createFetchHeaders(request) {
|
|
|
34
34
|
}
|
|
35
35
|
return headers;
|
|
36
36
|
}
|
|
37
|
+
function copyBytesToArrayBuffer(bytes) {
|
|
38
|
+
const body = new ArrayBuffer(bytes.byteLength);
|
|
39
|
+
new Uint8Array(body).set(bytes);
|
|
40
|
+
return body;
|
|
41
|
+
}
|
|
37
42
|
function createFetchBody(request, headers) {
|
|
38
43
|
const method = request.method.toUpperCase();
|
|
39
44
|
if (method === 'GET' || method === 'HEAD') {
|
|
40
45
|
return undefined;
|
|
41
46
|
}
|
|
42
47
|
if (request.rawBody) {
|
|
43
|
-
return
|
|
48
|
+
return copyBytesToArrayBuffer(request.rawBody);
|
|
44
49
|
}
|
|
45
50
|
if (request.body === undefined) {
|
|
46
51
|
return undefined;
|
|
@@ -49,10 +54,10 @@ function createFetchBody(request, headers) {
|
|
|
49
54
|
return request.body;
|
|
50
55
|
}
|
|
51
56
|
if (request.body instanceof Uint8Array) {
|
|
52
|
-
return
|
|
57
|
+
return copyBytesToArrayBuffer(request.body);
|
|
53
58
|
}
|
|
54
59
|
if (request.body instanceof ArrayBuffer) {
|
|
55
|
-
return
|
|
60
|
+
return request.body;
|
|
56
61
|
}
|
|
57
62
|
if (!headers.has('content-type')) {
|
|
58
63
|
headers.set('content-type', 'application/json; charset=utf-8');
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"yoga",
|
|
10
10
|
"api"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.
|
|
12
|
+
"version": "1.0.4",
|
|
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/
|
|
45
|
-
"@fluojs/
|
|
46
|
-
"@fluojs/http": "^1.
|
|
47
|
-
"@fluojs/runtime": "^1.1.
|
|
48
|
-
"@fluojs/
|
|
44
|
+
"@fluojs/di": "^1.1.0",
|
|
45
|
+
"@fluojs/validation": "^1.0.5",
|
|
46
|
+
"@fluojs/http": "^1.1.1",
|
|
47
|
+
"@fluojs/runtime": "^1.1.7",
|
|
48
|
+
"@fluojs/core": "^1.0.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/ws": "^8.18.1",
|