@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.
- package/README.md +100 -0
- package/builder/index.cjs +1431 -0
- package/builder/index.cjs.map +1 -0
- package/builder/index.d.cts +259 -0
- package/{dist/builder/pipe-api.d.ts → builder/index.d.ts} +49 -21
- package/builder/index.js +1390 -0
- package/builder/index.js.map +1 -0
- package/index.cjs +3419 -0
- package/index.cjs.map +1 -0
- package/index.d.cts +523 -0
- package/index.d.ts +523 -0
- package/index.js +3242 -0
- package/index.js.map +1 -0
- package/package.json +19 -28
- package/schema-builder-Cvdq7Kz_.d.cts +963 -0
- package/schema-builder-Cvdq7Kz_.d.ts +963 -0
- package/server/index.cjs +1555 -0
- package/server/index.cjs.map +1 -0
- package/server/index.d.cts +680 -0
- package/server/index.d.ts +680 -0
- package/server/index.js +1524 -0
- package/server/index.js.map +1 -0
- package/dist/analyzer-extension.d.ts +0 -105
- package/dist/analyzer-extension.d.ts.map +0 -1
- package/dist/analyzer-extension.js +0 -137
- package/dist/analyzer-extension.js.map +0 -1
- package/dist/builder/execute.d.ts +0 -26
- package/dist/builder/execute.d.ts.map +0 -1
- package/dist/builder/execute.js +0 -104
- package/dist/builder/execute.js.map +0 -1
- package/dist/builder/field-builders.d.ts +0 -30
- package/dist/builder/field-builders.d.ts.map +0 -1
- package/dist/builder/field-builders.js +0 -200
- package/dist/builder/field-builders.js.map +0 -1
- package/dist/builder/index.d.ts +0 -7
- package/dist/builder/index.d.ts.map +0 -1
- package/dist/builder/index.js +0 -31
- package/dist/builder/index.js.map +0 -1
- package/dist/builder/pipe-api.d.ts.map +0 -1
- package/dist/builder/pipe-api.js +0 -151
- package/dist/builder/pipe-api.js.map +0 -1
- package/dist/builder/schema-builder.d.ts +0 -301
- package/dist/builder/schema-builder.d.ts.map +0 -1
- package/dist/builder/schema-builder.js +0 -566
- package/dist/builder/schema-builder.js.map +0 -1
- package/dist/builder/type-registry.d.ts +0 -80
- package/dist/builder/type-registry.d.ts.map +0 -1
- package/dist/builder/type-registry.js +0 -505
- package/dist/builder/type-registry.js.map +0 -1
- package/dist/builder/types.d.ts +0 -283
- package/dist/builder/types.d.ts.map +0 -1
- package/dist/builder/types.js +0 -3
- package/dist/builder/types.js.map +0 -1
- package/dist/cli/generate-schema.d.ts +0 -29
- package/dist/cli/generate-schema.d.ts.map +0 -1
- package/dist/cli/generate-schema.js +0 -233
- package/dist/cli/generate-schema.js.map +0 -1
- package/dist/cli/index.d.ts +0 -19
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -24
- package/dist/cli/index.js.map +0 -1
- package/dist/context.d.ts +0 -18
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -11
- package/dist/context.js.map +0 -1
- package/dist/error.d.ts +0 -45
- package/dist/error.d.ts.map +0 -1
- package/dist/error.js +0 -29
- package/dist/error.js.map +0 -1
- package/dist/extensions.d.ts +0 -130
- package/dist/extensions.d.ts.map +0 -1
- package/dist/extensions.js +0 -78
- package/dist/extensions.js.map +0 -1
- package/dist/index.d.ts +0 -12
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -47
- package/dist/index.js.map +0 -1
- package/dist/loader.d.ts +0 -169
- package/dist/loader.d.ts.map +0 -1
- package/dist/loader.js +0 -237
- package/dist/loader.js.map +0 -1
- package/dist/resolver-context.d.ts +0 -154
- package/dist/resolver-context.d.ts.map +0 -1
- package/dist/resolver-context.js +0 -184
- package/dist/resolver-context.js.map +0 -1
- package/dist/schema-mapping.d.ts +0 -30
- package/dist/schema-mapping.d.ts.map +0 -1
- package/dist/schema-mapping.js +0 -280
- package/dist/schema-mapping.js.map +0 -1
- package/dist/server/cache-control.d.ts +0 -96
- package/dist/server/cache-control.d.ts.map +0 -1
- package/dist/server/cache-control.js +0 -308
- package/dist/server/cache-control.js.map +0 -1
- package/dist/server/complexity.d.ts +0 -165
- package/dist/server/complexity.d.ts.map +0 -1
- package/dist/server/complexity.js +0 -433
- package/dist/server/complexity.js.map +0 -1
- package/dist/server/config.d.ts +0 -66
- package/dist/server/config.d.ts.map +0 -1
- package/dist/server/config.js +0 -104
- package/dist/server/config.js.map +0 -1
- package/dist/server/graphiql.d.ts +0 -5
- package/dist/server/graphiql.d.ts.map +0 -1
- package/dist/server/graphiql.js +0 -43
- package/dist/server/graphiql.js.map +0 -1
- package/dist/server/index.d.ts +0 -18
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -48
- package/dist/server/index.js.map +0 -1
- package/dist/server/router.d.ts +0 -79
- package/dist/server/router.d.ts.map +0 -1
- package/dist/server/router.js +0 -232
- package/dist/server/router.js.map +0 -1
- package/dist/server/schema-builder-extensions.d.ts +0 -42
- package/dist/server/schema-builder-extensions.d.ts.map +0 -1
- package/dist/server/schema-builder-extensions.js +0 -48
- package/dist/server/schema-builder-extensions.js.map +0 -1
- package/dist/server/sse-adapter.d.ts +0 -64
- package/dist/server/sse-adapter.d.ts.map +0 -1
- package/dist/server/sse-adapter.js +0 -227
- package/dist/server/sse-adapter.js.map +0 -1
- package/dist/server/sse-types.d.ts +0 -192
- package/dist/server/sse-types.d.ts.map +0 -1
- package/dist/server/sse-types.js +0 -63
- package/dist/server/sse-types.js.map +0 -1
- package/dist/server/ws-adapter.d.ts +0 -39
- package/dist/server/ws-adapter.d.ts.map +0 -1
- package/dist/server/ws-adapter.js +0 -247
- package/dist/server/ws-adapter.js.map +0 -1
- package/dist/server/ws-types.d.ts +0 -169
- package/dist/server/ws-types.d.ts.map +0 -1
- package/dist/server/ws-types.js +0 -11
- package/dist/server/ws-types.js.map +0 -1
- package/dist/server/ws-utils.d.ts +0 -42
- package/dist/server/ws-utils.d.ts.map +0 -1
- package/dist/server/ws-utils.js +0 -99
- package/dist/server/ws-utils.js.map +0 -1
- package/src/analyzer-extension.ts +0 -254
- package/src/builder/execute.ts +0 -153
- package/src/builder/field-builders.ts +0 -322
- package/src/builder/index.ts +0 -48
- package/src/builder/pipe-api.ts +0 -312
- package/src/builder/schema-builder.ts +0 -970
- package/src/builder/type-registry.ts +0 -670
- package/src/builder/types.ts +0 -305
- package/src/context.ts +0 -23
- package/src/error.ts +0 -32
- package/src/extensions.ts +0 -240
- package/src/index.ts +0 -32
- package/src/loader.ts +0 -363
- package/src/resolver-context.ts +0 -253
- package/src/schema-mapping.ts +0 -307
- package/src/server/cache-control.ts +0 -590
- package/src/server/complexity.ts +0 -774
- package/src/server/config.ts +0 -174
- package/src/server/graphiql.ts +0 -38
- package/src/server/index.ts +0 -96
- package/src/server/router.ts +0 -432
- package/src/server/schema-builder-extensions.ts +0 -51
- package/src/server/sse-adapter.ts +0 -327
- package/src/server/sse-types.ts +0 -234
- package/src/server/ws-adapter.ts +0 -355
- package/src/server/ws-types.ts +0 -192
- package/src/server/ws-utils.ts +0 -136
package/index.d.ts
ADDED
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
import { F as FieldComplexityMap, G as GraphQLExtension, E as ExtensionsService } from './schema-builder-Cvdq7Kz_.js';
|
|
2
|
+
export { y as CacheControlConfig, J as CacheControlConfigFromEnv, h as CacheControlScope, C as CacheHint, w as CacheHintMap, x as CachePolicy, z as CachePolicyAnalysisInfo, q as ComplexityAnalysisError, l as ComplexityAnalysisInfo, n as ComplexityCalculator, j as ComplexityConfig, u as ComplexityConfigFromEnv, m as ComplexityExceededInfo, p as ComplexityLimitExceededError, k as ComplexityResult, D as DirectiveApplication, d as DirectiveRegistration, b as EnumRegistration, K as ExecutionArgs, o as FieldComplexity, a as FieldRegistration, f as GraphQLEffectContext, i as GraphQLSchemaBuilder, c as InputTypeRegistration, I as InterfaceRegistration, M as MiddlewareContext, e as MiddlewareRegistration, O as ObjectFieldRegistration, S as SubscriptionFieldRegistration, T as TypeRegistration, g as TypeRegistries, U as UnionRegistration, t as combineCalculators, A as computeCachePolicy, B as computeCachePolicyFromQuery, r as defaultComplexityCalculator, s as depthOnlyCalculator, L as makeExtensionsService, R as runExecuteEndHooks, Q as runExecuteStartHooks, N as runParseHooks, P as runValidateHooks, H as toCacheControlHeader, v as validateComplexity } from './schema-builder-Cvdq7Kz_.js';
|
|
3
|
+
import { GraphQLOutputType, GraphQLInputType, GraphQLFieldConfigArgumentMap, GraphQLObjectType } from 'graphql';
|
|
4
|
+
export { DirectiveLocation, GraphQLBoolean, GraphQLEnumType, GraphQLFieldConfigMap, GraphQLFloat, GraphQLID, GraphQLInputObjectType, GraphQLInt, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, GraphQLSchema, GraphQLString, GraphQLUnionType, Kind, ValueNode, graphql, lexicographicSortSchema, printSchema } from 'graphql';
|
|
5
|
+
export { compose, directive, enumType, execute, extension, field, getSchemaName, inputType, interfaceType, middleware, mutation, objectType, query, subscription, unionType } from './builder/index.js';
|
|
6
|
+
import { Effect, Context, Layer, Ref, HashMap, Option } from 'effect';
|
|
7
|
+
import * as S from 'effect/Schema';
|
|
8
|
+
import * as effect_Cause from 'effect/Cause';
|
|
9
|
+
import * as effect_Types from 'effect/Types';
|
|
10
|
+
import DataLoader from 'dataloader';
|
|
11
|
+
export { CloseEvent, CompleteMessage, ConnectionContext, EffectSSE, EffectWebSocket, ErrorHandler, GraphQLRouterConfig, GraphQLRouterConfigFromEnv, GraphQLRouterConfigInput, GraphQLSSEConfig, GraphQLSSEOptions, GraphQLWSConfig, GraphQLWSOptions, GraphiQLConfig, MakeGraphQLRouterOptions, SSEConnectionContext, SSEError, SSEEvent, SSEEventType, SSESubscriptionRequest, SSESubscriptionResult, SSE_HEADERS, SubscribeMessage, WS_CLOSED, WebSocketError, WsWebSocket, defaultConfig, defaultErrorHandler, formatCompleteEvent, formatErrorEvent, formatNextEvent, formatSSEMessage, graphiqlHtml, makeGraphQLRouter, makeGraphQLSSEHandler, makeGraphQLWSHandler, makeSSESubscriptionStream, normalizeConfig, toEffectWebSocketFromWs, toRouter } from './server/index.js';
|
|
12
|
+
import '@effect/platform';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Convert an Effect Schema to a GraphQL output type
|
|
16
|
+
*/
|
|
17
|
+
declare const toGraphQLType: (schema: S.Schema<any, any, any>) => GraphQLOutputType;
|
|
18
|
+
/**
|
|
19
|
+
* Convert an Effect Schema to a GraphQL input type
|
|
20
|
+
*/
|
|
21
|
+
declare const toGraphQLInputType: (schema: S.Schema<any, any, any>) => GraphQLInputType;
|
|
22
|
+
/**
|
|
23
|
+
* Additional field configuration for computed/relational fields
|
|
24
|
+
*/
|
|
25
|
+
interface AdditionalField<Parent, Args, R, E, A> {
|
|
26
|
+
type: GraphQLOutputType;
|
|
27
|
+
args?: GraphQLFieldConfigArgumentMap;
|
|
28
|
+
description?: string;
|
|
29
|
+
resolve: (parent: Parent, args: Args) => Effect.Effect<A, E, R>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create a GraphQL Object Type from an Effect Schema with a name
|
|
33
|
+
* Optionally add computed/relational fields with resolvers
|
|
34
|
+
*/
|
|
35
|
+
declare const toGraphQLObjectType: <T>(name: string, schema: S.Schema<any, any, any>, additionalFields?: Record<string, AdditionalField<T, any, any, any, any>>) => GraphQLObjectType;
|
|
36
|
+
/**
|
|
37
|
+
* Convert an Effect Schema to GraphQL arguments
|
|
38
|
+
*/
|
|
39
|
+
declare const toGraphQLArgs: (schema: S.Schema<any, any, any>) => GraphQLFieldConfigArgumentMap;
|
|
40
|
+
|
|
41
|
+
declare const GraphQLError_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 & {
|
|
42
|
+
readonly _tag: "GraphQLError";
|
|
43
|
+
} & Readonly<A>;
|
|
44
|
+
/**
|
|
45
|
+
* Base class for GraphQL errors in Effect
|
|
46
|
+
*/
|
|
47
|
+
declare class GraphQLError extends GraphQLError_base<{
|
|
48
|
+
message: string;
|
|
49
|
+
extensions?: Record<string, unknown>;
|
|
50
|
+
}> {
|
|
51
|
+
}
|
|
52
|
+
declare const ValidationError_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 & {
|
|
53
|
+
readonly _tag: "ValidationError";
|
|
54
|
+
} & Readonly<A>;
|
|
55
|
+
/**
|
|
56
|
+
* Validation error for input validation failures
|
|
57
|
+
*/
|
|
58
|
+
declare class ValidationError extends ValidationError_base<{
|
|
59
|
+
message: string;
|
|
60
|
+
field?: string;
|
|
61
|
+
}> {
|
|
62
|
+
}
|
|
63
|
+
declare const AuthorizationError_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 & {
|
|
64
|
+
readonly _tag: "AuthorizationError";
|
|
65
|
+
} & Readonly<A>;
|
|
66
|
+
/**
|
|
67
|
+
* Authorization error for access control failures
|
|
68
|
+
*/
|
|
69
|
+
declare class AuthorizationError extends AuthorizationError_base<{
|
|
70
|
+
message: string;
|
|
71
|
+
}> {
|
|
72
|
+
}
|
|
73
|
+
declare const NotFoundError_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 & {
|
|
74
|
+
readonly _tag: "NotFoundError";
|
|
75
|
+
} & Readonly<A>;
|
|
76
|
+
/**
|
|
77
|
+
* Not found error for missing resources
|
|
78
|
+
*/
|
|
79
|
+
declare class NotFoundError extends NotFoundError_base<{
|
|
80
|
+
message: string;
|
|
81
|
+
resource?: string;
|
|
82
|
+
}> {
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* GraphQL request context containing request-specific data
|
|
87
|
+
*/
|
|
88
|
+
interface GraphQLRequestContext {
|
|
89
|
+
readonly request: {
|
|
90
|
+
readonly headers: Record<string, string>;
|
|
91
|
+
readonly query: string;
|
|
92
|
+
readonly variables?: Record<string, unknown>;
|
|
93
|
+
readonly operationName?: string;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
declare const GraphQLRequestContext: Context.Tag<GraphQLRequestContext, GraphQLRequestContext>;
|
|
97
|
+
/**
|
|
98
|
+
* Create a layer from request context
|
|
99
|
+
*/
|
|
100
|
+
declare const makeRequestContextLayer: (context: GraphQLRequestContext) => Layer.Layer<GraphQLRequestContext>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Ergonomic DataLoader helpers for Effect-based GraphQL
|
|
104
|
+
*
|
|
105
|
+
* This module provides a type-safe, declarative way to define DataLoaders
|
|
106
|
+
* that integrate seamlessly with Effect's service system.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* // Define loaders
|
|
111
|
+
* const loaders = Loader.define({
|
|
112
|
+
* UserById: Loader.single<string, User>({
|
|
113
|
+
* batch: (ids) => db.getUsersByIds(ids),
|
|
114
|
+
* key: (user) => user.id,
|
|
115
|
+
* }),
|
|
116
|
+
*
|
|
117
|
+
* PostsByAuthorId: Loader.grouped<string, Post>({
|
|
118
|
+
* batch: (ids) => db.getPostsForAuthors(ids),
|
|
119
|
+
* groupBy: (post) => post.authorId,
|
|
120
|
+
* }),
|
|
121
|
+
* })
|
|
122
|
+
*
|
|
123
|
+
* // Use in resolvers
|
|
124
|
+
* resolve: (parent) => loaders.load("UserById", parent.authorId)
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
/**
|
|
128
|
+
* Configuration for a single-value loader (one key -> one value)
|
|
129
|
+
*/
|
|
130
|
+
interface SingleLoaderDef<K, V, R> {
|
|
131
|
+
readonly _tag: "single";
|
|
132
|
+
readonly batch: (keys: readonly K[]) => Effect.Effect<readonly V[], Error, R>;
|
|
133
|
+
readonly key: (value: V) => K;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Configuration for a grouped loader (one key -> many values)
|
|
137
|
+
*/
|
|
138
|
+
interface GroupedLoaderDef<K, V, R> {
|
|
139
|
+
readonly _tag: "grouped";
|
|
140
|
+
readonly batch: (keys: readonly K[]) => Effect.Effect<readonly V[], Error, R>;
|
|
141
|
+
readonly groupBy: (value: V) => K;
|
|
142
|
+
}
|
|
143
|
+
type LoaderDef<K, V, R> = SingleLoaderDef<K, V, R> | GroupedLoaderDef<K, V, R>;
|
|
144
|
+
/**
|
|
145
|
+
* Runtime DataLoader instances
|
|
146
|
+
*/
|
|
147
|
+
type LoaderInstances<Defs extends Record<string, LoaderDef<any, any, any>>> = {
|
|
148
|
+
[Name in keyof Defs]: Defs[Name] extends SingleLoaderDef<infer K, infer V, any> ? DataLoader<K, V> : Defs[Name] extends GroupedLoaderDef<infer K, infer V, any> ? DataLoader<K, V[]> : never;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Extract the value type for a loader (accounting for grouped loaders)
|
|
152
|
+
*/
|
|
153
|
+
type LoaderValue<Def> = Def extends SingleLoaderDef<any, infer V, any> ? V : Def extends GroupedLoaderDef<any, infer V, any> ? V[] : never;
|
|
154
|
+
/**
|
|
155
|
+
* Extract the key type for a loader
|
|
156
|
+
*/
|
|
157
|
+
type LoaderKey<Def> = Def extends LoaderDef<infer K, any, any> ? K : never;
|
|
158
|
+
/**
|
|
159
|
+
* Extract combined requirements from all loaders
|
|
160
|
+
*/
|
|
161
|
+
type LoaderRequirements<Defs extends Record<string, LoaderDef<any, any, any>>> = {
|
|
162
|
+
[K in keyof Defs]: Defs[K] extends LoaderDef<any, any, infer R> ? R : never;
|
|
163
|
+
}[keyof Defs];
|
|
164
|
+
/**
|
|
165
|
+
* Create a single-value loader definition.
|
|
166
|
+
* One key maps to one value.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```typescript
|
|
170
|
+
* Loader.single<string, User>({
|
|
171
|
+
* batch: (ids) => db.getUsersByIds(ids),
|
|
172
|
+
* key: (user) => user.id,
|
|
173
|
+
* })
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function single<K, V, R = never>(config: {
|
|
177
|
+
batch: (keys: readonly K[]) => Effect.Effect<readonly V[], Error, R>;
|
|
178
|
+
key: (value: V) => K;
|
|
179
|
+
}): SingleLoaderDef<K, V, R>;
|
|
180
|
+
/**
|
|
181
|
+
* Create a grouped loader definition.
|
|
182
|
+
* One key maps to many values.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* Loader.grouped<string, Post>({
|
|
187
|
+
* batch: (authorIds) => db.getPostsForAuthors(authorIds),
|
|
188
|
+
* groupBy: (post) => post.authorId,
|
|
189
|
+
* })
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
declare function grouped<K, V, R = never>(config: {
|
|
193
|
+
batch: (keys: readonly K[]) => Effect.Effect<readonly V[], Error, R>;
|
|
194
|
+
groupBy: (value: V) => K;
|
|
195
|
+
}): GroupedLoaderDef<K, V, R>;
|
|
196
|
+
/**
|
|
197
|
+
* A registry of loader definitions with methods to create instances and layers
|
|
198
|
+
*/
|
|
199
|
+
declare class LoaderRegistry<Defs extends Record<string, LoaderDef<any, any, any>>> {
|
|
200
|
+
readonly definitions: Defs;
|
|
201
|
+
readonly _tag = "LoaderRegistry";
|
|
202
|
+
/**
|
|
203
|
+
* The Effect service tag for this loader registry
|
|
204
|
+
*/
|
|
205
|
+
readonly Service: Context.Tag<LoaderInstances<Defs>, LoaderInstances<Defs>>;
|
|
206
|
+
constructor(definitions: Defs);
|
|
207
|
+
/**
|
|
208
|
+
* Create a Layer that provides fresh DataLoader instances.
|
|
209
|
+
* Call this once per request to get request-scoped loaders.
|
|
210
|
+
*/
|
|
211
|
+
toLayer(): Layer.Layer<LoaderInstances<Defs>, never, LoaderRequirements<Defs>>;
|
|
212
|
+
/**
|
|
213
|
+
* Helper to use loaders in a resolver with a callback.
|
|
214
|
+
*/
|
|
215
|
+
use<A>(fn: (loaders: LoaderInstances<Defs>) => Promise<A>): Effect.Effect<A, Error, LoaderInstances<Defs>>;
|
|
216
|
+
/**
|
|
217
|
+
* Load a single value by key.
|
|
218
|
+
* This is the most common operation in resolvers.
|
|
219
|
+
*/
|
|
220
|
+
load<Name extends keyof Defs & string>(name: Name, key: LoaderKey<Defs[Name]>): Effect.Effect<LoaderValue<Defs[Name]>, Error, LoaderInstances<Defs>>;
|
|
221
|
+
/**
|
|
222
|
+
* Load multiple values by keys.
|
|
223
|
+
* All keys are batched into a single request.
|
|
224
|
+
*/
|
|
225
|
+
loadMany<Name extends keyof Defs & string>(name: Name, keys: readonly LoaderKey<Defs[Name]>[]): Effect.Effect<readonly LoaderValue<Defs[Name]>[], Error, LoaderInstances<Defs>>;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Define a set of loaders.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```typescript
|
|
232
|
+
* const loaders = Loader.define({
|
|
233
|
+
* UserById: Loader.single<string, User>({
|
|
234
|
+
* batch: (ids) => db.getUsersByIds(ids),
|
|
235
|
+
* key: (user) => user.id,
|
|
236
|
+
* }),
|
|
237
|
+
* PostsByAuthorId: Loader.grouped<string, Post>({
|
|
238
|
+
* batch: (ids) => db.getPostsForAuthors(ids),
|
|
239
|
+
* groupBy: (post) => post.authorId,
|
|
240
|
+
* }),
|
|
241
|
+
* })
|
|
242
|
+
*
|
|
243
|
+
* // In resolvers:
|
|
244
|
+
* loaders.load("UserById", "123")
|
|
245
|
+
* loaders.loadMany("UserById", ["1", "2", "3"])
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
declare function define<Defs extends Record<string, LoaderDef<any, any, any>>>(definitions: Defs): LoaderRegistry<Defs>;
|
|
249
|
+
/**
|
|
250
|
+
* Map an array of items to match requested keys.
|
|
251
|
+
* Returns items in the same order as keys, with errors for missing items.
|
|
252
|
+
*/
|
|
253
|
+
declare function mapByKey<K, V>(keys: readonly K[], items: readonly V[], keyFn: (item: V) => K): (V | Error)[];
|
|
254
|
+
/**
|
|
255
|
+
* Group an array of items by a key function.
|
|
256
|
+
* Returns a Map from key to array of matching items.
|
|
257
|
+
* Guarantees an entry (possibly empty) for each requested key.
|
|
258
|
+
*/
|
|
259
|
+
declare function groupByKey<K, V>(keys: readonly K[], items: readonly V[], keyFn: (item: V) => K): Map<K, V[]>;
|
|
260
|
+
declare const Loader: {
|
|
261
|
+
readonly define: typeof define;
|
|
262
|
+
readonly single: typeof single;
|
|
263
|
+
readonly grouped: typeof grouped;
|
|
264
|
+
readonly mapByKey: typeof mapByKey;
|
|
265
|
+
readonly groupByKey: typeof groupByKey;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* A type-safe context system for passing values through the resolver hierarchy.
|
|
270
|
+
*
|
|
271
|
+
* Unlike simple property bags, this provides:
|
|
272
|
+
* - Type-safe slots that know their value type
|
|
273
|
+
* - Clear errors when required context is missing
|
|
274
|
+
* - Request-scoped storage that works across nested resolvers
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```typescript
|
|
278
|
+
* // Define a context slot
|
|
279
|
+
* const AuthPrincipal = ResolverContext.make<User>("AuthPrincipal")
|
|
280
|
+
*
|
|
281
|
+
* // Provide in a directive
|
|
282
|
+
* .directive({
|
|
283
|
+
* name: "auth",
|
|
284
|
+
* apply: () => (effect) => Effect.gen(function*() {
|
|
285
|
+
* const user = yield* validateJwt()
|
|
286
|
+
* yield* ResolverContext.set(AuthPrincipal, user)
|
|
287
|
+
* return yield* effect
|
|
288
|
+
* }),
|
|
289
|
+
* })
|
|
290
|
+
*
|
|
291
|
+
* // Access in any nested resolver
|
|
292
|
+
* .field("User", "posts", {
|
|
293
|
+
* resolve: (parent) => Effect.gen(function*() {
|
|
294
|
+
* const user = yield* ResolverContext.get(AuthPrincipal)
|
|
295
|
+
* // ...
|
|
296
|
+
* }),
|
|
297
|
+
* })
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
/**
|
|
301
|
+
* Error thrown when trying to access a context value that hasn't been set
|
|
302
|
+
*/
|
|
303
|
+
declare class MissingResolverContextError extends Error {
|
|
304
|
+
readonly contextName: string;
|
|
305
|
+
readonly _tag = "MissingResolverContextError";
|
|
306
|
+
constructor(contextName: string);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* A typed context slot that can hold a value of type A
|
|
310
|
+
*/
|
|
311
|
+
interface ResolverContextSlot<A> {
|
|
312
|
+
readonly _tag: "ResolverContextSlot";
|
|
313
|
+
readonly name: string;
|
|
314
|
+
readonly _A: A;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Internal storage for resolver context values.
|
|
318
|
+
* This is a request-scoped service that holds all context values.
|
|
319
|
+
*/
|
|
320
|
+
interface ResolverContextStore {
|
|
321
|
+
readonly ref: Ref.Ref<HashMap.HashMap<string, unknown>>;
|
|
322
|
+
}
|
|
323
|
+
declare const ResolverContextStore: Context.Tag<ResolverContextStore, ResolverContextStore>;
|
|
324
|
+
/**
|
|
325
|
+
* Create a Layer that provides the ResolverContextStore.
|
|
326
|
+
* This should be included in the request layer.
|
|
327
|
+
*/
|
|
328
|
+
declare const makeStoreLayer: () => Effect.Effect<Layer.Layer<ResolverContextStore>>;
|
|
329
|
+
/**
|
|
330
|
+
* Create a Layer that provides an empty ResolverContextStore.
|
|
331
|
+
* Convenience function for creating a fresh store layer.
|
|
332
|
+
*/
|
|
333
|
+
declare const storeLayer: Layer.Layer<ResolverContextStore>;
|
|
334
|
+
/**
|
|
335
|
+
* Create a new resolver context slot.
|
|
336
|
+
*
|
|
337
|
+
* The name is used for error messages when the context is accessed but not set.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```typescript
|
|
341
|
+
* const AuthPrincipal = ResolverContext.make<User>("AuthPrincipal")
|
|
342
|
+
* const TenantId = ResolverContext.make<string>("TenantId")
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
declare const make: <A>(name: string) => ResolverContextSlot<A>;
|
|
346
|
+
/**
|
|
347
|
+
* Get a value from the resolver context.
|
|
348
|
+
*
|
|
349
|
+
* Fails with MissingResolverContextError if the context was not set
|
|
350
|
+
* by a parent resolver or directive.
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```typescript
|
|
354
|
+
* const effect = Effect.gen(function*() {
|
|
355
|
+
* const user = yield* ResolverContext.get(AuthPrincipal)
|
|
356
|
+
* // user is typed as User
|
|
357
|
+
* })
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
declare const get: <A>(slot: ResolverContextSlot<A>) => Effect.Effect<A, MissingResolverContextError, ResolverContextStore>;
|
|
361
|
+
/**
|
|
362
|
+
* Get a value from the resolver context as an Option.
|
|
363
|
+
*
|
|
364
|
+
* Returns None if the context was not set, instead of failing.
|
|
365
|
+
* Useful when context is optional.
|
|
366
|
+
*/
|
|
367
|
+
declare const getOption: <A>(slot: ResolverContextSlot<A>) => Effect.Effect<Option.Option<A>, never, ResolverContextStore>;
|
|
368
|
+
/**
|
|
369
|
+
* Set a value in the resolver context.
|
|
370
|
+
*
|
|
371
|
+
* The value will be available to all subsequent resolver calls in this request.
|
|
372
|
+
* This mutates the request-scoped store, so nested resolvers will see the value.
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```typescript
|
|
376
|
+
* // In a directive
|
|
377
|
+
* const withAuth = (effect) => Effect.gen(function*() {
|
|
378
|
+
* const user = yield* validateJwt()
|
|
379
|
+
* yield* ResolverContext.set(AuthPrincipal, user)
|
|
380
|
+
* return yield* effect
|
|
381
|
+
* })
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
declare const set: <A>(slot: ResolverContextSlot<A>, value: A) => Effect.Effect<void, never, ResolverContextStore>;
|
|
385
|
+
/**
|
|
386
|
+
* Set multiple context values at once.
|
|
387
|
+
*/
|
|
388
|
+
declare const setMany: (values: ReadonlyArray<readonly [ResolverContextSlot<any>, any]>) => Effect.Effect<void, never, ResolverContextStore>;
|
|
389
|
+
/**
|
|
390
|
+
* Check if a context slot has a value set.
|
|
391
|
+
*/
|
|
392
|
+
declare const has: <A>(slot: ResolverContextSlot<A>) => Effect.Effect<boolean, never, ResolverContextStore>;
|
|
393
|
+
/**
|
|
394
|
+
* Get a value or return a default if not set.
|
|
395
|
+
*/
|
|
396
|
+
declare const getOrElse: <A>(slot: ResolverContextSlot<A>, orElse: () => A) => Effect.Effect<A, never, ResolverContextStore>;
|
|
397
|
+
/**
|
|
398
|
+
* Run an effect with a temporary context value.
|
|
399
|
+
* The value is set before the effect runs and removed after.
|
|
400
|
+
* Useful for scoped context that shouldn't persist.
|
|
401
|
+
*/
|
|
402
|
+
declare const scoped: <A>(slot: ResolverContextSlot<A>, value: A) => <B, E, R>(effect: Effect.Effect<B, E, R>) => Effect.Effect<B, E, R | ResolverContextStore>;
|
|
403
|
+
/**
|
|
404
|
+
* Namespace for ResolverContext functions
|
|
405
|
+
*/
|
|
406
|
+
declare const ResolverContext: {
|
|
407
|
+
readonly make: <A>(name: string) => ResolverContextSlot<A>;
|
|
408
|
+
readonly get: <A>(slot: ResolverContextSlot<A>) => Effect.Effect<A, MissingResolverContextError, ResolverContextStore>;
|
|
409
|
+
readonly getOption: <A>(slot: ResolverContextSlot<A>) => Effect.Effect<Option.Option<A>, never, ResolverContextStore>;
|
|
410
|
+
readonly set: <A>(slot: ResolverContextSlot<A>, value: A) => Effect.Effect<void, never, ResolverContextStore>;
|
|
411
|
+
readonly setMany: (values: ReadonlyArray<readonly [ResolverContextSlot<any>, any]>) => Effect.Effect<void, never, ResolverContextStore>;
|
|
412
|
+
readonly has: <A>(slot: ResolverContextSlot<A>) => Effect.Effect<boolean, never, ResolverContextStore>;
|
|
413
|
+
readonly getOrElse: <A>(slot: ResolverContextSlot<A>, orElse: () => A) => Effect.Effect<A, never, ResolverContextStore>;
|
|
414
|
+
readonly scoped: <A>(slot: ResolverContextSlot<A>, value: A) => <B, E, R>(effect: Effect.Effect<B, E, R>) => Effect.Effect<B, E, R | ResolverContextStore>;
|
|
415
|
+
readonly storeLayer: Layer.Layer<ResolverContextStore, never, never>;
|
|
416
|
+
readonly makeStoreLayer: () => Effect.Effect<Layer.Layer<ResolverContextStore>>;
|
|
417
|
+
readonly Store: Context.Tag<ResolverContextStore, ResolverContextStore>;
|
|
418
|
+
readonly MissingResolverContextError: typeof MissingResolverContextError;
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Configuration for the analyzer extension
|
|
423
|
+
*/
|
|
424
|
+
interface AnalyzerExtensionConfig {
|
|
425
|
+
/**
|
|
426
|
+
* Include the total complexity score in the response.
|
|
427
|
+
* @default true
|
|
428
|
+
*/
|
|
429
|
+
readonly includeComplexity?: boolean;
|
|
430
|
+
/**
|
|
431
|
+
* Include the maximum query depth in the response.
|
|
432
|
+
* @default true
|
|
433
|
+
*/
|
|
434
|
+
readonly includeDepth?: boolean;
|
|
435
|
+
/**
|
|
436
|
+
* Include the total field count in the response.
|
|
437
|
+
* @default false
|
|
438
|
+
*/
|
|
439
|
+
readonly includeFieldCount?: boolean;
|
|
440
|
+
/**
|
|
441
|
+
* Include the alias count in the response.
|
|
442
|
+
* @default false
|
|
443
|
+
*/
|
|
444
|
+
readonly includeAliasCount?: boolean;
|
|
445
|
+
/**
|
|
446
|
+
* The key to use in the response extensions object.
|
|
447
|
+
* @default "analyzer"
|
|
448
|
+
*/
|
|
449
|
+
readonly key?: string;
|
|
450
|
+
/**
|
|
451
|
+
* Thresholds for logging warnings when exceeded.
|
|
452
|
+
* When a metric exceeds its threshold, a warning is logged.
|
|
453
|
+
*/
|
|
454
|
+
readonly thresholds?: {
|
|
455
|
+
readonly depth?: number;
|
|
456
|
+
readonly complexity?: number;
|
|
457
|
+
readonly fieldCount?: number;
|
|
458
|
+
readonly aliasCount?: number;
|
|
459
|
+
};
|
|
460
|
+
/**
|
|
461
|
+
* Default complexity cost for fields without explicit costs.
|
|
462
|
+
* @default 1
|
|
463
|
+
*/
|
|
464
|
+
readonly defaultFieldComplexity?: number;
|
|
465
|
+
/**
|
|
466
|
+
* Optional field complexity overrides.
|
|
467
|
+
* If not provided, uses the field complexities from the schema builder
|
|
468
|
+
* (passed via ExecutionArgs).
|
|
469
|
+
*/
|
|
470
|
+
readonly fieldComplexities?: FieldComplexityMap;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Output format for analyzer extension
|
|
474
|
+
*/
|
|
475
|
+
interface AnalyzerOutput {
|
|
476
|
+
complexity?: number;
|
|
477
|
+
depth?: number;
|
|
478
|
+
fieldCount?: number;
|
|
479
|
+
aliasCount?: number;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Create an analyzer extension that reports query complexity metrics
|
|
483
|
+
* in the response extensions field.
|
|
484
|
+
*
|
|
485
|
+
* Similar to async-graphql's Analyzer extension, this allows you to
|
|
486
|
+
* monitor the complexity of incoming queries without blocking execution.
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```typescript
|
|
490
|
+
* // Basic usage - reports complexity and depth
|
|
491
|
+
* const analyzer = createAnalyzerExtension()
|
|
492
|
+
*
|
|
493
|
+
* // With all metrics and warnings
|
|
494
|
+
* const analyzer = createAnalyzerExtension({
|
|
495
|
+
* includeFieldCount: true,
|
|
496
|
+
* includeAliasCount: true,
|
|
497
|
+
* thresholds: {
|
|
498
|
+
* depth: 10,
|
|
499
|
+
* complexity: 100,
|
|
500
|
+
* },
|
|
501
|
+
* })
|
|
502
|
+
*
|
|
503
|
+
* // Add to schema builder
|
|
504
|
+
* const builder = GraphQLSchemaBuilder.empty.pipe(
|
|
505
|
+
* extension(analyzer),
|
|
506
|
+
* // ...queries, mutations, etc.
|
|
507
|
+
* )
|
|
508
|
+
*
|
|
509
|
+
* // Response will include:
|
|
510
|
+
* // {
|
|
511
|
+
* // "data": { ... },
|
|
512
|
+
* // "extensions": {
|
|
513
|
+
* // "analyzer": {
|
|
514
|
+
* // "complexity": 42,
|
|
515
|
+
* // "depth": 3
|
|
516
|
+
* // }
|
|
517
|
+
* // }
|
|
518
|
+
* // }
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
declare const createAnalyzerExtension: (config?: AnalyzerExtensionConfig) => GraphQLExtension<ExtensionsService>;
|
|
522
|
+
|
|
523
|
+
export { type AdditionalField, type AnalyzerExtensionConfig, type AnalyzerOutput, AuthorizationError, ExtensionsService, FieldComplexityMap, GraphQLError, GraphQLExtension, GraphQLRequestContext, Loader, type LoaderDef, type LoaderInstances, LoaderRegistry, MissingResolverContextError, NotFoundError, ResolverContext, type ResolverContextSlot, ResolverContextStore, ValidationError, createAnalyzerExtension, get, getOption, getOrElse, has, make, makeRequestContextLayer, makeStoreLayer, scoped, set, setMany, storeLayer, toGraphQLArgs, toGraphQLInputType, toGraphQLObjectType, toGraphQLType };
|