@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 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;
@@ -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,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"}
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 graphqlRequestContextStorage.run({
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 = graphqlRequestContextStorage.getStore();
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(Buffer.byteLength(body))}`, '', body].join('\r\n'));
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;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"}
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 Buffer.from(request.rawBody);
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 Buffer.from(request.body);
57
+ return copyBytesToArrayBuffer(request.body);
53
58
  }
54
59
  if (request.body instanceof ArrayBuffer) {
55
- return Buffer.from(request.body);
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.2",
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/core": "^1.0.2",
45
- "@fluojs/di": "^1.0.2",
46
- "@fluojs/http": "^1.0.0",
47
- "@fluojs/runtime": "^1.1.0",
48
- "@fluojs/validation": "^1.0.3"
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",