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