@effect-gql/core 0.1.0 → 1.1.0

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.
Files changed (164) hide show
  1. package/README.md +100 -0
  2. package/builder/index.cjs +1446 -0
  3. package/builder/index.cjs.map +1 -0
  4. package/builder/index.d.cts +260 -0
  5. package/{dist/builder/pipe-api.d.ts → builder/index.d.ts} +50 -21
  6. package/builder/index.js +1405 -0
  7. package/builder/index.js.map +1 -0
  8. package/index.cjs +3469 -0
  9. package/index.cjs.map +1 -0
  10. package/index.d.cts +529 -0
  11. package/index.d.ts +529 -0
  12. package/index.js +3292 -0
  13. package/index.js.map +1 -0
  14. package/package.json +19 -28
  15. package/schema-builder-DKvkzU_M.d.cts +965 -0
  16. package/schema-builder-DKvkzU_M.d.ts +965 -0
  17. package/server/index.cjs +1579 -0
  18. package/server/index.cjs.map +1 -0
  19. package/server/index.d.cts +682 -0
  20. package/server/index.d.ts +682 -0
  21. package/server/index.js +1548 -0
  22. package/server/index.js.map +1 -0
  23. package/dist/analyzer-extension.d.ts +0 -105
  24. package/dist/analyzer-extension.d.ts.map +0 -1
  25. package/dist/analyzer-extension.js +0 -137
  26. package/dist/analyzer-extension.js.map +0 -1
  27. package/dist/builder/execute.d.ts +0 -26
  28. package/dist/builder/execute.d.ts.map +0 -1
  29. package/dist/builder/execute.js +0 -104
  30. package/dist/builder/execute.js.map +0 -1
  31. package/dist/builder/field-builders.d.ts +0 -30
  32. package/dist/builder/field-builders.d.ts.map +0 -1
  33. package/dist/builder/field-builders.js +0 -200
  34. package/dist/builder/field-builders.js.map +0 -1
  35. package/dist/builder/index.d.ts +0 -7
  36. package/dist/builder/index.d.ts.map +0 -1
  37. package/dist/builder/index.js +0 -31
  38. package/dist/builder/index.js.map +0 -1
  39. package/dist/builder/pipe-api.d.ts.map +0 -1
  40. package/dist/builder/pipe-api.js +0 -151
  41. package/dist/builder/pipe-api.js.map +0 -1
  42. package/dist/builder/schema-builder.d.ts +0 -301
  43. package/dist/builder/schema-builder.d.ts.map +0 -1
  44. package/dist/builder/schema-builder.js +0 -566
  45. package/dist/builder/schema-builder.js.map +0 -1
  46. package/dist/builder/type-registry.d.ts +0 -80
  47. package/dist/builder/type-registry.d.ts.map +0 -1
  48. package/dist/builder/type-registry.js +0 -505
  49. package/dist/builder/type-registry.js.map +0 -1
  50. package/dist/builder/types.d.ts +0 -283
  51. package/dist/builder/types.d.ts.map +0 -1
  52. package/dist/builder/types.js +0 -3
  53. package/dist/builder/types.js.map +0 -1
  54. package/dist/cli/generate-schema.d.ts +0 -29
  55. package/dist/cli/generate-schema.d.ts.map +0 -1
  56. package/dist/cli/generate-schema.js +0 -233
  57. package/dist/cli/generate-schema.js.map +0 -1
  58. package/dist/cli/index.d.ts +0 -19
  59. package/dist/cli/index.d.ts.map +0 -1
  60. package/dist/cli/index.js +0 -24
  61. package/dist/cli/index.js.map +0 -1
  62. package/dist/context.d.ts +0 -18
  63. package/dist/context.d.ts.map +0 -1
  64. package/dist/context.js +0 -11
  65. package/dist/context.js.map +0 -1
  66. package/dist/error.d.ts +0 -45
  67. package/dist/error.d.ts.map +0 -1
  68. package/dist/error.js +0 -29
  69. package/dist/error.js.map +0 -1
  70. package/dist/extensions.d.ts +0 -130
  71. package/dist/extensions.d.ts.map +0 -1
  72. package/dist/extensions.js +0 -78
  73. package/dist/extensions.js.map +0 -1
  74. package/dist/index.d.ts +0 -12
  75. package/dist/index.d.ts.map +0 -1
  76. package/dist/index.js +0 -47
  77. package/dist/index.js.map +0 -1
  78. package/dist/loader.d.ts +0 -169
  79. package/dist/loader.d.ts.map +0 -1
  80. package/dist/loader.js +0 -237
  81. package/dist/loader.js.map +0 -1
  82. package/dist/resolver-context.d.ts +0 -154
  83. package/dist/resolver-context.d.ts.map +0 -1
  84. package/dist/resolver-context.js +0 -184
  85. package/dist/resolver-context.js.map +0 -1
  86. package/dist/schema-mapping.d.ts +0 -30
  87. package/dist/schema-mapping.d.ts.map +0 -1
  88. package/dist/schema-mapping.js +0 -280
  89. package/dist/schema-mapping.js.map +0 -1
  90. package/dist/server/cache-control.d.ts +0 -96
  91. package/dist/server/cache-control.d.ts.map +0 -1
  92. package/dist/server/cache-control.js +0 -308
  93. package/dist/server/cache-control.js.map +0 -1
  94. package/dist/server/complexity.d.ts +0 -165
  95. package/dist/server/complexity.d.ts.map +0 -1
  96. package/dist/server/complexity.js +0 -433
  97. package/dist/server/complexity.js.map +0 -1
  98. package/dist/server/config.d.ts +0 -66
  99. package/dist/server/config.d.ts.map +0 -1
  100. package/dist/server/config.js +0 -104
  101. package/dist/server/config.js.map +0 -1
  102. package/dist/server/graphiql.d.ts +0 -5
  103. package/dist/server/graphiql.d.ts.map +0 -1
  104. package/dist/server/graphiql.js +0 -43
  105. package/dist/server/graphiql.js.map +0 -1
  106. package/dist/server/index.d.ts +0 -18
  107. package/dist/server/index.d.ts.map +0 -1
  108. package/dist/server/index.js +0 -48
  109. package/dist/server/index.js.map +0 -1
  110. package/dist/server/router.d.ts +0 -79
  111. package/dist/server/router.d.ts.map +0 -1
  112. package/dist/server/router.js +0 -232
  113. package/dist/server/router.js.map +0 -1
  114. package/dist/server/schema-builder-extensions.d.ts +0 -42
  115. package/dist/server/schema-builder-extensions.d.ts.map +0 -1
  116. package/dist/server/schema-builder-extensions.js +0 -48
  117. package/dist/server/schema-builder-extensions.js.map +0 -1
  118. package/dist/server/sse-adapter.d.ts +0 -64
  119. package/dist/server/sse-adapter.d.ts.map +0 -1
  120. package/dist/server/sse-adapter.js +0 -227
  121. package/dist/server/sse-adapter.js.map +0 -1
  122. package/dist/server/sse-types.d.ts +0 -192
  123. package/dist/server/sse-types.d.ts.map +0 -1
  124. package/dist/server/sse-types.js +0 -63
  125. package/dist/server/sse-types.js.map +0 -1
  126. package/dist/server/ws-adapter.d.ts +0 -39
  127. package/dist/server/ws-adapter.d.ts.map +0 -1
  128. package/dist/server/ws-adapter.js +0 -247
  129. package/dist/server/ws-adapter.js.map +0 -1
  130. package/dist/server/ws-types.d.ts +0 -169
  131. package/dist/server/ws-types.d.ts.map +0 -1
  132. package/dist/server/ws-types.js +0 -11
  133. package/dist/server/ws-types.js.map +0 -1
  134. package/dist/server/ws-utils.d.ts +0 -42
  135. package/dist/server/ws-utils.d.ts.map +0 -1
  136. package/dist/server/ws-utils.js +0 -99
  137. package/dist/server/ws-utils.js.map +0 -1
  138. package/src/analyzer-extension.ts +0 -254
  139. package/src/builder/execute.ts +0 -153
  140. package/src/builder/field-builders.ts +0 -322
  141. package/src/builder/index.ts +0 -48
  142. package/src/builder/pipe-api.ts +0 -312
  143. package/src/builder/schema-builder.ts +0 -970
  144. package/src/builder/type-registry.ts +0 -670
  145. package/src/builder/types.ts +0 -305
  146. package/src/context.ts +0 -23
  147. package/src/error.ts +0 -32
  148. package/src/extensions.ts +0 -240
  149. package/src/index.ts +0 -32
  150. package/src/loader.ts +0 -363
  151. package/src/resolver-context.ts +0 -253
  152. package/src/schema-mapping.ts +0 -307
  153. package/src/server/cache-control.ts +0 -590
  154. package/src/server/complexity.ts +0 -774
  155. package/src/server/config.ts +0 -174
  156. package/src/server/graphiql.ts +0 -38
  157. package/src/server/index.ts +0 -96
  158. package/src/server/router.ts +0 -432
  159. package/src/server/schema-builder-extensions.ts +0 -51
  160. package/src/server/sse-adapter.ts +0 -327
  161. package/src/server/sse-types.ts +0 -234
  162. package/src/server/ws-adapter.ts +0 -355
  163. package/src/server/ws-types.ts +0 -192
  164. package/src/server/ws-utils.ts +0 -136
@@ -0,0 +1,1548 @@
1
+ import { Config, Option, Data, Context, Schema, Effect, Queue, Deferred, Stream, Ref, Runtime, Fiber } from 'effect';
2
+ import { HttpIncomingMessage, HttpServerResponse, HttpServerRequest, HttpRouter } from '@effect/platform';
3
+ import { Kind, GraphQLObjectType, parse, specifiedRules, NoSchemaIntrospectionCustomRule, validate, subscribe, GraphQLError, GraphQLNonNull, GraphQLList, GraphQLSchema, GraphQLScalarType, GraphQLEnumType, execute } from 'graphql';
4
+ import { makeServer } from 'graphql-ws';
5
+
6
+ // src/server/config.ts
7
+ var defaultConfig = {
8
+ path: "/graphql",
9
+ graphiql: false,
10
+ complexity: void 0,
11
+ introspection: true,
12
+ cacheControl: void 0
13
+ };
14
+ var normalizeConfig = (input = {}) => {
15
+ const path = input.path ?? defaultConfig.path;
16
+ let graphiql = false;
17
+ if (input.graphiql === true) {
18
+ graphiql = { path: "/graphiql", endpoint: path };
19
+ } else if (input.graphiql && typeof input.graphiql === "object") {
20
+ graphiql = {
21
+ path: input.graphiql.path ?? "/graphiql",
22
+ endpoint: input.graphiql.endpoint ?? path
23
+ };
24
+ }
25
+ return {
26
+ path,
27
+ graphiql,
28
+ complexity: input.complexity,
29
+ introspection: input.introspection ?? true,
30
+ cacheControl: input.cacheControl
31
+ };
32
+ };
33
+ var GraphQLRouterConfigFromEnv = Config.all({
34
+ path: Config.string("GRAPHQL_PATH").pipe(Config.withDefault("/graphql")),
35
+ introspection: Config.boolean("GRAPHQL_INTROSPECTION").pipe(Config.withDefault(true)),
36
+ graphiqlEnabled: Config.boolean("GRAPHIQL_ENABLED").pipe(Config.withDefault(false)),
37
+ graphiqlPath: Config.string("GRAPHIQL_PATH").pipe(Config.withDefault("/graphiql")),
38
+ graphiqlEndpoint: Config.string("GRAPHIQL_ENDPOINT").pipe(Config.option),
39
+ maxDepth: Config.number("GRAPHQL_MAX_DEPTH").pipe(Config.option),
40
+ maxComplexity: Config.number("GRAPHQL_MAX_COMPLEXITY").pipe(Config.option),
41
+ maxAliases: Config.number("GRAPHQL_MAX_ALIASES").pipe(Config.option),
42
+ maxFields: Config.number("GRAPHQL_MAX_FIELDS").pipe(Config.option),
43
+ defaultFieldComplexity: Config.number("GRAPHQL_DEFAULT_FIELD_COMPLEXITY").pipe(
44
+ Config.withDefault(1)
45
+ ),
46
+ cacheControlEnabled: Config.boolean("GRAPHQL_CACHE_CONTROL_ENABLED").pipe(
47
+ Config.withDefault(false)
48
+ ),
49
+ cacheControlDefaultMaxAge: Config.number("GRAPHQL_CACHE_CONTROL_DEFAULT_MAX_AGE").pipe(
50
+ Config.withDefault(0)
51
+ ),
52
+ cacheControlDefaultScope: Config.string("GRAPHQL_CACHE_CONTROL_DEFAULT_SCOPE").pipe(
53
+ Config.withDefault("PUBLIC")
54
+ )
55
+ }).pipe(
56
+ Config.map(
57
+ ({
58
+ path,
59
+ introspection,
60
+ graphiqlEnabled,
61
+ graphiqlPath,
62
+ graphiqlEndpoint,
63
+ maxDepth,
64
+ maxComplexity,
65
+ maxAliases,
66
+ maxFields,
67
+ defaultFieldComplexity,
68
+ cacheControlEnabled,
69
+ cacheControlDefaultMaxAge,
70
+ cacheControlDefaultScope
71
+ }) => {
72
+ const hasComplexity = Option.isSome(maxDepth) || Option.isSome(maxComplexity) || Option.isSome(maxAliases) || Option.isSome(maxFields);
73
+ return {
74
+ path,
75
+ introspection,
76
+ graphiql: graphiqlEnabled ? {
77
+ path: graphiqlPath,
78
+ endpoint: Option.isSome(graphiqlEndpoint) ? graphiqlEndpoint.value : path
79
+ } : false,
80
+ complexity: hasComplexity ? {
81
+ maxDepth: Option.getOrUndefined(maxDepth),
82
+ maxComplexity: Option.getOrUndefined(maxComplexity),
83
+ maxAliases: Option.getOrUndefined(maxAliases),
84
+ maxFields: Option.getOrUndefined(maxFields),
85
+ defaultFieldComplexity
86
+ } : void 0,
87
+ cacheControl: cacheControlEnabled ? {
88
+ enabled: true,
89
+ defaultMaxAge: cacheControlDefaultMaxAge,
90
+ defaultScope: cacheControlDefaultScope === "PRIVATE" ? "PRIVATE" : "PUBLIC",
91
+ calculateHttpHeaders: true
92
+ } : void 0
93
+ };
94
+ }
95
+ )
96
+ );
97
+
98
+ // src/server/graphiql.ts
99
+ var graphiqlHtml = (endpoint, subscriptionEndpoint) => `<!DOCTYPE html>
100
+ <html lang="en">
101
+ <head>
102
+ <meta charset="utf-8" />
103
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
104
+ <title>GraphiQL</title>
105
+ <link
106
+ rel="stylesheet"
107
+ href="https://unpkg.com/graphiql@3/graphiql.min.css"
108
+ />
109
+ </head>
110
+ <body style="margin: 0; overflow: hidden;">
111
+ <div id="graphiql" style="height: 100vh;"></div>
112
+ <script
113
+ crossorigin
114
+ src="https://unpkg.com/react@18/umd/react.production.min.js"
115
+ ></script>
116
+ <script
117
+ crossorigin
118
+ src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"
119
+ ></script>
120
+ <script
121
+ crossorigin
122
+ src="https://unpkg.com/graphiql@3/graphiql.min.js"
123
+ ></script>
124
+ <script>
125
+ const fetcher = GraphiQL.createFetcher({
126
+ url: ${JSON.stringify(endpoint)},
127
+ subscriptionUrl: ${JSON.stringify(subscriptionEndpoint ?? endpoint)},
128
+ });
129
+ ReactDOM.createRoot(document.getElementById('graphiql')).render(
130
+ React.createElement(GraphiQL, { fetcher })
131
+ );
132
+ </script>
133
+ </body>
134
+ </html>`;
135
+ var ComplexityLimitExceededError = class extends Data.TaggedError("ComplexityLimitExceededError") {
136
+ };
137
+ var ComplexityAnalysisError = class extends Data.TaggedError("ComplexityAnalysisError") {
138
+ };
139
+ var defaultComplexityCalculator = (defaultCost = 1) => {
140
+ return (info) => Effect.try({
141
+ try: () => {
142
+ const fragments = /* @__PURE__ */ new Map();
143
+ for (const definition of info.document.definitions) {
144
+ if (definition.kind === Kind.FRAGMENT_DEFINITION) {
145
+ fragments.set(definition.name.value, definition);
146
+ }
147
+ }
148
+ const rootType = getRootType(info.schema, info.operation.operation);
149
+ if (!rootType) {
150
+ throw new Error(`No root type found for operation: ${info.operation.operation}`);
151
+ }
152
+ const result = analyzeSelectionSet(
153
+ info.operation.selectionSet,
154
+ rootType,
155
+ info.schema,
156
+ fragments,
157
+ info.fieldComplexities,
158
+ info.variables ?? {},
159
+ defaultCost,
160
+ 1,
161
+ // Starting depth
162
+ /* @__PURE__ */ new Set()
163
+ // Visited fragments to prevent infinite loops
164
+ );
165
+ return result;
166
+ },
167
+ catch: (error) => new ComplexityAnalysisError({
168
+ message: `Failed to analyze query complexity: ${error}`,
169
+ cause: error
170
+ })
171
+ });
172
+ };
173
+ function getRootType(schema, operation) {
174
+ switch (operation) {
175
+ case "query":
176
+ return schema.getQueryType() ?? null;
177
+ case "mutation":
178
+ return schema.getMutationType() ?? null;
179
+ case "subscription":
180
+ return schema.getSubscriptionType() ?? null;
181
+ }
182
+ }
183
+ function getNamedType(type) {
184
+ if (type instanceof GraphQLNonNull || type instanceof GraphQLList) {
185
+ return getNamedType(type.ofType);
186
+ }
187
+ if (type instanceof GraphQLObjectType) {
188
+ return type;
189
+ }
190
+ return null;
191
+ }
192
+ function accumulateResult(acc, result) {
193
+ acc.maxDepth = Math.max(acc.maxDepth, result.depth);
194
+ acc.complexity += result.complexity;
195
+ acc.fieldCount += result.fieldCount;
196
+ acc.aliasCount += result.aliasCount;
197
+ }
198
+ function analyzeSelectionSet(selectionSet, parentType, schema, fragments, fieldComplexities, variables, defaultCost, currentDepth, visitedFragments) {
199
+ const ctx = { schema, fragments, fieldComplexities, variables, defaultCost };
200
+ const acc = { maxDepth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
201
+ for (const selection of selectionSet.selections) {
202
+ const result = analyzeSelection(selection, parentType, ctx, currentDepth, visitedFragments);
203
+ accumulateResult(acc, result);
204
+ }
205
+ return {
206
+ depth: acc.maxDepth,
207
+ complexity: acc.complexity,
208
+ fieldCount: acc.fieldCount,
209
+ aliasCount: acc.aliasCount
210
+ };
211
+ }
212
+ function analyzeSelection(selection, parentType, ctx, currentDepth, visitedFragments) {
213
+ switch (selection.kind) {
214
+ case Kind.FIELD:
215
+ return analyzeField(selection, parentType, ctx, currentDepth, visitedFragments);
216
+ case Kind.FRAGMENT_SPREAD:
217
+ return analyzeFragmentSpread(selection, ctx, currentDepth, visitedFragments);
218
+ case Kind.INLINE_FRAGMENT:
219
+ return analyzeInlineFragment(selection, parentType, ctx, currentDepth, visitedFragments);
220
+ }
221
+ }
222
+ function analyzeField(field, parentType, ctx, currentDepth, visitedFragments) {
223
+ const fieldName = field.name.value;
224
+ const aliasCount = field.alias ? 1 : 0;
225
+ if (fieldName.startsWith("__")) {
226
+ return { depth: currentDepth, complexity: 0, fieldCount: 1, aliasCount };
227
+ }
228
+ const schemaField = parentType.getFields()[fieldName];
229
+ if (!schemaField) {
230
+ return { depth: currentDepth, complexity: ctx.defaultCost, fieldCount: 1, aliasCount };
231
+ }
232
+ const args = resolveFieldArguments(field, ctx.variables);
233
+ const complexityKey = `${parentType.name}.${fieldName}`;
234
+ const fieldComplexity = ctx.fieldComplexities.get(complexityKey);
235
+ const cost = fieldComplexity !== void 0 ? typeof fieldComplexity === "function" ? fieldComplexity(args) : fieldComplexity : ctx.defaultCost;
236
+ if (field.selectionSet) {
237
+ const fieldType = getNamedType(schemaField.type);
238
+ if (fieldType) {
239
+ const nestedResult = analyzeSelectionSet(
240
+ field.selectionSet,
241
+ fieldType,
242
+ ctx.schema,
243
+ ctx.fragments,
244
+ ctx.fieldComplexities,
245
+ ctx.variables,
246
+ ctx.defaultCost,
247
+ currentDepth + 1,
248
+ visitedFragments
249
+ );
250
+ return {
251
+ depth: nestedResult.depth,
252
+ complexity: cost + nestedResult.complexity,
253
+ fieldCount: 1 + nestedResult.fieldCount,
254
+ aliasCount: aliasCount + nestedResult.aliasCount
255
+ };
256
+ }
257
+ }
258
+ return { depth: currentDepth, complexity: cost, fieldCount: 1, aliasCount };
259
+ }
260
+ function analyzeFragmentSpread(spread, ctx, currentDepth, visitedFragments) {
261
+ const fragmentName = spread.name.value;
262
+ if (visitedFragments.has(fragmentName)) {
263
+ return { depth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
264
+ }
265
+ const fragment = ctx.fragments.get(fragmentName);
266
+ if (!fragment) {
267
+ return { depth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
268
+ }
269
+ const fragmentType = ctx.schema.getType(fragment.typeCondition.name.value);
270
+ if (!(fragmentType instanceof GraphQLObjectType)) {
271
+ return { depth: currentDepth, complexity: 0, fieldCount: 0, aliasCount: 0 };
272
+ }
273
+ const newVisited = new Set(visitedFragments);
274
+ newVisited.add(fragmentName);
275
+ return analyzeSelectionSet(
276
+ fragment.selectionSet,
277
+ fragmentType,
278
+ ctx.schema,
279
+ ctx.fragments,
280
+ ctx.fieldComplexities,
281
+ ctx.variables,
282
+ ctx.defaultCost,
283
+ currentDepth,
284
+ newVisited
285
+ );
286
+ }
287
+ function analyzeInlineFragment(fragment, parentType, ctx, currentDepth, visitedFragments) {
288
+ let targetType = parentType;
289
+ if (fragment.typeCondition) {
290
+ const conditionType = ctx.schema.getType(fragment.typeCondition.name.value);
291
+ if (conditionType instanceof GraphQLObjectType) {
292
+ targetType = conditionType;
293
+ }
294
+ }
295
+ return analyzeSelectionSet(
296
+ fragment.selectionSet,
297
+ targetType,
298
+ ctx.schema,
299
+ ctx.fragments,
300
+ ctx.fieldComplexities,
301
+ ctx.variables,
302
+ ctx.defaultCost,
303
+ currentDepth,
304
+ visitedFragments
305
+ );
306
+ }
307
+ function resolveFieldArguments(field, variables) {
308
+ const args = {};
309
+ if (!field.arguments) {
310
+ return args;
311
+ }
312
+ for (const arg of field.arguments) {
313
+ const value = arg.value;
314
+ switch (value.kind) {
315
+ case Kind.VARIABLE:
316
+ args[arg.name.value] = variables[value.name.value];
317
+ break;
318
+ case Kind.INT:
319
+ args[arg.name.value] = parseInt(value.value, 10);
320
+ break;
321
+ case Kind.FLOAT:
322
+ args[arg.name.value] = parseFloat(value.value);
323
+ break;
324
+ case Kind.STRING:
325
+ args[arg.name.value] = value.value;
326
+ break;
327
+ case Kind.BOOLEAN:
328
+ args[arg.name.value] = value.value;
329
+ break;
330
+ case Kind.NULL:
331
+ args[arg.name.value] = null;
332
+ break;
333
+ case Kind.ENUM:
334
+ args[arg.name.value] = value.value;
335
+ break;
336
+ case Kind.LIST:
337
+ args[arg.name.value] = [];
338
+ break;
339
+ case Kind.OBJECT:
340
+ args[arg.name.value] = {};
341
+ break;
342
+ }
343
+ }
344
+ return args;
345
+ }
346
+ var validateComplexity = (query, operationName, variables, schema, fieldComplexities, config) => Effect.gen(function* () {
347
+ const document = yield* Effect.try({
348
+ try: () => parse(query),
349
+ catch: (error) => new ComplexityAnalysisError({
350
+ message: `Failed to parse query: ${error}`,
351
+ cause: error
352
+ })
353
+ });
354
+ const operation = yield* Effect.try({
355
+ try: () => {
356
+ const operations = document.definitions.filter(
357
+ (d) => d.kind === Kind.OPERATION_DEFINITION
358
+ );
359
+ if (operations.length === 0) {
360
+ throw new Error("No operation found in query");
361
+ }
362
+ if (operationName) {
363
+ const op = operations.find((o) => o.name?.value === operationName);
364
+ if (!op) {
365
+ throw new Error(`Operation "${operationName}" not found`);
366
+ }
367
+ return op;
368
+ }
369
+ if (operations.length > 1) {
370
+ throw new Error("Multiple operations found - operationName required");
371
+ }
372
+ return operations[0];
373
+ },
374
+ catch: (error) => new ComplexityAnalysisError({
375
+ message: String(error),
376
+ cause: error
377
+ })
378
+ });
379
+ const calculator = config.calculator ?? defaultComplexityCalculator(config.defaultFieldComplexity ?? 1);
380
+ const result = yield* calculator({
381
+ document,
382
+ operation,
383
+ variables,
384
+ schema,
385
+ fieldComplexities
386
+ });
387
+ const checkLimit = (limitType, limit, actual) => Effect.gen(function* () {
388
+ if (limit !== void 0 && actual > limit) {
389
+ const exceededInfo = {
390
+ result,
391
+ exceededLimit: limitType,
392
+ limit,
393
+ actual,
394
+ query,
395
+ operationName
396
+ };
397
+ if (config.onExceeded) {
398
+ yield* config.onExceeded(exceededInfo);
399
+ }
400
+ yield* Effect.fail(
401
+ new ComplexityLimitExceededError({
402
+ message: `Query ${limitType} of ${actual} exceeds maximum allowed ${limitType} of ${limit}`,
403
+ limit,
404
+ actual,
405
+ limitType
406
+ })
407
+ );
408
+ }
409
+ });
410
+ yield* checkLimit("depth", config.maxDepth, result.depth);
411
+ yield* checkLimit("complexity", config.maxComplexity, result.complexity);
412
+ yield* checkLimit("aliases", config.maxAliases, result.aliasCount);
413
+ yield* checkLimit("fields", config.maxFields, result.fieldCount);
414
+ return result;
415
+ });
416
+ var ComplexityConfigFromEnv = Config.all({
417
+ maxDepth: Config.number("GRAPHQL_MAX_DEPTH").pipe(Config.option),
418
+ maxComplexity: Config.number("GRAPHQL_MAX_COMPLEXITY").pipe(Config.option),
419
+ maxAliases: Config.number("GRAPHQL_MAX_ALIASES").pipe(Config.option),
420
+ maxFields: Config.number("GRAPHQL_MAX_FIELDS").pipe(Config.option),
421
+ defaultFieldComplexity: Config.number("GRAPHQL_DEFAULT_FIELD_COMPLEXITY").pipe(
422
+ Config.withDefault(1)
423
+ )
424
+ }).pipe(
425
+ Config.map(({ maxDepth, maxComplexity, maxAliases, maxFields, defaultFieldComplexity }) => ({
426
+ maxDepth: Option.getOrUndefined(maxDepth),
427
+ maxComplexity: Option.getOrUndefined(maxComplexity),
428
+ maxAliases: Option.getOrUndefined(maxAliases),
429
+ maxFields: Option.getOrUndefined(maxFields),
430
+ defaultFieldComplexity
431
+ }))
432
+ );
433
+ var depthOnlyCalculator = (info) => Effect.try({
434
+ try: () => {
435
+ const fragments = /* @__PURE__ */ new Map();
436
+ for (const definition of info.document.definitions) {
437
+ if (definition.kind === Kind.FRAGMENT_DEFINITION) {
438
+ fragments.set(definition.name.value, definition);
439
+ }
440
+ }
441
+ const depth = calculateMaxDepth(info.operation.selectionSet, fragments, 1, /* @__PURE__ */ new Set());
442
+ return {
443
+ depth,
444
+ complexity: 0,
445
+ fieldCount: 0,
446
+ aliasCount: 0
447
+ };
448
+ },
449
+ catch: (error) => new ComplexityAnalysisError({
450
+ message: `Failed to analyze query depth: ${error}`,
451
+ cause: error
452
+ })
453
+ });
454
+ function calculateMaxDepth(selectionSet, fragments, currentDepth, visitedFragments) {
455
+ let maxDepth = currentDepth;
456
+ for (const selection of selectionSet.selections) {
457
+ switch (selection.kind) {
458
+ case Kind.FIELD:
459
+ if (selection.selectionSet) {
460
+ const nestedDepth = calculateMaxDepth(
461
+ selection.selectionSet,
462
+ fragments,
463
+ currentDepth + 1,
464
+ visitedFragments
465
+ );
466
+ maxDepth = Math.max(maxDepth, nestedDepth);
467
+ }
468
+ break;
469
+ case Kind.FRAGMENT_SPREAD: {
470
+ const fragmentName = selection.name.value;
471
+ if (!visitedFragments.has(fragmentName)) {
472
+ const fragment = fragments.get(fragmentName);
473
+ if (fragment) {
474
+ const newVisited = new Set(visitedFragments);
475
+ newVisited.add(fragmentName);
476
+ const fragmentDepth = calculateMaxDepth(
477
+ fragment.selectionSet,
478
+ fragments,
479
+ currentDepth,
480
+ newVisited
481
+ );
482
+ maxDepth = Math.max(maxDepth, fragmentDepth);
483
+ }
484
+ }
485
+ break;
486
+ }
487
+ case Kind.INLINE_FRAGMENT: {
488
+ const inlineDepth = calculateMaxDepth(
489
+ selection.selectionSet,
490
+ fragments,
491
+ currentDepth,
492
+ visitedFragments
493
+ );
494
+ maxDepth = Math.max(maxDepth, inlineDepth);
495
+ break;
496
+ }
497
+ }
498
+ }
499
+ return maxDepth;
500
+ }
501
+ var combineCalculators = (...calculators) => {
502
+ return (info) => Effect.gen(function* () {
503
+ let maxDepth = 0;
504
+ let maxComplexity = 0;
505
+ let maxFieldCount = 0;
506
+ let maxAliasCount = 0;
507
+ for (const calculator of calculators) {
508
+ const result = yield* calculator(info);
509
+ maxDepth = Math.max(maxDepth, result.depth);
510
+ maxComplexity = Math.max(maxComplexity, result.complexity);
511
+ maxFieldCount = Math.max(maxFieldCount, result.fieldCount);
512
+ maxAliasCount = Math.max(maxAliasCount, result.aliasCount);
513
+ }
514
+ return {
515
+ depth: maxDepth,
516
+ complexity: maxComplexity,
517
+ fieldCount: maxFieldCount,
518
+ aliasCount: maxAliasCount
519
+ };
520
+ });
521
+ };
522
+ var computeCachePolicy = (info) => Effect.sync(() => {
523
+ const fragments = /* @__PURE__ */ new Map();
524
+ for (const definition of info.document.definitions) {
525
+ if (definition.kind === Kind.FRAGMENT_DEFINITION) {
526
+ fragments.set(definition.name.value, definition);
527
+ }
528
+ }
529
+ const rootType = getRootType2(info.schema, info.operation.operation);
530
+ if (!rootType) {
531
+ return { maxAge: 0, scope: "PUBLIC" };
532
+ }
533
+ const defaultMaxAge = info.config.defaultMaxAge ?? 0;
534
+ const defaultScope = info.config.defaultScope ?? "PUBLIC";
535
+ const result = analyzeSelectionSet2(
536
+ info.operation.selectionSet,
537
+ rootType,
538
+ info.schema,
539
+ fragments,
540
+ info.cacheHints,
541
+ defaultMaxAge,
542
+ defaultScope,
543
+ void 0,
544
+ // No parent maxAge for root
545
+ /* @__PURE__ */ new Set()
546
+ );
547
+ return result;
548
+ });
549
+ var computeCachePolicyFromQuery = (query, operationName, schema, cacheHints, config = {}) => Effect.gen(function* () {
550
+ const document = yield* Effect.try({
551
+ try: () => parse(query),
552
+ catch: (error) => new Error(`Failed to parse query: ${error}`)
553
+ });
554
+ const operation = yield* Effect.try({
555
+ try: () => {
556
+ const operations = document.definitions.filter(
557
+ (d) => d.kind === Kind.OPERATION_DEFINITION
558
+ );
559
+ if (operations.length === 0) {
560
+ throw new Error("No operation found in query");
561
+ }
562
+ if (operationName) {
563
+ const op = operations.find((o) => o.name?.value === operationName);
564
+ if (!op) {
565
+ throw new Error(`Operation "${operationName}" not found`);
566
+ }
567
+ return op;
568
+ }
569
+ if (operations.length > 1) {
570
+ throw new Error("Multiple operations found - operationName required");
571
+ }
572
+ return operations[0];
573
+ },
574
+ catch: (error) => error
575
+ });
576
+ return yield* computeCachePolicy({
577
+ document,
578
+ operation,
579
+ schema,
580
+ cacheHints,
581
+ config
582
+ });
583
+ });
584
+ var toCacheControlHeader = (policy) => {
585
+ if (policy.maxAge === 0) {
586
+ return "no-store";
587
+ }
588
+ const directives = [];
589
+ directives.push(policy.scope === "PRIVATE" ? "private" : "public");
590
+ directives.push(`max-age=${policy.maxAge}`);
591
+ return directives.join(", ");
592
+ };
593
+ function getRootType2(schema, operation) {
594
+ switch (operation) {
595
+ case "query":
596
+ return schema.getQueryType() ?? null;
597
+ case "mutation":
598
+ return schema.getMutationType() ?? null;
599
+ case "subscription":
600
+ return schema.getSubscriptionType() ?? null;
601
+ }
602
+ }
603
+ function getNamedType2(type) {
604
+ if (type instanceof GraphQLNonNull || type instanceof GraphQLList) {
605
+ return getNamedType2(type.ofType);
606
+ }
607
+ if (type instanceof GraphQLObjectType || type instanceof GraphQLScalarType || type instanceof GraphQLEnumType) {
608
+ return type;
609
+ }
610
+ return null;
611
+ }
612
+ function isLeafType(type) {
613
+ const namedType = getNamedType2(type);
614
+ return namedType instanceof GraphQLScalarType || namedType instanceof GraphQLEnumType;
615
+ }
616
+ function aggregatePolicy(acc, policy) {
617
+ if (acc.minMaxAge === void 0) {
618
+ acc.minMaxAge = policy.maxAge;
619
+ } else {
620
+ acc.minMaxAge = Math.min(acc.minMaxAge, policy.maxAge);
621
+ }
622
+ if (policy.scope === "PRIVATE") {
623
+ acc.hasPrivate = true;
624
+ }
625
+ }
626
+ function analyzeFragmentSpread2(fragmentName, ctx, parentMaxAge, visitedFragments) {
627
+ if (visitedFragments.has(fragmentName)) {
628
+ return void 0;
629
+ }
630
+ const fragment = ctx.fragments.get(fragmentName);
631
+ if (!fragment) {
632
+ return void 0;
633
+ }
634
+ const fragmentType = ctx.schema.getType(fragment.typeCondition.name.value);
635
+ if (!(fragmentType instanceof GraphQLObjectType)) {
636
+ return void 0;
637
+ }
638
+ const newVisited = new Set(visitedFragments);
639
+ newVisited.add(fragmentName);
640
+ return analyzeSelectionSet2(fragment.selectionSet, fragmentType, ctx, parentMaxAge, newVisited);
641
+ }
642
+ function analyzeInlineFragment2(selection, parentType, ctx, parentMaxAge, visitedFragments) {
643
+ let targetType = parentType;
644
+ if (selection.typeCondition) {
645
+ const conditionType = ctx.schema.getType(selection.typeCondition.name.value);
646
+ if (conditionType instanceof GraphQLObjectType) {
647
+ targetType = conditionType;
648
+ }
649
+ }
650
+ return analyzeSelectionSet2(
651
+ selection.selectionSet,
652
+ targetType,
653
+ ctx,
654
+ parentMaxAge,
655
+ visitedFragments
656
+ );
657
+ }
658
+ function lookupEffectiveCacheHint(parentTypeName, fieldName, returnType, cacheHints) {
659
+ const fieldKey = `${parentTypeName}.${fieldName}`;
660
+ const fieldHint = cacheHints.get(fieldKey);
661
+ if (fieldHint) return fieldHint;
662
+ const namedType = getNamedType2(returnType);
663
+ return namedType ? cacheHints.get(namedType.name) : void 0;
664
+ }
665
+ function computeFieldMaxAge(hint, fieldType, parentMaxAge, defaultMaxAge) {
666
+ if (hint) {
667
+ if (hint.inheritMaxAge && parentMaxAge !== void 0) {
668
+ return parentMaxAge;
669
+ }
670
+ if (hint.maxAge !== void 0) {
671
+ return hint.maxAge;
672
+ }
673
+ }
674
+ if (isLeafType(fieldType) && parentMaxAge !== void 0) {
675
+ return parentMaxAge;
676
+ }
677
+ return defaultMaxAge;
678
+ }
679
+ function analyzeSelectionSet2(selectionSet, parentType, schemaOrCtx, fragmentsOrParentMaxAge, cacheHintsOrVisited, defaultMaxAge, defaultScope, parentMaxAge, visitedFragments) {
680
+ let ctx;
681
+ let actualParentMaxAge;
682
+ let actualVisitedFragments;
683
+ if (schemaOrCtx instanceof GraphQLSchema) {
684
+ ctx = {
685
+ schema: schemaOrCtx,
686
+ fragments: fragmentsOrParentMaxAge,
687
+ cacheHints: cacheHintsOrVisited,
688
+ defaultMaxAge,
689
+ defaultScope
690
+ };
691
+ actualParentMaxAge = parentMaxAge;
692
+ actualVisitedFragments = visitedFragments;
693
+ } else {
694
+ ctx = schemaOrCtx;
695
+ actualParentMaxAge = fragmentsOrParentMaxAge;
696
+ actualVisitedFragments = cacheHintsOrVisited;
697
+ }
698
+ const acc = { minMaxAge: void 0, hasPrivate: false };
699
+ for (const selection of selectionSet.selections) {
700
+ let fieldPolicy;
701
+ switch (selection.kind) {
702
+ case Kind.FIELD:
703
+ fieldPolicy = analyzeField2(
704
+ selection,
705
+ parentType,
706
+ ctx,
707
+ actualParentMaxAge,
708
+ actualVisitedFragments
709
+ );
710
+ break;
711
+ case Kind.FRAGMENT_SPREAD:
712
+ fieldPolicy = analyzeFragmentSpread2(
713
+ selection.name.value,
714
+ ctx,
715
+ actualParentMaxAge,
716
+ actualVisitedFragments
717
+ );
718
+ break;
719
+ case Kind.INLINE_FRAGMENT:
720
+ fieldPolicy = analyzeInlineFragment2(
721
+ selection,
722
+ parentType,
723
+ ctx,
724
+ actualParentMaxAge,
725
+ actualVisitedFragments
726
+ );
727
+ break;
728
+ }
729
+ if (fieldPolicy) {
730
+ aggregatePolicy(acc, fieldPolicy);
731
+ }
732
+ }
733
+ return {
734
+ maxAge: acc.minMaxAge ?? ctx.defaultMaxAge,
735
+ scope: acc.hasPrivate ? "PRIVATE" : ctx.defaultScope
736
+ };
737
+ }
738
+ function analyzeField2(field, parentType, ctx, parentMaxAge, visitedFragments) {
739
+ const fieldName = field.name.value;
740
+ if (fieldName.startsWith("__")) {
741
+ return { maxAge: Infinity, scope: "PUBLIC" };
742
+ }
743
+ const schemaField = parentType.getFields()[fieldName];
744
+ if (!schemaField) {
745
+ return { maxAge: ctx.defaultMaxAge, scope: ctx.defaultScope };
746
+ }
747
+ const effectiveHint = lookupEffectiveCacheHint(
748
+ parentType.name,
749
+ fieldName,
750
+ schemaField.type,
751
+ ctx.cacheHints
752
+ );
753
+ const fieldMaxAge = computeFieldMaxAge(
754
+ effectiveHint,
755
+ schemaField.type,
756
+ parentMaxAge,
757
+ ctx.defaultMaxAge
758
+ );
759
+ const fieldScope = effectiveHint?.scope ?? ctx.defaultScope;
760
+ const namedType = getNamedType2(schemaField.type);
761
+ if (field.selectionSet && namedType instanceof GraphQLObjectType) {
762
+ const nestedPolicy = analyzeSelectionSet2(
763
+ field.selectionSet,
764
+ namedType,
765
+ ctx,
766
+ fieldMaxAge,
767
+ visitedFragments
768
+ );
769
+ return {
770
+ maxAge: Math.min(fieldMaxAge, nestedPolicy.maxAge),
771
+ scope: fieldScope === "PRIVATE" || nestedPolicy.scope === "PRIVATE" ? "PRIVATE" : "PUBLIC"
772
+ };
773
+ }
774
+ return { maxAge: fieldMaxAge, scope: fieldScope };
775
+ }
776
+ var CacheControlConfigFromEnv = Config.all({
777
+ enabled: Config.boolean("GRAPHQL_CACHE_CONTROL_ENABLED").pipe(Config.withDefault(true)),
778
+ defaultMaxAge: Config.number("GRAPHQL_CACHE_CONTROL_DEFAULT_MAX_AGE").pipe(Config.withDefault(0)),
779
+ defaultScope: Config.string("GRAPHQL_CACHE_CONTROL_DEFAULT_SCOPE").pipe(
780
+ Config.withDefault("PUBLIC"),
781
+ Config.map((s) => s === "PRIVATE" ? "PRIVATE" : "PUBLIC")
782
+ ),
783
+ calculateHttpHeaders: Config.boolean("GRAPHQL_CACHE_CONTROL_HTTP_HEADERS").pipe(
784
+ Config.withDefault(true)
785
+ )
786
+ });
787
+ var ExtensionsService = Context.GenericTag(
788
+ "@effect-gql/ExtensionsService"
789
+ );
790
+ function deepMerge(target, source) {
791
+ const result = { ...target };
792
+ for (const key of Object.keys(source)) {
793
+ const sourceValue = source[key];
794
+ const targetValue = result[key];
795
+ if (typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
796
+ result[key] = deepMerge(
797
+ targetValue,
798
+ sourceValue
799
+ );
800
+ } else {
801
+ result[key] = sourceValue;
802
+ }
803
+ }
804
+ return result;
805
+ }
806
+ var makeExtensionsService = () => Effect.gen(function* () {
807
+ const ref = yield* Ref.make({});
808
+ return ExtensionsService.of({
809
+ set: (key, value) => Ref.update(ref, (current) => ({ ...current, [key]: value })),
810
+ merge: (key, value) => Ref.update(ref, (current) => {
811
+ const existing = current[key];
812
+ if (typeof existing === "object" && existing !== null && !Array.isArray(existing)) {
813
+ return {
814
+ ...current,
815
+ [key]: deepMerge(existing, value)
816
+ };
817
+ }
818
+ return { ...current, [key]: value };
819
+ }),
820
+ get: () => Ref.get(ref)
821
+ });
822
+ });
823
+ var runExtensionHooks = (extensions, hookName, getHookEffect) => Effect.forEach(
824
+ extensions.filter((ext) => ext[hookName] !== void 0),
825
+ (ext) => getHookEffect(ext).pipe(
826
+ Effect.catchAllCause(
827
+ (cause) => Effect.logWarning(`Extension "${ext.name}" ${String(hookName)} hook failed`, cause)
828
+ )
829
+ ),
830
+ { discard: true }
831
+ );
832
+ var runParseHooks = (extensions, source, document) => runExtensionHooks(extensions, "onParse", (ext) => ext.onParse(source, document));
833
+ var runValidateHooks = (extensions, document, errors) => runExtensionHooks(extensions, "onValidate", (ext) => ext.onValidate(document, errors));
834
+ var runExecuteStartHooks = (extensions, args) => runExtensionHooks(extensions, "onExecuteStart", (ext) => ext.onExecuteStart(args));
835
+ var runExecuteEndHooks = (extensions, result) => runExtensionHooks(extensions, "onExecuteEnd", (ext) => ext.onExecuteEnd(result));
836
+
837
+ // src/server/router.ts
838
+ var defaultErrorHandler = (cause) => (process.env.NODE_ENV !== "production" ? Effect.logError("GraphQL error", cause) : Effect.void).pipe(
839
+ Effect.andThen(
840
+ HttpServerResponse.json(
841
+ {
842
+ errors: [
843
+ {
844
+ message: "An error occurred processing your request"
845
+ }
846
+ ]
847
+ },
848
+ { status: 500 }
849
+ ).pipe(Effect.orDie)
850
+ )
851
+ );
852
+ var GraphQLRequestBodySchema = Schema.Struct({
853
+ query: Schema.String,
854
+ variables: Schema.optionalWith(Schema.Record({ key: Schema.String, value: Schema.Unknown }), {
855
+ as: "Option"
856
+ }),
857
+ operationName: Schema.optionalWith(Schema.String, { as: "Option" })
858
+ });
859
+ var decodeRequestBody = HttpIncomingMessage.schemaBodyJson(GraphQLRequestBodySchema);
860
+ var parseGraphQLQuery = (query, extensionsService) => {
861
+ try {
862
+ const document = parse(query);
863
+ return Effect.succeed({ ok: true, document });
864
+ } catch (parseError) {
865
+ return extensionsService.get().pipe(
866
+ Effect.flatMap(
867
+ (extensionData) => HttpServerResponse.json({
868
+ errors: [{ message: String(parseError) }],
869
+ extensions: Object.keys(extensionData).length > 0 ? extensionData : void 0
870
+ }).pipe(
871
+ Effect.orDie,
872
+ Effect.map((response) => ({ ok: false, response }))
873
+ )
874
+ )
875
+ );
876
+ }
877
+ };
878
+ var runComplexityValidation = (body, schema, fieldComplexities, complexityConfig) => {
879
+ if (!complexityConfig) {
880
+ return Effect.void;
881
+ }
882
+ return validateComplexity(
883
+ body.query,
884
+ body.operationName,
885
+ body.variables,
886
+ schema,
887
+ fieldComplexities,
888
+ complexityConfig
889
+ ).pipe(
890
+ Effect.catchTag("ComplexityLimitExceededError", (error) => Effect.fail(error)),
891
+ Effect.catchTag(
892
+ "ComplexityAnalysisError",
893
+ (error) => Effect.logWarning("Complexity analysis failed", error)
894
+ )
895
+ );
896
+ };
897
+ var isPromiseLike = (value) => value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
898
+ var executeGraphQLQuery = (schema, document, variables, operationName, runtime) => {
899
+ const tryExecute = Effect.try({
900
+ try: () => execute({
901
+ schema,
902
+ document,
903
+ variableValues: variables,
904
+ operationName,
905
+ contextValue: { runtime }
906
+ }),
907
+ catch: (error) => new Error(String(error))
908
+ });
909
+ return tryExecute.pipe(
910
+ Effect.flatMap((executeResult) => {
911
+ if (isPromiseLike(executeResult)) {
912
+ return Effect.promise(() => executeResult);
913
+ }
914
+ return Effect.succeed(executeResult);
915
+ })
916
+ );
917
+ };
918
+ var computeCacheControlHeader = (document, operationName, schema, cacheHints, cacheControlConfig) => {
919
+ if (cacheControlConfig?.enabled === false || cacheControlConfig?.calculateHttpHeaders === false) {
920
+ return Effect.succeed(void 0);
921
+ }
922
+ const operations = document.definitions.filter(
923
+ (d) => d.kind === Kind.OPERATION_DEFINITION
924
+ );
925
+ const operation = operationName ? operations.find((o) => o.name?.value === operationName) : operations[0];
926
+ if (!operation || operation.operation === "mutation") {
927
+ return Effect.succeed(void 0);
928
+ }
929
+ return computeCachePolicy({
930
+ document,
931
+ operation,
932
+ schema,
933
+ cacheHints,
934
+ config: cacheControlConfig ?? {}
935
+ }).pipe(Effect.map(toCacheControlHeader));
936
+ };
937
+ var buildGraphQLResponse = (result, extensionData, cacheControlHeader) => {
938
+ const finalResult = Object.keys(extensionData).length > 0 ? {
939
+ ...result,
940
+ extensions: {
941
+ ...result.extensions,
942
+ ...extensionData
943
+ }
944
+ } : result;
945
+ const responseHeaders = cacheControlHeader ? { "cache-control": cacheControlHeader } : void 0;
946
+ return HttpServerResponse.json(finalResult, { headers: responseHeaders }).pipe(Effect.orDie);
947
+ };
948
+ var handleComplexityError = (error) => HttpServerResponse.json(
949
+ {
950
+ errors: [
951
+ {
952
+ message: error.message,
953
+ extensions: {
954
+ code: "COMPLEXITY_LIMIT_EXCEEDED",
955
+ limitType: error.limitType,
956
+ limit: error.limit,
957
+ actual: error.actual
958
+ }
959
+ }
960
+ ]
961
+ },
962
+ { status: 400 }
963
+ ).pipe(Effect.orDie);
964
+ var makeGraphQLRouter = (schema, layer, options = {}) => {
965
+ const resolvedConfig = normalizeConfig(options);
966
+ const fieldComplexities = options.fieldComplexities ?? /* @__PURE__ */ new Map();
967
+ const cacheHints = options.cacheHints ?? /* @__PURE__ */ new Map();
968
+ const extensions = options.extensions ?? [];
969
+ const errorHandler = options.errorHandler ?? defaultErrorHandler;
970
+ const graphqlHandler = Effect.gen(function* () {
971
+ const extensionsService = yield* makeExtensionsService();
972
+ const runtime = yield* Effect.runtime();
973
+ const request = yield* HttpServerRequest.HttpServerRequest;
974
+ const parsedBody = yield* decodeRequestBody(request);
975
+ const body = {
976
+ query: parsedBody.query,
977
+ variables: parsedBody.variables._tag === "Some" ? parsedBody.variables.value : void 0,
978
+ operationName: parsedBody.operationName._tag === "Some" ? parsedBody.operationName.value : void 0
979
+ };
980
+ const parseResult = yield* parseGraphQLQuery(body.query, extensionsService);
981
+ if (!parseResult.ok) {
982
+ return parseResult.response;
983
+ }
984
+ const document = parseResult.document;
985
+ yield* runParseHooks(extensions, body.query, document).pipe(
986
+ Effect.provideService(ExtensionsService, extensionsService)
987
+ );
988
+ const validationRules = resolvedConfig.introspection ? void 0 : specifiedRules.concat(NoSchemaIntrospectionCustomRule);
989
+ const validationErrors = validate(schema, document, validationRules);
990
+ yield* runValidateHooks(extensions, document, validationErrors).pipe(
991
+ Effect.provideService(ExtensionsService, extensionsService)
992
+ );
993
+ if (validationErrors.length > 0) {
994
+ const extensionData2 = yield* extensionsService.get();
995
+ return yield* HttpServerResponse.json(
996
+ {
997
+ errors: validationErrors.map((e) => ({
998
+ message: e.message,
999
+ locations: e.locations,
1000
+ path: e.path
1001
+ })),
1002
+ extensions: Object.keys(extensionData2).length > 0 ? extensionData2 : void 0
1003
+ },
1004
+ { status: 400 }
1005
+ );
1006
+ }
1007
+ yield* runComplexityValidation(body, schema, fieldComplexities, resolvedConfig.complexity);
1008
+ yield* runExecuteStartHooks(extensions, {
1009
+ source: body.query,
1010
+ document,
1011
+ variableValues: body.variables,
1012
+ operationName: body.operationName,
1013
+ schema,
1014
+ fieldComplexities
1015
+ }).pipe(Effect.provideService(ExtensionsService, extensionsService));
1016
+ const result = yield* executeGraphQLQuery(
1017
+ schema,
1018
+ document,
1019
+ body.variables,
1020
+ body.operationName,
1021
+ runtime
1022
+ );
1023
+ yield* runExecuteEndHooks(extensions, result).pipe(
1024
+ Effect.provideService(ExtensionsService, extensionsService)
1025
+ );
1026
+ const extensionData = yield* extensionsService.get();
1027
+ const cacheControlHeader = yield* computeCacheControlHeader(
1028
+ document,
1029
+ body.operationName,
1030
+ schema,
1031
+ cacheHints,
1032
+ resolvedConfig.cacheControl
1033
+ );
1034
+ return yield* buildGraphQLResponse(result, extensionData, cacheControlHeader);
1035
+ }).pipe(
1036
+ Effect.provide(layer),
1037
+ Effect.catchAll((error) => {
1038
+ if (error instanceof ComplexityLimitExceededError) {
1039
+ return handleComplexityError(error);
1040
+ }
1041
+ return Effect.fail(error);
1042
+ }),
1043
+ Effect.catchAllCause(errorHandler)
1044
+ );
1045
+ let router = HttpRouter.empty.pipe(
1046
+ HttpRouter.post(resolvedConfig.path, graphqlHandler)
1047
+ );
1048
+ if (resolvedConfig.graphiql) {
1049
+ const { path, endpoint, subscriptionEndpoint } = resolvedConfig.graphiql;
1050
+ router = router.pipe(
1051
+ HttpRouter.get(
1052
+ path,
1053
+ HttpServerResponse.html(graphiqlHtml(endpoint, subscriptionEndpoint))
1054
+ )
1055
+ );
1056
+ }
1057
+ return router;
1058
+ };
1059
+
1060
+ // src/server/schema-builder-extensions.ts
1061
+ var toRouter = (builder, layer, options) => {
1062
+ const schema = builder.buildSchema();
1063
+ const fieldComplexities = builder.getFieldComplexities();
1064
+ const cacheHints = builder.getCacheHints();
1065
+ return makeGraphQLRouter(schema, layer, { ...options, fieldComplexities, cacheHints });
1066
+ };
1067
+ var WebSocketError = class extends Data.TaggedError("WebSocketError") {
1068
+ };
1069
+ var createConnectionContext = (extra) => ({
1070
+ runtime: extra.runtime,
1071
+ connectionParams: extra.connectionParams,
1072
+ socket: extra.socket
1073
+ });
1074
+ var makeOnConnectHandler = (options) => {
1075
+ if (!options?.onConnect) return void 0;
1076
+ return async (ctx) => {
1077
+ const extra = ctx.extra;
1078
+ try {
1079
+ const result = await Runtime.runPromise(extra.runtime)(
1080
+ options.onConnect(ctx.connectionParams ?? {})
1081
+ );
1082
+ if (typeof result === "object" && result !== null) {
1083
+ Object.assign(extra.connectionParams, result);
1084
+ }
1085
+ return result !== false;
1086
+ } catch {
1087
+ return false;
1088
+ }
1089
+ };
1090
+ };
1091
+ var makeOnDisconnectHandler = (options) => {
1092
+ if (!options?.onDisconnect) return void 0;
1093
+ return async (ctx) => {
1094
+ const extra = ctx.extra;
1095
+ await Runtime.runPromise(extra.runtime)(
1096
+ options.onDisconnect(createConnectionContext(extra))
1097
+ ).catch(() => {
1098
+ });
1099
+ };
1100
+ };
1101
+ var makeOnSubscribeHandler = (options, schema, complexityConfig, fieldComplexities) => {
1102
+ return async (ctx, id, payload) => {
1103
+ const extra = ctx.extra;
1104
+ const connectionCtx = createConnectionContext(extra);
1105
+ if (complexityConfig) {
1106
+ const validationEffect = validateComplexity(
1107
+ payload.query,
1108
+ payload.operationName ?? void 0,
1109
+ payload.variables ?? void 0,
1110
+ schema,
1111
+ fieldComplexities,
1112
+ complexityConfig
1113
+ ).pipe(
1114
+ Effect.catchAll((error) => {
1115
+ if (error._tag === "ComplexityLimitExceededError") {
1116
+ throw new GraphQLError(error.message, {
1117
+ extensions: {
1118
+ code: "COMPLEXITY_LIMIT_EXCEEDED",
1119
+ limitType: error.limitType,
1120
+ limit: error.limit,
1121
+ actual: error.actual
1122
+ }
1123
+ });
1124
+ }
1125
+ return Effect.logWarning("Complexity analysis failed for subscription", error);
1126
+ })
1127
+ );
1128
+ await Effect.runPromise(validationEffect);
1129
+ }
1130
+ if (options?.onSubscribe) {
1131
+ await Runtime.runPromise(extra.runtime)(
1132
+ options.onSubscribe(connectionCtx, {
1133
+ id,
1134
+ payload: {
1135
+ query: payload.query,
1136
+ variables: payload.variables ?? void 0,
1137
+ operationName: payload.operationName ?? void 0,
1138
+ extensions: payload.extensions ?? void 0
1139
+ }
1140
+ })
1141
+ );
1142
+ }
1143
+ };
1144
+ };
1145
+ var makeOnCompleteHandler = (options) => {
1146
+ if (!options?.onComplete) return void 0;
1147
+ return async (ctx, id, _payload) => {
1148
+ const extra = ctx.extra;
1149
+ await Runtime.runPromise(extra.runtime)(
1150
+ options.onComplete(createConnectionContext(extra), { id })
1151
+ ).catch(() => {
1152
+ });
1153
+ };
1154
+ };
1155
+ var makeOnErrorHandler = (options) => {
1156
+ if (!options?.onError) return void 0;
1157
+ return async (ctx, _id, _payload, errors) => {
1158
+ const extra = ctx.extra;
1159
+ await Runtime.runPromise(extra.runtime)(
1160
+ options.onError(createConnectionContext(extra), errors)
1161
+ ).catch(() => {
1162
+ });
1163
+ };
1164
+ };
1165
+ var createGraphqlWsSocketAdapter = (socket, runtime) => {
1166
+ let messageCallback = null;
1167
+ return {
1168
+ adapter: {
1169
+ protocol: socket.protocol,
1170
+ send: (data) => Runtime.runPromise(runtime)(
1171
+ socket.send(data).pipe(Effect.catchAll((error) => Effect.logError("WebSocket send error", error)))
1172
+ ),
1173
+ close: (code, reason) => {
1174
+ Runtime.runPromise(runtime)(socket.close(code, reason)).catch(() => {
1175
+ });
1176
+ },
1177
+ onMessage: (cb) => {
1178
+ messageCallback = cb;
1179
+ },
1180
+ onPong: (_payload) => {
1181
+ }
1182
+ },
1183
+ dispatchMessage: async (message) => {
1184
+ if (messageCallback) {
1185
+ await messageCallback(message);
1186
+ }
1187
+ }
1188
+ };
1189
+ };
1190
+ var runConnectionLifecycle = (socket, wsServer, extra) => Effect.gen(function* () {
1191
+ const messageQueue = yield* Queue.unbounded();
1192
+ const closedDeferred = yield* Deferred.make();
1193
+ const messageFiber = yield* Effect.fork(
1194
+ Stream.runForEach(socket.messages, (msg) => Queue.offer(messageQueue, msg)).pipe(
1195
+ Effect.catchAll((error) => Deferred.fail(closedDeferred, error))
1196
+ )
1197
+ );
1198
+ const closeFiber = yield* Effect.fork(
1199
+ socket.closed.pipe(
1200
+ Effect.tap((event) => Deferred.succeed(closedDeferred, event)),
1201
+ Effect.catchAll((error) => Deferred.fail(closedDeferred, error))
1202
+ )
1203
+ );
1204
+ const { adapter, dispatchMessage } = createGraphqlWsSocketAdapter(socket, extra.runtime);
1205
+ const closedHandler = wsServer.opened(adapter, extra);
1206
+ const processMessagesFiber = yield* Effect.fork(
1207
+ Effect.gen(function* () {
1208
+ while (true) {
1209
+ const message = yield* Queue.take(messageQueue);
1210
+ yield* Effect.tryPromise({
1211
+ try: () => dispatchMessage(message),
1212
+ catch: (error) => error
1213
+ }).pipe(Effect.catchAll(() => Effect.void));
1214
+ }
1215
+ })
1216
+ );
1217
+ yield* Deferred.await(closedDeferred).pipe(
1218
+ Effect.catchAll(() => Effect.succeed({ code: 1e3, reason: "Error" }))
1219
+ );
1220
+ closedHandler(1e3, "Connection closed");
1221
+ yield* Fiber.interrupt(messageFiber);
1222
+ yield* Fiber.interrupt(closeFiber);
1223
+ yield* Fiber.interrupt(processMessagesFiber);
1224
+ yield* Queue.shutdown(messageQueue);
1225
+ }).pipe(
1226
+ Effect.catchAllCause(() => Effect.void),
1227
+ Effect.scoped
1228
+ );
1229
+ var makeGraphQLWSHandler = (schema, layer, options) => {
1230
+ const complexityConfig = options?.complexity;
1231
+ const fieldComplexities = options?.fieldComplexities ?? /* @__PURE__ */ new Map();
1232
+ const serverOptions = {
1233
+ schema,
1234
+ context: async (ctx) => {
1235
+ const extra = ctx.extra;
1236
+ return {
1237
+ runtime: extra.runtime,
1238
+ ...extra.connectionParams
1239
+ };
1240
+ },
1241
+ subscribe: async (args) => subscribe(args),
1242
+ onConnect: makeOnConnectHandler(options),
1243
+ onDisconnect: makeOnDisconnectHandler(options),
1244
+ onSubscribe: makeOnSubscribeHandler(options, schema, complexityConfig, fieldComplexities),
1245
+ onComplete: makeOnCompleteHandler(options),
1246
+ onError: makeOnErrorHandler(options)
1247
+ };
1248
+ const wsServer = makeServer(serverOptions);
1249
+ return (socket) => Effect.gen(function* () {
1250
+ const runtime = yield* Effect.provide(Effect.runtime(), layer);
1251
+ const extra = {
1252
+ socket,
1253
+ runtime,
1254
+ connectionParams: {}
1255
+ };
1256
+ yield* runConnectionLifecycle(socket, wsServer, extra);
1257
+ }).pipe(
1258
+ Effect.catchAllCause(() => Effect.void),
1259
+ Effect.scoped
1260
+ );
1261
+ };
1262
+ var WS_CLOSED = 3;
1263
+ var toEffectWebSocketFromWs = (ws) => {
1264
+ const messagesEffect = Effect.gen(function* () {
1265
+ const queue = yield* Queue.unbounded();
1266
+ const closed = yield* Deferred.make();
1267
+ ws.on("message", (data) => {
1268
+ const message = data.toString();
1269
+ Effect.runPromise(Queue.offer(queue, message)).catch(() => {
1270
+ });
1271
+ });
1272
+ ws.on("error", (error) => {
1273
+ Effect.runPromise(Deferred.fail(closed, new WebSocketError({ cause: error }))).catch(() => {
1274
+ });
1275
+ });
1276
+ ws.on("close", (code, reason) => {
1277
+ Effect.runPromise(
1278
+ Queue.shutdown(queue).pipe(
1279
+ Effect.andThen(Deferred.succeed(closed, { code, reason: reason.toString() }))
1280
+ )
1281
+ ).catch(() => {
1282
+ });
1283
+ });
1284
+ return { queue, closed };
1285
+ });
1286
+ const messages = Stream.unwrap(
1287
+ messagesEffect.pipe(
1288
+ Effect.map(({ queue }) => Stream.fromQueue(queue).pipe(Stream.catchAll(() => Stream.empty)))
1289
+ )
1290
+ );
1291
+ return {
1292
+ protocol: ws.protocol || "graphql-transport-ws",
1293
+ send: (data) => Effect.async((resume) => {
1294
+ ws.send(data, (error) => {
1295
+ if (error) {
1296
+ resume(Effect.fail(new WebSocketError({ cause: error })));
1297
+ } else {
1298
+ resume(Effect.succeed(void 0));
1299
+ }
1300
+ });
1301
+ }),
1302
+ close: (code, reason) => Effect.sync(() => {
1303
+ ws.close(code ?? 1e3, reason ?? "");
1304
+ }),
1305
+ messages,
1306
+ closed: Effect.async((resume) => {
1307
+ if (ws.readyState === WS_CLOSED) {
1308
+ resume(Effect.succeed({ code: 1e3, reason: "" }));
1309
+ return;
1310
+ }
1311
+ const onClose = (code, reason) => {
1312
+ cleanup();
1313
+ resume(Effect.succeed({ code, reason: reason.toString() }));
1314
+ };
1315
+ const onError = (error) => {
1316
+ cleanup();
1317
+ resume(Effect.fail(new WebSocketError({ cause: error })));
1318
+ };
1319
+ const cleanup = () => {
1320
+ ws.removeListener("close", onClose);
1321
+ ws.removeListener("error", onError);
1322
+ };
1323
+ ws.on("close", onClose);
1324
+ ws.on("error", onError);
1325
+ return Effect.sync(cleanup);
1326
+ })
1327
+ };
1328
+ };
1329
+ var SSE_HEADERS = {
1330
+ "Content-Type": "text/event-stream",
1331
+ "Cache-Control": "no-cache",
1332
+ Connection: "keep-alive",
1333
+ "X-Accel-Buffering": "no"
1334
+ // Disable nginx buffering
1335
+ };
1336
+ var SSEError = class extends Data.TaggedError("SSEError") {
1337
+ };
1338
+ var formatNextEvent = (result) => ({
1339
+ event: "next",
1340
+ data: JSON.stringify(result)
1341
+ });
1342
+ var formatErrorEvent = (errors) => ({
1343
+ event: "error",
1344
+ data: JSON.stringify({ errors })
1345
+ });
1346
+ var formatCompleteEvent = () => ({
1347
+ event: "complete",
1348
+ data: ""
1349
+ });
1350
+ var formatSSEMessage = (event) => {
1351
+ const lines = [`event: ${event.event}`];
1352
+ if (event.data) {
1353
+ lines.push(`data: ${event.data}`);
1354
+ }
1355
+ lines.push("", "");
1356
+ return lines.join("\n");
1357
+ };
1358
+ var makeSSESubscriptionStream = (schema, layer, request, headers, options) => {
1359
+ const complexityConfig = options?.complexity;
1360
+ const fieldComplexities = options?.fieldComplexities ?? /* @__PURE__ */ new Map();
1361
+ return Stream.unwrap(
1362
+ Effect.gen(function* () {
1363
+ const runtime = yield* Effect.provide(Effect.runtime(), layer);
1364
+ let connectionContext = {};
1365
+ if (options?.onConnect) {
1366
+ try {
1367
+ connectionContext = yield* Effect.provide(options.onConnect(request, headers), layer);
1368
+ } catch {
1369
+ return Stream.make(
1370
+ formatErrorEvent([
1371
+ new GraphQLError("Subscription connection rejected", {
1372
+ extensions: { code: "CONNECTION_REJECTED" }
1373
+ })
1374
+ ]),
1375
+ formatCompleteEvent()
1376
+ );
1377
+ }
1378
+ }
1379
+ let document;
1380
+ try {
1381
+ document = parse(request.query);
1382
+ } catch (syntaxError) {
1383
+ return Stream.make(formatErrorEvent([syntaxError]), formatCompleteEvent());
1384
+ }
1385
+ const validationErrors = validate(schema, document);
1386
+ if (validationErrors.length > 0) {
1387
+ return Stream.make(formatErrorEvent(validationErrors), formatCompleteEvent());
1388
+ }
1389
+ const operations = document.definitions.filter(
1390
+ (d) => d.kind === Kind.OPERATION_DEFINITION
1391
+ );
1392
+ const operation = request.operationName ? operations.find((o) => o.name?.value === request.operationName) : operations[0];
1393
+ if (!operation) {
1394
+ return Stream.make(
1395
+ formatErrorEvent([new GraphQLError("No operation found in query")]),
1396
+ formatCompleteEvent()
1397
+ );
1398
+ }
1399
+ if (operation.operation !== "subscription") {
1400
+ return Stream.make(
1401
+ formatErrorEvent([
1402
+ new GraphQLError(
1403
+ `SSE endpoint only supports subscriptions, received: ${operation.operation}`,
1404
+ { extensions: { code: "OPERATION_NOT_SUPPORTED" } }
1405
+ )
1406
+ ]),
1407
+ formatCompleteEvent()
1408
+ );
1409
+ }
1410
+ if (complexityConfig) {
1411
+ const complexityResult = yield* validateComplexity(
1412
+ request.query,
1413
+ request.operationName,
1414
+ request.variables,
1415
+ schema,
1416
+ fieldComplexities,
1417
+ complexityConfig
1418
+ ).pipe(
1419
+ Effect.map(() => null),
1420
+ Effect.catchAll((error) => {
1421
+ if (error._tag === "ComplexityLimitExceededError") {
1422
+ return Effect.succeed(
1423
+ new GraphQLError(error.message, {
1424
+ extensions: {
1425
+ code: "COMPLEXITY_LIMIT_EXCEEDED",
1426
+ limitType: error.limitType,
1427
+ limit: error.limit,
1428
+ actual: error.actual
1429
+ }
1430
+ })
1431
+ );
1432
+ }
1433
+ return Effect.logWarning("Complexity analysis failed for SSE subscription", error).pipe(
1434
+ Effect.map(() => null)
1435
+ );
1436
+ })
1437
+ );
1438
+ if (complexityResult) {
1439
+ return Stream.make(formatErrorEvent([complexityResult]), formatCompleteEvent());
1440
+ }
1441
+ }
1442
+ const ctx = {
1443
+ runtime,
1444
+ request,
1445
+ connectionContext
1446
+ };
1447
+ if (options?.onSubscribe) {
1448
+ yield* Effect.provide(options.onSubscribe(ctx), layer).pipe(
1449
+ Effect.catchAll(() => Effect.void)
1450
+ );
1451
+ }
1452
+ const graphqlContext = {
1453
+ runtime,
1454
+ ...connectionContext
1455
+ };
1456
+ const subscriptionResult = yield* Effect.tryPromise({
1457
+ try: () => subscribe({
1458
+ schema,
1459
+ document,
1460
+ variableValues: request.variables,
1461
+ operationName: request.operationName ?? void 0,
1462
+ contextValue: graphqlContext
1463
+ }),
1464
+ catch: (error) => new SSEError({ cause: error })
1465
+ });
1466
+ if (!isAsyncIterable(subscriptionResult)) {
1467
+ const result = subscriptionResult;
1468
+ if (result.errors) {
1469
+ return Stream.make(formatErrorEvent(result.errors), formatCompleteEvent());
1470
+ }
1471
+ return Stream.make(formatNextEvent(result), formatCompleteEvent());
1472
+ }
1473
+ const asyncIterator = subscriptionResult[Symbol.asyncIterator]();
1474
+ const eventStream = Stream.async((emit) => {
1475
+ let done = false;
1476
+ const iterate = async () => {
1477
+ try {
1478
+ while (!done) {
1479
+ const result = await asyncIterator.next();
1480
+ if (result.done) {
1481
+ emit.end();
1482
+ break;
1483
+ }
1484
+ emit.single(formatNextEvent(result.value));
1485
+ }
1486
+ } catch (error) {
1487
+ if (!done) {
1488
+ emit.single(
1489
+ formatErrorEvent([
1490
+ error instanceof GraphQLError ? error : new GraphQLError(
1491
+ error instanceof Error ? error.message : "Subscription error",
1492
+ { extensions: { code: "SUBSCRIPTION_ERROR" } }
1493
+ )
1494
+ ])
1495
+ );
1496
+ emit.end();
1497
+ }
1498
+ }
1499
+ };
1500
+ iterate();
1501
+ return Effect.sync(() => {
1502
+ done = true;
1503
+ asyncIterator.return?.();
1504
+ });
1505
+ });
1506
+ return eventStream.pipe(
1507
+ Stream.onDone(
1508
+ () => Effect.gen(function* () {
1509
+ yield* Effect.sync(() => {
1510
+ });
1511
+ }).pipe(Effect.asVoid)
1512
+ ),
1513
+ Stream.concat(Stream.make(formatCompleteEvent())),
1514
+ Stream.onDone(() => {
1515
+ if (options?.onComplete) {
1516
+ return Effect.provide(options.onComplete(ctx), layer).pipe(
1517
+ Effect.catchAll(() => Effect.void)
1518
+ );
1519
+ }
1520
+ return Effect.void;
1521
+ })
1522
+ );
1523
+ }).pipe(
1524
+ Effect.catchAll(
1525
+ (error) => Effect.succeed(
1526
+ Stream.make(
1527
+ formatErrorEvent([
1528
+ new GraphQLError(error instanceof Error ? error.message : "Internal error", {
1529
+ extensions: { code: "INTERNAL_ERROR" }
1530
+ })
1531
+ ]),
1532
+ formatCompleteEvent()
1533
+ )
1534
+ )
1535
+ )
1536
+ )
1537
+ );
1538
+ };
1539
+ var makeGraphQLSSEHandler = (schema, layer, options) => {
1540
+ return (request, headers) => makeSSESubscriptionStream(schema, layer, request, headers, options);
1541
+ };
1542
+ function isAsyncIterable(value) {
1543
+ return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
1544
+ }
1545
+
1546
+ export { CacheControlConfigFromEnv, ComplexityAnalysisError, ComplexityConfigFromEnv, ComplexityLimitExceededError, GraphQLRouterConfigFromEnv, SSEError, SSE_HEADERS, WS_CLOSED, WebSocketError, combineCalculators, computeCachePolicy, computeCachePolicyFromQuery, defaultComplexityCalculator, defaultConfig, defaultErrorHandler, depthOnlyCalculator, formatCompleteEvent, formatErrorEvent, formatNextEvent, formatSSEMessage, graphiqlHtml, makeGraphQLRouter, makeGraphQLSSEHandler, makeGraphQLWSHandler, makeSSESubscriptionStream, normalizeConfig, toCacheControlHeader, toEffectWebSocketFromWs, toRouter, validateComplexity };
1547
+ //# sourceMappingURL=index.js.map
1548
+ //# sourceMappingURL=index.js.map