@eddeee888/gcg-typescript-resolver-files 0.18.0 → 0.18.2
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/defineConfig.d.ts +1 -1
- package/dist/defineConfig.js +8 -0
- package/package.json +7 -3
- package/CHANGELOG.md +0 -816
- package/DEVELOPMENT.md +0 -49
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
- package/eslint.config.mjs +0 -22
- package/project.json +0 -8
- package/src/addVirtualTypesFileToTsMorphProject/addVirtualTypesFileToTsMorphProject.ts +0 -109
- package/src/addVirtualTypesFileToTsMorphProject/index.ts +0 -1
- package/src/defineConfig.spec.ts +0 -76
- package/src/defineConfig.ts +0 -37
- package/src/generateResolverFiles/addExternalResolverImport.ts +0 -185
- package/src/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.spec.ts +0 -1174
- package/src/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.ts +0 -144
- package/src/generateResolverFiles/addResolverMainFiles.ts +0 -343
- package/src/generateResolverFiles/ensureEnumTypeResolversAreGenerated.ts +0 -51
- package/src/generateResolverFiles/generateResolverFiles.ts +0 -148
- package/src/generateResolverFiles/getImportStatementWithExpectedNamedImport.spec.ts +0 -127
- package/src/generateResolverFiles/getImportStatementWithExpectedNamedImport.ts +0 -25
- package/src/generateResolverFiles/getVariableStatementWithExpectedIdentifier.spec.ts +0 -147
- package/src/generateResolverFiles/getVariableStatementWithExpectedIdentifier.ts +0 -34
- package/src/generateResolverFiles/handleGraphQLEnumType.ts +0 -100
- package/src/generateResolverFiles/handleGraphQLInterfaceType.ts +0 -70
- package/src/generateResolverFiles/handleGraphQLObjectType.ts +0 -171
- package/src/generateResolverFiles/handleGraphQLRootObjectTypeField.ts +0 -105
- package/src/generateResolverFiles/handleGraphQLScalarType.ts +0 -81
- package/src/generateResolverFiles/handleGraphQLUnionType.ts +0 -68
- package/src/generateResolverFiles/index.ts +0 -2
- package/src/generateResolverFiles/postProcessFiles.ts +0 -287
- package/src/generateResolverFiles/types.ts +0 -203
- package/src/generateResolverFiles/visitNamedType.ts +0 -66
- package/src/generateTypeDefsFiles/generateTypeDefsContent.ts +0 -15
- package/src/generateTypeDefsFiles/generateTypeDefsFiles.ts +0 -100
- package/src/generateTypeDefsFiles/index.ts +0 -1
- package/src/getGraphQLObjectTypeResolversToGenerate/getGraphQLObjectTypeResolversToGenerate.ts +0 -361
- package/src/getGraphQLObjectTypeResolversToGenerate/getNodePropertyMap.spec.ts +0 -115
- package/src/getGraphQLObjectTypeResolversToGenerate/getNodePropertyMap.ts +0 -88
- package/src/getGraphQLObjectTypeResolversToGenerate/index.ts +0 -1
- package/src/index.ts +0 -3
- package/src/normalizeAddConfigPath/index.ts +0 -1
- package/src/normalizeAddConfigPath/normalizeAddConfigPath.ts +0 -29
- package/src/parseGraphQLSchema/index.ts +0 -2
- package/src/parseGraphQLSchema/normalizeResolverName.ts +0 -28
- package/src/parseGraphQLSchema/parseGraphQLSchema.ts +0 -531
- package/src/parseGraphQLSchema/parseLocationForOutputDir.ts +0 -76
- package/src/parseSources/index.ts +0 -1
- package/src/parseSources/parseSources.ts +0 -83
- package/src/parseTypeMappers/collectTypeMappersFromSourceFile.spec.ts +0 -789
- package/src/parseTypeMappers/collectTypeMappersFromSourceFile.ts +0 -197
- package/src/parseTypeMappers/index.ts +0 -1
- package/src/parseTypeMappers/parseTypeMappers.ts +0 -75
- package/src/preset.ts +0 -317
- package/src/utils/cwd.ts +0 -8
- package/src/utils/fmt.ts +0 -16
- package/src/utils/index.ts +0 -12
- package/src/utils/isMatchResolverNamePattern.ts +0 -27
- package/src/utils/isNativeNamedType.ts +0 -21
- package/src/utils/isRootObjectType.ts +0 -8
- package/src/utils/isWhitelistedModule.spec.ts +0 -71
- package/src/utils/isWhitelistedModule.ts +0 -21
- package/src/utils/logger.ts +0 -14
- package/src/utils/normalizeImportExtension.spec.ts +0 -42
- package/src/utils/normalizeImportExtension.ts +0 -16
- package/src/utils/normalizeRelativePath.ts +0 -6
- package/src/utils/parseLocationForWhitelistedModule.spec.ts +0 -130
- package/src/utils/parseLocationForWhitelistedModule.ts +0 -38
- package/src/utils/printImportLine.spec.ts +0 -150
- package/src/utils/printImportLine.ts +0 -78
- package/src/utils/relativeModulePath.ts +0 -7
- package/src/validateAndMergeParsedConfigs/index.ts +0 -1
- package/src/validateAndMergeParsedConfigs/validateAndMergeParsedConfigs.spec.ts +0 -211
- package/src/validateAndMergeParsedConfigs/validateAndMergeParsedConfigs.ts +0 -92
- package/src/validatePresetConfig/index.ts +0 -1
- package/src/validatePresetConfig/validatePresetConfig.spec.ts +0 -706
- package/src/validatePresetConfig/validatePresetConfig.ts +0 -571
- package/tsconfig.json +0 -14
- package/tsconfig.lib.json +0 -18
- package/tsconfig.spec.json +0 -20
- package/vite.config.ts +0 -24
package/src/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { type PropertyAssignment, type SourceFile, SyntaxKind } from 'ts-morph';
|
|
2
|
-
import type { ObjectTypeFile } from './types.js';
|
|
3
|
-
import { getVariableStatementWithExpectedIdentifier } from './getVariableStatementWithExpectedIdentifier.js';
|
|
4
|
-
|
|
5
|
-
export type AddedPropertyAssignmentNodes = Record<
|
|
6
|
-
string, // SourceFile's filename
|
|
7
|
-
Record<
|
|
8
|
-
number, // Line number
|
|
9
|
-
{
|
|
10
|
-
node: PropertyAssignment;
|
|
11
|
-
resolverFile: ObjectTypeFile;
|
|
12
|
-
__toBeRemoved: boolean;
|
|
13
|
-
}
|
|
14
|
-
>
|
|
15
|
-
>;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Ensure objectTypeResolver files have all the resolvers due to mismatched types
|
|
19
|
-
*/
|
|
20
|
-
export const addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented = ({
|
|
21
|
-
addedPropertyAssignmentNodes,
|
|
22
|
-
sourceFile,
|
|
23
|
-
resolverFile,
|
|
24
|
-
mode,
|
|
25
|
-
}: {
|
|
26
|
-
addedPropertyAssignmentNodes: AddedPropertyAssignmentNodes;
|
|
27
|
-
sourceFile: SourceFile;
|
|
28
|
-
resolverFile: ObjectTypeFile;
|
|
29
|
-
mode: 'smart' | 'fast';
|
|
30
|
-
}): void => {
|
|
31
|
-
const sourceFilePath = sourceFile.getFilePath().toString();
|
|
32
|
-
addedPropertyAssignmentNodes[sourceFilePath] =
|
|
33
|
-
addedPropertyAssignmentNodes[sourceFilePath] || {};
|
|
34
|
-
|
|
35
|
-
const resolversToGenerate = resolverFile.meta.resolversToGenerate || {};
|
|
36
|
-
if (!Object.keys(resolversToGenerate).length) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const { variableStatement } = getVariableStatementWithExpectedIdentifier(
|
|
41
|
-
sourceFile,
|
|
42
|
-
resolverFile
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
if (!variableStatement) {
|
|
46
|
-
throw new Error(
|
|
47
|
-
'Missing variableStatement in addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.'
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 1. Check to see which generated to-be-generated resolvers are implemented
|
|
52
|
-
const resolversData: Record<
|
|
53
|
-
string,
|
|
54
|
-
{
|
|
55
|
-
resolverName: string;
|
|
56
|
-
resolverDeclaration: string;
|
|
57
|
-
implemented?: true;
|
|
58
|
-
}
|
|
59
|
-
> = { ...resolversToGenerate };
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* PropertyAssignment
|
|
63
|
-
* ```
|
|
64
|
-
* const name = () => {};
|
|
65
|
-
* const OutputType = {
|
|
66
|
-
* id: () => {},
|
|
67
|
-
* name: name,
|
|
68
|
-
* }
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
variableStatement
|
|
72
|
-
.getDescendantsOfKind(SyntaxKind.PropertyAssignment)
|
|
73
|
-
.forEach((propertyAssignment) => {
|
|
74
|
-
const resolverName = propertyAssignment.getName();
|
|
75
|
-
if (resolversData[resolverName]) {
|
|
76
|
-
resolversData[resolverName].implemented = true;
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* MethodDeclaration
|
|
82
|
-
* ```
|
|
83
|
-
* const OutputType = {
|
|
84
|
-
* id(){},
|
|
85
|
-
* }
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
variableStatement
|
|
89
|
-
.getDescendantsOfKind(SyntaxKind.MethodDeclaration)
|
|
90
|
-
.forEach((methodDeclaration) => {
|
|
91
|
-
const resolverName = methodDeclaration.getName();
|
|
92
|
-
if (resolversData[resolverName]) {
|
|
93
|
-
resolversData[resolverName].implemented = true;
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* ShorthandPropertyAssignment example:
|
|
99
|
-
* ```
|
|
100
|
-
* const id = () => {};
|
|
101
|
-
* const OutputType = {
|
|
102
|
-
* id,
|
|
103
|
-
* }
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
|
-
variableStatement
|
|
107
|
-
.getDescendantsOfKind(SyntaxKind.ShorthandPropertyAssignment)
|
|
108
|
-
.forEach((propertyAssignment) => {
|
|
109
|
-
const resolverName = propertyAssignment.getName();
|
|
110
|
-
if (resolversData[resolverName]) {
|
|
111
|
-
resolversData[resolverName].implemented = true;
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// 2. Add missing resolver properties if they haven't been implemented
|
|
116
|
-
Object.values(resolversData).forEach(
|
|
117
|
-
({ resolverName, resolverDeclaration, implemented }) => {
|
|
118
|
-
if (implemented) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const addedNode = variableStatement
|
|
123
|
-
.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)[0]
|
|
124
|
-
.addPropertyAssignment({
|
|
125
|
-
name: resolverName,
|
|
126
|
-
initializer: resolverDeclaration,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
if (mode === 'fast') {
|
|
130
|
-
resolverFile.filesystem.contentUpdated = true;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
addedPropertyAssignmentNodes[sourceFilePath][
|
|
134
|
-
addedNode.getStartLineNumber()
|
|
135
|
-
] = {
|
|
136
|
-
node: addedNode,
|
|
137
|
-
resolverFile,
|
|
138
|
-
// When mode is "smart", we use TS compiler for typechecking, and it'd remove the node if there is no compilation error. Therefore, `__toBeRemoved: true`
|
|
139
|
-
// When mode is "fast", we already check whether the the type is assignable, so no need to remove the node.
|
|
140
|
-
__toBeRemoved: mode === 'fast' ? false : true,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
);
|
|
144
|
-
};
|
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
|
-
import {
|
|
3
|
-
isRootObjectType,
|
|
4
|
-
printImportLine,
|
|
5
|
-
relativeModulePath,
|
|
6
|
-
type RootObjectType,
|
|
7
|
-
} from '../utils/index.js';
|
|
8
|
-
import type { GenerateResolverFilesContext } from './types.js';
|
|
9
|
-
|
|
10
|
-
interface FileDetails {
|
|
11
|
-
importLines: string[];
|
|
12
|
-
queryFields: ObjectFieldMapping[];
|
|
13
|
-
mutationFields: ObjectFieldMapping[];
|
|
14
|
-
subscriptionFields: ObjectFieldMapping[];
|
|
15
|
-
objectTypes: ObjectTypesMap;
|
|
16
|
-
}
|
|
17
|
-
const createDefaultFileDetails = (): FileDetails => ({
|
|
18
|
-
importLines: [],
|
|
19
|
-
queryFields: [],
|
|
20
|
-
mutationFields: [],
|
|
21
|
-
subscriptionFields: [],
|
|
22
|
-
objectTypes: {},
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* addResolverMainFiles
|
|
27
|
-
*
|
|
28
|
-
* @description Function to create resolver main file/s (default: resolvers.generated.ts)
|
|
29
|
-
* If resolverMainFileMode=merged, only one file is generated
|
|
30
|
-
* If resolverMainFileMode=modules, one file is generated for each module
|
|
31
|
-
* If no resolvers are created or imported, do not generate a file.
|
|
32
|
-
*/
|
|
33
|
-
export const addResolverMainFiles = ({
|
|
34
|
-
config: {
|
|
35
|
-
baseOutputDir,
|
|
36
|
-
resolverTypesPath,
|
|
37
|
-
resolverMainFile,
|
|
38
|
-
resolverMainFileMode,
|
|
39
|
-
emitLegacyCommonJSImports,
|
|
40
|
-
importExtension,
|
|
41
|
-
generatedTypesFileMeta: { generatedResolverTypes },
|
|
42
|
-
},
|
|
43
|
-
result,
|
|
44
|
-
}: GenerateResolverFilesContext): void => {
|
|
45
|
-
const baseIdentifierUsage = countBaseIdentifiersUsage(result.files);
|
|
46
|
-
|
|
47
|
-
const resolverMainFiles = Object.entries(result.files).reduce<
|
|
48
|
-
Record<string, FileDetails>
|
|
49
|
-
>((res, [filepath, file]) => {
|
|
50
|
-
if (file.__filetype === 'file') {
|
|
51
|
-
return res;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const { meta } = file;
|
|
55
|
-
|
|
56
|
-
// If resolverMainFileMode === 'modules', generate main resolver files into modules, otherwise, do it at baseOutputDir
|
|
57
|
-
const resolverMainFilename =
|
|
58
|
-
resolverMainFileMode === 'modules'
|
|
59
|
-
? path.posix.join(
|
|
60
|
-
baseOutputDir,
|
|
61
|
-
...meta.relativePathFromBaseToModule,
|
|
62
|
-
resolverMainFile
|
|
63
|
-
)
|
|
64
|
-
: path.posix.join(baseOutputDir, resolverMainFile);
|
|
65
|
-
|
|
66
|
-
const outputDir = path.dirname(resolverMainFilename);
|
|
67
|
-
|
|
68
|
-
if (!res[resolverMainFilename]) {
|
|
69
|
-
res[resolverMainFilename] = createDefaultFileDetails();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const baseIdentifierName = makeNormalizedResolverNameVariableCompatible(
|
|
73
|
-
file.meta.normalizedResolverName.base
|
|
74
|
-
);
|
|
75
|
-
const identifierName =
|
|
76
|
-
baseIdentifierUsage[baseIdentifierName] > 1
|
|
77
|
-
? makeNormalizedResolverNameVariableCompatible(
|
|
78
|
-
file.meta.normalizedResolverName.withModule
|
|
79
|
-
)
|
|
80
|
-
: baseIdentifierName;
|
|
81
|
-
|
|
82
|
-
const fieldMapping: ObjectFieldMapping = {
|
|
83
|
-
propertyName: file.mainImportIdentifier,
|
|
84
|
-
identifierName,
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// Non Root Object fields that was generated
|
|
88
|
-
if (
|
|
89
|
-
file.__filetype === 'objectType' ||
|
|
90
|
-
file.__filetype === 'interfaceResolver' ||
|
|
91
|
-
file.__filetype === 'unionResolver' ||
|
|
92
|
-
file.__filetype === 'scalarResolver' ||
|
|
93
|
-
file.__filetype === 'enumResolver'
|
|
94
|
-
) {
|
|
95
|
-
res[resolverMainFilename].importLines.push(
|
|
96
|
-
printImportLine({
|
|
97
|
-
isTypeImport: false,
|
|
98
|
-
module: relativeModulePath(outputDir, filepath),
|
|
99
|
-
moduleType: 'file',
|
|
100
|
-
namedImports: [fieldMapping],
|
|
101
|
-
emitLegacyCommonJSImports,
|
|
102
|
-
importExtension,
|
|
103
|
-
})
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
pushToObjectTypes({
|
|
107
|
-
objectTypes: res[resolverMainFilename].objectTypes,
|
|
108
|
-
property: file.mainImportIdentifier,
|
|
109
|
-
value: identifierName,
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return res;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Root object fields
|
|
116
|
-
res[resolverMainFilename].importLines.push(
|
|
117
|
-
printImportLine({
|
|
118
|
-
isTypeImport: false,
|
|
119
|
-
module: relativeModulePath(outputDir, filepath),
|
|
120
|
-
moduleType: 'file',
|
|
121
|
-
namedImports: [fieldMapping],
|
|
122
|
-
emitLegacyCommonJSImports,
|
|
123
|
-
importExtension,
|
|
124
|
-
})
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
const rootObjectMap: Record<RootObjectType, () => void> = {
|
|
128
|
-
Query: () => res[resolverMainFilename].queryFields.push(fieldMapping),
|
|
129
|
-
Mutation: () =>
|
|
130
|
-
res[resolverMainFilename].mutationFields.push(fieldMapping),
|
|
131
|
-
Subscription: () =>
|
|
132
|
-
res[resolverMainFilename].subscriptionFields.push(fieldMapping),
|
|
133
|
-
};
|
|
134
|
-
rootObjectMap[file.meta.belongsToRootObject]();
|
|
135
|
-
|
|
136
|
-
return res;
|
|
137
|
-
}, {});
|
|
138
|
-
|
|
139
|
-
Object.entries(result.externalImports).reduce((res, [module, meta]) => {
|
|
140
|
-
// If resolverMainFileMode === 'modules', generate main resolver files into modules, otherwise, do it at baseOutputDir
|
|
141
|
-
const resolverMainFilename =
|
|
142
|
-
resolverMainFileMode === 'modules'
|
|
143
|
-
? path.posix.join(
|
|
144
|
-
baseOutputDir,
|
|
145
|
-
...meta.relativePathFromBaseToModule,
|
|
146
|
-
resolverMainFile
|
|
147
|
-
)
|
|
148
|
-
: path.posix.join(baseOutputDir, resolverMainFile);
|
|
149
|
-
|
|
150
|
-
if (!res[resolverMainFilename]) {
|
|
151
|
-
res[resolverMainFilename] = createDefaultFileDetails();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
res[resolverMainFilename].importLines.push(
|
|
155
|
-
printImportLine({
|
|
156
|
-
isTypeImport: false,
|
|
157
|
-
module,
|
|
158
|
-
moduleType: 'preserve',
|
|
159
|
-
namedImports: meta.importLineMeta.namedImports,
|
|
160
|
-
defaultImport: meta.importLineMeta.defaultImport,
|
|
161
|
-
emitLegacyCommonJSImports,
|
|
162
|
-
importExtension,
|
|
163
|
-
})
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
meta.identifierUsages.forEach((usage) => {
|
|
167
|
-
const resolverNameParts = usage.normalizedResolverName.split('.');
|
|
168
|
-
|
|
169
|
-
// Only 1 part, this is a GraphQL ObjectType
|
|
170
|
-
if (resolverNameParts.length === 1) {
|
|
171
|
-
pushToObjectTypes({
|
|
172
|
-
objectTypes: res[resolverMainFilename].objectTypes,
|
|
173
|
-
property: resolverNameParts[0],
|
|
174
|
-
value: usage.identifierName,
|
|
175
|
-
});
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// 2+ parts, treat as 2 parts. This is a GraphQL ObjectType with field e.g. Query.me, Mutation.updateUser
|
|
180
|
-
const [rootObjectType, field] = resolverNameParts;
|
|
181
|
-
if (!isRootObjectType(rootObjectType)) {
|
|
182
|
-
throw new Error(`Unexpected root object type found: ${rootObjectType}`);
|
|
183
|
-
}
|
|
184
|
-
const fieldMapping: ObjectFieldMapping = {
|
|
185
|
-
identifierName: usage.identifierName,
|
|
186
|
-
propertyName: field,
|
|
187
|
-
};
|
|
188
|
-
const rootObjectMap: Record<RootObjectType, () => void> = {
|
|
189
|
-
Query: () => res[resolverMainFilename].queryFields.push(fieldMapping),
|
|
190
|
-
Mutation: () =>
|
|
191
|
-
res[resolverMainFilename].mutationFields.push(fieldMapping),
|
|
192
|
-
Subscription: () =>
|
|
193
|
-
res[resolverMainFilename].subscriptionFields.push(fieldMapping),
|
|
194
|
-
};
|
|
195
|
-
rootObjectMap[rootObjectType]();
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
return res;
|
|
199
|
-
}, resolverMainFiles);
|
|
200
|
-
|
|
201
|
-
const resolversIdentifier = 'resolvers';
|
|
202
|
-
const resolversTypeName = generatedResolverTypes.resolversMap.name;
|
|
203
|
-
|
|
204
|
-
Object.entries(resolverMainFiles).forEach(([resolverMainFilename, file]) => {
|
|
205
|
-
const outputDir = path.dirname(resolverMainFilename);
|
|
206
|
-
const relativePathToResolverTypes = relativeModulePath(
|
|
207
|
-
outputDir,
|
|
208
|
-
resolverTypesPath
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
const queries =
|
|
212
|
-
file.queryFields.length > 0
|
|
213
|
-
? `Query: { ${file.queryFields.map(printObjectMapping).join(',')} },`
|
|
214
|
-
: '';
|
|
215
|
-
const mutations =
|
|
216
|
-
file.mutationFields.length > 0
|
|
217
|
-
? `Mutation: { ${file.mutationFields
|
|
218
|
-
.map(printObjectMapping)
|
|
219
|
-
.join(',')} },`
|
|
220
|
-
: '';
|
|
221
|
-
const suscriptions =
|
|
222
|
-
file.subscriptionFields.length > 0
|
|
223
|
-
? `Subscription: { ${file.subscriptionFields
|
|
224
|
-
.map(printObjectMapping)
|
|
225
|
-
.join(',')} },`
|
|
226
|
-
: '';
|
|
227
|
-
|
|
228
|
-
result.files[resolverMainFilename] = {
|
|
229
|
-
__filetype: 'file',
|
|
230
|
-
// TODO: type='virtual' means we will generate these main files every run.
|
|
231
|
-
// Consider checking if these files are already on the filesystem, and whether the content has changed before generating?
|
|
232
|
-
filesystem: {
|
|
233
|
-
type: 'virtual',
|
|
234
|
-
contentUpdated: false,
|
|
235
|
-
},
|
|
236
|
-
mainImportIdentifier: resolversIdentifier,
|
|
237
|
-
content: `/* This file was automatically generated. DO NOT UPDATE MANUALLY. */
|
|
238
|
-
${printImportLine({
|
|
239
|
-
isTypeImport: true,
|
|
240
|
-
module: relativePathToResolverTypes,
|
|
241
|
-
moduleType: 'file',
|
|
242
|
-
namedImports: [resolversTypeName],
|
|
243
|
-
emitLegacyCommonJSImports,
|
|
244
|
-
importExtension,
|
|
245
|
-
})}
|
|
246
|
-
${file.importLines.join('\n')}
|
|
247
|
-
export const ${resolversIdentifier}: ${resolversTypeName} = {
|
|
248
|
-
${queries}
|
|
249
|
-
${mutations}
|
|
250
|
-
${suscriptions}
|
|
251
|
-
${printObjectTypes(file.objectTypes)}
|
|
252
|
-
}`,
|
|
253
|
-
};
|
|
254
|
-
});
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
interface ObjectFieldMapping {
|
|
258
|
-
propertyName: string;
|
|
259
|
-
identifierName: string;
|
|
260
|
-
}
|
|
261
|
-
const printObjectMapping = ({
|
|
262
|
-
propertyName,
|
|
263
|
-
identifierName,
|
|
264
|
-
}: ObjectFieldMapping): string => `${propertyName}: ${identifierName}`;
|
|
265
|
-
|
|
266
|
-
type ObjectTypesMap = Record<string, string[]>;
|
|
267
|
-
const pushToObjectTypes = ({
|
|
268
|
-
objectTypes,
|
|
269
|
-
property,
|
|
270
|
-
value,
|
|
271
|
-
}: {
|
|
272
|
-
objectTypes: ObjectTypesMap;
|
|
273
|
-
property: string;
|
|
274
|
-
value: string;
|
|
275
|
-
}): void => {
|
|
276
|
-
if (!objectTypes[property]) {
|
|
277
|
-
objectTypes[property] = [];
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
objectTypes[property].push(value);
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
const printObjectTypes = (objectTypes: ObjectTypesMap): string => {
|
|
284
|
-
return Object.entries(objectTypes)
|
|
285
|
-
.map(([property, values]) => {
|
|
286
|
-
if (values.length === 1) {
|
|
287
|
-
return `${property}: ${values[0]}`;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const spreadedValueString = values
|
|
291
|
-
.map((value) => `...${value}`)
|
|
292
|
-
.join(',');
|
|
293
|
-
return `${property}: { ${spreadedValueString} }`;
|
|
294
|
-
})
|
|
295
|
-
.join(',\n');
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* countBaseIdentifiersUsage
|
|
300
|
-
*
|
|
301
|
-
* function to count how many of the same identifier is used across all files
|
|
302
|
-
*/
|
|
303
|
-
const countBaseIdentifiersUsage = (
|
|
304
|
-
files: GenerateResolverFilesContext['result']['files']
|
|
305
|
-
): Record<string, number> => {
|
|
306
|
-
return Object.entries(files).reduce<Record<string, number>>(
|
|
307
|
-
(res, [_filepath, file]) => {
|
|
308
|
-
if (file.__filetype === 'file') {
|
|
309
|
-
return res;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const identifier = makeNormalizedResolverNameVariableCompatible(
|
|
313
|
-
file.meta.normalizedResolverName.base
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
if (!res[identifier]) {
|
|
317
|
-
res[identifier] = 0;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
res[identifier]++;
|
|
321
|
-
|
|
322
|
-
return res;
|
|
323
|
-
},
|
|
324
|
-
{}
|
|
325
|
-
);
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* makeNormalizedResolverNameVariableCompatible
|
|
330
|
-
* @description Function to replace `-` and `.` in a string with underscore to be used as a variable name
|
|
331
|
-
*
|
|
332
|
-
* Note: this is to make sure the resolver name is a valid variable name because we use it in resolvers.generated.ts
|
|
333
|
-
* However, this naive implementation means there could be a duplicated variable name if a mix of kebab-case and snake_case is used.
|
|
334
|
-
* e.g. `user-by-account-name` and `user_by_account_name` will both be normalized to `user_by_account_name`
|
|
335
|
-
*
|
|
336
|
-
* If users report this issue. We can try another approach.
|
|
337
|
-
* I'm banking my slim hope in humanity that no codebase is so chaotic that it uses both kebab-case and snake_case.
|
|
338
|
-
*/
|
|
339
|
-
const makeNormalizedResolverNameVariableCompatible = (
|
|
340
|
-
identifier: string
|
|
341
|
-
): string => {
|
|
342
|
-
return identifier.replace(/[-.]/g, '_');
|
|
343
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { SyntaxKind, type SourceFile } from 'ts-morph';
|
|
2
|
-
import type { EnumResolverFile } from './types.js';
|
|
3
|
-
import { getVariableStatementWithExpectedIdentifier } from './getVariableStatementWithExpectedIdentifier.js';
|
|
4
|
-
|
|
5
|
-
export const ensureEnumTypeResolversAreGenerated = (
|
|
6
|
-
sourceFile: SourceFile,
|
|
7
|
-
resolverFile: EnumResolverFile
|
|
8
|
-
): void => {
|
|
9
|
-
const { variableStatement } = getVariableStatementWithExpectedIdentifier(
|
|
10
|
-
sourceFile,
|
|
11
|
-
resolverFile
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
if (!variableStatement) {
|
|
15
|
-
throw new Error(
|
|
16
|
-
'Missing variableStatement in ensureEnumTypeResolversAreGenerated.'
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const allowedValuesMap = resolverFile.meta.allowedValues.reduce<
|
|
21
|
-
Record<string, { implemented: boolean }>
|
|
22
|
-
>((res, allowedValue) => {
|
|
23
|
-
res[allowedValue] = { implemented: false };
|
|
24
|
-
return res;
|
|
25
|
-
}, {});
|
|
26
|
-
|
|
27
|
-
// Mark allowed value as implemented if found
|
|
28
|
-
variableStatement
|
|
29
|
-
.getDescendantsOfKind(SyntaxKind.PropertyAssignment)
|
|
30
|
-
.forEach((propertyAssignment) => {
|
|
31
|
-
const propertyName = propertyAssignment.getName();
|
|
32
|
-
if (allowedValuesMap[propertyName]) {
|
|
33
|
-
allowedValuesMap[propertyName].implemented = true;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// Add unimplemented allowed values
|
|
38
|
-
Object.entries(allowedValuesMap).forEach(
|
|
39
|
-
([allowedValue, { implemented }]) => {
|
|
40
|
-
if (!implemented) {
|
|
41
|
-
variableStatement
|
|
42
|
-
.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)[0]
|
|
43
|
-
.addPropertyAssignment({
|
|
44
|
-
name: allowedValue,
|
|
45
|
-
initializer: `'${allowedValue}'`,
|
|
46
|
-
});
|
|
47
|
-
resolverFile.filesystem.contentUpdated = true;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
);
|
|
51
|
-
};
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { addResolverMainFiles } from './addResolverMainFiles.js';
|
|
2
|
-
import { postProcessFiles } from './postProcessFiles.js';
|
|
3
|
-
import { handleGraphQLRootObjectTypeField } from './handleGraphQLRootObjectTypeField.js';
|
|
4
|
-
import { handleGraphQLObjectType } from './handleGraphQLObjectType.js';
|
|
5
|
-
import { handleGraphQLUnionType } from './handleGraphQLUnionType.js';
|
|
6
|
-
import { handleGraphQLScalarType } from './handleGraphQLScalarType.js';
|
|
7
|
-
import { handleGraphQLInterfaceType } from './handleGraphQLInterfaceType.js';
|
|
8
|
-
import { handleGraphQLEnumType } from './handleGraphQLEnumType.js';
|
|
9
|
-
import { visitNamedType } from './visitNamedType.js';
|
|
10
|
-
import type { GenerateResolverFilesContext } from './types.js';
|
|
11
|
-
|
|
12
|
-
export const generateResolverFiles = (
|
|
13
|
-
ctx: GenerateResolverFilesContext
|
|
14
|
-
): void => {
|
|
15
|
-
// Query
|
|
16
|
-
Object.values(
|
|
17
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.query
|
|
18
|
-
).forEach((details) => {
|
|
19
|
-
visitNamedType(
|
|
20
|
-
{
|
|
21
|
-
...details,
|
|
22
|
-
belongsToRootObject: 'Query',
|
|
23
|
-
visitor: handleGraphQLRootObjectTypeField,
|
|
24
|
-
},
|
|
25
|
-
ctx
|
|
26
|
-
);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// Mutation
|
|
30
|
-
Object.values(
|
|
31
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.mutation
|
|
32
|
-
).forEach((details) => {
|
|
33
|
-
visitNamedType(
|
|
34
|
-
{
|
|
35
|
-
...details,
|
|
36
|
-
belongsToRootObject: 'Mutation',
|
|
37
|
-
visitor: handleGraphQLRootObjectTypeField,
|
|
38
|
-
},
|
|
39
|
-
ctx
|
|
40
|
-
);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Subscription
|
|
44
|
-
Object.values(
|
|
45
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.subscription
|
|
46
|
-
).forEach((details) => {
|
|
47
|
-
visitNamedType(
|
|
48
|
-
{
|
|
49
|
-
...details,
|
|
50
|
-
belongsToRootObject: 'Subscription',
|
|
51
|
-
visitor: handleGraphQLRootObjectTypeField,
|
|
52
|
-
},
|
|
53
|
-
ctx
|
|
54
|
-
);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Object
|
|
58
|
-
Object.values(
|
|
59
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.object
|
|
60
|
-
).forEach((objectsByModules) => {
|
|
61
|
-
Object.values(objectsByModules).forEach((details) => {
|
|
62
|
-
visitNamedType(
|
|
63
|
-
{
|
|
64
|
-
...details,
|
|
65
|
-
belongsToRootObject: null,
|
|
66
|
-
visitor: (baseParams, prev_ctx) =>
|
|
67
|
-
handleGraphQLObjectType(
|
|
68
|
-
{
|
|
69
|
-
...baseParams,
|
|
70
|
-
fieldsToPick: details.fieldsToPick,
|
|
71
|
-
},
|
|
72
|
-
prev_ctx
|
|
73
|
-
),
|
|
74
|
-
},
|
|
75
|
-
ctx
|
|
76
|
-
);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Scalar
|
|
81
|
-
Object.values(
|
|
82
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.scalar
|
|
83
|
-
).forEach((details) => {
|
|
84
|
-
visitNamedType(
|
|
85
|
-
{
|
|
86
|
-
...details,
|
|
87
|
-
belongsToRootObject: null,
|
|
88
|
-
visitor: handleGraphQLScalarType,
|
|
89
|
-
},
|
|
90
|
-
ctx
|
|
91
|
-
);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Interface
|
|
95
|
-
Object.values(
|
|
96
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.interface
|
|
97
|
-
).forEach((details) => {
|
|
98
|
-
visitNamedType(
|
|
99
|
-
{
|
|
100
|
-
...details,
|
|
101
|
-
belongsToRootObject: null,
|
|
102
|
-
visitor: handleGraphQLInterfaceType,
|
|
103
|
-
},
|
|
104
|
-
ctx
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Union
|
|
109
|
-
Object.values(
|
|
110
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.union
|
|
111
|
-
).forEach((details) => {
|
|
112
|
-
visitNamedType(
|
|
113
|
-
{
|
|
114
|
-
...details,
|
|
115
|
-
belongsToRootObject: null,
|
|
116
|
-
visitor: handleGraphQLUnionType,
|
|
117
|
-
},
|
|
118
|
-
ctx
|
|
119
|
-
);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// Enum
|
|
123
|
-
Object.values(
|
|
124
|
-
ctx.config.parsedGraphQLSchemaMeta.userDefinedSchemaTypeMap.enum
|
|
125
|
-
).forEach((details) => {
|
|
126
|
-
visitNamedType(
|
|
127
|
-
{
|
|
128
|
-
...details,
|
|
129
|
-
belongsToRootObject: null,
|
|
130
|
-
visitor: (baseParams, prev_ctx) =>
|
|
131
|
-
handleGraphQLEnumType(
|
|
132
|
-
{
|
|
133
|
-
...baseParams,
|
|
134
|
-
allowedValues: details.allowedValues,
|
|
135
|
-
},
|
|
136
|
-
prev_ctx
|
|
137
|
-
),
|
|
138
|
-
},
|
|
139
|
-
ctx
|
|
140
|
-
);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Post process generated files (could be existing files or files to be generated)
|
|
144
|
-
postProcessFiles(ctx);
|
|
145
|
-
|
|
146
|
-
// Put all resolvers into barrel file/s (or main file/s)
|
|
147
|
-
addResolverMainFiles(ctx);
|
|
148
|
-
};
|