@cosmneo/onion-lasagna 0.3.0 → 0.4.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/dist/{chunk-XWKHOLIP.js → chunk-4HMXTGHK.js} +2 -2
- package/dist/chunk-4RFWJ5XZ.js +192 -0
- package/dist/chunk-4RFWJ5XZ.js.map +1 -0
- package/dist/{chunk-4BVOLXDJ.js → chunk-4YBAV6LZ.js} +2 -2
- package/dist/chunk-ANLXZHUS.js +230 -0
- package/dist/chunk-ANLXZHUS.js.map +1 -0
- package/dist/chunk-BG2FY27M.js +36 -0
- package/dist/chunk-BG2FY27M.js.map +1 -0
- package/dist/chunk-FEY2GSVT.js +1 -0
- package/dist/chunk-FEY2GSVT.js.map +1 -0
- package/dist/{chunk-2BVCU32G.js → chunk-HNEAH6OZ.js} +121 -2
- package/dist/chunk-HNEAH6OZ.js.map +1 -0
- package/dist/chunk-NQMFWI6Q.js +1 -0
- package/dist/chunk-NQMFWI6Q.js.map +1 -0
- package/dist/chunk-TZRBETT3.js +127 -0
- package/dist/chunk-TZRBETT3.js.map +1 -0
- package/dist/{chunk-MF2JDREK.js → chunk-UNVB4INM.js} +1 -1
- package/dist/{chunk-MF2JDREK.js.map → chunk-UNVB4INM.js.map} +1 -1
- package/dist/chunk-VBG3UYQR.js +119 -0
- package/dist/chunk-VBG3UYQR.js.map +1 -0
- package/dist/events/index.js +3 -4
- package/dist/events/server/index.js +3 -4
- package/dist/events/shared/index.js +2 -3
- package/dist/graphql/field/index.cjs +189 -0
- package/dist/graphql/field/index.cjs.map +1 -0
- package/dist/graphql/field/index.d.cts +214 -0
- package/dist/graphql/field/index.d.ts +214 -0
- package/dist/graphql/field/index.js +25 -0
- package/dist/graphql/field/index.js.map +1 -0
- package/dist/graphql/index.cjs +1148 -0
- package/dist/graphql/index.cjs.map +1 -0
- package/dist/graphql/index.d.cts +8 -0
- package/dist/graphql/index.d.ts +8 -0
- package/dist/graphql/index.js +49 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/sdl/index.cjs +241 -0
- package/dist/graphql/sdl/index.cjs.map +1 -0
- package/dist/graphql/sdl/index.d.cts +77 -0
- package/dist/graphql/sdl/index.d.ts +77 -0
- package/dist/graphql/sdl/index.js +8 -0
- package/dist/graphql/sdl/index.js.map +1 -0
- package/dist/graphql/server/index.cjs +505 -0
- package/dist/graphql/server/index.cjs.map +1 -0
- package/dist/graphql/server/index.d.cts +268 -0
- package/dist/graphql/server/index.d.ts +268 -0
- package/dist/graphql/server/index.js +15 -0
- package/dist/graphql/server/index.js.map +1 -0
- package/dist/graphql/shared/index.cjs +586 -0
- package/dist/graphql/shared/index.cjs.map +1 -0
- package/dist/graphql/shared/index.d.cts +82 -0
- package/dist/graphql/shared/index.d.ts +82 -0
- package/dist/graphql/shared/index.js +16 -0
- package/dist/graphql/shared/index.js.map +1 -0
- package/dist/http/index.cjs.map +1 -1
- package/dist/http/index.js +2 -3
- package/dist/http/route/index.cjs.map +1 -1
- package/dist/http/route/index.d.cts +4 -0
- package/dist/http/route/index.d.ts +4 -0
- package/dist/http/route/index.js +1 -1
- package/dist/http/shared/index.js +1 -2
- package/dist/index.cjs +672 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +43 -1
- package/dist/index.js.map +1 -1
- package/dist/schema-definition.type-C9PntBVc.d.cts +166 -0
- package/dist/schema-definition.type-CuhQLDr0.d.ts +166 -0
- package/package.json +31 -1
- package/dist/chunk-2BVCU32G.js.map +0 -1
- package/dist/chunk-H5TNDC5U.js +0 -138
- package/dist/chunk-H5TNDC5U.js.map +0 -1
- /package/dist/{chunk-XWKHOLIP.js.map → chunk-4HMXTGHK.js.map} +0 -0
- /package/dist/{chunk-4BVOLXDJ.js.map → chunk-4YBAV6LZ.js.map} +0 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { b as GraphQLFieldDefinition, G as GraphQLOperationType, d as GraphQLSchemaConfig, f as GraphQLSchemaDefinition, S as SchemaKeys, g as GetField } from '../../schema-definition.type-C9PntBVc.cjs';
|
|
2
|
+
export { U as UseCasePort } from '../../types-afYpL7Ap.cjs';
|
|
3
|
+
import '../../http/schema/types.cjs';
|
|
4
|
+
import '../../router-definition.type-BElX-Pl4.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview Server types for the GraphQL field system.
|
|
8
|
+
*
|
|
9
|
+
* @module graphql/server/types
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Validated arguments with typed data.
|
|
14
|
+
* This is what handlers receive after input validation passes.
|
|
15
|
+
*/
|
|
16
|
+
interface ValidatedArgs<TField extends GraphQLFieldDefinition> {
|
|
17
|
+
/** Validated input arguments. */
|
|
18
|
+
readonly input: TField['_types']['input'];
|
|
19
|
+
/** Raw unvalidated arguments for advanced use cases. */
|
|
20
|
+
readonly raw: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Typed GraphQL context based on field definition.
|
|
24
|
+
* If the field defines a context schema, this will be the validated type.
|
|
25
|
+
* Otherwise, it falls back to the generic GraphQLHandlerContext.
|
|
26
|
+
*/
|
|
27
|
+
type TypedGraphQLContext<TField extends GraphQLFieldDefinition> = TField['_types']['context'] extends undefined ? GraphQLHandlerContext : TField['_types']['context'];
|
|
28
|
+
/**
|
|
29
|
+
* Context passed to GraphQL handlers.
|
|
30
|
+
* Can be extended with custom context via graphqlRoutes options.
|
|
31
|
+
*/
|
|
32
|
+
interface GraphQLHandlerContext {
|
|
33
|
+
/** Request ID for tracing. */
|
|
34
|
+
readonly requestId?: string;
|
|
35
|
+
/** Additional context data. */
|
|
36
|
+
readonly [key: string]: unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Handler configuration using the use case pattern.
|
|
40
|
+
*
|
|
41
|
+
* @typeParam TField - The field definition type
|
|
42
|
+
* @typeParam TInput - Use case input type
|
|
43
|
+
* @typeParam TOutput - Use case output type
|
|
44
|
+
*/
|
|
45
|
+
interface GraphQLHandlerConfig<TField extends GraphQLFieldDefinition, TInput = void, TOutput = void> {
|
|
46
|
+
/**
|
|
47
|
+
* Maps the validated args to use case input.
|
|
48
|
+
* Both `args` and `ctx` are fully typed based on field schemas.
|
|
49
|
+
*/
|
|
50
|
+
readonly argsMapper: (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => TInput;
|
|
51
|
+
/** The use case to execute. */
|
|
52
|
+
readonly useCase: {
|
|
53
|
+
execute(input?: TInput): Promise<TOutput>;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Maps the use case output to the GraphQL response.
|
|
57
|
+
*/
|
|
58
|
+
readonly responseMapper: (output: TOutput) => TField['_types']['output'];
|
|
59
|
+
/** Middleware to run before the handler. */
|
|
60
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Simple handler function that directly returns the output.
|
|
64
|
+
* Use this for query and mutation fields.
|
|
65
|
+
*/
|
|
66
|
+
type SimpleGraphQLHandlerFn<TField extends GraphQLFieldDefinition> = (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => Promise<TField['_types']['output']> | TField['_types']['output'];
|
|
67
|
+
/**
|
|
68
|
+
* Subscription handler function that returns an async iterable.
|
|
69
|
+
* Each yielded value is sent to the subscriber.
|
|
70
|
+
*/
|
|
71
|
+
type SimpleGraphQLSubscriptionFn<TField extends GraphQLFieldDefinition> = (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => AsyncIterable<TField['_types']['output']>;
|
|
72
|
+
/**
|
|
73
|
+
* Configuration for a simple handler (no use case).
|
|
74
|
+
*/
|
|
75
|
+
interface SimpleGraphQLHandlerConfig<TField extends GraphQLFieldDefinition> {
|
|
76
|
+
readonly handler: SimpleGraphQLHandlerFn<TField>;
|
|
77
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Union of all handler config types.
|
|
81
|
+
* Used internally to store handlers in the builder.
|
|
82
|
+
*/
|
|
83
|
+
type AnyGraphQLHandlerConfig<TField extends GraphQLFieldDefinition, TInput = unknown, TOutput = unknown> = GraphQLHandlerConfig<TField, TInput, TOutput> | SimpleGraphQLHandlerConfig<TField>;
|
|
84
|
+
/**
|
|
85
|
+
* Type guard to check if config is a simple GraphQL handler.
|
|
86
|
+
*/
|
|
87
|
+
declare function isSimpleGraphQLHandlerConfig(config: AnyGraphQLHandlerConfig<GraphQLFieldDefinition, unknown, unknown>): config is SimpleGraphQLHandlerConfig<GraphQLFieldDefinition>;
|
|
88
|
+
/**
|
|
89
|
+
* GraphQL middleware function type.
|
|
90
|
+
*/
|
|
91
|
+
type GraphQLMiddlewareFunction = (args: unknown, context: GraphQLHandlerContext, next: () => Promise<unknown>) => Promise<unknown>;
|
|
92
|
+
/**
|
|
93
|
+
* Options for creating GraphQL routes.
|
|
94
|
+
*/
|
|
95
|
+
interface CreateGraphQLRoutesOptions {
|
|
96
|
+
/** Global middleware to run before all handlers. */
|
|
97
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
98
|
+
/**
|
|
99
|
+
* Whether to validate incoming args against field schemas.
|
|
100
|
+
* When enabled, invalid args throw ObjectValidationError.
|
|
101
|
+
* @default true
|
|
102
|
+
*/
|
|
103
|
+
readonly validateInput?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Whether to validate outgoing results against field schemas.
|
|
106
|
+
* When enabled, invalid results log a warning.
|
|
107
|
+
* @default true
|
|
108
|
+
*/
|
|
109
|
+
readonly validateOutput?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Context factory to create handler context.
|
|
112
|
+
*/
|
|
113
|
+
readonly createContext?: (rawContext: unknown) => GraphQLHandlerContext;
|
|
114
|
+
/**
|
|
115
|
+
* Allow partial handler configuration (not all fields need handlers).
|
|
116
|
+
* When true, missing handlers are silently skipped.
|
|
117
|
+
* When false (default), missing handlers throw an error.
|
|
118
|
+
* @default false
|
|
119
|
+
* @internal Used by builder pattern's buildPartial()
|
|
120
|
+
*/
|
|
121
|
+
readonly allowPartial?: boolean;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* GraphQL field input compatible with framework adapters.
|
|
125
|
+
* This is the output of graphqlRoutes().build().
|
|
126
|
+
*/
|
|
127
|
+
interface UnifiedGraphQLField {
|
|
128
|
+
/** Schema key path (e.g., 'users.get'). */
|
|
129
|
+
readonly key: string;
|
|
130
|
+
/** GraphQL operation type. */
|
|
131
|
+
readonly operation: GraphQLOperationType;
|
|
132
|
+
/** Handler function. */
|
|
133
|
+
readonly handler: (args: unknown, context: unknown) => Promise<unknown>;
|
|
134
|
+
/** Field metadata for documentation. */
|
|
135
|
+
readonly metadata: {
|
|
136
|
+
readonly fieldId?: string;
|
|
137
|
+
readonly description?: string;
|
|
138
|
+
readonly tags?: readonly string[];
|
|
139
|
+
readonly deprecated?: boolean;
|
|
140
|
+
readonly deprecationReason?: string;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @fileoverview Builder pattern for creating type-safe GraphQL routes.
|
|
146
|
+
*
|
|
147
|
+
* The `graphqlRoutes` function returns a builder that provides 100% type inference
|
|
148
|
+
* for all handler parameters — no manual type annotations required.
|
|
149
|
+
*
|
|
150
|
+
* @module graphql/server/graphql-routes-builder
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Error type displayed when attempting to build() with missing handlers.
|
|
155
|
+
* The `___missingFields` property shows which fields are missing.
|
|
156
|
+
*/
|
|
157
|
+
interface MissingHandlersError<TMissing extends string> {
|
|
158
|
+
/**
|
|
159
|
+
* This error indicates that not all GraphQL fields have handlers.
|
|
160
|
+
* Use buildPartial() to build with only the defined handlers,
|
|
161
|
+
* or add handlers for the missing fields.
|
|
162
|
+
*/
|
|
163
|
+
(options?: never): never;
|
|
164
|
+
/** Fields that are missing handlers. */
|
|
165
|
+
readonly ___missingFields: TMissing;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Handler configuration for the builder pattern.
|
|
169
|
+
*/
|
|
170
|
+
interface BuilderGraphQLHandlerConfig<TField extends GraphQLFieldDefinition, TInput, TOutput> {
|
|
171
|
+
/**
|
|
172
|
+
* Maps the validated args to use case input.
|
|
173
|
+
* Both `args` and `ctx` are fully typed based on field schemas.
|
|
174
|
+
*/
|
|
175
|
+
readonly argsMapper: (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => TInput;
|
|
176
|
+
/** The use case to execute. */
|
|
177
|
+
readonly useCase: {
|
|
178
|
+
execute(input?: TInput): Promise<TOutput>;
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Maps the use case output to the GraphQL response.
|
|
182
|
+
*/
|
|
183
|
+
readonly responseMapper: (output: TOutput) => TField['_types']['output'];
|
|
184
|
+
/** Middleware to run before the handler. */
|
|
185
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Builder interface for creating type-safe GraphQL routes.
|
|
189
|
+
*
|
|
190
|
+
* Each `.handle()` call captures the specific field type and provides
|
|
191
|
+
* full type inference for argsMapper, useCase, and responseMapper.
|
|
192
|
+
*
|
|
193
|
+
* @typeParam T - The schema configuration type
|
|
194
|
+
* @typeParam THandled - Union of field keys that have handlers (accumulates)
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const fields = graphqlRoutes(projectSchema)
|
|
199
|
+
* .handleWithUseCase('projects.create', {
|
|
200
|
+
* argsMapper: (args, ctx) => ({
|
|
201
|
+
* name: args.input.name,
|
|
202
|
+
* createdBy: ctx.userId,
|
|
203
|
+
* }),
|
|
204
|
+
* useCase: createProjectUseCase,
|
|
205
|
+
* responseMapper: (output) => ({ projectId: output.projectId }),
|
|
206
|
+
* })
|
|
207
|
+
* .handle('projects.list', async (args) => {
|
|
208
|
+
* return allProjects;
|
|
209
|
+
* })
|
|
210
|
+
* .build();
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
interface GraphQLRoutesBuilder<T extends GraphQLSchemaConfig, THandled extends string = never> {
|
|
214
|
+
/**
|
|
215
|
+
* Register a simple handler for a field.
|
|
216
|
+
* The handler receives validated args and context, returns output directly.
|
|
217
|
+
*/
|
|
218
|
+
handle<K extends Exclude<SchemaKeys<T>, THandled>>(key: K, handlerOrConfig: SimpleGraphQLHandlerFn<GetField<T, K>> | SimpleGraphQLHandlerConfig<GetField<T, K>>): GraphQLRoutesBuilder<T, THandled | K>;
|
|
219
|
+
/**
|
|
220
|
+
* Register a handler using the use case pattern.
|
|
221
|
+
* Follows: argsMapper → useCase.execute() → responseMapper
|
|
222
|
+
*/
|
|
223
|
+
handleWithUseCase<K extends Exclude<SchemaKeys<T>, THandled>, TInput, TOutput>(key: K, config: BuilderGraphQLHandlerConfig<GetField<T, K>, TInput, TOutput>): GraphQLRoutesBuilder<T, THandled | K>;
|
|
224
|
+
/**
|
|
225
|
+
* Build the fields array for framework adapter registration.
|
|
226
|
+
*
|
|
227
|
+
* This method is only available when ALL fields have handlers.
|
|
228
|
+
* If some fields are missing handlers, use `buildPartial()` instead.
|
|
229
|
+
*/
|
|
230
|
+
build: [Exclude<SchemaKeys<T>, THandled>] extends [never] ? (options?: CreateGraphQLRoutesOptions) => UnifiedGraphQLField[] : MissingHandlersError<Exclude<SchemaKeys<T>, THandled>>;
|
|
231
|
+
/**
|
|
232
|
+
* Build fields for only the defined handlers.
|
|
233
|
+
* No compile-time enforcement of completeness.
|
|
234
|
+
*/
|
|
235
|
+
buildPartial(options?: CreateGraphQLRoutesOptions): UnifiedGraphQLField[];
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Creates a type-safe GraphQL routes builder for a schema.
|
|
239
|
+
*
|
|
240
|
+
* The builder pattern provides 100% type inference for all handler parameters:
|
|
241
|
+
* - `args.input` is typed from the field's input schema
|
|
242
|
+
* - `ctx` is typed from the field's context schema (or GraphQLHandlerContext)
|
|
243
|
+
* - `output` in responseMapper is typed from the use case
|
|
244
|
+
*
|
|
245
|
+
* @param schema - GraphQL schema definition or schema config
|
|
246
|
+
* @returns Builder for registering handlers
|
|
247
|
+
*
|
|
248
|
+
* @example Basic usage
|
|
249
|
+
* ```typescript
|
|
250
|
+
* import { graphqlRoutes } from '@cosmneo/onion-lasagna/graphql/server';
|
|
251
|
+
* import { projectSchema } from './schema';
|
|
252
|
+
*
|
|
253
|
+
* const fields = graphqlRoutes(projectSchema)
|
|
254
|
+
* .handleWithUseCase('projects.create', {
|
|
255
|
+
* argsMapper: (args, ctx) => ({
|
|
256
|
+
* name: args.input.name,
|
|
257
|
+
* createdBy: ctx.userId,
|
|
258
|
+
* }),
|
|
259
|
+
* useCase: createProjectUseCase,
|
|
260
|
+
* responseMapper: (output) => ({ projectId: output.projectId }),
|
|
261
|
+
* })
|
|
262
|
+
* .handle('projects.list', async () => allProjects)
|
|
263
|
+
* .build();
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
declare function graphqlRoutes<T extends GraphQLSchemaConfig>(schema: T | GraphQLSchemaDefinition<T>): GraphQLRoutesBuilder<T, never>;
|
|
267
|
+
|
|
268
|
+
export { type AnyGraphQLHandlerConfig, type BuilderGraphQLHandlerConfig, type CreateGraphQLRoutesOptions, type GraphQLHandlerConfig, type GraphQLHandlerContext, type GraphQLMiddlewareFunction, type GraphQLRoutesBuilder, type MissingHandlersError, type SimpleGraphQLHandlerConfig, type SimpleGraphQLHandlerFn, type SimpleGraphQLSubscriptionFn, type TypedGraphQLContext, type UnifiedGraphQLField, type ValidatedArgs, graphqlRoutes, isSimpleGraphQLHandlerConfig };
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { b as GraphQLFieldDefinition, G as GraphQLOperationType, d as GraphQLSchemaConfig, f as GraphQLSchemaDefinition, S as SchemaKeys, g as GetField } from '../../schema-definition.type-CuhQLDr0.js';
|
|
2
|
+
export { U as UseCasePort } from '../../types-B6Q1iCgf.js';
|
|
3
|
+
import '../../http/schema/types.js';
|
|
4
|
+
import '../../router-definition.type-DxG8ncJZ.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview Server types for the GraphQL field system.
|
|
8
|
+
*
|
|
9
|
+
* @module graphql/server/types
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Validated arguments with typed data.
|
|
14
|
+
* This is what handlers receive after input validation passes.
|
|
15
|
+
*/
|
|
16
|
+
interface ValidatedArgs<TField extends GraphQLFieldDefinition> {
|
|
17
|
+
/** Validated input arguments. */
|
|
18
|
+
readonly input: TField['_types']['input'];
|
|
19
|
+
/** Raw unvalidated arguments for advanced use cases. */
|
|
20
|
+
readonly raw: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Typed GraphQL context based on field definition.
|
|
24
|
+
* If the field defines a context schema, this will be the validated type.
|
|
25
|
+
* Otherwise, it falls back to the generic GraphQLHandlerContext.
|
|
26
|
+
*/
|
|
27
|
+
type TypedGraphQLContext<TField extends GraphQLFieldDefinition> = TField['_types']['context'] extends undefined ? GraphQLHandlerContext : TField['_types']['context'];
|
|
28
|
+
/**
|
|
29
|
+
* Context passed to GraphQL handlers.
|
|
30
|
+
* Can be extended with custom context via graphqlRoutes options.
|
|
31
|
+
*/
|
|
32
|
+
interface GraphQLHandlerContext {
|
|
33
|
+
/** Request ID for tracing. */
|
|
34
|
+
readonly requestId?: string;
|
|
35
|
+
/** Additional context data. */
|
|
36
|
+
readonly [key: string]: unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Handler configuration using the use case pattern.
|
|
40
|
+
*
|
|
41
|
+
* @typeParam TField - The field definition type
|
|
42
|
+
* @typeParam TInput - Use case input type
|
|
43
|
+
* @typeParam TOutput - Use case output type
|
|
44
|
+
*/
|
|
45
|
+
interface GraphQLHandlerConfig<TField extends GraphQLFieldDefinition, TInput = void, TOutput = void> {
|
|
46
|
+
/**
|
|
47
|
+
* Maps the validated args to use case input.
|
|
48
|
+
* Both `args` and `ctx` are fully typed based on field schemas.
|
|
49
|
+
*/
|
|
50
|
+
readonly argsMapper: (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => TInput;
|
|
51
|
+
/** The use case to execute. */
|
|
52
|
+
readonly useCase: {
|
|
53
|
+
execute(input?: TInput): Promise<TOutput>;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Maps the use case output to the GraphQL response.
|
|
57
|
+
*/
|
|
58
|
+
readonly responseMapper: (output: TOutput) => TField['_types']['output'];
|
|
59
|
+
/** Middleware to run before the handler. */
|
|
60
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Simple handler function that directly returns the output.
|
|
64
|
+
* Use this for query and mutation fields.
|
|
65
|
+
*/
|
|
66
|
+
type SimpleGraphQLHandlerFn<TField extends GraphQLFieldDefinition> = (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => Promise<TField['_types']['output']> | TField['_types']['output'];
|
|
67
|
+
/**
|
|
68
|
+
* Subscription handler function that returns an async iterable.
|
|
69
|
+
* Each yielded value is sent to the subscriber.
|
|
70
|
+
*/
|
|
71
|
+
type SimpleGraphQLSubscriptionFn<TField extends GraphQLFieldDefinition> = (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => AsyncIterable<TField['_types']['output']>;
|
|
72
|
+
/**
|
|
73
|
+
* Configuration for a simple handler (no use case).
|
|
74
|
+
*/
|
|
75
|
+
interface SimpleGraphQLHandlerConfig<TField extends GraphQLFieldDefinition> {
|
|
76
|
+
readonly handler: SimpleGraphQLHandlerFn<TField>;
|
|
77
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Union of all handler config types.
|
|
81
|
+
* Used internally to store handlers in the builder.
|
|
82
|
+
*/
|
|
83
|
+
type AnyGraphQLHandlerConfig<TField extends GraphQLFieldDefinition, TInput = unknown, TOutput = unknown> = GraphQLHandlerConfig<TField, TInput, TOutput> | SimpleGraphQLHandlerConfig<TField>;
|
|
84
|
+
/**
|
|
85
|
+
* Type guard to check if config is a simple GraphQL handler.
|
|
86
|
+
*/
|
|
87
|
+
declare function isSimpleGraphQLHandlerConfig(config: AnyGraphQLHandlerConfig<GraphQLFieldDefinition, unknown, unknown>): config is SimpleGraphQLHandlerConfig<GraphQLFieldDefinition>;
|
|
88
|
+
/**
|
|
89
|
+
* GraphQL middleware function type.
|
|
90
|
+
*/
|
|
91
|
+
type GraphQLMiddlewareFunction = (args: unknown, context: GraphQLHandlerContext, next: () => Promise<unknown>) => Promise<unknown>;
|
|
92
|
+
/**
|
|
93
|
+
* Options for creating GraphQL routes.
|
|
94
|
+
*/
|
|
95
|
+
interface CreateGraphQLRoutesOptions {
|
|
96
|
+
/** Global middleware to run before all handlers. */
|
|
97
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
98
|
+
/**
|
|
99
|
+
* Whether to validate incoming args against field schemas.
|
|
100
|
+
* When enabled, invalid args throw ObjectValidationError.
|
|
101
|
+
* @default true
|
|
102
|
+
*/
|
|
103
|
+
readonly validateInput?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Whether to validate outgoing results against field schemas.
|
|
106
|
+
* When enabled, invalid results log a warning.
|
|
107
|
+
* @default true
|
|
108
|
+
*/
|
|
109
|
+
readonly validateOutput?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Context factory to create handler context.
|
|
112
|
+
*/
|
|
113
|
+
readonly createContext?: (rawContext: unknown) => GraphQLHandlerContext;
|
|
114
|
+
/**
|
|
115
|
+
* Allow partial handler configuration (not all fields need handlers).
|
|
116
|
+
* When true, missing handlers are silently skipped.
|
|
117
|
+
* When false (default), missing handlers throw an error.
|
|
118
|
+
* @default false
|
|
119
|
+
* @internal Used by builder pattern's buildPartial()
|
|
120
|
+
*/
|
|
121
|
+
readonly allowPartial?: boolean;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* GraphQL field input compatible with framework adapters.
|
|
125
|
+
* This is the output of graphqlRoutes().build().
|
|
126
|
+
*/
|
|
127
|
+
interface UnifiedGraphQLField {
|
|
128
|
+
/** Schema key path (e.g., 'users.get'). */
|
|
129
|
+
readonly key: string;
|
|
130
|
+
/** GraphQL operation type. */
|
|
131
|
+
readonly operation: GraphQLOperationType;
|
|
132
|
+
/** Handler function. */
|
|
133
|
+
readonly handler: (args: unknown, context: unknown) => Promise<unknown>;
|
|
134
|
+
/** Field metadata for documentation. */
|
|
135
|
+
readonly metadata: {
|
|
136
|
+
readonly fieldId?: string;
|
|
137
|
+
readonly description?: string;
|
|
138
|
+
readonly tags?: readonly string[];
|
|
139
|
+
readonly deprecated?: boolean;
|
|
140
|
+
readonly deprecationReason?: string;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @fileoverview Builder pattern for creating type-safe GraphQL routes.
|
|
146
|
+
*
|
|
147
|
+
* The `graphqlRoutes` function returns a builder that provides 100% type inference
|
|
148
|
+
* for all handler parameters — no manual type annotations required.
|
|
149
|
+
*
|
|
150
|
+
* @module graphql/server/graphql-routes-builder
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Error type displayed when attempting to build() with missing handlers.
|
|
155
|
+
* The `___missingFields` property shows which fields are missing.
|
|
156
|
+
*/
|
|
157
|
+
interface MissingHandlersError<TMissing extends string> {
|
|
158
|
+
/**
|
|
159
|
+
* This error indicates that not all GraphQL fields have handlers.
|
|
160
|
+
* Use buildPartial() to build with only the defined handlers,
|
|
161
|
+
* or add handlers for the missing fields.
|
|
162
|
+
*/
|
|
163
|
+
(options?: never): never;
|
|
164
|
+
/** Fields that are missing handlers. */
|
|
165
|
+
readonly ___missingFields: TMissing;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Handler configuration for the builder pattern.
|
|
169
|
+
*/
|
|
170
|
+
interface BuilderGraphQLHandlerConfig<TField extends GraphQLFieldDefinition, TInput, TOutput> {
|
|
171
|
+
/**
|
|
172
|
+
* Maps the validated args to use case input.
|
|
173
|
+
* Both `args` and `ctx` are fully typed based on field schemas.
|
|
174
|
+
*/
|
|
175
|
+
readonly argsMapper: (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => TInput;
|
|
176
|
+
/** The use case to execute. */
|
|
177
|
+
readonly useCase: {
|
|
178
|
+
execute(input?: TInput): Promise<TOutput>;
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Maps the use case output to the GraphQL response.
|
|
182
|
+
*/
|
|
183
|
+
readonly responseMapper: (output: TOutput) => TField['_types']['output'];
|
|
184
|
+
/** Middleware to run before the handler. */
|
|
185
|
+
readonly middleware?: readonly GraphQLMiddlewareFunction[];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Builder interface for creating type-safe GraphQL routes.
|
|
189
|
+
*
|
|
190
|
+
* Each `.handle()` call captures the specific field type and provides
|
|
191
|
+
* full type inference for argsMapper, useCase, and responseMapper.
|
|
192
|
+
*
|
|
193
|
+
* @typeParam T - The schema configuration type
|
|
194
|
+
* @typeParam THandled - Union of field keys that have handlers (accumulates)
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const fields = graphqlRoutes(projectSchema)
|
|
199
|
+
* .handleWithUseCase('projects.create', {
|
|
200
|
+
* argsMapper: (args, ctx) => ({
|
|
201
|
+
* name: args.input.name,
|
|
202
|
+
* createdBy: ctx.userId,
|
|
203
|
+
* }),
|
|
204
|
+
* useCase: createProjectUseCase,
|
|
205
|
+
* responseMapper: (output) => ({ projectId: output.projectId }),
|
|
206
|
+
* })
|
|
207
|
+
* .handle('projects.list', async (args) => {
|
|
208
|
+
* return allProjects;
|
|
209
|
+
* })
|
|
210
|
+
* .build();
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
interface GraphQLRoutesBuilder<T extends GraphQLSchemaConfig, THandled extends string = never> {
|
|
214
|
+
/**
|
|
215
|
+
* Register a simple handler for a field.
|
|
216
|
+
* The handler receives validated args and context, returns output directly.
|
|
217
|
+
*/
|
|
218
|
+
handle<K extends Exclude<SchemaKeys<T>, THandled>>(key: K, handlerOrConfig: SimpleGraphQLHandlerFn<GetField<T, K>> | SimpleGraphQLHandlerConfig<GetField<T, K>>): GraphQLRoutesBuilder<T, THandled | K>;
|
|
219
|
+
/**
|
|
220
|
+
* Register a handler using the use case pattern.
|
|
221
|
+
* Follows: argsMapper → useCase.execute() → responseMapper
|
|
222
|
+
*/
|
|
223
|
+
handleWithUseCase<K extends Exclude<SchemaKeys<T>, THandled>, TInput, TOutput>(key: K, config: BuilderGraphQLHandlerConfig<GetField<T, K>, TInput, TOutput>): GraphQLRoutesBuilder<T, THandled | K>;
|
|
224
|
+
/**
|
|
225
|
+
* Build the fields array for framework adapter registration.
|
|
226
|
+
*
|
|
227
|
+
* This method is only available when ALL fields have handlers.
|
|
228
|
+
* If some fields are missing handlers, use `buildPartial()` instead.
|
|
229
|
+
*/
|
|
230
|
+
build: [Exclude<SchemaKeys<T>, THandled>] extends [never] ? (options?: CreateGraphQLRoutesOptions) => UnifiedGraphQLField[] : MissingHandlersError<Exclude<SchemaKeys<T>, THandled>>;
|
|
231
|
+
/**
|
|
232
|
+
* Build fields for only the defined handlers.
|
|
233
|
+
* No compile-time enforcement of completeness.
|
|
234
|
+
*/
|
|
235
|
+
buildPartial(options?: CreateGraphQLRoutesOptions): UnifiedGraphQLField[];
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Creates a type-safe GraphQL routes builder for a schema.
|
|
239
|
+
*
|
|
240
|
+
* The builder pattern provides 100% type inference for all handler parameters:
|
|
241
|
+
* - `args.input` is typed from the field's input schema
|
|
242
|
+
* - `ctx` is typed from the field's context schema (or GraphQLHandlerContext)
|
|
243
|
+
* - `output` in responseMapper is typed from the use case
|
|
244
|
+
*
|
|
245
|
+
* @param schema - GraphQL schema definition or schema config
|
|
246
|
+
* @returns Builder for registering handlers
|
|
247
|
+
*
|
|
248
|
+
* @example Basic usage
|
|
249
|
+
* ```typescript
|
|
250
|
+
* import { graphqlRoutes } from '@cosmneo/onion-lasagna/graphql/server';
|
|
251
|
+
* import { projectSchema } from './schema';
|
|
252
|
+
*
|
|
253
|
+
* const fields = graphqlRoutes(projectSchema)
|
|
254
|
+
* .handleWithUseCase('projects.create', {
|
|
255
|
+
* argsMapper: (args, ctx) => ({
|
|
256
|
+
* name: args.input.name,
|
|
257
|
+
* createdBy: ctx.userId,
|
|
258
|
+
* }),
|
|
259
|
+
* useCase: createProjectUseCase,
|
|
260
|
+
* responseMapper: (output) => ({ projectId: output.projectId }),
|
|
261
|
+
* })
|
|
262
|
+
* .handle('projects.list', async () => allProjects)
|
|
263
|
+
* .build();
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
declare function graphqlRoutes<T extends GraphQLSchemaConfig>(schema: T | GraphQLSchemaDefinition<T>): GraphQLRoutesBuilder<T, never>;
|
|
267
|
+
|
|
268
|
+
export { type AnyGraphQLHandlerConfig, type BuilderGraphQLHandlerConfig, type CreateGraphQLRoutesOptions, type GraphQLHandlerConfig, type GraphQLHandlerContext, type GraphQLMiddlewareFunction, type GraphQLRoutesBuilder, type MissingHandlersError, type SimpleGraphQLHandlerConfig, type SimpleGraphQLHandlerFn, type SimpleGraphQLSubscriptionFn, type TypedGraphQLContext, type UnifiedGraphQLField, type ValidatedArgs, graphqlRoutes, isSimpleGraphQLHandlerConfig };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
graphqlRoutes,
|
|
3
|
+
isSimpleGraphQLHandlerConfig
|
|
4
|
+
} from "../../chunk-ANLXZHUS.js";
|
|
5
|
+
import "../../chunk-VBG3UYQR.js";
|
|
6
|
+
import "../../chunk-BG2FY27M.js";
|
|
7
|
+
import "../../chunk-HNEAH6OZ.js";
|
|
8
|
+
import "../../chunk-T7S574XQ.js";
|
|
9
|
+
import "../../chunk-3BY5RBF2.js";
|
|
10
|
+
import "../../chunk-A4JUAZK4.js";
|
|
11
|
+
export {
|
|
12
|
+
graphqlRoutes,
|
|
13
|
+
isSimpleGraphQLHandlerConfig
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|