@njdamstra/appwrite-utils-cli 1.11.7 → 1.11.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.
|
@@ -250,6 +250,31 @@ export async function executeMigrationPlan(adapter, options) {
|
|
|
250
250
|
skipped += entries.length;
|
|
251
251
|
continue;
|
|
252
252
|
}
|
|
253
|
+
// Temporarily set ALL required attributes in this collection to optional.
|
|
254
|
+
// Appwrite rejects partial updateRow calls if a required attribute is missing
|
|
255
|
+
// from the payload — even if the field exists in the document. This affects
|
|
256
|
+
// every data-copy step during migration.
|
|
257
|
+
const schemaRes = await tryAwaitWithRetry(() => adapter.getTable({ databaseId: first.databaseId, tableId: first.collectionId }));
|
|
258
|
+
const allAttrs = schemaRes?.data?.attributes || schemaRes?.data?.columns || [];
|
|
259
|
+
const originallyRequired = allAttrs
|
|
260
|
+
.filter((a) => a.required === true && a.status === "available")
|
|
261
|
+
.map((a) => a.key);
|
|
262
|
+
if (originallyRequired.length > 0) {
|
|
263
|
+
MessageFormatter.info(` Temporarily setting ${originallyRequired.length} required attribute(s) to optional...`, { prefix: "Execute" });
|
|
264
|
+
for (const key of originallyRequired) {
|
|
265
|
+
try {
|
|
266
|
+
await tryAwaitWithRetry(() => adapter.updateAttribute({
|
|
267
|
+
databaseId: first.databaseId,
|
|
268
|
+
tableId: first.collectionId,
|
|
269
|
+
key,
|
|
270
|
+
required: false,
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// Non-fatal — attribute might not support updating required
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
253
278
|
// Migrate each attribute in this collection
|
|
254
279
|
for (const entry of entries) {
|
|
255
280
|
const cpEntry = getOrCreateCheckpointEntry(checkpoint, entry);
|
|
@@ -275,25 +300,23 @@ export async function executeMigrationPlan(adapter, options) {
|
|
|
275
300
|
MessageFormatter.error(` ${entry.attributeKey}: FAILED — ${cpEntry.error}`, undefined, { prefix: "Execute" });
|
|
276
301
|
}
|
|
277
302
|
}
|
|
278
|
-
// Restore required flags
|
|
279
|
-
// This
|
|
280
|
-
//
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
catch {
|
|
296
|
-
MessageFormatter.info(` Warning: could not set ${entry.attributeKey} back to required`, { prefix: "Execute" });
|
|
303
|
+
// Restore required flags for ALL originally-required attributes.
|
|
304
|
+
// This covers both migrated attributes (recreated as optional) and
|
|
305
|
+
// non-migrated attributes (temporarily set to optional above).
|
|
306
|
+
if (originallyRequired.length > 0) {
|
|
307
|
+
MessageFormatter.info(` Restoring ${originallyRequired.length} required attribute(s)...`, { prefix: "Execute" });
|
|
308
|
+
for (const key of originallyRequired) {
|
|
309
|
+
try {
|
|
310
|
+
await tryAwaitWithRetry(() => adapter.updateAttribute({
|
|
311
|
+
databaseId: first.databaseId,
|
|
312
|
+
tableId: first.collectionId,
|
|
313
|
+
key,
|
|
314
|
+
required: true,
|
|
315
|
+
}));
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
MessageFormatter.info(` Warning: could not restore required flag for ${key}`, { prefix: "Execute" });
|
|
319
|
+
}
|
|
297
320
|
}
|
|
298
321
|
}
|
|
299
322
|
// After collection completes, offer to update local YAML
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@njdamstra/appwrite-utils-cli",
|
|
3
3
|
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
|
4
|
-
"version": "1.11.
|
|
4
|
+
"version": "1.11.8",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|
|
@@ -338,6 +338,40 @@ export async function executeMigrationPlan(
|
|
|
338
338
|
continue;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
// Temporarily set ALL required attributes in this collection to optional.
|
|
342
|
+
// Appwrite rejects partial updateRow calls if a required attribute is missing
|
|
343
|
+
// from the payload — even if the field exists in the document. This affects
|
|
344
|
+
// every data-copy step during migration.
|
|
345
|
+
const schemaRes = await tryAwaitWithRetry(() =>
|
|
346
|
+
adapter.getTable({ databaseId: first.databaseId, tableId: first.collectionId })
|
|
347
|
+
);
|
|
348
|
+
const allAttrs: any[] =
|
|
349
|
+
schemaRes?.data?.attributes || schemaRes?.data?.columns || [];
|
|
350
|
+
const originallyRequired = allAttrs
|
|
351
|
+
.filter((a: any) => a.required === true && a.status === "available")
|
|
352
|
+
.map((a: any) => a.key as string);
|
|
353
|
+
|
|
354
|
+
if (originallyRequired.length > 0) {
|
|
355
|
+
MessageFormatter.info(
|
|
356
|
+
` Temporarily setting ${originallyRequired.length} required attribute(s) to optional...`,
|
|
357
|
+
{ prefix: "Execute" }
|
|
358
|
+
);
|
|
359
|
+
for (const key of originallyRequired) {
|
|
360
|
+
try {
|
|
361
|
+
await tryAwaitWithRetry(() =>
|
|
362
|
+
adapter.updateAttribute({
|
|
363
|
+
databaseId: first.databaseId,
|
|
364
|
+
tableId: first.collectionId,
|
|
365
|
+
key,
|
|
366
|
+
required: false,
|
|
367
|
+
} as any)
|
|
368
|
+
);
|
|
369
|
+
} catch {
|
|
370
|
+
// Non-fatal — attribute might not support updating required
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
341
375
|
// Migrate each attribute in this collection
|
|
342
376
|
for (const entry of entries) {
|
|
343
377
|
const cpEntry = getOrCreateCheckpointEntry(checkpoint, entry);
|
|
@@ -382,29 +416,30 @@ export async function executeMigrationPlan(
|
|
|
382
416
|
}
|
|
383
417
|
}
|
|
384
418
|
|
|
385
|
-
// Restore required flags
|
|
386
|
-
// This
|
|
387
|
-
//
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
419
|
+
// Restore required flags for ALL originally-required attributes.
|
|
420
|
+
// This covers both migrated attributes (recreated as optional) and
|
|
421
|
+
// non-migrated attributes (temporarily set to optional above).
|
|
422
|
+
if (originallyRequired.length > 0) {
|
|
423
|
+
MessageFormatter.info(
|
|
424
|
+
` Restoring ${originallyRequired.length} required attribute(s)...`,
|
|
425
|
+
{ prefix: "Execute" }
|
|
426
|
+
);
|
|
427
|
+
for (const key of originallyRequired) {
|
|
428
|
+
try {
|
|
429
|
+
await tryAwaitWithRetry(() =>
|
|
430
|
+
adapter.updateAttribute({
|
|
431
|
+
databaseId: first.databaseId,
|
|
432
|
+
tableId: first.collectionId,
|
|
433
|
+
key,
|
|
434
|
+
required: true,
|
|
435
|
+
} as any)
|
|
436
|
+
);
|
|
437
|
+
} catch {
|
|
438
|
+
MessageFormatter.info(
|
|
439
|
+
` Warning: could not restore required flag for ${key}`,
|
|
440
|
+
{ prefix: "Execute" }
|
|
441
|
+
);
|
|
442
|
+
}
|
|
408
443
|
}
|
|
409
444
|
}
|
|
410
445
|
|