@prisma/param-graph-builder 7.4.0-integration-parameterization.6 → 7.4.0-integration-parameterization.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-param-graph.d.ts +19 -7
- package/dist/build-param-graph.js +12 -400
- package/dist/build-param-graph.mjs +10 -402
- package/dist/dmmf-traverser.d.ts +36 -0
- package/dist/dmmf-traverser.js +338 -0
- package/dist/dmmf-traverser.mjs +314 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -0
- package/dist/index.mjs +6 -1
- package/dist/param-graph-builder.d.ts +56 -0
- package/dist/param-graph-builder.js +139 -0
- package/dist/param-graph-builder.mjs +115 -0
- package/package.json +3 -3
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var dmmf_traverser_exports = {};
|
|
20
|
+
__export(dmmf_traverser_exports, {
|
|
21
|
+
DMMFTraverser: () => DMMFTraverser
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(dmmf_traverser_exports);
|
|
24
|
+
var import_dmmf = require("@prisma/dmmf");
|
|
25
|
+
var import_param_graph = require("@prisma/param-graph");
|
|
26
|
+
class DMMFTraverser {
|
|
27
|
+
#builder;
|
|
28
|
+
#inputTypeMap;
|
|
29
|
+
#outputTypeMap;
|
|
30
|
+
constructor(builder, dmmf) {
|
|
31
|
+
this.#builder = builder;
|
|
32
|
+
this.#inputTypeMap = /* @__PURE__ */ new Map();
|
|
33
|
+
this.#outputTypeMap = /* @__PURE__ */ new Map();
|
|
34
|
+
for (const inputType of dmmf.schema.inputObjectTypes.prisma ?? []) {
|
|
35
|
+
this.#inputTypeMap.set(getTypeName(inputType.name, "prisma"), inputType);
|
|
36
|
+
}
|
|
37
|
+
for (const inputType of dmmf.schema.inputObjectTypes.model ?? []) {
|
|
38
|
+
this.#inputTypeMap.set(getTypeName(inputType.name, "model"), inputType);
|
|
39
|
+
}
|
|
40
|
+
for (const outputType of dmmf.schema.outputObjectTypes.prisma ?? []) {
|
|
41
|
+
this.#outputTypeMap.set(getTypeName(outputType.name, "prisma"), outputType);
|
|
42
|
+
}
|
|
43
|
+
for (const outputType of dmmf.schema.outputObjectTypes.model ?? []) {
|
|
44
|
+
this.#outputTypeMap.set(getTypeName(outputType.name, "model"), outputType);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Process all root operations from model mappings.
|
|
49
|
+
*/
|
|
50
|
+
processRoots(mappings) {
|
|
51
|
+
for (const mapping of mappings) {
|
|
52
|
+
const modelName = mapping.model;
|
|
53
|
+
const actions = Object.keys(import_dmmf.ModelAction);
|
|
54
|
+
for (const action of actions) {
|
|
55
|
+
const fieldName = mapping[action];
|
|
56
|
+
if (!fieldName) continue;
|
|
57
|
+
const rootField = this.#findRootField(fieldName);
|
|
58
|
+
if (!rootField) continue;
|
|
59
|
+
const argsNodeId = this.buildInputNodeFromArgs(rootField.args);
|
|
60
|
+
let outputNodeId;
|
|
61
|
+
if (rootField.outputType.location === "outputObjectTypes") {
|
|
62
|
+
outputNodeId = this.buildOutputTypeNode(
|
|
63
|
+
getTypeName(rootField.outputType.type, rootField.outputType.namespace)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
const dmmfActionToJsonAction = {
|
|
67
|
+
create: "createOne",
|
|
68
|
+
update: "updateOne",
|
|
69
|
+
delete: "deleteOne",
|
|
70
|
+
upsert: "upsertOne"
|
|
71
|
+
};
|
|
72
|
+
const jsonAction = dmmfActionToJsonAction[action] ?? action;
|
|
73
|
+
const rootKey = `${modelName}.${jsonAction}`;
|
|
74
|
+
this.#builder.setRoot(rootKey, {
|
|
75
|
+
argsNodeId,
|
|
76
|
+
outputNodeId
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
#findRootField(fieldName) {
|
|
82
|
+
const queryType = this.#outputTypeMap.get("prisma.Query");
|
|
83
|
+
if (queryType) {
|
|
84
|
+
const field = queryType.fields.find((f) => f.name === fieldName);
|
|
85
|
+
if (field) return field;
|
|
86
|
+
}
|
|
87
|
+
const mutationType = this.#outputTypeMap.get("prisma.Mutation");
|
|
88
|
+
if (mutationType) {
|
|
89
|
+
const field = mutationType.fields.find((f) => f.name === fieldName);
|
|
90
|
+
if (field) return field;
|
|
91
|
+
}
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Builds an input node from schema arguments.
|
|
96
|
+
*/
|
|
97
|
+
buildInputNodeFromArgs(args) {
|
|
98
|
+
const edges = {};
|
|
99
|
+
let hasAnyEdge = false;
|
|
100
|
+
for (const arg of args) {
|
|
101
|
+
const edge = this.#mergeFieldVariants([arg]);
|
|
102
|
+
if (edge) {
|
|
103
|
+
const stringIndex = this.#builder.internString(arg.name);
|
|
104
|
+
edges[stringIndex] = edge;
|
|
105
|
+
hasAnyEdge = true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!hasAnyEdge) {
|
|
109
|
+
return void 0;
|
|
110
|
+
}
|
|
111
|
+
const nodeId = this.#builder.allocateInputNode();
|
|
112
|
+
this.#builder.setInputNodeEdges(nodeId, edges);
|
|
113
|
+
return nodeId;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Builds an input node for a named input type.
|
|
117
|
+
*/
|
|
118
|
+
buildInputTypeNode(typeName) {
|
|
119
|
+
if (this.#builder.hasInputTypeNode(typeName)) {
|
|
120
|
+
return this.#builder.getInputTypeNode(typeName);
|
|
121
|
+
}
|
|
122
|
+
const inputType = this.#inputTypeMap.get(typeName);
|
|
123
|
+
if (!inputType) {
|
|
124
|
+
this.#builder.setInputTypeNode(typeName, void 0);
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
const nodeId = this.#builder.allocateInputNode();
|
|
128
|
+
this.#builder.setInputTypeNode(typeName, nodeId);
|
|
129
|
+
const edges = {};
|
|
130
|
+
let hasAnyEdge = false;
|
|
131
|
+
for (const field of inputType.fields) {
|
|
132
|
+
const edge = this.#mergeFieldVariants([field]);
|
|
133
|
+
if (edge) {
|
|
134
|
+
const stringIndex = this.#builder.internString(field.name);
|
|
135
|
+
edges[stringIndex] = edge;
|
|
136
|
+
hasAnyEdge = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (hasAnyEdge) {
|
|
140
|
+
this.#builder.setInputNodeEdges(nodeId, edges);
|
|
141
|
+
}
|
|
142
|
+
return nodeId;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Builds a union node for multiple input types.
|
|
146
|
+
*/
|
|
147
|
+
buildUnionNode(typeNames) {
|
|
148
|
+
const sortedNames = [...typeNames].sort();
|
|
149
|
+
const cacheKey = sortedNames.join("|");
|
|
150
|
+
if (this.#builder.hasUnionNode(cacheKey)) {
|
|
151
|
+
return this.#builder.getUnionNode(cacheKey);
|
|
152
|
+
}
|
|
153
|
+
const nodeId = this.#builder.allocateInputNode();
|
|
154
|
+
this.#builder.setUnionNode(cacheKey, nodeId);
|
|
155
|
+
const fieldsByName = /* @__PURE__ */ new Map();
|
|
156
|
+
for (const typeName of typeNames) {
|
|
157
|
+
const inputType = this.#inputTypeMap.get(typeName);
|
|
158
|
+
if (!inputType) continue;
|
|
159
|
+
for (const field of inputType.fields) {
|
|
160
|
+
let fieldsForName = fieldsByName.get(field.name);
|
|
161
|
+
if (!fieldsForName) {
|
|
162
|
+
fieldsForName = [];
|
|
163
|
+
fieldsByName.set(field.name, fieldsForName);
|
|
164
|
+
}
|
|
165
|
+
fieldsForName.push(field);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const mergedEdges = {};
|
|
169
|
+
let hasAnyEdge = false;
|
|
170
|
+
for (const [fieldName, variantFields] of fieldsByName) {
|
|
171
|
+
const mergedEdge = this.#mergeFieldVariants(variantFields);
|
|
172
|
+
if (mergedEdge) {
|
|
173
|
+
const stringIndex = this.#builder.internString(fieldName);
|
|
174
|
+
mergedEdges[stringIndex] = mergedEdge;
|
|
175
|
+
hasAnyEdge = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (hasAnyEdge) {
|
|
179
|
+
this.#builder.setInputNodeEdges(nodeId, mergedEdges);
|
|
180
|
+
}
|
|
181
|
+
return nodeId;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Merges field variants to produce a single edge descriptor.
|
|
185
|
+
* This is the most complex part of the traversal - it handles
|
|
186
|
+
* union types and determines what kinds of values a field accepts.
|
|
187
|
+
*/
|
|
188
|
+
#mergeFieldVariants(variants) {
|
|
189
|
+
let flags = 0;
|
|
190
|
+
let scalarMask = 0;
|
|
191
|
+
let childNodeId;
|
|
192
|
+
let enumNameIndex;
|
|
193
|
+
const scalarTypes = [];
|
|
194
|
+
const enumTypes = [];
|
|
195
|
+
const inputObjectTypes = [];
|
|
196
|
+
for (const variant of variants) {
|
|
197
|
+
for (const inputType of variant.inputTypes) {
|
|
198
|
+
switch (inputType.location) {
|
|
199
|
+
case "scalar":
|
|
200
|
+
if (variant.isParameterizable) {
|
|
201
|
+
scalarTypes.push(inputType);
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
case "enumTypes":
|
|
205
|
+
if (variant.isParameterizable) {
|
|
206
|
+
enumTypes.push(inputType);
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
case "inputObjectTypes":
|
|
210
|
+
if (!inputObjectTypes.some(
|
|
211
|
+
(ot) => ot.type === inputType.type && ot.namespace === inputType.namespace && ot.isList === inputType.isList
|
|
212
|
+
)) {
|
|
213
|
+
inputObjectTypes.push(inputType);
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
case "fieldRefTypes":
|
|
217
|
+
break;
|
|
218
|
+
default:
|
|
219
|
+
inputType.location;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (const st of scalarTypes) {
|
|
224
|
+
scalarMask |= (0, import_param_graph.scalarTypeToMask)(st.type);
|
|
225
|
+
if (st.isList) {
|
|
226
|
+
flags |= import_param_graph.EdgeFlag.ParamListScalar;
|
|
227
|
+
} else {
|
|
228
|
+
flags |= import_param_graph.EdgeFlag.ParamScalar;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
for (const et of enumTypes) {
|
|
232
|
+
if (et.namespace === "model") {
|
|
233
|
+
enumNameIndex = this.#builder.internString(et.type);
|
|
234
|
+
if (et.isList) {
|
|
235
|
+
flags |= import_param_graph.EdgeFlag.ParamListEnum;
|
|
236
|
+
} else {
|
|
237
|
+
flags |= import_param_graph.EdgeFlag.ParamEnum;
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (inputObjectTypes.length > 0) {
|
|
243
|
+
const hasObjectList = inputObjectTypes.some((iot) => iot.isList);
|
|
244
|
+
const hasSingleObject = inputObjectTypes.some((iot) => !iot.isList);
|
|
245
|
+
if (hasObjectList) {
|
|
246
|
+
flags |= import_param_graph.EdgeFlag.ListObject;
|
|
247
|
+
}
|
|
248
|
+
if (hasSingleObject) {
|
|
249
|
+
flags |= import_param_graph.EdgeFlag.Object;
|
|
250
|
+
}
|
|
251
|
+
if (inputObjectTypes.length === 1) {
|
|
252
|
+
childNodeId = this.buildInputTypeNode(
|
|
253
|
+
getTypeName(inputObjectTypes[0].type, inputObjectTypes[0].namespace)
|
|
254
|
+
);
|
|
255
|
+
} else {
|
|
256
|
+
childNodeId = this.buildUnionNode(
|
|
257
|
+
inputObjectTypes.map((iot) => getTypeName(iot.type, iot.namespace))
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (flags === 0) {
|
|
262
|
+
return void 0;
|
|
263
|
+
}
|
|
264
|
+
const edge = { flags };
|
|
265
|
+
if (childNodeId !== void 0) {
|
|
266
|
+
edge.childNodeId = childNodeId;
|
|
267
|
+
}
|
|
268
|
+
if (scalarMask !== 0) {
|
|
269
|
+
edge.scalarMask = scalarMask;
|
|
270
|
+
}
|
|
271
|
+
if (enumNameIndex !== void 0) {
|
|
272
|
+
edge.enumNameIndex = enumNameIndex;
|
|
273
|
+
}
|
|
274
|
+
return edge;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Builds an output node for a named output type.
|
|
278
|
+
*/
|
|
279
|
+
buildOutputTypeNode(typeName) {
|
|
280
|
+
if (this.#builder.hasOutputTypeNode(typeName)) {
|
|
281
|
+
return this.#builder.getOutputTypeNode(typeName);
|
|
282
|
+
}
|
|
283
|
+
const outputType = this.#outputTypeMap.get(typeName);
|
|
284
|
+
if (!outputType) {
|
|
285
|
+
this.#builder.setOutputTypeNode(typeName, void 0);
|
|
286
|
+
return void 0;
|
|
287
|
+
}
|
|
288
|
+
const nodeId = this.#builder.allocateOutputNode();
|
|
289
|
+
this.#builder.setOutputTypeNode(typeName, nodeId);
|
|
290
|
+
const edges = {};
|
|
291
|
+
let hasAnyEdge = false;
|
|
292
|
+
for (const field of outputType.fields) {
|
|
293
|
+
const edge = this.#buildOutputEdge(field);
|
|
294
|
+
if (edge) {
|
|
295
|
+
const stringIndex = this.#builder.internString(field.name);
|
|
296
|
+
edges[stringIndex] = edge;
|
|
297
|
+
hasAnyEdge = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (hasAnyEdge) {
|
|
301
|
+
this.#builder.setOutputNodeEdges(nodeId, edges);
|
|
302
|
+
}
|
|
303
|
+
return nodeId;
|
|
304
|
+
}
|
|
305
|
+
#buildOutputEdge(field) {
|
|
306
|
+
let argsNodeId;
|
|
307
|
+
let outputNodeId;
|
|
308
|
+
if (field.args.length > 0) {
|
|
309
|
+
argsNodeId = this.buildInputNodeFromArgs(field.args);
|
|
310
|
+
}
|
|
311
|
+
if (field.outputType.location === "outputObjectTypes") {
|
|
312
|
+
outputNodeId = this.buildOutputTypeNode(
|
|
313
|
+
getTypeName(field.outputType.type, field.outputType.namespace)
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
if (argsNodeId === void 0 && outputNodeId === void 0) {
|
|
317
|
+
return void 0;
|
|
318
|
+
}
|
|
319
|
+
const edge = {};
|
|
320
|
+
if (argsNodeId !== void 0) {
|
|
321
|
+
edge.argsNodeId = argsNodeId;
|
|
322
|
+
}
|
|
323
|
+
if (outputNodeId !== void 0) {
|
|
324
|
+
edge.outputNodeId = outputNodeId;
|
|
325
|
+
}
|
|
326
|
+
return edge;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function getTypeName(name, namespace) {
|
|
330
|
+
if (namespace === void 0) {
|
|
331
|
+
return name;
|
|
332
|
+
}
|
|
333
|
+
return `${namespace}.${name}`;
|
|
334
|
+
}
|
|
335
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
336
|
+
0 && (module.exports = {
|
|
337
|
+
DMMFTraverser
|
|
338
|
+
});
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { ModelAction } from "@prisma/dmmf";
|
|
2
|
+
import { EdgeFlag, scalarTypeToMask } from "@prisma/param-graph";
|
|
3
|
+
class DMMFTraverser {
|
|
4
|
+
#builder;
|
|
5
|
+
#inputTypeMap;
|
|
6
|
+
#outputTypeMap;
|
|
7
|
+
constructor(builder, dmmf) {
|
|
8
|
+
this.#builder = builder;
|
|
9
|
+
this.#inputTypeMap = /* @__PURE__ */ new Map();
|
|
10
|
+
this.#outputTypeMap = /* @__PURE__ */ new Map();
|
|
11
|
+
for (const inputType of dmmf.schema.inputObjectTypes.prisma ?? []) {
|
|
12
|
+
this.#inputTypeMap.set(getTypeName(inputType.name, "prisma"), inputType);
|
|
13
|
+
}
|
|
14
|
+
for (const inputType of dmmf.schema.inputObjectTypes.model ?? []) {
|
|
15
|
+
this.#inputTypeMap.set(getTypeName(inputType.name, "model"), inputType);
|
|
16
|
+
}
|
|
17
|
+
for (const outputType of dmmf.schema.outputObjectTypes.prisma ?? []) {
|
|
18
|
+
this.#outputTypeMap.set(getTypeName(outputType.name, "prisma"), outputType);
|
|
19
|
+
}
|
|
20
|
+
for (const outputType of dmmf.schema.outputObjectTypes.model ?? []) {
|
|
21
|
+
this.#outputTypeMap.set(getTypeName(outputType.name, "model"), outputType);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Process all root operations from model mappings.
|
|
26
|
+
*/
|
|
27
|
+
processRoots(mappings) {
|
|
28
|
+
for (const mapping of mappings) {
|
|
29
|
+
const modelName = mapping.model;
|
|
30
|
+
const actions = Object.keys(ModelAction);
|
|
31
|
+
for (const action of actions) {
|
|
32
|
+
const fieldName = mapping[action];
|
|
33
|
+
if (!fieldName) continue;
|
|
34
|
+
const rootField = this.#findRootField(fieldName);
|
|
35
|
+
if (!rootField) continue;
|
|
36
|
+
const argsNodeId = this.buildInputNodeFromArgs(rootField.args);
|
|
37
|
+
let outputNodeId;
|
|
38
|
+
if (rootField.outputType.location === "outputObjectTypes") {
|
|
39
|
+
outputNodeId = this.buildOutputTypeNode(
|
|
40
|
+
getTypeName(rootField.outputType.type, rootField.outputType.namespace)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const dmmfActionToJsonAction = {
|
|
44
|
+
create: "createOne",
|
|
45
|
+
update: "updateOne",
|
|
46
|
+
delete: "deleteOne",
|
|
47
|
+
upsert: "upsertOne"
|
|
48
|
+
};
|
|
49
|
+
const jsonAction = dmmfActionToJsonAction[action] ?? action;
|
|
50
|
+
const rootKey = `${modelName}.${jsonAction}`;
|
|
51
|
+
this.#builder.setRoot(rootKey, {
|
|
52
|
+
argsNodeId,
|
|
53
|
+
outputNodeId
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
#findRootField(fieldName) {
|
|
59
|
+
const queryType = this.#outputTypeMap.get("prisma.Query");
|
|
60
|
+
if (queryType) {
|
|
61
|
+
const field = queryType.fields.find((f) => f.name === fieldName);
|
|
62
|
+
if (field) return field;
|
|
63
|
+
}
|
|
64
|
+
const mutationType = this.#outputTypeMap.get("prisma.Mutation");
|
|
65
|
+
if (mutationType) {
|
|
66
|
+
const field = mutationType.fields.find((f) => f.name === fieldName);
|
|
67
|
+
if (field) return field;
|
|
68
|
+
}
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Builds an input node from schema arguments.
|
|
73
|
+
*/
|
|
74
|
+
buildInputNodeFromArgs(args) {
|
|
75
|
+
const edges = {};
|
|
76
|
+
let hasAnyEdge = false;
|
|
77
|
+
for (const arg of args) {
|
|
78
|
+
const edge = this.#mergeFieldVariants([arg]);
|
|
79
|
+
if (edge) {
|
|
80
|
+
const stringIndex = this.#builder.internString(arg.name);
|
|
81
|
+
edges[stringIndex] = edge;
|
|
82
|
+
hasAnyEdge = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!hasAnyEdge) {
|
|
86
|
+
return void 0;
|
|
87
|
+
}
|
|
88
|
+
const nodeId = this.#builder.allocateInputNode();
|
|
89
|
+
this.#builder.setInputNodeEdges(nodeId, edges);
|
|
90
|
+
return nodeId;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Builds an input node for a named input type.
|
|
94
|
+
*/
|
|
95
|
+
buildInputTypeNode(typeName) {
|
|
96
|
+
if (this.#builder.hasInputTypeNode(typeName)) {
|
|
97
|
+
return this.#builder.getInputTypeNode(typeName);
|
|
98
|
+
}
|
|
99
|
+
const inputType = this.#inputTypeMap.get(typeName);
|
|
100
|
+
if (!inputType) {
|
|
101
|
+
this.#builder.setInputTypeNode(typeName, void 0);
|
|
102
|
+
return void 0;
|
|
103
|
+
}
|
|
104
|
+
const nodeId = this.#builder.allocateInputNode();
|
|
105
|
+
this.#builder.setInputTypeNode(typeName, nodeId);
|
|
106
|
+
const edges = {};
|
|
107
|
+
let hasAnyEdge = false;
|
|
108
|
+
for (const field of inputType.fields) {
|
|
109
|
+
const edge = this.#mergeFieldVariants([field]);
|
|
110
|
+
if (edge) {
|
|
111
|
+
const stringIndex = this.#builder.internString(field.name);
|
|
112
|
+
edges[stringIndex] = edge;
|
|
113
|
+
hasAnyEdge = true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (hasAnyEdge) {
|
|
117
|
+
this.#builder.setInputNodeEdges(nodeId, edges);
|
|
118
|
+
}
|
|
119
|
+
return nodeId;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Builds a union node for multiple input types.
|
|
123
|
+
*/
|
|
124
|
+
buildUnionNode(typeNames) {
|
|
125
|
+
const sortedNames = [...typeNames].sort();
|
|
126
|
+
const cacheKey = sortedNames.join("|");
|
|
127
|
+
if (this.#builder.hasUnionNode(cacheKey)) {
|
|
128
|
+
return this.#builder.getUnionNode(cacheKey);
|
|
129
|
+
}
|
|
130
|
+
const nodeId = this.#builder.allocateInputNode();
|
|
131
|
+
this.#builder.setUnionNode(cacheKey, nodeId);
|
|
132
|
+
const fieldsByName = /* @__PURE__ */ new Map();
|
|
133
|
+
for (const typeName of typeNames) {
|
|
134
|
+
const inputType = this.#inputTypeMap.get(typeName);
|
|
135
|
+
if (!inputType) continue;
|
|
136
|
+
for (const field of inputType.fields) {
|
|
137
|
+
let fieldsForName = fieldsByName.get(field.name);
|
|
138
|
+
if (!fieldsForName) {
|
|
139
|
+
fieldsForName = [];
|
|
140
|
+
fieldsByName.set(field.name, fieldsForName);
|
|
141
|
+
}
|
|
142
|
+
fieldsForName.push(field);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const mergedEdges = {};
|
|
146
|
+
let hasAnyEdge = false;
|
|
147
|
+
for (const [fieldName, variantFields] of fieldsByName) {
|
|
148
|
+
const mergedEdge = this.#mergeFieldVariants(variantFields);
|
|
149
|
+
if (mergedEdge) {
|
|
150
|
+
const stringIndex = this.#builder.internString(fieldName);
|
|
151
|
+
mergedEdges[stringIndex] = mergedEdge;
|
|
152
|
+
hasAnyEdge = true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (hasAnyEdge) {
|
|
156
|
+
this.#builder.setInputNodeEdges(nodeId, mergedEdges);
|
|
157
|
+
}
|
|
158
|
+
return nodeId;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Merges field variants to produce a single edge descriptor.
|
|
162
|
+
* This is the most complex part of the traversal - it handles
|
|
163
|
+
* union types and determines what kinds of values a field accepts.
|
|
164
|
+
*/
|
|
165
|
+
#mergeFieldVariants(variants) {
|
|
166
|
+
let flags = 0;
|
|
167
|
+
let scalarMask = 0;
|
|
168
|
+
let childNodeId;
|
|
169
|
+
let enumNameIndex;
|
|
170
|
+
const scalarTypes = [];
|
|
171
|
+
const enumTypes = [];
|
|
172
|
+
const inputObjectTypes = [];
|
|
173
|
+
for (const variant of variants) {
|
|
174
|
+
for (const inputType of variant.inputTypes) {
|
|
175
|
+
switch (inputType.location) {
|
|
176
|
+
case "scalar":
|
|
177
|
+
if (variant.isParameterizable) {
|
|
178
|
+
scalarTypes.push(inputType);
|
|
179
|
+
}
|
|
180
|
+
break;
|
|
181
|
+
case "enumTypes":
|
|
182
|
+
if (variant.isParameterizable) {
|
|
183
|
+
enumTypes.push(inputType);
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
case "inputObjectTypes":
|
|
187
|
+
if (!inputObjectTypes.some(
|
|
188
|
+
(ot) => ot.type === inputType.type && ot.namespace === inputType.namespace && ot.isList === inputType.isList
|
|
189
|
+
)) {
|
|
190
|
+
inputObjectTypes.push(inputType);
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
case "fieldRefTypes":
|
|
194
|
+
break;
|
|
195
|
+
default:
|
|
196
|
+
inputType.location;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (const st of scalarTypes) {
|
|
201
|
+
scalarMask |= scalarTypeToMask(st.type);
|
|
202
|
+
if (st.isList) {
|
|
203
|
+
flags |= EdgeFlag.ParamListScalar;
|
|
204
|
+
} else {
|
|
205
|
+
flags |= EdgeFlag.ParamScalar;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const et of enumTypes) {
|
|
209
|
+
if (et.namespace === "model") {
|
|
210
|
+
enumNameIndex = this.#builder.internString(et.type);
|
|
211
|
+
if (et.isList) {
|
|
212
|
+
flags |= EdgeFlag.ParamListEnum;
|
|
213
|
+
} else {
|
|
214
|
+
flags |= EdgeFlag.ParamEnum;
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (inputObjectTypes.length > 0) {
|
|
220
|
+
const hasObjectList = inputObjectTypes.some((iot) => iot.isList);
|
|
221
|
+
const hasSingleObject = inputObjectTypes.some((iot) => !iot.isList);
|
|
222
|
+
if (hasObjectList) {
|
|
223
|
+
flags |= EdgeFlag.ListObject;
|
|
224
|
+
}
|
|
225
|
+
if (hasSingleObject) {
|
|
226
|
+
flags |= EdgeFlag.Object;
|
|
227
|
+
}
|
|
228
|
+
if (inputObjectTypes.length === 1) {
|
|
229
|
+
childNodeId = this.buildInputTypeNode(
|
|
230
|
+
getTypeName(inputObjectTypes[0].type, inputObjectTypes[0].namespace)
|
|
231
|
+
);
|
|
232
|
+
} else {
|
|
233
|
+
childNodeId = this.buildUnionNode(
|
|
234
|
+
inputObjectTypes.map((iot) => getTypeName(iot.type, iot.namespace))
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (flags === 0) {
|
|
239
|
+
return void 0;
|
|
240
|
+
}
|
|
241
|
+
const edge = { flags };
|
|
242
|
+
if (childNodeId !== void 0) {
|
|
243
|
+
edge.childNodeId = childNodeId;
|
|
244
|
+
}
|
|
245
|
+
if (scalarMask !== 0) {
|
|
246
|
+
edge.scalarMask = scalarMask;
|
|
247
|
+
}
|
|
248
|
+
if (enumNameIndex !== void 0) {
|
|
249
|
+
edge.enumNameIndex = enumNameIndex;
|
|
250
|
+
}
|
|
251
|
+
return edge;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Builds an output node for a named output type.
|
|
255
|
+
*/
|
|
256
|
+
buildOutputTypeNode(typeName) {
|
|
257
|
+
if (this.#builder.hasOutputTypeNode(typeName)) {
|
|
258
|
+
return this.#builder.getOutputTypeNode(typeName);
|
|
259
|
+
}
|
|
260
|
+
const outputType = this.#outputTypeMap.get(typeName);
|
|
261
|
+
if (!outputType) {
|
|
262
|
+
this.#builder.setOutputTypeNode(typeName, void 0);
|
|
263
|
+
return void 0;
|
|
264
|
+
}
|
|
265
|
+
const nodeId = this.#builder.allocateOutputNode();
|
|
266
|
+
this.#builder.setOutputTypeNode(typeName, nodeId);
|
|
267
|
+
const edges = {};
|
|
268
|
+
let hasAnyEdge = false;
|
|
269
|
+
for (const field of outputType.fields) {
|
|
270
|
+
const edge = this.#buildOutputEdge(field);
|
|
271
|
+
if (edge) {
|
|
272
|
+
const stringIndex = this.#builder.internString(field.name);
|
|
273
|
+
edges[stringIndex] = edge;
|
|
274
|
+
hasAnyEdge = true;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (hasAnyEdge) {
|
|
278
|
+
this.#builder.setOutputNodeEdges(nodeId, edges);
|
|
279
|
+
}
|
|
280
|
+
return nodeId;
|
|
281
|
+
}
|
|
282
|
+
#buildOutputEdge(field) {
|
|
283
|
+
let argsNodeId;
|
|
284
|
+
let outputNodeId;
|
|
285
|
+
if (field.args.length > 0) {
|
|
286
|
+
argsNodeId = this.buildInputNodeFromArgs(field.args);
|
|
287
|
+
}
|
|
288
|
+
if (field.outputType.location === "outputObjectTypes") {
|
|
289
|
+
outputNodeId = this.buildOutputTypeNode(
|
|
290
|
+
getTypeName(field.outputType.type, field.outputType.namespace)
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
if (argsNodeId === void 0 && outputNodeId === void 0) {
|
|
294
|
+
return void 0;
|
|
295
|
+
}
|
|
296
|
+
const edge = {};
|
|
297
|
+
if (argsNodeId !== void 0) {
|
|
298
|
+
edge.argsNodeId = argsNodeId;
|
|
299
|
+
}
|
|
300
|
+
if (outputNodeId !== void 0) {
|
|
301
|
+
edge.outputNodeId = outputNodeId;
|
|
302
|
+
}
|
|
303
|
+
return edge;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function getTypeName(name, namespace) {
|
|
307
|
+
if (namespace === void 0) {
|
|
308
|
+
return name;
|
|
309
|
+
}
|
|
310
|
+
return `${namespace}.${name}`;
|
|
311
|
+
}
|
|
312
|
+
export {
|
|
313
|
+
DMMFTraverser
|
|
314
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
export { buildParamGraph } from './build-param-graph';
|
|
1
|
+
export { buildAndSerializeParamGraph, buildParamGraph } from './build-param-graph';
|
|
2
|
+
export { DMMFTraverser } from './dmmf-traverser';
|
|
3
|
+
export { ParamGraphBuilder } from './param-graph-builder';
|
|
4
|
+
export type { NodeId } from './param-graph-builder';
|
package/dist/index.js
CHANGED
|
@@ -18,11 +18,19 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var index_exports = {};
|
|
20
20
|
__export(index_exports, {
|
|
21
|
+
DMMFTraverser: () => import_dmmf_traverser.DMMFTraverser,
|
|
22
|
+
ParamGraphBuilder: () => import_param_graph_builder.ParamGraphBuilder,
|
|
23
|
+
buildAndSerializeParamGraph: () => import_build_param_graph.buildAndSerializeParamGraph,
|
|
21
24
|
buildParamGraph: () => import_build_param_graph.buildParamGraph
|
|
22
25
|
});
|
|
23
26
|
module.exports = __toCommonJS(index_exports);
|
|
24
27
|
var import_build_param_graph = require("./build-param-graph");
|
|
28
|
+
var import_dmmf_traverser = require("./dmmf-traverser");
|
|
29
|
+
var import_param_graph_builder = require("./param-graph-builder");
|
|
25
30
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
31
|
0 && (module.exports = {
|
|
32
|
+
DMMFTraverser,
|
|
33
|
+
ParamGraphBuilder,
|
|
34
|
+
buildAndSerializeParamGraph,
|
|
27
35
|
buildParamGraph
|
|
28
36
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import { buildParamGraph } from "./build-param-graph";
|
|
1
|
+
import { buildAndSerializeParamGraph, buildParamGraph } from "./build-param-graph";
|
|
2
|
+
import { DMMFTraverser } from "./dmmf-traverser";
|
|
3
|
+
import { ParamGraphBuilder } from "./param-graph-builder";
|
|
2
4
|
export {
|
|
5
|
+
DMMFTraverser,
|
|
6
|
+
ParamGraphBuilder,
|
|
7
|
+
buildAndSerializeParamGraph,
|
|
3
8
|
buildParamGraph
|
|
4
9
|
};
|