dynamo-query-engine 1.0.7 → 1.0.8
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/package.json +1 -1
- package/src/core/expandResolver.js +112 -10
package/package.json
CHANGED
|
@@ -35,7 +35,11 @@ export async function resolveExpand({
|
|
|
35
35
|
field,
|
|
36
36
|
args = {},
|
|
37
37
|
}) {
|
|
38
|
+
console.log(`[expandResolver] resolveExpand called for field: ${field}`);
|
|
39
|
+
console.log(`[expandResolver] parentItems count: ${parentItems?.length || 0}`);
|
|
40
|
+
|
|
38
41
|
if (!parentItems || parentItems.length === 0) {
|
|
42
|
+
console.log(`[expandResolver] No parent items, skipping expand for field: ${field}`);
|
|
39
43
|
return;
|
|
40
44
|
}
|
|
41
45
|
|
|
@@ -52,11 +56,13 @@ export async function resolveExpand({
|
|
|
52
56
|
const policy = expandPolicy[field];
|
|
53
57
|
|
|
54
58
|
if (!policy) {
|
|
59
|
+
console.error(`[expandResolver] Field '${field}' does not have expand configuration`);
|
|
55
60
|
throw new Error(
|
|
56
61
|
`Field '${field}' does not have expand configuration in parent model`
|
|
57
62
|
);
|
|
58
63
|
}
|
|
59
64
|
|
|
65
|
+
|
|
60
66
|
// Get target model from registry
|
|
61
67
|
const targetModel = modelRegistry.get(policy.type);
|
|
62
68
|
|
|
@@ -77,12 +83,20 @@ export async function resolveExpand({
|
|
|
77
83
|
const expandPromises = parentItems.map(async (parent) => {
|
|
78
84
|
try {
|
|
79
85
|
// Get partition key value from parent
|
|
80
|
-
//
|
|
81
|
-
const
|
|
86
|
+
// First, determine the target model's hash key name
|
|
87
|
+
const targetAttributes = targetModel.schema.getAttributes();
|
|
88
|
+
const targetHashKeyName = Object.keys(targetAttributes).find(
|
|
89
|
+
(key) => targetAttributes[key].hashKey === true
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// Get the partition key value from the parent using the target's hash key name
|
|
94
|
+
const partitionKeyValue = parent[targetHashKeyName];
|
|
82
95
|
|
|
96
|
+
|
|
83
97
|
if (!partitionKeyValue) {
|
|
84
98
|
console.warn(
|
|
85
|
-
`Cannot expand '${field}' for parent: missing partition key value`
|
|
99
|
+
`[expandResolver] Cannot expand '${field}' for parent: missing partition key value`
|
|
86
100
|
);
|
|
87
101
|
parent[expandPropertyName] = policy.relation === "ONE" ? null : [];
|
|
88
102
|
return;
|
|
@@ -96,7 +110,7 @@ export async function resolveExpand({
|
|
|
96
110
|
|
|
97
111
|
if (!foreignKeyValue) {
|
|
98
112
|
console.warn(
|
|
99
|
-
`Cannot expand '${field}' for parent: missing foreign key value '${policy.foreignKey}'`
|
|
113
|
+
`[expandResolver] Cannot expand '${field}' for parent: missing foreign key value '${policy.foreignKey}'`
|
|
100
114
|
);
|
|
101
115
|
parent[expandPropertyName] = null;
|
|
102
116
|
return;
|
|
@@ -110,7 +124,7 @@ export async function resolveExpand({
|
|
|
110
124
|
|
|
111
125
|
if (!rangeKeyName) {
|
|
112
126
|
console.warn(
|
|
113
|
-
`Cannot expand '${field}': target model '${policy.type}' has no range key defined`
|
|
127
|
+
`[expandResolver] Cannot expand '${field}': target model '${policy.type}' has no range key defined`
|
|
114
128
|
);
|
|
115
129
|
parent[expandPropertyName] = null;
|
|
116
130
|
return;
|
|
@@ -121,11 +135,12 @@ export async function resolveExpand({
|
|
|
121
135
|
items: [
|
|
122
136
|
{
|
|
123
137
|
field: rangeKeyName,
|
|
124
|
-
operator: "
|
|
138
|
+
operator: "eq",
|
|
125
139
|
value: foreignKeyValue,
|
|
126
140
|
},
|
|
127
141
|
],
|
|
128
142
|
});
|
|
143
|
+
|
|
129
144
|
|
|
130
145
|
const { query } = buildGridQuery({
|
|
131
146
|
model: targetModel,
|
|
@@ -155,6 +170,7 @@ export async function resolveExpand({
|
|
|
155
170
|
__typename: graphqlTypeName,
|
|
156
171
|
}));
|
|
157
172
|
|
|
173
|
+
|
|
158
174
|
// Assign results to parent
|
|
159
175
|
if (policy.relation === "ONE") {
|
|
160
176
|
parent[expandPropertyName] = resultsWithTypename.length > 0 ? resultsWithTypename[0] : null;
|
|
@@ -162,7 +178,8 @@ export async function resolveExpand({
|
|
|
162
178
|
parent[expandPropertyName] = resultsWithTypename;
|
|
163
179
|
}
|
|
164
180
|
} catch (error) {
|
|
165
|
-
console.error(`Error expanding '${field}' for parent:`, error);
|
|
181
|
+
console.error(`[expandResolver] Error expanding '${field}' for parent:`, error);
|
|
182
|
+
console.error(`[expandResolver] Error stack:`, error.stack);
|
|
166
183
|
// Gracefully handle errors - set empty result
|
|
167
184
|
parent[expandPropertyName] = policy.relation === "ONE" ? null : [];
|
|
168
185
|
}
|
|
@@ -193,19 +210,102 @@ function createGraphQLToSchemaFieldMap(schema) {
|
|
|
193
210
|
return map;
|
|
194
211
|
}
|
|
195
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Parse AppSync selectionSetList to extract requested expand fields
|
|
215
|
+
* @param {string[]} selectionSetList - AppSync selectionSetList array
|
|
216
|
+
* @param {string} parentPath - Parent path prefix (e.g., "rows")
|
|
217
|
+
* @returns {Set<string>} Set of field names that were requested
|
|
218
|
+
*/
|
|
219
|
+
function parseAppSyncSelectionSet(selectionSetList, parentPath = "rows") {
|
|
220
|
+
const requestedFields = new Set();
|
|
221
|
+
const prefix = parentPath + "/";
|
|
222
|
+
|
|
223
|
+
for (const path of selectionSetList) {
|
|
224
|
+
if (path.startsWith(prefix)) {
|
|
225
|
+
const afterPrefix = path.substring(prefix.length);
|
|
226
|
+
const firstSlash = afterPrefix.indexOf("/");
|
|
227
|
+
|
|
228
|
+
if (firstSlash === -1) {
|
|
229
|
+
// This is a direct child field (e.g., "rows/unitId")
|
|
230
|
+
requestedFields.add(afterPrefix);
|
|
231
|
+
} else {
|
|
232
|
+
// This is a nested field (e.g., "rows/Unit/name")
|
|
233
|
+
const fieldName = afterPrefix.substring(0, firstSlash);
|
|
234
|
+
requestedFields.add(fieldName);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return requestedFields;
|
|
240
|
+
}
|
|
241
|
+
|
|
196
242
|
/**
|
|
197
243
|
* Resolve multiple expands from GraphQL resolve info
|
|
198
244
|
* @param {Array} parentItems - Parent items to expand
|
|
199
245
|
* @param {*} parentModel - Parent Dynamoose model
|
|
200
|
-
* @param {Object} fieldsByTypeName - Fields by type name from graphql-parse-resolve-info
|
|
246
|
+
* @param {Object|string[]} fieldsByTypeName - Fields by type name from graphql-parse-resolve-info OR AppSync selectionSetList
|
|
247
|
+
* @param {Object} [options] - Additional options
|
|
248
|
+
* @param {boolean} [options.isAppSync] - Whether to parse AppSync selectionSetList format
|
|
249
|
+
* @param {string} [options.parentPath] - Parent path for AppSync (default: "rows")
|
|
201
250
|
* @returns {Promise<void>}
|
|
202
251
|
*/
|
|
203
252
|
export async function resolveExpands(
|
|
204
253
|
parentItems,
|
|
205
254
|
parentModel,
|
|
206
|
-
fieldsByTypeName
|
|
255
|
+
fieldsByTypeName,
|
|
256
|
+
options = {}
|
|
207
257
|
) {
|
|
258
|
+
const { isAppSync = false, parentPath = "rows" } = options;
|
|
259
|
+
|
|
260
|
+
// Handle AppSync format
|
|
261
|
+
if (isAppSync) {
|
|
262
|
+
const selectionSetList = fieldsByTypeName;
|
|
263
|
+
|
|
264
|
+
if (!selectionSetList || selectionSetList.length === 0) {
|
|
265
|
+
console.log(`[expandResolver] No selectionSetList, skipping`);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Parse AppSync selection set to find requested fields
|
|
270
|
+
const requestedFields = parseAppSyncSelectionSet(selectionSetList, parentPath);
|
|
271
|
+
|
|
272
|
+
// Get expand policy to filter only expandable fields
|
|
273
|
+
const expandPolicy = extractExpandPolicy(parentModel.schema);
|
|
274
|
+
|
|
275
|
+
// Create mapping from GraphQL field names to schema field names
|
|
276
|
+
const graphqlToSchemaMap = createGraphQLToSchemaFieldMap(parentModel.schema);
|
|
277
|
+
|
|
278
|
+
// Resolve all expands in parallel
|
|
279
|
+
const expandPromises = Array.from(requestedFields)
|
|
280
|
+
.map((graphqlFieldName) => {
|
|
281
|
+
// Map GraphQL field name to schema field name
|
|
282
|
+
const schemaFieldName = graphqlToSchemaMap[graphqlFieldName];
|
|
283
|
+
|
|
284
|
+
// Check if this field is expandable
|
|
285
|
+
if (!schemaFieldName || !expandPolicy[schemaFieldName]) {
|
|
286
|
+
console.log(`[expandResolver] Field '${graphqlFieldName}' is not expandable (schemaFieldName: ${schemaFieldName}, has policy: ${!!expandPolicy[schemaFieldName]})`);
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
console.log(`[expandResolver] Expanding field '${graphqlFieldName}' (schema: ${schemaFieldName})`);
|
|
291
|
+
return resolveExpand({
|
|
292
|
+
parentItems,
|
|
293
|
+
parentModel,
|
|
294
|
+
field: schemaFieldName,
|
|
295
|
+
args: {},
|
|
296
|
+
});
|
|
297
|
+
})
|
|
298
|
+
.filter(Boolean); // Remove null entries
|
|
299
|
+
|
|
300
|
+
console.log(`[expandResolver] Executing ${expandPromises.length} expand promises`);
|
|
301
|
+
await Promise.all(expandPromises);
|
|
302
|
+
console.log(`[expandResolver] All expands completed`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Handle standard graphql-parse-resolve-info format
|
|
208
307
|
if (!fieldsByTypeName || Object.keys(fieldsByTypeName).length === 0) {
|
|
308
|
+
console.log(`[expandResolver] No fieldsByTypeName, skipping`);
|
|
209
309
|
return;
|
|
210
310
|
}
|
|
211
311
|
|
|
@@ -214,12 +314,13 @@ export async function resolveExpands(
|
|
|
214
314
|
const fields = fieldsByTypeName[typeName];
|
|
215
315
|
|
|
216
316
|
if (!fields) {
|
|
317
|
+
console.log(`[expandResolver] No fields found for type ${typeName}`);
|
|
217
318
|
return;
|
|
218
319
|
}
|
|
219
320
|
|
|
220
321
|
// Get expand policy to filter only expandable fields
|
|
221
322
|
const expandPolicy = extractExpandPolicy(parentModel.schema);
|
|
222
|
-
|
|
323
|
+
|
|
223
324
|
// Create mapping from GraphQL field names to schema field names
|
|
224
325
|
const graphqlToSchemaMap = createGraphQLToSchemaFieldMap(parentModel.schema);
|
|
225
326
|
|
|
@@ -231,6 +332,7 @@ export async function resolveExpands(
|
|
|
231
332
|
|
|
232
333
|
// Check if this field is expandable
|
|
233
334
|
if (!schemaFieldName || !expandPolicy[schemaFieldName]) {
|
|
335
|
+
console.log(`[expandResolver] Field '${graphqlFieldName}' is not expandable (schemaFieldName: ${schemaFieldName}, has policy: ${!!expandPolicy[schemaFieldName]})`);
|
|
234
336
|
return null;
|
|
235
337
|
}
|
|
236
338
|
|