@prisma/param-graph-builder 0.0.1

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/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @prisma/param-graph-builder
2
+
3
+ This package is intended for Prisma's internal use.
4
+
5
+ Builds a ParamGraph from DMMF (Data Model Metadata Format) at client generation time.
6
+
7
+ The ParamGraph is a compact data structure that enables schema-aware parameterization at runtime. It stores only parameterizable paths and uses a string table to de-duplicate field names.
8
+
9
+ This package is used by both `@prisma/client-generator-js` and `@prisma/client-generator-ts` to generate the parameterization schema that is embedded in the generated Prisma Client.
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Builds a ParamGraph from DMMF at client generation time.
3
+ *
4
+ * The ParamGraph is a compact data structure that enables schema-aware
5
+ * parameterization at runtime. It only stores parameterizable paths,
6
+ * and uses a string table to de-duplicate field names.
7
+ */
8
+ import type * as DMMF from '@prisma/dmmf';
9
+ import { ParamGraph } from '@prisma/param-graph';
10
+ /**
11
+ * Builds a ParamGraph from DMMF schema.
12
+ */
13
+ export declare function buildParamGraph(dmmf: DMMF.Document): ParamGraph;
@@ -0,0 +1,492 @@
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 build_param_graph_exports = {};
20
+ __export(build_param_graph_exports, {
21
+ buildParamGraph: () => buildParamGraph
22
+ });
23
+ module.exports = __toCommonJS(build_param_graph_exports);
24
+ var import_dmmf = require("@prisma/dmmf");
25
+ var import_param_graph = require("@prisma/param-graph");
26
+ class ParamGraphBuilder {
27
+ stringTable = [];
28
+ stringToIndex = /* @__PURE__ */ new Map();
29
+ enumNames = [];
30
+ enumToIndex = /* @__PURE__ */ new Map();
31
+ inputNodes = [];
32
+ outputNodes = [];
33
+ roots = {};
34
+ // Cache for input type nodes to avoid rebuilding
35
+ inputTypeNodeCache = /* @__PURE__ */ new Map();
36
+ // Cache for union nodes keyed by sorted type names
37
+ unionNodeCache = /* @__PURE__ */ new Map();
38
+ // Cache for output type nodes
39
+ outputTypeNodeCache = /* @__PURE__ */ new Map();
40
+ /**
41
+ * Interns a string into the string table, returning its index.
42
+ */
43
+ internString(str) {
44
+ let index = this.stringToIndex.get(str);
45
+ if (index === void 0) {
46
+ index = this.stringTable.length;
47
+ this.stringTable.push(str);
48
+ this.stringToIndex.set(str, index);
49
+ }
50
+ return index;
51
+ }
52
+ /**
53
+ * Registers a user enum name, returning its index.
54
+ */
55
+ registerEnum(enumName) {
56
+ let index = this.enumToIndex.get(enumName);
57
+ if (index === void 0) {
58
+ index = this.enumNames.length;
59
+ this.enumNames.push(enumName);
60
+ this.enumToIndex.set(enumName, index);
61
+ }
62
+ return index;
63
+ }
64
+ /**
65
+ * Allocates a new input node and returns its ID.
66
+ */
67
+ allocateInputNode() {
68
+ const id = this.inputNodes.length;
69
+ this.inputNodes.push({});
70
+ return id;
71
+ }
72
+ /**
73
+ * Sets fields on an input node.
74
+ */
75
+ setInputNodeFields(nodeId, fields) {
76
+ if (Object.keys(fields).length > 0) {
77
+ this.inputNodes[nodeId].f = fields;
78
+ }
79
+ }
80
+ /**
81
+ * Allocates a new output node and returns its ID.
82
+ */
83
+ allocateOutputNode() {
84
+ const id = this.outputNodes.length;
85
+ this.outputNodes.push({});
86
+ return id;
87
+ }
88
+ /**
89
+ * Sets fields on an output node.
90
+ */
91
+ setOutputNodeFields(nodeId, fields) {
92
+ if (Object.keys(fields).length > 0) {
93
+ this.outputNodes[nodeId].f = fields;
94
+ }
95
+ }
96
+ /**
97
+ * Records a root entry for an operation.
98
+ */
99
+ setRoot(key, entry) {
100
+ if (entry.a !== void 0 || entry.o !== void 0) {
101
+ this.roots[key] = entry;
102
+ }
103
+ }
104
+ /**
105
+ * Gets or sets a cached input type node ID.
106
+ */
107
+ getInputTypeNode(typeName) {
108
+ return this.inputTypeNodeCache.get(typeName);
109
+ }
110
+ setInputTypeNode(typeName, nodeId) {
111
+ this.inputTypeNodeCache.set(typeName, nodeId);
112
+ }
113
+ hasInputTypeNode(typeName) {
114
+ return this.inputTypeNodeCache.has(typeName);
115
+ }
116
+ /**
117
+ * Gets or sets a cached union node ID.
118
+ */
119
+ getUnionNode(key) {
120
+ return this.unionNodeCache.get(key);
121
+ }
122
+ setUnionNode(key, nodeId) {
123
+ this.unionNodeCache.set(key, nodeId);
124
+ }
125
+ hasUnionNode(key) {
126
+ return this.unionNodeCache.has(key);
127
+ }
128
+ /**
129
+ * Gets or sets a cached output type node ID.
130
+ */
131
+ getOutputTypeNode(typeName) {
132
+ return this.outputTypeNodeCache.get(typeName);
133
+ }
134
+ setOutputTypeNode(typeName, nodeId) {
135
+ this.outputTypeNodeCache.set(typeName, nodeId);
136
+ }
137
+ hasOutputTypeNode(typeName) {
138
+ return this.outputTypeNodeCache.has(typeName);
139
+ }
140
+ /**
141
+ * Builds the final ParamGraph.
142
+ */
143
+ build() {
144
+ return {
145
+ s: this.stringTable,
146
+ en: this.enumNames,
147
+ i: this.inputNodes,
148
+ o: this.outputNodes,
149
+ r: this.roots
150
+ };
151
+ }
152
+ }
153
+ function buildParamGraph(dmmf) {
154
+ const builder = new ParamGraphBuilder();
155
+ const inputTypeMap = /* @__PURE__ */ new Map();
156
+ const outputTypeMap = /* @__PURE__ */ new Map();
157
+ const userEnumNames = /* @__PURE__ */ new Set();
158
+ for (const e of dmmf.datamodel.enums) {
159
+ userEnumNames.add(e.name);
160
+ }
161
+ for (const inputType of dmmf.schema.inputObjectTypes.prisma ?? []) {
162
+ inputTypeMap.set(inputType.name, inputType);
163
+ }
164
+ for (const inputType of dmmf.schema.inputObjectTypes.model ?? []) {
165
+ inputTypeMap.set(inputType.name, inputType);
166
+ }
167
+ for (const outputType of dmmf.schema.outputObjectTypes.prisma) {
168
+ outputTypeMap.set(outputType.name, outputType);
169
+ }
170
+ for (const outputType of dmmf.schema.outputObjectTypes.model) {
171
+ outputTypeMap.set(outputType.name, outputType);
172
+ }
173
+ function buildInputNodeFromArgs(args) {
174
+ const fields = {};
175
+ let hasAnyField = false;
176
+ for (const arg of args) {
177
+ const edge = buildInputEdge(arg);
178
+ if (edge) {
179
+ const stringIndex = builder.internString(arg.name);
180
+ fields[stringIndex] = edge;
181
+ hasAnyField = true;
182
+ }
183
+ }
184
+ if (!hasAnyField) {
185
+ return void 0;
186
+ }
187
+ const nodeId = builder.allocateInputNode();
188
+ builder.setInputNodeFields(nodeId, fields);
189
+ return nodeId;
190
+ }
191
+ function buildInputEdge(arg) {
192
+ let flags = 0;
193
+ let scalarMask = 0;
194
+ let childNodeId;
195
+ let enumNameId;
196
+ const scalarTypes = [];
197
+ const enumTypes = [];
198
+ const inputObjectTypes = [];
199
+ for (const inputType of arg.inputTypes) {
200
+ switch (inputType.location) {
201
+ case "scalar":
202
+ scalarTypes.push(inputType);
203
+ break;
204
+ case "enumTypes":
205
+ enumTypes.push(inputType);
206
+ break;
207
+ case "inputObjectTypes":
208
+ inputObjectTypes.push(inputType);
209
+ break;
210
+ case "fieldRefTypes":
211
+ break;
212
+ }
213
+ }
214
+ for (const st of scalarTypes) {
215
+ scalarMask |= (0, import_param_graph.scalarTypeToMask)(st.type);
216
+ }
217
+ const hasStringScalar = (scalarMask & import_param_graph.ScalarMask.String) !== 0;
218
+ for (const et of enumTypes) {
219
+ const isUserEnum = userEnumNames.has(et.type);
220
+ const isPrismaEnum = et.namespace === "prisma";
221
+ if (isUserEnum) {
222
+ if (!hasStringScalar) {
223
+ enumNameId = builder.registerEnum(et.type);
224
+ }
225
+ scalarMask |= import_param_graph.ScalarMask.String;
226
+ } else if (!isPrismaEnum) {
227
+ scalarMask |= import_param_graph.ScalarMask.String;
228
+ }
229
+ }
230
+ const canParamScalar = arg.isParameterizable && scalarMask !== 0;
231
+ if (canParamScalar) {
232
+ const hasScalarList = scalarTypes.some((st) => st.isList) || enumTypes.some((et) => et.isList && (userEnumNames.has(et.type) || et.namespace !== "prisma"));
233
+ if (hasScalarList) {
234
+ flags |= import_param_graph.EdgeFlag.ListScalar;
235
+ } else {
236
+ flags |= import_param_graph.EdgeFlag.ParamScalar;
237
+ }
238
+ }
239
+ if (inputObjectTypes.length > 0) {
240
+ const hasObjectList = inputObjectTypes.some((iot) => iot.isList);
241
+ if (hasObjectList) {
242
+ flags |= import_param_graph.EdgeFlag.ListObject;
243
+ } else {
244
+ flags |= import_param_graph.EdgeFlag.Object;
245
+ }
246
+ if (inputObjectTypes.length === 1) {
247
+ childNodeId = buildInputTypeNode(inputObjectTypes[0].type);
248
+ } else {
249
+ childNodeId = buildUnionNode(inputObjectTypes.map((iot) => iot.type));
250
+ }
251
+ }
252
+ if (arg.isNullable) {
253
+ flags |= import_param_graph.EdgeFlag.Nullable;
254
+ }
255
+ if (flags === 0 && childNodeId === void 0) {
256
+ return void 0;
257
+ }
258
+ const edge = { k: flags };
259
+ if (childNodeId !== void 0) {
260
+ edge.c = childNodeId;
261
+ }
262
+ if (scalarMask !== 0 && canParamScalar) {
263
+ edge.m = scalarMask;
264
+ }
265
+ if (enumNameId !== void 0) {
266
+ edge.e = enumNameId;
267
+ }
268
+ return edge;
269
+ }
270
+ function buildInputTypeNode(typeName) {
271
+ if (builder.hasInputTypeNode(typeName)) {
272
+ return builder.getInputTypeNode(typeName);
273
+ }
274
+ const inputType = inputTypeMap.get(typeName);
275
+ if (!inputType) {
276
+ builder.setInputTypeNode(typeName, void 0);
277
+ return void 0;
278
+ }
279
+ const nodeId = builder.allocateInputNode();
280
+ builder.setInputTypeNode(typeName, nodeId);
281
+ const fields = {};
282
+ let hasAnyField = false;
283
+ for (const field of inputType.fields) {
284
+ const edge = buildInputEdge(field);
285
+ if (edge) {
286
+ const stringIndex = builder.internString(field.name);
287
+ fields[stringIndex] = edge;
288
+ hasAnyField = true;
289
+ }
290
+ }
291
+ if (hasAnyField) {
292
+ builder.setInputNodeFields(nodeId, fields);
293
+ return nodeId;
294
+ }
295
+ return nodeId;
296
+ }
297
+ function buildUnionNode(typeNames) {
298
+ const sortedNames = [...typeNames].sort();
299
+ const cacheKey = sortedNames.join("|");
300
+ if (builder.hasUnionNode(cacheKey)) {
301
+ return builder.getUnionNode(cacheKey);
302
+ }
303
+ const nodeId = builder.allocateInputNode();
304
+ builder.setUnionNode(cacheKey, nodeId);
305
+ const fieldsByName = /* @__PURE__ */ new Map();
306
+ for (const typeName of typeNames) {
307
+ const inputType = inputTypeMap.get(typeName);
308
+ if (!inputType) continue;
309
+ for (const field of inputType.fields) {
310
+ let fieldsForName = fieldsByName.get(field.name);
311
+ if (!fieldsForName) {
312
+ fieldsForName = [];
313
+ fieldsByName.set(field.name, fieldsForName);
314
+ }
315
+ fieldsForName.push(field);
316
+ }
317
+ }
318
+ const mergedFields = {};
319
+ let hasAnyField = false;
320
+ for (const [fieldName, variantFields] of fieldsByName) {
321
+ const mergedEdge = mergeFieldVariants(variantFields, typeNames.length);
322
+ if (mergedEdge) {
323
+ const stringIndex = builder.internString(fieldName);
324
+ mergedFields[stringIndex] = mergedEdge;
325
+ hasAnyField = true;
326
+ }
327
+ }
328
+ if (hasAnyField) {
329
+ builder.setInputNodeFields(nodeId, mergedFields);
330
+ }
331
+ return nodeId;
332
+ }
333
+ function mergeFieldVariants(variants, _totalVariants) {
334
+ const parameterizableCount = variants.filter((v) => v.isParameterizable).length;
335
+ const allAgreeOnParam = parameterizableCount === 0 || parameterizableCount === variants.length;
336
+ if (!allAgreeOnParam) {
337
+ }
338
+ let combinedMask = 0;
339
+ const masks = [];
340
+ for (const variant of variants) {
341
+ let variantMask = 0;
342
+ for (const inputType of variant.inputTypes) {
343
+ if (inputType.location === "scalar") {
344
+ variantMask |= (0, import_param_graph.scalarTypeToMask)(inputType.type);
345
+ }
346
+ }
347
+ masks.push(variantMask);
348
+ combinedMask |= variantMask;
349
+ }
350
+ const allAgreeOnScalars = masks.every((m) => m === masks[0]);
351
+ const allObjectTypes = /* @__PURE__ */ new Set();
352
+ let hasObjectList = false;
353
+ let hasObject = false;
354
+ for (const variant of variants) {
355
+ for (const inputType of variant.inputTypes) {
356
+ if (inputType.location === "inputObjectTypes") {
357
+ allObjectTypes.add(inputType.type);
358
+ if (inputType.isList) {
359
+ hasObjectList = true;
360
+ } else {
361
+ hasObject = true;
362
+ }
363
+ }
364
+ }
365
+ }
366
+ let flags = 0;
367
+ let childNodeId;
368
+ const canParamScalar = allAgreeOnParam && allAgreeOnScalars && variants.every((v) => v.isParameterizable) && combinedMask !== 0;
369
+ if (canParamScalar) {
370
+ const hasScalarList = variants.some((v) => v.inputTypes.some((it) => it.location === "scalar" && it.isList));
371
+ if (hasScalarList) {
372
+ flags |= import_param_graph.EdgeFlag.ListScalar;
373
+ } else {
374
+ flags |= import_param_graph.EdgeFlag.ParamScalar;
375
+ }
376
+ }
377
+ if (allObjectTypes.size > 0) {
378
+ if (hasObjectList) {
379
+ flags |= import_param_graph.EdgeFlag.ListObject;
380
+ } else if (hasObject) {
381
+ flags |= import_param_graph.EdgeFlag.Object;
382
+ }
383
+ const objectTypeArray = [...allObjectTypes];
384
+ if (objectTypeArray.length === 1) {
385
+ childNodeId = buildInputTypeNode(objectTypeArray[0]);
386
+ } else {
387
+ childNodeId = buildUnionNode(objectTypeArray);
388
+ }
389
+ }
390
+ if (variants.some((v) => v.isNullable)) {
391
+ flags |= import_param_graph.EdgeFlag.Nullable;
392
+ }
393
+ if (flags === 0 && childNodeId === void 0) {
394
+ return void 0;
395
+ }
396
+ const edge = { k: flags };
397
+ if (childNodeId !== void 0) {
398
+ edge.c = childNodeId;
399
+ }
400
+ if (canParamScalar && combinedMask !== 0) {
401
+ edge.m = combinedMask;
402
+ }
403
+ return edge;
404
+ }
405
+ function buildOutputTypeNode(typeName) {
406
+ if (builder.hasOutputTypeNode(typeName)) {
407
+ return builder.getOutputTypeNode(typeName);
408
+ }
409
+ const outputType = outputTypeMap.get(typeName);
410
+ if (!outputType) {
411
+ builder.setOutputTypeNode(typeName, void 0);
412
+ return void 0;
413
+ }
414
+ const nodeId = builder.allocateOutputNode();
415
+ builder.setOutputTypeNode(typeName, nodeId);
416
+ const fields = {};
417
+ let hasAnyField = false;
418
+ for (const field of outputType.fields) {
419
+ const edge = buildOutputEdge(field);
420
+ if (edge) {
421
+ const stringIndex = builder.internString(field.name);
422
+ fields[stringIndex] = edge;
423
+ hasAnyField = true;
424
+ }
425
+ }
426
+ if (hasAnyField) {
427
+ builder.setOutputNodeFields(nodeId, fields);
428
+ return nodeId;
429
+ }
430
+ return nodeId;
431
+ }
432
+ function buildOutputEdge(field) {
433
+ let argsNodeId;
434
+ let childOutputNodeId;
435
+ if (field.args.length > 0) {
436
+ argsNodeId = buildInputNodeFromArgs(field.args);
437
+ }
438
+ if (field.outputType.location === "outputObjectTypes") {
439
+ childOutputNodeId = buildOutputTypeNode(field.outputType.type);
440
+ }
441
+ if (argsNodeId === void 0 && childOutputNodeId === void 0) {
442
+ return void 0;
443
+ }
444
+ const edge = {};
445
+ if (argsNodeId !== void 0) {
446
+ edge.a = argsNodeId;
447
+ }
448
+ if (childOutputNodeId !== void 0) {
449
+ edge.o = childOutputNodeId;
450
+ }
451
+ return edge;
452
+ }
453
+ for (const mapping of dmmf.mappings.modelOperations) {
454
+ const modelName = mapping.model;
455
+ const actions = Object.keys(import_dmmf.ModelAction);
456
+ for (const action of actions) {
457
+ const fieldName = mapping[action];
458
+ if (!fieldName) continue;
459
+ let rootField;
460
+ const queryType = outputTypeMap.get("Query");
461
+ if (queryType) {
462
+ rootField = queryType.fields.find((f) => f.name === fieldName);
463
+ }
464
+ if (!rootField) {
465
+ const mutationType = outputTypeMap.get("Mutation");
466
+ if (mutationType) {
467
+ rootField = mutationType.fields.find((f) => f.name === fieldName);
468
+ }
469
+ }
470
+ if (!rootField) continue;
471
+ const argsNodeId = buildInputNodeFromArgs(rootField.args);
472
+ let outputNodeId;
473
+ if (rootField.outputType.location === "outputObjectTypes") {
474
+ outputNodeId = buildOutputTypeNode(rootField.outputType.type);
475
+ }
476
+ const dmmfActionToJsonAction = {
477
+ create: "createOne",
478
+ update: "updateOne",
479
+ delete: "deleteOne",
480
+ upsert: "upsertOne"
481
+ };
482
+ const jsonAction = dmmfActionToJsonAction[action] ?? action;
483
+ const rootKey = `${modelName}.${jsonAction}`;
484
+ builder.setRoot(rootKey, { a: argsNodeId, o: outputNodeId });
485
+ }
486
+ }
487
+ return builder.build();
488
+ }
489
+ // Annotate the CommonJS export names for ESM import in node:
490
+ 0 && (module.exports = {
491
+ buildParamGraph
492
+ });
@@ -0,0 +1,472 @@
1
+ import { ModelAction } from "@prisma/dmmf";
2
+ import {
3
+ EdgeFlag,
4
+ ScalarMask,
5
+ scalarTypeToMask
6
+ } from "@prisma/param-graph";
7
+ class ParamGraphBuilder {
8
+ stringTable = [];
9
+ stringToIndex = /* @__PURE__ */ new Map();
10
+ enumNames = [];
11
+ enumToIndex = /* @__PURE__ */ new Map();
12
+ inputNodes = [];
13
+ outputNodes = [];
14
+ roots = {};
15
+ // Cache for input type nodes to avoid rebuilding
16
+ inputTypeNodeCache = /* @__PURE__ */ new Map();
17
+ // Cache for union nodes keyed by sorted type names
18
+ unionNodeCache = /* @__PURE__ */ new Map();
19
+ // Cache for output type nodes
20
+ outputTypeNodeCache = /* @__PURE__ */ new Map();
21
+ /**
22
+ * Interns a string into the string table, returning its index.
23
+ */
24
+ internString(str) {
25
+ let index = this.stringToIndex.get(str);
26
+ if (index === void 0) {
27
+ index = this.stringTable.length;
28
+ this.stringTable.push(str);
29
+ this.stringToIndex.set(str, index);
30
+ }
31
+ return index;
32
+ }
33
+ /**
34
+ * Registers a user enum name, returning its index.
35
+ */
36
+ registerEnum(enumName) {
37
+ let index = this.enumToIndex.get(enumName);
38
+ if (index === void 0) {
39
+ index = this.enumNames.length;
40
+ this.enumNames.push(enumName);
41
+ this.enumToIndex.set(enumName, index);
42
+ }
43
+ return index;
44
+ }
45
+ /**
46
+ * Allocates a new input node and returns its ID.
47
+ */
48
+ allocateInputNode() {
49
+ const id = this.inputNodes.length;
50
+ this.inputNodes.push({});
51
+ return id;
52
+ }
53
+ /**
54
+ * Sets fields on an input node.
55
+ */
56
+ setInputNodeFields(nodeId, fields) {
57
+ if (Object.keys(fields).length > 0) {
58
+ this.inputNodes[nodeId].f = fields;
59
+ }
60
+ }
61
+ /**
62
+ * Allocates a new output node and returns its ID.
63
+ */
64
+ allocateOutputNode() {
65
+ const id = this.outputNodes.length;
66
+ this.outputNodes.push({});
67
+ return id;
68
+ }
69
+ /**
70
+ * Sets fields on an output node.
71
+ */
72
+ setOutputNodeFields(nodeId, fields) {
73
+ if (Object.keys(fields).length > 0) {
74
+ this.outputNodes[nodeId].f = fields;
75
+ }
76
+ }
77
+ /**
78
+ * Records a root entry for an operation.
79
+ */
80
+ setRoot(key, entry) {
81
+ if (entry.a !== void 0 || entry.o !== void 0) {
82
+ this.roots[key] = entry;
83
+ }
84
+ }
85
+ /**
86
+ * Gets or sets a cached input type node ID.
87
+ */
88
+ getInputTypeNode(typeName) {
89
+ return this.inputTypeNodeCache.get(typeName);
90
+ }
91
+ setInputTypeNode(typeName, nodeId) {
92
+ this.inputTypeNodeCache.set(typeName, nodeId);
93
+ }
94
+ hasInputTypeNode(typeName) {
95
+ return this.inputTypeNodeCache.has(typeName);
96
+ }
97
+ /**
98
+ * Gets or sets a cached union node ID.
99
+ */
100
+ getUnionNode(key) {
101
+ return this.unionNodeCache.get(key);
102
+ }
103
+ setUnionNode(key, nodeId) {
104
+ this.unionNodeCache.set(key, nodeId);
105
+ }
106
+ hasUnionNode(key) {
107
+ return this.unionNodeCache.has(key);
108
+ }
109
+ /**
110
+ * Gets or sets a cached output type node ID.
111
+ */
112
+ getOutputTypeNode(typeName) {
113
+ return this.outputTypeNodeCache.get(typeName);
114
+ }
115
+ setOutputTypeNode(typeName, nodeId) {
116
+ this.outputTypeNodeCache.set(typeName, nodeId);
117
+ }
118
+ hasOutputTypeNode(typeName) {
119
+ return this.outputTypeNodeCache.has(typeName);
120
+ }
121
+ /**
122
+ * Builds the final ParamGraph.
123
+ */
124
+ build() {
125
+ return {
126
+ s: this.stringTable,
127
+ en: this.enumNames,
128
+ i: this.inputNodes,
129
+ o: this.outputNodes,
130
+ r: this.roots
131
+ };
132
+ }
133
+ }
134
+ function buildParamGraph(dmmf) {
135
+ const builder = new ParamGraphBuilder();
136
+ const inputTypeMap = /* @__PURE__ */ new Map();
137
+ const outputTypeMap = /* @__PURE__ */ new Map();
138
+ const userEnumNames = /* @__PURE__ */ new Set();
139
+ for (const e of dmmf.datamodel.enums) {
140
+ userEnumNames.add(e.name);
141
+ }
142
+ for (const inputType of dmmf.schema.inputObjectTypes.prisma ?? []) {
143
+ inputTypeMap.set(inputType.name, inputType);
144
+ }
145
+ for (const inputType of dmmf.schema.inputObjectTypes.model ?? []) {
146
+ inputTypeMap.set(inputType.name, inputType);
147
+ }
148
+ for (const outputType of dmmf.schema.outputObjectTypes.prisma) {
149
+ outputTypeMap.set(outputType.name, outputType);
150
+ }
151
+ for (const outputType of dmmf.schema.outputObjectTypes.model) {
152
+ outputTypeMap.set(outputType.name, outputType);
153
+ }
154
+ function buildInputNodeFromArgs(args) {
155
+ const fields = {};
156
+ let hasAnyField = false;
157
+ for (const arg of args) {
158
+ const edge = buildInputEdge(arg);
159
+ if (edge) {
160
+ const stringIndex = builder.internString(arg.name);
161
+ fields[stringIndex] = edge;
162
+ hasAnyField = true;
163
+ }
164
+ }
165
+ if (!hasAnyField) {
166
+ return void 0;
167
+ }
168
+ const nodeId = builder.allocateInputNode();
169
+ builder.setInputNodeFields(nodeId, fields);
170
+ return nodeId;
171
+ }
172
+ function buildInputEdge(arg) {
173
+ let flags = 0;
174
+ let scalarMask = 0;
175
+ let childNodeId;
176
+ let enumNameId;
177
+ const scalarTypes = [];
178
+ const enumTypes = [];
179
+ const inputObjectTypes = [];
180
+ for (const inputType of arg.inputTypes) {
181
+ switch (inputType.location) {
182
+ case "scalar":
183
+ scalarTypes.push(inputType);
184
+ break;
185
+ case "enumTypes":
186
+ enumTypes.push(inputType);
187
+ break;
188
+ case "inputObjectTypes":
189
+ inputObjectTypes.push(inputType);
190
+ break;
191
+ case "fieldRefTypes":
192
+ break;
193
+ }
194
+ }
195
+ for (const st of scalarTypes) {
196
+ scalarMask |= scalarTypeToMask(st.type);
197
+ }
198
+ const hasStringScalar = (scalarMask & ScalarMask.String) !== 0;
199
+ for (const et of enumTypes) {
200
+ const isUserEnum = userEnumNames.has(et.type);
201
+ const isPrismaEnum = et.namespace === "prisma";
202
+ if (isUserEnum) {
203
+ if (!hasStringScalar) {
204
+ enumNameId = builder.registerEnum(et.type);
205
+ }
206
+ scalarMask |= ScalarMask.String;
207
+ } else if (!isPrismaEnum) {
208
+ scalarMask |= ScalarMask.String;
209
+ }
210
+ }
211
+ const canParamScalar = arg.isParameterizable && scalarMask !== 0;
212
+ if (canParamScalar) {
213
+ const hasScalarList = scalarTypes.some((st) => st.isList) || enumTypes.some((et) => et.isList && (userEnumNames.has(et.type) || et.namespace !== "prisma"));
214
+ if (hasScalarList) {
215
+ flags |= EdgeFlag.ListScalar;
216
+ } else {
217
+ flags |= EdgeFlag.ParamScalar;
218
+ }
219
+ }
220
+ if (inputObjectTypes.length > 0) {
221
+ const hasObjectList = inputObjectTypes.some((iot) => iot.isList);
222
+ if (hasObjectList) {
223
+ flags |= EdgeFlag.ListObject;
224
+ } else {
225
+ flags |= EdgeFlag.Object;
226
+ }
227
+ if (inputObjectTypes.length === 1) {
228
+ childNodeId = buildInputTypeNode(inputObjectTypes[0].type);
229
+ } else {
230
+ childNodeId = buildUnionNode(inputObjectTypes.map((iot) => iot.type));
231
+ }
232
+ }
233
+ if (arg.isNullable) {
234
+ flags |= EdgeFlag.Nullable;
235
+ }
236
+ if (flags === 0 && childNodeId === void 0) {
237
+ return void 0;
238
+ }
239
+ const edge = { k: flags };
240
+ if (childNodeId !== void 0) {
241
+ edge.c = childNodeId;
242
+ }
243
+ if (scalarMask !== 0 && canParamScalar) {
244
+ edge.m = scalarMask;
245
+ }
246
+ if (enumNameId !== void 0) {
247
+ edge.e = enumNameId;
248
+ }
249
+ return edge;
250
+ }
251
+ function buildInputTypeNode(typeName) {
252
+ if (builder.hasInputTypeNode(typeName)) {
253
+ return builder.getInputTypeNode(typeName);
254
+ }
255
+ const inputType = inputTypeMap.get(typeName);
256
+ if (!inputType) {
257
+ builder.setInputTypeNode(typeName, void 0);
258
+ return void 0;
259
+ }
260
+ const nodeId = builder.allocateInputNode();
261
+ builder.setInputTypeNode(typeName, nodeId);
262
+ const fields = {};
263
+ let hasAnyField = false;
264
+ for (const field of inputType.fields) {
265
+ const edge = buildInputEdge(field);
266
+ if (edge) {
267
+ const stringIndex = builder.internString(field.name);
268
+ fields[stringIndex] = edge;
269
+ hasAnyField = true;
270
+ }
271
+ }
272
+ if (hasAnyField) {
273
+ builder.setInputNodeFields(nodeId, fields);
274
+ return nodeId;
275
+ }
276
+ return nodeId;
277
+ }
278
+ function buildUnionNode(typeNames) {
279
+ const sortedNames = [...typeNames].sort();
280
+ const cacheKey = sortedNames.join("|");
281
+ if (builder.hasUnionNode(cacheKey)) {
282
+ return builder.getUnionNode(cacheKey);
283
+ }
284
+ const nodeId = builder.allocateInputNode();
285
+ builder.setUnionNode(cacheKey, nodeId);
286
+ const fieldsByName = /* @__PURE__ */ new Map();
287
+ for (const typeName of typeNames) {
288
+ const inputType = inputTypeMap.get(typeName);
289
+ if (!inputType) continue;
290
+ for (const field of inputType.fields) {
291
+ let fieldsForName = fieldsByName.get(field.name);
292
+ if (!fieldsForName) {
293
+ fieldsForName = [];
294
+ fieldsByName.set(field.name, fieldsForName);
295
+ }
296
+ fieldsForName.push(field);
297
+ }
298
+ }
299
+ const mergedFields = {};
300
+ let hasAnyField = false;
301
+ for (const [fieldName, variantFields] of fieldsByName) {
302
+ const mergedEdge = mergeFieldVariants(variantFields, typeNames.length);
303
+ if (mergedEdge) {
304
+ const stringIndex = builder.internString(fieldName);
305
+ mergedFields[stringIndex] = mergedEdge;
306
+ hasAnyField = true;
307
+ }
308
+ }
309
+ if (hasAnyField) {
310
+ builder.setInputNodeFields(nodeId, mergedFields);
311
+ }
312
+ return nodeId;
313
+ }
314
+ function mergeFieldVariants(variants, _totalVariants) {
315
+ const parameterizableCount = variants.filter((v) => v.isParameterizable).length;
316
+ const allAgreeOnParam = parameterizableCount === 0 || parameterizableCount === variants.length;
317
+ if (!allAgreeOnParam) {
318
+ }
319
+ let combinedMask = 0;
320
+ const masks = [];
321
+ for (const variant of variants) {
322
+ let variantMask = 0;
323
+ for (const inputType of variant.inputTypes) {
324
+ if (inputType.location === "scalar") {
325
+ variantMask |= scalarTypeToMask(inputType.type);
326
+ }
327
+ }
328
+ masks.push(variantMask);
329
+ combinedMask |= variantMask;
330
+ }
331
+ const allAgreeOnScalars = masks.every((m) => m === masks[0]);
332
+ const allObjectTypes = /* @__PURE__ */ new Set();
333
+ let hasObjectList = false;
334
+ let hasObject = false;
335
+ for (const variant of variants) {
336
+ for (const inputType of variant.inputTypes) {
337
+ if (inputType.location === "inputObjectTypes") {
338
+ allObjectTypes.add(inputType.type);
339
+ if (inputType.isList) {
340
+ hasObjectList = true;
341
+ } else {
342
+ hasObject = true;
343
+ }
344
+ }
345
+ }
346
+ }
347
+ let flags = 0;
348
+ let childNodeId;
349
+ const canParamScalar = allAgreeOnParam && allAgreeOnScalars && variants.every((v) => v.isParameterizable) && combinedMask !== 0;
350
+ if (canParamScalar) {
351
+ const hasScalarList = variants.some((v) => v.inputTypes.some((it) => it.location === "scalar" && it.isList));
352
+ if (hasScalarList) {
353
+ flags |= EdgeFlag.ListScalar;
354
+ } else {
355
+ flags |= EdgeFlag.ParamScalar;
356
+ }
357
+ }
358
+ if (allObjectTypes.size > 0) {
359
+ if (hasObjectList) {
360
+ flags |= EdgeFlag.ListObject;
361
+ } else if (hasObject) {
362
+ flags |= EdgeFlag.Object;
363
+ }
364
+ const objectTypeArray = [...allObjectTypes];
365
+ if (objectTypeArray.length === 1) {
366
+ childNodeId = buildInputTypeNode(objectTypeArray[0]);
367
+ } else {
368
+ childNodeId = buildUnionNode(objectTypeArray);
369
+ }
370
+ }
371
+ if (variants.some((v) => v.isNullable)) {
372
+ flags |= EdgeFlag.Nullable;
373
+ }
374
+ if (flags === 0 && childNodeId === void 0) {
375
+ return void 0;
376
+ }
377
+ const edge = { k: flags };
378
+ if (childNodeId !== void 0) {
379
+ edge.c = childNodeId;
380
+ }
381
+ if (canParamScalar && combinedMask !== 0) {
382
+ edge.m = combinedMask;
383
+ }
384
+ return edge;
385
+ }
386
+ function buildOutputTypeNode(typeName) {
387
+ if (builder.hasOutputTypeNode(typeName)) {
388
+ return builder.getOutputTypeNode(typeName);
389
+ }
390
+ const outputType = outputTypeMap.get(typeName);
391
+ if (!outputType) {
392
+ builder.setOutputTypeNode(typeName, void 0);
393
+ return void 0;
394
+ }
395
+ const nodeId = builder.allocateOutputNode();
396
+ builder.setOutputTypeNode(typeName, nodeId);
397
+ const fields = {};
398
+ let hasAnyField = false;
399
+ for (const field of outputType.fields) {
400
+ const edge = buildOutputEdge(field);
401
+ if (edge) {
402
+ const stringIndex = builder.internString(field.name);
403
+ fields[stringIndex] = edge;
404
+ hasAnyField = true;
405
+ }
406
+ }
407
+ if (hasAnyField) {
408
+ builder.setOutputNodeFields(nodeId, fields);
409
+ return nodeId;
410
+ }
411
+ return nodeId;
412
+ }
413
+ function buildOutputEdge(field) {
414
+ let argsNodeId;
415
+ let childOutputNodeId;
416
+ if (field.args.length > 0) {
417
+ argsNodeId = buildInputNodeFromArgs(field.args);
418
+ }
419
+ if (field.outputType.location === "outputObjectTypes") {
420
+ childOutputNodeId = buildOutputTypeNode(field.outputType.type);
421
+ }
422
+ if (argsNodeId === void 0 && childOutputNodeId === void 0) {
423
+ return void 0;
424
+ }
425
+ const edge = {};
426
+ if (argsNodeId !== void 0) {
427
+ edge.a = argsNodeId;
428
+ }
429
+ if (childOutputNodeId !== void 0) {
430
+ edge.o = childOutputNodeId;
431
+ }
432
+ return edge;
433
+ }
434
+ for (const mapping of dmmf.mappings.modelOperations) {
435
+ const modelName = mapping.model;
436
+ const actions = Object.keys(ModelAction);
437
+ for (const action of actions) {
438
+ const fieldName = mapping[action];
439
+ if (!fieldName) continue;
440
+ let rootField;
441
+ const queryType = outputTypeMap.get("Query");
442
+ if (queryType) {
443
+ rootField = queryType.fields.find((f) => f.name === fieldName);
444
+ }
445
+ if (!rootField) {
446
+ const mutationType = outputTypeMap.get("Mutation");
447
+ if (mutationType) {
448
+ rootField = mutationType.fields.find((f) => f.name === fieldName);
449
+ }
450
+ }
451
+ if (!rootField) continue;
452
+ const argsNodeId = buildInputNodeFromArgs(rootField.args);
453
+ let outputNodeId;
454
+ if (rootField.outputType.location === "outputObjectTypes") {
455
+ outputNodeId = buildOutputTypeNode(rootField.outputType.type);
456
+ }
457
+ const dmmfActionToJsonAction = {
458
+ create: "createOne",
459
+ update: "updateOne",
460
+ delete: "deleteOne",
461
+ upsert: "upsertOne"
462
+ };
463
+ const jsonAction = dmmfActionToJsonAction[action] ?? action;
464
+ const rootKey = `${modelName}.${jsonAction}`;
465
+ builder.setRoot(rootKey, { a: argsNodeId, o: outputNodeId });
466
+ }
467
+ }
468
+ return builder.build();
469
+ }
470
+ export {
471
+ buildParamGraph
472
+ };
@@ -0,0 +1 @@
1
+ export { buildParamGraph } from './build-param-graph';
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
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 index_exports = {};
20
+ __export(index_exports, {
21
+ buildParamGraph: () => import_build_param_graph.buildParamGraph
22
+ });
23
+ module.exports = __toCommonJS(index_exports);
24
+ var import_build_param_graph = require("./build-param-graph");
25
+ // Annotate the CommonJS export names for ESM import in node:
26
+ 0 && (module.exports = {
27
+ buildParamGraph
28
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import { buildParamGraph } from "./build-param-graph";
2
+ export {
3
+ buildParamGraph
4
+ };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@prisma/param-graph-builder",
3
+ "version": "0.0.1",
4
+ "description": "This package is intended for Prisma's internal use",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "require": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "import": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.mjs"
17
+ }
18
+ }
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/prisma/prisma.git",
23
+ "directory": "packages/param-graph-builder"
24
+ },
25
+ "license": "Apache-2.0",
26
+ "dependencies": {
27
+ "@prisma/dmmf": "workspace:*",
28
+ "@prisma/param-graph": "workspace:*"
29
+ },
30
+ "scripts": {
31
+ "dev": "DEV=true tsx helpers/build.ts",
32
+ "build": "tsx helpers/build.ts",
33
+ "prepublishOnly": "pnpm run build"
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "sideEffects": false
39
+ }