@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.
Files changed (74) hide show
  1. package/dist/{chunk-XWKHOLIP.js → chunk-4HMXTGHK.js} +2 -2
  2. package/dist/chunk-4RFWJ5XZ.js +192 -0
  3. package/dist/chunk-4RFWJ5XZ.js.map +1 -0
  4. package/dist/{chunk-4BVOLXDJ.js → chunk-4YBAV6LZ.js} +2 -2
  5. package/dist/chunk-ANLXZHUS.js +230 -0
  6. package/dist/chunk-ANLXZHUS.js.map +1 -0
  7. package/dist/chunk-BG2FY27M.js +36 -0
  8. package/dist/chunk-BG2FY27M.js.map +1 -0
  9. package/dist/chunk-FEY2GSVT.js +1 -0
  10. package/dist/chunk-FEY2GSVT.js.map +1 -0
  11. package/dist/{chunk-2BVCU32G.js → chunk-HNEAH6OZ.js} +121 -2
  12. package/dist/chunk-HNEAH6OZ.js.map +1 -0
  13. package/dist/chunk-NQMFWI6Q.js +1 -0
  14. package/dist/chunk-NQMFWI6Q.js.map +1 -0
  15. package/dist/chunk-TZRBETT3.js +127 -0
  16. package/dist/chunk-TZRBETT3.js.map +1 -0
  17. package/dist/{chunk-MF2JDREK.js → chunk-UNVB4INM.js} +1 -1
  18. package/dist/{chunk-MF2JDREK.js.map → chunk-UNVB4INM.js.map} +1 -1
  19. package/dist/chunk-VBG3UYQR.js +119 -0
  20. package/dist/chunk-VBG3UYQR.js.map +1 -0
  21. package/dist/events/index.js +3 -4
  22. package/dist/events/server/index.js +3 -4
  23. package/dist/events/shared/index.js +2 -3
  24. package/dist/graphql/field/index.cjs +189 -0
  25. package/dist/graphql/field/index.cjs.map +1 -0
  26. package/dist/graphql/field/index.d.cts +214 -0
  27. package/dist/graphql/field/index.d.ts +214 -0
  28. package/dist/graphql/field/index.js +25 -0
  29. package/dist/graphql/field/index.js.map +1 -0
  30. package/dist/graphql/index.cjs +1148 -0
  31. package/dist/graphql/index.cjs.map +1 -0
  32. package/dist/graphql/index.d.cts +8 -0
  33. package/dist/graphql/index.d.ts +8 -0
  34. package/dist/graphql/index.js +49 -0
  35. package/dist/graphql/index.js.map +1 -0
  36. package/dist/graphql/sdl/index.cjs +241 -0
  37. package/dist/graphql/sdl/index.cjs.map +1 -0
  38. package/dist/graphql/sdl/index.d.cts +77 -0
  39. package/dist/graphql/sdl/index.d.ts +77 -0
  40. package/dist/graphql/sdl/index.js +8 -0
  41. package/dist/graphql/sdl/index.js.map +1 -0
  42. package/dist/graphql/server/index.cjs +505 -0
  43. package/dist/graphql/server/index.cjs.map +1 -0
  44. package/dist/graphql/server/index.d.cts +268 -0
  45. package/dist/graphql/server/index.d.ts +268 -0
  46. package/dist/graphql/server/index.js +15 -0
  47. package/dist/graphql/server/index.js.map +1 -0
  48. package/dist/graphql/shared/index.cjs +586 -0
  49. package/dist/graphql/shared/index.cjs.map +1 -0
  50. package/dist/graphql/shared/index.d.cts +82 -0
  51. package/dist/graphql/shared/index.d.ts +82 -0
  52. package/dist/graphql/shared/index.js +16 -0
  53. package/dist/graphql/shared/index.js.map +1 -0
  54. package/dist/http/index.cjs.map +1 -1
  55. package/dist/http/index.js +2 -3
  56. package/dist/http/route/index.cjs.map +1 -1
  57. package/dist/http/route/index.d.cts +4 -0
  58. package/dist/http/route/index.d.ts +4 -0
  59. package/dist/http/route/index.js +1 -1
  60. package/dist/http/shared/index.js +1 -2
  61. package/dist/index.cjs +672 -0
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +8 -0
  64. package/dist/index.d.ts +8 -0
  65. package/dist/index.js +43 -1
  66. package/dist/index.js.map +1 -1
  67. package/dist/schema-definition.type-C9PntBVc.d.cts +166 -0
  68. package/dist/schema-definition.type-CuhQLDr0.d.ts +166 -0
  69. package/package.json +31 -1
  70. package/dist/chunk-2BVCU32G.js.map +0 -1
  71. package/dist/chunk-H5TNDC5U.js +0 -138
  72. package/dist/chunk-H5TNDC5U.js.map +0 -1
  73. /package/dist/{chunk-XWKHOLIP.js.map → chunk-4HMXTGHK.js.map} +0 -0
  74. /package/dist/{chunk-4BVOLXDJ.js.map → chunk-4YBAV6LZ.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapErrorToEventResult
3
- } from "./chunk-4BVOLXDJ.js";
3
+ } from "./chunk-4YBAV6LZ.js";
4
4
  import {
5
5
  collectEventHandlers,
6
6
  generateHandlerId,
@@ -188,4 +188,4 @@ export {
188
188
  isSimpleEventHandlerConfig,
189
189
  eventRoutes
190
190
  };
191
- //# sourceMappingURL=chunk-XWKHOLIP.js.map
191
+ //# sourceMappingURL=chunk-4HMXTGHK.js.map
@@ -0,0 +1,192 @@
1
+ import {
2
+ collectFields,
3
+ generateFieldId,
4
+ isSchemaDefinition
5
+ } from "./chunk-BG2FY27M.js";
6
+
7
+ // src/presentation/graphql/sdl/generate.ts
8
+ function generateGraphQLSDL(schema, config) {
9
+ const fields = isSchemaDefinition(schema) ? schema.fields : schema;
10
+ const collectedFields = collectFields(fields);
11
+ const includeDescriptions = config?.includeDescriptions ?? true;
12
+ const includeDeprecations = config?.includeDeprecations ?? true;
13
+ const queries = [];
14
+ const mutations = [];
15
+ const subscriptions = [];
16
+ for (const { key, field } of collectedFields) {
17
+ const fieldId = generateFieldId(key);
18
+ if (field.operation === "query") {
19
+ queries.push({ fieldId, field });
20
+ } else if (field.operation === "mutation") {
21
+ mutations.push({ fieldId, field });
22
+ } else if (field.operation === "subscription") {
23
+ subscriptions.push({ fieldId, field });
24
+ }
25
+ }
26
+ const namedTypes = /* @__PURE__ */ new Map();
27
+ const lines = [];
28
+ if (config?.preamble) {
29
+ lines.push(config.preamble);
30
+ lines.push("");
31
+ }
32
+ if (queries.length > 0) {
33
+ lines.push("type Query {");
34
+ for (const { fieldId, field } of queries) {
35
+ const fieldLine = buildFieldLine(
36
+ fieldId,
37
+ field,
38
+ namedTypes,
39
+ includeDescriptions,
40
+ includeDeprecations
41
+ );
42
+ lines.push(fieldLine);
43
+ }
44
+ lines.push("}");
45
+ lines.push("");
46
+ }
47
+ if (mutations.length > 0) {
48
+ lines.push("type Mutation {");
49
+ for (const { fieldId, field } of mutations) {
50
+ const fieldLine = buildFieldLine(
51
+ fieldId,
52
+ field,
53
+ namedTypes,
54
+ includeDescriptions,
55
+ includeDeprecations
56
+ );
57
+ lines.push(fieldLine);
58
+ }
59
+ lines.push("}");
60
+ lines.push("");
61
+ }
62
+ if (subscriptions.length > 0) {
63
+ lines.push("type Subscription {");
64
+ for (const { fieldId, field } of subscriptions) {
65
+ const fieldLine = buildFieldLine(
66
+ fieldId,
67
+ field,
68
+ namedTypes,
69
+ includeDescriptions,
70
+ includeDeprecations
71
+ );
72
+ lines.push(fieldLine);
73
+ }
74
+ lines.push("}");
75
+ lines.push("");
76
+ }
77
+ for (const [, typeBody] of namedTypes) {
78
+ lines.push(typeBody);
79
+ lines.push("");
80
+ }
81
+ return lines.join("\n").trimEnd() + "\n";
82
+ }
83
+ function buildFieldLine(fieldId, field, namedTypes, includeDescriptions, includeDeprecations) {
84
+ const parts = [];
85
+ if (includeDescriptions && field.docs.description) {
86
+ const escaped = field.docs.description.replace(/"""/g, '\\"""');
87
+ parts.push(` """${escaped}"""`);
88
+ }
89
+ const inputTypeName = field.input ? `${capitalize(fieldId)}Input` : void 0;
90
+ const outputTypeName = field.output ? `${capitalize(fieldId)}Output` : void 0;
91
+ if (field.input && inputTypeName) {
92
+ const jsonSchema = field.input.toJsonSchema();
93
+ namedTypes.set(inputTypeName, buildInputType(inputTypeName, jsonSchema));
94
+ }
95
+ if (field.output && outputTypeName) {
96
+ const jsonSchema = field.output.toJsonSchema();
97
+ namedTypes.set(outputTypeName, buildOutputType(outputTypeName, jsonSchema));
98
+ }
99
+ let signature = ` ${fieldId}`;
100
+ if (inputTypeName) {
101
+ signature += `(input: ${inputTypeName}!)`;
102
+ }
103
+ signature += ": ";
104
+ signature += outputTypeName ?? "JSON";
105
+ if (includeDeprecations && field.docs.deprecated) {
106
+ const reason = field.docs.deprecationReason;
107
+ signature += reason ? ` @deprecated(reason: "${escapeSDLString(reason)}")` : " @deprecated";
108
+ }
109
+ if (parts.length > 0) {
110
+ return parts.join("\n") + "\n" + signature;
111
+ }
112
+ return signature;
113
+ }
114
+ function buildInputType(typeName, jsonSchema) {
115
+ const lines = [`input ${typeName} {`];
116
+ if (jsonSchema.properties && typeof jsonSchema.properties === "object") {
117
+ const required = new Set(
118
+ Array.isArray(jsonSchema.required) ? jsonSchema.required : []
119
+ );
120
+ for (const [propName, propSchema] of Object.entries(
121
+ jsonSchema.properties
122
+ )) {
123
+ const graphqlType = jsonSchemaToGraphQLType(propSchema);
124
+ const isRequired = required.has(propName);
125
+ lines.push(` ${propName}: ${graphqlType}${isRequired ? "!" : ""}`);
126
+ }
127
+ }
128
+ lines.push("}");
129
+ return lines.join("\n");
130
+ }
131
+ function buildOutputType(typeName, jsonSchema) {
132
+ const lines = [`type ${typeName} {`];
133
+ if (jsonSchema.properties && typeof jsonSchema.properties === "object") {
134
+ const required = new Set(
135
+ Array.isArray(jsonSchema.required) ? jsonSchema.required : []
136
+ );
137
+ for (const [propName, propSchema] of Object.entries(
138
+ jsonSchema.properties
139
+ )) {
140
+ const graphqlType = jsonSchemaToGraphQLType(propSchema);
141
+ const isRequired = required.has(propName);
142
+ lines.push(` ${propName}: ${graphqlType}${isRequired ? "!" : ""}`);
143
+ }
144
+ }
145
+ lines.push("}");
146
+ return lines.join("\n");
147
+ }
148
+ function jsonSchemaToGraphQLType(schema) {
149
+ if (!schema || typeof schema !== "object") return "JSON";
150
+ if (schema.enum && Array.isArray(schema.enum)) {
151
+ return "String";
152
+ }
153
+ const type = schema.type;
154
+ switch (type) {
155
+ case "string":
156
+ return "String";
157
+ case "integer":
158
+ return "Int";
159
+ case "number":
160
+ return "Float";
161
+ case "boolean":
162
+ return "Boolean";
163
+ case "array": {
164
+ const items = schema.items;
165
+ if (items) {
166
+ return `[${jsonSchemaToGraphQLType(items)}]`;
167
+ }
168
+ return "[JSON]";
169
+ }
170
+ case "object":
171
+ return "JSON";
172
+ default:
173
+ if (schema.oneOf || schema.anyOf || schema.allOf) {
174
+ return "JSON";
175
+ }
176
+ if (schema.properties) {
177
+ return "JSON";
178
+ }
179
+ return "JSON";
180
+ }
181
+ }
182
+ function capitalize(str) {
183
+ return str.charAt(0).toUpperCase() + str.slice(1);
184
+ }
185
+ function escapeSDLString(str) {
186
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
187
+ }
188
+
189
+ export {
190
+ generateGraphQLSDL
191
+ };
192
+ //# sourceMappingURL=chunk-4RFWJ5XZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/presentation/graphql/sdl/generate.ts"],"sourcesContent":["/**\n * @fileoverview GraphQL SDL generation from schema definitions.\n *\n * The `generateGraphQLSDL` function creates a complete GraphQL Schema\n * Definition Language string from a schema definition.\n *\n * Input/output schemas are converted to JSON Schema via `toJsonSchema()`,\n * then mapped to GraphQL type definitions.\n *\n * @module graphql/sdl/generate\n */\n\nimport type { SchemaAdapter, JsonSchema } from '../../http/schema/types';\nimport type {\n GraphQLSchemaConfig,\n GraphQLSchemaDefinition,\n GraphQLFieldDefinition,\n} from '../field/types';\nimport { isSchemaDefinition, collectFields } from '../field/types';\nimport { generateFieldId } from '../field/utils';\nimport type { GraphQLSDLConfig } from './types';\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Generates a GraphQL SDL string from a schema definition.\n *\n * Walks the schema structure, extracts JSON schemas from all field\n * definitions, and builds a complete SDL with Query, Mutation, and\n * type definitions.\n *\n * @param schema - Schema definition or schema config\n * @param config - Optional SDL generation configuration\n * @returns Complete GraphQL SDL string\n *\n * @example Basic usage\n * ```typescript\n * import { generateGraphQLSDL } from '@cosmneo/onion-lasagna/graphql/sdl';\n *\n * const sdl = generateGraphQLSDL(projectSchema, {\n * preamble: 'scalar DateTime',\n * });\n *\n * console.log(sdl);\n * // type Query {\n * // projectsGet(input: ProjectsGetInput!): ProjectsGetOutput\n * // projectsList: ProjectsListOutput\n * // }\n * // ...\n * ```\n */\nexport function generateGraphQLSDL<T extends GraphQLSchemaConfig>(\n schema: T | GraphQLSchemaDefinition<T>,\n config?: GraphQLSDLConfig,\n): string {\n const fields = isSchemaDefinition(schema) ? schema.fields : schema;\n const collectedFields = collectFields(fields);\n\n const includeDescriptions = config?.includeDescriptions ?? true;\n const includeDeprecations = config?.includeDeprecations ?? true;\n\n // Partition fields by operation type\n const queries: { fieldId: string; field: GraphQLFieldDefinition }[] = [];\n const mutations: { fieldId: string; field: GraphQLFieldDefinition }[] = [];\n const subscriptions: { fieldId: string; field: GraphQLFieldDefinition }[] = [];\n\n for (const { key, field } of collectedFields) {\n const fieldId = generateFieldId(key);\n if (field.operation === 'query') {\n queries.push({ fieldId, field });\n } else if (field.operation === 'mutation') {\n mutations.push({ fieldId, field });\n } else if (field.operation === 'subscription') {\n subscriptions.push({ fieldId, field });\n }\n }\n\n // Collect all named types that need to be emitted\n const namedTypes: Map<string, string> = new Map();\n const lines: string[] = [];\n\n // Preamble\n if (config?.preamble) {\n lines.push(config.preamble);\n lines.push('');\n }\n\n // Build Query type\n if (queries.length > 0) {\n lines.push('type Query {');\n for (const { fieldId, field } of queries) {\n const fieldLine = buildFieldLine(\n fieldId,\n field,\n namedTypes,\n includeDescriptions,\n includeDeprecations,\n );\n lines.push(fieldLine);\n }\n lines.push('}');\n lines.push('');\n }\n\n // Build Mutation type\n if (mutations.length > 0) {\n lines.push('type Mutation {');\n for (const { fieldId, field } of mutations) {\n const fieldLine = buildFieldLine(\n fieldId,\n field,\n namedTypes,\n includeDescriptions,\n includeDeprecations,\n );\n lines.push(fieldLine);\n }\n lines.push('}');\n lines.push('');\n }\n\n // Build Subscription type\n if (subscriptions.length > 0) {\n lines.push('type Subscription {');\n for (const { fieldId, field } of subscriptions) {\n const fieldLine = buildFieldLine(\n fieldId,\n field,\n namedTypes,\n includeDescriptions,\n includeDeprecations,\n );\n lines.push(fieldLine);\n }\n lines.push('}');\n lines.push('');\n }\n\n // Emit named types (inputs and outputs)\n for (const [, typeBody] of namedTypes) {\n lines.push(typeBody);\n lines.push('');\n }\n\n return lines.join('\\n').trimEnd() + '\\n';\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n/**\n * Builds a single field line for a root type (Query/Mutation/Subscription).\n */\nfunction buildFieldLine(\n fieldId: string,\n field: GraphQLFieldDefinition,\n namedTypes: Map<string, string>,\n includeDescriptions: boolean,\n includeDeprecations: boolean,\n): string {\n const parts: string[] = [];\n\n // Description as SDL doc string (escaped to prevent triple-quote injection)\n if (includeDescriptions && field.docs.description) {\n const escaped = field.docs.description.replace(/\"\"\"/g, '\\\\\"\"\"');\n parts.push(` \"\"\"${escaped}\"\"\"`);\n }\n\n // Build args and return type\n const inputTypeName = field.input ? `${capitalize(fieldId)}Input` : undefined;\n const outputTypeName = field.output ? `${capitalize(fieldId)}Output` : undefined;\n\n // Register named input type\n if (field.input && inputTypeName) {\n const jsonSchema = (field.input as SchemaAdapter).toJsonSchema();\n namedTypes.set(inputTypeName, buildInputType(inputTypeName, jsonSchema));\n }\n\n // Register named output type\n if (field.output && outputTypeName) {\n const jsonSchema = (field.output as SchemaAdapter).toJsonSchema();\n namedTypes.set(outputTypeName, buildOutputType(outputTypeName, jsonSchema));\n }\n\n // Build field signature\n let signature = ` ${fieldId}`;\n\n if (inputTypeName) {\n signature += `(input: ${inputTypeName}!)`;\n }\n\n signature += ': ';\n signature += outputTypeName ?? 'JSON';\n\n // Deprecation directive\n if (includeDeprecations && field.docs.deprecated) {\n const reason = field.docs.deprecationReason;\n signature += reason ? ` @deprecated(reason: \"${escapeSDLString(reason)}\")` : ' @deprecated';\n }\n\n if (parts.length > 0) {\n return parts.join('\\n') + '\\n' + signature;\n }\n return signature;\n}\n\n/**\n * Builds a GraphQL input type from a JSON schema.\n */\nfunction buildInputType(typeName: string, jsonSchema: JsonSchema): string {\n const lines: string[] = [`input ${typeName} {`];\n\n if (jsonSchema.properties && typeof jsonSchema.properties === 'object') {\n const required = new Set(\n Array.isArray(jsonSchema.required) ? (jsonSchema.required as string[]) : [],\n );\n\n for (const [propName, propSchema] of Object.entries(\n jsonSchema.properties as Record<string, JsonSchema>,\n )) {\n const graphqlType = jsonSchemaToGraphQLType(propSchema);\n const isRequired = required.has(propName);\n lines.push(` ${propName}: ${graphqlType}${isRequired ? '!' : ''}`);\n }\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Builds a GraphQL output type from a JSON schema.\n */\nfunction buildOutputType(typeName: string, jsonSchema: JsonSchema): string {\n const lines: string[] = [`type ${typeName} {`];\n\n if (jsonSchema.properties && typeof jsonSchema.properties === 'object') {\n const required = new Set(\n Array.isArray(jsonSchema.required) ? (jsonSchema.required as string[]) : [],\n );\n\n for (const [propName, propSchema] of Object.entries(\n jsonSchema.properties as Record<string, JsonSchema>,\n )) {\n const graphqlType = jsonSchemaToGraphQLType(propSchema);\n const isRequired = required.has(propName);\n lines.push(` ${propName}: ${graphqlType}${isRequired ? '!' : ''}`);\n }\n }\n\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Converts a JSON schema to a GraphQL type string.\n */\nfunction jsonSchemaToGraphQLType(schema: JsonSchema): string {\n if (!schema || typeof schema !== 'object') return 'JSON';\n\n // Handle enum\n if (schema.enum && Array.isArray(schema.enum)) {\n return 'String';\n }\n\n // Handle type\n const type = schema.type as string | undefined;\n\n switch (type) {\n case 'string':\n return 'String';\n case 'integer':\n return 'Int';\n case 'number':\n return 'Float';\n case 'boolean':\n return 'Boolean';\n case 'array': {\n const items = schema.items as JsonSchema | undefined;\n if (items) {\n return `[${jsonSchemaToGraphQLType(items)}]`;\n }\n return '[JSON]';\n }\n case 'object':\n return 'JSON';\n default:\n // Handle oneOf, anyOf, allOf — fallback to JSON\n if (schema.oneOf || schema.anyOf || schema.allOf) {\n return 'JSON';\n }\n // Object without explicit type but has properties\n if (schema.properties) {\n return 'JSON';\n }\n return 'JSON';\n }\n}\n\n/**\n * Capitalizes the first letter of a string.\n */\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Escapes a string for use in SDL quoted string literals.\n * Handles backslashes, quotes, newlines, and triple-quote injection.\n */\nfunction escapeSDLString(str: string): string {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isErrorType
3
- } from "./chunk-H5TNDC5U.js";
3
+ } from "./chunk-HNEAH6OZ.js";
4
4
 
5
5
  // src/presentation/events/shared/error-mapping.ts
6
6
  var DLQ_ERROR_TYPES = [
@@ -51,4 +51,4 @@ function mapErrorToEventResult(error) {
51
51
  export {
52
52
  mapErrorToEventResult
53
53
  };
54
- //# sourceMappingURL=chunk-4BVOLXDJ.js.map
54
+ //# sourceMappingURL=chunk-4YBAV6LZ.js.map
@@ -0,0 +1,230 @@
1
+ import {
2
+ collectFields,
3
+ generateFieldId,
4
+ isSchemaDefinition
5
+ } from "./chunk-BG2FY27M.js";
6
+ import {
7
+ UnauthorizedError
8
+ } from "./chunk-T7S574XQ.js";
9
+ import {
10
+ ObjectValidationError
11
+ } from "./chunk-3BY5RBF2.js";
12
+
13
+ // src/presentation/graphql/server/types.ts
14
+ function isSimpleGraphQLHandlerConfig(config) {
15
+ return "handler" in config && typeof config.handler === "function";
16
+ }
17
+
18
+ // src/presentation/graphql/server/create-graphql-routes.ts
19
+ function createGraphQLRoutesInternal(schema, handlers, options) {
20
+ const config = isSchemaDefinition(schema) ? schema.fields : schema;
21
+ const collectedFields = collectFields(config);
22
+ const result = [];
23
+ const resolvedOptions = {
24
+ ...options,
25
+ validateInput: options?.validateInput ?? true,
26
+ validateOutput: options?.validateOutput ?? true,
27
+ allowPartial: options?.allowPartial ?? false
28
+ };
29
+ for (const { key, field } of collectedFields) {
30
+ const handlerConfig = handlers[key];
31
+ if (!handlerConfig) {
32
+ if (resolvedOptions.allowPartial) {
33
+ continue;
34
+ }
35
+ throw new Error(
36
+ `Missing handler for field "${key}". All fields must have a handler configuration.`
37
+ );
38
+ }
39
+ result.push(createFieldHandler(key, field, handlerConfig, resolvedOptions));
40
+ }
41
+ return result;
42
+ }
43
+ function createFieldHandler(key, field, config, options) {
44
+ const middleware = config.middleware ?? [];
45
+ const globalMiddleware = options?.middleware ?? [];
46
+ const allMiddleware = [...globalMiddleware, ...middleware];
47
+ const shouldValidateInput = options.validateInput ?? true;
48
+ const shouldValidateOutput = options.validateOutput ?? true;
49
+ return {
50
+ key,
51
+ operation: field.operation,
52
+ metadata: {
53
+ fieldId: generateFieldId(key),
54
+ description: field.docs.description,
55
+ tags: field.docs.tags,
56
+ deprecated: field.docs.deprecated,
57
+ deprecationReason: field.docs.deprecationReason
58
+ },
59
+ handler: async (rawArgs, rawContext) => {
60
+ const context = options?.createContext ? options.createContext(rawContext) : rawContext ?? { requestId: generateRequestId() };
61
+ let validatedContext = context;
62
+ if (field.context) {
63
+ const contextResult = validateContextData(field, context);
64
+ if (!contextResult.success) {
65
+ throw new UnauthorizedError({
66
+ message: "Authentication required"
67
+ });
68
+ }
69
+ validatedContext = contextResult.data;
70
+ }
71
+ let validatedInput = rawArgs;
72
+ if (shouldValidateInput && field.input) {
73
+ const inputResult = validateInputData(field, rawArgs);
74
+ if (!inputResult.success) {
75
+ const errors = inputResult.errors ?? [];
76
+ throw new ObjectValidationError({
77
+ message: "Input validation failed",
78
+ validationErrors: errors.map((e) => ({
79
+ field: e.path.join("."),
80
+ message: e.message
81
+ }))
82
+ });
83
+ }
84
+ validatedInput = inputResult.data;
85
+ }
86
+ const validatedArgs = {
87
+ input: validatedInput,
88
+ raw: rawArgs
89
+ };
90
+ const executePipeline = async () => {
91
+ if (isSimpleGraphQLHandlerConfig(config)) {
92
+ return config.handler(
93
+ validatedArgs,
94
+ validatedContext
95
+ );
96
+ } else {
97
+ const { argsMapper, useCase, responseMapper } = config;
98
+ const input = argsMapper(
99
+ validatedArgs,
100
+ validatedContext
101
+ );
102
+ const output = await useCase.execute(input);
103
+ return responseMapper(output);
104
+ }
105
+ };
106
+ let result;
107
+ if (allMiddleware.length === 0) {
108
+ result = await executePipeline();
109
+ } else {
110
+ let index = 0;
111
+ let called = false;
112
+ const next = async () => {
113
+ if (index >= allMiddleware.length) {
114
+ if (called) throw new Error("next() called after pipeline already executed");
115
+ called = true;
116
+ return executePipeline();
117
+ }
118
+ const currentIndex = index++;
119
+ const mw = allMiddleware[currentIndex];
120
+ return mw(rawArgs, context, next);
121
+ };
122
+ result = await next();
123
+ }
124
+ if (shouldValidateOutput && field.output) {
125
+ const outputResult = validateOutputData(field, result);
126
+ if (!outputResult.success) {
127
+ const details = outputResult.errors?.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ");
128
+ throw new ObjectValidationError({
129
+ message: `Output validation failed for field "${key}": ${details}`,
130
+ validationErrors: (outputResult.errors ?? []).map((e) => ({
131
+ field: e.path.join("."),
132
+ message: e.message
133
+ }))
134
+ });
135
+ }
136
+ }
137
+ return result;
138
+ }
139
+ };
140
+ }
141
+ function validateInputData(field, args) {
142
+ const schema = field.input;
143
+ if (!schema) return { success: true, data: args };
144
+ const result = schema.validate(args);
145
+ if (result.success) {
146
+ return { success: true, data: result.data };
147
+ }
148
+ const errors = result.issues.map((issue) => ({
149
+ ...issue,
150
+ path: ["input", ...issue.path]
151
+ }));
152
+ return { success: false, errors };
153
+ }
154
+ function validateOutputData(field, data) {
155
+ const schema = field.output;
156
+ if (!schema) return { success: true, data };
157
+ const result = schema.validate(data);
158
+ if (result.success) {
159
+ return { success: true, data: result.data };
160
+ }
161
+ const errors = result.issues.map((issue) => ({
162
+ ...issue,
163
+ path: ["output", ...issue.path]
164
+ }));
165
+ return { success: false, errors };
166
+ }
167
+ function validateContextData(field, context) {
168
+ const schema = field.context;
169
+ if (!schema) return { success: true, data: context };
170
+ const result = schema.validate(context);
171
+ if (result.success) {
172
+ return { success: true, data: result.data };
173
+ }
174
+ const errors = result.issues.map((issue) => ({
175
+ ...issue,
176
+ path: ["context", ...issue.path]
177
+ }));
178
+ return { success: false, errors };
179
+ }
180
+ function generateRequestId() {
181
+ return `gql_${crypto.randomUUID()}`;
182
+ }
183
+
184
+ // src/presentation/graphql/server/graphql-routes-builder.ts
185
+ var GraphQLRoutesBuilderImpl = class _GraphQLRoutesBuilderImpl {
186
+ schema;
187
+ handlers;
188
+ constructor(schema, handlers) {
189
+ this.schema = schema;
190
+ this.handlers = handlers ?? /* @__PURE__ */ new Map();
191
+ }
192
+ handle(key, handlerOrConfig) {
193
+ const config = typeof handlerOrConfig === "function" ? { handler: handlerOrConfig } : handlerOrConfig;
194
+ const newHandlers = new Map(this.handlers);
195
+ newHandlers.set(key, config);
196
+ return new _GraphQLRoutesBuilderImpl(
197
+ this.schema,
198
+ newHandlers
199
+ );
200
+ }
201
+ handleWithUseCase(key, config) {
202
+ const newHandlers = new Map(this.handlers);
203
+ newHandlers.set(
204
+ key,
205
+ config
206
+ );
207
+ return new _GraphQLRoutesBuilderImpl(
208
+ this.schema,
209
+ newHandlers
210
+ );
211
+ }
212
+ build(options) {
213
+ return createGraphQLRoutesInternal(this.schema, Object.fromEntries(this.handlers), options);
214
+ }
215
+ buildPartial(options) {
216
+ return createGraphQLRoutesInternal(this.schema, Object.fromEntries(this.handlers), {
217
+ ...options,
218
+ allowPartial: true
219
+ });
220
+ }
221
+ };
222
+ function graphqlRoutes(schema) {
223
+ return new GraphQLRoutesBuilderImpl(schema);
224
+ }
225
+
226
+ export {
227
+ isSimpleGraphQLHandlerConfig,
228
+ graphqlRoutes
229
+ };
230
+ //# sourceMappingURL=chunk-ANLXZHUS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/presentation/graphql/server/types.ts","../src/presentation/graphql/server/create-graphql-routes.ts","../src/presentation/graphql/server/graphql-routes-builder.ts"],"sourcesContent":["/**\n * @fileoverview Server types for the GraphQL field system.\n *\n * @module graphql/server/types\n */\n\nimport type { GraphQLFieldDefinition, GraphQLOperationType } from '../field/types';\n\n// Re-export UseCasePort from HTTP — same interface, no duplication\nexport type { UseCasePort } from '../../http/server/types';\n\n// ============================================================================\n// Validated Args\n// ============================================================================\n\n/**\n * Validated arguments with typed data.\n * This is what handlers receive after input validation passes.\n */\nexport interface ValidatedArgs<TField extends GraphQLFieldDefinition> {\n /** Validated input arguments. */\n readonly input: TField['_types']['input'];\n\n /** Raw unvalidated arguments for advanced use cases. */\n readonly raw: unknown;\n}\n\n/**\n * Typed GraphQL context based on field definition.\n * If the field defines a context schema, this will be the validated type.\n * Otherwise, it falls back to the generic GraphQLHandlerContext.\n */\nexport type TypedGraphQLContext<TField extends GraphQLFieldDefinition> =\n TField['_types']['context'] extends undefined\n ? GraphQLHandlerContext\n : TField['_types']['context'];\n\n// ============================================================================\n// Handler Context\n// ============================================================================\n\n/**\n * Context passed to GraphQL handlers.\n * Can be extended with custom context via graphqlRoutes options.\n */\nexport interface GraphQLHandlerContext {\n /** Request ID for tracing. */\n readonly requestId?: string;\n\n /** Additional context data. */\n readonly [key: string]: unknown;\n}\n\n// ============================================================================\n// Handler Types\n// ============================================================================\n\n/**\n * Handler configuration using the use case pattern.\n *\n * @typeParam TField - The field definition type\n * @typeParam TInput - Use case input type\n * @typeParam TOutput - Use case output type\n */\nexport interface GraphQLHandlerConfig<\n TField extends GraphQLFieldDefinition,\n TInput = void,\n TOutput = void,\n> {\n /**\n * Maps the validated args to use case input.\n * Both `args` and `ctx` are fully typed based on field schemas.\n */\n readonly argsMapper: (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => TInput;\n\n /** The use case to execute. */\n readonly useCase: { execute(input?: TInput): Promise<TOutput> };\n\n /**\n * Maps the use case output to the GraphQL response.\n */\n readonly responseMapper: (output: TOutput) => TField['_types']['output'];\n\n /** Middleware to run before the handler. */\n readonly middleware?: readonly GraphQLMiddlewareFunction[];\n}\n\n/**\n * Simple handler function that directly returns the output.\n * Use this for query and mutation fields.\n */\nexport type SimpleGraphQLHandlerFn<TField extends GraphQLFieldDefinition> = (\n args: ValidatedArgs<TField>,\n ctx: TypedGraphQLContext<TField>,\n) => Promise<TField['_types']['output']> | TField['_types']['output'];\n\n/**\n * Subscription handler function that returns an async iterable.\n * Each yielded value is sent to the subscriber.\n */\nexport type SimpleGraphQLSubscriptionFn<TField extends GraphQLFieldDefinition> = (\n args: ValidatedArgs<TField>,\n ctx: TypedGraphQLContext<TField>,\n) => AsyncIterable<TField['_types']['output']>;\n\n/**\n * Configuration for a simple handler (no use case).\n */\nexport interface SimpleGraphQLHandlerConfig<TField extends GraphQLFieldDefinition> {\n readonly handler: SimpleGraphQLHandlerFn<TField>;\n readonly middleware?: readonly GraphQLMiddlewareFunction[];\n}\n\n/**\n * Union of all handler config types.\n * Used internally to store handlers in the builder.\n */\nexport type AnyGraphQLHandlerConfig<\n TField extends GraphQLFieldDefinition,\n TInput = unknown,\n TOutput = unknown,\n> = GraphQLHandlerConfig<TField, TInput, TOutput> | SimpleGraphQLHandlerConfig<TField>;\n\n/**\n * Type guard to check if config is a simple GraphQL handler.\n */\nexport function isSimpleGraphQLHandlerConfig(\n config: AnyGraphQLHandlerConfig<GraphQLFieldDefinition, unknown, unknown>,\n): config is SimpleGraphQLHandlerConfig<GraphQLFieldDefinition> {\n return 'handler' in config && typeof config.handler === 'function';\n}\n\n/**\n * GraphQL middleware function type.\n */\nexport type GraphQLMiddlewareFunction = (\n args: unknown,\n context: GraphQLHandlerContext,\n next: () => Promise<unknown>,\n) => Promise<unknown>;\n\n// ============================================================================\n// Server Configuration\n// ============================================================================\n\n/**\n * Options for creating GraphQL routes.\n */\nexport interface CreateGraphQLRoutesOptions {\n /** Global middleware to run before all handlers. */\n readonly middleware?: readonly GraphQLMiddlewareFunction[];\n\n /**\n * Whether to validate incoming args against field schemas.\n * When enabled, invalid args throw ObjectValidationError.\n * @default true\n */\n readonly validateInput?: boolean;\n\n /**\n * Whether to validate outgoing results against field schemas.\n * When enabled, invalid results log a warning.\n * @default true\n */\n readonly validateOutput?: boolean;\n\n /**\n * Context factory to create handler context.\n */\n readonly createContext?: (rawContext: unknown) => GraphQLHandlerContext;\n\n /**\n * Allow partial handler configuration (not all fields need handlers).\n * When true, missing handlers are silently skipped.\n * When false (default), missing handlers throw an error.\n * @default false\n * @internal Used by builder pattern's buildPartial()\n */\n readonly allowPartial?: boolean;\n}\n\n// ============================================================================\n// Unified GraphQL Field (for framework adapters)\n// ============================================================================\n\n/**\n * GraphQL field input compatible with framework adapters.\n * This is the output of graphqlRoutes().build().\n */\nexport interface UnifiedGraphQLField {\n /** Schema key path (e.g., 'users.get'). */\n readonly key: string;\n\n /** GraphQL operation type. */\n readonly operation: GraphQLOperationType;\n\n /** Handler function. */\n readonly handler: (args: unknown, context: unknown) => Promise<unknown>;\n\n /** Field metadata for documentation. */\n readonly metadata: {\n readonly fieldId?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n readonly deprecationReason?: string;\n };\n}\n","/**\n * @fileoverview Internal implementation for creating GraphQL routes with auto-validation.\n *\n * Generates GraphQL field handlers from a schema definition.\n * Each handler automatically validates incoming args and outgoing results\n * against the field's schemas.\n *\n * @module graphql/server/create-graphql-routes\n * @internal\n */\n\nimport type { SchemaAdapter, ValidationIssue } from '../../http/schema/types';\nimport type {\n GraphQLSchemaConfig,\n GraphQLSchemaDefinition,\n GraphQLFieldDefinition,\n} from '../field/types';\nimport { isSchemaDefinition, collectFields } from '../field/types';\nimport { generateFieldId } from '../field/utils';\nimport { mapErrorToGraphQLError } from '../shared/error-mapping';\nimport type {\n AnyGraphQLHandlerConfig,\n CreateGraphQLRoutesOptions,\n GraphQLHandlerContext,\n UnifiedGraphQLField,\n ValidatedArgs,\n} from './types';\nimport { isSimpleGraphQLHandlerConfig } from './types';\nimport { ObjectValidationError } from '../../../global/exceptions/object-validation.error';\nimport { UnauthorizedError } from '../../../app/exceptions/unauthorized.error';\n\n/**\n * Internal implementation for creating GraphQL routes.\n * Used by the builder pattern (graphqlRoutes).\n *\n * @internal\n */\nexport function createGraphQLRoutesInternal<T extends GraphQLSchemaConfig>(\n schema: T | GraphQLSchemaDefinition<T>,\n handlers: Record<string, AnyGraphQLHandlerConfig<GraphQLFieldDefinition, unknown, unknown>>,\n options?: CreateGraphQLRoutesOptions,\n): UnifiedGraphQLField[] {\n const config = isSchemaDefinition(schema) ? schema.fields : schema;\n const collectedFields = collectFields(config);\n\n const result: UnifiedGraphQLField[] = [];\n\n const resolvedOptions: CreateGraphQLRoutesOptions = {\n ...options,\n validateInput: options?.validateInput ?? true,\n validateOutput: options?.validateOutput ?? true,\n allowPartial: options?.allowPartial ?? false,\n };\n\n for (const { key, field } of collectedFields) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handlerConfig = handlers[key] as\n | AnyGraphQLHandlerConfig<GraphQLFieldDefinition, any, any>\n | undefined;\n\n if (!handlerConfig) {\n if (resolvedOptions.allowPartial) {\n continue;\n }\n throw new Error(\n `Missing handler for field \"${key}\". All fields must have a handler configuration.`,\n );\n }\n\n result.push(createFieldHandler(key, field, handlerConfig, resolvedOptions));\n }\n\n return result;\n}\n\n/**\n * Creates a single field handler with validation and error mapping.\n */\nfunction createFieldHandler(\n key: string,\n field: GraphQLFieldDefinition,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n config: AnyGraphQLHandlerConfig<GraphQLFieldDefinition, any, any>,\n options: CreateGraphQLRoutesOptions,\n): UnifiedGraphQLField {\n const middleware = config.middleware ?? [];\n const globalMiddleware = options?.middleware ?? [];\n const allMiddleware = [...globalMiddleware, ...middleware];\n const shouldValidateInput = options.validateInput ?? true;\n const shouldValidateOutput = options.validateOutput ?? true;\n\n return {\n key,\n operation: field.operation,\n metadata: {\n fieldId: generateFieldId(key),\n description: field.docs.description,\n tags: field.docs.tags as string[],\n deprecated: field.docs.deprecated,\n deprecationReason: field.docs.deprecationReason,\n },\n handler: async (rawArgs: unknown, rawContext: unknown): Promise<unknown> => {\n // Create context\n const context: GraphQLHandlerContext = options?.createContext\n ? options.createContext(rawContext)\n : ((rawContext as GraphQLHandlerContext) ?? { requestId: generateRequestId() });\n\n // Validate context (if schema defined)\n // Context validation failures → UnauthorizedError (401 semantics).\n // Error message is generic to prevent leaking context schema details\n // (field names, types, constraints) to unauthenticated clients.\n let validatedContext: unknown = context;\n if (field.context) {\n const contextResult = validateContextData(field, context);\n if (!contextResult.success) {\n throw new UnauthorizedError({\n message: 'Authentication required',\n });\n }\n validatedContext = contextResult.data;\n }\n\n // Validate input args (if enabled and schema defined)\n let validatedInput: unknown = rawArgs;\n if (shouldValidateInput && field.input) {\n const inputResult = validateInputData(field, rawArgs);\n if (!inputResult.success) {\n const errors = inputResult.errors ?? [];\n throw new ObjectValidationError({\n message: 'Input validation failed',\n validationErrors: errors.map((e) => ({\n field: e.path.join('.'),\n message: e.message,\n })),\n });\n }\n validatedInput = inputResult.data;\n }\n\n const validatedArgs: ValidatedArgsInternal = {\n input: validatedInput,\n raw: rawArgs,\n };\n\n // Execute the pipeline\n const executePipeline = async (): Promise<unknown> => {\n if (isSimpleGraphQLHandlerConfig(config)) {\n return config.handler(\n validatedArgs as unknown as ValidatedArgs<GraphQLFieldDefinition>,\n validatedContext as GraphQLHandlerContext,\n );\n } else {\n const { argsMapper, useCase, responseMapper } = config;\n\n const input = argsMapper(\n validatedArgs as unknown as ValidatedArgs<GraphQLFieldDefinition>,\n validatedContext as GraphQLHandlerContext,\n );\n\n const output = await useCase.execute(input);\n\n return responseMapper(output);\n }\n };\n\n let result: unknown;\n\n if (allMiddleware.length === 0) {\n result = await executePipeline();\n } else {\n // Build middleware chain with re-entrancy guard\n let index = 0;\n let called = false;\n const next = async (): Promise<unknown> => {\n if (index >= allMiddleware.length) {\n if (called) throw new Error('next() called after pipeline already executed');\n called = true;\n return executePipeline();\n }\n const currentIndex = index++;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- index bounds checked above\n const mw = allMiddleware[currentIndex]!;\n return mw(rawArgs, context, next);\n };\n\n result = await next();\n }\n\n // Validate output (if enabled and schema defined)\n if (shouldValidateOutput && field.output) {\n const outputResult = validateOutputData(field, result);\n if (!outputResult.success) {\n const details = outputResult.errors\n ?.map((e) => `${e.path.join('.')}: ${e.message}`)\n .join('; ');\n throw new ObjectValidationError({\n message: `Output validation failed for field \"${key}\": ${details}`,\n validationErrors: (outputResult.errors ?? []).map((e) => ({\n field: e.path.join('.'),\n message: e.message,\n })),\n });\n }\n }\n\n return result;\n },\n };\n}\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\ninterface ValidationResultInternal {\n success: boolean;\n errors?: ValidationIssue[];\n data?: unknown;\n}\n\n/**\n * Validates input args against the field's input schema.\n */\nfunction validateInputData(field: GraphQLFieldDefinition, args: unknown): ValidationResultInternal {\n const schema = field.input as SchemaAdapter | undefined;\n if (!schema) return { success: true, data: args };\n\n const result = schema.validate(args);\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['input', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\n/**\n * Validates output data against the field's output schema.\n */\nfunction validateOutputData(\n field: GraphQLFieldDefinition,\n data: unknown,\n): ValidationResultInternal {\n const schema = field.output as SchemaAdapter | undefined;\n if (!schema) return { success: true, data };\n\n const result = schema.validate(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['output', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\n/**\n * Validates context data against the field's context schema.\n */\nfunction validateContextData(\n field: GraphQLFieldDefinition,\n context: GraphQLHandlerContext,\n): ValidationResultInternal {\n const schema = field.context as SchemaAdapter | undefined;\n if (!schema) return { success: true, data: context };\n\n const result = schema.validate(context);\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errors = result.issues.map((issue) => ({\n ...issue,\n path: ['context', ...issue.path],\n }));\n\n return { success: false, errors };\n}\n\n/**\n * Internal validated args type with unknown fields.\n * Used inside createFieldHandler where specific types are erased.\n */\ninterface ValidatedArgsInternal {\n readonly input: unknown;\n readonly raw: unknown;\n}\n\n/**\n * Generates a unique request ID.\n */\nfunction generateRequestId(): string {\n return `gql_${crypto.randomUUID()}`;\n}\n","/**\n * @fileoverview Builder pattern for creating type-safe GraphQL routes.\n *\n * The `graphqlRoutes` function returns a builder that provides 100% type inference\n * for all handler parameters — no manual type annotations required.\n *\n * @module graphql/server/graphql-routes-builder\n */\n\nimport type {\n GraphQLSchemaConfig,\n GraphQLSchemaDefinition,\n GetField,\n SchemaKeys,\n GraphQLFieldDefinition,\n} from '../field/types';\nimport type {\n AnyGraphQLHandlerConfig,\n CreateGraphQLRoutesOptions,\n GraphQLHandlerConfig,\n GraphQLMiddlewareFunction,\n SimpleGraphQLHandlerConfig,\n SimpleGraphQLHandlerFn,\n TypedGraphQLContext,\n UnifiedGraphQLField,\n ValidatedArgs,\n} from './types';\nimport { createGraphQLRoutesInternal } from './create-graphql-routes';\n\n// ============================================================================\n// Builder Types\n// ============================================================================\n\n/**\n * Error type displayed when attempting to build() with missing handlers.\n * The `___missingFields` property shows which fields are missing.\n */\nexport interface MissingHandlersError<TMissing extends string> {\n /**\n * This error indicates that not all GraphQL fields have handlers.\n * Use buildPartial() to build with only the defined handlers,\n * or add handlers for the missing fields.\n */\n (options?: never): never;\n /** Fields that are missing handlers. */\n readonly ___missingFields: TMissing;\n}\n\n/**\n * Handler configuration for the builder pattern.\n */\nexport interface BuilderGraphQLHandlerConfig<\n TField extends GraphQLFieldDefinition,\n TInput,\n TOutput,\n> {\n /**\n * Maps the validated args to use case input.\n * Both `args` and `ctx` are fully typed based on field schemas.\n */\n readonly argsMapper: (args: ValidatedArgs<TField>, ctx: TypedGraphQLContext<TField>) => TInput;\n\n /** The use case to execute. */\n readonly useCase: { execute(input?: TInput): Promise<TOutput> };\n\n /**\n * Maps the use case output to the GraphQL response.\n */\n readonly responseMapper: (output: TOutput) => TField['_types']['output'];\n\n /** Middleware to run before the handler. */\n readonly middleware?: readonly GraphQLMiddlewareFunction[];\n}\n\n/**\n * Builder interface for creating type-safe GraphQL routes.\n *\n * Each `.handle()` call captures the specific field type and provides\n * full type inference for argsMapper, useCase, and responseMapper.\n *\n * @typeParam T - The schema configuration type\n * @typeParam THandled - Union of field keys that have handlers (accumulates)\n *\n * @example\n * ```typescript\n * const fields = graphqlRoutes(projectSchema)\n * .handleWithUseCase('projects.create', {\n * argsMapper: (args, ctx) => ({\n * name: args.input.name,\n * createdBy: ctx.userId,\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (output) => ({ projectId: output.projectId }),\n * })\n * .handle('projects.list', async (args) => {\n * return allProjects;\n * })\n * .build();\n * ```\n */\nexport interface GraphQLRoutesBuilder<\n T extends GraphQLSchemaConfig,\n THandled extends string = never,\n> {\n /**\n * Register a simple handler for a field.\n * The handler receives validated args and context, returns output directly.\n */\n handle<K extends Exclude<SchemaKeys<T>, THandled>>(\n key: K,\n handlerOrConfig:\n | SimpleGraphQLHandlerFn<GetField<T, K>>\n | SimpleGraphQLHandlerConfig<GetField<T, K>>,\n ): GraphQLRoutesBuilder<T, THandled | K>;\n\n /**\n * Register a handler using the use case pattern.\n * Follows: argsMapper → useCase.execute() → responseMapper\n */\n handleWithUseCase<K extends Exclude<SchemaKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderGraphQLHandlerConfig<GetField<T, K>, TInput, TOutput>,\n ): GraphQLRoutesBuilder<T, THandled | K>;\n\n /**\n * Build the fields array for framework adapter registration.\n *\n * This method is only available when ALL fields have handlers.\n * If some fields are missing handlers, use `buildPartial()` instead.\n */\n build: [Exclude<SchemaKeys<T>, THandled>] extends [never]\n ? (options?: CreateGraphQLRoutesOptions) => UnifiedGraphQLField[]\n : MissingHandlersError<Exclude<SchemaKeys<T>, THandled>>;\n\n /**\n * Build fields for only the defined handlers.\n * No compile-time enforcement of completeness.\n */\n buildPartial(options?: CreateGraphQLRoutesOptions): UnifiedGraphQLField[];\n}\n\n// ============================================================================\n// Builder Implementation\n// ============================================================================\n\n/**\n * Internal builder implementation.\n *\n * Uses an immutable pattern where each handle() call returns a new\n * builder instance with the updated handlers map.\n */\nclass GraphQLRoutesBuilderImpl<T extends GraphQLSchemaConfig, THandled extends string = never> {\n private readonly schema: T | GraphQLSchemaDefinition<T>;\n private readonly handlers: Map<\n string,\n AnyGraphQLHandlerConfig<GraphQLFieldDefinition, unknown, unknown>\n >;\n\n constructor(\n schema: T | GraphQLSchemaDefinition<T>,\n handlers?: Map<string, AnyGraphQLHandlerConfig<GraphQLFieldDefinition, unknown, unknown>>,\n ) {\n this.schema = schema;\n this.handlers = handlers ?? new Map();\n }\n\n handle<K extends Exclude<SchemaKeys<T>, THandled>>(\n key: K,\n handlerOrConfig:\n | SimpleGraphQLHandlerFn<GetField<T, K>>\n | SimpleGraphQLHandlerConfig<GetField<T, K>>,\n ): GraphQLRoutesBuilder<T, THandled | K> {\n // Cast through unknown is safe: type erasure in the builder requires this cast\n // The type system tracks the specific field types through the interface\n const config: SimpleGraphQLHandlerConfig<GraphQLFieldDefinition> =\n typeof handlerOrConfig === 'function'\n ? { handler: handlerOrConfig as unknown as SimpleGraphQLHandlerFn<GraphQLFieldDefinition> }\n : (handlerOrConfig as unknown as SimpleGraphQLHandlerConfig<GraphQLFieldDefinition>);\n\n const newHandlers = new Map(this.handlers);\n newHandlers.set(key as string, config);\n\n return new GraphQLRoutesBuilderImpl<T, THandled | K>(\n this.schema,\n newHandlers,\n ) as unknown as GraphQLRoutesBuilder<T, THandled | K>;\n }\n\n handleWithUseCase<K extends Exclude<SchemaKeys<T>, THandled>, TInput, TOutput>(\n key: K,\n config: BuilderGraphQLHandlerConfig<GetField<T, K>, TInput, TOutput>,\n ): GraphQLRoutesBuilder<T, THandled | K> {\n const newHandlers = new Map(this.handlers);\n // Cast through unknown is safe: the type system tracks THandled | K through the interface\n newHandlers.set(\n key as string,\n config as unknown as GraphQLHandlerConfig<GraphQLFieldDefinition, unknown, unknown>,\n );\n\n return new GraphQLRoutesBuilderImpl<T, THandled | K>(\n this.schema,\n newHandlers,\n ) as unknown as GraphQLRoutesBuilder<T, THandled | K>;\n }\n\n build(options?: CreateGraphQLRoutesOptions): UnifiedGraphQLField[] {\n return createGraphQLRoutesInternal(this.schema, Object.fromEntries(this.handlers), options);\n }\n\n buildPartial(options?: CreateGraphQLRoutesOptions): UnifiedGraphQLField[] {\n return createGraphQLRoutesInternal(this.schema, Object.fromEntries(this.handlers), {\n ...options,\n allowPartial: true,\n });\n }\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Creates a type-safe GraphQL routes builder for a schema.\n *\n * The builder pattern provides 100% type inference for all handler parameters:\n * - `args.input` is typed from the field's input schema\n * - `ctx` is typed from the field's context schema (or GraphQLHandlerContext)\n * - `output` in responseMapper is typed from the use case\n *\n * @param schema - GraphQL schema definition or schema config\n * @returns Builder for registering handlers\n *\n * @example Basic usage\n * ```typescript\n * import { graphqlRoutes } from '@cosmneo/onion-lasagna/graphql/server';\n * import { projectSchema } from './schema';\n *\n * const fields = graphqlRoutes(projectSchema)\n * .handleWithUseCase('projects.create', {\n * argsMapper: (args, ctx) => ({\n * name: args.input.name,\n * createdBy: ctx.userId,\n * }),\n * useCase: createProjectUseCase,\n * responseMapper: (output) => ({ projectId: output.projectId }),\n * })\n * .handle('projects.list', async () => allProjects)\n * .build();\n * ```\n */\nexport function graphqlRoutes<T extends GraphQLSchemaConfig>(\n schema: T | GraphQLSchemaDefinition<T>,\n): GraphQLRoutesBuilder<T, never> {\n return new GraphQLRoutesBuilderImpl(schema) as unknown as GraphQLRoutesBuilder<T, never>;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,36 @@
1
+ // src/presentation/graphql/field/types/schema-definition.type.ts
2
+ function isFieldDefinition(value) {
3
+ return typeof value === "object" && value !== null && "_isGraphQLField" in value && value._isGraphQLField === true;
4
+ }
5
+ function isSchemaDefinition(value) {
6
+ return typeof value === "object" && value !== null && "_isGraphQLSchema" in value && value._isGraphQLSchema === true;
7
+ }
8
+ function collectFields(config, basePath = "") {
9
+ const fields = [];
10
+ for (const [key, value] of Object.entries(config)) {
11
+ const fullKey = basePath ? `${basePath}.${key}` : key;
12
+ if (isFieldDefinition(value)) {
13
+ fields.push({ key: fullKey, field: value });
14
+ } else if (isSchemaDefinition(value)) {
15
+ fields.push(...collectFields(value.fields, fullKey));
16
+ } else if (typeof value === "object" && value !== null) {
17
+ fields.push(...collectFields(value, fullKey));
18
+ }
19
+ }
20
+ return fields;
21
+ }
22
+
23
+ // src/presentation/graphql/field/utils.ts
24
+ function generateFieldId(key) {
25
+ return key.split(".").map(
26
+ (segment, index) => index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1)
27
+ ).join("");
28
+ }
29
+
30
+ export {
31
+ isFieldDefinition,
32
+ isSchemaDefinition,
33
+ collectFields,
34
+ generateFieldId
35
+ };
36
+ //# sourceMappingURL=chunk-BG2FY27M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/presentation/graphql/field/types/schema-definition.type.ts","../src/presentation/graphql/field/utils.ts"],"sourcesContent":["/**\n * @fileoverview GraphQL schema definition types for grouping fields.\n *\n * Mirrors the HTTP router definition pattern with hierarchical grouping,\n * dotted-key access, and deep merge support.\n *\n * @module graphql/field/types/schema-definition\n */\n\nimport type { GraphQLFieldDefinition, GraphQLOperationType } from './field-definition.type';\nimport type { SchemaAdapter } from '../../../http/schema/types';\n\n// ============================================================================\n// Schema Types\n// ============================================================================\n\n/**\n * A schema entry can be a field definition, a nested config, or a schema definition.\n */\nexport type GraphQLSchemaEntry =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n | GraphQLFieldDefinition<GraphQLOperationType, any, any, any>\n | GraphQLSchemaConfig\n | GraphQLSchemaDefinition;\n\n/**\n * Configuration for a GraphQL schema (group of fields).\n */\nexport interface GraphQLSchemaConfig {\n readonly [key: string]: GraphQLSchemaEntry;\n}\n\n/**\n * Schema-level defaults applied to all child fields.\n */\nexport interface GraphQLSchemaDefaults {\n /** Default tags for all fields. Merged with field-specific tags. */\n readonly tags?: readonly string[];\n\n /** Default context schema. Applied to fields that don't define their own. */\n readonly context?: SchemaAdapter;\n}\n\n/**\n * A fully defined GraphQL schema.\n */\nexport interface GraphQLSchemaDefinition<T extends GraphQLSchemaConfig = GraphQLSchemaConfig> {\n /** The fields and nested groups in this schema. */\n readonly fields: T;\n\n /** Default values applied to all child fields. */\n readonly defaults?: GraphQLSchemaDefaults;\n\n /**\n * Marker to identify this as a GraphQL schema definition.\n * @internal\n */\n readonly _isGraphQLSchema: true;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Checks if a value is a GraphQLFieldDefinition.\n */\nexport function isFieldDefinition(value: unknown): value is GraphQLFieldDefinition {\n return (\n typeof value === 'object' &&\n value !== null &&\n '_isGraphQLField' in value &&\n (value as GraphQLFieldDefinition)._isGraphQLField === true\n );\n}\n\n/**\n * Checks if a value is a GraphQLSchemaDefinition.\n */\nexport function isSchemaDefinition(value: unknown): value is GraphQLSchemaDefinition {\n return (\n typeof value === 'object' &&\n value !== null &&\n '_isGraphQLSchema' in value &&\n (value as GraphQLSchemaDefinition)._isGraphQLSchema === true\n );\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Flattens a schema into a map of dotted keys to field definitions.\n */\nexport type FlattenSchema<\n T extends GraphQLSchemaConfig,\n Prefix extends string = '',\n> = T extends GraphQLSchemaConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends GraphQLFieldDefinition<any, any, any, any>\n ? { [P in `${Prefix}${K & string}`]: T[K] }\n : T[K] extends GraphQLSchemaConfig\n ? FlattenSchema<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T] extends infer U\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n U extends Record<string, GraphQLFieldDefinition<any, any, any, any>>\n ? U\n : never\n : never\n : never;\n\n/**\n * Gets all field keys from a schema.\n */\nexport type SchemaKeys<\n T extends GraphQLSchemaConfig,\n Prefix extends string = '',\n> = T extends GraphQLSchemaConfig\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof T]: T[K] extends GraphQLFieldDefinition<any, any, any, any>\n ? `${Prefix}${K & string}`\n : T[K] extends GraphQLSchemaConfig\n ? SchemaKeys<T[K], `${Prefix}${K & string}.`>\n : never;\n }[keyof T]\n : never;\n\n/**\n * Gets a field by its dotted key path.\n */\nexport type GetField<\n T extends GraphQLSchemaConfig,\n K extends string,\n> = K extends `${infer Head}.${infer Tail}`\n ? Head extends keyof T\n ? T[Head] extends GraphQLSchemaConfig\n ? GetField<T[Head], Tail>\n : never\n : never\n : K extends keyof T\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T[K] extends GraphQLFieldDefinition<any, any, any, any>\n ? T[K]\n : never\n : never;\n\n// ============================================================================\n// Deep Merge Types\n// ============================================================================\n\n/**\n * Deep-merges two schema configs at the type level.\n */\nexport type DeepMergeSchemas<A extends GraphQLSchemaConfig, B extends GraphQLSchemaConfig> = {\n readonly [K in keyof A | keyof B]: K extends keyof A\n ? K extends keyof B\n ? A[K] extends GraphQLSchemaConfig\n ? B[K] extends GraphQLSchemaConfig\n ? DeepMergeSchemas<A[K], B[K]>\n : B[K]\n : B[K]\n : A[K]\n : K extends keyof B\n ? B[K]\n : never;\n};\n\n/**\n * Recursively deep-merges N schema configs left-to-right.\n */\nexport type DeepMergeSchemasAll<T extends readonly GraphQLSchemaConfig[]> = T extends readonly [\n infer Only extends GraphQLSchemaConfig,\n]\n ? Only\n : T extends readonly [\n infer First extends GraphQLSchemaConfig,\n infer Second extends GraphQLSchemaConfig,\n ...infer Rest extends readonly GraphQLSchemaConfig[],\n ]\n ? DeepMergeSchemasAll<[DeepMergeSchemas<First, Second>, ...Rest]>\n : GraphQLSchemaConfig;\n\n// ============================================================================\n// Runtime Utilities\n// ============================================================================\n\n/**\n * Collects all fields from a schema into a flat array.\n */\nexport function collectFields(\n config: GraphQLSchemaConfig,\n basePath = '',\n): { key: string; field: GraphQLFieldDefinition }[] {\n const fields: { key: string; field: GraphQLFieldDefinition }[] = [];\n\n for (const [key, value] of Object.entries(config)) {\n const fullKey = basePath ? `${basePath}.${key}` : key;\n\n if (isFieldDefinition(value)) {\n fields.push({ key: fullKey, field: value });\n } else if (isSchemaDefinition(value)) {\n fields.push(...collectFields(value.fields, fullKey));\n } else if (typeof value === 'object' && value !== null) {\n fields.push(...collectFields(value as GraphQLSchemaConfig, fullKey));\n }\n }\n\n return fields;\n}\n","/**\n * @fileoverview GraphQL field utility functions.\n *\n * @module graphql/field/utils\n */\n\n/**\n * Generates a field ID from a schema key path.\n *\n * This is the **single source of truth** for the naming convention used across:\n * - SDL generation (`type Query { usersGet(...) }`)\n * - Yoga resolver map keys\n * - Client query string field names\n *\n * Converts dotted key paths to camelCase:\n * - `\"users.get\"` → `\"usersGet\"`\n * - `\"projects.members.list\"` → `\"projectsMembersList\"`\n * - `\"getUser\"` → `\"getUser\"` (single segment unchanged)\n *\n * @param key - The dotted schema key path\n * @returns A camelCase field ID string\n */\nexport function generateFieldId(key: string): string {\n return key\n .split('.')\n .map((segment, index) =>\n index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1),\n )\n .join('');\n}\n"],"mappings":";AAmEO,SAAS,kBAAkB,OAAiD;AACjF,SACE,OAAO,UAAU,YACjB,UAAU,QACV,qBAAqB,SACpB,MAAiC,oBAAoB;AAE1D;AAKO,SAAS,mBAAmB,OAAkD;AACnF,SACE,OAAO,UAAU,YACjB,UAAU,QACV,sBAAsB,SACrB,MAAkC,qBAAqB;AAE5D;AA2GO,SAAS,cACd,QACA,WAAW,IACuC;AAClD,QAAM,SAA2D,CAAC;AAElE,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAM,UAAU,WAAW,GAAG,QAAQ,IAAI,GAAG,KAAK;AAElD,QAAI,kBAAkB,KAAK,GAAG;AAC5B,aAAO,KAAK,EAAE,KAAK,SAAS,OAAO,MAAM,CAAC;AAAA,IAC5C,WAAW,mBAAmB,KAAK,GAAG;AACpC,aAAO,KAAK,GAAG,cAAc,MAAM,QAAQ,OAAO,CAAC;AAAA,IACrD,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,aAAO,KAAK,GAAG,cAAc,OAA8B,OAAO,CAAC;AAAA,IACrE;AAAA,EACF;AAEA,SAAO;AACT;;;AC9LO,SAAS,gBAAgB,KAAqB;AACnD,SAAO,IACJ,MAAM,GAAG,EACT;AAAA,IAAI,CAAC,SAAS,UACb,UAAU,IAAI,UAAU,QAAQ,OAAO,CAAC,EAAE,YAAY,IAAI,QAAQ,MAAM,CAAC;AAAA,EAC3E,EACC,KAAK,EAAE;AACZ;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-FEY2GSVT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}