appwrite-utils-cli 0.0.47 → 0.0.49

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.
@@ -15,7 +15,10 @@ import {
15
15
  import _ from "lodash";
16
16
  import { logger } from "./logging.js";
17
17
  import { splitIntoBatches } from "./migrationHelper.js";
18
- import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
18
+ import {
19
+ getAppwriteClient,
20
+ tryAwaitWithRetry,
21
+ } from "../utils/helperFunctions.js";
19
22
 
20
23
  export class UsersController {
21
24
  private config: AppwriteConfig;
@@ -294,4 +297,66 @@ export class UsersController {
294
297
  }
295
298
  }
296
299
  }
300
+
301
+ transferUsersBetweenDbsLocalToRemote = async (
302
+ endpoint: string,
303
+ projectId: string,
304
+ apiKey: string
305
+ ) => {
306
+ const localUsers = this.users;
307
+ const client = getAppwriteClient(endpoint, projectId, apiKey);
308
+ const remoteUsers = new Users(client);
309
+
310
+ let fromUsers = await localUsers.list([Query.limit(50)]);
311
+
312
+ if (fromUsers.users.length === 0) {
313
+ console.log(`No users found`);
314
+ return;
315
+ } else if (fromUsers.users.length < 50) {
316
+ console.log(`Transferring ${fromUsers.users.length} users to remote`);
317
+ const batchedPromises = fromUsers.users.map((user) => {
318
+ return tryAwaitWithRetry(async () => {
319
+ const toCreateObject: Partial<typeof user> = {
320
+ ...user,
321
+ };
322
+ delete toCreateObject.$id;
323
+ delete toCreateObject.$createdAt;
324
+ delete toCreateObject.$updatedAt;
325
+ await remoteUsers.create(
326
+ user.$id,
327
+ user.email,
328
+ user.phone,
329
+ user.password,
330
+ user.name
331
+ );
332
+ });
333
+ });
334
+ await Promise.all(batchedPromises);
335
+ } else {
336
+ while (fromUsers.users.length === 50) {
337
+ fromUsers = await localUsers.list([
338
+ Query.limit(50),
339
+ Query.cursorAfter(fromUsers.users[fromUsers.users.length - 1].$id),
340
+ ]);
341
+ const batchedPromises = fromUsers.users.map((user) => {
342
+ return tryAwaitWithRetry(async () => {
343
+ const toCreateObject: Partial<typeof user> = {
344
+ ...user,
345
+ };
346
+ delete toCreateObject.$id;
347
+ delete toCreateObject.$createdAt;
348
+ delete toCreateObject.$updatedAt;
349
+ await remoteUsers.create(
350
+ user.$id,
351
+ user.email,
352
+ user.phone,
353
+ user.password,
354
+ user.name
355
+ );
356
+ });
357
+ });
358
+ await Promise.all(batchedPromises);
359
+ }
360
+ }
361
+ };
297
362
  }
@@ -1,4 +1,9 @@
1
- import { AppwriteException, type Models, type Storage } from "node-appwrite";
1
+ import {
2
+ AppwriteException,
3
+ Client,
4
+ type Models,
5
+ type Storage,
6
+ } from "node-appwrite";
2
7
  import fs from "node:fs";
3
8
  import path from "node:path";
4
9
  import type { CollectionImportData } from "../migrations/dataLoader.js";
@@ -162,3 +167,14 @@ export const tryAwaitWithRetry = async <T>(
162
167
  return Promise.resolve();
163
168
  }
164
169
  };
170
+
171
+ export const getAppwriteClient = (
172
+ endpoint: string,
173
+ projectId: string,
174
+ apiKey: string
175
+ ) => {
176
+ return new Client()
177
+ .setEndpoint(endpoint)
178
+ .setProject(projectId)
179
+ .setKey(apiKey);
180
+ };
@@ -20,6 +20,19 @@ import _ from "lodash";
20
20
  import { AppwriteToX } from "./migrations/appwriteToX.js";
21
21
  import { loadConfig as loadTsConfig } from "./utils/loadConfigs.js";
22
22
  import { findAppwriteConfig } from "./utils/loadConfigs.js";
23
+ import {
24
+ transferDocumentsBetweenDbsLocalToLocal,
25
+ transferDocumentsBetweenDbsLocalToRemote,
26
+ } from "./migrations/collections.js";
27
+ import { UsersController } from "./migrations/users.js";
28
+ import {
29
+ transferDatabaseLocalToLocal,
30
+ transferDatabaseLocalToRemote,
31
+ } from "./migrations/databases.js";
32
+ import {
33
+ transferStorageLocalToLocal,
34
+ transferStorageLocalToRemote,
35
+ } from "./migrations/storage.js";
23
36
 
24
37
  // async function loadConfig(configPath: string) {
25
38
  // if (!fs.existsSync(configPath)) {
@@ -48,6 +61,17 @@ export interface SetupOptions {
48
61
  endpoint?: string;
49
62
  project?: string;
50
63
  key?: string;
64
+ transfer?: boolean;
65
+ transferEndpoint?: string;
66
+ transferProject?: string;
67
+ transferKey?: string;
68
+ fromDbId?: string;
69
+ targetDbId?: string;
70
+ fromCollection?: string;
71
+ collection?: string;
72
+ transferUsers?: boolean;
73
+ fromBucket?: string;
74
+ targetBucket?: string;
51
75
  }
52
76
 
53
77
  export class UtilsController {
@@ -140,6 +164,122 @@ export class UtilsController {
140
164
  throw new Error("Database or storage not initialized");
141
165
  }
142
166
 
167
+ if (options.transfer) {
168
+ if (options.fromCollection) {
169
+ if (
170
+ options.transferEndpoint &&
171
+ options.transferProject &&
172
+ options.transferKey
173
+ ) {
174
+ if (options.transferUsers) {
175
+ console.log(
176
+ `Transferring users from local database ${options.fromDbId} to remote database ${options.targetDbId} on endpoint ${options.transferEndpoint}...`
177
+ );
178
+ const usersController = new UsersController(
179
+ this.config,
180
+ this.database
181
+ );
182
+ await usersController.transferUsersBetweenDbsLocalToRemote(
183
+ options.transferEndpoint,
184
+ options.transferProject,
185
+ options.transferKey
186
+ );
187
+ }
188
+ console.log("Transferring documents to remote database...");
189
+ await transferDocumentsBetweenDbsLocalToRemote(
190
+ this.database,
191
+ options.transferEndpoint,
192
+ options.transferProject,
193
+ options.transferKey,
194
+ options.fromDbId!,
195
+ options.targetDbId!,
196
+ options.fromCollection!,
197
+ options.collection!
198
+ );
199
+ } else {
200
+ console.log("Transferring documents between local databases...");
201
+ await transferDocumentsBetweenDbsLocalToLocal(
202
+ this.database,
203
+ options.fromDbId!,
204
+ options.targetDbId!,
205
+ options.fromCollection!,
206
+ options.collection!
207
+ );
208
+ }
209
+ } else if (options.fromDbId && options.targetDbId) {
210
+ if (
211
+ options.transferEndpoint &&
212
+ options.transferProject &&
213
+ options.transferKey
214
+ ) {
215
+ if (options.transferUsers) {
216
+ console.log(
217
+ `Transferring users from local database ${options.fromDbId} to remote database ${options.targetDbId} on endpoint ${options.transferEndpoint}...`
218
+ );
219
+ const usersController = new UsersController(
220
+ this.config,
221
+ this.database
222
+ );
223
+ await usersController.transferUsersBetweenDbsLocalToRemote(
224
+ options.transferEndpoint,
225
+ options.transferProject,
226
+ options.transferKey
227
+ );
228
+ }
229
+ console.log(
230
+ `Transferring databases from local database ${options.fromDbId} to remote database ${options.targetDbId} on endpoint ${options.transferEndpoint}...`
231
+ );
232
+ await transferDatabaseLocalToRemote(
233
+ this.database,
234
+ options.transferEndpoint,
235
+ options.transferProject,
236
+ options.transferKey,
237
+ options.fromDbId!,
238
+ options.targetDbId!
239
+ );
240
+ } else {
241
+ console.log(
242
+ `Transferring databases from local database ${options.fromDbId} to local database ${options.targetDbId}`
243
+ );
244
+ await transferDatabaseLocalToLocal(
245
+ this.database,
246
+ options.fromDbId!,
247
+ options.targetDbId!
248
+ );
249
+ }
250
+ }
251
+ if (options.fromBucket && options.targetBucket) {
252
+ if (
253
+ options.transferEndpoint &&
254
+ options.transferProject &&
255
+ options.transferKey
256
+ ) {
257
+ console.log(
258
+ `Transferring files from bucket ${options.fromBucket} to bucket ${options.targetBucket} on endpoint ${options.transferEndpoint}...`
259
+ );
260
+ await transferStorageLocalToRemote(
261
+ this.storage,
262
+ options.transferEndpoint,
263
+ options.transferProject,
264
+ options.transferKey,
265
+ options.fromBucket,
266
+ options.targetBucket
267
+ );
268
+ } else {
269
+ console.log(
270
+ `Transferring files from bucket ${options.fromBucket} to bucket ${options.targetBucket}...`
271
+ );
272
+ await transferStorageLocalToLocal(
273
+ this.storage,
274
+ options.fromBucket,
275
+ options.targetBucket
276
+ );
277
+ }
278
+ }
279
+ console.log("Transfer complete.");
280
+ return;
281
+ }
282
+
143
283
  if (options.sync) {
144
284
  console.log("Starting synchronization with server...");
145
285
  const appwriteToX = new AppwriteToX(this.config, this.appwriteFolderPath);