@gqlkit-ts/cli 0.5.1 → 0.7.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/auto-type-generator/auto-type-generator.d.ts +7 -0
- package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
- package/dist/auto-type-generator/auto-type-generator.js +379 -56
- package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
- package/dist/auto-type-generator/discriminator-field-validator.d.ts +26 -0
- package/dist/auto-type-generator/discriminator-field-validator.d.ts.map +1 -0
- package/dist/auto-type-generator/discriminator-field-validator.js +242 -0
- package/dist/auto-type-generator/discriminator-field-validator.js.map +1 -0
- package/dist/auto-type-generator/discriminator-naming.d.ts +11 -0
- package/dist/auto-type-generator/discriminator-naming.d.ts.map +1 -0
- package/dist/auto-type-generator/discriminator-naming.js +15 -0
- package/dist/auto-type-generator/discriminator-naming.js.map +1 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.d.ts +44 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.d.ts.map +1 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.js +77 -0
- package/dist/auto-type-generator/discriminator-resolve-type-generator.js.map +1 -0
- package/dist/auto-type-generator/index.d.ts +3 -0
- package/dist/auto-type-generator/index.d.ts.map +1 -1
- package/dist/auto-type-generator/index.js +3 -0
- package/dist/auto-type-generator/index.js.map +1 -1
- package/dist/auto-type-generator/inline-enum-collector.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-enum-collector.js +14 -7
- package/dist/auto-type-generator/inline-enum-collector.js.map +1 -1
- package/dist/auto-type-generator/inline-object-converter.d.ts +12 -0
- package/dist/auto-type-generator/inline-object-converter.d.ts.map +1 -0
- package/dist/auto-type-generator/inline-object-converter.js +72 -0
- package/dist/auto-type-generator/inline-object-converter.js.map +1 -0
- package/dist/auto-type-generator/inline-object-traverser.d.ts +2 -1
- package/dist/auto-type-generator/inline-object-traverser.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-object-traverser.js +22 -4
- package/dist/auto-type-generator/inline-object-traverser.js.map +1 -1
- package/dist/auto-type-generator/inline-union-collector.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-union-collector.js +20 -6
- package/dist/auto-type-generator/inline-union-collector.js.map +1 -1
- package/dist/auto-type-generator/inline-union-types.d.ts +2 -0
- package/dist/auto-type-generator/inline-union-types.d.ts.map +1 -1
- package/dist/auto-type-generator/inline-union-validator.js +3 -3
- package/dist/auto-type-generator/inline-union-validator.js.map +1 -1
- package/dist/auto-type-generator/intersection-flattener.d.ts +44 -0
- package/dist/auto-type-generator/intersection-flattener.d.ts.map +1 -0
- package/dist/auto-type-generator/intersection-flattener.js +398 -0
- package/dist/auto-type-generator/intersection-flattener.js.map +1 -0
- package/dist/auto-type-generator/naming-convention.d.ts +23 -2
- package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
- package/dist/auto-type-generator/naming-convention.js +145 -1
- package/dist/auto-type-generator/naming-convention.js.map +1 -1
- package/dist/auto-type-generator/resolver-field-iterator.d.ts +1 -1
- package/dist/auto-type-generator/resolver-field-iterator.d.ts.map +1 -1
- package/dist/auto-type-generator/resolver-field-iterator.js +3 -0
- package/dist/auto-type-generator/resolver-field-iterator.js.map +1 -1
- package/dist/auto-type-generator/typename-extractor.d.ts +2 -0
- package/dist/auto-type-generator/typename-extractor.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-extractor.js +11 -3
- package/dist/auto-type-generator/typename-extractor.js.map +1 -1
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts +2 -0
- package/dist/auto-type-generator/typename-resolve-type-generator.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-resolve-type-generator.js +12 -84
- package/dist/auto-type-generator/typename-resolve-type-generator.js.map +1 -1
- package/dist/auto-type-generator/typename-types.d.ts +4 -0
- package/dist/auto-type-generator/typename-types.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-types.js +6 -0
- package/dist/auto-type-generator/typename-types.js.map +1 -1
- package/dist/auto-type-generator/typename-validator.d.ts.map +1 -1
- package/dist/auto-type-generator/typename-validator.js +4 -3
- package/dist/auto-type-generator/typename-validator.js.map +1 -1
- package/dist/commands/docs.d.ts +1 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/gen.d.ts +1 -0
- package/dist/commands/gen.d.ts.map +1 -1
- package/dist/commands/gen.js +2 -1
- package/dist/commands/gen.js.map +1 -1
- package/dist/commands/main.d.ts +1 -0
- package/dist/commands/main.d.ts.map +1 -1
- package/dist/config/types.d.ts +7 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config-loader/index.d.ts +1 -1
- package/dist/config-loader/index.d.ts.map +1 -1
- package/dist/config-loader/index.js.map +1 -1
- package/dist/config-loader/loader.d.ts +6 -0
- package/dist/config-loader/loader.d.ts.map +1 -1
- package/dist/config-loader/loader.js +1 -0
- package/dist/config-loader/loader.js.map +1 -1
- package/dist/config-loader/validator.d.ts.map +1 -1
- package/dist/config-loader/validator.js +84 -1
- package/dist/config-loader/validator.js.map +1 -1
- package/dist/gen-orchestrator/orchestrator.d.ts +2 -1
- package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/gen-orchestrator/orchestrator.js +43 -3
- package/dist/gen-orchestrator/orchestrator.js.map +1 -1
- package/dist/resolver-extractor/extract-resolvers.d.ts +4 -0
- package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +2 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
- package/dist/resolver-extractor/extractor/define-api-extractor.js +35 -6
- package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
- package/dist/resolver-extractor/index.d.ts +1 -1
- package/dist/resolver-extractor/index.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts +2 -0
- package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts.map +1 -1
- package/dist/resolver-extractor/validator/abstract-resolver-validator.js +16 -3
- package/dist/resolver-extractor/validator/abstract-resolver-validator.js.map +1 -1
- package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
- package/dist/schema-generator/emitter/code-emitter.js +24 -4
- package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.d.ts +18 -0
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.d.ts.map +1 -0
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.js +89 -0
- package/dist/schema-generator/emitter/discriminator-resolve-type-emitter.js.map +1 -0
- package/dist/schema-generator/generate-schema.d.ts +2 -0
- package/dist/schema-generator/generate-schema.d.ts.map +1 -1
- package/dist/schema-generator/generate-schema.js +69 -10
- package/dist/schema-generator/generate-schema.js.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.d.ts +5 -0
- package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
- package/dist/schema-generator/integrator/result-integrator.js +44 -3
- package/dist/schema-generator/integrator/result-integrator.js.map +1 -1
- package/dist/schema-generator/resolver-collector/resolver-collector.d.ts +2 -0
- package/dist/schema-generator/resolver-collector/resolver-collector.d.ts.map +1 -1
- package/dist/schema-generator/resolver-collector/resolver-collector.js +4 -0
- package/dist/schema-generator/resolver-collector/resolver-collector.js.map +1 -1
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +14 -1
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/enum-prefix-detector.d.ts.map +1 -1
- package/dist/shared/enum-prefix-detector.js +78 -8
- package/dist/shared/enum-prefix-detector.js.map +1 -1
- package/dist/shared/inline-object-utils.js +1 -1
- package/dist/shared/inline-object-utils.js.map +1 -1
- package/dist/shared/type-converter.d.ts.map +1 -1
- package/dist/shared/type-converter.js +55 -0
- package/dist/shared/type-converter.js.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
- package/dist/type-extractor/converter/graphql-converter.js +11 -1
- package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
- package/dist/type-extractor/extractor/field-type-resolver.d.ts +18 -0
- package/dist/type-extractor/extractor/field-type-resolver.d.ts.map +1 -1
- package/dist/type-extractor/extractor/field-type-resolver.js +198 -15
- package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.d.ts +1 -0
- package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
- package/dist/type-extractor/extractor/type-extractor.js +100 -9
- package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
- package/dist/type-extractor/types/diagnostics.d.ts +1 -1
- package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
- package/dist/type-extractor/types/index.d.ts +1 -1
- package/dist/type-extractor/types/index.d.ts.map +1 -1
- package/dist/type-extractor/types/index.js +1 -1
- package/dist/type-extractor/types/index.js.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts +7 -1
- package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -1
- package/dist/type-extractor/types/ts-type-reference-factory.js +18 -3
- package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -1
- package/dist/type-extractor/types/typescript.d.ts +3 -1
- package/dist/type-extractor/types/typescript.d.ts.map +1 -1
- package/dist/type-extractor/validator/type-validator.d.ts.map +1 -1
- package/dist/type-extractor/validator/type-validator.js +6 -1
- package/dist/type-extractor/validator/type-validator.js.map +1 -1
- package/docs/configuration.md +19 -0
- package/docs/getting-started.md +2 -1
- package/docs/index.md +2 -0
- package/docs/integration/ai-sdk.md +189 -0
- package/docs/schema/conventions.md +7 -0
- package/docs/schema/fields.md +15 -0
- package/docs/schema/queries-mutations.md +21 -2
- package/docs/schema/subscriptions.md +173 -0
- package/docs/schema/unions.md +117 -0
- package/package.json +4 -4
- package/src/auto-type-generator/auto-type-generator.ts +588 -62
- package/src/auto-type-generator/discriminator-field-validator.ts +368 -0
- package/src/auto-type-generator/discriminator-naming.ts +24 -0
- package/src/auto-type-generator/discriminator-resolve-type-generator.ts +136 -0
- package/src/auto-type-generator/index.ts +17 -0
- package/src/auto-type-generator/inline-enum-collector.ts +19 -4
- package/src/auto-type-generator/inline-object-converter.ts +100 -0
- package/src/auto-type-generator/inline-object-traverser.ts +33 -7
- package/src/auto-type-generator/inline-union-collector.ts +26 -4
- package/src/auto-type-generator/inline-union-types.ts +2 -0
- package/src/auto-type-generator/inline-union-validator.ts +3 -3
- package/src/auto-type-generator/intersection-flattener.ts +554 -0
- package/src/auto-type-generator/naming-convention.ts +207 -3
- package/src/auto-type-generator/resolver-field-iterator.ts +5 -1
- package/src/auto-type-generator/typename-extractor.ts +17 -3
- package/src/auto-type-generator/typename-resolve-type-generator.ts +19 -108
- package/src/auto-type-generator/typename-types.ts +7 -0
- package/src/auto-type-generator/typename-validator.ts +4 -3
- package/src/commands/gen.ts +9 -2
- package/src/config/types.ts +10 -0
- package/src/config-loader/index.ts +1 -0
- package/src/config-loader/loader.ts +11 -0
- package/src/config-loader/validator.ts +100 -1
- package/src/gen-orchestrator/orchestrator.ts +50 -3
- package/src/resolver-extractor/extract-resolvers.ts +5 -0
- package/src/resolver-extractor/extractor/define-api-extractor.ts +47 -7
- package/src/resolver-extractor/index.ts +1 -0
- package/src/resolver-extractor/validator/abstract-resolver-validator.ts +20 -6
- package/src/schema-generator/emitter/code-emitter.ts +43 -5
- package/src/schema-generator/emitter/discriminator-resolve-type-emitter.ts +125 -0
- package/src/schema-generator/generate-schema.ts +100 -13
- package/src/schema-generator/integrator/result-integrator.ts +55 -2
- package/src/schema-generator/resolver-collector/resolver-collector.ts +7 -0
- package/src/shared/constants.ts +15 -1
- package/src/shared/enum-prefix-detector.ts +96 -8
- package/src/shared/inline-object-utils.ts +1 -1
- package/src/shared/type-converter.ts +63 -0
- package/src/type-extractor/converter/graphql-converter.ts +17 -1
- package/src/type-extractor/extractor/field-type-resolver.ts +241 -16
- package/src/type-extractor/extractor/type-extractor.ts +119 -5
- package/src/type-extractor/types/diagnostics.ts +10 -1
- package/src/type-extractor/types/index.ts +2 -1
- package/src/type-extractor/types/ts-type-reference-factory.ts +24 -3
- package/src/type-extractor/types/typescript.ts +6 -2
- package/src/type-extractor/validator/type-validator.ts +6 -1
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { BUILT_IN_SCALARS } from "../../shared/constants.js";
|
|
2
|
-
const PLACEHOLDER_TYPES = new Set([
|
|
2
|
+
const PLACEHOLDER_TYPES = new Set([
|
|
3
|
+
"__INLINE_OBJECT__",
|
|
4
|
+
"__INLINE_ENUM__",
|
|
5
|
+
"__INLINE_UNION__",
|
|
6
|
+
"__NEVER__",
|
|
7
|
+
]);
|
|
3
8
|
export function validateTypes(options) {
|
|
4
9
|
const { types, customScalarNames } = options;
|
|
5
10
|
const diagnostics = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-validator.js","sourceRoot":"","sources":["../../../src/type-extractor/validator/type-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAY7D,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"type-validator.js","sourceRoot":"","sources":["../../../src/type-extractor/validator/type-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAY7D,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,mBAAmB;IACnB,iBAAiB;IACjB,kBAAkB;IAClB,WAAW;CACZ,CAAC,CAAC;AAEH,MAAM,UAAU,aAAa,CAAC,OAA6B;IACzD,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC;IAE7C,MAAM,WAAW,GAAiB,EAAE,CAAC;IAErC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;QAC3B,GAAG,gBAAgB;QACnB,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC;KAC7B,CAAC,CAAC;IAEH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAErC,IACE,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;oBACxB,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAC3B,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAChC,CAAC;oBACD,WAAW,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,sBAAsB;wBAC5B,OAAO,EAAE,UAAU,KAAK,CAAC,IAAI,iCAAiC,QAAQ,GAAG;wBACzE,QAAQ,EAAE,OAAO;wBACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;qBACxD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBACxD,WAAW,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,sBAAsB;wBAC5B,OAAO,EAAE,UAAU,IAAI,CAAC,IAAI,iCAAiC,MAAM,GAAG;wBACtE,QAAQ,EAAE,OAAO;wBACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;qBACxD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,WAAW,CAAC,MAAM,KAAK,CAAC;QAC/B,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
package/docs/configuration.md
CHANGED
|
@@ -155,6 +155,25 @@ export default defineConfig({
|
|
|
155
155
|
|------|-------------|
|
|
156
156
|
| `afterAllFileWrite` | Runs after all generated files are written. Receives the list of written file paths. |
|
|
157
157
|
|
|
158
|
+
## Custom Discriminator Fields
|
|
159
|
+
|
|
160
|
+
Specify custom TypeScript fields for union type resolution. This is useful when union members use a discriminator field other than `__typename` or `$typeName` (e.g., external library types).
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
export default defineConfig({
|
|
164
|
+
discriminatorFields: {
|
|
165
|
+
// Single field
|
|
166
|
+
ContentPart: "type",
|
|
167
|
+
// Multiple fields for tuple-based discrimination
|
|
168
|
+
Content: ["type", "mediaType"],
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Keys are GraphQL union type names, and values are either a single field name or an array of field names. gqlkit automatically generates `__resolveType` functions based on these fields.
|
|
174
|
+
|
|
175
|
+
See [Union Types - Custom Discriminator Fields](./schema/unions.md#custom-discriminator-fields) for detailed usage and validation rules.
|
|
176
|
+
|
|
158
177
|
## Source Directory
|
|
159
178
|
|
|
160
179
|
By default, gqlkit scans `src/gqlkit/schema` for types and resolvers.
|
package/docs/getting-started.md
CHANGED
|
@@ -57,7 +57,7 @@ Create `src/gqlkit/gqlkit.ts` to export resolver factories:
|
|
|
57
57
|
import { createGqlkitApis } from "@gqlkit-ts/runtime";
|
|
58
58
|
import type { Context } from "./context";
|
|
59
59
|
|
|
60
|
-
export const { defineQuery, defineMutation, defineField } =
|
|
60
|
+
export const { defineQuery, defineMutation, defineSubscription, defineField } =
|
|
61
61
|
createGqlkitApis<Context>();
|
|
62
62
|
```
|
|
63
63
|
|
|
@@ -118,3 +118,4 @@ export const schema = makeExecutableSchema({ typeDefs, resolvers });
|
|
|
118
118
|
- [HTTP Server Integration](./integration/yoga) - Connect your schema to graphql-yoga, Apollo Server, or other HTTP servers
|
|
119
119
|
- [Object Types](./schema/objects) - Learn more about defining types
|
|
120
120
|
- [Queries & Mutations](./schema/queries-mutations) - Advanced resolver patterns
|
|
121
|
+
- [Subscriptions](./schema/subscriptions) - Real-time data with subscriptions
|
package/docs/index.md
CHANGED
|
@@ -25,6 +25,7 @@ gqlkit generates GraphQL schema and resolver maps from TypeScript types and func
|
|
|
25
25
|
- [Defining Object Types](./schema/objects.md): Plain TypeScript type exports become GraphQL Object types.
|
|
26
26
|
- [Defining Input Types](./schema/inputs.md): TypeScript types with Input suffix are treated as GraphQL input types.
|
|
27
27
|
- [Defining Queries and Mutations](./schema/queries-mutations.md): Define Query and Mutation fields using the @gqlkit-ts/runtime API.
|
|
28
|
+
- [Defining Subscriptions](./schema/subscriptions.md): Define Subscription fields using the @gqlkit-ts/runtime API.
|
|
28
29
|
- [Defining Field Resolvers](./schema/fields.md): Add computed fields to object types using defineField.
|
|
29
30
|
- [Defining Scalar Types](./schema/scalars.md): gqlkit provides built-in scalar types and supports custom scalar definitions.
|
|
30
31
|
- [Defining Enum Types](./schema/enums.md): gqlkit converts TypeScript string literal unions and enums to GraphQL enum types.
|
|
@@ -40,6 +41,7 @@ gqlkit generates GraphQL schema and resolver maps from TypeScript types and func
|
|
|
40
41
|
- [Integration with Apollo Server](./integration/apollo.md): Use gqlkit with Apollo Server, a popular GraphQL server.
|
|
41
42
|
- [Integration with Drizzle ORM](./integration/drizzle.md): Derive GraphQL types from Drizzle table definitions.
|
|
42
43
|
- [Integration with Prisma](./integration/prisma.md): Derive GraphQL types from Prisma model types.
|
|
44
|
+
- [Integration with Vercel AI SDK](./integration/ai-sdk.md): Stream AI responses as GraphQL subscriptions using the Vercel AI SDK.
|
|
43
45
|
|
|
44
46
|
## Guides
|
|
45
47
|
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Integration with Vercel AI SDK
|
|
3
|
+
description: Stream AI responses as GraphQL subscriptions using the Vercel AI SDK.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vercel AI SDK
|
|
7
|
+
|
|
8
|
+
The [Vercel AI SDK](https://ai-sdk.dev/) provides a unified API for working with large language models. gqlkit integrates with the AI SDK by automatically converting its rich message types — including tool invocations, step boundaries, and custom data parts — into GraphQL unions and subscriptions.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```sh filename="npm"
|
|
13
|
+
npm install ai @ai-sdk/openai
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```sh filename="pnpm"
|
|
17
|
+
pnpm add ai @ai-sdk/openai
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```sh filename="yarn"
|
|
21
|
+
yarn add ai @ai-sdk/openai
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Defining Tools
|
|
25
|
+
|
|
26
|
+
Define AI tools using the AI SDK's `tool()` helper. The `ToolSet` and `InferUITools` types let you derive strongly-typed UI tool representations:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// src/agent.ts
|
|
30
|
+
import type { InferUITools, ToolSet, UIMessage } from "ai";
|
|
31
|
+
import { tool } from "ai";
|
|
32
|
+
import { z } from "zod";
|
|
33
|
+
|
|
34
|
+
export const tools = {
|
|
35
|
+
weather: tool({
|
|
36
|
+
description: "Get current weather for a location",
|
|
37
|
+
inputSchema: z.object({
|
|
38
|
+
location: z.string().describe("City name"),
|
|
39
|
+
}),
|
|
40
|
+
execute: async ({ location }) => ({
|
|
41
|
+
location,
|
|
42
|
+
temperature: 72,
|
|
43
|
+
condition: "sunny" as const,
|
|
44
|
+
}),
|
|
45
|
+
}),
|
|
46
|
+
calculate: tool({
|
|
47
|
+
description: "Calculate a math expression",
|
|
48
|
+
inputSchema: z.object({
|
|
49
|
+
expression: z.string().describe("Math expression"),
|
|
50
|
+
}),
|
|
51
|
+
execute: async ({ expression }) => ({
|
|
52
|
+
expression,
|
|
53
|
+
result: 42,
|
|
54
|
+
}),
|
|
55
|
+
}),
|
|
56
|
+
} satisfies ToolSet;
|
|
57
|
+
|
|
58
|
+
export type AppTools = InferUITools<typeof tools>;
|
|
59
|
+
|
|
60
|
+
export type AppMetadata = {
|
|
61
|
+
model: string;
|
|
62
|
+
timestamp: number;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export type AppData = {
|
|
66
|
+
chart: { labels: string[]; values: number[] };
|
|
67
|
+
suggestion: { text: string; confidence: number };
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type AppMessage = UIMessage<AppMetadata, AppData, AppTools>;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Defining the Message Type
|
|
74
|
+
|
|
75
|
+
Re-export your `AppMessage` as a named type in the gqlkit schema directory. gqlkit discovers the `UIMessage` fields — including the `parts` union — transitively, so you don't need to manually define each part type:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// src/gqlkit/schema/message.ts
|
|
79
|
+
import type { NoArgs } from "@gqlkit-ts/runtime";
|
|
80
|
+
import type { AppMessage } from "../../agent.js";
|
|
81
|
+
import { defineQuery } from "../gqlkit.js";
|
|
82
|
+
|
|
83
|
+
// Re-export AppMessage as Message — gqlkit discovers UIMessage fields transitively.
|
|
84
|
+
export type Message = AppMessage;
|
|
85
|
+
|
|
86
|
+
export const messages = defineQuery<NoArgs, Message[]>(() => mockMessages);
|
|
87
|
+
export const message = defineQuery<{ id: string }, Message | null>(
|
|
88
|
+
(_root, args) => mockMessages.find((m) => m.id === args.id) ?? null,
|
|
89
|
+
);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The `parts` field on `UIMessage` is a discriminated union of text parts, tool invocations, tool results, step boundaries, source parts, file parts, reasoning parts, and your custom data parts. gqlkit automatically generates a corresponding GraphQL union type for this.
|
|
93
|
+
|
|
94
|
+
## Defining Subscriptions
|
|
95
|
+
|
|
96
|
+
The AI SDK provides two streaming patterns that map naturally to GraphQL subscriptions:
|
|
97
|
+
|
|
98
|
+
### Raw Stream (chunk-by-chunk)
|
|
99
|
+
|
|
100
|
+
Use `toUIMessageStream()` to yield each `UIMessageChunk` as it arrives:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// src/gqlkit/schema/subscription.ts
|
|
104
|
+
import type { InferUIMessageChunk } from "ai";
|
|
105
|
+
import { streamText } from "ai";
|
|
106
|
+
import type { AppMessage } from "../../agent.js";
|
|
107
|
+
import { tools } from "../../agent.js";
|
|
108
|
+
import { defineSubscription } from "../gqlkit.js";
|
|
109
|
+
|
|
110
|
+
export type ChatStreamChunk = InferUIMessageChunk<AppMessage>;
|
|
111
|
+
|
|
112
|
+
export const chatStream = defineSubscription<
|
|
113
|
+
{ prompt: string },
|
|
114
|
+
ChatStreamChunk
|
|
115
|
+
>(async (_root, args, ctx) => {
|
|
116
|
+
const result = streamText({ model: ctx.model, prompt: args.prompt, tools });
|
|
117
|
+
return result.toUIMessageStream<AppMessage>();
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Assembled Message (progressive updates)
|
|
122
|
+
|
|
123
|
+
Use `readUIMessageStream()` to yield the progressively-built `Message` on each update:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { readUIMessageStream, streamText } from "ai";
|
|
127
|
+
import type { AppMessage } from "../../agent.js";
|
|
128
|
+
import { tools } from "../../agent.js";
|
|
129
|
+
import { defineSubscription } from "../gqlkit.js";
|
|
130
|
+
import type { Message } from "./message.js";
|
|
131
|
+
|
|
132
|
+
export const chat = defineSubscription<{ prompt: string }, Message>(
|
|
133
|
+
async (_root, args, ctx) => {
|
|
134
|
+
const result = streamText({ model: ctx.model, prompt: args.prompt, tools });
|
|
135
|
+
return readUIMessageStream<AppMessage>({
|
|
136
|
+
stream: result.toUIMessageStream(),
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Discriminator Fields Configuration
|
|
143
|
+
|
|
144
|
+
The AI SDK's union types use discriminator fields that gqlkit needs to know about. Configure them in `gqlkit.config.ts`:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// gqlkit.config.ts
|
|
148
|
+
import type { GqlkitConfig } from "@gqlkit-ts/cli";
|
|
149
|
+
|
|
150
|
+
const config: GqlkitConfig = {
|
|
151
|
+
discriminatorFields: {
|
|
152
|
+
// Message.parts union — discriminated by "type" with "state" as a secondary field
|
|
153
|
+
MessageParts: ["type", "state"],
|
|
154
|
+
// UIMessageChunk variants — discriminated by "type"
|
|
155
|
+
ChatStreamChunk: ["type"],
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default config;
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The `discriminatorFields` option tells gqlkit which fields to use when generating the GraphQL union's `__resolveType` implementation.
|
|
163
|
+
|
|
164
|
+
## Context with Language Model
|
|
165
|
+
|
|
166
|
+
Inject the `LanguageModel` via context so resolvers stay testable and model-agnostic. For basic setup, see [Set Up Context and Resolver Factories](../getting-started.md#set-up-context-and-resolver-factories).
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// src/gqlkit/context.ts
|
|
170
|
+
import type { LanguageModel } from "ai";
|
|
171
|
+
|
|
172
|
+
export type Context = {
|
|
173
|
+
model: LanguageModel;
|
|
174
|
+
};
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Complete Example
|
|
178
|
+
|
|
179
|
+
See the [examples/with-ai-sdk](https://github.com/gqlkit/gqlkit/tree/main/examples/with-ai-sdk) directory for a complete working example with:
|
|
180
|
+
|
|
181
|
+
- Tool definitions with Zod schemas
|
|
182
|
+
- `UIMessage` with custom metadata, data parts, and tool types
|
|
183
|
+
- Both streaming patterns (`chatStream` and `chat` subscriptions)
|
|
184
|
+
- Discriminator fields configuration
|
|
185
|
+
|
|
186
|
+
## Further Reading
|
|
187
|
+
|
|
188
|
+
- [AI SDK Documentation](https://ai-sdk.dev/docs)
|
|
189
|
+
- [AI SDK GitHub](https://github.com/vercel/ai)
|
|
@@ -34,6 +34,13 @@ gqlkit maps TypeScript types to GraphQL types as follows:
|
|
|
34
34
|
|
|
35
35
|
gqlkit generates type names using predictable conventions:
|
|
36
36
|
|
|
37
|
+
For `defineQuery`, `defineMutation`, and `defineField`, GraphQL field names are also derived from exported variable names:
|
|
38
|
+
|
|
39
|
+
- Default: the full export name is used as-is.
|
|
40
|
+
- If the export name contains `$`, gqlkit uses the substring after the last `$`.
|
|
41
|
+
- Common usage is a single prefix (for example, `Query$users` -> `users`).
|
|
42
|
+
- If the export name ends with `$`, gqlkit reports an error.
|
|
43
|
+
|
|
37
44
|
| Context | Pattern | Example |
|
|
38
45
|
|---------|---------|---------|
|
|
39
46
|
| Object field (inline) | `{ParentType}{Field}` | `User.profile` → `UserProfile` |
|
package/docs/schema/fields.md
CHANGED
|
@@ -7,6 +7,12 @@ description: Add computed fields to object types using defineField.
|
|
|
7
7
|
|
|
8
8
|
Add computed fields to object types using `defineField`. Define them alongside the type.
|
|
9
9
|
|
|
10
|
+
GraphQL field names are derived from the exported variable name:
|
|
11
|
+
|
|
12
|
+
- Default: the full export name is used as-is.
|
|
13
|
+
- If the export name contains `$`, gqlkit uses the substring after the last `$`.
|
|
14
|
+
- If the export name ends with `$`, gqlkit reports an error.
|
|
15
|
+
|
|
10
16
|
## Basic Usage
|
|
11
17
|
|
|
12
18
|
```typescript
|
|
@@ -44,6 +50,15 @@ type User {
|
|
|
44
50
|
}
|
|
45
51
|
```
|
|
46
52
|
|
|
53
|
+
Example with `$` delimiter:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// GraphQL field name: posts
|
|
57
|
+
export const User$posts = defineField<User, NoArgs, Post[]>(
|
|
58
|
+
(parent) => findPostsByAuthor(parent.id)
|
|
59
|
+
);
|
|
60
|
+
```
|
|
61
|
+
|
|
47
62
|
## Resolver Function Signature
|
|
48
63
|
|
|
49
64
|
Field resolvers receive four arguments:
|
|
@@ -11,7 +11,11 @@ Define Query and Mutation fields using the `@gqlkit-ts/runtime` API.
|
|
|
11
11
|
|
|
12
12
|
## Query Resolvers
|
|
13
13
|
|
|
14
|
-
Use `defineQuery` to define Query fields.
|
|
14
|
+
Use `defineQuery` to define Query fields. GraphQL field names are derived from the exported variable name:
|
|
15
|
+
|
|
16
|
+
- Default: the full export name is used as-is.
|
|
17
|
+
- If the export name contains `$`, gqlkit uses the substring after the last `$`.
|
|
18
|
+
- If the export name ends with `$`, gqlkit reports an error.
|
|
15
19
|
|
|
16
20
|
```typescript
|
|
17
21
|
import { defineQuery } from "../gqlkit";
|
|
@@ -50,9 +54,16 @@ type Query {
|
|
|
50
54
|
}
|
|
51
55
|
```
|
|
52
56
|
|
|
57
|
+
Example with `$` delimiter:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// GraphQL field name: users
|
|
61
|
+
export const Query$users = defineQuery<NoArgs, User[]>(() => []);
|
|
62
|
+
```
|
|
63
|
+
|
|
53
64
|
## Mutation Resolvers
|
|
54
65
|
|
|
55
|
-
Use `defineMutation` to define Mutation fields:
|
|
66
|
+
Use `defineMutation` to define Mutation fields. The same export-name rule applies:
|
|
56
67
|
|
|
57
68
|
```typescript
|
|
58
69
|
import { defineMutation } from "../gqlkit";
|
|
@@ -71,6 +82,14 @@ export const deleteUser = defineMutation<{ id: string }, boolean>(
|
|
|
71
82
|
return ctx.db.deleteUser(args.id);
|
|
72
83
|
}
|
|
73
84
|
);
|
|
85
|
+
|
|
86
|
+
// GraphQL field name: createUser
|
|
87
|
+
export const Mutation$createUser = defineMutation<
|
|
88
|
+
{ input: CreateUserInput },
|
|
89
|
+
User
|
|
90
|
+
>((_root, args, ctx) => {
|
|
91
|
+
return ctx.db.createUser(args.input);
|
|
92
|
+
});
|
|
74
93
|
```
|
|
75
94
|
|
|
76
95
|
Generates:
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Defining Subscriptions
|
|
3
|
+
description: Define Subscription fields using the @gqlkit-ts/runtime API.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Subscriptions
|
|
7
|
+
|
|
8
|
+
Define Subscription fields using the `@gqlkit-ts/runtime` API.
|
|
9
|
+
|
|
10
|
+
> **Prerequisites**: This guide assumes you have completed the [basic setup](../getting-started.md#set-up-context-and-resolver-factories).
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
Export `defineSubscription` from your `gqlkit.ts`:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { createGqlkitApis } from "@gqlkit-ts/runtime";
|
|
18
|
+
import type { Context } from "./context";
|
|
19
|
+
|
|
20
|
+
export const { defineQuery, defineMutation, defineSubscription } =
|
|
21
|
+
createGqlkitApis<Context>();
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Subscription Resolvers
|
|
25
|
+
|
|
26
|
+
Use `defineSubscription` to define Subscription fields. The resolver is typically an async generator function:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { defineSubscription } from "../gqlkit";
|
|
30
|
+
import type { Message } from "./message";
|
|
31
|
+
|
|
32
|
+
// Subscription.messageAdded(channelId: String!)
|
|
33
|
+
export const messageAdded = defineSubscription<
|
|
34
|
+
{ channelId: string },
|
|
35
|
+
Message
|
|
36
|
+
>(async function* (_root, args, ctx) {
|
|
37
|
+
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Generates:
|
|
42
|
+
|
|
43
|
+
```graphql
|
|
44
|
+
type Subscription {
|
|
45
|
+
messageAdded(channelId: String!): Message!
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The same export name conventions apply as with [Queries & Mutations](./queries-mutations.md):
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// GraphQL field name: messageAdded
|
|
53
|
+
export const Subscription$messageAdded = defineSubscription<
|
|
54
|
+
{ channelId: string },
|
|
55
|
+
Message
|
|
56
|
+
>(async function* (_root, args, ctx) {
|
|
57
|
+
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## NoArgs Subscriptions
|
|
62
|
+
|
|
63
|
+
For subscriptions without arguments, use `NoArgs` as the first type parameter — same as with `defineQuery` and `defineMutation`. See [Queries & Mutations](./queries-mutations.md#noargs-queries) for details.
|
|
64
|
+
|
|
65
|
+
## Resolver Function Signature
|
|
66
|
+
|
|
67
|
+
Subscription resolvers receive the same four arguments as Query/Mutation resolvers, but return an `AsyncIterable` instead of a direct value:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
(root, args, ctx, info) => AsyncIterable<T> | Promise<AsyncIterable<T>>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
| Argument | Description |
|
|
74
|
+
|----------|-------------|
|
|
75
|
+
| `root` | The root value (always undefined) |
|
|
76
|
+
| `args` | The arguments passed to the field |
|
|
77
|
+
| `ctx` | The context object (typed via `createGqlkitApis<Context>()`) |
|
|
78
|
+
| `info` | GraphQL resolve info |
|
|
79
|
+
|
|
80
|
+
## Inline Object Arguments
|
|
81
|
+
|
|
82
|
+
Subscription arguments support the same inline object types as queries and mutations:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
export const orderUpdated = defineSubscription<
|
|
86
|
+
{
|
|
87
|
+
filter: {
|
|
88
|
+
orderId: string | null;
|
|
89
|
+
status: string | null;
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
Order
|
|
93
|
+
>(async function* (_root, args, ctx) {
|
|
94
|
+
yield* ctx.pubsub.subscribe<Order>("ORDER_UPDATED", args.filter);
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Generates:
|
|
99
|
+
|
|
100
|
+
```graphql
|
|
101
|
+
type Subscription {
|
|
102
|
+
orderUpdated(filter: OrderUpdatedFilterInput!): Order!
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
input OrderUpdatedFilterInput {
|
|
106
|
+
orderId: String
|
|
107
|
+
status: String
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Attaching Directives
|
|
112
|
+
|
|
113
|
+
Add a third type parameter to attach directives:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { defineSubscription } from "../gqlkit";
|
|
117
|
+
import type { AuthDirective } from "./directives";
|
|
118
|
+
import type { Message } from "./message";
|
|
119
|
+
|
|
120
|
+
export const messageAdded = defineSubscription<
|
|
121
|
+
{ channelId: string },
|
|
122
|
+
Message,
|
|
123
|
+
[AuthDirective<{ role: ["USER"] }>]
|
|
124
|
+
>(async function* (_root, args, ctx) {
|
|
125
|
+
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Generates:
|
|
130
|
+
|
|
131
|
+
```graphql
|
|
132
|
+
type Subscription {
|
|
133
|
+
messageAdded(channelId: String!): Message! @auth(role: [USER])
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
See [Directives](./directives.md) for more details on defining and using custom directives.
|
|
138
|
+
|
|
139
|
+
## Documentation
|
|
140
|
+
|
|
141
|
+
TSDoc comments on subscription exports are extracted as GraphQL descriptions:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
/** Subscribe to new messages in a channel. */
|
|
145
|
+
export const messageAdded = defineSubscription<
|
|
146
|
+
{ channelId: string },
|
|
147
|
+
Message
|
|
148
|
+
>(async function* (_root, args, ctx) {
|
|
149
|
+
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @deprecated Use messageAdded instead.
|
|
154
|
+
*/
|
|
155
|
+
export const onMessage = defineSubscription<
|
|
156
|
+
{ channelId: string },
|
|
157
|
+
Message
|
|
158
|
+
>(async function* (_root, args, ctx) {
|
|
159
|
+
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Generates:
|
|
164
|
+
|
|
165
|
+
```graphql
|
|
166
|
+
type Subscription {
|
|
167
|
+
"""Subscribe to new messages in a channel."""
|
|
168
|
+
messageAdded(channelId: String!): Message!
|
|
169
|
+
onMessage(channelId: String!): Message! @deprecated(reason: "Use messageAdded instead.")
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
See [Documentation](./documentation.md) for more details.
|
package/docs/schema/unions.md
CHANGED
|
@@ -279,6 +279,123 @@ export type SearchResult = User | Post;
|
|
|
279
279
|
// resolveType is automatically generated - no manual definition needed
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
+
### Custom Discriminator Fields
|
|
283
|
+
|
|
284
|
+
When union member types use a field other than `__typename` or `$typeName` for discrimination (e.g., external library types like AI SDK's `UIMessagePart`), you can configure custom discriminator fields via `gqlkit.config.ts`. gqlkit will automatically generate `__resolveType` based on the specified fields.
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
// gqlkit.config.ts
|
|
288
|
+
import { defineConfig } from "@gqlkit-ts/cli";
|
|
289
|
+
|
|
290
|
+
export default defineConfig({
|
|
291
|
+
discriminatorFields: {
|
|
292
|
+
ContentPart: "type",
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// src/gqlkit/schema/types.ts
|
|
299
|
+
export interface TextPart {
|
|
300
|
+
type: "text";
|
|
301
|
+
text: string;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export interface ImagePart {
|
|
305
|
+
type: "image";
|
|
306
|
+
url: string;
|
|
307
|
+
alt: string;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export type ContentPart = TextPart | ImagePart;
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Generates a `switch`-based `__resolveType`:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
ContentPart: {
|
|
317
|
+
__resolveType: (obj) => {
|
|
318
|
+
switch (obj.type) {
|
|
319
|
+
case "text": return "TextPart";
|
|
320
|
+
case "image": return "ImagePart";
|
|
321
|
+
default: return undefined;
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Unlike `__typename` or `$typeName`, custom discriminator fields remain as regular GraphQL fields in the generated schema:
|
|
328
|
+
|
|
329
|
+
```graphql
|
|
330
|
+
union ContentPart = ImagePart | TextPart
|
|
331
|
+
|
|
332
|
+
type TextPart {
|
|
333
|
+
type: String!
|
|
334
|
+
text: String!
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
type ImagePart {
|
|
338
|
+
type: String!
|
|
339
|
+
url: String!
|
|
340
|
+
alt: String!
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### Multiple Discriminator Fields
|
|
345
|
+
|
|
346
|
+
When a single field is not enough to uniquely identify each member, you can specify multiple discriminator fields as an array. The first field must exist on all members with a string literal type. Secondary fields do not need to exist on every member.
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
// gqlkit.config.ts
|
|
350
|
+
import { defineConfig } from "@gqlkit-ts/cli";
|
|
351
|
+
|
|
352
|
+
export default defineConfig({
|
|
353
|
+
discriminatorFields: {
|
|
354
|
+
Content: ["type", "mediaType"],
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
export type Content =
|
|
361
|
+
| { type: "text"; mediaType: "plain"; body: string }
|
|
362
|
+
| { type: "text"; mediaType: "html"; html: string }
|
|
363
|
+
| { type: "image"; url: string; alt: string };
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Generates nested `switch` statements and type names derived from the discriminator values:
|
|
367
|
+
|
|
368
|
+
```graphql
|
|
369
|
+
union Content = ContentImage | ContentTextHtml | ContentTextPlain
|
|
370
|
+
|
|
371
|
+
type ContentTextPlain {
|
|
372
|
+
type: String!
|
|
373
|
+
mediaType: String!
|
|
374
|
+
body: String!
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
type ContentTextHtml {
|
|
378
|
+
type: String!
|
|
379
|
+
mediaType: String!
|
|
380
|
+
html: String!
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
type ContentImage {
|
|
384
|
+
type: String!
|
|
385
|
+
url: String!
|
|
386
|
+
alt: String!
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
#### Validation Rules
|
|
391
|
+
|
|
392
|
+
- The **first** discriminator field must exist on **all** union members and have a string literal type
|
|
393
|
+
- Secondary fields do not need to exist on every member, but the combination of values must be unique across all members
|
|
394
|
+
- If a `defineResolveType` is manually defined for the same union, the manual definition takes priority
|
|
395
|
+
- If `discriminatorFields` is configured for a union that also has `$typeName` or `__typename`, the `discriminatorFields` configuration takes priority
|
|
396
|
+
|
|
397
|
+
See [Configuration](../configuration.md#custom-discriminator-fields) for the full config reference.
|
|
398
|
+
|
|
282
399
|
### Manual Resolution
|
|
283
400
|
|
|
284
401
|
For types without `__typename` or `$typeName`, use `defineResolveType`:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gqlkit-ts/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Just types and functions — write TypeScript, generate GraphQL.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@graphql-tools/utils": "^11.0.0",
|
|
44
|
-
"gunshi": "^0.
|
|
44
|
+
"gunshi": "^0.29.0",
|
|
45
45
|
"jiti": "^2.4.2",
|
|
46
46
|
"shell-quote": "^1.8.3"
|
|
47
47
|
},
|
|
@@ -59,9 +59,9 @@
|
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/shell-quote": "1.7.5",
|
|
62
|
-
"memfs": "4.56.
|
|
62
|
+
"memfs": "4.56.11",
|
|
63
63
|
"@gqlkit-ts/docs": "0.0.1",
|
|
64
|
-
"@gqlkit-ts/runtime": "0.
|
|
64
|
+
"@gqlkit-ts/runtime": "0.3.0"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"build": "tsc --build && bundle-docs --target ./docs",
|