@eddeee888/gcg-typescript-resolver-files 0.16.0 → 0.18.0

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 (287) hide show
  1. package/CHANGELOG.md +816 -0
  2. package/DEVELOPMENT.md +49 -0
  3. package/LICENSE +21 -0
  4. package/README.md +3 -3
  5. package/{src → dist}/addVirtualTypesFileToTsMorphProject/addVirtualTypesFileToTsMorphProject.d.ts +2 -2
  6. package/{src → dist}/addVirtualTypesFileToTsMorphProject/addVirtualTypesFileToTsMorphProject.js +11 -17
  7. package/dist/addVirtualTypesFileToTsMorphProject/index.d.ts +1 -0
  8. package/dist/addVirtualTypesFileToTsMorphProject/index.js +1 -0
  9. package/{src → dist}/defineConfig.d.ts +1 -1
  10. package/{src → dist}/defineConfig.js +4 -10
  11. package/{src → dist}/generateResolverFiles/addExternalResolverImport.d.ts +1 -1
  12. package/{src → dist}/generateResolverFiles/addExternalResolverImport.js +3 -8
  13. package/{src → dist}/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.d.ts +1 -1
  14. package/{src → dist}/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.js +9 -14
  15. package/{src → dist}/generateResolverFiles/addResolverMainFiles.d.ts +1 -1
  16. package/{src → dist}/generateResolverFiles/addResolverMainFiles.js +11 -17
  17. package/{src → dist}/generateResolverFiles/ensureEnumTypeResolversAreGenerated.d.ts +1 -1
  18. package/{src → dist}/generateResolverFiles/ensureEnumTypeResolversAreGenerated.js +6 -11
  19. package/{src → dist}/generateResolverFiles/generateResolverFiles.d.ts +1 -1
  20. package/dist/generateResolverFiles/generateResolverFiles.js +87 -0
  21. package/{src → dist}/generateResolverFiles/getImportStatementWithExpectedNamedImport.d.ts +1 -1
  22. package/dist/generateResolverFiles/getImportStatementWithExpectedNamedImport.js +14 -0
  23. package/{src → dist}/generateResolverFiles/getVariableStatementWithExpectedIdentifier.d.ts +1 -1
  24. package/{src → dist}/generateResolverFiles/getVariableStatementWithExpectedIdentifier.js +1 -6
  25. package/{src → dist}/generateResolverFiles/handleGraphQLEnumType.d.ts +1 -1
  26. package/{src → dist}/generateResolverFiles/handleGraphQLEnumType.js +6 -11
  27. package/{src → dist}/generateResolverFiles/handleGraphQLInterfaceType.d.ts +1 -1
  28. package/{src → dist}/generateResolverFiles/handleGraphQLInterfaceType.js +6 -11
  29. package/{src → dist}/generateResolverFiles/handleGraphQLObjectType.d.ts +1 -1
  30. package/{src → dist}/generateResolverFiles/handleGraphQLObjectType.js +8 -14
  31. package/dist/generateResolverFiles/handleGraphQLRootObjectTypeField.d.ts +3 -0
  32. package/{src → dist}/generateResolverFiles/handleGraphQLRootObjectTypeField.js +8 -13
  33. package/{src → dist}/generateResolverFiles/handleGraphQLScalarType.d.ts +1 -1
  34. package/{src → dist}/generateResolverFiles/handleGraphQLScalarType.js +6 -11
  35. package/{src → dist}/generateResolverFiles/handleGraphQLUnionType.d.ts +1 -1
  36. package/{src → dist}/generateResolverFiles/handleGraphQLUnionType.js +5 -10
  37. package/dist/generateResolverFiles/index.d.ts +2 -0
  38. package/dist/generateResolverFiles/index.js +1 -0
  39. package/{src → dist}/generateResolverFiles/postProcessFiles.d.ts +1 -1
  40. package/{src → dist}/generateResolverFiles/postProcessFiles.js +24 -26
  41. package/{src → dist}/generateResolverFiles/types.d.ts +6 -6
  42. package/dist/generateResolverFiles/types.js +1 -0
  43. package/{src → dist}/generateResolverFiles/visitNamedType.d.ts +2 -2
  44. package/{src → dist}/generateResolverFiles/visitNamedType.js +3 -8
  45. package/dist/generateTypeDefsFiles/generateTypeDefsContent.js +7 -0
  46. package/{src → dist}/generateTypeDefsFiles/generateTypeDefsFiles.d.ts +3 -3
  47. package/{src → dist}/generateTypeDefsFiles/generateTypeDefsFiles.js +7 -13
  48. package/dist/generateTypeDefsFiles/index.d.ts +1 -0
  49. package/dist/generateTypeDefsFiles/index.js +1 -0
  50. package/{src → dist}/getGraphQLObjectTypeResolversToGenerate/getGraphQLObjectTypeResolversToGenerate.d.ts +3 -3
  51. package/{src → dist}/getGraphQLObjectTypeResolversToGenerate/getGraphQLObjectTypeResolversToGenerate.js +17 -22
  52. package/{src → dist}/getGraphQLObjectTypeResolversToGenerate/getNodePropertyMap.js +5 -10
  53. package/dist/getGraphQLObjectTypeResolversToGenerate/index.d.ts +1 -0
  54. package/dist/getGraphQLObjectTypeResolversToGenerate/index.js +1 -0
  55. package/dist/index.d.ts +3 -0
  56. package/dist/index.js +3 -0
  57. package/dist/normalizeAddConfigPath/index.d.ts +1 -0
  58. package/dist/normalizeAddConfigPath/index.js +1 -0
  59. package/{src → dist}/normalizeAddConfigPath/normalizeAddConfigPath.d.ts +1 -1
  60. package/{src → dist}/normalizeAddConfigPath/normalizeAddConfigPath.js +2 -8
  61. package/{src → dist}/parseGraphQLSchema/index.d.ts +2 -2
  62. package/dist/parseGraphQLSchema/index.js +1 -0
  63. package/{src → dist}/parseGraphQLSchema/normalizeResolverName.d.ts +1 -1
  64. package/{src → dist}/parseGraphQLSchema/normalizeResolverName.js +1 -6
  65. package/{src → dist}/parseGraphQLSchema/parseGraphQLSchema.d.ts +5 -5
  66. package/{src → dist}/parseGraphQLSchema/parseGraphQLSchema.js +43 -50
  67. package/{src → dist}/parseGraphQLSchema/parseLocationForOutputDir.d.ts +2 -2
  68. package/{src → dist}/parseGraphQLSchema/parseLocationForOutputDir.js +4 -10
  69. package/dist/parseSources/index.d.ts +1 -0
  70. package/dist/parseSources/index.js +1 -0
  71. package/{src → dist}/parseSources/parseSources.d.ts +1 -1
  72. package/{src → dist}/parseSources/parseSources.js +2 -7
  73. package/{src → dist}/parseTypeMappers/collectTypeMappersFromSourceFile.d.ts +2 -2
  74. package/{src → dist}/parseTypeMappers/collectTypeMappersFromSourceFile.js +15 -21
  75. package/dist/parseTypeMappers/index.d.ts +1 -0
  76. package/dist/parseTypeMappers/index.js +1 -0
  77. package/{src → dist}/parseTypeMappers/parseTypeMappers.d.ts +2 -2
  78. package/dist/parseTypeMappers/parseTypeMappers.js +20 -0
  79. package/{src → dist}/preset.d.ts +1 -1
  80. package/dist/preset.js +214 -0
  81. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  82. package/dist/utils/cwd.js +7 -0
  83. package/dist/utils/fmt.js +15 -0
  84. package/dist/utils/index.d.ts +12 -0
  85. package/dist/utils/index.js +12 -0
  86. package/{src → dist}/utils/isMatchResolverNamePattern.js +3 -9
  87. package/dist/utils/isNativeNamedType.js +13 -0
  88. package/dist/utils/isRootObjectType.js +3 -0
  89. package/{src → dist}/utils/isWhitelistedModule.js +1 -6
  90. package/{src → dist}/utils/logger.d.ts +1 -1
  91. package/dist/utils/logger.js +13 -0
  92. package/dist/utils/normalizeImportExtension.js +9 -0
  93. package/dist/utils/normalizeRelativePath.js +6 -0
  94. package/{src → dist}/utils/parseLocationForWhitelistedModule.d.ts +1 -1
  95. package/dist/utils/parseLocationForWhitelistedModule.js +17 -0
  96. package/{src → dist}/utils/printImportLine.d.ts +1 -1
  97. package/{src → dist}/utils/printImportLine.js +3 -7
  98. package/dist/utils/relativeModulePath.js +6 -0
  99. package/dist/validateAndMergeParsedConfigs/index.d.ts +1 -0
  100. package/dist/validateAndMergeParsedConfigs/index.js +1 -0
  101. package/{src → dist}/validateAndMergeParsedConfigs/validateAndMergeParsedConfigs.d.ts +2 -2
  102. package/{src → dist}/validateAndMergeParsedConfigs/validateAndMergeParsedConfigs.js +16 -13
  103. package/dist/validatePresetConfig/index.d.ts +1 -0
  104. package/dist/validatePresetConfig/index.js +1 -0
  105. package/{src → dist}/validatePresetConfig/validatePresetConfig.d.ts +2 -2
  106. package/{src → dist}/validatePresetConfig/validatePresetConfig.js +29 -36
  107. package/eslint.config.mjs +22 -0
  108. package/package.json +25 -18
  109. package/project.json +8 -0
  110. package/src/addVirtualTypesFileToTsMorphProject/addVirtualTypesFileToTsMorphProject.ts +109 -0
  111. package/src/addVirtualTypesFileToTsMorphProject/index.ts +1 -0
  112. package/src/defineConfig.spec.ts +76 -0
  113. package/src/defineConfig.ts +37 -0
  114. package/src/generateResolverFiles/addExternalResolverImport.ts +185 -0
  115. package/src/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.spec.ts +1174 -0
  116. package/src/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.ts +144 -0
  117. package/src/generateResolverFiles/addResolverMainFiles.ts +343 -0
  118. package/src/generateResolverFiles/ensureEnumTypeResolversAreGenerated.ts +51 -0
  119. package/src/generateResolverFiles/generateResolverFiles.ts +148 -0
  120. package/src/generateResolverFiles/getImportStatementWithExpectedNamedImport.spec.ts +127 -0
  121. package/src/generateResolverFiles/getImportStatementWithExpectedNamedImport.ts +25 -0
  122. package/src/generateResolverFiles/getVariableStatementWithExpectedIdentifier.spec.ts +147 -0
  123. package/src/generateResolverFiles/getVariableStatementWithExpectedIdentifier.ts +34 -0
  124. package/src/generateResolverFiles/handleGraphQLEnumType.ts +100 -0
  125. package/src/generateResolverFiles/handleGraphQLInterfaceType.ts +70 -0
  126. package/src/generateResolverFiles/handleGraphQLObjectType.ts +171 -0
  127. package/src/generateResolverFiles/handleGraphQLRootObjectTypeField.ts +105 -0
  128. package/src/generateResolverFiles/handleGraphQLScalarType.ts +81 -0
  129. package/src/generateResolverFiles/handleGraphQLUnionType.ts +68 -0
  130. package/src/generateResolverFiles/index.ts +2 -0
  131. package/src/generateResolverFiles/postProcessFiles.ts +287 -0
  132. package/src/generateResolverFiles/types.ts +203 -0
  133. package/src/generateResolverFiles/visitNamedType.ts +66 -0
  134. package/src/generateTypeDefsFiles/generateTypeDefsContent.ts +15 -0
  135. package/src/generateTypeDefsFiles/generateTypeDefsFiles.ts +100 -0
  136. package/src/generateTypeDefsFiles/index.ts +1 -0
  137. package/src/getGraphQLObjectTypeResolversToGenerate/getGraphQLObjectTypeResolversToGenerate.ts +361 -0
  138. package/src/getGraphQLObjectTypeResolversToGenerate/getNodePropertyMap.spec.ts +115 -0
  139. package/src/getGraphQLObjectTypeResolversToGenerate/getNodePropertyMap.ts +88 -0
  140. package/src/getGraphQLObjectTypeResolversToGenerate/index.ts +1 -0
  141. package/src/index.ts +3 -0
  142. package/src/normalizeAddConfigPath/index.ts +1 -0
  143. package/src/normalizeAddConfigPath/normalizeAddConfigPath.ts +29 -0
  144. package/src/parseGraphQLSchema/index.ts +2 -0
  145. package/src/parseGraphQLSchema/normalizeResolverName.ts +28 -0
  146. package/src/parseGraphQLSchema/parseGraphQLSchema.ts +531 -0
  147. package/src/parseGraphQLSchema/parseLocationForOutputDir.ts +76 -0
  148. package/src/parseSources/index.ts +1 -0
  149. package/src/parseSources/parseSources.ts +83 -0
  150. package/src/parseTypeMappers/collectTypeMappersFromSourceFile.spec.ts +789 -0
  151. package/src/parseTypeMappers/collectTypeMappersFromSourceFile.ts +197 -0
  152. package/src/parseTypeMappers/index.ts +1 -0
  153. package/src/parseTypeMappers/parseTypeMappers.ts +75 -0
  154. package/src/preset.ts +317 -0
  155. package/src/utils/cwd.ts +8 -0
  156. package/src/utils/fmt.ts +16 -0
  157. package/src/utils/index.ts +12 -0
  158. package/src/utils/isMatchResolverNamePattern.ts +27 -0
  159. package/src/utils/isNativeNamedType.ts +21 -0
  160. package/src/utils/isRootObjectType.ts +8 -0
  161. package/src/utils/isWhitelistedModule.spec.ts +71 -0
  162. package/src/utils/isWhitelistedModule.ts +21 -0
  163. package/src/utils/logger.ts +14 -0
  164. package/src/utils/normalizeImportExtension.spec.ts +42 -0
  165. package/src/utils/normalizeImportExtension.ts +16 -0
  166. package/src/utils/normalizeRelativePath.ts +6 -0
  167. package/src/utils/parseLocationForWhitelistedModule.spec.ts +130 -0
  168. package/src/utils/parseLocationForWhitelistedModule.ts +38 -0
  169. package/src/utils/printImportLine.spec.ts +150 -0
  170. package/src/utils/printImportLine.ts +78 -0
  171. package/src/utils/relativeModulePath.ts +7 -0
  172. package/src/validateAndMergeParsedConfigs/index.ts +1 -0
  173. package/src/validateAndMergeParsedConfigs/validateAndMergeParsedConfigs.spec.ts +211 -0
  174. package/src/validateAndMergeParsedConfigs/validateAndMergeParsedConfigs.ts +92 -0
  175. package/src/validatePresetConfig/index.ts +1 -0
  176. package/src/validatePresetConfig/validatePresetConfig.spec.ts +706 -0
  177. package/src/validatePresetConfig/validatePresetConfig.ts +571 -0
  178. package/tsconfig.json +14 -0
  179. package/tsconfig.lib.json +18 -0
  180. package/tsconfig.spec.json +20 -0
  181. package/vite.config.ts +24 -0
  182. package/src/addVirtualTypesFileToTsMorphProject/addVirtualTypesFileToTsMorphProject.js.map +0 -1
  183. package/src/addVirtualTypesFileToTsMorphProject/index.d.ts +0 -1
  184. package/src/addVirtualTypesFileToTsMorphProject/index.js +0 -5
  185. package/src/addVirtualTypesFileToTsMorphProject/index.js.map +0 -1
  186. package/src/defineConfig.js.map +0 -1
  187. package/src/generateResolverFiles/addExternalResolverImport.js.map +0 -1
  188. package/src/generateResolverFiles/addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.js.map +0 -1
  189. package/src/generateResolverFiles/addResolverMainFiles.js.map +0 -1
  190. package/src/generateResolverFiles/ensureEnumTypeResolversAreGenerated.js.map +0 -1
  191. package/src/generateResolverFiles/generateResolverFiles.js +0 -54
  192. package/src/generateResolverFiles/generateResolverFiles.js.map +0 -1
  193. package/src/generateResolverFiles/getImportStatementWithExpectedNamedImport.js +0 -20
  194. package/src/generateResolverFiles/getImportStatementWithExpectedNamedImport.js.map +0 -1
  195. package/src/generateResolverFiles/getVariableStatementWithExpectedIdentifier.js.map +0 -1
  196. package/src/generateResolverFiles/handleGraphQLEnumType.js.map +0 -1
  197. package/src/generateResolverFiles/handleGraphQLInterfaceType.js.map +0 -1
  198. package/src/generateResolverFiles/handleGraphQLObjectType.js.map +0 -1
  199. package/src/generateResolverFiles/handleGraphQLRootObjectTypeField.d.ts +0 -3
  200. package/src/generateResolverFiles/handleGraphQLRootObjectTypeField.js.map +0 -1
  201. package/src/generateResolverFiles/handleGraphQLScalarType.js.map +0 -1
  202. package/src/generateResolverFiles/handleGraphQLUnionType.js.map +0 -1
  203. package/src/generateResolverFiles/index.d.ts +0 -2
  204. package/src/generateResolverFiles/index.js +0 -6
  205. package/src/generateResolverFiles/index.js.map +0 -1
  206. package/src/generateResolverFiles/postProcessFiles.js.map +0 -1
  207. package/src/generateResolverFiles/types.js +0 -3
  208. package/src/generateResolverFiles/types.js.map +0 -1
  209. package/src/generateResolverFiles/visitNamedType.js.map +0 -1
  210. package/src/generateTypeDefsFiles/generateTypeDefsContent.js +0 -12
  211. package/src/generateTypeDefsFiles/generateTypeDefsContent.js.map +0 -1
  212. package/src/generateTypeDefsFiles/generateTypeDefsFiles.js.map +0 -1
  213. package/src/generateTypeDefsFiles/index.d.ts +0 -1
  214. package/src/generateTypeDefsFiles/index.js +0 -5
  215. package/src/generateTypeDefsFiles/index.js.map +0 -1
  216. package/src/getGraphQLObjectTypeResolversToGenerate/getGraphQLObjectTypeResolversToGenerate.js.map +0 -1
  217. package/src/getGraphQLObjectTypeResolversToGenerate/getNodePropertyMap.js.map +0 -1
  218. package/src/getGraphQLObjectTypeResolversToGenerate/index.d.ts +0 -1
  219. package/src/getGraphQLObjectTypeResolversToGenerate/index.js +0 -5
  220. package/src/getGraphQLObjectTypeResolversToGenerate/index.js.map +0 -1
  221. package/src/index.d.ts +0 -3
  222. package/src/index.js +0 -10
  223. package/src/index.js.map +0 -1
  224. package/src/normalizeAddConfigPath/index.d.ts +0 -1
  225. package/src/normalizeAddConfigPath/index.js +0 -5
  226. package/src/normalizeAddConfigPath/index.js.map +0 -1
  227. package/src/normalizeAddConfigPath/normalizeAddConfigPath.js.map +0 -1
  228. package/src/parseGraphQLSchema/index.js +0 -5
  229. package/src/parseGraphQLSchema/index.js.map +0 -1
  230. package/src/parseGraphQLSchema/normalizeResolverName.js.map +0 -1
  231. package/src/parseGraphQLSchema/parseGraphQLSchema.js.map +0 -1
  232. package/src/parseGraphQLSchema/parseLocationForOutputDir.js.map +0 -1
  233. package/src/parseSources/index.d.ts +0 -1
  234. package/src/parseSources/index.js +0 -5
  235. package/src/parseSources/index.js.map +0 -1
  236. package/src/parseSources/parseSources.js.map +0 -1
  237. package/src/parseTypeMappers/collectTypeMappersFromSourceFile.js.map +0 -1
  238. package/src/parseTypeMappers/index.d.ts +0 -1
  239. package/src/parseTypeMappers/index.js +0 -5
  240. package/src/parseTypeMappers/index.js.map +0 -1
  241. package/src/parseTypeMappers/parseTypeMappers.js +0 -26
  242. package/src/parseTypeMappers/parseTypeMappers.js.map +0 -1
  243. package/src/preset.js +0 -214
  244. package/src/preset.js.map +0 -1
  245. package/src/utils/cwd.js +0 -13
  246. package/src/utils/cwd.js.map +0 -1
  247. package/src/utils/fmt.js +0 -19
  248. package/src/utils/fmt.js.map +0 -1
  249. package/src/utils/index.d.ts +0 -12
  250. package/src/utils/index.js +0 -16
  251. package/src/utils/index.js.map +0 -1
  252. package/src/utils/isMatchResolverNamePattern.js.map +0 -1
  253. package/src/utils/isNativeNamedType.js +0 -18
  254. package/src/utils/isNativeNamedType.js.map +0 -1
  255. package/src/utils/isRootObjectType.js +0 -8
  256. package/src/utils/isRootObjectType.js.map +0 -1
  257. package/src/utils/isWhitelistedModule.js.map +0 -1
  258. package/src/utils/logger.js +0 -17
  259. package/src/utils/logger.js.map +0 -1
  260. package/src/utils/normalizeImportExtension.js +0 -13
  261. package/src/utils/normalizeImportExtension.js.map +0 -1
  262. package/src/utils/normalizeRelativePath.js +0 -11
  263. package/src/utils/normalizeRelativePath.js.map +0 -1
  264. package/src/utils/parseLocationForWhitelistedModule.js +0 -22
  265. package/src/utils/parseLocationForWhitelistedModule.js.map +0 -1
  266. package/src/utils/printImportLine.js.map +0 -1
  267. package/src/utils/relativeModulePath.js +0 -12
  268. package/src/utils/relativeModulePath.js.map +0 -1
  269. package/src/validateAndMergeParsedConfigs/index.d.ts +0 -1
  270. package/src/validateAndMergeParsedConfigs/index.js +0 -5
  271. package/src/validateAndMergeParsedConfigs/index.js.map +0 -1
  272. package/src/validateAndMergeParsedConfigs/validateAndMergeParsedConfigs.js.map +0 -1
  273. package/src/validatePresetConfig/index.d.ts +0 -1
  274. package/src/validatePresetConfig/index.js +0 -5
  275. package/src/validatePresetConfig/index.js.map +0 -1
  276. package/src/validatePresetConfig/validatePresetConfig.js.map +0 -1
  277. /package/{src → dist}/generateTypeDefsFiles/generateTypeDefsContent.d.ts +0 -0
  278. /package/{src → dist}/getGraphQLObjectTypeResolversToGenerate/getNodePropertyMap.d.ts +0 -0
  279. /package/{src → dist}/utils/cwd.d.ts +0 -0
  280. /package/{src → dist}/utils/fmt.d.ts +0 -0
  281. /package/{src → dist}/utils/isMatchResolverNamePattern.d.ts +0 -0
  282. /package/{src → dist}/utils/isNativeNamedType.d.ts +0 -0
  283. /package/{src → dist}/utils/isRootObjectType.d.ts +0 -0
  284. /package/{src → dist}/utils/isWhitelistedModule.d.ts +0 -0
  285. /package/{src → dist}/utils/normalizeImportExtension.d.ts +0 -0
  286. /package/{src → dist}/utils/normalizeRelativePath.d.ts +0 -0
  287. /package/{src → dist}/utils/relativeModulePath.d.ts +0 -0
@@ -0,0 +1,1174 @@
1
+ import * as path from 'path';
2
+ import { Project } from 'ts-morph';
3
+ import {
4
+ type AddedPropertyAssignmentNodes,
5
+ addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented,
6
+ } from './addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented.js';
7
+ import type { ObjectTypeFile } from './types';
8
+
9
+ const createFilePath = (filePath: string): string =>
10
+ path.join('/path/', filePath);
11
+
12
+ describe('addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented() - mode: smart', () => {
13
+ it('adds missing field resolvers if needed', () => {
14
+ const project = new Project();
15
+ project.createSourceFile(
16
+ createFilePath('user.mappers.ts'),
17
+ `export interface UserMapper {
18
+ id: number;
19
+ firstName: string;
20
+ lastName: string;
21
+ role: 'ADMIN' | 'USER';
22
+ createdAt: Date;
23
+ }`
24
+ );
25
+ project.createSourceFile(
26
+ createFilePath('types.generated.ts'),
27
+ `
28
+ import { UserMapper } from './user.mappers';
29
+ export type Maybe<T> = T | null;
30
+ export type InputMaybe<T> = Maybe<T>;
31
+ export type Exact<T extends { [key: string]: unknown }> = {
32
+ [K in keyof T]: T[K];
33
+ };
34
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
35
+ [SubKey in K]?: Maybe<T[SubKey]>;
36
+ };
37
+ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {
38
+ [SubKey in K]: Maybe<T[SubKey]>;
39
+ };
40
+ /** All built-in and custom scalars, mapped to their actual values */
41
+ export type Scalars = {
42
+ ID: string;
43
+ String: string;
44
+ Boolean: boolean;
45
+ Int: number;
46
+ Float: number;
47
+ DateTime: Date | string;
48
+ };
49
+
50
+ export type Query = {
51
+ __typename: 'Query';
52
+ me?: Maybe<User>;
53
+ };
54
+
55
+ export type User = {
56
+ __typename: 'User';
57
+ accountGitHub?: Maybe<Scalars['String']>;
58
+ accountGoogle?: Maybe<Scalars['String']>;
59
+ createdAt: Scalars['DateTime'];
60
+ fullName: Scalars['String'];
61
+ id: Scalars['ID'];
62
+ role: UserRole;
63
+ };
64
+
65
+ export type UserRole = 'ADMIN' | 'USER';
66
+
67
+ export type ResolverTypeWrapper<T> = Promise<T> | T;
68
+
69
+ export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
70
+ resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
71
+ };
72
+ export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
73
+ | ResolverFn<TResult, TParent, TContext, TArgs>
74
+ | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
75
+
76
+ export type ResolverFn<TResult, TParent, TContext, TArgs> = (
77
+ parent: TParent,
78
+ args: TArgs,
79
+ context: TContext,
80
+ info: any
81
+ ) => Promise<TResult> | TResult;
82
+
83
+ /** Mapping between all available schema types and the resolvers types */
84
+ export type ResolversTypes = {
85
+ DateTime: ResolverTypeWrapper<Scalars['DateTime']>;
86
+ Query: ResolverTypeWrapper<{}>;
87
+ User: ResolverTypeWrapper<UserMapper>;
88
+ String: ResolverTypeWrapper<Scalars['String']>;
89
+ ID: ResolverTypeWrapper<Scalars['ID']>;
90
+ UserRole: UserRole;
91
+ Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
92
+ };
93
+
94
+ /** Mapping between all available schema types and the resolvers parents */
95
+ export type ResolversParentTypes = {
96
+ DateTime: Scalars['DateTime'];
97
+ Query: {};
98
+ User: UserMapper;
99
+ String: Scalars['String'];
100
+ ID: Scalars['ID'];
101
+ Boolean: Scalars['Boolean'];
102
+ };
103
+
104
+ export type UserResolvers<
105
+ ContextType = any,
106
+ ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']
107
+ > = {
108
+ accountGitHub?: Resolver<
109
+ Maybe<ResolversTypes['String']>,
110
+ ParentType,
111
+ ContextType
112
+ >;
113
+ accountGoogle?: Resolver<
114
+ Maybe<ResolversTypes['String']>,
115
+ ParentType,
116
+ ContextType
117
+ >;
118
+ createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
119
+ fullName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
120
+ id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
121
+ role?: Resolver<ResolversTypes['UserRole'], ParentType, ContextType>;
122
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
123
+ };
124
+ `
125
+ );
126
+
127
+ const addedPropertyAssignmentNodes: AddedPropertyAssignmentNodes = {};
128
+ const sourceFile = project.createSourceFile(
129
+ createFilePath('User.ts'),
130
+ `import type { UserResolvers } from './types.generated';
131
+ export const User: UserResolvers = {
132
+ /* Implement logic here */
133
+ };`
134
+ );
135
+ const resolverFile: ObjectTypeFile = {
136
+ __filetype: 'objectType',
137
+ content: '',
138
+ mainImportIdentifier: 'User',
139
+ filesystem: {
140
+ type: 'filesystem',
141
+ contentUpdated: false,
142
+ },
143
+ meta: {
144
+ moduleName: 'user',
145
+ relativePathFromBaseToModule: ['user'],
146
+ normalizedResolverName: {
147
+ base: 'User',
148
+ withModule: 'user.User',
149
+ },
150
+ resolverTypeImportDeclaration: '',
151
+ variableStatement: '',
152
+ resolverType: {
153
+ baseImport: 'UserResolvers',
154
+ final: 'UserResolvers',
155
+ otherVariants: [],
156
+ },
157
+ resolversToGenerate: {
158
+ id: {
159
+ resolverName: 'id',
160
+ resolverDeclaration: `({ id }) => id`,
161
+ },
162
+ accountGitHub: {
163
+ resolverName: 'accountGitHub',
164
+ resolverDeclaration: `({ accountGitHub }) => accountGitHub`,
165
+ },
166
+ accountGoogle: {
167
+ resolverName: 'accountGoogle',
168
+ resolverDeclaration: `({ accountGoogle }) => accountGoogle`,
169
+ },
170
+ fullName: {
171
+ resolverName: 'fullName',
172
+ resolverDeclaration: `({ fullName }) => fullName`,
173
+ },
174
+ },
175
+ },
176
+ };
177
+ addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented({
178
+ mode: 'smart',
179
+ addedPropertyAssignmentNodes,
180
+ sourceFile,
181
+ resolverFile,
182
+ });
183
+
184
+ // This is `/path/User.ts` file. We target it this way because the path on windows is different from linux
185
+ const file = Object.values(addedPropertyAssignmentNodes)[0];
186
+
187
+ const addedNode1 = file[4];
188
+ expect(addedNode1.__toBeRemoved).toBe(true);
189
+ expect(addedNode1.node.getText()).toBe('id: ({ id }) => id');
190
+
191
+ const addedNode2 = file[5];
192
+ expect(addedNode2.__toBeRemoved).toBe(true);
193
+ expect(addedNode2.node.getText()).toBe(
194
+ 'accountGitHub: ({ accountGitHub }) => accountGitHub'
195
+ );
196
+
197
+ const addedNode3 = file[6];
198
+ expect(addedNode3.__toBeRemoved).toBe(true);
199
+ expect(addedNode3.node.getText()).toBe(
200
+ 'accountGoogle: ({ accountGoogle }) => accountGoogle'
201
+ );
202
+
203
+ const addedNode4 = file[7];
204
+ expect(addedNode4.__toBeRemoved).toBe(true);
205
+ expect(addedNode4.node.getText()).toBe(
206
+ 'fullName: ({ fullName }) => fullName'
207
+ );
208
+
209
+ expect(sourceFile.getText()).toMatchInlineSnapshot(`
210
+ "import type { UserResolvers } from './types.generated';
211
+ export const User: UserResolvers = {
212
+ /* Implement logic here */
213
+ id: ({ id }) => id,
214
+ accountGitHub: ({ accountGitHub }) => accountGitHub,
215
+ accountGoogle: ({ accountGoogle }) => accountGoogle,
216
+ fullName: ({ fullName }) => fullName
217
+ };"
218
+ `);
219
+ });
220
+
221
+ it('adds does not add missing field resolvers if not needed i.e. resolversToGenerate is {}', () => {
222
+ const project = new Project();
223
+ project.createSourceFile(
224
+ createFilePath('user.mappers.ts'),
225
+ `export interface UserMapper {
226
+ id: number;
227
+ fullName: string;
228
+ role: 'ADMIN' | 'USER';
229
+ createdAt: Date;
230
+ }`
231
+ );
232
+ project.createSourceFile(
233
+ createFilePath('types.generated.ts'),
234
+ `
235
+ import { UserMapper } from './user.mappers';
236
+ export type Maybe<T> = T | null;
237
+ export type InputMaybe<T> = Maybe<T>;
238
+ export type Exact<T extends { [key: string]: unknown }> = {
239
+ [K in keyof T]: T[K];
240
+ };
241
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
242
+ [SubKey in K]?: Maybe<T[SubKey]>;
243
+ };
244
+ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {
245
+ [SubKey in K]: Maybe<T[SubKey]>;
246
+ };
247
+ /** All built-in and custom scalars, mapped to their actual values */
248
+ export type Scalars = {
249
+ ID: string;
250
+ String: string;
251
+ Boolean: boolean;
252
+ Int: number;
253
+ Float: number;
254
+ DateTime: Date | string;
255
+ };
256
+
257
+ export type Query = {
258
+ __typename: 'Query';
259
+ me?: Maybe<User>;
260
+ };
261
+
262
+ export type User = {
263
+ __typename: 'User';
264
+ accountGitHub?: Maybe<Scalars['String']>;
265
+ accountGoogle?: Maybe<Scalars['String']>;
266
+ createdAt: Scalars['DateTime'];
267
+ fullName: Scalars['String'];
268
+ id: Scalars['ID'];
269
+ role: UserRole;
270
+ };
271
+
272
+ export type UserRole = 'ADMIN' | 'USER';
273
+
274
+ export type ResolverTypeWrapper<T> = Promise<T> | T;
275
+
276
+ export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
277
+ resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
278
+ };
279
+ export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
280
+ | ResolverFn<TResult, TParent, TContext, TArgs>
281
+ | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
282
+
283
+ export type ResolverFn<TResult, TParent, TContext, TArgs> = (
284
+ parent: TParent,
285
+ args: TArgs,
286
+ context: TContext,
287
+ info: any
288
+ ) => Promise<TResult> | TResult;
289
+
290
+ /** Mapping between all available schema types and the resolvers types */
291
+ export type ResolversTypes = {
292
+ DateTime: ResolverTypeWrapper<Scalars['DateTime']>;
293
+ Query: ResolverTypeWrapper<{}>;
294
+ User: ResolverTypeWrapper<UserMapper>;
295
+ String: ResolverTypeWrapper<Scalars['String']>;
296
+ ID: ResolverTypeWrapper<Scalars['ID']>;
297
+ UserRole: UserRole;
298
+ Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
299
+ };
300
+
301
+ /** Mapping between all available schema types and the resolvers parents */
302
+ export type ResolversParentTypes = {
303
+ DateTime: Scalars['DateTime'];
304
+ Query: {};
305
+ User: UserMapper;
306
+ String: Scalars['String'];
307
+ ID: Scalars['ID'];
308
+ Boolean: Scalars['Boolean'];
309
+ };
310
+
311
+ export type UserResolvers<
312
+ ContextType = any,
313
+ ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']
314
+ > = {
315
+ accountGitHub?: Resolver<
316
+ Maybe<ResolversTypes['String']>,
317
+ ParentType,
318
+ ContextType
319
+ >;
320
+ accountGoogle?: Resolver<
321
+ Maybe<ResolversTypes['String']>,
322
+ ParentType,
323
+ ContextType
324
+ >;
325
+ createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
326
+ fullName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
327
+ id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
328
+ role?: Resolver<ResolversTypes['UserRole'], ParentType, ContextType>;
329
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
330
+ };
331
+ `
332
+ );
333
+
334
+ const addedPropertyAssignmentNodes: AddedPropertyAssignmentNodes = {};
335
+ const sourceFile = project.createSourceFile(
336
+ createFilePath('User.ts'),
337
+ `import type { UserResolvers } from './types.generated';
338
+ export const User: UserResolvers = {};`
339
+ );
340
+ const resolverFile: ObjectTypeFile = {
341
+ __filetype: 'objectType',
342
+ content: '',
343
+ mainImportIdentifier: 'User',
344
+ filesystem: {
345
+ type: 'filesystem',
346
+ contentUpdated: false,
347
+ },
348
+ meta: {
349
+ moduleName: 'user',
350
+ relativePathFromBaseToModule: ['user'],
351
+ normalizedResolverName: {
352
+ base: 'User',
353
+ withModule: 'user.User',
354
+ },
355
+ resolverTypeImportDeclaration: '',
356
+ variableStatement: '',
357
+ resolverType: {
358
+ baseImport: 'UserResolvers',
359
+ final: 'UserResolvers',
360
+ otherVariants: [],
361
+ },
362
+ resolversToGenerate: {},
363
+ },
364
+ };
365
+ addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented({
366
+ mode: 'smart',
367
+ addedPropertyAssignmentNodes,
368
+ sourceFile,
369
+ resolverFile,
370
+ });
371
+
372
+ // This is `/path/User.ts` file. We target it this way because the path on windows is different from linux
373
+ const file = Object.values(addedPropertyAssignmentNodes)[0];
374
+
375
+ expect(file).toEqual({});
376
+ expect(sourceFile.getText()).toMatchInlineSnapshot(`
377
+ "import type { UserResolvers } from './types.generated';
378
+ export const User: UserResolvers = {};"
379
+ `);
380
+ });
381
+
382
+ it('adds missing field resolvers, if necessary, when Mapper is a Class', () => {
383
+ const project = new Project();
384
+ project.createSourceFile(
385
+ createFilePath('user.mappers.ts'),
386
+ `export class UserMapper {
387
+ id: number;
388
+ firstName: string;
389
+ lastName: string;
390
+ role: 'ADMIN' | 'USER';
391
+ createdAt: Date;
392
+ }`
393
+ );
394
+ project.createSourceFile(
395
+ createFilePath('types.generated.ts'),
396
+ `
397
+ import { UserMapper } from './user.mappers';
398
+ export type Maybe<T> = T | null;
399
+ export type InputMaybe<T> = Maybe<T>;
400
+ export type Exact<T extends { [key: string]: unknown }> = {
401
+ [K in keyof T]: T[K];
402
+ };
403
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
404
+ [SubKey in K]?: Maybe<T[SubKey]>;
405
+ };
406
+ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {
407
+ [SubKey in K]: Maybe<T[SubKey]>;
408
+ };
409
+ /** All built-in and custom scalars, mapped to their actual values */
410
+ export type Scalars = {
411
+ ID: string;
412
+ String: string;
413
+ Boolean: boolean;
414
+ Int: number;
415
+ Float: number;
416
+ DateTime: Date | string;
417
+ };
418
+
419
+ export type Query = {
420
+ __typename: 'Query';
421
+ me?: Maybe<User>;
422
+ };
423
+
424
+ export type User = {
425
+ __typename: 'User';
426
+ accountGitHub?: Maybe<Scalars['String']>;
427
+ accountGoogle?: Maybe<Scalars['String']>;
428
+ createdAt: Scalars['DateTime'];
429
+ fullName: Scalars['String'];
430
+ id: Scalars['ID'];
431
+ role: UserRole;
432
+ };
433
+
434
+ export type UserRole = 'ADMIN' | 'USER';
435
+
436
+ export type ResolverTypeWrapper<T> = Promise<T> | T;
437
+
438
+ export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
439
+ resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
440
+ };
441
+ export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
442
+ | ResolverFn<TResult, TParent, TContext, TArgs>
443
+ | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
444
+
445
+ export type ResolverFn<TResult, TParent, TContext, TArgs> = (
446
+ parent: TParent,
447
+ args: TArgs,
448
+ context: TContext,
449
+ info: any
450
+ ) => Promise<TResult> | TResult;
451
+
452
+ /** Mapping between all available schema types and the resolvers types */
453
+ export type ResolversTypes = {
454
+ DateTime: ResolverTypeWrapper<Scalars['DateTime']>;
455
+ Query: ResolverTypeWrapper<{}>;
456
+ User: ResolverTypeWrapper<UserMapper>;
457
+ String: ResolverTypeWrapper<Scalars['String']>;
458
+ ID: ResolverTypeWrapper<Scalars['ID']>;
459
+ UserRole: UserRole;
460
+ Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
461
+ };
462
+
463
+ /** Mapping between all available schema types and the resolvers parents */
464
+ export type ResolversParentTypes = {
465
+ DateTime: Scalars['DateTime'];
466
+ Query: {};
467
+ User: UserMapper;
468
+ String: Scalars['String'];
469
+ ID: Scalars['ID'];
470
+ Boolean: Scalars['Boolean'];
471
+ };
472
+
473
+ export type UserResolvers<
474
+ ContextType = any,
475
+ ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']
476
+ > = {
477
+ accountGitHub?: Resolver<
478
+ Maybe<ResolversTypes['String']>,
479
+ ParentType,
480
+ ContextType
481
+ >;
482
+ accountGoogle?: Resolver<
483
+ Maybe<ResolversTypes['String']>,
484
+ ParentType,
485
+ ContextType
486
+ >;
487
+ createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
488
+ fullName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
489
+ id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
490
+ role?: Resolver<ResolversTypes['UserRole'], ParentType, ContextType>;
491
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
492
+ };
493
+ `
494
+ );
495
+
496
+ const sourceFile = project.createSourceFile(
497
+ createFilePath('User.ts'),
498
+ `import type { UserResolvers } from './types.generated';
499
+ export const User: UserResolvers = {
500
+ /* Implement logic here */
501
+ };`
502
+ );
503
+ const resolverFile: Parameters<
504
+ typeof addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented
505
+ >[0]['resolverFile'] = {
506
+ __filetype: 'objectType',
507
+ content: '',
508
+ filesystem: {
509
+ type: 'filesystem',
510
+ contentUpdated: false,
511
+ },
512
+ mainImportIdentifier: 'User',
513
+ meta: {
514
+ moduleName: 'user',
515
+ relativePathFromBaseToModule: ['user'],
516
+ normalizedResolverName: {
517
+ base: 'User',
518
+ withModule: 'user.User',
519
+ },
520
+ resolverTypeImportDeclaration: '',
521
+ variableStatement: '',
522
+ resolverType: {
523
+ baseImport: 'UserResolvers',
524
+ final: 'UserResolvers',
525
+ otherVariants: [],
526
+ },
527
+ resolversToGenerate: {
528
+ id: {
529
+ resolverName: 'id',
530
+ resolverDeclaration: `({ id }) => id`,
531
+ },
532
+ accountGitHub: {
533
+ resolverName: 'accountGitHub',
534
+ resolverDeclaration: `({ accountGitHub }) => accountGitHub`,
535
+ },
536
+ accountGoogle: {
537
+ resolverName: 'accountGoogle',
538
+ resolverDeclaration: `({ accountGoogle }) => accountGoogle`,
539
+ },
540
+ fullName: {
541
+ resolverName: 'fullName',
542
+ resolverDeclaration: `({ fullName }) => fullName`,
543
+ },
544
+ },
545
+ },
546
+ };
547
+
548
+ const addedPropertyAssignmentNodes: AddedPropertyAssignmentNodes = {};
549
+ addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented({
550
+ mode: 'smart',
551
+ addedPropertyAssignmentNodes,
552
+ sourceFile,
553
+ resolverFile,
554
+ });
555
+
556
+ // This is `/path/User.ts` file. We target it this way because the path on windows is different from linux
557
+ const file = Object.values(addedPropertyAssignmentNodes)[0];
558
+
559
+ const addedNode1 = file[4];
560
+ expect(addedNode1.__toBeRemoved).toBe(true);
561
+ expect(addedNode1.node.getText()).toBe('id: ({ id }) => id');
562
+
563
+ const addedNode2 = file[5];
564
+ expect(addedNode2.__toBeRemoved).toBe(true);
565
+ expect(addedNode2.node.getText()).toBe(
566
+ 'accountGitHub: ({ accountGitHub }) => accountGitHub'
567
+ );
568
+
569
+ const addedNode3 = file[6];
570
+ expect(addedNode3.__toBeRemoved).toBe(true);
571
+ expect(addedNode3.node.getText()).toBe(
572
+ 'accountGoogle: ({ accountGoogle }) => accountGoogle'
573
+ );
574
+
575
+ const addedNode4 = file[7];
576
+ expect(addedNode4.__toBeRemoved).toBe(true);
577
+ expect(addedNode4.node.getText()).toBe(
578
+ 'fullName: ({ fullName }) => fullName'
579
+ );
580
+
581
+ expect(sourceFile.getText()).toMatchInlineSnapshot(`
582
+ "import type { UserResolvers } from './types.generated';
583
+ export const User: UserResolvers = {
584
+ /* Implement logic here */
585
+ id: ({ id }) => id,
586
+ accountGitHub: ({ accountGitHub }) => accountGitHub,
587
+ accountGoogle: ({ accountGoogle }) => accountGoogle,
588
+ fullName: ({ fullName }) => fullName
589
+ };"
590
+ `);
591
+ });
592
+ });
593
+
594
+ describe('addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented() - mode: fast', () => {
595
+ it('adds missing field resolvers if needed', () => {
596
+ const project = new Project();
597
+ project.createSourceFile(
598
+ createFilePath('user.mappers.ts'),
599
+ `export interface UserMapper {
600
+ id: number;
601
+ firstName: string;
602
+ lastName: string;
603
+ role: 'ADMIN' | 'USER';
604
+ createdAt: Date;
605
+ }`
606
+ );
607
+ project.createSourceFile(
608
+ createFilePath('types.generated.ts'),
609
+ `
610
+ import { UserMapper } from './user.mappers';
611
+ export type Maybe<T> = T | null;
612
+ export type InputMaybe<T> = Maybe<T>;
613
+ export type Exact<T extends { [key: string]: unknown }> = {
614
+ [K in keyof T]: T[K];
615
+ };
616
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
617
+ [SubKey in K]?: Maybe<T[SubKey]>;
618
+ };
619
+ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {
620
+ [SubKey in K]: Maybe<T[SubKey]>;
621
+ };
622
+ /** All built-in and custom scalars, mapped to their actual values */
623
+ export type Scalars = {
624
+ ID: string;
625
+ String: string;
626
+ Boolean: boolean;
627
+ Int: number;
628
+ Float: number;
629
+ DateTime: Date | string;
630
+ };
631
+
632
+ export type Query = {
633
+ __typename: 'Query';
634
+ me?: Maybe<User>;
635
+ };
636
+
637
+ export type User = {
638
+ __typename: 'User';
639
+ accountGitHub?: Maybe<Scalars['String']>;
640
+ accountGoogle?: Maybe<Scalars['String']>;
641
+ createdAt: Scalars['DateTime'];
642
+ fullName: Scalars['String'];
643
+ id: Scalars['ID'];
644
+ role: UserRole;
645
+ };
646
+
647
+ export type UserRole = 'ADMIN' | 'USER';
648
+
649
+ export type ResolverTypeWrapper<T> = Promise<T> | T;
650
+
651
+ export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
652
+ resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
653
+ };
654
+ export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
655
+ | ResolverFn<TResult, TParent, TContext, TArgs>
656
+ | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
657
+
658
+ export type ResolverFn<TResult, TParent, TContext, TArgs> = (
659
+ parent: TParent,
660
+ args: TArgs,
661
+ context: TContext,
662
+ info: any
663
+ ) => Promise<TResult> | TResult;
664
+
665
+ /** Mapping between all available schema types and the resolvers types */
666
+ export type ResolversTypes = {
667
+ DateTime: ResolverTypeWrapper<Scalars['DateTime']>;
668
+ Query: ResolverTypeWrapper<{}>;
669
+ User: ResolverTypeWrapper<UserMapper>;
670
+ String: ResolverTypeWrapper<Scalars['String']>;
671
+ ID: ResolverTypeWrapper<Scalars['ID']>;
672
+ UserRole: UserRole;
673
+ Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
674
+ };
675
+
676
+ /** Mapping between all available schema types and the resolvers parents */
677
+ export type ResolversParentTypes = {
678
+ DateTime: Scalars['DateTime'];
679
+ Query: {};
680
+ User: UserMapper;
681
+ String: Scalars['String'];
682
+ ID: Scalars['ID'];
683
+ Boolean: Scalars['Boolean'];
684
+ };
685
+
686
+ export type UserResolvers<
687
+ ContextType = any,
688
+ ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']
689
+ > = {
690
+ accountGitHub?: Resolver<
691
+ Maybe<ResolversTypes['String']>,
692
+ ParentType,
693
+ ContextType
694
+ >;
695
+ accountGoogle?: Resolver<
696
+ Maybe<ResolversTypes['String']>,
697
+ ParentType,
698
+ ContextType
699
+ >;
700
+ createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
701
+ fullName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
702
+ id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
703
+ role?: Resolver<ResolversTypes['UserRole'], ParentType, ContextType>;
704
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
705
+ };
706
+ `
707
+ );
708
+
709
+ const addedPropertyAssignmentNodes: AddedPropertyAssignmentNodes = {};
710
+ const sourceFile = project.createSourceFile(
711
+ createFilePath('User.ts'),
712
+ `import type { UserResolvers } from './types.generated';
713
+ export const User: UserResolvers = {
714
+ /* Implement logic here */
715
+ };`
716
+ );
717
+ const resolverFile: ObjectTypeFile = {
718
+ __filetype: 'objectType',
719
+ content: '',
720
+ mainImportIdentifier: 'User',
721
+ filesystem: {
722
+ type: 'filesystem',
723
+ contentUpdated: false,
724
+ },
725
+ meta: {
726
+ moduleName: 'user',
727
+ relativePathFromBaseToModule: ['user'],
728
+ normalizedResolverName: {
729
+ base: 'User',
730
+ withModule: 'user.User',
731
+ },
732
+ resolverTypeImportDeclaration: '',
733
+ variableStatement: '',
734
+ resolverType: {
735
+ baseImport: 'UserResolvers',
736
+ final: 'UserResolvers',
737
+ otherVariants: [],
738
+ },
739
+ resolversToGenerate: {
740
+ id: {
741
+ resolverName: 'id',
742
+ resolverDeclaration: `({ id }) => id`,
743
+ },
744
+ accountGitHub: {
745
+ resolverName: 'accountGitHub',
746
+ resolverDeclaration: `({ accountGitHub }) => accountGitHub`,
747
+ },
748
+ accountGoogle: {
749
+ resolverName: 'accountGoogle',
750
+ resolverDeclaration: `({ accountGoogle }) => accountGoogle`,
751
+ },
752
+ fullName: {
753
+ resolverName: 'fullName',
754
+ resolverDeclaration: `({ fullName }) => fullName`,
755
+ },
756
+ },
757
+ },
758
+ };
759
+ addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented({
760
+ mode: 'fast',
761
+ addedPropertyAssignmentNodes,
762
+ sourceFile,
763
+ resolverFile,
764
+ });
765
+
766
+ // This is `/path/User.ts` file. We target it this way because the path on windows is different from linux
767
+ const file = Object.values(addedPropertyAssignmentNodes)[0];
768
+
769
+ const addedNode1 = file[4];
770
+ expect(addedNode1.__toBeRemoved).toBe(false);
771
+ expect(addedNode1.node.getText()).toBe('id: ({ id }) => id');
772
+
773
+ const addedNode2 = file[5];
774
+ expect(addedNode2.__toBeRemoved).toBe(false);
775
+ expect(addedNode2.node.getText()).toBe(
776
+ 'accountGitHub: ({ accountGitHub }) => accountGitHub'
777
+ );
778
+
779
+ const addedNode3 = file[6];
780
+ expect(addedNode3.__toBeRemoved).toBe(false);
781
+ expect(addedNode3.node.getText()).toBe(
782
+ 'accountGoogle: ({ accountGoogle }) => accountGoogle'
783
+ );
784
+
785
+ const addedNode4 = file[7];
786
+ expect(addedNode4.__toBeRemoved).toBe(false);
787
+ expect(addedNode4.node.getText()).toBe(
788
+ 'fullName: ({ fullName }) => fullName'
789
+ );
790
+
791
+ expect(sourceFile.getText()).toMatchInlineSnapshot(`
792
+ "import type { UserResolvers } from './types.generated';
793
+ export const User: UserResolvers = {
794
+ /* Implement logic here */
795
+ id: ({ id }) => id,
796
+ accountGitHub: ({ accountGitHub }) => accountGitHub,
797
+ accountGoogle: ({ accountGoogle }) => accountGoogle,
798
+ fullName: ({ fullName }) => fullName
799
+ };"
800
+ `);
801
+ });
802
+
803
+ it('adds does not add missing field resolvers if not needed i.e. resolversToGenerate is {}', () => {
804
+ const project = new Project();
805
+ project.createSourceFile(
806
+ createFilePath('user.mappers.ts'),
807
+ `export interface UserMapper {
808
+ id: number;
809
+ fullName: string;
810
+ role: 'ADMIN' | 'USER';
811
+ createdAt: Date;
812
+ }`
813
+ );
814
+ project.createSourceFile(
815
+ createFilePath('types.generated.ts'),
816
+ `
817
+ import { UserMapper } from './user.mappers';
818
+ export type Maybe<T> = T | null;
819
+ export type InputMaybe<T> = Maybe<T>;
820
+ export type Exact<T extends { [key: string]: unknown }> = {
821
+ [K in keyof T]: T[K];
822
+ };
823
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
824
+ [SubKey in K]?: Maybe<T[SubKey]>;
825
+ };
826
+ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {
827
+ [SubKey in K]: Maybe<T[SubKey]>;
828
+ };
829
+ /** All built-in and custom scalars, mapped to their actual values */
830
+ export type Scalars = {
831
+ ID: string;
832
+ String: string;
833
+ Boolean: boolean;
834
+ Int: number;
835
+ Float: number;
836
+ DateTime: Date | string;
837
+ };
838
+
839
+ export type Query = {
840
+ __typename: 'Query';
841
+ me?: Maybe<User>;
842
+ };
843
+
844
+ export type User = {
845
+ __typename: 'User';
846
+ accountGitHub?: Maybe<Scalars['String']>;
847
+ accountGoogle?: Maybe<Scalars['String']>;
848
+ createdAt: Scalars['DateTime'];
849
+ fullName: Scalars['String'];
850
+ id: Scalars['ID'];
851
+ role: UserRole;
852
+ };
853
+
854
+ export type UserRole = 'ADMIN' | 'USER';
855
+
856
+ export type ResolverTypeWrapper<T> = Promise<T> | T;
857
+
858
+ export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
859
+ resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
860
+ };
861
+ export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
862
+ | ResolverFn<TResult, TParent, TContext, TArgs>
863
+ | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
864
+
865
+ export type ResolverFn<TResult, TParent, TContext, TArgs> = (
866
+ parent: TParent,
867
+ args: TArgs,
868
+ context: TContext,
869
+ info: any
870
+ ) => Promise<TResult> | TResult;
871
+
872
+ /** Mapping between all available schema types and the resolvers types */
873
+ export type ResolversTypes = {
874
+ DateTime: ResolverTypeWrapper<Scalars['DateTime']>;
875
+ Query: ResolverTypeWrapper<{}>;
876
+ User: ResolverTypeWrapper<UserMapper>;
877
+ String: ResolverTypeWrapper<Scalars['String']>;
878
+ ID: ResolverTypeWrapper<Scalars['ID']>;
879
+ UserRole: UserRole;
880
+ Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
881
+ };
882
+
883
+ /** Mapping between all available schema types and the resolvers parents */
884
+ export type ResolversParentTypes = {
885
+ DateTime: Scalars['DateTime'];
886
+ Query: {};
887
+ User: UserMapper;
888
+ String: Scalars['String'];
889
+ ID: Scalars['ID'];
890
+ Boolean: Scalars['Boolean'];
891
+ };
892
+
893
+ export type UserResolvers<
894
+ ContextType = any,
895
+ ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']
896
+ > = {
897
+ accountGitHub?: Resolver<
898
+ Maybe<ResolversTypes['String']>,
899
+ ParentType,
900
+ ContextType
901
+ >;
902
+ accountGoogle?: Resolver<
903
+ Maybe<ResolversTypes['String']>,
904
+ ParentType,
905
+ ContextType
906
+ >;
907
+ createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
908
+ fullName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
909
+ id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
910
+ role?: Resolver<ResolversTypes['UserRole'], ParentType, ContextType>;
911
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
912
+ };
913
+ `
914
+ );
915
+
916
+ const addedPropertyAssignmentNodes: AddedPropertyAssignmentNodes = {};
917
+ const sourceFile = project.createSourceFile(
918
+ createFilePath('User.ts'),
919
+ `import type { UserResolvers } from './types.generated';
920
+ export const User: UserResolvers = {};`
921
+ );
922
+ const resolverFile: ObjectTypeFile = {
923
+ __filetype: 'objectType',
924
+ content: '',
925
+ mainImportIdentifier: 'User',
926
+ filesystem: {
927
+ type: 'filesystem',
928
+ contentUpdated: false,
929
+ },
930
+ meta: {
931
+ moduleName: 'user',
932
+ relativePathFromBaseToModule: ['user'],
933
+ normalizedResolverName: {
934
+ base: 'User',
935
+ withModule: 'user.User',
936
+ },
937
+ resolverTypeImportDeclaration: '',
938
+ variableStatement: '',
939
+ resolverType: {
940
+ baseImport: 'UserResolvers',
941
+ final: 'UserResolvers',
942
+ otherVariants: [],
943
+ },
944
+ resolversToGenerate: {},
945
+ },
946
+ };
947
+ addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented({
948
+ mode: 'fast',
949
+ addedPropertyAssignmentNodes,
950
+ sourceFile,
951
+ resolverFile,
952
+ });
953
+
954
+ // This is `/path/User.ts` file. We target it this way because the path on windows is different from linux
955
+ const file = Object.values(addedPropertyAssignmentNodes)[0];
956
+
957
+ expect(file).toEqual({});
958
+ expect(sourceFile.getText()).toMatchInlineSnapshot(`
959
+ "import type { UserResolvers } from './types.generated';
960
+ export const User: UserResolvers = {};"
961
+ `);
962
+ });
963
+
964
+ it('adds missing field resolvers, if necessary, when Mapper is a Class', () => {
965
+ const project = new Project();
966
+ project.createSourceFile(
967
+ createFilePath('user.mappers.ts'),
968
+ `export class UserMapper {
969
+ id: number;
970
+ firstName: string;
971
+ lastName: string;
972
+ role: 'ADMIN' | 'USER';
973
+ createdAt: Date;
974
+ }`
975
+ );
976
+ project.createSourceFile(
977
+ createFilePath('types.generated.ts'),
978
+ `
979
+ import { UserMapper } from './user.mappers';
980
+ export type Maybe<T> = T | null;
981
+ export type InputMaybe<T> = Maybe<T>;
982
+ export type Exact<T extends { [key: string]: unknown }> = {
983
+ [K in keyof T]: T[K];
984
+ };
985
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
986
+ [SubKey in K]?: Maybe<T[SubKey]>;
987
+ };
988
+ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {
989
+ [SubKey in K]: Maybe<T[SubKey]>;
990
+ };
991
+ /** All built-in and custom scalars, mapped to their actual values */
992
+ export type Scalars = {
993
+ ID: string;
994
+ String: string;
995
+ Boolean: boolean;
996
+ Int: number;
997
+ Float: number;
998
+ DateTime: Date | string;
999
+ };
1000
+
1001
+ export type Query = {
1002
+ __typename: 'Query';
1003
+ me?: Maybe<User>;
1004
+ };
1005
+
1006
+ export type User = {
1007
+ __typename: 'User';
1008
+ accountGitHub?: Maybe<Scalars['String']>;
1009
+ accountGoogle?: Maybe<Scalars['String']>;
1010
+ createdAt: Scalars['DateTime'];
1011
+ fullName: Scalars['String'];
1012
+ id: Scalars['ID'];
1013
+ role: UserRole;
1014
+ };
1015
+
1016
+ export type UserRole = 'ADMIN' | 'USER';
1017
+
1018
+ export type ResolverTypeWrapper<T> = Promise<T> | T;
1019
+
1020
+ export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
1021
+ resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
1022
+ };
1023
+ export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
1024
+ | ResolverFn<TResult, TParent, TContext, TArgs>
1025
+ | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
1026
+
1027
+ export type ResolverFn<TResult, TParent, TContext, TArgs> = (
1028
+ parent: TParent,
1029
+ args: TArgs,
1030
+ context: TContext,
1031
+ info: any
1032
+ ) => Promise<TResult> | TResult;
1033
+
1034
+ /** Mapping between all available schema types and the resolvers types */
1035
+ export type ResolversTypes = {
1036
+ DateTime: ResolverTypeWrapper<Scalars['DateTime']>;
1037
+ Query: ResolverTypeWrapper<{}>;
1038
+ User: ResolverTypeWrapper<UserMapper>;
1039
+ String: ResolverTypeWrapper<Scalars['String']>;
1040
+ ID: ResolverTypeWrapper<Scalars['ID']>;
1041
+ UserRole: UserRole;
1042
+ Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
1043
+ };
1044
+
1045
+ /** Mapping between all available schema types and the resolvers parents */
1046
+ export type ResolversParentTypes = {
1047
+ DateTime: Scalars['DateTime'];
1048
+ Query: {};
1049
+ User: UserMapper;
1050
+ String: Scalars['String'];
1051
+ ID: Scalars['ID'];
1052
+ Boolean: Scalars['Boolean'];
1053
+ };
1054
+
1055
+ export type UserResolvers<
1056
+ ContextType = any,
1057
+ ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']
1058
+ > = {
1059
+ accountGitHub?: Resolver<
1060
+ Maybe<ResolversTypes['String']>,
1061
+ ParentType,
1062
+ ContextType
1063
+ >;
1064
+ accountGoogle?: Resolver<
1065
+ Maybe<ResolversTypes['String']>,
1066
+ ParentType,
1067
+ ContextType
1068
+ >;
1069
+ createdAt?: Resolver<ResolversTypes['DateTime'], ParentType, ContextType>;
1070
+ fullName?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1071
+ id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
1072
+ role?: Resolver<ResolversTypes['UserRole'], ParentType, ContextType>;
1073
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
1074
+ };
1075
+ `
1076
+ );
1077
+
1078
+ const sourceFile = project.createSourceFile(
1079
+ createFilePath('User.ts'),
1080
+ `import type { UserResolvers } from './types.generated';
1081
+ export const User: UserResolvers = {
1082
+ /* Implement logic here */
1083
+ };`
1084
+ );
1085
+ const resolverFile: Parameters<
1086
+ typeof addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented
1087
+ >[0]['resolverFile'] = {
1088
+ __filetype: 'objectType',
1089
+ content: '',
1090
+ filesystem: {
1091
+ type: 'filesystem',
1092
+ contentUpdated: false,
1093
+ },
1094
+ mainImportIdentifier: 'User',
1095
+ meta: {
1096
+ moduleName: 'user',
1097
+ relativePathFromBaseToModule: ['user'],
1098
+ normalizedResolverName: {
1099
+ base: 'User',
1100
+ withModule: 'user.User',
1101
+ },
1102
+ resolverTypeImportDeclaration: '',
1103
+ variableStatement: '',
1104
+ resolverType: {
1105
+ baseImport: 'UserResolvers',
1106
+ final: 'UserResolvers',
1107
+ otherVariants: [],
1108
+ },
1109
+ resolversToGenerate: {
1110
+ id: {
1111
+ resolverName: 'id',
1112
+ resolverDeclaration: `({ id }) => id`,
1113
+ },
1114
+ accountGitHub: {
1115
+ resolverName: 'accountGitHub',
1116
+ resolverDeclaration: `({ accountGitHub }) => accountGitHub`,
1117
+ },
1118
+ accountGoogle: {
1119
+ resolverName: 'accountGoogle',
1120
+ resolverDeclaration: `({ accountGoogle }) => accountGoogle`,
1121
+ },
1122
+ fullName: {
1123
+ resolverName: 'fullName',
1124
+ resolverDeclaration: `({ fullName }) => fullName`,
1125
+ },
1126
+ },
1127
+ },
1128
+ };
1129
+
1130
+ const addedPropertyAssignmentNodes: AddedPropertyAssignmentNodes = {};
1131
+ addObjectTypeResolversPropertyAssignmentNodesIfNotImplemented({
1132
+ mode: 'fast',
1133
+ addedPropertyAssignmentNodes,
1134
+ sourceFile,
1135
+ resolverFile,
1136
+ });
1137
+
1138
+ // This is `/path/User.ts` file. We target it this way because the path on windows is different from linux
1139
+ const file = Object.values(addedPropertyAssignmentNodes)[0];
1140
+
1141
+ const addedNode1 = file[4];
1142
+ expect(addedNode1.__toBeRemoved).toBe(false);
1143
+ expect(addedNode1.node.getText()).toBe('id: ({ id }) => id');
1144
+
1145
+ const addedNode2 = file[5];
1146
+ expect(addedNode2.__toBeRemoved).toBe(false);
1147
+ expect(addedNode2.node.getText()).toBe(
1148
+ 'accountGitHub: ({ accountGitHub }) => accountGitHub'
1149
+ );
1150
+
1151
+ const addedNode3 = file[6];
1152
+ expect(addedNode3.__toBeRemoved).toBe(false);
1153
+ expect(addedNode3.node.getText()).toBe(
1154
+ 'accountGoogle: ({ accountGoogle }) => accountGoogle'
1155
+ );
1156
+
1157
+ const addedNode4 = file[7];
1158
+ expect(addedNode4.__toBeRemoved).toBe(false);
1159
+ expect(addedNode4.node.getText()).toBe(
1160
+ 'fullName: ({ fullName }) => fullName'
1161
+ );
1162
+
1163
+ expect(sourceFile.getText()).toMatchInlineSnapshot(`
1164
+ "import type { UserResolvers } from './types.generated';
1165
+ export const User: UserResolvers = {
1166
+ /* Implement logic here */
1167
+ id: ({ id }) => id,
1168
+ accountGitHub: ({ accountGitHub }) => accountGitHub,
1169
+ accountGoogle: ({ accountGoogle }) => accountGoogle,
1170
+ fullName: ({ fullName }) => fullName
1171
+ };"
1172
+ `);
1173
+ });
1174
+ });