@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,682 @@
1
+ import { Config, Layer, Cause, Effect, Stream, Runtime } from 'effect';
2
+ import { j as ComplexityConfig, y as CacheControlConfig, F as FieldComplexityMap, w as CacheHintMap, G as GraphQLExtension, i as GraphQLSchemaBuilder } from '../schema-builder-DKvkzU_M.cjs';
3
+ export { J as CacheControlConfigFromEnv, x as CachePolicy, z as CachePolicyAnalysisInfo, q as ComplexityAnalysisError, l as ComplexityAnalysisInfo, n as ComplexityCalculator, u as ComplexityConfigFromEnv, m as ComplexityExceededInfo, p as ComplexityLimitExceededError, k as ComplexityResult, o as FieldComplexity, t as combineCalculators, A as computeCachePolicy, B as computeCachePolicyFromQuery, r as defaultComplexityCalculator, s as depthOnlyCalculator, H as toCacheControlHeader, v as validateComplexity } from '../schema-builder-DKvkzU_M.cjs';
4
+ import { HttpServerResponse, HttpRouter } from '@effect/platform';
5
+ import { GraphQLSchema, ExecutionResult } from 'graphql';
6
+ import * as effect_Cause from 'effect/Cause';
7
+ import * as effect_Types from 'effect/Types';
8
+ import 'effect/Schema';
9
+
10
+ /**
11
+ * Configuration for the GraphiQL UI
12
+ */
13
+ interface GraphiQLConfig {
14
+ /** Path where GraphiQL UI is served (default: "/graphiql") */
15
+ readonly path: string;
16
+ /** URL where GraphiQL sends requests (default: same as graphql path) */
17
+ readonly endpoint: string;
18
+ /** WebSocket URL for subscriptions (default: same as endpoint) */
19
+ readonly subscriptionEndpoint?: string;
20
+ }
21
+ /**
22
+ * Configuration for the GraphQL router
23
+ */
24
+ interface GraphQLRouterConfig {
25
+ /** Path for GraphQL endpoint (default: "/graphql") */
26
+ readonly path: string;
27
+ /** GraphiQL configuration, or false to disable */
28
+ readonly graphiql: false | GraphiQLConfig;
29
+ /** Query complexity limiting configuration */
30
+ readonly complexity?: ComplexityConfig;
31
+ /** Enable introspection queries (default: true). Set to false in production. */
32
+ readonly introspection: boolean;
33
+ /** Cache control configuration for HTTP Cache-Control headers */
34
+ readonly cacheControl?: CacheControlConfig;
35
+ }
36
+ /**
37
+ * Default configuration values
38
+ */
39
+ declare const defaultConfig: GraphQLRouterConfig;
40
+ /**
41
+ * Normalize user-provided config (which may use boolean shorthand for graphiql)
42
+ * into the full GraphQLRouterConfig format
43
+ */
44
+ interface GraphQLRouterConfigInput {
45
+ readonly path?: string;
46
+ readonly graphiql?: boolean | Partial<GraphiQLConfig>;
47
+ /** Query complexity limiting configuration */
48
+ readonly complexity?: ComplexityConfig;
49
+ /** Enable introspection queries (default: true). Set to false in production. */
50
+ readonly introspection?: boolean;
51
+ /** Cache control configuration for HTTP Cache-Control headers */
52
+ readonly cacheControl?: CacheControlConfig;
53
+ }
54
+ declare const normalizeConfig: (input?: GraphQLRouterConfigInput) => GraphQLRouterConfig;
55
+ /**
56
+ * Effect Config for loading GraphQL router configuration from environment variables.
57
+ *
58
+ * Environment variables:
59
+ * - GRAPHQL_PATH: Path for GraphQL endpoint (default: "/graphql")
60
+ * - GRAPHQL_INTROSPECTION: Enable introspection queries (default: true)
61
+ * - GRAPHIQL_ENABLED: Enable GraphiQL UI (default: false)
62
+ * - GRAPHIQL_PATH: Path for GraphiQL UI (default: "/graphiql")
63
+ * - GRAPHIQL_ENDPOINT: URL where GraphiQL sends requests (default: same as GRAPHQL_PATH)
64
+ * - GRAPHQL_MAX_DEPTH: Maximum query depth (optional)
65
+ * - GRAPHQL_MAX_COMPLEXITY: Maximum complexity score (optional)
66
+ * - GRAPHQL_MAX_ALIASES: Maximum number of aliases (optional)
67
+ * - GRAPHQL_MAX_FIELDS: Maximum number of fields (optional)
68
+ * - GRAPHQL_DEFAULT_FIELD_COMPLEXITY: Default field complexity (default: 1)
69
+ * - GRAPHQL_CACHE_CONTROL_ENABLED: Enable cache control headers (default: false)
70
+ * - GRAPHQL_CACHE_CONTROL_DEFAULT_MAX_AGE: Default maxAge for root fields (default: 0)
71
+ * - GRAPHQL_CACHE_CONTROL_DEFAULT_SCOPE: Default scope - PUBLIC or PRIVATE (default: PUBLIC)
72
+ */
73
+ declare const GraphQLRouterConfigFromEnv: Config.Config<GraphQLRouterConfig>;
74
+
75
+ /**
76
+ * Generate HTML for GraphiQL IDE, loading dependencies from CDN
77
+ */
78
+ declare const graphiqlHtml: (endpoint: string, subscriptionEndpoint?: string) => string;
79
+
80
+ /**
81
+ * Error handler function type for handling uncaught errors during GraphQL execution.
82
+ * Receives the error cause and should return an HTTP response.
83
+ */
84
+ type ErrorHandler = (cause: Cause.Cause<unknown>) => Effect.Effect<HttpServerResponse.HttpServerResponse, never, never>;
85
+ /**
86
+ * Default error handler that returns a 500 Internal Server Error.
87
+ * In non-production environments, it logs the full error for debugging.
88
+ */
89
+ declare const defaultErrorHandler: ErrorHandler;
90
+ /**
91
+ * Options for makeGraphQLRouter
92
+ */
93
+ interface MakeGraphQLRouterOptions extends GraphQLRouterConfigInput {
94
+ /**
95
+ * Field complexity definitions from the schema builder.
96
+ * If using toRouter(), this is automatically extracted from the builder.
97
+ * If using makeGraphQLRouter() directly, call builder.getFieldComplexities().
98
+ */
99
+ readonly fieldComplexities?: FieldComplexityMap;
100
+ /**
101
+ * Cache hint definitions from the schema builder.
102
+ * If using toRouter(), this is automatically extracted from the builder.
103
+ * If using makeGraphQLRouter() directly, call builder.getCacheHints().
104
+ */
105
+ readonly cacheHints?: CacheHintMap;
106
+ /**
107
+ * GraphQL extensions for lifecycle hooks.
108
+ * If using toRouter(), this is automatically extracted from the builder.
109
+ * If using makeGraphQLRouter() directly, call builder.getExtensions().
110
+ */
111
+ readonly extensions?: readonly GraphQLExtension<any>[];
112
+ /**
113
+ * Custom error handler for uncaught errors during GraphQL execution.
114
+ * Receives the error cause and should return an HTTP response.
115
+ * Defaults to returning a 500 Internal Server Error with a generic message.
116
+ */
117
+ readonly errorHandler?: ErrorHandler;
118
+ }
119
+ /**
120
+ * Create an HttpRouter configured for GraphQL
121
+ *
122
+ * The router handles:
123
+ * - POST requests to the GraphQL endpoint
124
+ * - GET requests to the GraphiQL UI (if enabled)
125
+ * - Query complexity validation (if configured)
126
+ * - Extension lifecycle hooks (onParse, onValidate, onExecuteStart, onExecuteEnd)
127
+ *
128
+ * @param schema - The GraphQL schema
129
+ * @param layer - Effect layer providing services required by resolvers
130
+ * @param options - Optional configuration for paths, GraphiQL, complexity, and extensions
131
+ * @returns An HttpRouter that can be composed with other routes
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * const router = makeGraphQLRouter(schema, Layer.empty, {
136
+ * path: "/graphql",
137
+ * graphiql: { path: "/graphiql" },
138
+ * complexity: { maxDepth: 10, maxComplexity: 1000 },
139
+ * fieldComplexities: builder.getFieldComplexities(),
140
+ * extensions: builder.getExtensions()
141
+ * })
142
+ *
143
+ * // Compose with other routes
144
+ * const app = HttpRouter.empty.pipe(
145
+ * HttpRouter.get("/health", HttpServerResponse.json({ status: "ok" })),
146
+ * HttpRouter.concat(router)
147
+ * )
148
+ * ```
149
+ */
150
+ declare const makeGraphQLRouter: <R>(schema: GraphQLSchema, layer: Layer.Layer<R>, options?: MakeGraphQLRouterOptions) => HttpRouter.HttpRouter<never, never>;
151
+
152
+ /**
153
+ * Convert a GraphQLSchemaBuilder to an HttpRouter.
154
+ *
155
+ * This bridges the GraphQL schema builder with the @effect/platform HTTP server.
156
+ * Field complexities and cache hints are automatically extracted from the builder.
157
+ *
158
+ * @param builder - The GraphQL schema builder
159
+ * @param layer - Effect layer providing services required by resolvers
160
+ * @param options - Optional configuration for paths, GraphiQL, complexity, and caching
161
+ * @returns An HttpRouter that can be composed with other routes
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * import { GraphQLSchemaBuilder, query, toRouter } from "@effect-gql/core"
166
+ * import { Layer, Effect } from "effect"
167
+ * import * as S from "effect/Schema"
168
+ *
169
+ * const builder = GraphQLSchemaBuilder.empty.pipe(
170
+ * query("hello", { type: S.String, resolve: () => Effect.succeed("world") })
171
+ * )
172
+ *
173
+ * // Basic usage
174
+ * const router = toRouter(builder, Layer.empty, { graphiql: true })
175
+ *
176
+ * // With complexity limiting
177
+ * const routerWithLimits = toRouter(builder, Layer.empty, {
178
+ * graphiql: true,
179
+ * complexity: { maxDepth: 10, maxComplexity: 1000 }
180
+ * })
181
+ *
182
+ * // With cache control
183
+ * const routerWithCaching = toRouter(builder, Layer.empty, {
184
+ * cacheControl: { enabled: true, defaultMaxAge: 0 }
185
+ * })
186
+ * ```
187
+ */
188
+ declare const toRouter: <R, R2>(builder: GraphQLSchemaBuilder<R>, layer: Layer.Layer<R2>, options?: Omit<MakeGraphQLRouterOptions, "fieldComplexities" | "cacheHints">) => HttpRouter.HttpRouter<never, never>;
189
+
190
+ declare const WebSocketError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
191
+ readonly _tag: "WebSocketError";
192
+ } & Readonly<A>;
193
+ /**
194
+ * Error type for WebSocket operations
195
+ */
196
+ declare class WebSocketError extends WebSocketError_base<{
197
+ readonly cause: unknown;
198
+ }> {
199
+ }
200
+ /**
201
+ * WebSocket close event information
202
+ */
203
+ interface CloseEvent {
204
+ readonly code: number;
205
+ readonly reason: string;
206
+ }
207
+ /**
208
+ * Platform-neutral WebSocket interface using Effect types.
209
+ *
210
+ * This interface abstracts WebSocket operations across different platforms
211
+ * (Node.js ws, Bun built-in, browser WebSocket). Platform packages implement
212
+ * this interface to bridge their specific WebSocket implementations.
213
+ */
214
+ interface EffectWebSocket {
215
+ /**
216
+ * Send a message to the client.
217
+ * Returns an Effect that completes when the message is sent.
218
+ */
219
+ readonly send: (data: string) => Effect.Effect<void, WebSocketError>;
220
+ /**
221
+ * Close the WebSocket connection.
222
+ * @param code - Optional close code (default: 1000)
223
+ * @param reason - Optional close reason
224
+ */
225
+ readonly close: (code?: number, reason?: string) => Effect.Effect<void, WebSocketError>;
226
+ /**
227
+ * Stream of incoming messages from the client.
228
+ * The stream completes when the connection closes.
229
+ */
230
+ readonly messages: Stream.Stream<string, WebSocketError>;
231
+ /**
232
+ * Effect that completes with CloseEvent when the connection closes.
233
+ * Use this to detect client disconnection.
234
+ */
235
+ readonly closed: Effect.Effect<CloseEvent, WebSocketError>;
236
+ /**
237
+ * The WebSocket subprotocol negotiated during handshake.
238
+ * For GraphQL subscriptions, this should be "graphql-transport-ws".
239
+ */
240
+ readonly protocol: string;
241
+ }
242
+ /**
243
+ * Context available during a WebSocket connection.
244
+ * This is passed to lifecycle hooks.
245
+ */
246
+ interface ConnectionContext<R> {
247
+ /**
248
+ * The Effect runtime for this connection.
249
+ * Use this to run Effects within the connection scope.
250
+ */
251
+ readonly runtime: Runtime.Runtime<R>;
252
+ /**
253
+ * Connection parameters sent by the client during CONNECTION_INIT.
254
+ * Often used for authentication tokens.
255
+ */
256
+ readonly connectionParams: Record<string, unknown>;
257
+ /**
258
+ * The underlying WebSocket for this connection.
259
+ */
260
+ readonly socket: EffectWebSocket;
261
+ }
262
+ /**
263
+ * Options for configuring the GraphQL WebSocket handler.
264
+ *
265
+ * @template R - Service requirements for lifecycle hooks
266
+ */
267
+ interface GraphQLWSOptions<R> {
268
+ /**
269
+ * Query complexity limiting configuration.
270
+ * When provided, subscriptions are validated against complexity limits
271
+ * before execution begins.
272
+ */
273
+ readonly complexity?: ComplexityConfig;
274
+ /**
275
+ * Field complexity definitions from the schema builder.
276
+ * If using the platform serve() functions with subscriptions config,
277
+ * this is typically passed automatically.
278
+ */
279
+ readonly fieldComplexities?: FieldComplexityMap;
280
+ /**
281
+ * Called when a client initiates a connection (CONNECTION_INIT message).
282
+ *
283
+ * Use this for authentication. Return:
284
+ * - `true` to accept the connection
285
+ * - `false` to reject the connection
286
+ * - An object to accept and provide additional context
287
+ *
288
+ * The returned object (or true) is merged into the GraphQL context.
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * onConnect: (params) => Effect.gen(function* () {
293
+ * const token = params.authToken as string
294
+ * const user = yield* AuthService.validateToken(token)
295
+ * return { user } // Available in GraphQL context
296
+ * })
297
+ * ```
298
+ */
299
+ readonly onConnect?: (params: Record<string, unknown>) => Effect.Effect<boolean | Record<string, unknown>, unknown, R>;
300
+ /**
301
+ * Called when a client disconnects.
302
+ * Use this for cleanup (e.g., removing user from active connections).
303
+ */
304
+ readonly onDisconnect?: (ctx: ConnectionContext<R>) => Effect.Effect<void, never, R>;
305
+ /**
306
+ * Called when a client starts a subscription (SUBSCRIBE message).
307
+ * Use this for per-subscription authorization or logging.
308
+ *
309
+ * Note: If complexity validation is enabled, it runs before this hook.
310
+ * Throw an error to reject the subscription.
311
+ */
312
+ readonly onSubscribe?: (ctx: ConnectionContext<R>, message: SubscribeMessage) => Effect.Effect<void, unknown, R>;
313
+ /**
314
+ * Called when a subscription completes or is stopped.
315
+ */
316
+ readonly onComplete?: (ctx: ConnectionContext<R>, message: CompleteMessage) => Effect.Effect<void, never, R>;
317
+ /**
318
+ * Called when an error occurs during subscription execution.
319
+ */
320
+ readonly onError?: (ctx: ConnectionContext<R>, error: unknown) => Effect.Effect<void, never, R>;
321
+ }
322
+ /**
323
+ * GraphQL WebSocket SUBSCRIBE message payload
324
+ */
325
+ interface SubscribeMessage {
326
+ readonly id: string;
327
+ readonly payload: {
328
+ readonly query: string;
329
+ readonly variables?: Record<string, unknown>;
330
+ readonly operationName?: string;
331
+ readonly extensions?: Record<string, unknown>;
332
+ };
333
+ }
334
+ /**
335
+ * GraphQL WebSocket COMPLETE message payload
336
+ */
337
+ interface CompleteMessage {
338
+ readonly id: string;
339
+ }
340
+ /**
341
+ * Configuration for the WebSocket endpoint
342
+ */
343
+ interface GraphQLWSConfig {
344
+ /**
345
+ * Path for WebSocket connections.
346
+ * @default "/graphql"
347
+ */
348
+ readonly path?: string;
349
+ /**
350
+ * How long to wait for CONNECTION_INIT message before closing.
351
+ * @default 5000 (5 seconds)
352
+ */
353
+ readonly connectionInitWaitTimeout?: number;
354
+ }
355
+
356
+ /**
357
+ * Create a WebSocket handler for GraphQL subscriptions using the graphql-ws protocol.
358
+ *
359
+ * This function creates a handler that can be used with any WebSocket implementation
360
+ * that conforms to the EffectWebSocket interface. Platform packages (node, bun, express)
361
+ * provide adapters that convert their native WebSocket to EffectWebSocket.
362
+ *
363
+ * The handler:
364
+ * - Uses the graphql-ws protocol for client communication
365
+ * - Creates an Effect runtime from the provided layer for each connection
366
+ * - Executes subscriptions using GraphQL's subscribe() function
367
+ * - Properly cleans up resources when connections close
368
+ *
369
+ * @param schema - The GraphQL schema with subscription definitions
370
+ * @param layer - Effect layer providing services required by resolvers
371
+ * @param options - Optional lifecycle hooks for connection/subscription events
372
+ * @returns A function that handles individual WebSocket connections
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * import { makeGraphQLWSHandler } from "@effect-gql/core"
377
+ *
378
+ * const handler = makeGraphQLWSHandler(schema, serviceLayer, {
379
+ * onConnect: (params) => Effect.gen(function* () {
380
+ * const user = yield* AuthService.validateToken(params.authToken)
381
+ * return { user }
382
+ * }),
383
+ * })
384
+ *
385
+ * // In platform-specific code:
386
+ * const effectSocket = toEffectWebSocket(rawWebSocket)
387
+ * await Effect.runPromise(handler(effectSocket))
388
+ * ```
389
+ */
390
+ declare const makeGraphQLWSHandler: <R>(schema: GraphQLSchema, layer: Layer.Layer<R>, options?: GraphQLWSOptions<R>) => ((socket: EffectWebSocket) => Effect.Effect<void, never, never>);
391
+
392
+ /**
393
+ * Interface for the 'ws' library WebSocket.
394
+ * This allows type-safe usage without requiring core to depend on 'ws'.
395
+ */
396
+ interface WsWebSocket {
397
+ readonly protocol: string;
398
+ readonly readyState: number;
399
+ send(data: string, callback?: (error?: Error) => void): void;
400
+ close(code?: number, reason?: string): void;
401
+ on(event: "message", listener: (data: Buffer | string) => void): void;
402
+ on(event: "error", listener: (error: Error) => void): void;
403
+ on(event: "close", listener: (code: number, reason: Buffer) => void): void;
404
+ removeListener(event: string, listener: (...args: any[]) => void): void;
405
+ }
406
+ /** WebSocket.CLOSED constant from 'ws' library */
407
+ declare const WS_CLOSED = 3;
408
+ /**
409
+ * Convert a WebSocket from the 'ws' library to an EffectWebSocket.
410
+ *
411
+ * This creates an Effect-based wrapper around the ws WebSocket instance,
412
+ * providing a Stream for incoming messages and Effect-based send/close operations.
413
+ *
414
+ * This utility is used by platform packages (node, express) that integrate
415
+ * with the 'ws' library for WebSocket support.
416
+ *
417
+ * @param ws - The WebSocket instance from the 'ws' library
418
+ * @returns An EffectWebSocket that can be used with makeGraphQLWSHandler
419
+ *
420
+ * @example
421
+ * ```typescript
422
+ * import { toEffectWebSocketFromWs } from "@effect-gql/core"
423
+ * import { WebSocket } from "ws"
424
+ *
425
+ * wss.on("connection", (ws: WebSocket) => {
426
+ * const effectSocket = toEffectWebSocketFromWs(ws)
427
+ * Effect.runPromise(handler(effectSocket))
428
+ * })
429
+ * ```
430
+ */
431
+ declare const toEffectWebSocketFromWs: (ws: WsWebSocket) => EffectWebSocket;
432
+
433
+ /**
434
+ * Standard SSE response headers following the graphql-sse protocol.
435
+ * Use these headers when writing SSE responses in platform adapters.
436
+ */
437
+ declare const SSE_HEADERS: Record<string, string>;
438
+ declare const SSEError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
439
+ readonly _tag: "SSEError";
440
+ } & Readonly<A>;
441
+ /**
442
+ * Error type for SSE operations
443
+ */
444
+ declare class SSEError extends SSEError_base<{
445
+ readonly cause: unknown;
446
+ }> {
447
+ }
448
+ /**
449
+ * SSE event types following the graphql-sse protocol (distinct connections mode).
450
+ * @see https://github.com/enisdenjo/graphql-sse/blob/master/PROTOCOL.md
451
+ */
452
+ type SSEEventType = "next" | "error" | "complete";
453
+ /**
454
+ * An SSE event to be sent to the client.
455
+ */
456
+ interface SSEEvent {
457
+ readonly event: SSEEventType;
458
+ readonly data: string;
459
+ }
460
+ /**
461
+ * Platform-neutral SSE response interface using Effect types.
462
+ *
463
+ * This interface abstracts SSE operations across different platforms
464
+ * (Node.js, Bun, Deno, Workers). Platform packages implement this
465
+ * interface to bridge their specific HTTP response implementations.
466
+ *
467
+ * Unlike WebSocket which is bidirectional, SSE is unidirectional
468
+ * (server to client only). The subscription query is provided
469
+ * upfront when creating the SSE connection.
470
+ */
471
+ interface EffectSSE {
472
+ /**
473
+ * Send an SSE event to the client.
474
+ * The platform adapter formats this as proper SSE format:
475
+ * ```
476
+ * event: next
477
+ * data: {"data":{"field":"value"}}
478
+ *
479
+ * ```
480
+ */
481
+ readonly sendEvent: (event: SSEEvent) => Effect.Effect<void, SSEError>;
482
+ /**
483
+ * Effect that completes when the client disconnects.
484
+ * Use this to detect client disconnection and cleanup.
485
+ */
486
+ readonly closed: Effect.Effect<void, SSEError>;
487
+ }
488
+ /**
489
+ * The GraphQL request payload for SSE subscriptions.
490
+ * Same as a regular GraphQL HTTP request.
491
+ */
492
+ interface SSESubscriptionRequest {
493
+ readonly query: string;
494
+ readonly variables?: Record<string, unknown>;
495
+ readonly operationName?: string;
496
+ readonly extensions?: Record<string, unknown>;
497
+ }
498
+ /**
499
+ * Context available during an SSE subscription.
500
+ * This is passed to lifecycle hooks.
501
+ */
502
+ interface SSEConnectionContext<R> {
503
+ /**
504
+ * The Effect runtime for this connection.
505
+ * Use this to run Effects within the connection scope.
506
+ */
507
+ readonly runtime: Runtime.Runtime<R>;
508
+ /**
509
+ * The original subscription request.
510
+ */
511
+ readonly request: SSESubscriptionRequest;
512
+ /**
513
+ * Optional authentication/authorization context.
514
+ * Populated by the onConnect hook.
515
+ */
516
+ readonly connectionContext: Record<string, unknown>;
517
+ }
518
+ /**
519
+ * Options for configuring the GraphQL SSE handler.
520
+ *
521
+ * @template R - Service requirements for lifecycle hooks
522
+ */
523
+ interface GraphQLSSEOptions<R> {
524
+ /**
525
+ * Query complexity limiting configuration.
526
+ * When provided, subscriptions are validated against complexity limits
527
+ * before execution begins.
528
+ */
529
+ readonly complexity?: ComplexityConfig;
530
+ /**
531
+ * Field complexity definitions from the schema builder.
532
+ * If using the platform serve() functions, this is typically
533
+ * passed automatically.
534
+ */
535
+ readonly fieldComplexities?: FieldComplexityMap;
536
+ /**
537
+ * Called before a subscription starts.
538
+ *
539
+ * Use this for authentication/authorization. Return:
540
+ * - A context object to accept the subscription
541
+ * - Throw/fail to reject the subscription
542
+ *
543
+ * The returned object is available in the GraphQL context.
544
+ *
545
+ * @example
546
+ * ```typescript
547
+ * onConnect: (request, headers) => Effect.gen(function* () {
548
+ * const token = headers.get("authorization")
549
+ * const user = yield* AuthService.validateToken(token)
550
+ * return { user } // Available in GraphQL context
551
+ * })
552
+ * ```
553
+ */
554
+ readonly onConnect?: (request: SSESubscriptionRequest, headers: Headers) => Effect.Effect<Record<string, unknown>, unknown, R>;
555
+ /**
556
+ * Called when the subscription starts streaming.
557
+ */
558
+ readonly onSubscribe?: (ctx: SSEConnectionContext<R>) => Effect.Effect<void, never, R>;
559
+ /**
560
+ * Called when the subscription completes (normally or due to error).
561
+ */
562
+ readonly onComplete?: (ctx: SSEConnectionContext<R>) => Effect.Effect<void, never, R>;
563
+ /**
564
+ * Called when the client disconnects.
565
+ */
566
+ readonly onDisconnect?: (ctx: SSEConnectionContext<R>) => Effect.Effect<void, never, R>;
567
+ /**
568
+ * Called when an error occurs during subscription execution.
569
+ */
570
+ readonly onError?: (ctx: SSEConnectionContext<R>, error: unknown) => Effect.Effect<void, never, R>;
571
+ }
572
+ /**
573
+ * Configuration for the SSE endpoint
574
+ */
575
+ interface GraphQLSSEConfig {
576
+ /**
577
+ * Path for SSE connections.
578
+ * @default "/graphql/stream"
579
+ */
580
+ readonly path?: string;
581
+ }
582
+ /**
583
+ * Result of SSE subscription handler creation.
584
+ * This is used by platform packages to implement their SSE response.
585
+ */
586
+ interface SSESubscriptionResult {
587
+ /**
588
+ * Stream of SSE events to send to the client.
589
+ * The platform adapter should consume this stream and send events.
590
+ */
591
+ readonly events: Stream.Stream<SSEEvent, SSEError>;
592
+ /**
593
+ * Effect that should be run when client disconnects.
594
+ * This allows cleanup of resources.
595
+ */
596
+ readonly cleanup: Effect.Effect<void, never, never>;
597
+ }
598
+ /**
599
+ * Format an ExecutionResult as an SSE "next" event.
600
+ */
601
+ declare const formatNextEvent: (result: ExecutionResult) => SSEEvent;
602
+ /**
603
+ * Format errors as an SSE "error" event.
604
+ */
605
+ declare const formatErrorEvent: (errors: readonly unknown[]) => SSEEvent;
606
+ /**
607
+ * Format a "complete" event.
608
+ */
609
+ declare const formatCompleteEvent: () => SSEEvent;
610
+ /**
611
+ * Format an SSE event to the wire format.
612
+ * Each event is formatted as:
613
+ * ```
614
+ * event: <type>
615
+ * data: <json>
616
+ *
617
+ * ```
618
+ */
619
+ declare const formatSSEMessage: (event: SSEEvent) => string;
620
+
621
+ /**
622
+ * Create a subscription event stream for SSE.
623
+ *
624
+ * This function handles the GraphQL subscription lifecycle:
625
+ * 1. Parse and validate the query
626
+ * 2. Check complexity limits if configured
627
+ * 3. Execute the subscription
628
+ * 4. Stream results as SSE events
629
+ *
630
+ * @param schema - The GraphQL schema with subscription definitions
631
+ * @param layer - Effect layer providing services required by resolvers
632
+ * @param request - The subscription request (query, variables, operationName)
633
+ * @param headers - HTTP headers from the request (for auth)
634
+ * @param options - Optional lifecycle hooks and configuration
635
+ * @returns A Stream of SSE events to send to the client
636
+ *
637
+ * @example
638
+ * ```typescript
639
+ * const eventStream = makeSSESubscriptionStream(
640
+ * schema,
641
+ * serviceLayer,
642
+ * { query: "subscription { tick { count } }" },
643
+ * new Headers(),
644
+ * { onConnect: (req, headers) => Effect.succeed({ user: "alice" }) }
645
+ * )
646
+ *
647
+ * // In platform-specific code, consume and send events:
648
+ * Stream.runForEach(eventStream, (event) =>
649
+ * Effect.sync(() => res.write(formatSSEMessage(event)))
650
+ * )
651
+ * ```
652
+ */
653
+ declare const makeSSESubscriptionStream: <R>(schema: GraphQLSchema, layer: Layer.Layer<R>, request: SSESubscriptionRequest, headers: Headers, options?: GraphQLSSEOptions<R>) => Stream.Stream<SSEEvent, SSEError>;
654
+ /**
655
+ * Create an SSE subscription handler that can be used with platform-specific servers.
656
+ *
657
+ * This is a higher-level API that returns a handler function. The handler
658
+ * takes a request and headers, and returns a Stream of SSE events.
659
+ *
660
+ * @param schema - The GraphQL schema with subscription definitions
661
+ * @param layer - Effect layer providing services required by resolvers
662
+ * @param options - Optional lifecycle hooks and configuration
663
+ * @returns A handler function for SSE subscription requests
664
+ *
665
+ * @example
666
+ * ```typescript
667
+ * const handler = makeGraphQLSSEHandler(schema, serviceLayer, {
668
+ * onConnect: (request, headers) => Effect.gen(function* () {
669
+ * const token = headers.get("authorization")
670
+ * const user = yield* AuthService.validateToken(token)
671
+ * return { user }
672
+ * }),
673
+ * })
674
+ *
675
+ * // In platform-specific code:
676
+ * const events = handler(request, headers)
677
+ * // Stream events to client...
678
+ * ```
679
+ */
680
+ declare const makeGraphQLSSEHandler: <R>(schema: GraphQLSchema, layer: Layer.Layer<R>, options?: GraphQLSSEOptions<R>) => ((request: SSESubscriptionRequest, headers: Headers) => Stream.Stream<SSEEvent, SSEError>);
681
+
682
+ export { CacheControlConfig, CacheHintMap, type CloseEvent, type CompleteMessage, ComplexityConfig, type ConnectionContext, type EffectSSE, type EffectWebSocket, type ErrorHandler, FieldComplexityMap, type GraphQLRouterConfig, GraphQLRouterConfigFromEnv, type GraphQLRouterConfigInput, type GraphQLSSEConfig, type GraphQLSSEOptions, type GraphQLWSConfig, type GraphQLWSOptions, type GraphiQLConfig, type MakeGraphQLRouterOptions, type SSEConnectionContext, SSEError, type SSEEvent, type SSEEventType, type SSESubscriptionRequest, type SSESubscriptionResult, SSE_HEADERS, type SubscribeMessage, WS_CLOSED, WebSocketError, type WsWebSocket, defaultConfig, defaultErrorHandler, formatCompleteEvent, formatErrorEvent, formatNextEvent, formatSSEMessage, graphiqlHtml, makeGraphQLRouter, makeGraphQLSSEHandler, makeGraphQLWSHandler, makeSSESubscriptionStream, normalizeConfig, toEffectWebSocketFromWs, toRouter };