-
-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathvisitor.ts
90 lines (75 loc) · 2.46 KB
/
visitor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { TsVisitor } from '@graphql-codegen/typescript';
import type {
FieldDefinitionNode,
GraphQLSchema,
InterfaceTypeDefinitionNode,
NameNode,
ObjectTypeDefinitionNode,
} from 'graphql';
import {
specifiedScalarTypes,
} from 'graphql';
import type { ValidationSchemaPluginConfig } from './config.js';
export class Visitor extends TsVisitor {
constructor(
private scalarDirection: 'input' | 'output' | 'both',
private schema: GraphQLSchema,
private pluginConfig: ValidationSchemaPluginConfig,
) {
super(schema, pluginConfig);
}
private isSpecifiedScalarName(scalarName: string) {
return specifiedScalarTypes.some(({ name }) => name === scalarName);
}
public getType(name: string) {
return this.schema.getType(name);
}
public getNameNodeConverter(node: NameNode) {
const typ = this.schema.getType(node.value);
const astNode = typ?.astNode;
if (astNode === undefined || astNode === null)
return undefined;
return {
targetKind: astNode.kind,
convertName: () => this.convertName(astNode.name.value),
};
}
public getScalarType(scalarName: string): string | null {
if (this.scalarDirection === 'both')
return null;
const scalar = this.scalars[scalarName];
if (!scalar)
throw new Error(`Unknown scalar ${scalarName}`);
return scalar[this.scalarDirection];
}
public shouldEmitAsNotAllowEmptyString(name: string): boolean {
if (this.pluginConfig.notAllowEmptyString !== true)
return false;
const typ = this.getType(name);
if (typ?.astNode?.kind !== 'ScalarTypeDefinition' && !this.isSpecifiedScalarName(name))
return false;
const tsType = this.getScalarType(name);
return tsType === 'string';
}
public buildArgumentsSchemaBlock(
node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode,
callback: (typeName: string, field: FieldDefinitionNode) => string,
) {
const fieldsWithArguments = node.fields?.filter(field => field.arguments && field.arguments.length > 0) ?? [];
if (fieldsWithArguments.length === 0)
return undefined;
return fieldsWithArguments
.map((field) => {
const name
= `${this.convertName(node.name.value)
+ (this.config.addUnderscoreToArgsType ? '_' : '')
+ this.convertName(field, {
useTypesPrefix: false,
useTypesSuffix: false,
})
}Args`;
return callback(name, field);
})
.join('\n');
}
}