@prisma/param-graph-builder 7.4.0-integration-parameterization.18 → 7.4.0-integration-parameterization.20

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.
@@ -23,10 +23,14 @@ export declare class DMMFTraverser {
23
23
  buildInputNodeFromArgs(args: readonly DMMF.SchemaArg[]): NodeId | undefined;
24
24
  /**
25
25
  * Builds an input node for a named input type.
26
+ * Node allocation happens immediately, but field processing is deferred
27
+ * to avoid deep recursion.
26
28
  */
27
29
  buildInputTypeNode(typeName: string): NodeId | undefined;
28
30
  /**
29
31
  * Builds a union node for multiple input types.
32
+ * Node allocation happens immediately, but field processing is deferred
33
+ * to avoid deep recursion.
30
34
  */
31
35
  buildUnionNode(typeNames: string[]): NodeId | undefined;
32
36
  /**
@@ -27,6 +27,8 @@ class DMMFTraverser {
27
27
  #builder;
28
28
  #inputTypeMap;
29
29
  #outputTypeMap;
30
+ #pendingInputNodes = [];
31
+ #pendingUnionNodes = [];
30
32
  constructor(builder, dmmf) {
31
33
  this.#builder = builder;
32
34
  this.#inputTypeMap = /* @__PURE__ */ new Map();
@@ -77,6 +79,23 @@ class DMMFTraverser {
77
79
  });
78
80
  }
79
81
  }
82
+ this.#drainPendingWork();
83
+ }
84
+ /**
85
+ * Iteratively processes all pending input and union nodes.
86
+ * This avoids deep recursion that can cause stack overflow on complex schemas.
87
+ */
88
+ #drainPendingWork() {
89
+ while (this.#pendingInputNodes.length > 0 || this.#pendingUnionNodes.length > 0) {
90
+ while (this.#pendingInputNodes.length > 0) {
91
+ const pending = this.#pendingInputNodes.pop();
92
+ this.#processInputNodeFields(pending.nodeId, pending.fields);
93
+ }
94
+ while (this.#pendingUnionNodes.length > 0) {
95
+ const pending = this.#pendingUnionNodes.pop();
96
+ this.#processUnionNodeFields(pending.nodeId, pending.typeNames);
97
+ }
98
+ }
80
99
  }
81
100
  #findRootField(fieldName) {
82
101
  const queryType = this.#outputTypeMap.get("prisma.Query");
@@ -114,6 +133,8 @@ class DMMFTraverser {
114
133
  }
115
134
  /**
116
135
  * Builds an input node for a named input type.
136
+ * Node allocation happens immediately, but field processing is deferred
137
+ * to avoid deep recursion.
117
138
  */
118
139
  buildInputTypeNode(typeName) {
119
140
  if (this.#builder.hasInputTypeNode(typeName)) {
@@ -126,9 +147,16 @@ class DMMFTraverser {
126
147
  }
127
148
  const nodeId = this.#builder.allocateInputNode();
128
149
  this.#builder.setInputTypeNode(typeName, nodeId);
150
+ this.#pendingInputNodes.push({ nodeId, fields: inputType.fields });
151
+ return nodeId;
152
+ }
153
+ /**
154
+ * Process fields for an input node (called from drainPendingWork).
155
+ */
156
+ #processInputNodeFields(nodeId, fields) {
129
157
  const edges = {};
130
158
  let hasAnyEdge = false;
131
- for (const field of inputType.fields) {
159
+ for (const field of fields) {
132
160
  const edge = this.#mergeFieldVariants([field]);
133
161
  if (edge) {
134
162
  const stringIndex = this.#builder.internString(field.name);
@@ -139,10 +167,11 @@ class DMMFTraverser {
139
167
  if (hasAnyEdge) {
140
168
  this.#builder.setInputNodeEdges(nodeId, edges);
141
169
  }
142
- return nodeId;
143
170
  }
144
171
  /**
145
172
  * Builds a union node for multiple input types.
173
+ * Node allocation happens immediately, but field processing is deferred
174
+ * to avoid deep recursion.
146
175
  */
147
176
  buildUnionNode(typeNames) {
148
177
  const sortedNames = [...typeNames].sort();
@@ -152,6 +181,13 @@ class DMMFTraverser {
152
181
  }
153
182
  const nodeId = this.#builder.allocateInputNode();
154
183
  this.#builder.setUnionNode(cacheKey, nodeId);
184
+ this.#pendingUnionNodes.push({ nodeId, typeNames });
185
+ return nodeId;
186
+ }
187
+ /**
188
+ * Process fields for a union node (called from drainPendingWork).
189
+ */
190
+ #processUnionNodeFields(nodeId, typeNames) {
155
191
  const fieldsByName = /* @__PURE__ */ new Map();
156
192
  for (const typeName of typeNames) {
157
193
  const inputType = this.#inputTypeMap.get(typeName);
@@ -178,7 +214,6 @@ class DMMFTraverser {
178
214
  if (hasAnyEdge) {
179
215
  this.#builder.setInputNodeEdges(nodeId, mergedEdges);
180
216
  }
181
- return nodeId;
182
217
  }
183
218
  /**
184
219
  * Merges field variants to produce a single edge descriptor.
@@ -4,6 +4,8 @@ class DMMFTraverser {
4
4
  #builder;
5
5
  #inputTypeMap;
6
6
  #outputTypeMap;
7
+ #pendingInputNodes = [];
8
+ #pendingUnionNodes = [];
7
9
  constructor(builder, dmmf) {
8
10
  this.#builder = builder;
9
11
  this.#inputTypeMap = /* @__PURE__ */ new Map();
@@ -54,6 +56,23 @@ class DMMFTraverser {
54
56
  });
55
57
  }
56
58
  }
59
+ this.#drainPendingWork();
60
+ }
61
+ /**
62
+ * Iteratively processes all pending input and union nodes.
63
+ * This avoids deep recursion that can cause stack overflow on complex schemas.
64
+ */
65
+ #drainPendingWork() {
66
+ while (this.#pendingInputNodes.length > 0 || this.#pendingUnionNodes.length > 0) {
67
+ while (this.#pendingInputNodes.length > 0) {
68
+ const pending = this.#pendingInputNodes.pop();
69
+ this.#processInputNodeFields(pending.nodeId, pending.fields);
70
+ }
71
+ while (this.#pendingUnionNodes.length > 0) {
72
+ const pending = this.#pendingUnionNodes.pop();
73
+ this.#processUnionNodeFields(pending.nodeId, pending.typeNames);
74
+ }
75
+ }
57
76
  }
58
77
  #findRootField(fieldName) {
59
78
  const queryType = this.#outputTypeMap.get("prisma.Query");
@@ -91,6 +110,8 @@ class DMMFTraverser {
91
110
  }
92
111
  /**
93
112
  * Builds an input node for a named input type.
113
+ * Node allocation happens immediately, but field processing is deferred
114
+ * to avoid deep recursion.
94
115
  */
95
116
  buildInputTypeNode(typeName) {
96
117
  if (this.#builder.hasInputTypeNode(typeName)) {
@@ -103,9 +124,16 @@ class DMMFTraverser {
103
124
  }
104
125
  const nodeId = this.#builder.allocateInputNode();
105
126
  this.#builder.setInputTypeNode(typeName, nodeId);
127
+ this.#pendingInputNodes.push({ nodeId, fields: inputType.fields });
128
+ return nodeId;
129
+ }
130
+ /**
131
+ * Process fields for an input node (called from drainPendingWork).
132
+ */
133
+ #processInputNodeFields(nodeId, fields) {
106
134
  const edges = {};
107
135
  let hasAnyEdge = false;
108
- for (const field of inputType.fields) {
136
+ for (const field of fields) {
109
137
  const edge = this.#mergeFieldVariants([field]);
110
138
  if (edge) {
111
139
  const stringIndex = this.#builder.internString(field.name);
@@ -116,10 +144,11 @@ class DMMFTraverser {
116
144
  if (hasAnyEdge) {
117
145
  this.#builder.setInputNodeEdges(nodeId, edges);
118
146
  }
119
- return nodeId;
120
147
  }
121
148
  /**
122
149
  * Builds a union node for multiple input types.
150
+ * Node allocation happens immediately, but field processing is deferred
151
+ * to avoid deep recursion.
123
152
  */
124
153
  buildUnionNode(typeNames) {
125
154
  const sortedNames = [...typeNames].sort();
@@ -129,6 +158,13 @@ class DMMFTraverser {
129
158
  }
130
159
  const nodeId = this.#builder.allocateInputNode();
131
160
  this.#builder.setUnionNode(cacheKey, nodeId);
161
+ this.#pendingUnionNodes.push({ nodeId, typeNames });
162
+ return nodeId;
163
+ }
164
+ /**
165
+ * Process fields for a union node (called from drainPendingWork).
166
+ */
167
+ #processUnionNodeFields(nodeId, typeNames) {
132
168
  const fieldsByName = /* @__PURE__ */ new Map();
133
169
  for (const typeName of typeNames) {
134
170
  const inputType = this.#inputTypeMap.get(typeName);
@@ -155,7 +191,6 @@ class DMMFTraverser {
155
191
  if (hasAnyEdge) {
156
192
  this.#builder.setInputNodeEdges(nodeId, mergedEdges);
157
193
  }
158
- return nodeId;
159
194
  }
160
195
  /**
161
196
  * Merges field variants to produce a single edge descriptor.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/param-graph-builder",
3
- "version": "7.4.0-integration-parameterization.18",
3
+ "version": "7.4.0-integration-parameterization.20",
4
4
  "description": "This package is intended for Prisma's internal use",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -24,8 +24,8 @@
24
24
  },
25
25
  "license": "Apache-2.0",
26
26
  "dependencies": {
27
- "@prisma/dmmf": "7.4.0-integration-parameterization.18",
28
- "@prisma/param-graph": "7.4.0-integration-parameterization.18"
27
+ "@prisma/dmmf": "7.4.0-integration-parameterization.20",
28
+ "@prisma/param-graph": "7.4.0-integration-parameterization.20"
29
29
  },
30
30
  "files": [
31
31
  "dist"