@graphcommerce/graphql-codegen-markdown-docs 6.0.0-canary.20
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/MarkdownVisitor.js +192 -0
- package/dist/config.js +2 -0
- package/dist/graphql.js +22 -0
- package/dist/index.js +55 -0
- package/package.json +41 -0
- package/src/config.ts +15 -0
- package/src/graphql.ts +28 -0
- package/src/index.ts +64 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MarkdownVisitor = void 0;
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
5
|
+
/* eslint-disable prefer-template */
|
|
6
|
+
const typescript_1 = require("@graphql-codegen/typescript");
|
|
7
|
+
const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common");
|
|
8
|
+
const graphql_1 = require("./graphql");
|
|
9
|
+
const importZod = `import { z } from 'zod'`;
|
|
10
|
+
const anySchema = `definedNonNullAnySchema`;
|
|
11
|
+
const MarkdownVisitor = (schema, config) => {
|
|
12
|
+
const tsVisitor = new typescript_1.TsVisitor(schema, config);
|
|
13
|
+
const importTypes = [];
|
|
14
|
+
return {
|
|
15
|
+
buildImports: () =>
|
|
16
|
+
// if (config.importFrom && importTypes.length > 0) {
|
|
17
|
+
// return [importZod, `import { ${importTypes.join(', ')} } from '${config.importFrom}'`]
|
|
18
|
+
// }
|
|
19
|
+
[importZod],
|
|
20
|
+
initialEmit: () => '\n' +
|
|
21
|
+
[
|
|
22
|
+
new visitor_plugin_common_1.DeclarationBlock({})
|
|
23
|
+
.asKind('type')
|
|
24
|
+
.withName('Properties<T>')
|
|
25
|
+
.withContent(['Required<{', ' [K in keyof T]: z.ZodType<T[K], any, T[K]>;', '}>'].join('\n')).string,
|
|
26
|
+
// Unfortunately, zod doesn’t provide non-null defined any schema.
|
|
27
|
+
// This is a temporary hack until it is fixed.
|
|
28
|
+
// see: https://github.com/colinhacks/zod/issues/884
|
|
29
|
+
new visitor_plugin_common_1.DeclarationBlock({}).asKind('type').withName('definedNonNullAny').withContent('{}')
|
|
30
|
+
.string,
|
|
31
|
+
new visitor_plugin_common_1.DeclarationBlock({})
|
|
32
|
+
.export()
|
|
33
|
+
.asKind('const')
|
|
34
|
+
.withName(`isDefinedNonNullAny`)
|
|
35
|
+
.withContent(`(v: any): v is definedNonNullAny => v !== undefined && v !== null`).string,
|
|
36
|
+
new visitor_plugin_common_1.DeclarationBlock({})
|
|
37
|
+
.export()
|
|
38
|
+
.asKind('const')
|
|
39
|
+
.withName(`${anySchema}`)
|
|
40
|
+
.withContent(`z.any().refine((v) => isDefinedNonNullAny(v))`).string,
|
|
41
|
+
].join('\n'),
|
|
42
|
+
InputObjectTypeDefinition: (node) => {
|
|
43
|
+
const name = tsVisitor.convertName(node.name.value);
|
|
44
|
+
importTypes.push(name);
|
|
45
|
+
const shape = node.fields
|
|
46
|
+
?.map((field) => generateFieldZodSchema(config, tsVisitor, schema, field, 2))
|
|
47
|
+
.join(',\n');
|
|
48
|
+
return new visitor_plugin_common_1.DeclarationBlock({})
|
|
49
|
+
.export()
|
|
50
|
+
.asKind('function')
|
|
51
|
+
.withName(`${name}Schema(): z.ZodObject<Properties<${name}>>`)
|
|
52
|
+
.withBlock([(0, visitor_plugin_common_1.indent)(`return z.object<Properties<${name}>>({`), shape, (0, visitor_plugin_common_1.indent)('})')].join('\n')).string;
|
|
53
|
+
},
|
|
54
|
+
ObjectTypeDefinition: ObjectTypeDefinitionBuilder(true, (node) => {
|
|
55
|
+
const name = tsVisitor.convertName(node.name.value);
|
|
56
|
+
importTypes.push(name);
|
|
57
|
+
const shape = node.fields
|
|
58
|
+
?.map((field) => generateFieldZodSchema(config, tsVisitor, schema, field, 2))
|
|
59
|
+
.join(',\n');
|
|
60
|
+
return new visitor_plugin_common_1.DeclarationBlock({})
|
|
61
|
+
.export()
|
|
62
|
+
.asKind('function')
|
|
63
|
+
.withName(`${name}Schema(): z.ZodObject<Properties<${name}>>`)
|
|
64
|
+
.withBlock([
|
|
65
|
+
(0, visitor_plugin_common_1.indent)(`return z.object<Properties<${name}>>({`),
|
|
66
|
+
(0, visitor_plugin_common_1.indent)(`__typename: z.literal('${node.name.value}').optional(),`, 2),
|
|
67
|
+
shape,
|
|
68
|
+
(0, visitor_plugin_common_1.indent)('})'),
|
|
69
|
+
].join('\n')).string;
|
|
70
|
+
}),
|
|
71
|
+
EnumTypeDefinition: (node) => {
|
|
72
|
+
const enumname = tsVisitor.convertName(node.name.value);
|
|
73
|
+
importTypes.push(enumname);
|
|
74
|
+
if (config.enumsAsTypes) {
|
|
75
|
+
return new visitor_plugin_common_1.DeclarationBlock({})
|
|
76
|
+
.export()
|
|
77
|
+
.asKind('const')
|
|
78
|
+
.withName(`${enumname}Schema`)
|
|
79
|
+
.withContent(`z.enum([${node.values
|
|
80
|
+
?.map((enumOption) => `'${enumOption.name.value}'`)
|
|
81
|
+
.join(', ')}])`).string;
|
|
82
|
+
}
|
|
83
|
+
return new visitor_plugin_common_1.DeclarationBlock({})
|
|
84
|
+
.export()
|
|
85
|
+
.asKind('const')
|
|
86
|
+
.withName(`${enumname}Schema`)
|
|
87
|
+
.withContent(`z.nativeEnum(${enumname})`).string;
|
|
88
|
+
},
|
|
89
|
+
UnionTypeDefinition: (node) => {
|
|
90
|
+
if (!node.types)
|
|
91
|
+
return undefined;
|
|
92
|
+
const unionName = tsVisitor.convertName(node.name.value);
|
|
93
|
+
const unionElements = node.types
|
|
94
|
+
.map((t) => `${tsVisitor.convertName(t.name.value)}Schema()`)
|
|
95
|
+
.join(', ');
|
|
96
|
+
const unionElementsCount = node.types.length ?? 0;
|
|
97
|
+
const union = unionElementsCount > 1
|
|
98
|
+
? (0, visitor_plugin_common_1.indent)(`return z.union([${unionElements}])`)
|
|
99
|
+
: (0, visitor_plugin_common_1.indent)(`return ${unionElements}`);
|
|
100
|
+
return new visitor_plugin_common_1.DeclarationBlock({})
|
|
101
|
+
.export()
|
|
102
|
+
.asKind('function')
|
|
103
|
+
.withName(`${unionName}Schema()`)
|
|
104
|
+
.withBlock(union).string;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
exports.MarkdownVisitor = MarkdownVisitor;
|
|
109
|
+
const generateFieldZodSchema = (config, tsVisitor, schema, field, indentCount) => {
|
|
110
|
+
const gen = generateFieldTypeZodSchema(config, tsVisitor, schema, field, field.type);
|
|
111
|
+
return (0, visitor_plugin_common_1.indent)(`${field.name.value}: ${maybeLazy(field.type, gen)}`, indentCount);
|
|
112
|
+
};
|
|
113
|
+
const generateFieldTypeZodSchema = (config, tsVisitor, schema, field, type, parentType) => {
|
|
114
|
+
if ((0, graphql_1.isListType)(type)) {
|
|
115
|
+
const gen = generateFieldTypeZodSchema(config, tsVisitor, schema, field, type.type, type);
|
|
116
|
+
if (!(0, graphql_1.isNonNullType)(parentType)) {
|
|
117
|
+
const arrayGen = `z.array(${maybeLazy(type.type, gen)})`;
|
|
118
|
+
const maybeLazyGen = applyDirectives(config, field, arrayGen);
|
|
119
|
+
return `${maybeLazyGen}.nullish()`;
|
|
120
|
+
}
|
|
121
|
+
return `z.array(${maybeLazy(type.type, gen)})`;
|
|
122
|
+
}
|
|
123
|
+
if ((0, graphql_1.isNonNullType)(type)) {
|
|
124
|
+
const gen = generateFieldTypeZodSchema(config, tsVisitor, schema, field, type.type, type);
|
|
125
|
+
return maybeLazy(type.type, gen);
|
|
126
|
+
}
|
|
127
|
+
if ((0, graphql_1.isNamedType)(type)) {
|
|
128
|
+
const gen = generateNameNodeZodSchema(config, tsVisitor, schema, type.name);
|
|
129
|
+
if ((0, graphql_1.isListType)(parentType)) {
|
|
130
|
+
return `${gen}.nullable()`;
|
|
131
|
+
}
|
|
132
|
+
const appliedDirectivesGen = applyDirectives(config, field, gen);
|
|
133
|
+
if ((0, graphql_1.isNonNullType)(parentType)) {
|
|
134
|
+
// if (config.notAllowEmptyString === true) {
|
|
135
|
+
// const tsType = tsVisitor.scalars[type.name.value]
|
|
136
|
+
// if (tsType === 'string') return `${appliedDirectivesGen}.min(1)`
|
|
137
|
+
// }
|
|
138
|
+
return appliedDirectivesGen;
|
|
139
|
+
}
|
|
140
|
+
if ((0, graphql_1.isListType)(parentType)) {
|
|
141
|
+
return `${appliedDirectivesGen}.nullable()`;
|
|
142
|
+
}
|
|
143
|
+
return `${appliedDirectivesGen}.nullish()`;
|
|
144
|
+
}
|
|
145
|
+
console.warn('unhandled type:', type);
|
|
146
|
+
return '';
|
|
147
|
+
};
|
|
148
|
+
const applyDirectives = (config, field, gen) =>
|
|
149
|
+
// if (config.directives && field.directives) {
|
|
150
|
+
// const formatted = formatDirectiveConfig(config.directives)
|
|
151
|
+
// return gen + buildApi(formatted, field.directives)
|
|
152
|
+
// }
|
|
153
|
+
gen;
|
|
154
|
+
const generateNameNodeZodSchema = (config, tsVisitor, schema, node) => {
|
|
155
|
+
const typ = schema.getType(node.value);
|
|
156
|
+
if (typ?.astNode?.kind === 'InputObjectTypeDefinition') {
|
|
157
|
+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
|
|
158
|
+
return `${enumName}Schema()`;
|
|
159
|
+
}
|
|
160
|
+
if (typ?.astNode?.kind === 'ObjectTypeDefinition') {
|
|
161
|
+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
|
|
162
|
+
return `${enumName}Schema()`;
|
|
163
|
+
}
|
|
164
|
+
if (typ?.astNode?.kind === 'EnumTypeDefinition') {
|
|
165
|
+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
|
|
166
|
+
return `${enumName}Schema`;
|
|
167
|
+
}
|
|
168
|
+
if (typ?.astNode?.kind === 'UnionTypeDefinition') {
|
|
169
|
+
const enumName = tsVisitor.convertName(typ.astNode.name.value);
|
|
170
|
+
return `${enumName}Schema()`;
|
|
171
|
+
}
|
|
172
|
+
return zod4Scalar(config, tsVisitor, node.value);
|
|
173
|
+
};
|
|
174
|
+
const maybeLazy = (type, schema) => {
|
|
175
|
+
if ((0, graphql_1.isNamedType)(type) && (0, graphql_1.isInput)(type.name.value)) {
|
|
176
|
+
return `z.lazy(() => ${schema})`;
|
|
177
|
+
}
|
|
178
|
+
return schema;
|
|
179
|
+
};
|
|
180
|
+
const zod4Scalar = (config, tsVisitor, scalarName) => {
|
|
181
|
+
const tsType = tsVisitor.scalars[scalarName];
|
|
182
|
+
switch (tsType) {
|
|
183
|
+
case 'string':
|
|
184
|
+
return `z.string()`;
|
|
185
|
+
case 'number':
|
|
186
|
+
return `z.number()`;
|
|
187
|
+
case 'boolean':
|
|
188
|
+
return `z.boolean()`;
|
|
189
|
+
}
|
|
190
|
+
console.warn('unhandled scalar name:', scalarName);
|
|
191
|
+
return anySchema;
|
|
192
|
+
};
|
package/dist/config.js
ADDED
package/dist/graphql.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObjectTypeDefinitionBuilder = exports.isInput = exports.isNamedType = exports.isNonNullType = exports.isListType = void 0;
|
|
4
|
+
const isListType = (typ) => typ?.kind === 'ListType';
|
|
5
|
+
exports.isListType = isListType;
|
|
6
|
+
const isNonNullType = (typ) => typ?.kind === 'NonNullType';
|
|
7
|
+
exports.isNonNullType = isNonNullType;
|
|
8
|
+
const isNamedType = (typ) => typ?.kind === 'NamedType';
|
|
9
|
+
exports.isNamedType = isNamedType;
|
|
10
|
+
const isInput = (kind) => kind.includes('Input');
|
|
11
|
+
exports.isInput = isInput;
|
|
12
|
+
const ObjectTypeDefinitionBuilder = (useObjectTypes, callback) => {
|
|
13
|
+
if (!useObjectTypes)
|
|
14
|
+
return undefined;
|
|
15
|
+
return (node) => {
|
|
16
|
+
if (/^(Query|Mutation|Subscription)$/.test(node.name.value)) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
return callback(node);
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
exports.ObjectTypeDefinitionBuilder = ObjectTypeDefinitionBuilder;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.plugin = void 0;
|
|
4
|
+
const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
|
|
5
|
+
const graphql_1 = require("graphql");
|
|
6
|
+
/** Converts input type to markdown document. */
|
|
7
|
+
const plugin = (schema, _documents, config) => {
|
|
8
|
+
const astNode = (0, plugin_helpers_1.getCachedDocumentNodeFromSchema)(schema);
|
|
9
|
+
const enumStings = new Map();
|
|
10
|
+
const descriptionText = (node) => {
|
|
11
|
+
if (!node.description) {
|
|
12
|
+
console.warn(`Missing description for ${node.name}`);
|
|
13
|
+
}
|
|
14
|
+
return node.description ? `\n\n${node.description}` : '';
|
|
15
|
+
};
|
|
16
|
+
const res = (0, graphql_1.visit)(astNode, {
|
|
17
|
+
Document: {
|
|
18
|
+
leave: (node) => `<!-- auto generated -->${node.definitions.filter(Boolean).join('\n')}`,
|
|
19
|
+
},
|
|
20
|
+
Name: { leave: (node) => node.value },
|
|
21
|
+
NamedType: { leave: (node) => node.name },
|
|
22
|
+
StringValue: { leave: (node) => node.value },
|
|
23
|
+
ListType: { leave: (node) => `[${node.type}]` },
|
|
24
|
+
NonNullType: { leave: (node) => `${node.type}!` },
|
|
25
|
+
InputValueDefinition: {
|
|
26
|
+
leave: (node) => {
|
|
27
|
+
const { type } = node;
|
|
28
|
+
return `\`${node.name}: ${type}\`${descriptionText(node)}`;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
InputObjectTypeDefinition: {
|
|
32
|
+
enter: (node) => ({
|
|
33
|
+
...node,
|
|
34
|
+
// Move required fields to the top.
|
|
35
|
+
fields: [...(node.fields ?? [])].sort((a, b) => a.type.kind === 'NonNullType' && b.type.kind !== 'NonNullType' ? -1 : 1),
|
|
36
|
+
}),
|
|
37
|
+
leave: (node) => `\n## ${node.name}${descriptionText(node)}
|
|
38
|
+
${node.fields?.map((f) => `\n### ${f}`).join('\n')}`,
|
|
39
|
+
},
|
|
40
|
+
EnumValueDefinition: {
|
|
41
|
+
leave: (node) => `${node.name} # ${node.description}`,
|
|
42
|
+
},
|
|
43
|
+
EnumTypeDefinition: {
|
|
44
|
+
leave: (node) => {
|
|
45
|
+
enumStings.set(node.name, node.values?.join('\n') || '');
|
|
46
|
+
return '';
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
// prepend: buildImports(),
|
|
52
|
+
content: [res].join('\n'),
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
exports.plugin = plugin;
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@graphcommerce/graphql-codegen-markdown-docs",
|
|
3
|
+
"homepage": "https://www.graphcommerce.org/",
|
|
4
|
+
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
+
"version": "6.0.0-canary.20",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "src/index.ts",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"dev": "tsc -W --preserveWatchOutput",
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"prepack": "tsc"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
19
|
+
],
|
|
20
|
+
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
21
|
+
"eslintConfig": {
|
|
22
|
+
"extends": "@graphcommerce/eslint-config-pwa",
|
|
23
|
+
"parserOptions": {
|
|
24
|
+
"project": "./tsconfig.json"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@graphcommerce/eslint-config-pwa": "6.0.0-canary.20",
|
|
29
|
+
"@graphcommerce/prettier-config-pwa": "6.0.0-canary.20",
|
|
30
|
+
"@graphcommerce/typescript-config-pwa": "6.0.0-canary.20"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@graphql-codegen/add": "4.0.0",
|
|
34
|
+
"@graphql-codegen/plugin-helpers": "4.0.0",
|
|
35
|
+
"@graphql-codegen/visitor-plugin-common": "3.0.0",
|
|
36
|
+
"@graphql-tools/utils": "^9.2.1",
|
|
37
|
+
"@types/parse-filepath": "^1.0.0",
|
|
38
|
+
"graphql": "16.6.0",
|
|
39
|
+
"parse-filepath": "^1.0.2"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TypeScriptPluginConfig } from '@graphql-codegen/typescript'
|
|
2
|
+
|
|
3
|
+
export interface DirectiveConfig {
|
|
4
|
+
[directive: string]: {
|
|
5
|
+
[argument: string]: string | string[] | DirectiveObjectArguments
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface DirectiveObjectArguments {
|
|
10
|
+
[matched: string]: string | string[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface MarkdownDocsPluginConfig extends TypeScriptPluginConfig {
|
|
14
|
+
markdown: boolean
|
|
15
|
+
}
|
package/src/graphql.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ListTypeNode,
|
|
3
|
+
NonNullTypeNode,
|
|
4
|
+
NamedTypeNode,
|
|
5
|
+
TypeNode,
|
|
6
|
+
ObjectTypeDefinitionNode,
|
|
7
|
+
} from 'graphql'
|
|
8
|
+
|
|
9
|
+
export const isListType = (typ?: TypeNode): typ is ListTypeNode => typ?.kind === 'ListType'
|
|
10
|
+
export const isNonNullType = (typ?: TypeNode): typ is NonNullTypeNode => typ?.kind === 'NonNullType'
|
|
11
|
+
export const isNamedType = (typ?: TypeNode): typ is NamedTypeNode => typ?.kind === 'NamedType'
|
|
12
|
+
|
|
13
|
+
export const isInput = (kind: string) => kind.includes('Input')
|
|
14
|
+
|
|
15
|
+
type ObjectTypeDefinitionFn = (node: ObjectTypeDefinitionNode) => any
|
|
16
|
+
|
|
17
|
+
export const ObjectTypeDefinitionBuilder = (
|
|
18
|
+
useObjectTypes: boolean | undefined,
|
|
19
|
+
callback: ObjectTypeDefinitionFn,
|
|
20
|
+
): ObjectTypeDefinitionFn | undefined => {
|
|
21
|
+
if (!useObjectTypes) return undefined
|
|
22
|
+
return (node) => {
|
|
23
|
+
if (/^(Query|Mutation|Subscription)$/.test(node.name.value)) {
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
return callback(node)
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PluginFunction, Types } from '@graphql-codegen/plugin-helpers'
|
|
2
|
+
import { getCachedDocumentNodeFromSchema } from '@graphql-codegen/plugin-helpers'
|
|
3
|
+
import { GraphQLSchema, visit } from 'graphql'
|
|
4
|
+
import { MarkdownDocsPluginConfig } from './config'
|
|
5
|
+
|
|
6
|
+
/** Converts input type to markdown document. */
|
|
7
|
+
export const plugin: PluginFunction<MarkdownDocsPluginConfig, Types.ComplexPluginOutput> = (
|
|
8
|
+
schema: GraphQLSchema,
|
|
9
|
+
_documents: Types.DocumentFile[],
|
|
10
|
+
config: MarkdownDocsPluginConfig,
|
|
11
|
+
): Types.ComplexPluginOutput => {
|
|
12
|
+
const astNode = getCachedDocumentNodeFromSchema(schema)
|
|
13
|
+
|
|
14
|
+
const enumStings = new Map<string, string>()
|
|
15
|
+
|
|
16
|
+
const descriptionText = (node: { description?: string; name: string }) => {
|
|
17
|
+
if (!node.description) {
|
|
18
|
+
console.warn(`Missing description for ${node.name}`)
|
|
19
|
+
}
|
|
20
|
+
return node.description ? `\n\n${node.description}` : ''
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const res = visit<string>(astNode, {
|
|
24
|
+
Document: {
|
|
25
|
+
leave: (node) => `<!-- auto generated -->${node.definitions.filter(Boolean).join('\n')}`,
|
|
26
|
+
},
|
|
27
|
+
Name: { leave: (node) => node.value },
|
|
28
|
+
NamedType: { leave: (node) => node.name }, // String, Boolean, GraphCommerceDebugConfig, etc.
|
|
29
|
+
StringValue: { leave: (node) => node.value },
|
|
30
|
+
ListType: { leave: (node) => `[${node.type}]` },
|
|
31
|
+
NonNullType: { leave: (node) => `${node.type}!` },
|
|
32
|
+
InputValueDefinition: {
|
|
33
|
+
leave: (node) => {
|
|
34
|
+
const { type } = node
|
|
35
|
+
return `\`${node.name}: ${type}\`${descriptionText(node)}`
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
InputObjectTypeDefinition: {
|
|
39
|
+
enter: (node) => ({
|
|
40
|
+
...node,
|
|
41
|
+
// Move required fields to the top.
|
|
42
|
+
fields: [...(node.fields ?? [])].sort((a, b) =>
|
|
43
|
+
a.type.kind === 'NonNullType' && b.type.kind !== 'NonNullType' ? -1 : 1,
|
|
44
|
+
),
|
|
45
|
+
}),
|
|
46
|
+
leave: (node) => `\n## ${node.name}${descriptionText(node)}
|
|
47
|
+
${node.fields?.map((f) => `\n### ${f}`).join('\n')}`,
|
|
48
|
+
},
|
|
49
|
+
EnumValueDefinition: {
|
|
50
|
+
leave: (node) => `${node.name} # ${node.description}`,
|
|
51
|
+
},
|
|
52
|
+
EnumTypeDefinition: {
|
|
53
|
+
leave: (node) => {
|
|
54
|
+
enumStings.set(node.name, node.values?.join('\n') || '')
|
|
55
|
+
return ''
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
// prepend: buildImports(),
|
|
62
|
+
content: [res].join('\n'),
|
|
63
|
+
}
|
|
64
|
+
}
|