appwrite-utils-cli 0.9.5 → 0.9.51

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.
@@ -194,16 +194,42 @@ export const transferDocumentsBetweenDbsLocalToLocal = async (
194
194
  fromCollId: string,
195
195
  toCollId: string
196
196
  ) => {
197
- let fromCollDocs = await tryAwaitWithRetry(async () =>
198
- db.listDocuments(fromDbId, fromCollId, [Query.limit(50)])
199
- );
200
197
  let totalDocumentsTransferred = 0;
198
+ let lastDocumentId: string | undefined;
199
+ let hasMoreDocuments = true;
201
200
 
202
- if (fromCollDocs.documents.length === 0) {
203
- console.log(`No documents found in collection ${fromCollId}`);
204
- return;
205
- } else if (fromCollDocs.documents.length < 50) {
206
- const batchedPromises = fromCollDocs.documents.map((doc) => {
201
+ while (hasMoreDocuments) {
202
+ const queryParams = [Query.limit(50)];
203
+ if (lastDocumentId) {
204
+ queryParams.push(Query.cursorAfter(lastDocumentId));
205
+ }
206
+
207
+ const fromCollDocs = await tryAwaitWithRetry(async () =>
208
+ db.listDocuments(fromDbId, fromCollId, queryParams)
209
+ );
210
+
211
+ if (fromCollDocs.documents.length === 0) {
212
+ if (totalDocumentsTransferred === 0) {
213
+ console.log(`No documents found in collection ${fromCollId}`);
214
+ }
215
+ break;
216
+ }
217
+
218
+ const allDocsToCreateCheck = await tryAwaitWithRetry(
219
+ async () =>
220
+ await db.listDocuments(toDbId, toCollId, [
221
+ Query.equal(
222
+ "$id",
223
+ fromCollDocs.documents.map((doc) => doc.$id)
224
+ ),
225
+ ])
226
+ );
227
+
228
+ const docsToCreate = fromCollDocs.documents.filter(
229
+ (doc) => !allDocsToCreateCheck.documents.some((d) => d.$id === doc.$id)
230
+ );
231
+
232
+ const batchedPromises = docsToCreate.map((doc) => {
207
233
  const toCreateObject: Partial<typeof doc> = {
208
234
  ...doc,
209
235
  };
@@ -224,64 +250,15 @@ export const transferDocumentsBetweenDbsLocalToLocal = async (
224
250
  )
225
251
  );
226
252
  });
253
+
227
254
  await Promise.all(batchedPromises);
228
- totalDocumentsTransferred += fromCollDocs.documents.length;
229
- } else {
230
- const batchedPromises = fromCollDocs.documents.map((doc) => {
231
- const toCreateObject: Partial<typeof doc> = {
232
- ...doc,
233
- };
234
- delete toCreateObject.$databaseId;
235
- delete toCreateObject.$collectionId;
236
- delete toCreateObject.$createdAt;
237
- delete toCreateObject.$updatedAt;
238
- delete toCreateObject.$id;
239
- delete toCreateObject.$permissions;
240
- return tryAwaitWithRetry(async () =>
241
- db.createDocument(
242
- toDbId,
243
- toCollId,
244
- doc.$id,
245
- toCreateObject,
246
- doc.$permissions
247
- )
248
- );
249
- });
250
- await Promise.all(batchedPromises);
251
- totalDocumentsTransferred += fromCollDocs.documents.length;
252
- while (fromCollDocs.documents.length === 50) {
253
- fromCollDocs = await tryAwaitWithRetry(
254
- async () =>
255
- await db.listDocuments(fromDbId, fromCollId, [
256
- Query.limit(50),
257
- Query.cursorAfter(
258
- fromCollDocs.documents[fromCollDocs.documents.length - 1].$id
259
- ),
260
- ])
261
- );
262
- const batchedPromises = fromCollDocs.documents.map((doc) => {
263
- const toCreateObject: Partial<typeof doc> = {
264
- ...doc,
265
- };
266
- delete toCreateObject.$databaseId;
267
- delete toCreateObject.$collectionId;
268
- delete toCreateObject.$createdAt;
269
- delete toCreateObject.$updatedAt;
270
- delete toCreateObject.$id;
271
- delete toCreateObject.$permissions;
272
- return tryAwaitWithRetry(
273
- async () =>
274
- await db.createDocument(
275
- toDbId,
276
- toCollId,
277
- doc.$id,
278
- toCreateObject,
279
- doc.$permissions
280
- )
281
- );
282
- });
283
- await Promise.all(batchedPromises);
284
- totalDocumentsTransferred += fromCollDocs.documents.length;
255
+ totalDocumentsTransferred += docsToCreate.length;
256
+
257
+ if (fromCollDocs.documents.length < 50) {
258
+ hasMoreDocuments = false;
259
+ } else {
260
+ lastDocumentId =
261
+ fromCollDocs.documents[fromCollDocs.documents.length - 1].$id;
285
262
  }
286
263
  }
287
264
 
@@ -314,7 +291,19 @@ export const transferDocumentsBetweenDbsLocalToRemote = async (
314
291
  console.log(`No documents found in collection ${fromCollId}`);
315
292
  return;
316
293
  } else if (fromCollDocs.documents.length < 50) {
317
- const batchedPromises = fromCollDocs.documents.map((doc) => {
294
+ const allDocsToCreateCheck = await tryAwaitWithRetry(
295
+ async () =>
296
+ await remoteDb.listDocuments(toDbId, toCollId, [
297
+ Query.equal(
298
+ "$id",
299
+ fromCollDocs.documents.map((doc) => doc.$id)
300
+ ),
301
+ ])
302
+ );
303
+ const docsToCreate = fromCollDocs.documents.filter(
304
+ (doc) => !allDocsToCreateCheck.documents.some((d) => d.$id === doc.$id)
305
+ );
306
+ const batchedPromises = docsToCreate.map((doc) => {
318
307
  const toCreateObject: Partial<typeof doc> = {
319
308
  ...doc,
320
309
  };
@@ -337,7 +326,19 @@ export const transferDocumentsBetweenDbsLocalToRemote = async (
337
326
  await Promise.all(batchedPromises);
338
327
  totalDocumentsTransferred += fromCollDocs.documents.length;
339
328
  } else {
340
- const batchedPromises = fromCollDocs.documents.map((doc) => {
329
+ const allDocsToCreateCheck = await tryAwaitWithRetry(
330
+ async () =>
331
+ await remoteDb.listDocuments(toDbId, toCollId, [
332
+ Query.equal(
333
+ "$id",
334
+ fromCollDocs.documents.map((doc) => doc.$id)
335
+ ),
336
+ ])
337
+ );
338
+ const docsToCreate = fromCollDocs.documents.filter(
339
+ (doc) => !allDocsToCreateCheck.documents.some((d) => d.$id === doc.$id)
340
+ );
341
+ const batchedPromises = docsToCreate.map((doc) => {
341
342
  const toCreateObject: Partial<typeof doc> = {
342
343
  ...doc,
343
344
  };
@@ -533,8 +534,7 @@ export const transferDatabaseLocalToRemote = async (
533
534
  async () => await localDb.listCollections(fromDbId, [Query.limit(50)])
534
535
  );
535
536
  const allFromCollections = fromCollections.collections;
536
- if (fromCollections.collections.length < 50) {
537
- } else {
537
+ if (fromCollections.collections.length >= 50) {
538
538
  lastCollectionId =
539
539
  fromCollections.collections[fromCollections.collections.length - 1].$id;
540
540
  while (lastCollectionId) {
@@ -555,43 +555,108 @@ export const transferDatabaseLocalToRemote = async (
555
555
  }
556
556
 
557
557
  for (const collection of allFromCollections) {
558
- const toCollection = await tryAwaitWithRetry(
558
+ let toCollection: Models.Collection;
559
+ const toCollectionExists = await tryAwaitWithRetry(
559
560
  async () =>
560
- await remoteDb.createCollection(
561
- toDbId,
562
- collection.$id,
563
- collection.name,
564
- collection.$permissions,
565
- collection.documentSecurity,
566
- collection.enabled
567
- )
561
+ await remoteDb.listCollections(toDbId, [
562
+ Query.equal("$id", collection.$id),
563
+ ])
568
564
  );
569
- console.log(`Collection ${toCollection.name} created`);
570
565
 
571
- for (const attribute of collection.attributes) {
572
- await tryAwaitWithRetry(
566
+ if (toCollectionExists.collections.length > 0) {
567
+ console.log(`Collection ${collection.name} already exists. Updating...`);
568
+ toCollection = toCollectionExists.collections[0];
569
+ // Update collection if needed
570
+ if (
571
+ toCollection.name !== collection.name ||
572
+ toCollection.$permissions !== collection.$permissions ||
573
+ toCollection.documentSecurity !== collection.documentSecurity ||
574
+ toCollection.enabled !== collection.enabled
575
+ ) {
576
+ toCollection = await tryAwaitWithRetry(
577
+ async () =>
578
+ await remoteDb.updateCollection(
579
+ toDbId,
580
+ collection.$id,
581
+ collection.name,
582
+ collection.$permissions,
583
+ collection.documentSecurity,
584
+ collection.enabled
585
+ )
586
+ );
587
+ console.log(`Collection ${toCollection.name} updated`);
588
+ }
589
+ } else {
590
+ toCollection = await tryAwaitWithRetry(
573
591
  async () =>
574
- await createOrUpdateAttribute(
575
- remoteDb,
592
+ await remoteDb.createCollection(
576
593
  toDbId,
577
- toCollection,
578
- parseAttribute(attribute as any)
594
+ collection.$id,
595
+ collection.name,
596
+ collection.$permissions,
597
+ collection.documentSecurity,
598
+ collection.enabled
579
599
  )
580
600
  );
601
+ console.log(`Collection ${toCollection.name} created`);
602
+ }
603
+
604
+ // Check and update attributes
605
+ const existingAttributes = await tryAwaitWithRetry(
606
+ async () => await remoteDb.listAttributes(toDbId, toCollection.$id)
607
+ );
608
+ for (const attribute of collection.attributes) {
609
+ const parsedAttribute = parseAttribute(attribute as any);
610
+ const existingAttribute = existingAttributes.attributes.find(
611
+ // @ts-expect-error
612
+ (attr) => attr.key === parsedAttribute.key
613
+ );
614
+ if (!existingAttribute) {
615
+ await tryAwaitWithRetry(
616
+ async () =>
617
+ await createOrUpdateAttribute(
618
+ remoteDb,
619
+ toDbId,
620
+ toCollection,
621
+ parsedAttribute
622
+ )
623
+ );
624
+ console.log(`Attribute ${parsedAttribute.key} created`);
625
+ } else {
626
+ // Check if attribute needs updating
627
+ // Note: Appwrite doesn't allow updating most attribute properties
628
+ // You might need to delete and recreate the attribute if significant changes are needed
629
+ console.log(`Attribute ${parsedAttribute.key} already exists`);
630
+ }
581
631
  }
582
632
 
633
+ // Check and update indexes
634
+ const existingIndexes = await tryAwaitWithRetry(
635
+ async () => await remoteDb.listIndexes(toDbId, toCollection.$id)
636
+ );
583
637
  for (const index of collection.indexes) {
584
- await tryAwaitWithRetry(
585
- async () =>
586
- await remoteDb.createIndex(
587
- toDbId,
588
- toCollection.$id,
589
- index.key,
590
- index.type as IndexType,
591
- index.attributes,
592
- index.orders
593
- )
638
+ const existingIndex = existingIndexes.indexes.find(
639
+ (idx) => idx.key === index.key
594
640
  );
641
+ if (!existingIndex) {
642
+ await tryAwaitWithRetry(
643
+ async () =>
644
+ await remoteDb.createIndex(
645
+ toDbId,
646
+ toCollection.$id,
647
+ index.key,
648
+ index.type as IndexType,
649
+ index.attributes,
650
+ index.orders
651
+ )
652
+ );
653
+ console.log(`Index ${index.key} created`);
654
+ } else {
655
+ // Check if index needs updating
656
+ // Note: Appwrite doesn't allow updating indexes
657
+ // You might need to delete and recreate the index if changes are needed
658
+ console.log(`Index ${index.key} already exists`);
659
+ }
595
660
  }
596
661
 
597
662
  await transferDocumentsBetweenDbsLocalToRemote(