@xyd-js/gql 0.1.0-xyd.9 → 0.1.0-xyd.96

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 (89) hide show
  1. package/CHANGELOG.md +810 -0
  2. package/LICENSE +21 -0
  3. package/TODO.md +8 -0
  4. package/__fixtures__/-1.opendocs.docs-nested/input.graphql +66 -0
  5. package/__fixtures__/-1.opendocs.docs-nested/output.json +554 -0
  6. package/__fixtures__/-1.opendocs.flat/input.graphql +19 -0
  7. package/__fixtures__/-1.opendocs.flat/output.json +243 -0
  8. package/__fixtures__/-1.opendocs.scopes/input.graphql +33 -0
  9. package/__fixtures__/-1.opendocs.scopes/output.json +378 -0
  10. package/__fixtures__/-1.opendocs.sidebar/input.graphql +44 -0
  11. package/__fixtures__/-1.opendocs.sort/input.graphql +92 -0
  12. package/__fixtures__/-1.opendocs.sort/output.json +1078 -0
  13. package/__fixtures__/-1.opendocs.sort+group/input.graphql +111 -0
  14. package/__fixtures__/-1.opendocs.sort+group/output.json +1114 -0
  15. package/__fixtures__/-1.opendocs.sort+group+path/input.graphql +118 -0
  16. package/__fixtures__/-1.opendocs.sort+group+path/output.json +1114 -0
  17. package/__fixtures__/-2.complex.github/input.graphql +69424 -0
  18. package/__fixtures__/-2.complex.github/output.json +269874 -0
  19. package/__fixtures__/-2.complex.livesession/input.graphql +23 -0
  20. package/__fixtures__/-2.complex.livesession/output.json +302 -0
  21. package/__fixtures__/-2.complex.monday/input.graphql +6089 -0
  22. package/__fixtures__/-2.complex.monday/output.json +1 -0
  23. package/__fixtures__/-3.array-non-null-return/input.graphql +9 -0
  24. package/__fixtures__/-3.array-non-null-return/output.json +151 -0
  25. package/__fixtures__/1.basic/input.graphql +118 -0
  26. package/__fixtures__/1.basic/output.json +630 -0
  27. package/__fixtures__/2.circular/input.graphql +17 -0
  28. package/__fixtures__/2.circular/output.json +248 -0
  29. package/__fixtures__/3.opendocs/input.graphql +27 -0
  30. package/__fixtures__/3.opendocs/output.json +338 -0
  31. package/__fixtures__/4.union/input.graphql +19 -0
  32. package/__fixtures__/4.union/output.json +344 -0
  33. package/__fixtures__/5.flat/input.graphql +27 -0
  34. package/__fixtures__/5.flat/output.json +383 -0
  35. package/__fixtures__/6.default-values/input.graphql +47 -0
  36. package/__fixtures__/6.default-values/output.json +655 -0
  37. package/__fixtures__/7.type-args/input.graphql +19 -0
  38. package/__fixtures__/7.type-args/output.json +301 -0
  39. package/__fixtures__/8.default-sort/input.graphql +60 -0
  40. package/__fixtures__/8.default-sort/output.json +1078 -0
  41. package/__tests__/gqlSchemaToReferences.test.ts +109 -0
  42. package/__tests__/utils.ts +45 -0
  43. package/declarations.d.ts +4 -0
  44. package/dist/index.d.ts +17 -1
  45. package/dist/index.js +1334 -19871
  46. package/dist/index.js.map +1 -1
  47. package/dist/opendocs.graphql +56 -0
  48. package/package.json +7 -9
  49. package/src/context.ts +17 -0
  50. package/src/converters/gql-arg.ts +51 -0
  51. package/src/converters/gql-enum.ts +27 -0
  52. package/src/converters/gql-field.ts +164 -0
  53. package/src/converters/gql-input.ts +34 -0
  54. package/src/converters/gql-interface.ts +35 -0
  55. package/src/converters/gql-mutation.ts +36 -0
  56. package/src/converters/gql-object.ts +83 -0
  57. package/src/converters/gql-operation.ts +128 -0
  58. package/src/converters/gql-query.ts +36 -0
  59. package/src/converters/gql-sample.ts +159 -0
  60. package/src/converters/gql-scalar.ts +16 -0
  61. package/src/converters/gql-subscription.ts +36 -0
  62. package/src/converters/gql-types.ts +195 -0
  63. package/src/converters/gql-union.ts +40 -0
  64. package/src/gql-core.ts +362 -0
  65. package/src/opendocs.graphql +56 -0
  66. package/src/opendocs.ts +253 -0
  67. package/src/schema.ts +253 -67
  68. package/src/types.ts +103 -0
  69. package/src/utils.ts +21 -96
  70. package/tsconfig.json +1 -1
  71. package/tsup.config.ts +15 -1
  72. package/vitest.config.ts +15 -1
  73. package/examples/basic/index.ts +0 -12
  74. package/examples/basic/schema.graphqls +0 -89
  75. package/examples/basic/todo-app.graphqls +0 -184
  76. package/examples/graphql-types/graphql-types.0.basic.graphqls +0 -28
  77. package/examples/nested/nested-arg.0.not-required.graphqls +0 -8
  78. package/examples/nested/nested-arg.0.required.graphqls +0 -8
  79. package/examples/nested/nested-arg.1.deep.graphqls +0 -12
  80. package/src/hydration/README.md +0 -1
  81. package/src/hydration/gql-arg.ts +0 -53
  82. package/src/hydration/gql-field.ts +0 -206
  83. package/src/hydration/gql-input.ts +0 -67
  84. package/src/hydration/gql-object.ts +0 -35
  85. package/src/hydration/gql-types.ts +0 -50
  86. package/src/samples/index.ts +0 -95
  87. package/test/graphql-types.0.test.ts +0 -125
  88. package/test/nested-arg.0.test.ts +0 -208
  89. package/test/nested-arg.1.test.ts +0 -19
package/src/schema.ts CHANGED
@@ -1,107 +1,293 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import {fileURLToPath} from "node:url";
4
+
1
5
  import {
2
- GraphQLInputObjectType,
3
- GraphQLObjectType,
4
- GraphQLEnumType,
5
- isSpecifiedScalarType,
6
- isIntrospectionType
6
+ buildSchema,
7
+ DirectiveNode,
8
+ print,
9
+ visit,
10
+ parse,
11
+ ObjectTypeExtensionNode,
12
+ GraphQLSchema,
13
+ StringValueNode
7
14
  } from "graphql";
8
- import {OperationTypeNode} from "graphql/language/ast";
9
-
10
- import {getDocumentLoaders, loadSchema} from "@graphql-markdown/graphql";
11
- import {GraphQLScalarType} from "@graphql-markdown/types";
15
+ import {mergeTypeDefs} from '@graphql-tools/merge';
12
16
 
13
17
  import type {Reference} from "@xyd-js/uniform"
14
- import {ReferenceType} from "@xyd-js/uniform"
15
- import {gqlInputToUniformRef} from "./hydration/gql-input";
16
- import {gqlEnumToUniformRef, gqlScalarToUniformRef} from "./hydration/gql-types";
17
- import {gqlObjectToUniformRef} from "./hydration/gql-object";
18
- import {gqlOperationsToUniformRef} from "./utils";
18
+ import {ReferenceType} from "@xyd-js/uniform";
19
+
20
+ import type {
21
+ GQLSchemaToReferencesOptions,
22
+ OpenDocsSortConfig,
23
+ FieldMetadata,
24
+ GQLSchemaMetadata,
25
+ SortItem
26
+ } from "./types";
27
+ import {DEFAULT_SORT_ORDER} from "./types";
28
+ import {graphqlTypesToUniformReferences} from "./converters/gql-types";
29
+ import {graphqlQueriesToUniformReferences} from "./converters/gql-query";
30
+ import {graphqlMutationsToUniformReferences} from "./converters/gql-mutation";
31
+ import {graphqlSubscriptionsToUniformReferences} from "./converters/gql-subscription";
32
+ import {OPEN_DOCS_DIRECTIVE_NAME, OPEN_DOCS_SCHEMA_DIRECTIVE_NAME, openDocsExtensionsToOptions} from "./opendocs";
33
+ import openDocsSchemaRaw from './opendocs.graphql'
19
34
 
20
35
  // TODO: support multi graphql files
21
- // TODO: !!! CIRCULAR_DEPENDENCY !!!
22
36
  // TODO: sort by tag??
23
-
24
37
  export async function gqlSchemaToReferences(
25
- schemaLocation: string
38
+ schemaLocation: string | string[],
39
+ options?: GQLSchemaToReferencesOptions
26
40
  ): Promise<Reference[]> {
27
- const loadersList = {
28
- ["GraphQLFileLoader"]: "@graphql-tools/graphql-file-loader",
41
+ // 1. Convert schemaLocation to array
42
+ const schemaLocations = Array.isArray(schemaLocation) ? schemaLocation : [schemaLocation];
43
+
44
+ // Add opendocs.graphql to schema locations (first)
45
+ schemaLocations.unshift(openDocsSchemaRaw);
46
+
47
+ // 2. Read all schema contents
48
+ const schemaContents = await Promise.all(schemaLocations.map(async location => {
49
+ if (location.startsWith('http://') || location.startsWith('https://')) {
50
+ const response = await fetch(location);
51
+ if (!response.ok) {
52
+ throw new Error(`Failed to fetch schema from URL: ${location}`);
53
+ }
54
+ return response.text();
55
+ }
56
+ if (fs.existsSync(location)) {
57
+ return fs.readFileSync(location, 'utf-8');
58
+ }
59
+ return location;
60
+ }));
61
+
62
+ // 3. Merge all schema contents
63
+ const mergedTypeDefs = mergeTypeDefs(schemaContents);
64
+ const schemaString = print(mergedTypeDefs);
65
+
66
+ // 4. Build the schema
67
+ const schema = buildSchema(schemaString, {
68
+ assumeValid: true
69
+ });
70
+ if (schemaContents.length > 2) {
71
+ console.warn(`Warning: More than 2 schema files provided - no all featues will be supported!`);
72
+ }
73
+
74
+ docDirectiveChain(schemaContents[1], schema);
75
+ // TODO: fix schemaContents[1]
76
+
77
+ if (!options) {
78
+ options = {}
29
79
  }
30
- const loaders = await getDocumentLoaders(loadersList);
31
80
 
32
- // @ts-ignore TODO: but ts works in @graphql-markdown/core
33
- const schema = await loadSchema(schemaLocation as string, loaders);
81
+ if (!options.hasOwnProperty('flat')) {
82
+ options.flat = true; // Default flat is true
83
+ }
84
+ options = {
85
+ ...options,
86
+ ...openDocsExtensionsToOptions(schema)
87
+ }
88
+
89
+ // 5. Generate uniform references from the schema
90
+ const references = [
91
+ // types
92
+ ...graphqlTypesToUniformReferences(schema, options),
93
+
94
+ // queries
95
+ ...graphqlQueriesToUniformReferences(schema, options),
96
+
97
+ // mutations
98
+ ...graphqlMutationsToUniformReferences(schema, options),
99
+
100
+ // subscriptions
101
+ ...graphqlSubscriptionsToUniformReferences(schema, options),
102
+ ]
103
+
104
+ // Sort references using provided sort config or defaults
105
+ const sortConfig = options.sort ?? {sort: DEFAULT_SORT_ORDER};
106
+ references.sort((a, b) => {
107
+ const aOrder = getSortOrder(a, sortConfig);
108
+ const bOrder = getSortOrder(b, sortConfig);
109
+ return aOrder - bOrder;
110
+ });
111
+
112
+ if (options.route) {
113
+ // TODO: types or better solution!!!
114
+ // @ts-ignore
115
+ references.__UNSAFE_route = () => options.route
116
+ }
117
+ return references
118
+ }
119
+
120
+ function getSortOrder(reference: Reference, sortConfig: OpenDocsSortConfig): number {
121
+ const sortItems = sortConfig.sort ?? DEFAULT_SORT_ORDER;
122
+ const sortStacks = sortConfig.sortStack ?? [];
123
+ const referenceGroups = getReferenceGroups(reference);
124
+
125
+ // First, find which primary group this reference belongs to
126
+ for (let groupIndex = 0; groupIndex < sortItems.length; groupIndex++) {
127
+ const sortItem = sortItems[groupIndex];
34
128
 
35
- const references: Reference[] = []
129
+ // Check if this reference matches the primary group
130
+ if (matchesPrimaryGroup(reference, sortItem)) {
131
+ // Determine which stack to use (default to 0 if not specified)
132
+ const stackIndex = sortItem.stack !== undefined ? sortItem.stack : 0;
36
133
 
37
- const queries = schema.getRootType(OperationTypeNode.QUERY)
38
- const queryFields = queries?.getFields?.()
134
+ // Calculate position within this group using the stack
135
+ const positionInGroup = calculatePositionInGroup(reference, stackIndex, sortStacks);
39
136
 
40
- if (queryFields) {
41
- references.push(...gqlOperationsToUniformRef(
42
- ReferenceType.GRAPHQL_QUERY,
43
- queryFields
44
- ))
137
+ const result = (groupIndex * 1000) + positionInGroup;
138
+
139
+ // Return order: groupIndex * 1000 + positionInGroup
140
+ // This ensures all items in group 0 come before all items in group 1, etc.
141
+ return result;
142
+ }
45
143
  }
46
144
 
47
- const mutations = schema.getRootType(OperationTypeNode.MUTATION)
48
- const mutationFields = mutations?.getFields?.()
145
+ return Number.MAX_SAFE_INTEGER;
146
+ }
49
147
 
50
- if (mutationFields) {
51
- references.push(...gqlOperationsToUniformRef(
52
- ReferenceType.GRAPHQL_MUTATION,
53
- mutationFields
54
- ))
148
+ function matchesPrimaryGroup(reference: Reference, sortItem: SortItem): boolean {
149
+ // Check node match first
150
+ if (sortItem.node) {
151
+ const context = reference.context as any;
152
+ if (context?.graphqlTypeShort === sortItem.node) {
153
+ return true;
154
+ }
155
+ // If node is specified but doesn't match, return false (don't fall through)
156
+ return false;
55
157
  }
56
158
 
57
- const typeMap = schema.getTypeMap();
159
+ // Check group match
160
+ if (sortItem.group && sortItem.group.length > 0) {
161
+ const referenceGroups = getReferenceGroups(reference);
162
+ const match = sortItem.group.some(group => referenceGroups.includes(group));
163
+ return match;
164
+ }
58
165
 
59
- for (const gqlType of Object.values(typeMap)) {
60
- const builtInType = isSpecifiedScalarType(gqlType) ||
61
- isIntrospectionType(gqlType) ||
62
- gqlType.name === "Mutation"
166
+ return true;
167
+ }
168
+
169
+ function calculatePositionInGroup(reference: Reference, stackIndex: number, sortStacks: string[][]): number {
170
+ if (stackIndex < 0 || stackIndex >= sortStacks.length) {
171
+ return 0;
172
+ }
63
173
 
64
- if (builtInType) {
65
- continue;
174
+ const stackGroups = sortStacks[stackIndex];
175
+ const referenceGroups = getReferenceGroups(reference);
176
+
177
+ // Find the position of the reference's type in the stack
178
+ for (let i = 0; i < stackGroups.length; i++) {
179
+ const stackGroup = stackGroups[i];
180
+ if (referenceGroups.includes(stackGroup)) {
181
+ return i;
66
182
  }
183
+ }
184
+
185
+ return 999; // If not found in stack, put at the end of the group
186
+ }
67
187
 
68
- switch (gqlType.constructor.name) {
69
- case 'GraphQLObjectType': {
70
- const type = gqlType as GraphQLObjectType;
71
188
 
72
- references.push(gqlObjectToUniformRef(type))
189
+ function getReferenceGroups(reference: Reference): string[] {
190
+ // Extract groups from reference context
191
+ const context = reference.context as any;
192
+ if (context?.group && Array.isArray(context.group)) {
193
+ return context.group;
194
+ }
73
195
 
74
- break
196
+ // Fallback: try to get groups from metadata if available
197
+ if (reference.__UNSAFE_selector) {
198
+ try {
199
+ const selector = reference.__UNSAFE_selector;
200
+ const metadata = selector("[metadata]");
201
+ if (metadata?.groups) {
202
+ return metadata.groups;
75
203
  }
204
+ } catch (e) {
205
+ // Ignore errors from selector
206
+ }
207
+ }
208
+
209
+ return [];
210
+ }
76
211
 
77
- case 'GraphQLInputObjectType': {
78
- const type = gqlType as GraphQLInputObjectType;
212
+ function docDirectiveChain(
213
+ rawSDL: string,
214
+ schema: GraphQLSchema
215
+ ) {
216
+ const ast = parse(rawSDL);
217
+ const metadata: GQLSchemaMetadata = {
218
+ fields: new Map<string, FieldMetadata>()
219
+ };
79
220
 
80
- references.push(gqlInputToUniformRef(type))
81
- break
221
+ // First, find root groups from @docs directive
222
+ visit(ast, {
223
+ SchemaExtension(node) {
224
+ for (const directive of node.directives || []) {
225
+ if (directive.name.value === OPEN_DOCS_SCHEMA_DIRECTIVE_NAME) {
226
+ const groupArg = directive.arguments?.find(arg => arg.name.value === 'group');
227
+ if (groupArg?.value.kind === 'ListValue') {
228
+ metadata.rootGroups = groupArg.value.values
229
+ .filter((v): v is StringValueNode => v.kind === 'StringValue')
230
+ .map(v => v.value);
231
+ }
232
+ }
82
233
  }
234
+ }
235
+ });
83
236
 
84
- case 'GraphQLEnumType': {
85
- const type = gqlType as GraphQLEnumType;
237
+ // Then process type extensions and fields
238
+ visit(ast, {
239
+ ObjectTypeExtension(node: ObjectTypeExtensionNode) {
240
+ const validNodeTypes = ['Query', 'Mutation', 'Subscription'];
241
+ if (!validNodeTypes.includes(node.name.value)) return;
86
242
 
87
- references.push(gqlEnumToUniformRef(type))
243
+ const typeLevelDoc = node.directives?.find(d => d.name.value === OPEN_DOCS_DIRECTIVE_NAME);
244
+ const typeLevelDocArgs = typeLevelDoc ? extractDocArgs(typeLevelDoc) : {};
88
245
 
89
- break
90
- }
246
+ for (const field of node.fields ?? []) {
247
+ const fieldName = field.name.value;
91
248
 
92
- case 'GraphQLScalarType': {
93
- const type = gqlType as GraphQLScalarType
249
+ const fieldDoc = field.directives?.find(d => d.name.value === OPEN_DOCS_DIRECTIVE_NAME);
250
+ const fieldDocArgs = fieldDoc ? extractDocArgs(fieldDoc) : {};
94
251
 
95
- references.push(gqlScalarToUniformRef(type))
252
+ // Merge paths: if both type and field have paths, join them
253
+ let path = fieldDocArgs.path;
254
+ if (typeLevelDocArgs.path && fieldDocArgs.path) {
255
+ path = `${typeLevelDocArgs.path}/${fieldDocArgs.path}`;
256
+ } else if (typeLevelDocArgs.path) {
257
+ path = typeLevelDocArgs.path;
258
+ }
96
259
 
97
- break
98
- }
260
+ if (!fieldDocArgs.path && path) {
261
+ path += "/" + fieldName
262
+ }
263
+
264
+ // Merge groups: combine root groups with type/field groups
265
+ const groups = fieldDocArgs.groups ?? typeLevelDocArgs.groups ?? [];
99
266
 
100
- default: {
101
- console.debug(`Unsupported type: ${gqlType.constructor.name}`)
267
+ const effectiveDoc: FieldMetadata = {
268
+ groups,
269
+ path
270
+ };
271
+
272
+ metadata.fields.set(`${node.name.value}.${fieldName}`, effectiveDoc);
102
273
  }
103
274
  }
104
- }
275
+ });
105
276
 
106
- return references
277
+ // Attach metadata to schema
278
+ (schema as any).__metadata = metadata;
107
279
  }
280
+
281
+ function extractDocArgs(directive: DirectiveNode): FieldMetadata {
282
+ const info: FieldMetadata = {};
283
+ for (const arg of directive.arguments ?? []) {
284
+ if (arg.name.value === 'group' && arg.value.kind === 'ListValue') {
285
+ info.groups = arg.value.values
286
+ .filter((v): v is StringValueNode => v.kind === 'StringValue')
287
+ .map(v => v.value);
288
+ } else if (arg.name.value === 'path' && arg.value.kind === 'StringValue') {
289
+ info.path = arg.value.value;
290
+ }
291
+ }
292
+ return info;
293
+ }
package/src/types.ts ADDED
@@ -0,0 +1,103 @@
1
+ import type {GraphQLInputObjectType, GraphQLInterfaceType, GraphQLNamedType, GraphQLObjectType} from "graphql";
2
+ import {GraphQLField, OperationTypeNode} from "graphql";
3
+
4
+ import type {DefinitionProperty} from "@xyd-js/uniform";
5
+
6
+ // New sorting types based on the documentation
7
+ export interface SortItem {
8
+ node?: string;
9
+ group?: string[];
10
+ stack?: number;
11
+ }
12
+
13
+ export interface SortStack {
14
+ sortStack?: string[][];
15
+ sort?: SortItem[];
16
+ }
17
+
18
+ export interface OpenDocsSortConfig {
19
+ sortStack?: string[][];
20
+ sort?: SortItem[];
21
+ }
22
+
23
+ export const DEFAULT_SORT_ORDER: SortItem[] = [
24
+ { node: "query" },
25
+ { node: "mutation" },
26
+ { node: "subscription" },
27
+ { node: "object" },
28
+ { node: "interface" },
29
+ { node: "union" },
30
+ { node: "input" },
31
+ { node: "enum" },
32
+ { node: "scalar" },
33
+ ];
34
+
35
+ export interface GQLSchemaToReferencesOptions {
36
+ // TODO: support line ranged in the future?
37
+ regions?: string[] // TODO: BETTER API - UNIFY FOR REST API / GRAPHQL ETC
38
+
39
+ flat?: boolean;
40
+ sort?: OpenDocsSortConfig;
41
+ route?: string
42
+ }
43
+
44
+ export type NestedGraphqlType = {
45
+ __definitionProperties?: DefinitionProperty[];
46
+ } & (GraphQLObjectType | GraphQLInputObjectType | GraphQLInterfaceType)
47
+
48
+ // needed cuz GraphQLField does not have operation info?
49
+ export class GQLOperation implements GraphQLField<any, any> {
50
+ public _operationType!: OperationTypeNode
51
+ field: GraphQLField<any, any>;
52
+
53
+ constructor(field: GraphQLField<any, any>) {
54
+ this.field = field;
55
+ }
56
+
57
+ get name() {
58
+ return this.field.name;
59
+ }
60
+
61
+ get description() {
62
+ return this.field.description;
63
+ }
64
+
65
+ get type() {
66
+ return this.field.type;
67
+ }
68
+
69
+ get args() {
70
+ return this.field.args;
71
+ }
72
+
73
+ get deprecationReason() {
74
+ return this.field.deprecationReason;
75
+ }
76
+
77
+ get extensions() {
78
+ return this.field.extensions;
79
+ }
80
+
81
+ get astNode() {
82
+ return this.field.astNode;
83
+ }
84
+
85
+ set __operationType(operationType: OperationTypeNode) {
86
+ this._operationType = operationType;
87
+ }
88
+ }
89
+
90
+ export interface GQLTypeInfo {
91
+ typeFlat?: GraphQLNamedType
92
+ }
93
+
94
+ export interface FieldMetadata {
95
+ path?: string;
96
+ groups?: string[];
97
+ }
98
+
99
+ export interface GQLSchemaMetadata {
100
+ fields: Map<string, FieldMetadata>;
101
+ rootGroups?: string[];
102
+ }
103
+
package/src/utils.ts CHANGED
@@ -1,100 +1,25 @@
1
- import {GraphQLFieldMap} from "graphql/type";
2
- import {
3
- Reference,
4
- ReferenceCategory,
5
- ReferenceType,
6
- ExampleGroup,
7
- Definition,
8
- Example,
9
- } from "@xyd-js/uniform";
10
-
11
- import {gqlArgToUniformDefinitionProperty} from "./hydration/gql-arg";
12
- import {gqlFieldToUniformDefinitionProperty} from "./hydration/gql-field";
13
- import {simpleGraphqlExample} from "./samples";
14
-
15
- // gqlOperationsToUniformRef is a helper function to create a list of xyd reference for a GraphQL query or mutation.
16
- export function gqlOperationsToUniformRef(
17
- operationType: ReferenceType.GRAPHQL_MUTATION | ReferenceType.GRAPHQL_QUERY,
18
- fieldsMap: GraphQLFieldMap<any, any>
19
- ) {
20
- const references: Reference[] = []
21
-
22
- for (const [operationName, operationField] of Object.entries(fieldsMap)) {
23
- const definitions: Definition[] = []
24
-
25
- const args = gqlArgToUniformDefinitionProperty(operationField.args)
26
- const returns = gqlFieldToUniformDefinitionProperty(operationName, operationField)
27
- const returnProperties = returns.properties || []
28
-
29
- definitions.push({
30
- title: "Arguments",
31
- properties: args,
32
- })
33
- definitions.push({
34
- title: "Returns",
35
- properties: returnProperties
36
- })
37
-
38
- const exampleQuery = simpleGraphqlExample(
39
- operationType,
40
- operationName,
41
- args,
42
- returnProperties
43
- )
44
- const examples: Example[] = [
45
- {
46
- codeblock: {
47
- tabs: [
48
- {
49
- title: "graphql",
50
- language: "graphql",
51
- code: exampleQuery,
52
- }
53
- ]
54
- }
55
- }
56
- ]
57
-
58
- const exampleGroup = {
59
- description: "Example request",
60
- examples,
61
- }
62
-
63
- let description = operationField.description || ""
64
-
65
- references.push(graphqlReference(
66
- operationType,
67
- operationName,
68
- operationName,
69
- description,
70
- [exampleGroup],
71
- definitions,
72
- ))
1
+ /**
2
+ * Helper function to filter fields based on region patterns
3
+ * @param fields - The fields to filter
4
+ * @param prefix - The prefix for the region key (e.g., "Query" or "Mutation")
5
+ * @param regions - The regions to filter by
6
+ * @returns Filtered fields object
7
+ */
8
+ export function filterFieldsByRegions<T>(
9
+ fields: Record<string, T>,
10
+ prefix: string,
11
+ regions?: string[]
12
+ ): Record<string, T> {
13
+ if (!regions || regions.length === 0) {
14
+ return fields;
73
15
  }
74
16
 
75
- return references
76
- }
77
-
78
- // graphqlReference is a helper function to create a Reference object for a GraphQL query or mutation.
79
- function graphqlReference(
80
- operationType: ReferenceType.GRAPHQL_QUERY | ReferenceType.GRAPHQL_MUTATION,
81
- title: string,
82
- canonical: string,
83
- description: string,
84
- examples: ExampleGroup[],
85
- definitions: Definition[],
86
- ): Reference {
87
- return {
88
- title,
89
- canonical,
90
- description,
91
-
92
- category: ReferenceCategory.GRAPHQL,
93
- type: operationType,
94
-
95
- examples: {
96
- groups: examples,
97
- },
98
- definitions,
17
+ const filteredFields: Record<string, T> = {};
18
+ for (const [fieldName, field] of Object.entries(fields)) {
19
+ const regionKey = `${prefix}.${fieldName}`;
20
+ if (regions.some(region => region === regionKey)) {
21
+ filteredFields[fieldName] = field;
22
+ }
99
23
  }
24
+ return filteredFields;
100
25
  }
package/tsconfig.json CHANGED
@@ -13,6 +13,6 @@
13
13
  "incremental": true,
14
14
  "tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
15
15
  },
16
- "include": ["examples/basic-example/**/*.ts", "src/**/*.ts"],
16
+ "include": ["examples/basic-example/**/*.ts", "src/**/*.ts", "declarations.d.ts"],
17
17
  "exclude": ["node_modules", "dist"]
18
18
  }
package/tsup.config.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { copyFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
1
4
  import {defineConfig} from 'tsup';
2
5
 
3
6
  export default defineConfig({
@@ -14,6 +17,17 @@ export default defineConfig({
14
17
  esbuildOptions: (options) => {
15
18
  options.platform = 'node'; // Ensure the platform is set to Node.js
16
19
  options.external = ['node:fs/promises']; // Mark 'node:fs/promises' as external
17
- options.loader = {'.js': 'jsx'}; // Ensure proper handling of .js files
20
+ options.loader = {
21
+ '.js': 'jsx', // Ensure proper handling of .js files
22
+ '.graphql': 'text' // Load .graphql files as text
23
+ };
18
24
  },
25
+ onSuccess: async () => {
26
+ // Copy opendocs.graphql to dist
27
+ copyFileSync(
28
+ join('src', 'opendocs.graphql'),
29
+ join('dist', 'opendocs.graphql')
30
+ );
31
+ return Promise.resolve();
32
+ }
19
33
  });
package/vitest.config.ts CHANGED
@@ -2,6 +2,20 @@ import { defineConfig } from 'vitest/config'
2
2
 
3
3
  export default defineConfig({
4
4
  test: {
5
- // ...
5
+ environment: 'node',
6
+ globals: true,
6
7
  },
8
+ plugins: [
9
+ {
10
+ name: 'graphql-raw',
11
+ transform(code, id) {
12
+ if (id.endsWith('.graphql')) {
13
+ return {
14
+ code: `export default ${JSON.stringify(code)};`,
15
+ map: null
16
+ }
17
+ }
18
+ }
19
+ }
20
+ ]
7
21
  })
@@ -1,12 +0,0 @@
1
- import path from 'path';
2
-
3
- import {gqlSchemaToReferences} from "../../src";
4
-
5
- // TODO: support multi graphql files
6
- // TODO: !!! CIRCULAR_DEPENDENCY !!!
7
- // TODO: sort by tag??
8
- (async () => {
9
- const schemaLocation = path.join(process.cwd(), "./examples/basic/todo-app.graphqls")
10
-
11
- const references = await gqlSchemaToReferences(schemaLocation)
12
- })()