@gqlkit-ts/cli 0.5.0 → 0.6.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 (58) hide show
  1. package/README.md +3 -1
  2. package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
  3. package/dist/auto-type-generator/auto-type-generator.js +4 -1
  4. package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
  5. package/dist/auto-type-generator/naming-convention.d.ts +2 -2
  6. package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
  7. package/dist/auto-type-generator/resolver-field-iterator.d.ts +1 -1
  8. package/dist/auto-type-generator/resolver-field-iterator.d.ts.map +1 -1
  9. package/dist/auto-type-generator/resolver-field-iterator.js +3 -0
  10. package/dist/auto-type-generator/resolver-field-iterator.js.map +1 -1
  11. package/dist/commands/docs.d.ts +1 -0
  12. package/dist/commands/docs.d.ts.map +1 -1
  13. package/dist/commands/gen.d.ts +1 -0
  14. package/dist/commands/gen.d.ts.map +1 -1
  15. package/dist/commands/main.d.ts +1 -0
  16. package/dist/commands/main.d.ts.map +1 -1
  17. package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
  18. package/dist/gen-orchestrator/orchestrator.js +32 -1
  19. package/dist/gen-orchestrator/orchestrator.js.map +1 -1
  20. package/dist/resolver-extractor/extract-resolvers.d.ts +4 -0
  21. package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
  22. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +2 -1
  23. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
  24. package/dist/resolver-extractor/extractor/define-api-extractor.js +31 -6
  25. package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
  26. package/dist/resolver-extractor/index.d.ts +1 -1
  27. package/dist/resolver-extractor/index.d.ts.map +1 -1
  28. package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
  29. package/dist/schema-generator/emitter/code-emitter.js +11 -3
  30. package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
  31. package/dist/schema-generator/integrator/result-integrator.d.ts +1 -0
  32. package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
  33. package/dist/schema-generator/integrator/result-integrator.js +26 -1
  34. package/dist/schema-generator/integrator/result-integrator.js.map +1 -1
  35. package/dist/type-extractor/extractor/type-name-collector.d.ts +6 -0
  36. package/dist/type-extractor/extractor/type-name-collector.d.ts.map +1 -1
  37. package/dist/type-extractor/extractor/type-name-collector.js +54 -18
  38. package/dist/type-extractor/extractor/type-name-collector.js.map +1 -1
  39. package/dist/type-extractor/types/diagnostics.d.ts +1 -1
  40. package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
  41. package/docs/getting-started.md +2 -1
  42. package/docs/index.md +1 -0
  43. package/docs/schema/conventions.md +7 -0
  44. package/docs/schema/fields.md +15 -0
  45. package/docs/schema/queries-mutations.md +21 -2
  46. package/docs/schema/subscriptions.md +173 -0
  47. package/package.json +3 -3
  48. package/src/auto-type-generator/auto-type-generator.ts +12 -4
  49. package/src/auto-type-generator/naming-convention.ts +2 -2
  50. package/src/auto-type-generator/resolver-field-iterator.ts +5 -1
  51. package/src/gen-orchestrator/orchestrator.ts +38 -1
  52. package/src/resolver-extractor/extract-resolvers.ts +5 -0
  53. package/src/resolver-extractor/extractor/define-api-extractor.ts +43 -7
  54. package/src/resolver-extractor/index.ts +1 -0
  55. package/src/schema-generator/emitter/code-emitter.ts +17 -4
  56. package/src/schema-generator/integrator/result-integrator.ts +30 -1
  57. package/src/type-extractor/extractor/type-name-collector.ts +80 -18
  58. package/src/type-extractor/types/diagnostics.ts +2 -1
@@ -3,7 +3,7 @@ export interface SourceLocation {
3
3
  readonly line: number;
4
4
  readonly column: number;
5
5
  }
6
- export type DiagnosticCode = "DIRECTORY_NOT_FOUND" | "PARSE_ERROR" | "UNSUPPORTED_SYNTAX" | "RESERVED_TYPE_NAME" | "UNRESOLVED_REFERENCE" | "NAMING_CONVENTION_MISMATCH" | "INVALID_RESOLVER_SIGNATURE" | "UNSUPPORTED_RETURN_TYPE" | "UNSUPPORTED_ARG_TYPE" | "UNKNOWN_TARGET_TYPE" | "PARENT_TYPE_MISMATCH" | "MISSING_PARENT_TYPE" | "UNSUPPORTED_ENUM_TYPE" | "INVALID_ENUM_MEMBER" | "INVALID_INPUT_TYPE" | "UNKNOWN_ARGUMENT_TYPE" | "OUTPUT_TYPE_IN_INPUT" | "CIRCULAR_INPUT_REFERENCE" | "UNKNOWN_BRANDED_SCALAR" | "INVALID_SCALAR_IMPORT" | "CONFLICTING_SCALAR_TYPE" | "INVALID_DEFINE_CALL" | "CONFIG_SYNTAX_ERROR" | "CONFIG_FILE_NOT_FOUND" | "CONFIG_MISSING_PROPERTY" | "CONFIG_INVALID_TYPE" | "CONFIG_INVALID_PATH" | "CONFIG_BUILTIN_OVERRIDE" | "CONFIG_DUPLICATE_MAPPING" | "CONFIG_DUPLICATE_TYPE" | "CONFIG_INVALID_OUTPUT_TYPE" | "CONFIG_INVALID_OUTPUT_PATH" | "CONFIG_INVALID_SOURCE_DIR" | "CONFIG_INVALID_IGNORE_GLOBS" | "CONFIG_INVALID_HOOK_TYPE" | "CONFIG_INVALID_HOOK_COMMAND" | "CONFIG_INVALID_ONLY_VALUE" | "CONFIG_INVALID_IMPORT_EXTENSION" | "CUSTOM_SCALAR_TYPE_NOT_FOUND" | "TSCONFIG_NOT_FOUND" | "TSCONFIG_PARSE_ERROR" | "TSCONFIG_INVALID" | "ONEOF_FIELD_NAME_CONFLICT" | "ONEOF_MULTIPLE_PROPERTIES" | "ONEOF_EMPTY_OBJECT" | "ONEOF_INVALID_FIELD_TYPE" | "ONEOF_DUPLICATE_PROPERTY" | "ONEOF_MIXED_MEMBERS" | "ONEOF_NAMED_TYPE_UNION" | "MULTIPLE_INPUT_TYPES" | "MISSING_INPUT_TYPE" | "MISSING_OUTPUT_TYPE" | "EMPTY_DIRECTIVE_NAME" | "UNRESOLVABLE_ARGUMENT" | "UNRESOLVABLE_ARG_TYPE" | "INVALID_LOCATION" | "INVALID_DIRECTIVE_LOCATION" | "UNSUPPORTED_DIRECTIVE_LOCATION" | "UNDEFINED_DIRECTIVE" | "INTERFACE_NOT_FOUND" | "INTERFACE_NOT_INTERFACE" | "INTERFACE_MISSING_FIELD" | "INTERFACE_FIELD_TYPE_MISMATCH" | "INTERFACE_CIRCULAR_REFERENCE" | "UNRESOLVABLE_DEFAULT_VALUE" | "AUTO_TYPE_NAME_COLLISION_USER" | "AUTO_TYPE_NAME_COLLISION_AUTO" | "MODULE_RESOLUTION_ERROR" | "SKIPPED_FIELD" | "SKIPPED_ENUM_VALUE" | "INDEX_SIGNATURE_ONLY" | "UNKNOWN_ABSTRACT_TYPE" | "INVALID_ABSTRACT_TYPE_KIND" | "INVALID_OBJECT_TYPE_KIND" | "DUPLICATE_RESOLVE_TYPE" | "DUPLICATE_IS_TYPE_OF" | "MISSING_ABSTRACT_TYPE_RESOLVER" | "DUPLICATE_ENUM_VALUE" | "DUPLICATE_ENUM_VALUE_AFTER_CONVERSION" | "INVALID_ENUM_MEMBER_NAME" | "AMBIGUOUS_SCALAR_BASE_TYPE" | "INLINE_UNION_PRIMITIVE_MEMBER" | "INLINE_UNION_ENUM_MEMBER" | "INLINE_UNION_UNRESOLVABLE_MEMBER" | "MISSING_TYPENAME_PROPERTY" | "INVALID_TYPENAME_TYPE" | "OPTIONAL_TYPENAME_PROPERTY" | "NULLABLE_TYPENAME_PROPERTY" | "TYPENAME_FIELD_STRUCTURE_MISMATCH" | "DUPLICATE_TYPENAME_VALUE" | "IGNORE_FIELD_NOT_FOUND" | "IGNORE_ALL_FIELDS";
6
+ export type DiagnosticCode = "DIRECTORY_NOT_FOUND" | "PARSE_ERROR" | "UNSUPPORTED_SYNTAX" | "RESERVED_TYPE_NAME" | "UNRESOLVED_REFERENCE" | "NAMING_CONVENTION_MISMATCH" | "INVALID_RESOLVER_SIGNATURE" | "UNSUPPORTED_RETURN_TYPE" | "UNSUPPORTED_ARG_TYPE" | "UNKNOWN_TARGET_TYPE" | "PARENT_TYPE_MISMATCH" | "MISSING_PARENT_TYPE" | "UNSUPPORTED_ENUM_TYPE" | "INVALID_ENUM_MEMBER" | "INVALID_INPUT_TYPE" | "UNKNOWN_ARGUMENT_TYPE" | "OUTPUT_TYPE_IN_INPUT" | "CIRCULAR_INPUT_REFERENCE" | "UNKNOWN_BRANDED_SCALAR" | "INVALID_SCALAR_IMPORT" | "CONFLICTING_SCALAR_TYPE" | "INVALID_DEFINE_CALL" | "CONFIG_SYNTAX_ERROR" | "CONFIG_FILE_NOT_FOUND" | "CONFIG_MISSING_PROPERTY" | "CONFIG_INVALID_TYPE" | "CONFIG_INVALID_PATH" | "CONFIG_BUILTIN_OVERRIDE" | "CONFIG_DUPLICATE_MAPPING" | "CONFIG_DUPLICATE_TYPE" | "CONFIG_INVALID_OUTPUT_TYPE" | "CONFIG_INVALID_OUTPUT_PATH" | "CONFIG_INVALID_SOURCE_DIR" | "CONFIG_INVALID_IGNORE_GLOBS" | "CONFIG_INVALID_HOOK_TYPE" | "CONFIG_INVALID_HOOK_COMMAND" | "CONFIG_INVALID_ONLY_VALUE" | "CONFIG_INVALID_IMPORT_EXTENSION" | "CUSTOM_SCALAR_TYPE_NOT_FOUND" | "TSCONFIG_NOT_FOUND" | "TSCONFIG_PARSE_ERROR" | "TSCONFIG_INVALID" | "ONEOF_FIELD_NAME_CONFLICT" | "ONEOF_MULTIPLE_PROPERTIES" | "ONEOF_EMPTY_OBJECT" | "ONEOF_INVALID_FIELD_TYPE" | "ONEOF_DUPLICATE_PROPERTY" | "ONEOF_MIXED_MEMBERS" | "ONEOF_NAMED_TYPE_UNION" | "MULTIPLE_INPUT_TYPES" | "MISSING_INPUT_TYPE" | "MISSING_OUTPUT_TYPE" | "EMPTY_DIRECTIVE_NAME" | "UNRESOLVABLE_ARGUMENT" | "UNRESOLVABLE_ARG_TYPE" | "INVALID_LOCATION" | "INVALID_DIRECTIVE_LOCATION" | "UNSUPPORTED_DIRECTIVE_LOCATION" | "UNDEFINED_DIRECTIVE" | "INTERFACE_NOT_FOUND" | "INTERFACE_NOT_INTERFACE" | "INTERFACE_MISSING_FIELD" | "INTERFACE_FIELD_TYPE_MISMATCH" | "INTERFACE_CIRCULAR_REFERENCE" | "UNRESOLVABLE_DEFAULT_VALUE" | "AUTO_TYPE_NAME_COLLISION_USER" | "AUTO_TYPE_NAME_COLLISION_AUTO" | "MODULE_RESOLUTION_ERROR" | "SKIPPED_FIELD" | "SKIPPED_ENUM_VALUE" | "INDEX_SIGNATURE_ONLY" | "UNKNOWN_ABSTRACT_TYPE" | "INVALID_ABSTRACT_TYPE_KIND" | "INVALID_OBJECT_TYPE_KIND" | "DUPLICATE_RESOLVE_TYPE" | "DUPLICATE_IS_TYPE_OF" | "MISSING_ABSTRACT_TYPE_RESOLVER" | "DUPLICATE_ENUM_VALUE" | "DUPLICATE_ENUM_VALUE_AFTER_CONVERSION" | "INVALID_ENUM_MEMBER_NAME" | "AMBIGUOUS_SCALAR_BASE_TYPE" | "INLINE_UNION_PRIMITIVE_MEMBER" | "INLINE_UNION_ENUM_MEMBER" | "INLINE_UNION_UNRESOLVABLE_MEMBER" | "MISSING_TYPENAME_PROPERTY" | "INVALID_TYPENAME_TYPE" | "OPTIONAL_TYPENAME_PROPERTY" | "NULLABLE_TYPENAME_PROPERTY" | "TYPENAME_FIELD_STRUCTURE_MISMATCH" | "DUPLICATE_TYPENAME_VALUE" | "IGNORE_FIELD_NOT_FOUND" | "IGNORE_ALL_FIELDS" | "DUPLICATE_TYPE_EXPORT";
7
7
  export interface Diagnostic {
8
8
  readonly code: DiagnosticCode;
9
9
  readonly message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../src/type-extractor/types/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,cAAc,GACtB,qBAAqB,GACrB,aAAa,GACb,oBAAoB,GACpB,oBAAoB,GACpB,sBAAsB,GACtB,4BAA4B,GAC5B,4BAA4B,GAC5B,yBAAyB,GACzB,sBAAsB,GACtB,qBAAqB,GACrB,sBAAsB,GACtB,qBAAqB,GACrB,uBAAuB,GACvB,qBAAqB,GACrB,oBAAoB,GACpB,uBAAuB,GACvB,sBAAsB,GACtB,0BAA0B,GAC1B,wBAAwB,GACxB,uBAAuB,GACvB,yBAAyB,GACzB,qBAAqB,GACrB,qBAAqB,GACrB,uBAAuB,GACvB,yBAAyB,GACzB,qBAAqB,GACrB,qBAAqB,GACrB,yBAAyB,GACzB,0BAA0B,GAC1B,uBAAuB,GACvB,4BAA4B,GAC5B,4BAA4B,GAC5B,2BAA2B,GAC3B,6BAA6B,GAC7B,0BAA0B,GAC1B,6BAA6B,GAC7B,2BAA2B,GAC3B,iCAAiC,GACjC,8BAA8B,GAC9B,oBAAoB,GACpB,sBAAsB,GACtB,kBAAkB,GAClB,2BAA2B,GAC3B,2BAA2B,GAC3B,oBAAoB,GACpB,0BAA0B,GAC1B,0BAA0B,GAC1B,qBAAqB,GACrB,wBAAwB,GACxB,sBAAsB,GACtB,oBAAoB,GACpB,qBAAqB,GACrB,sBAAsB,GACtB,uBAAuB,GACvB,uBAAuB,GACvB,kBAAkB,GAClB,4BAA4B,GAC5B,gCAAgC,GAChC,qBAAqB,GACrB,qBAAqB,GACrB,yBAAyB,GACzB,yBAAyB,GACzB,+BAA+B,GAC/B,8BAA8B,GAC9B,4BAA4B,GAC5B,+BAA+B,GAC/B,+BAA+B,GAC/B,yBAAyB,GACzB,eAAe,GACf,oBAAoB,GACpB,sBAAsB,GACtB,uBAAuB,GACvB,4BAA4B,GAC5B,0BAA0B,GAC1B,wBAAwB,GACxB,sBAAsB,GACtB,gCAAgC,GAChC,sBAAsB,GACtB,uCAAuC,GACvC,0BAA0B,GAC1B,4BAA4B,GAC5B,+BAA+B,GAC/B,0BAA0B,GAC1B,kCAAkC,GAClC,2BAA2B,GAC3B,uBAAuB,GACvB,4BAA4B,GAC5B,4BAA4B,GAC5B,mCAAmC,GACnC,0BAA0B,GAC1B,wBAAwB,GACxB,mBAAmB,CAAC;AAExB,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CAC9C"}
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../src/type-extractor/types/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,cAAc,GACtB,qBAAqB,GACrB,aAAa,GACb,oBAAoB,GACpB,oBAAoB,GACpB,sBAAsB,GACtB,4BAA4B,GAC5B,4BAA4B,GAC5B,yBAAyB,GACzB,sBAAsB,GACtB,qBAAqB,GACrB,sBAAsB,GACtB,qBAAqB,GACrB,uBAAuB,GACvB,qBAAqB,GACrB,oBAAoB,GACpB,uBAAuB,GACvB,sBAAsB,GACtB,0BAA0B,GAC1B,wBAAwB,GACxB,uBAAuB,GACvB,yBAAyB,GACzB,qBAAqB,GACrB,qBAAqB,GACrB,uBAAuB,GACvB,yBAAyB,GACzB,qBAAqB,GACrB,qBAAqB,GACrB,yBAAyB,GACzB,0BAA0B,GAC1B,uBAAuB,GACvB,4BAA4B,GAC5B,4BAA4B,GAC5B,2BAA2B,GAC3B,6BAA6B,GAC7B,0BAA0B,GAC1B,6BAA6B,GAC7B,2BAA2B,GAC3B,iCAAiC,GACjC,8BAA8B,GAC9B,oBAAoB,GACpB,sBAAsB,GACtB,kBAAkB,GAClB,2BAA2B,GAC3B,2BAA2B,GAC3B,oBAAoB,GACpB,0BAA0B,GAC1B,0BAA0B,GAC1B,qBAAqB,GACrB,wBAAwB,GACxB,sBAAsB,GACtB,oBAAoB,GACpB,qBAAqB,GACrB,sBAAsB,GACtB,uBAAuB,GACvB,uBAAuB,GACvB,kBAAkB,GAClB,4BAA4B,GAC5B,gCAAgC,GAChC,qBAAqB,GACrB,qBAAqB,GACrB,yBAAyB,GACzB,yBAAyB,GACzB,+BAA+B,GAC/B,8BAA8B,GAC9B,4BAA4B,GAC5B,+BAA+B,GAC/B,+BAA+B,GAC/B,yBAAyB,GACzB,eAAe,GACf,oBAAoB,GACpB,sBAAsB,GACtB,uBAAuB,GACvB,4BAA4B,GAC5B,0BAA0B,GAC1B,wBAAwB,GACxB,sBAAsB,GACtB,gCAAgC,GAChC,sBAAsB,GACtB,uCAAuC,GACvC,0BAA0B,GAC1B,4BAA4B,GAC5B,+BAA+B,GAC/B,0BAA0B,GAC1B,kCAAkC,GAClC,2BAA2B,GAC3B,uBAAuB,GACvB,4BAA4B,GAC5B,4BAA4B,GAC5B,mCAAmC,GACnC,0BAA0B,GAC1B,wBAAwB,GACxB,mBAAmB,GACnB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CAC9C"}
@@ -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.
@@ -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` |
@@ -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. The export name becomes the GraphQL field name:
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gqlkit-ts/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.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.27.5",
44
+ "gunshi": "^0.29.0",
45
45
  "jiti": "^2.4.2",
46
46
  "shell-quote": "^1.8.3"
47
47
  },
@@ -61,7 +61,7 @@
61
61
  "@types/shell-quote": "1.7.5",
62
62
  "memfs": "4.56.10",
63
63
  "@gqlkit-ts/docs": "0.0.1",
64
- "@gqlkit-ts/runtime": "0.2.0"
64
+ "@gqlkit-ts/runtime": "0.3.0"
65
65
  },
66
66
  "scripts": {
67
67
  "build": "tsc --build && bundle-docs --target ./docs",
@@ -52,7 +52,10 @@ import {
52
52
  isInputTypeName,
53
53
  } from "./naming-convention.js";
54
54
  import type { ResolveTypeFieldPattern } from "./resolve-type-generator.js";
55
- import { forEachResolverField } from "./resolver-field-iterator.js";
55
+ import {
56
+ forEachResolverField,
57
+ type ResolverType,
58
+ } from "./resolver-field-iterator.js";
56
59
  import {
57
60
  createFieldNameSet,
58
61
  findTypenameProperty,
@@ -353,7 +356,7 @@ function collectInlineObjectsFromResolvers(
353
356
 
354
357
  function collectInlineObjectsFromResolverArgs(
355
358
  field: GraphQLFieldDefinition,
356
- resolverType: "query" | "mutation" | "field",
359
+ resolverType: ResolverType,
357
360
  parentTypeName: string | null,
358
361
  results: InlineObjectWithContext[],
359
362
  ): void {
@@ -420,7 +423,7 @@ function collectInlinePayloadsFromResolvers(
420
423
 
421
424
  function collectInlinePayloadFromReturnType(
422
425
  field: GraphQLFieldDefinition,
423
- resolverType: "query" | "mutation" | "field",
426
+ resolverType: ResolverType,
424
427
  parentTypeName: string | null,
425
428
  results: InlineObjectWithContext[],
426
429
  ): void {
@@ -716,6 +719,11 @@ function updateResolversResult(
716
719
  updateResolverField(field, params, "mutation", null),
717
720
  ),
718
721
  },
722
+ subscriptionFields: {
723
+ fields: resolversResult.subscriptionFields.fields.map((field) =>
724
+ updateResolverField(field, params, "subscription", null),
725
+ ),
726
+ },
719
727
  typeExtensions: resolversResult.typeExtensions.map((ext) => ({
720
728
  ...ext,
721
729
  fields: ext.fields.map((field) =>
@@ -728,7 +736,7 @@ function updateResolversResult(
728
736
  function updateResolverField(
729
737
  field: GraphQLFieldDefinition,
730
738
  params: UpdateTypeNamesParams,
731
- resolverType: "query" | "mutation" | "field",
739
+ resolverType: "query" | "mutation" | "subscription" | "field",
732
740
  parentTypeName: string | null,
733
741
  ): GraphQLFieldDefinition {
734
742
  const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
@@ -34,7 +34,7 @@ export interface InputFieldContext {
34
34
  */
35
35
  export interface ResolverArgContext {
36
36
  readonly kind: "resolverArg";
37
- readonly resolverType: "query" | "mutation" | "field";
37
+ readonly resolverType: "query" | "mutation" | "subscription" | "field";
38
38
  readonly fieldName: string;
39
39
  readonly argName: string;
40
40
  readonly parentTypeName: string | null;
@@ -49,7 +49,7 @@ export interface ResolverArgContext {
49
49
  */
50
50
  export interface ResolverPayloadContext {
51
51
  readonly kind: "resolverPayload";
52
- readonly resolverType: "query" | "mutation" | "field";
52
+ readonly resolverType: "query" | "mutation" | "subscription" | "field";
53
53
  readonly fieldName: string;
54
54
  readonly parentTypeName: string | null;
55
55
  readonly fieldPath: ReadonlyArray<string>;
@@ -3,7 +3,7 @@ import type {
3
3
  GraphQLFieldDefinition,
4
4
  } from "../resolver-extractor/index.js";
5
5
 
6
- export type ResolverType = "query" | "mutation" | "field";
6
+ export type ResolverType = "query" | "mutation" | "field" | "subscription";
7
7
 
8
8
  export interface ResolverFieldInfo {
9
9
  readonly field: GraphQLFieldDefinition;
@@ -27,6 +27,10 @@ export function forEachResolverField(
27
27
  visitor({ field, resolverType: "mutation", parentTypeName: null });
28
28
  }
29
29
 
30
+ for (const field of resolversResult.subscriptionFields.fields) {
31
+ visitor({ field, resolverType: "subscription", parentTypeName: null });
32
+ }
33
+
30
34
  for (const ext of resolversResult.typeExtensions) {
31
35
  for (const field of ext.fields) {
32
36
  visitor({
@@ -34,6 +34,7 @@ import {
34
34
  collectScalars,
35
35
  type ScalarMetadataInfo,
36
36
  } from "../type-extractor/collector/scalar-collector.js";
37
+ import { isEligibleField } from "../type-extractor/converter/field-eligibility.js";
37
38
  import { convertToGraphQL } from "../type-extractor/converter/graphql-converter.js";
38
39
  import {
39
40
  extractTypesFromProgram,
@@ -86,6 +87,7 @@ interface TypesResult {
86
87
  interface ResolversResult {
87
88
  queryFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
88
89
  mutationFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
90
+ subscriptionFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
89
91
  typeExtensions: ReadonlyArray<TypeExtension>;
90
92
  abstractTypeResolvers: ReadonlyArray<AbstractResolverInfo>;
91
93
  diagnostics: Diagnostics;
@@ -279,20 +281,42 @@ function convertDefineApiToFields(
279
281
  ): {
280
282
  queryFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
281
283
  mutationFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
284
+ subscriptionFields: { fields: ReadonlyArray<GraphQLFieldDefinition> };
282
285
  typeExtensions: ReadonlyArray<TypeExtension>;
286
+ diagnostics: ReadonlyArray<Diagnostic>;
283
287
  } {
284
288
  const queryFields: GraphQLFieldDefinition[] = [];
285
289
  const mutationFields: GraphQLFieldDefinition[] = [];
290
+ const subscriptionFields: GraphQLFieldDefinition[] = [];
286
291
  const typeExtensionMap = new Map<string, GraphQLFieldDefinition[]>();
292
+ const diagnostics: Diagnostic[] = [];
287
293
 
288
294
  for (const resolver of resolvers) {
295
+ const eligibility = isEligibleField({
296
+ fieldName: resolver.fieldName,
297
+ kind: "object",
298
+ });
299
+ if (!eligibility.eligible) {
300
+ diagnostics.push({
301
+ code: "SKIPPED_FIELD",
302
+ message: eligibility.skipReason.message,
303
+ severity: "warning",
304
+ location: {
305
+ file: resolver.sourceLocation.file,
306
+ line: resolver.sourceLocation.line,
307
+ column: resolver.sourceLocation.column,
308
+ },
309
+ });
310
+ continue;
311
+ }
312
+
289
313
  const returnType = resolver.returnType;
290
314
  const fieldDef: GraphQLFieldDefinition = {
291
315
  name: resolver.fieldName,
292
316
  type: convertTsTypeToGraphQLType(returnType),
293
317
  args: resolver.args ? convertArgsToInputValues(resolver.args) : null,
294
318
  sourceLocation: resolver.sourceLocation,
295
- resolverExportName: resolver.fieldName,
319
+ resolverExportName: resolver.resolverExportName,
296
320
  description: resolver.description,
297
321
  deprecated: resolver.deprecated,
298
322
  directives: resolver.directives,
@@ -316,6 +340,8 @@ function convertDefineApiToFields(
316
340
  queryFields.push(fieldDef);
317
341
  } else if (resolver.resolverType === "mutation") {
318
342
  mutationFields.push(fieldDef);
343
+ } else if (resolver.resolverType === "subscription") {
344
+ subscriptionFields.push(fieldDef);
319
345
  } else if (resolver.resolverType === "field" && resolver.parentTypeName) {
320
346
  const existing = typeExtensionMap.get(resolver.parentTypeName) ?? [];
321
347
  existing.push(fieldDef);
@@ -331,7 +357,9 @@ function convertDefineApiToFields(
331
357
  return {
332
358
  queryFields: { fields: queryFields },
333
359
  mutationFields: { fields: mutationFields },
360
+ subscriptionFields: { fields: subscriptionFields },
334
361
  typeExtensions,
362
+ diagnostics,
335
363
  };
336
364
  }
337
365
 
@@ -411,9 +439,11 @@ function extractResolversCore(
411
439
  allDiagnostics.push(...defineApiExtractionResult.diagnostics);
412
440
 
413
441
  const result = convertDefineApiToFields(defineApiExtractionResult.resolvers);
442
+ allDiagnostics.push(...result.diagnostics);
414
443
  return {
415
444
  queryFields: result.queryFields,
416
445
  mutationFields: result.mutationFields,
446
+ subscriptionFields: result.subscriptionFields,
417
447
  typeExtensions: result.typeExtensions,
418
448
  abstractTypeResolvers: defineApiExtractionResult.abstractTypeResolvers,
419
449
  diagnostics: collectDiagnostics(allDiagnostics),
@@ -514,11 +544,18 @@ function collectTypeNamesStep(ctx: PipelineContext): PipelineContext {
514
544
 
515
545
  const result = collectDeclaredTypeNames(ctx.program, ctx.sourceFiles);
516
546
 
547
+ const diagnostics = [...ctx.diagnostics, ...result.diagnostics];
548
+ const hasDiagnosticErrors = result.diagnostics.some(
549
+ (d) => d.severity === "error",
550
+ );
551
+
517
552
  return {
518
553
  ...ctx,
519
554
  knownTypeNames: result.typeNames,
520
555
  knownTypeSymbols: result.typeSymbols,
521
556
  underlyingSymbolToTypeName: result.underlyingSymbolToTypeName,
557
+ diagnostics,
558
+ aborted: hasDiagnosticErrors,
522
559
  };
523
560
  }
524
561
 
@@ -68,6 +68,10 @@ export interface MutationFieldDefinitions {
68
68
  readonly fields: ReadonlyArray<GraphQLFieldDefinition>;
69
69
  }
70
70
 
71
+ export interface SubscriptionFieldDefinitions {
72
+ readonly fields: ReadonlyArray<GraphQLFieldDefinition>;
73
+ }
74
+
71
75
  export interface TypeExtension {
72
76
  readonly targetTypeName: string;
73
77
  readonly fields: ReadonlyArray<GraphQLFieldDefinition>;
@@ -76,6 +80,7 @@ export interface TypeExtension {
76
80
  export interface ExtractResolversResult {
77
81
  readonly queryFields: QueryFieldDefinitions;
78
82
  readonly mutationFields: MutationFieldDefinitions;
83
+ readonly subscriptionFields: SubscriptionFieldDefinitions;
79
84
  readonly typeExtensions: ReadonlyArray<TypeExtension>;
80
85
  readonly abstractTypeResolvers: ReadonlyArray<AbstractResolverInfo>;
81
86
  readonly diagnostics: Diagnostics;