appwrite-utils-cli 0.9.5 → 0.9.52
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 +2 -0
- package/dist/collections/attributes.js +4 -4
- package/dist/collections/indexes.js +3 -1
- package/dist/collections/methods.js +13 -7
- package/dist/interactiveCLI.js +28 -14
- package/dist/migrations/transfer.js +86 -52
- package/dist/utils/helperFunctions.d.ts +1 -0
- package/dist/utils/helperFunctions.js +1 -0
- package/package.json +53 -53
- package/src/collections/attributes.ts +5 -4
- package/src/collections/indexes.ts +3 -1
- package/src/collections/methods.ts +17 -7
- package/src/interactiveCLI.ts +41 -15
- package/src/migrations/transfer.ts +160 -95
- package/src/utils/helperFunctions.ts +3 -0
- package/zlogs/announcements.json +397 -0
- package/zlogs/announcementscomments.json +36 -0
- package/zlogs/articles.json +138 -0
- package/zlogs/articlescomments.json +4 -0
- package/zlogs/businesscategories.json +7097 -0
- package/zlogs/contacts.json +517063 -0
- package/zlogs/contactscouncils.json +61905 -0
- package/zlogs/contactssociallinks.json +13776 -0
- package/zlogs/councils.json +5076 -0
- package/zlogs/documents.json +917 -0
- package/zlogs/emails.json +4 -0
- package/zlogs/events.json +132625 -0
- package/zlogs/knowledgebase.json +333 -0
- package/zlogs/knowledgebasecomments.json +4 -0
- package/zlogs/linkcategories.json +180 -0
- package/zlogs/links.json +4364 -0
- package/zlogs/memberrequests.json +83 -0
- package/zlogs/memberrequestscomments.json +65 -0
- package/zlogs/mergedUserMap.json +56 -0
- package/zlogs/oldIdToNewIdPerCollectionMap.json +27663 -0
- package/zlogs/regions.json +145 -0
- package/zlogs/testimonials.json +335 -0
- package/zlogs/users.json +25516 -0
package/src/interactiveCLI.ts
CHANGED
@@ -558,14 +558,14 @@ export class InteractiveCLI {
|
|
558
558
|
},
|
559
559
|
]);
|
560
560
|
|
561
|
-
const { checkDuplicates } = await inquirer.prompt([
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
]);
|
561
|
+
// const { checkDuplicates } = await inquirer.prompt([
|
562
|
+
// {
|
563
|
+
// type: "confirm",
|
564
|
+
// name: "checkDuplicates",
|
565
|
+
// message: "Do you want to check for duplicates during import?",
|
566
|
+
// default: true,
|
567
|
+
// },
|
568
|
+
// ]);
|
569
569
|
|
570
570
|
console.log("Importing data...");
|
571
571
|
await this.controller!.importData({
|
@@ -575,7 +575,8 @@ export class InteractiveCLI {
|
|
575
575
|
? selectedCollections.map((c) => c.$id)
|
576
576
|
: undefined,
|
577
577
|
shouldWriteFile,
|
578
|
-
checkDuplicates,
|
578
|
+
checkDuplicates: false,
|
579
|
+
// checkDuplicates,
|
579
580
|
});
|
580
581
|
}
|
581
582
|
|
@@ -637,19 +638,42 @@ export class InteractiveCLI {
|
|
637
638
|
targetDatabases = await fetchAllDatabases(targetClient);
|
638
639
|
} else {
|
639
640
|
targetClient = sourceClient;
|
640
|
-
|
641
|
+
const allDatabases = await fetchAllDatabases(sourceClient);
|
642
|
+
sourceDatabases = targetDatabases = allDatabases;
|
641
643
|
}
|
642
644
|
|
643
|
-
const
|
645
|
+
const fromDbs = await this.selectDatabases(
|
644
646
|
sourceDatabases,
|
645
647
|
"Select the source database:",
|
646
648
|
false
|
647
649
|
);
|
648
|
-
|
649
|
-
|
650
|
+
console.log(fromDbs);
|
651
|
+
const fromDb = fromDbs as unknown as {
|
652
|
+
$id: string;
|
653
|
+
name: string;
|
654
|
+
$createdAt: string;
|
655
|
+
$updatedAt: string;
|
656
|
+
enabled: boolean;
|
657
|
+
};
|
658
|
+
if (!fromDb) {
|
659
|
+
throw new Error("No source database selected");
|
660
|
+
}
|
661
|
+
const availableDbs = targetDatabases.filter((db) => db.$id !== fromDb.$id);
|
662
|
+
const targetDbs = await this.selectDatabases(
|
663
|
+
availableDbs,
|
650
664
|
"Select the target database:",
|
651
665
|
false
|
652
666
|
);
|
667
|
+
const targetDb = targetDbs as unknown as {
|
668
|
+
$id: string;
|
669
|
+
name: string;
|
670
|
+
$createdAt: string;
|
671
|
+
$updatedAt: string;
|
672
|
+
enabled: boolean;
|
673
|
+
};
|
674
|
+
if (!targetDb) {
|
675
|
+
throw new Error("No target database selected");
|
676
|
+
}
|
653
677
|
|
654
678
|
const selectedCollections = await this.selectCollections(
|
655
679
|
fromDb,
|
@@ -685,16 +709,18 @@ export class InteractiveCLI {
|
|
685
709
|
? await listBuckets(targetStorage)
|
686
710
|
: sourceBuckets;
|
687
711
|
|
688
|
-
|
712
|
+
const sourceBucketPicked = await this.selectBuckets(
|
689
713
|
sourceBuckets.buckets,
|
690
714
|
"Select the source bucket:",
|
691
715
|
false
|
692
716
|
);
|
693
|
-
|
717
|
+
const targetBucketPicked = await this.selectBuckets(
|
694
718
|
targetBuckets.buckets,
|
695
719
|
"Select the target bucket:",
|
696
720
|
false
|
697
721
|
);
|
722
|
+
sourceBucket = sourceBucketPicked as unknown as Models.Bucket;
|
723
|
+
targetBucket = targetBucketPicked as unknown as Models.Bucket;
|
698
724
|
}
|
699
725
|
|
700
726
|
let transferOptions: TransferOptions = {
|
@@ -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
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
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 +=
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
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
|
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
|
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
|
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
|
-
|
558
|
+
let toCollection: Models.Collection;
|
559
|
+
const toCollectionExists = await tryAwaitWithRetry(
|
559
560
|
async () =>
|
560
|
-
await remoteDb.
|
561
|
-
|
562
|
-
|
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
|
-
|
572
|
-
|
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
|
575
|
-
remoteDb,
|
592
|
+
await remoteDb.createCollection(
|
576
593
|
toDbId,
|
577
|
-
|
578
|
-
|
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
|
-
|
585
|
-
|
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(
|