joist-graphql-codegen 2.3.0-next.7 → 2.3.0-next.71

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 (167) hide show
  1. package/build/_virtual/_rolldown/runtime.cjs +23 -0
  2. package/build/generateEnumDetailResolvers.cjs +40 -0
  3. package/build/generateEnumDetailResolvers.cjs.map +1 -0
  4. package/build/generateEnumDetailResolvers.d.cts +8 -0
  5. package/build/generateEnumDetailResolvers.d.cts.map +1 -0
  6. package/build/generateEnumDetailResolvers.d.mts +8 -0
  7. package/build/generateEnumDetailResolvers.d.mts.map +1 -0
  8. package/build/generateEnumDetailResolvers.js +23 -23
  9. package/build/generateEnumDetailResolvers.js.map +1 -1
  10. package/build/generateEnumsGraphql.cjs +29 -0
  11. package/build/generateEnumsGraphql.cjs.map +1 -0
  12. package/build/generateEnumsGraphql.d.cts +8 -0
  13. package/build/generateEnumsGraphql.d.cts.map +1 -0
  14. package/build/generateEnumsGraphql.d.mts +8 -0
  15. package/build/generateEnumsGraphql.d.mts.map +1 -0
  16. package/build/generateEnumsGraphql.js +24 -27
  17. package/build/generateEnumsGraphql.js.map +1 -1
  18. package/build/generateGraphqlCodegen.cjs +54 -0
  19. package/build/generateGraphqlCodegen.cjs.map +1 -0
  20. package/build/generateGraphqlCodegen.d.cts +8 -0
  21. package/build/generateGraphqlCodegen.d.cts.map +1 -0
  22. package/build/generateGraphqlCodegen.d.mts +8 -0
  23. package/build/generateGraphqlCodegen.d.mts.map +1 -0
  24. package/build/generateGraphqlCodegen.js +28 -30
  25. package/build/generateGraphqlCodegen.js.map +1 -1
  26. package/build/generateGraphqlSchemaFiles.cjs +491 -0
  27. package/build/generateGraphqlSchemaFiles.cjs.map +1 -0
  28. package/build/{generateGraphqlSchemaFiles.d.ts → generateGraphqlSchemaFiles.d.cts} +6 -3
  29. package/build/generateGraphqlSchemaFiles.d.cts.map +1 -0
  30. package/build/generateGraphqlSchemaFiles.d.mts +15 -0
  31. package/build/generateGraphqlSchemaFiles.d.mts.map +1 -0
  32. package/build/generateGraphqlSchemaFiles.js +444 -286
  33. package/build/generateGraphqlSchemaFiles.js.map +1 -1
  34. package/build/generateObjectResolvers.cjs +70 -0
  35. package/build/generateObjectResolvers.cjs.map +1 -0
  36. package/build/{generateObjectResolvers.d.ts → generateObjectResolvers.d.cts} +5 -2
  37. package/build/generateObjectResolvers.d.cts.map +1 -0
  38. package/build/generateObjectResolvers.d.mts +17 -0
  39. package/build/generateObjectResolvers.d.mts.map +1 -0
  40. package/build/generateObjectResolvers.js +48 -38
  41. package/build/generateObjectResolvers.js.map +1 -1
  42. package/build/generateQueryPageResolvers.cjs +51 -0
  43. package/build/generateQueryPageResolvers.cjs.map +1 -0
  44. package/build/generateQueryPageResolvers.d.cts +8 -0
  45. package/build/generateQueryPageResolvers.d.cts.map +1 -0
  46. package/build/generateQueryPageResolvers.d.mts +8 -0
  47. package/build/generateQueryPageResolvers.d.mts.map +1 -0
  48. package/build/generateQueryPageResolvers.js +31 -35
  49. package/build/generateQueryPageResolvers.js.map +1 -1
  50. package/build/generateQueryResolvers.cjs +55 -0
  51. package/build/generateQueryResolvers.cjs.map +1 -0
  52. package/build/generateQueryResolvers.d.cts +10 -0
  53. package/build/generateQueryResolvers.d.cts.map +1 -0
  54. package/build/generateQueryResolvers.d.mts +10 -0
  55. package/build/generateQueryResolvers.d.mts.map +1 -0
  56. package/build/generateQueryResolvers.js +38 -36
  57. package/build/generateQueryResolvers.js.map +1 -1
  58. package/build/generateResolverUtils.cjs +36 -0
  59. package/build/generateResolverUtils.cjs.map +1 -0
  60. package/build/generateResolverUtils.d.cts +8 -0
  61. package/build/generateResolverUtils.d.cts.map +1 -0
  62. package/build/generateResolverUtils.d.mts +8 -0
  63. package/build/generateResolverUtils.d.mts.map +1 -0
  64. package/build/generateResolverUtils.js +25 -26
  65. package/build/generateResolverUtils.js.map +1 -1
  66. package/build/generateSaveResolvers.cjs +57 -0
  67. package/build/generateSaveResolvers.cjs.map +1 -0
  68. package/build/{generateSaveResolvers.d.ts → generateSaveResolvers.d.cts} +5 -2
  69. package/build/generateSaveResolvers.d.cts.map +1 -0
  70. package/build/generateSaveResolvers.d.mts +17 -0
  71. package/build/generateSaveResolvers.d.mts.map +1 -0
  72. package/build/generateSaveResolvers.js +39 -40
  73. package/build/generateSaveResolvers.js.map +1 -1
  74. package/build/graphqlUtils.cjs +160 -0
  75. package/build/graphqlUtils.cjs.map +1 -0
  76. package/build/graphqlUtils.d.cts +31 -0
  77. package/build/graphqlUtils.d.cts.map +1 -0
  78. package/build/graphqlUtils.d.mts +31 -0
  79. package/build/graphqlUtils.d.mts.map +1 -0
  80. package/build/graphqlUtils.js +120 -218
  81. package/build/graphqlUtils.js.map +1 -1
  82. package/build/history.cjs +25 -0
  83. package/build/history.cjs.map +1 -0
  84. package/build/history.d.cts +9 -0
  85. package/build/history.d.cts.map +1 -0
  86. package/build/history.d.mts +9 -0
  87. package/build/history.d.mts.map +1 -0
  88. package/build/history.js +17 -14
  89. package/build/history.js.map +1 -1
  90. package/build/index.cjs +57 -0
  91. package/build/index.cjs.map +1 -0
  92. package/build/index.d.cts +7 -0
  93. package/build/index.d.cts.map +1 -0
  94. package/build/index.d.mts +7 -0
  95. package/build/index.d.mts.map +1 -0
  96. package/build/index.js +48 -54
  97. package/build/index.js.map +1 -1
  98. package/build/testUtils.cjs +191 -0
  99. package/build/testUtils.cjs.map +1 -0
  100. package/build/testUtils.d.cts +20 -0
  101. package/build/testUtils.d.cts.map +1 -0
  102. package/build/testUtils.d.mts +20 -0
  103. package/build/testUtils.d.mts.map +1 -0
  104. package/build/testUtils.js +162 -158
  105. package/build/testUtils.js.map +1 -1
  106. package/build/utils.cjs +51 -0
  107. package/build/utils.cjs.map +1 -0
  108. package/build/utils.d.cts +16 -0
  109. package/build/utils.d.cts.map +1 -0
  110. package/build/utils.d.mts +16 -0
  111. package/build/utils.d.mts.map +1 -0
  112. package/build/utils.js +37 -49
  113. package/build/utils.js.map +1 -1
  114. package/package.json +33 -13
  115. package/build/generateEnumDetailResolvers.d.ts +0 -5
  116. package/build/generateEnumDetailResolvers.d.ts.map +0 -1
  117. package/build/generateEnumDetailResolvers.test.d.ts +0 -2
  118. package/build/generateEnumDetailResolvers.test.d.ts.map +0 -1
  119. package/build/generateEnumDetailResolvers.test.js +0 -34
  120. package/build/generateEnumDetailResolvers.test.js.map +0 -1
  121. package/build/generateEnumsGraphql.d.ts +0 -5
  122. package/build/generateEnumsGraphql.d.ts.map +0 -1
  123. package/build/generateGraphqlCodegen.d.ts +0 -5
  124. package/build/generateGraphqlCodegen.d.ts.map +0 -1
  125. package/build/generateGraphqlCodegen.test.d.ts +0 -2
  126. package/build/generateGraphqlCodegen.test.d.ts.map +0 -1
  127. package/build/generateGraphqlCodegen.test.js +0 -44
  128. package/build/generateGraphqlCodegen.test.js.map +0 -1
  129. package/build/generateGraphqlSchemaFiles.d.ts.map +0 -1
  130. package/build/generateGraphqlSchemaFiles.test.d.ts +0 -2
  131. package/build/generateGraphqlSchemaFiles.test.d.ts.map +0 -1
  132. package/build/generateGraphqlSchemaFiles.test.js +0 -1008
  133. package/build/generateGraphqlSchemaFiles.test.js.map +0 -1
  134. package/build/generateObjectResolvers.d.ts.map +0 -1
  135. package/build/generateQueryPageResolvers.d.ts +0 -5
  136. package/build/generateQueryPageResolvers.d.ts.map +0 -1
  137. package/build/generateQueryPageResolvers.test.d.ts +0 -2
  138. package/build/generateQueryPageResolvers.test.d.ts.map +0 -1
  139. package/build/generateQueryPageResolvers.test.js +0 -46
  140. package/build/generateQueryPageResolvers.test.js.map +0 -1
  141. package/build/generateQueryResolvers.d.ts +0 -7
  142. package/build/generateQueryResolvers.d.ts.map +0 -1
  143. package/build/generateQueryResolvers.test.d.ts +0 -2
  144. package/build/generateQueryResolvers.test.d.ts.map +0 -1
  145. package/build/generateQueryResolvers.test.js +0 -45
  146. package/build/generateQueryResolvers.test.js.map +0 -1
  147. package/build/generateResolverUtils.d.ts +0 -5
  148. package/build/generateResolverUtils.d.ts.map +0 -1
  149. package/build/generateResolverUtils.test.d.ts +0 -2
  150. package/build/generateResolverUtils.test.d.ts.map +0 -1
  151. package/build/generateResolverUtils.test.js +0 -53
  152. package/build/generateResolverUtils.test.js.map +0 -1
  153. package/build/generateSaveResolvers.d.ts.map +0 -1
  154. package/build/generateSaveResolvers.test.d.ts +0 -2
  155. package/build/generateSaveResolvers.test.d.ts.map +0 -1
  156. package/build/generateSaveResolvers.test.js +0 -49
  157. package/build/generateSaveResolvers.test.js.map +0 -1
  158. package/build/graphqlUtils.d.ts +0 -28
  159. package/build/graphqlUtils.d.ts.map +0 -1
  160. package/build/history.d.ts +0 -6
  161. package/build/history.d.ts.map +0 -1
  162. package/build/index.d.ts +0 -4
  163. package/build/index.d.ts.map +0 -1
  164. package/build/testUtils.d.ts +0 -25
  165. package/build/testUtils.d.ts.map +0 -1
  166. package/build/utils.d.ts +0 -13
  167. package/build/utils.d.ts.map +0 -1
@@ -0,0 +1,160 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
3
+ require("./utils.cjs");
4
+ require("joist-codegen");
5
+ let ts_poet = require("ts-poet");
6
+ let joist_utils = require("joist-utils");
7
+ let graphql = require("graphql");
8
+ let prettier = require("prettier");
9
+ prettier = require_runtime.__toESM(prettier, 1);
10
+ //#region src/graphqlUtils.ts
11
+ /** Given a `file` and `fields` to go in it (for potentially different objects), upserts into the existing types. */
12
+ async function upsertIntoFile(fs, file, fields) {
13
+ const byObjectName = (0, joist_utils.groupBy)(fields, (f) => f.objectName);
14
+ const existingDoc = parseOrNewEmptyDoc(await fs.load(file));
15
+ const newDocs = Object.entries(byObjectName).map(([objectName, fields]) => {
16
+ const [entry] = fields;
17
+ return [objectName, entry.objectType === "union" ? createUnionDoc(entry) : createFieldDoc(objectName, fields)];
18
+ });
19
+ const formatted = await formatGraphQL((0, graphql.print)(mergeDocs(existingDoc, newDocs)));
20
+ await fs.save(file, formatted);
21
+ }
22
+ let prettierPromise;
23
+ async function formatGraphQL(content) {
24
+ const prettierConfig = await (prettierPromise ??= (0, prettier.resolveConfig)("./"));
25
+ return prettier.default.format(content, {
26
+ parser: "graphql",
27
+ ...prettierConfig,
28
+ plugins: []
29
+ });
30
+ }
31
+ /**
32
+ * Creates a new AST DocumentNode for the given object + field definitions.
33
+ *
34
+ * This leverages `parse` to do the dirty work of taking an "easy for us to create"
35
+ * string of GraphQL SDL and turning it into a "pita to create by hand" AST
36
+ * of object / field / type / etc. nodes.
37
+ */
38
+ function createFieldDoc(objectName, fields) {
39
+ const [{ objectType }] = fields;
40
+ const type = objectType === "output" ? "type" : objectType;
41
+ const maybeArgs = (f) => f.argsString ? `(${f.argsString})` : "";
42
+ const source = `${fields.some((f) => f.extends) ? "extend " : ""}${type} ${objectName} {
43
+ ${fields.map((f) => `${f.fieldName}${maybeArgs(f)}: ${f.fieldType}`)}
44
+ }`;
45
+ return (0, graphql.parse)(source);
46
+ }
47
+ function createUnionDoc(union) {
48
+ const { objectName, types } = union;
49
+ return (0, graphql.parse)(`union ${objectName} = ${types.join(" | ")}`);
50
+ }
51
+ function parseOrNewEmptyDoc(content) {
52
+ return content ? (0, graphql.parse)(content) : newEmptyDocument();
53
+ }
54
+ function newEmptyDocument() {
55
+ return (0, graphql.visit)((0, graphql.parse)("type Foo"), { ObjectTypeDefinition() {
56
+ return null;
57
+ } });
58
+ }
59
+ /**
60
+ * Merges a given `newType` from `newDoc` into `existingDoc*.
61
+ *
62
+ * There are existing "merge schema" libraries/tools out there, but we want to be very purposeful
63
+ * about keeping the existing SDL and this is really not too bad because we're only stitching
64
+ * ~two levels of the AST (document -> objects and object -> fields).
65
+ *
66
+ * We also cheat by using `createNewDoc` to get ASTs of the new content, so we don't have
67
+ * to laboriously built up the ASTs by hand.
68
+ */
69
+ function mergeDocs(existingDoc, newDocs) {
70
+ return (0, graphql.visit)(existingDoc, {
71
+ Document(node) {
72
+ return {
73
+ ...node,
74
+ definitions: [...node.definitions, ...newDocs.filter(([objectType]) => {
75
+ return !node.definitions.some((d) => (d.kind === "ObjectTypeDefinition" || d.kind === "ObjectTypeExtension" || d.kind === "InputObjectTypeDefinition" || d.kind === "UnionTypeDefinition") && d.name.value === objectType);
76
+ }).flatMap(([, d]) => d.definitions)].sort(byOperationExtensionsFirst)
77
+ };
78
+ },
79
+ ObjectTypeDefinition(node) {
80
+ return mergeObjectTypeFields(node, newDocs);
81
+ },
82
+ ObjectTypeExtension(node) {
83
+ return mergeObjectTypeFields(node, newDocs);
84
+ },
85
+ InputObjectTypeDefinition(node) {
86
+ const found = newDocs.find(([objectType]) => node.name.value === objectType);
87
+ if (found) {
88
+ const [, newDoc] = found;
89
+ const existingFieldNames = (node.fields || []).map((f) => f.name.value);
90
+ const newObjectType = newDoc.definitions[0];
91
+ return {
92
+ ...node,
93
+ fields: [...node.fields || [], ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value))]
94
+ };
95
+ }
96
+ return node;
97
+ },
98
+ UnionTypeDefinition(node) {
99
+ const found = newDocs.find(([objectType]) => node.name.value === objectType);
100
+ if (found) {
101
+ const [, newDoc] = found;
102
+ const [definition] = newDoc.definitions;
103
+ return {
104
+ ...node,
105
+ types: definition.types
106
+ };
107
+ }
108
+ return node;
109
+ }
110
+ });
111
+ }
112
+ /** Merges generated fields into an existing `type` or `extend type`. */
113
+ function mergeObjectTypeFields(node, newDocs) {
114
+ const found = newDocs.find(([objectType]) => node.name.value === objectType);
115
+ if (found) {
116
+ const [, newDoc] = found;
117
+ const existingFieldNames = (node.fields || []).map((f) => f.name.value);
118
+ const newObjectType = newDoc.definitions[0];
119
+ return {
120
+ ...node,
121
+ fields: [...node.fields || [], ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value))]
122
+ };
123
+ }
124
+ return node;
125
+ }
126
+ /** Keeps the primary operation extensions at the top of generated schema files. */
127
+ function byOperationExtensionsFirst(a, b) {
128
+ return operationExtensionRank(a) - operationExtensionRank(b);
129
+ }
130
+ /** Returns the priority for placing generated operation extensions before types/inputs. */
131
+ function operationExtensionRank(definition) {
132
+ if (definition.kind === "ObjectTypeExtension" && definition.name.value === "Query") return 0;
133
+ if (definition.kind === "ObjectTypeExtension" && definition.name.value === "Mutation") return 1;
134
+ return 2;
135
+ }
136
+ function mapTypescriptTypeToGraphQLType(fieldName, type) {
137
+ if (type === "string") return "String";
138
+ else if (type === "boolean") return "Boolean";
139
+ else if (type === "number") return "Int";
140
+ else if (type === "bigint") return "BigInt";
141
+ else if (type instanceof ts_poet.Code) {
142
+ const rawType = type.toCodeString([]);
143
+ if (rawType.startsWith("Date")) return fieldName.endsWith("At") ? "DateTime" : "Date";
144
+ else if (rawType.startsWith("Temporal.ZonedDateTime")) return "DateTime";
145
+ else if (rawType.startsWith("Temporal.PlainDateTime")) return "DateTime";
146
+ else if (rawType.startsWith("Temporal.PlainDate")) return "Date";
147
+ else return;
148
+ } else if (type instanceof ts_poet.Import) return;
149
+ else return;
150
+ }
151
+ function isJsonbColumn(p) {
152
+ return p.fieldType === "Object" || p.fieldType instanceof ts_poet.Import;
153
+ }
154
+ //#endregion
155
+ exports.formatGraphQL = formatGraphQL;
156
+ exports.isJsonbColumn = isJsonbColumn;
157
+ exports.mapTypescriptTypeToGraphQLType = mapTypescriptTypeToGraphQLType;
158
+ exports.upsertIntoFile = upsertIntoFile;
159
+
160
+ //# sourceMappingURL=graphqlUtils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphqlUtils.cjs","names":["groupBy","print","resolveConfig","parse","visit","Code","Import"],"sources":["../src/graphqlUtils.ts"],"sourcesContent":["import {\n type DocumentNode,\n type InputObjectTypeDefinitionNode,\n type ObjectTypeDefinitionNode,\n type ObjectTypeExtensionNode,\n type UnionTypeDefinitionNode,\n parse,\n print,\n visit,\n} from \"graphql\";\nimport { type PrimitiveField, type PrimitiveTypescriptType } from \"joist-codegen\";\nimport { groupBy } from \"joist-utils\";\nimport prettier, { type Options, resolveConfig } from \"prettier\";\nimport { Code, Import } from \"ts-poet\";\n\nimport { type Fs } from \"./utils.ts\";\n\n/** A type for the fields we want to add to `*.graphql` files. */\nexport type GqlField = {\n file: string;\n objectType: \"input\" | \"output\";\n objectName: string;\n fieldName: string;\n fieldType: string;\n // Not a true AST, but just `foo: Bar, zaz: number`\n argsString?: string;\n extends?: boolean;\n};\n\nexport type GqlUnion = { file: string; objectName: string; objectType: \"union\"; types: string[] };\n\nexport type GqlEntry = GqlField | GqlUnion;\n\n/** Given a `file` and `fields` to go in it (for potentially different objects), upserts into the existing types. */\nexport async function upsertIntoFile(fs: Fs, file: string, fields: GqlEntry[]): Promise<void> {\n // Group the fields by each individual object (either input types or output types)\n const byObjectName = groupBy(fields, (f) => f.objectName);\n const existingDoc = parseOrNewEmptyDoc(await fs.load(file));\n\n // For each type, create a \"new\" / ideal definition that exactly matches the domain model\n const newDocs = Object.entries(byObjectName).map(([objectName, fields]) => {\n const [entry] = fields;\n return [\n objectName,\n entry.objectType === \"union\"\n ? createUnionDoc(entry as GqlUnion)\n : createFieldDoc(objectName, fields as GqlField[]),\n ] as [string, DocumentNode];\n });\n\n // Merge each `newDoc` object definition into the file's existing types\n const content = print(mergeDocs(existingDoc, newDocs));\n const formatted = await formatGraphQL(content);\n\n await fs.save(file, formatted);\n}\n\nlet prettierPromise: Promise<Options | null>;\n\nexport async function formatGraphQL(content: string): Promise<string> {\n const prettierConfig = await (prettierPromise ??= resolveConfig(\"./\"));\n return prettier.format(content, {\n parser: \"graphql\",\n ...prettierConfig,\n plugins: [],\n });\n}\n\n/**\n * Creates a new AST DocumentNode for the given object + field definitions.\n *\n * This leverages `parse` to do the dirty work of taking an \"easy for us to create\"\n * string of GraphQL SDL and turning it into a \"pita to create by hand\" AST\n * of object / field / type / etc. nodes.\n */\nfunction createFieldDoc(objectName: string, fields: GqlField[]): DocumentNode {\n const [{ objectType }] = fields;\n const type = objectType === \"output\" ? \"type\" : objectType;\n const maybeArgs = (f: GqlField) => (f.argsString ? `(${f.argsString})` : \"\");\n const maybeExtends = fields.some((f: GqlField) => f.extends) ? \"extend \" : \"\";\n const source = `${maybeExtends}${type} ${objectName} {\n ${fields.map((f) => `${f.fieldName}${maybeArgs(f)}: ${f.fieldType}`)}\n }`;\n return parse(source);\n}\n\nfunction createUnionDoc(union: GqlUnion): DocumentNode {\n const { objectName, types } = union;\n return parse(`union ${objectName} = ${types.join(\" | \")}`);\n}\n\nfunction parseOrNewEmptyDoc(content: string | undefined): DocumentNode {\n return content ? parse(content) : newEmptyDocument();\n}\n\nfunction newEmptyDocument(): DocumentNode {\n // I can't figure out how to `parse(\"\")`, i.e. create an empty DocumentNode, so pretend\n // to make a `type Foo` but then throw it away so that DocumentNode ends up empty.\n return visit(parse(\"type Foo\"), {\n ObjectTypeDefinition() {\n return null;\n },\n });\n}\n\n/**\n * Merges a given `newType` from `newDoc` into `existingDoc*.\n *\n * There are existing \"merge schema\" libraries/tools out there, but we want to be very purposeful\n * about keeping the existing SDL and this is really not too bad because we're only stitching\n * ~two levels of the AST (document -> objects and object -> fields).\n *\n * We also cheat by using `createNewDoc` to get ASTs of the new content, so we don't have\n * to laboriously built up the ASTs by hand.\n */\nfunction mergeDocs(existingDoc: DocumentNode, newDocs: [string, DocumentNode][]): DocumentNode {\n // Now merged the two\n return visit(existingDoc, {\n // If the `type Book` does not exist yet, add it\n Document(node) {\n return {\n ...node,\n definitions: [\n ...node.definitions,\n ...newDocs\n .filter(([objectType]) => {\n return !node.definitions.some(\n (d) =>\n (d.kind === \"ObjectTypeDefinition\" ||\n d.kind === \"ObjectTypeExtension\" ||\n d.kind === \"InputObjectTypeDefinition\" ||\n d.kind === \"UnionTypeDefinition\") &&\n d.name.value === objectType,\n );\n })\n .flatMap(([, d]) => d.definitions),\n ].sort(byOperationExtensionsFirst),\n };\n },\n\n // If fields don't exist yet, add them\n ObjectTypeDefinition(node) {\n return mergeObjectTypeFields(node, newDocs);\n },\n\n ObjectTypeExtension(node) {\n return mergeObjectTypeFields(node, newDocs);\n },\n\n // If fields don't exist yet, add them\n InputObjectTypeDefinition(node) {\n const found = newDocs.find(([objectType]) => node.name.value === objectType);\n if (found) {\n const [, newDoc] = found;\n const existingFieldNames = (node.fields || []).map((f) => f.name.value);\n const newObjectType = newDoc.definitions[0] as InputObjectTypeDefinitionNode;\n return {\n ...node,\n fields: [\n ...(node.fields || []),\n ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value)),\n ],\n };\n }\n return node;\n },\n\n UnionTypeDefinition(node) {\n const found = newDocs.find(([objectType]) => node.name.value === objectType);\n if (found) {\n const [, newDoc] = found;\n const [definition] = newDoc.definitions as UnionTypeDefinitionNode[];\n return {\n ...node,\n types: definition.types,\n };\n }\n return node;\n },\n });\n}\n\n/** Merges generated fields into an existing `type` or `extend type`. */\nfunction mergeObjectTypeFields<T extends ObjectTypeDefinitionNode | ObjectTypeExtensionNode>(\n node: T,\n newDocs: [string, DocumentNode][],\n): T {\n const found = newDocs.find(([objectType]) => node.name.value === objectType);\n if (found) {\n const [, newDoc] = found;\n const existingFieldNames = (node.fields || []).map((f) => f.name.value);\n const newObjectType = newDoc.definitions[0] as ObjectTypeDefinitionNode;\n return {\n ...node,\n fields: [\n ...(node.fields || []),\n ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value)),\n ],\n };\n }\n return node;\n}\n\n/** Keeps the primary operation extensions at the top of generated schema files. */\nfunction byOperationExtensionsFirst(\n a: DocumentNode[\"definitions\"][number],\n b: DocumentNode[\"definitions\"][number],\n): number {\n return operationExtensionRank(a) - operationExtensionRank(b);\n}\n\n/** Returns the priority for placing generated operation extensions before types/inputs. */\nfunction operationExtensionRank(definition: DocumentNode[\"definitions\"][number]): number {\n if (definition.kind === \"ObjectTypeExtension\" && definition.name.value === \"Query\") return 0;\n if (definition.kind === \"ObjectTypeExtension\" && definition.name.value === \"Mutation\") return 1;\n return 2;\n}\n\nexport type GraphQLType = \"BigInt\" | \"Boolean\" | \"String\" | \"Int\" | \"Date\" | \"DateTime\" | string;\n\nexport type SupportedTypescriptTypes = Exclude<PrimitiveTypescriptType, \"Object\" | Import>;\n\nexport function mapTypescriptTypeToGraphQLType(\n fieldName: string,\n type: PrimitiveTypescriptType | Import | Code,\n): GraphQLType | undefined {\n if (type === \"string\") {\n return \"String\";\n } else if (type === \"boolean\") {\n return \"Boolean\";\n } else if (type === \"number\") {\n return \"Int\";\n } else if (type === \"bigint\") {\n return \"BigInt\";\n } else if (type instanceof Code) {\n const rawType = type.toCodeString([]);\n if (rawType.startsWith(\"Date\")) {\n // Legacy javascript Date doesn't have different `date` vs. `datetime` types but GraphQL does\n // so lean on the `..._at` suffix convention to know \"DateTime\".\n return fieldName.endsWith(\"At\") ? \"DateTime\" : \"Date\";\n } else if (rawType.startsWith(\"Temporal.ZonedDateTime\")) {\n return \"DateTime\";\n } else if (rawType.startsWith(\"Temporal.PlainDateTime\")) {\n return \"DateTime\";\n } else if (rawType.startsWith(\"Temporal.PlainDate\")) {\n return \"Date\";\n } else {\n // If this is a fancy import like a superstruct/something, we can't guess what it will be in GraphQL\n return undefined;\n }\n } else if (type instanceof Import) {\n // If this is a fancy import like a superstruct/something, we can't guess what it will be in GraphQL\n return undefined;\n } else {\n // Anything else like `jsonb` (which shows up as `Object`) is also unlikely to be a valid\n // GraphQL type, and doing things like `someField: Object` w/o predefined scalar types will\n // cause GraphQL parsing errors.\n return undefined;\n }\n}\n\nexport function isJsonbColumn(p: PrimitiveField) {\n return p.fieldType === \"Object\" || p.fieldType instanceof Import;\n}\n"],"mappings":";;;;;;;;;;;AAkCA,eAAsB,eAAe,IAAQ,MAAc,QAAmC;CAE5F,MAAM,gBAAA,GAAeA,YAAAA,QAAAA,CAAQ,SAAS,MAAM,EAAE,UAAU;CACxD,MAAM,cAAc,mBAAmB,MAAM,GAAG,KAAK,IAAI,CAAC;CAG1D,MAAM,UAAU,OAAO,QAAQ,YAAY,CAAC,CAAC,KAAK,CAAC,YAAY,YAAY;EACzE,MAAM,CAAC,SAAS;EAChB,OAAO,CACL,YACA,MAAM,eAAe,UACjB,eAAe,KAAiB,IAChC,eAAe,YAAY,MAAoB,CACrD;CACF,CAAC;CAID,MAAM,YAAY,MAAM,eAAA,GADRC,QAAAA,MAAAA,CAAM,UAAU,aAAa,OAAO,CACR,CAAC;CAE7C,MAAM,GAAG,KAAK,MAAM,SAAS;AAC/B;AAEA,IAAI;AAEJ,eAAsB,cAAc,SAAkC;CACpE,MAAM,iBAAiB,OAAO,qBAAA,GAAoBC,SAAAA,cAAAA,CAAc,IAAI;CACpE,OAAO,SAAA,QAAS,OAAO,SAAS;EAC9B,QAAQ;EACR,GAAG;EACH,SAAS,CAAC;CACZ,CAAC;AACH;;;;;;;;AASA,SAAS,eAAe,YAAoB,QAAkC;CAC5E,MAAM,CAAC,EAAE,gBAAgB;CACzB,MAAM,OAAO,eAAe,WAAW,SAAS;CAChD,MAAM,aAAa,MAAiB,EAAE,aAAa,IAAI,EAAE,WAAW,KAAK;CAEzE,MAAM,SAAS,GADM,OAAO,MAAM,MAAgB,EAAE,OAAO,IAAI,YAAY,KAC1C,KAAK,GAAG,WAAW;MAChD,OAAO,KAAK,MAAM,GAAG,EAAE,YAAY,UAAU,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE;;CAEvE,QAAA,GAAOC,QAAAA,MAAAA,CAAM,MAAM;AACrB;AAEA,SAAS,eAAe,OAA+B;CACrD,MAAM,EAAE,YAAY,UAAU;CAC9B,QAAA,GAAOA,QAAAA,MAAAA,CAAM,SAAS,WAAW,KAAK,MAAM,KAAK,KAAK,GAAG;AAC3D;AAEA,SAAS,mBAAmB,SAA2C;CACrE,OAAO,WAAA,GAAUA,QAAAA,MAAAA,CAAM,OAAO,IAAI,iBAAiB;AACrD;AAEA,SAAS,mBAAiC;CAGxC,QAAA,GAAOC,QAAAA,MAAAA,EAAAA,GAAMD,QAAAA,MAAAA,CAAM,UAAU,GAAG,EAC9B,uBAAuB;EACrB,OAAO;CACT,EACF,CAAC;AACH;;;;;;;;;;;AAYA,SAAS,UAAU,aAA2B,SAAiD;CAE7F,QAAA,GAAOC,QAAAA,MAAAA,CAAM,aAAa;EAExB,SAAS,MAAM;GACb,OAAO;IACL,GAAG;IACH,aAAa,CACX,GAAG,KAAK,aACR,GAAG,QACA,QAAQ,CAAC,gBAAgB;KACxB,OAAO,CAAC,KAAK,YAAY,MACtB,OACE,EAAE,SAAS,0BACV,EAAE,SAAS,yBACX,EAAE,SAAS,+BACX,EAAE,SAAS,0BACb,EAAE,KAAK,UAAU,UACrB;IACF,CAAC,CAAC,CACD,SAAS,GAAG,OAAO,EAAE,WAAW,CACrC,CAAC,CAAC,KAAK,0BAA0B;GACnC;EACF;EAGA,qBAAqB,MAAM;GACzB,OAAO,sBAAsB,MAAM,OAAO;EAC5C;EAEA,oBAAoB,MAAM;GACxB,OAAO,sBAAsB,MAAM,OAAO;EAC5C;EAGA,0BAA0B,MAAM;GAC9B,MAAM,QAAQ,QAAQ,MAAM,CAAC,gBAAgB,KAAK,KAAK,UAAU,UAAU;GAC3E,IAAI,OAAO;IACT,MAAM,GAAG,UAAU;IACnB,MAAM,sBAAsB,KAAK,UAAU,CAAC,EAAA,CAAG,KAAK,MAAM,EAAE,KAAK,KAAK;IACtE,MAAM,gBAAgB,OAAO,YAAY;IACzC,OAAO;KACL,GAAG;KACH,QAAQ,CACN,GAAI,KAAK,UAAU,CAAC,GACpB,IAAI,cAAc,UAAU,CAAC,EAAA,CAAG,QAAQ,MAAM,CAAC,mBAAmB,SAAS,EAAE,KAAK,KAAK,CAAC,CAC1F;IACF;GACF;GACA,OAAO;EACT;EAEA,oBAAoB,MAAM;GACxB,MAAM,QAAQ,QAAQ,MAAM,CAAC,gBAAgB,KAAK,KAAK,UAAU,UAAU;GAC3E,IAAI,OAAO;IACT,MAAM,GAAG,UAAU;IACnB,MAAM,CAAC,cAAc,OAAO;IAC5B,OAAO;KACL,GAAG;KACH,OAAO,WAAW;IACpB;GACF;GACA,OAAO;EACT;CACF,CAAC;AACH;;AAGA,SAAS,sBACP,MACA,SACG;CACH,MAAM,QAAQ,QAAQ,MAAM,CAAC,gBAAgB,KAAK,KAAK,UAAU,UAAU;CAC3E,IAAI,OAAO;EACT,MAAM,GAAG,UAAU;EACnB,MAAM,sBAAsB,KAAK,UAAU,CAAC,EAAA,CAAG,KAAK,MAAM,EAAE,KAAK,KAAK;EACtE,MAAM,gBAAgB,OAAO,YAAY;EACzC,OAAO;GACL,GAAG;GACH,QAAQ,CACN,GAAI,KAAK,UAAU,CAAC,GACpB,IAAI,cAAc,UAAU,CAAC,EAAA,CAAG,QAAQ,MAAM,CAAC,mBAAmB,SAAS,EAAE,KAAK,KAAK,CAAC,CAC1F;EACF;CACF;CACA,OAAO;AACT;;AAGA,SAAS,2BACP,GACA,GACQ;CACR,OAAO,uBAAuB,CAAC,IAAI,uBAAuB,CAAC;AAC7D;;AAGA,SAAS,uBAAuB,YAAyD;CACvF,IAAI,WAAW,SAAS,yBAAyB,WAAW,KAAK,UAAU,SAAS,OAAO;CAC3F,IAAI,WAAW,SAAS,yBAAyB,WAAW,KAAK,UAAU,YAAY,OAAO;CAC9F,OAAO;AACT;AAMA,SAAgB,+BACd,WACA,MACyB;CACzB,IAAI,SAAS,UACX,OAAO;MACF,IAAI,SAAS,WAClB,OAAO;MACF,IAAI,SAAS,UAClB,OAAO;MACF,IAAI,SAAS,UAClB,OAAO;MACF,IAAI,gBAAgBC,QAAAA,MAAM;EAC/B,MAAM,UAAU,KAAK,aAAa,CAAC,CAAC;EACpC,IAAI,QAAQ,WAAW,MAAM,GAG3B,OAAO,UAAU,SAAS,IAAI,IAAI,aAAa;OAC1C,IAAI,QAAQ,WAAW,wBAAwB,GACpD,OAAO;OACF,IAAI,QAAQ,WAAW,wBAAwB,GACpD,OAAO;OACF,IAAI,QAAQ,WAAW,oBAAoB,GAChD,OAAO;OAGP;CAEJ,OAAO,IAAI,gBAAgBC,QAAAA,QAEzB;MAKA;AAEJ;AAEA,SAAgB,cAAc,GAAmB;CAC/C,OAAO,EAAE,cAAc,YAAY,EAAE,qBAAqBA,QAAAA;AAC5D"}
@@ -0,0 +1,31 @@
1
+ import { Fs } from "./utils.cjs";
2
+ import { PrimitiveField, PrimitiveTypescriptType } from "joist-codegen";
3
+ import { Code, Import } from "ts-poet";
4
+ //#region src/graphqlUtils.d.ts
5
+ /** A type for the fields we want to add to `*.graphql` files. */
6
+ type GqlField = {
7
+ file: string;
8
+ objectType: "input" | "output";
9
+ objectName: string;
10
+ fieldName: string;
11
+ fieldType: string;
12
+ argsString?: string;
13
+ extends?: boolean;
14
+ };
15
+ type GqlUnion = {
16
+ file: string;
17
+ objectName: string;
18
+ objectType: "union";
19
+ types: string[];
20
+ };
21
+ type GqlEntry = GqlField | GqlUnion;
22
+ /** Given a `file` and `fields` to go in it (for potentially different objects), upserts into the existing types. */
23
+ declare function upsertIntoFile(fs: Fs, file: string, fields: GqlEntry[]): Promise<void>;
24
+ declare function formatGraphQL(content: string): Promise<string>;
25
+ type GraphQLType = "BigInt" | "Boolean" | "String" | "Int" | "Date" | "DateTime" | string;
26
+ type SupportedTypescriptTypes = Exclude<PrimitiveTypescriptType, "Object" | Import>;
27
+ declare function mapTypescriptTypeToGraphQLType(fieldName: string, type: PrimitiveTypescriptType | Import | Code): GraphQLType | undefined;
28
+ declare function isJsonbColumn(p: PrimitiveField): boolean;
29
+ //#endregion
30
+ export { GqlEntry, GqlField, GqlUnion, GraphQLType, SupportedTypescriptTypes, formatGraphQL, isJsonbColumn, mapTypescriptTypeToGraphQLType, upsertIntoFile };
31
+ //# sourceMappingURL=graphqlUtils.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphqlUtils.d.cts","names":[],"sources":["../src/graphqlUtils.ts"],"mappings":";;;;;KAkBY;EACV;EACA;EACA;EACA;EACA;EAEA;EACA;;KAGU;EAAa;EAAc;EAAoB;EAAqB;;KAEpE,WAAW,WAAW;;iBAGZ,eAAe,IAAI,IAAI,cAAc,QAAQ,aAAa;iBAyB1D,cAAc,kBAAkB;KA+J1C;KAEA,2BAA2B,QAAQ,oCAAoC;iBAEnE,+BACd,mBACA,MAAM,0BAA0B,SAAS,OACxC;iBAoCa,cAAc,GAAG"}
@@ -0,0 +1,31 @@
1
+ import { Fs } from "./utils.mjs";
2
+ import { PrimitiveField, PrimitiveTypescriptType } from "joist-codegen";
3
+ import { Code, Import } from "ts-poet";
4
+ //#region src/graphqlUtils.d.ts
5
+ /** A type for the fields we want to add to `*.graphql` files. */
6
+ type GqlField = {
7
+ file: string;
8
+ objectType: "input" | "output";
9
+ objectName: string;
10
+ fieldName: string;
11
+ fieldType: string;
12
+ argsString?: string;
13
+ extends?: boolean;
14
+ };
15
+ type GqlUnion = {
16
+ file: string;
17
+ objectName: string;
18
+ objectType: "union";
19
+ types: string[];
20
+ };
21
+ type GqlEntry = GqlField | GqlUnion;
22
+ /** Given a `file` and `fields` to go in it (for potentially different objects), upserts into the existing types. */
23
+ declare function upsertIntoFile(fs: Fs, file: string, fields: GqlEntry[]): Promise<void>;
24
+ declare function formatGraphQL(content: string): Promise<string>;
25
+ type GraphQLType = "BigInt" | "Boolean" | "String" | "Int" | "Date" | "DateTime" | string;
26
+ type SupportedTypescriptTypes = Exclude<PrimitiveTypescriptType, "Object" | Import>;
27
+ declare function mapTypescriptTypeToGraphQLType(fieldName: string, type: PrimitiveTypescriptType | Import | Code): GraphQLType | undefined;
28
+ declare function isJsonbColumn(p: PrimitiveField): boolean;
29
+ //#endregion
30
+ export { GqlEntry, GqlField, GqlUnion, GraphQLType, SupportedTypescriptTypes, formatGraphQL, isJsonbColumn, mapTypescriptTypeToGraphQLType, upsertIntoFile };
31
+ //# sourceMappingURL=graphqlUtils.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphqlUtils.d.mts","names":[],"sources":["../src/graphqlUtils.ts"],"mappings":";;;;;KAkBY;EACV;EACA;EACA;EACA;EACA;EAEA;EACA;;KAGU;EAAa;EAAc;EAAoB;EAAqB;;KAEpE,WAAW,WAAW;;iBAGZ,eAAe,IAAI,IAAI,cAAc,QAAQ,aAAa;iBAyB1D,cAAc,kBAAkB;KA+J1C;KAEA,2BAA2B,QAAQ,oCAAoC;iBAEnE,+BACd,mBACA,MAAM,0BAA0B,SAAS,OACxC;iBAoCa,cAAc,GAAG"}
@@ -1,252 +1,154 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.upsertIntoFile = upsertIntoFile;
37
- exports.formatGraphQL = formatGraphQL;
38
- exports.mapTypescriptTypeToGraphQLType = mapTypescriptTypeToGraphQLType;
39
- exports.isJsonbColumn = isJsonbColumn;
40
- const graphql_1 = require("graphql");
41
- const joist_utils_1 = require("joist-utils");
42
- const prettier_1 = __importStar(require("prettier"));
43
- const ts_poet_1 = require("ts-poet");
1
+ import "./utils.js";
2
+ import "joist-codegen";
3
+ import { Code, Import } from "ts-poet";
4
+ import { groupBy } from "joist-utils";
5
+ import { parse, print, visit } from "graphql";
6
+ import prettier, { resolveConfig } from "prettier";
7
+ //#region src/graphqlUtils.ts
44
8
  /** Given a `file` and `fields` to go in it (for potentially different objects), upserts into the existing types. */
45
9
  async function upsertIntoFile(fs, file, fields) {
46
- // Group the fields by each individual object (either input types or output types)
47
- const byObjectName = (0, joist_utils_1.groupBy)(fields, (f) => f.objectName);
48
- const existingDoc = parseOrNewEmptyDoc(await fs.load(file));
49
- // For each type, create a "new" / ideal definition that exactly matches the domain model
50
- const newDocs = Object.entries(byObjectName).map(([objectName, fields]) => {
51
- const [entry] = fields;
52
- return [
53
- objectName,
54
- entry.objectType === "union"
55
- ? createUnionDoc(entry)
56
- : createFieldDoc(objectName, fields),
57
- ];
58
- });
59
- // Merge each `newDoc` object definition into the file's existing types
60
- const content = (0, graphql_1.print)(mergeDocs(existingDoc, newDocs));
61
- const formatted = await formatGraphQL(content);
62
- await fs.save(file, formatted);
10
+ const byObjectName = groupBy(fields, (f) => f.objectName);
11
+ const existingDoc = parseOrNewEmptyDoc(await fs.load(file));
12
+ const newDocs = Object.entries(byObjectName).map(([objectName, fields]) => {
13
+ const [entry] = fields;
14
+ return [objectName, entry.objectType === "union" ? createUnionDoc(entry) : createFieldDoc(objectName, fields)];
15
+ });
16
+ const formatted = await formatGraphQL(print(mergeDocs(existingDoc, newDocs)));
17
+ await fs.save(file, formatted);
63
18
  }
64
19
  let prettierPromise;
65
20
  async function formatGraphQL(content) {
66
- const prettierConfig = await (prettierPromise ??= (0, prettier_1.resolveConfig)("./"));
67
- return prettier_1.default.format(content, {
68
- parser: "graphql",
69
- ...prettierConfig,
70
- plugins: [],
71
- });
21
+ const prettierConfig = await (prettierPromise ??= resolveConfig("./"));
22
+ return prettier.format(content, {
23
+ parser: "graphql",
24
+ ...prettierConfig,
25
+ plugins: []
26
+ });
72
27
  }
73
28
  /**
74
- * Creates a new AST DocumentNode for the given object + field definitions.
75
- *
76
- * This leverages `parse` to do the dirty work of taking an "easy for us to create"
77
- * string of GraphQL SDL and turning it into a "pita to create by hand" AST
78
- * of object / field / type / etc. nodes.
79
- */
29
+ * Creates a new AST DocumentNode for the given object + field definitions.
30
+ *
31
+ * This leverages `parse` to do the dirty work of taking an "easy for us to create"
32
+ * string of GraphQL SDL and turning it into a "pita to create by hand" AST
33
+ * of object / field / type / etc. nodes.
34
+ */
80
35
  function createFieldDoc(objectName, fields) {
81
- const [{ objectType }] = fields;
82
- const type = objectType === "output" ? "type" : objectType;
83
- const maybeArgs = (f) => (f.argsString ? `(${f.argsString})` : "");
84
- const maybeExtends = fields.some((f) => f.extends) ? "extend " : "";
85
- const source = `${maybeExtends}${type} ${objectName} {
36
+ const [{ objectType }] = fields;
37
+ const type = objectType === "output" ? "type" : objectType;
38
+ const maybeArgs = (f) => f.argsString ? `(${f.argsString})` : "";
39
+ const source = `${fields.some((f) => f.extends) ? "extend " : ""}${type} ${objectName} {
86
40
  ${fields.map((f) => `${f.fieldName}${maybeArgs(f)}: ${f.fieldType}`)}
87
41
  }`;
88
- return (0, graphql_1.parse)(source);
42
+ return parse(source);
89
43
  }
90
44
  function createUnionDoc(union) {
91
- const { objectName, types } = union;
92
- return (0, graphql_1.parse)(`union ${objectName} = ${types.join(" | ")}`);
45
+ const { objectName, types } = union;
46
+ return parse(`union ${objectName} = ${types.join(" | ")}`);
93
47
  }
94
48
  function parseOrNewEmptyDoc(content) {
95
- return content ? (0, graphql_1.parse)(content) : newEmptyDocument();
49
+ return content ? parse(content) : newEmptyDocument();
96
50
  }
97
51
  function newEmptyDocument() {
98
- // I can't figure out how to `parse("")`, i.e. create an empty DocumentNode, so pretend
99
- // to make a `type Foo` but then throw it away so that DocumentNode ends up empty.
100
- return (0, graphql_1.visit)((0, graphql_1.parse)("type Foo"), {
101
- ObjectTypeDefinition() {
102
- return null;
103
- },
104
- });
52
+ return visit(parse("type Foo"), { ObjectTypeDefinition() {
53
+ return null;
54
+ } });
105
55
  }
106
56
  /**
107
- * Merges a given `newType` from `newDoc` into `existingDoc*.
108
- *
109
- * There are existing "merge schema" libraries/tools out there, but we want to be very purposeful
110
- * about keeping the existing SDL and this is really not too bad because we're only stitching
111
- * ~two levels of the AST (document -> objects and object -> fields).
112
- *
113
- * We also cheat by using `createNewDoc` to get ASTs of the new content, so we don't have
114
- * to laboriously built up the ASTs by hand.
115
- */
57
+ * Merges a given `newType` from `newDoc` into `existingDoc*.
58
+ *
59
+ * There are existing "merge schema" libraries/tools out there, but we want to be very purposeful
60
+ * about keeping the existing SDL and this is really not too bad because we're only stitching
61
+ * ~two levels of the AST (document -> objects and object -> fields).
62
+ *
63
+ * We also cheat by using `createNewDoc` to get ASTs of the new content, so we don't have
64
+ * to laboriously built up the ASTs by hand.
65
+ */
116
66
  function mergeDocs(existingDoc, newDocs) {
117
- // Now merged the two
118
- return (0, graphql_1.visit)(existingDoc, {
119
- // If the `type Book` does not exist yet, add it
120
- Document(node) {
121
- return {
122
- ...node,
123
- definitions: [
124
- ...node.definitions,
125
- ...newDocs
126
- .filter(([objectType]) => {
127
- return !node.definitions.some((d) => (d.kind === "ObjectTypeDefinition" ||
128
- d.kind === "ObjectTypeExtension" ||
129
- d.kind === "InputObjectTypeDefinition" ||
130
- d.kind === "UnionTypeDefinition") &&
131
- d.name.value === objectType);
132
- })
133
- .flatMap(([, d]) => d.definitions),
134
- ].sort(byOperationExtensionsFirst),
135
- };
136
- },
137
- // If fields don't exist yet, add them
138
- ObjectTypeDefinition(node) {
139
- return mergeObjectTypeFields(node, newDocs);
140
- },
141
- ObjectTypeExtension(node) {
142
- return mergeObjectTypeFields(node, newDocs);
143
- },
144
- // If fields don't exist yet, add them
145
- InputObjectTypeDefinition(node) {
146
- const found = newDocs.find(([objectType]) => node.name.value === objectType);
147
- if (found) {
148
- const [, newDoc] = found;
149
- const existingFieldNames = (node.fields || []).map((f) => f.name.value);
150
- const newObjectType = newDoc.definitions[0];
151
- return {
152
- ...node,
153
- fields: [
154
- ...(node.fields || []),
155
- ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value)),
156
- ],
157
- };
158
- }
159
- return node;
160
- },
161
- UnionTypeDefinition(node) {
162
- const found = newDocs.find(([objectType]) => node.name.value === objectType);
163
- if (found) {
164
- const [, newDoc] = found;
165
- const [definition] = newDoc.definitions;
166
- return {
167
- ...node,
168
- types: definition.types,
169
- };
170
- }
171
- return node;
172
- },
173
- });
67
+ return visit(existingDoc, {
68
+ Document(node) {
69
+ return {
70
+ ...node,
71
+ definitions: [...node.definitions, ...newDocs.filter(([objectType]) => {
72
+ return !node.definitions.some((d) => (d.kind === "ObjectTypeDefinition" || d.kind === "ObjectTypeExtension" || d.kind === "InputObjectTypeDefinition" || d.kind === "UnionTypeDefinition") && d.name.value === objectType);
73
+ }).flatMap(([, d]) => d.definitions)].sort(byOperationExtensionsFirst)
74
+ };
75
+ },
76
+ ObjectTypeDefinition(node) {
77
+ return mergeObjectTypeFields(node, newDocs);
78
+ },
79
+ ObjectTypeExtension(node) {
80
+ return mergeObjectTypeFields(node, newDocs);
81
+ },
82
+ InputObjectTypeDefinition(node) {
83
+ const found = newDocs.find(([objectType]) => node.name.value === objectType);
84
+ if (found) {
85
+ const [, newDoc] = found;
86
+ const existingFieldNames = (node.fields || []).map((f) => f.name.value);
87
+ const newObjectType = newDoc.definitions[0];
88
+ return {
89
+ ...node,
90
+ fields: [...node.fields || [], ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value))]
91
+ };
92
+ }
93
+ return node;
94
+ },
95
+ UnionTypeDefinition(node) {
96
+ const found = newDocs.find(([objectType]) => node.name.value === objectType);
97
+ if (found) {
98
+ const [, newDoc] = found;
99
+ const [definition] = newDoc.definitions;
100
+ return {
101
+ ...node,
102
+ types: definition.types
103
+ };
104
+ }
105
+ return node;
106
+ }
107
+ });
174
108
  }
175
109
  /** Merges generated fields into an existing `type` or `extend type`. */
176
110
  function mergeObjectTypeFields(node, newDocs) {
177
- const found = newDocs.find(([objectType]) => node.name.value === objectType);
178
- if (found) {
179
- const [, newDoc] = found;
180
- const existingFieldNames = (node.fields || []).map((f) => f.name.value);
181
- const newObjectType = newDoc.definitions[0];
182
- return {
183
- ...node,
184
- fields: [
185
- ...(node.fields || []),
186
- ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value)),
187
- ],
188
- };
189
- }
190
- return node;
111
+ const found = newDocs.find(([objectType]) => node.name.value === objectType);
112
+ if (found) {
113
+ const [, newDoc] = found;
114
+ const existingFieldNames = (node.fields || []).map((f) => f.name.value);
115
+ const newObjectType = newDoc.definitions[0];
116
+ return {
117
+ ...node,
118
+ fields: [...node.fields || [], ...(newObjectType.fields || []).filter((f) => !existingFieldNames.includes(f.name.value))]
119
+ };
120
+ }
121
+ return node;
191
122
  }
192
123
  /** Keeps the primary operation extensions at the top of generated schema files. */
193
124
  function byOperationExtensionsFirst(a, b) {
194
- return operationExtensionRank(a) - operationExtensionRank(b);
125
+ return operationExtensionRank(a) - operationExtensionRank(b);
195
126
  }
196
127
  /** Returns the priority for placing generated operation extensions before types/inputs. */
197
128
  function operationExtensionRank(definition) {
198
- if (definition.kind === "ObjectTypeExtension" && definition.name.value === "Query")
199
- return 0;
200
- if (definition.kind === "ObjectTypeExtension" && definition.name.value === "Mutation")
201
- return 1;
202
- return 2;
129
+ if (definition.kind === "ObjectTypeExtension" && definition.name.value === "Query") return 0;
130
+ if (definition.kind === "ObjectTypeExtension" && definition.name.value === "Mutation") return 1;
131
+ return 2;
203
132
  }
204
133
  function mapTypescriptTypeToGraphQLType(fieldName, type) {
205
- if (type === "string") {
206
- return "String";
207
- }
208
- else if (type === "boolean") {
209
- return "Boolean";
210
- }
211
- else if (type === "number") {
212
- return "Int";
213
- }
214
- else if (type === "bigint") {
215
- return "BigInt";
216
- }
217
- else if (type instanceof ts_poet_1.Code) {
218
- const rawType = type.toCodeString([]);
219
- if (rawType.startsWith("Date")) {
220
- // Legacy javascript Date doesn't have different `date` vs. `datetime` types but GraphQL does
221
- // so lean on the `..._at` suffix convention to know "DateTime".
222
- return fieldName.endsWith("At") ? "DateTime" : "Date";
223
- }
224
- else if (rawType.startsWith("Temporal.ZonedDateTime")) {
225
- return "DateTime";
226
- }
227
- else if (rawType.startsWith("Temporal.PlainDateTime")) {
228
- return "DateTime";
229
- }
230
- else if (rawType.startsWith("Temporal.PlainDate")) {
231
- return "Date";
232
- }
233
- else {
234
- // If this is a fancy import like a superstruct/something, we can't guess what it will be in GraphQL
235
- return undefined;
236
- }
237
- }
238
- else if (type instanceof ts_poet_1.Import) {
239
- // If this is a fancy import like a superstruct/something, we can't guess what it will be in GraphQL
240
- return undefined;
241
- }
242
- else {
243
- // Anything else like `jsonb` (which shows up as `Object`) is also unlikely to be a valid
244
- // GraphQL type, and doing things like `someField: Object` w/o predefined scalar types will
245
- // cause GraphQL parsing errors.
246
- return undefined;
247
- }
134
+ if (type === "string") return "String";
135
+ else if (type === "boolean") return "Boolean";
136
+ else if (type === "number") return "Int";
137
+ else if (type === "bigint") return "BigInt";
138
+ else if (type instanceof Code) {
139
+ const rawType = type.toCodeString([]);
140
+ if (rawType.startsWith("Date")) return fieldName.endsWith("At") ? "DateTime" : "Date";
141
+ else if (rawType.startsWith("Temporal.ZonedDateTime")) return "DateTime";
142
+ else if (rawType.startsWith("Temporal.PlainDateTime")) return "DateTime";
143
+ else if (rawType.startsWith("Temporal.PlainDate")) return "Date";
144
+ else return;
145
+ } else if (type instanceof Import) return;
146
+ else return;
248
147
  }
249
148
  function isJsonbColumn(p) {
250
- return p.fieldType === "Object" || p.fieldType instanceof ts_poet_1.Import;
149
+ return p.fieldType === "Object" || p.fieldType instanceof Import;
251
150
  }
151
+ //#endregion
152
+ export { formatGraphQL, isJsonbColumn, mapTypescriptTypeToGraphQLType, upsertIntoFile };
153
+
252
154
  //# sourceMappingURL=graphqlUtils.js.map