@gqlkit-ts/cli 0.4.1 → 0.5.1

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 (31) hide show
  1. package/README.md +3 -1
  2. package/dist/commands/gen.d.ts +11 -0
  3. package/dist/commands/gen.d.ts.map +1 -1
  4. package/dist/commands/gen.js +11 -2
  5. package/dist/commands/gen.js.map +1 -1
  6. package/dist/config-loader/loader.d.ts +1 -0
  7. package/dist/config-loader/loader.d.ts.map +1 -1
  8. package/dist/config-loader/loader.js +40 -2
  9. package/dist/config-loader/loader.js.map +1 -1
  10. package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
  11. package/dist/gen-orchestrator/orchestrator.js +4 -0
  12. package/dist/gen-orchestrator/orchestrator.js.map +1 -1
  13. package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
  14. package/dist/schema-generator/emitter/code-emitter.js +52 -16
  15. package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
  16. package/dist/type-extractor/extractor/type-name-collector.d.ts +6 -0
  17. package/dist/type-extractor/extractor/type-name-collector.d.ts.map +1 -1
  18. package/dist/type-extractor/extractor/type-name-collector.js +54 -18
  19. package/dist/type-extractor/extractor/type-name-collector.js.map +1 -1
  20. package/dist/type-extractor/types/diagnostics.d.ts +1 -1
  21. package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
  22. package/docs/configuration.md +24 -0
  23. package/docs/index.md +6 -6
  24. package/package.json +1 -1
  25. package/src/commands/gen.ts +12 -2
  26. package/src/config-loader/loader.ts +43 -2
  27. package/src/gen-orchestrator/orchestrator.ts +7 -0
  28. package/src/schema-generator/emitter/code-emitter.ts +86 -21
  29. package/src/type-extractor/extractor/type-name-collector.ts +80 -18
  30. package/src/type-extractor/types/diagnostics.ts +3 -1
  31. /package/docs/schema/{index.md → conventions.md} +0 -0
@@ -1,5 +1,12 @@
1
1
  import ts from "typescript";
2
+ import { getSourceLocationFromNode, } from "../../shared/source-location.js";
2
3
  import { isExported, resolveOriginalSymbol, } from "../../shared/typescript-utils.js";
4
+ /**
5
+ * Formats a source location as a human-readable string.
6
+ */
7
+ function formatLocation(location) {
8
+ return `${location.file}:${location.line}`;
9
+ }
3
10
  /**
4
11
  * Collects all declared type names from exported type declarations.
5
12
  *
@@ -15,7 +22,42 @@ export function collectDeclaredTypeNames(program, sourceFiles) {
15
22
  const typeNames = new Set();
16
23
  const typeSymbols = new Map();
17
24
  const underlyingSymbolToTypeName = new Map();
25
+ const diagnostics = [];
18
26
  const checker = program.getTypeChecker();
27
+ const typeLocations = new Map();
28
+ /**
29
+ * Registers a type name and checks for duplicates.
30
+ * Returns true if this is a new type, false if it's a duplicate.
31
+ */
32
+ function registerTypeName(name, location, symbol) {
33
+ const resolvedSymbol = symbol
34
+ ? resolveOriginalSymbol(symbol, checker)
35
+ : null;
36
+ const existing = typeLocations.get(name);
37
+ if (existing) {
38
+ // Check if both symbols resolve to the same underlying type
39
+ // (e.g., re-exports of the same type from different files)
40
+ if (resolvedSymbol &&
41
+ existing.symbol &&
42
+ resolvedSymbol === existing.symbol) {
43
+ // Same underlying type - not a true duplicate, skip silently
44
+ return false;
45
+ }
46
+ diagnostics.push({
47
+ code: "DUPLICATE_TYPE_EXPORT",
48
+ message: `Type '${name}' is exported from multiple files. First defined at ${formatLocation(existing.location)}.`,
49
+ severity: "error",
50
+ location,
51
+ });
52
+ return false;
53
+ }
54
+ typeLocations.set(name, { location, symbol: resolvedSymbol });
55
+ typeNames.add(name);
56
+ if (resolvedSymbol) {
57
+ typeSymbols.set(name, resolvedSymbol);
58
+ }
59
+ return true;
60
+ }
19
61
  for (const filePath of sourceFiles) {
20
62
  const sourceFile = program.getSourceFile(filePath);
21
63
  if (!sourceFile)
@@ -24,10 +66,10 @@ export function collectDeclaredTypeNames(program, sourceFiles) {
24
66
  // Direct type declarations
25
67
  if (ts.isTypeAliasDeclaration(node) && isExported(node)) {
26
68
  const name = node.name.getText(sourceFile);
27
- typeNames.add(name);
69
+ const location = getSourceLocationFromNode(node);
28
70
  const symbol = checker.getSymbolAtLocation(node.name);
29
- if (symbol) {
30
- typeSymbols.set(name, resolveOriginalSymbol(symbol, checker));
71
+ const isNew = registerTypeName(name, location, symbol);
72
+ if (isNew && symbol) {
31
73
  // For type aliases like `type User = ExternalUser;`,
32
74
  // also track the underlying type's symbol
33
75
  const type = checker.getTypeAtLocation(node.type);
@@ -39,19 +81,15 @@ export function collectDeclaredTypeNames(program, sourceFiles) {
39
81
  }
40
82
  if (ts.isInterfaceDeclaration(node) && isExported(node)) {
41
83
  const name = node.name.getText(sourceFile);
42
- typeNames.add(name);
84
+ const location = getSourceLocationFromNode(node);
43
85
  const symbol = checker.getSymbolAtLocation(node.name);
44
- if (symbol) {
45
- typeSymbols.set(name, resolveOriginalSymbol(symbol, checker));
46
- }
86
+ registerTypeName(name, location, symbol);
47
87
  }
48
88
  if (ts.isEnumDeclaration(node) && isExported(node)) {
49
89
  const name = node.name.getText(sourceFile);
50
- typeNames.add(name);
90
+ const location = getSourceLocationFromNode(node);
51
91
  const symbol = checker.getSymbolAtLocation(node.name);
52
- if (symbol) {
53
- typeSymbols.set(name, resolveOriginalSymbol(symbol, checker));
54
- }
92
+ registerTypeName(name, location, symbol);
55
93
  }
56
94
  // Re-exports: `export type { ... } from "..."` or `export type * from "..."`
57
95
  if (ts.isExportDeclaration(node) && node.isTypeOnly) {
@@ -61,11 +99,9 @@ export function collectDeclaredTypeNames(program, sourceFiles) {
61
99
  for (const element of node.exportClause.elements) {
62
100
  // Use the exported name (element.name), not the property name
63
101
  const name = element.name.getText(sourceFile);
64
- typeNames.add(name);
102
+ const location = getSourceLocationFromNode(element);
65
103
  const symbol = checker.getSymbolAtLocation(element.name);
66
- if (symbol) {
67
- typeSymbols.set(name, resolveOriginalSymbol(symbol, checker));
68
- }
104
+ registerTypeName(name, location, symbol);
69
105
  }
70
106
  }
71
107
  }
@@ -78,8 +114,8 @@ export function collectDeclaredTypeNames(program, sourceFiles) {
78
114
  const name = exp.getName();
79
115
  // Check if the export is a type (not a value)
80
116
  if (isTypeExport(exp)) {
81
- typeNames.add(name);
82
- typeSymbols.set(name, resolveOriginalSymbol(exp, checker));
117
+ const location = getSourceLocationFromNode(node);
118
+ registerTypeName(name, location, exp);
83
119
  }
84
120
  }
85
121
  }
@@ -87,7 +123,7 @@ export function collectDeclaredTypeNames(program, sourceFiles) {
87
123
  }
88
124
  });
89
125
  }
90
- return { typeNames, typeSymbols, underlyingSymbolToTypeName };
126
+ return { typeNames, typeSymbols, underlyingSymbolToTypeName, diagnostics };
91
127
  }
92
128
  /**
93
129
  * Checks if a symbol represents a type export (not a value export).
@@ -1 +1 @@
1
- {"version":3,"file":"type-name-collector.js","sourceRoot":"","sources":["../../../src/type-extractor/extractor/type-name-collector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"type-name-collector.js","sourceRoot":"","sources":["../../../src/type-extractor/extractor/type-name-collector.ts"],"names":[],"mappings":"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"}
@@ -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_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,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"}
@@ -7,6 +7,30 @@ description: Configure gqlkit via gqlkit.config.ts in your project root.
7
7
 
8
8
  gqlkit can be configured via `gqlkit.config.ts` in your project root.
9
9
 
10
+ ## CLI Options
11
+
12
+ The `gqlkit gen` command accepts the following options:
13
+
14
+ | Option | Short | Description |
15
+ |--------|-------|-------------|
16
+ | `--config <path>` | `-c` | Path to config file (default: `gqlkit.config.ts`) |
17
+ | `--cwd <path>` | | Working directory for code generation |
18
+
19
+ ### Using Multiple Config Files
20
+
21
+ You can use different config files for different GraphQL schemas:
22
+
23
+ ```sh
24
+ # Generate with default config (gqlkit.config.ts)
25
+ gqlkit gen
26
+
27
+ # Generate with a specific config file
28
+ gqlkit gen --config gqlkit.public.config.ts
29
+ gqlkit gen -c gqlkit.admin.config.ts
30
+ ```
31
+
32
+ This is useful when you need to generate multiple GraphQL schemas from the same project, such as separate public and internal APIs.
33
+
10
34
  ## Basic Configuration
11
35
 
12
36
  ```ts
package/docs/index.md CHANGED
@@ -18,15 +18,10 @@ gqlkit generates GraphQL schema and resolver maps from TypeScript types and func
18
18
 
19
19
  - [What is gqlkit?](./what-is-gqlkit.md): Just types and functions — write TypeScript, generate GraphQL.
20
20
  - [Getting Started](./getting-started.md): Install gqlkit and create your first GraphQL schema from TypeScript.
21
- - [Coding Agents](./coding-agents.md): Set up AI coding agents like Claude Code and Codex to understand gqlkit conventions. (skip if reading via `gqlkit-guide` skill)
22
-
23
- ## CLI
24
-
25
- - [Configuration](./configuration.md): Configure gqlkit via gqlkit.config.ts in your project root.
26
21
 
27
22
  ## Schema Definition
28
23
 
29
- - [Schema Definition](./schema.md): gqlkit generates GraphQL schema from your TypeScript types.
24
+ - [Schema Definition](./schema/conventions.md): gqlkit generates GraphQL schema from your TypeScript types.
30
25
  - [Defining Object Types](./schema/objects.md): Plain TypeScript type exports become GraphQL Object types.
31
26
  - [Defining Input Types](./schema/inputs.md): TypeScript types with Input suffix are treated as GraphQL input types.
32
27
  - [Defining Queries and Mutations](./schema/queries-mutations.md): Define Query and Mutation fields using the @gqlkit-ts/runtime API.
@@ -45,3 +40,8 @@ gqlkit generates GraphQL schema and resolver maps from TypeScript types and func
45
40
  - [Integration with Apollo Server](./integration/apollo.md): Use gqlkit with Apollo Server, a popular GraphQL server.
46
41
  - [Integration with Drizzle ORM](./integration/drizzle.md): Derive GraphQL types from Drizzle table definitions.
47
42
  - [Integration with Prisma](./integration/prisma.md): Derive GraphQL types from Prisma model types.
43
+
44
+ ## Guides
45
+
46
+ - [Configuration](./configuration.md): Configure gqlkit via gqlkit.config.ts in your project root.
47
+ - [Coding Agents](./coding-agents.md): Set up AI coding agents like Claude Code and Codex to understand gqlkit conventions. (skip if reading via `gqlkit-guide` skill)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gqlkit-ts/cli",
3
- "version": "0.4.1",
3
+ "version": "0.5.1",
4
4
  "description": "Just types and functions — write TypeScript, generate GraphQL.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,6 +12,7 @@ import { createProgressReporter } from "../gen-orchestrator/reporter/progress-re
12
12
 
13
13
  export interface RunGenCommandOptions {
14
14
  readonly cwd: string;
15
+ readonly configPath: string | null;
15
16
  }
16
17
 
17
18
  export interface RunGenCommandResult {
@@ -29,7 +30,10 @@ export async function runGenCommand(
29
30
  const progressReporter = createProgressReporter(writer);
30
31
  const diagnosticReporter = createDiagnosticReporter(writer);
31
32
 
32
- const configResult = await loadConfig({ cwd: options.cwd });
33
+ const configResult = await loadConfig({
34
+ cwd: options.cwd,
35
+ configPath: options.configPath,
36
+ });
33
37
 
34
38
  if (configResult.diagnostics.length > 0) {
35
39
  diagnosticReporter.reportDiagnostics(configResult.diagnostics);
@@ -130,10 +134,16 @@ export const genCommand = define({
130
134
  type: "string",
131
135
  description: "Working directory for code generation",
132
136
  },
137
+ config: {
138
+ type: "string",
139
+ short: "c",
140
+ description: "Path to config file",
141
+ },
133
142
  },
134
143
  run: async (ctx) => {
135
144
  const cwd = ctx.values.cwd ?? process.cwd();
136
- const result = await runGenCommand({ cwd });
145
+ const configPath = ctx.values.config ?? null;
146
+ const result = await runGenCommand({ cwd, configPath });
137
147
  if (result.exitCode !== 0) {
138
148
  process.exitCode = result.exitCode;
139
149
  }
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
- import { join } from "node:path";
2
+ import { isAbsolute, join } from "node:path";
3
3
  import { createJiti } from "jiti";
4
4
  import type { ImportExtension } from "../config/types.js";
5
5
  import type { Diagnostic } from "../type-extractor/types/index.js";
@@ -7,6 +7,7 @@ import { validateConfig } from "./validator.js";
7
7
 
8
8
  export interface LoadConfigOptions {
9
9
  readonly cwd: string;
10
+ readonly configPath: string | null;
10
11
  }
11
12
 
12
13
  export interface ResolvedScalarMapping {
@@ -86,9 +87,35 @@ const DEFAULT_RESOLVED_CONFIG: ResolvedConfig = {
86
87
  export async function loadConfig(
87
88
  options: LoadConfigOptions,
88
89
  ): Promise<LoadConfigResult> {
89
- const configPath = join(options.cwd, CONFIG_FILE_NAME);
90
+ const configPath = resolveConfigPath(options);
91
+
92
+ if (configPath === null) {
93
+ return {
94
+ config: DEFAULT_RESOLVED_CONFIG,
95
+ configPath: undefined,
96
+ diagnostics: [],
97
+ };
98
+ }
90
99
 
91
100
  if (!existsSync(configPath)) {
101
+ if (options.configPath !== null) {
102
+ return {
103
+ config: DEFAULT_RESOLVED_CONFIG,
104
+ configPath,
105
+ diagnostics: [
106
+ {
107
+ code: "CONFIG_FILE_NOT_FOUND",
108
+ message: `Config file not found: ${configPath}`,
109
+ severity: "error",
110
+ location: {
111
+ file: configPath,
112
+ line: 1,
113
+ column: 1,
114
+ },
115
+ },
116
+ ],
117
+ };
118
+ }
92
119
  return {
93
120
  config: DEFAULT_RESOLVED_CONFIG,
94
121
  configPath: undefined,
@@ -145,3 +172,17 @@ export async function loadConfig(
145
172
  };
146
173
  }
147
174
  }
175
+
176
+ function resolveConfigPath(options: LoadConfigOptions): string | null {
177
+ if (options.configPath !== null) {
178
+ if (isAbsolute(options.configPath)) {
179
+ return options.configPath;
180
+ }
181
+ return join(options.cwd, options.configPath);
182
+ }
183
+ const defaultPath = join(options.cwd, CONFIG_FILE_NAME);
184
+ if (existsSync(defaultPath)) {
185
+ return defaultPath;
186
+ }
187
+ return null;
188
+ }
@@ -514,11 +514,18 @@ function collectTypeNamesStep(ctx: PipelineContext): PipelineContext {
514
514
 
515
515
  const result = collectDeclaredTypeNames(ctx.program, ctx.sourceFiles);
516
516
 
517
+ const diagnostics = [...ctx.diagnostics, ...result.diagnostics];
518
+ const hasDiagnosticErrors = result.diagnostics.some(
519
+ (d) => d.severity === "error",
520
+ );
521
+
517
522
  return {
518
523
  ...ctx,
519
524
  knownTypeNames: result.typeNames,
520
525
  knownTypeSymbols: result.typeSymbols,
521
526
  underlyingSymbolToTypeName: result.underlyingSymbolToTypeName,
527
+ diagnostics,
528
+ aborted: hasDiagnosticErrors,
522
529
  };
523
530
  }
524
531
 
@@ -170,31 +170,80 @@ function buildScalarResolverEntries(
170
170
  );
171
171
  }
172
172
 
173
- function collectResolverImportsByFile(
173
+ /**
174
+ * Information about a resolver import with a unique alias.
175
+ */
176
+ interface ResolverImportInfo {
177
+ /** The original export name from the source file */
178
+ readonly originalName: string;
179
+ /** The unique local name using the pattern <Parent>$<field> */
180
+ readonly localName: string;
181
+ }
182
+
183
+ /**
184
+ * Creates a unique local name for a resolver import.
185
+ * Format: <ParentType>$<FieldName>
186
+ */
187
+ function makeResolverLocalName(parentType: string, fieldName: string): string {
188
+ return `${parentType}$${fieldName}`;
189
+ }
190
+
191
+ /**
192
+ * Collects resolver imports with unique aliases.
193
+ * Uses the pattern <Parent>$<field> for alias names.
194
+ *
195
+ * Note: Uniqueness assumes no duplicate resolver definitions for the same
196
+ * (parentType, fieldName) pair. Duplicate field definitions are caught
197
+ * by GraphQL schema validation at build time.
198
+ */
199
+ function collectResolverImports(
174
200
  resolverInfo: ResolverInfo,
175
- ): Map<string, Set<string>> {
176
- const importsByFile = new Map<string, Set<string>>();
201
+ ): Map<string, ResolverImportInfo[]> {
202
+ const importsByFile = new Map<string, ResolverImportInfo[]>();
203
+ // Track seen localNames per file to avoid duplicate import specifiers
204
+ const seenByFile = new Map<string, Set<string>>();
177
205
 
178
206
  for (const type of resolverInfo.types) {
179
207
  for (const field of type.fields) {
180
- const existing = importsByFile.get(field.sourceFile) ?? new Set<string>();
181
- existing.add(field.resolverValueName);
182
- importsByFile.set(field.sourceFile, existing);
208
+ const localName = makeResolverLocalName(type.typeName, field.fieldName);
209
+
210
+ const seen = seenByFile.get(field.sourceFile) ?? new Set<string>();
211
+ if (seen.has(localName)) {
212
+ continue;
213
+ }
214
+ seen.add(localName);
215
+ seenByFile.set(field.sourceFile, seen);
216
+
217
+ const infos = importsByFile.get(field.sourceFile) ?? [];
218
+ infos.push({ originalName: field.resolverValueName, localName });
219
+ importsByFile.set(field.sourceFile, infos);
183
220
  }
184
221
  }
185
222
 
186
223
  for (const abstractResolver of resolverInfo.abstractTypeResolvers) {
187
- const existing =
188
- importsByFile.get(abstractResolver.sourceFile) ?? new Set<string>();
189
- existing.add(abstractResolver.exportName);
190
- importsByFile.set(abstractResolver.sourceFile, existing);
224
+ const localName = makeResolverLocalName(
225
+ abstractResolver.typeName,
226
+ abstractResolver.resolverKey,
227
+ );
228
+
229
+ const seen =
230
+ seenByFile.get(abstractResolver.sourceFile) ?? new Set<string>();
231
+ if (seen.has(localName)) {
232
+ continue;
233
+ }
234
+ seen.add(localName);
235
+ seenByFile.set(abstractResolver.sourceFile, seen);
236
+
237
+ const infos = importsByFile.get(abstractResolver.sourceFile) ?? [];
238
+ infos.push({ originalName: abstractResolver.exportName, localName });
239
+ importsByFile.set(abstractResolver.sourceFile, infos);
191
240
  }
192
241
 
193
242
  return importsByFile;
194
243
  }
195
244
 
196
245
  function buildResolverImports(
197
- importsByFile: Map<string, Set<string>>,
246
+ importsByFile: Map<string, ResolverImportInfo[]>,
198
247
  outputDir: string,
199
248
  importExtension: ImportExtension,
200
249
  ): string[] {
@@ -202,17 +251,25 @@ function buildResolverImports(
202
251
  const sortedFiles = [...importsByFile.keys()].sort();
203
252
 
204
253
  for (const sourceFile of sortedFiles) {
205
- const valueNames = importsByFile.get(sourceFile) ?? new Set<string>();
254
+ const importInfos = importsByFile.get(sourceFile) ?? [];
206
255
  const importPath = computeRelativeImportPath(
207
256
  outputDir,
208
257
  sourceFile,
209
258
  importExtension,
210
259
  );
211
- const sortedValues = [...valueNames].sort();
212
260
 
213
- if (sortedValues.length > 0) {
261
+ // Sort by localName for consistent output
262
+ const sortedInfos = [...importInfos].sort((a, b) =>
263
+ a.localName.localeCompare(b.localName),
264
+ );
265
+
266
+ if (sortedInfos.length > 0) {
267
+ const importSpecifiers = sortedInfos.map(
268
+ (info) => `${info.originalName} as ${info.localName}`,
269
+ );
270
+
214
271
  imports.push(
215
- `import { ${sortedValues.join(", ")} } from "${importPath}";`,
272
+ `import { ${importSpecifiers.join(", ")} } from "${importPath}";`,
216
273
  );
217
274
  }
218
275
  }
@@ -223,7 +280,11 @@ function buildResolverImports(
223
280
  function buildAbstractOnlyTypeEntry(
224
281
  abstractResolver: AbstractTypeResolverInfo,
225
282
  ): string {
226
- return ` ${abstractResolver.typeName}: {\n ${abstractResolver.resolverKey}: ${abstractResolver.exportName},\n },`;
283
+ const localName = makeResolverLocalName(
284
+ abstractResolver.typeName,
285
+ abstractResolver.resolverKey,
286
+ );
287
+ return ` ${abstractResolver.typeName}: {\n ${abstractResolver.resolverKey}: ${localName},\n },`;
227
288
  }
228
289
 
229
290
  function buildNumericEnumResolver(enumInfo: NumericEnumInfo): string {
@@ -261,19 +322,23 @@ function buildTypeResolverEntry(
261
322
  const entries: string[] = [];
262
323
 
263
324
  for (const field of type.fields) {
325
+ const localName = makeResolverLocalName(type.typeName, field.fieldName);
326
+
264
327
  if (field.isDirectExport) {
265
- entries.push(` ${field.fieldName}: ${field.resolverValueName},`);
328
+ entries.push(` ${field.fieldName}: ${localName},`);
266
329
  } else {
267
330
  entries.push(
268
- ` ${field.fieldName}: ${field.resolverValueName}.${field.fieldName},`,
331
+ ` ${field.fieldName}: ${localName}.${field.fieldName},`,
269
332
  );
270
333
  }
271
334
  }
272
335
 
273
336
  if (abstractResolverForType !== null) {
274
- entries.push(
275
- ` ${abstractResolverForType.resolverKey}: ${abstractResolverForType.exportName},`,
337
+ const localName = makeResolverLocalName(
338
+ abstractResolverForType.typeName,
339
+ abstractResolverForType.resolverKey,
276
340
  );
341
+ entries.push(` ${abstractResolverForType.resolverKey}: ${localName},`);
277
342
  }
278
343
 
279
344
  return ` ${type.typeName}: {\n${entries.join("\n")}\n },`;
@@ -379,7 +444,7 @@ export function emitResolversCode(params: EmitResolversCodeParams): string {
379
444
  imports.push('import { GraphQLScalarType } from "graphql";');
380
445
  }
381
446
 
382
- const importsByFile = collectResolverImportsByFile(resolverInfo);
447
+ const importsByFile = collectResolverImports(resolverInfo);
383
448
  imports.push(
384
449
  ...buildResolverImports(importsByFile, outputDir, importExtension),
385
450
  );