appwrite-utils-cli 0.0.15 → 0.0.17

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.
@@ -168,6 +168,10 @@ export class ImportController {
168
168
  return;
169
169
  }
170
170
  const user = await usersController.createUserAndReturn(userToCreate.data);
171
+ if (!user) {
172
+ logger.error(`Skipping user & contact creation for ${item} because of an error...`);
173
+ return;
174
+ }
171
175
  createIdToUse = user.$id;
172
176
  context.docId = createIdToUse;
173
177
  context = { ...context, ...user };
@@ -233,19 +237,29 @@ export class ImportController {
233
237
  async handleCreate(context, finalItem, updateDefs, id) {
234
238
  const existing = await documentExists(this.database, context.dbId, context.collId, finalItem);
235
239
  if (!existing) {
236
- const createdDoc = await this.database.createDocument(context.dbId, context.collId, id || ID.unique(), finalItem);
237
- context.docId = createdDoc.$id;
238
- context.createdDoc = createdDoc;
239
- context = { ...context, ...createdDoc };
240
- // Populate document cache for updates
241
- if (updateDefs) {
242
- updateDefs.forEach((def) => {
243
- if (def.updateMapping) {
244
- this.documentCache.set(`${finalItem[def.updateMapping.targetField]}`, context);
245
- }
246
- });
240
+ try {
241
+ const createdDoc = await this.database.createDocument(context.dbId, context.collId, id || ID.unique(), finalItem);
242
+ context.docId = createdDoc.$id;
243
+ context.createdDoc = createdDoc;
244
+ context = { ...context, ...createdDoc };
245
+ // Populate document cache for updates
246
+ if (updateDefs) {
247
+ updateDefs.forEach((def) => {
248
+ if (def.updateMapping) {
249
+ this.documentCache.set(`${finalItem[def.updateMapping.targetField]}`, context);
250
+ }
251
+ });
252
+ }
253
+ return context;
254
+ }
255
+ catch (error) {
256
+ logger.error(`An error occurred during creation -- ${context}, id: ${id}, ${finalItem}}`);
257
+ if (error.type === "document_already_exists") {
258
+ logger.warn(`Document already exists, retrying creation. -- ${context}, id: ${id}, ${finalItem}}`);
259
+ await this.handleCreate(context, finalItem, updateDefs, ID.unique());
260
+ }
261
+ return;
247
262
  }
248
- return context;
249
263
  }
250
264
  else {
251
265
  console.log("Document already exists, skipping creation.");
@@ -7,5 +7,5 @@ export declare class UsersController {
7
7
  static userFields: string[];
8
8
  constructor(config: AppwriteConfig, db: Databases);
9
9
  wipeUsers(): Promise<void>;
10
- createUserAndReturn(item: AuthUserCreate): Promise<Models.User<Models.Preferences>>;
10
+ createUserAndReturn(item: AuthUserCreate): Promise<Models.User<Models.Preferences> | undefined>;
11
11
  }
@@ -40,72 +40,79 @@ export class UsersController {
40
40
  }
41
41
  }
42
42
  async createUserAndReturn(item) {
43
- // Attempt to find an existing user by email or phone.
44
- let foundUsers = [];
45
- if (item.email) {
46
- const foundUsersByEmail = await this.users.list([
47
- Query.equal("email", item.email),
48
- ]);
49
- foundUsers = foundUsersByEmail.users;
50
- }
51
- if (item.phone) {
52
- const foundUsersByPhone = await this.users.list([
53
- Query.equal("phone", item.phone),
54
- ]);
55
- foundUsers = foundUsers.length
56
- ? foundUsers.concat(foundUsersByPhone.users)
57
- : foundUsersByPhone.users;
58
- }
59
- let userToReturn = foundUsers[0] || undefined;
60
- if (!userToReturn) {
61
- userToReturn = await this.users.create(item.userId || ID.unique(), item.email || undefined, item.phone && item.phone.length < 15 && item.phone.startsWith("+")
62
- ? item.phone
63
- : undefined, item.password?.toLowerCase() || `changeMe${item.email}`.toLowerCase(), item.name || undefined);
64
- }
65
- else {
66
- // Update user details as necessary, ensuring email uniqueness if attempting an update.
67
- if (item.email &&
68
- item.email !== userToReturn.email &&
69
- !_.isEmpty(item.email) &&
70
- !_.isUndefined(item.email)) {
71
- const emailExists = await this.users.list([
43
+ let userToReturn = undefined;
44
+ try {
45
+ // Attempt to find an existing user by email or phone.
46
+ let foundUsers = [];
47
+ if (item.email) {
48
+ const foundUsersByEmail = await this.users.list([
72
49
  Query.equal("email", item.email),
73
50
  ]);
74
- if (emailExists.users.length === 0) {
75
- userToReturn = await this.users.updateEmail(userToReturn.$id, item.email);
51
+ foundUsers = foundUsersByEmail.users;
52
+ }
53
+ if (item.phone) {
54
+ const foundUsersByPhone = await this.users.list([
55
+ Query.equal("phone", item.phone),
56
+ ]);
57
+ foundUsers = foundUsers.length
58
+ ? foundUsers.concat(foundUsersByPhone.users)
59
+ : foundUsersByPhone.users;
60
+ }
61
+ userToReturn = foundUsers[0] || undefined;
62
+ if (!userToReturn) {
63
+ userToReturn = await this.users.create(item.userId || ID.unique(), item.email || undefined, item.phone && item.phone.length < 15 && item.phone.startsWith("+")
64
+ ? item.phone
65
+ : undefined, item.password?.toLowerCase() || `changeMe${item.email}`.toLowerCase(), item.name || undefined);
66
+ }
67
+ else {
68
+ // Update user details as necessary, ensuring email uniqueness if attempting an update.
69
+ if (item.email &&
70
+ item.email !== userToReturn.email &&
71
+ !_.isEmpty(item.email) &&
72
+ !_.isUndefined(item.email)) {
73
+ const emailExists = await this.users.list([
74
+ Query.equal("email", item.email),
75
+ ]);
76
+ if (emailExists.users.length === 0) {
77
+ userToReturn = await this.users.updateEmail(userToReturn.$id, item.email);
78
+ }
79
+ else {
80
+ console.log("Email update skipped: Email already exists.");
81
+ }
82
+ }
83
+ if (item.password) {
84
+ userToReturn = await this.users.updatePassword(userToReturn.$id, item.password.toLowerCase());
76
85
  }
77
- else {
78
- console.log("Email update skipped: Email already exists.");
86
+ if (item.name && item.name !== userToReturn.name) {
87
+ userToReturn = await this.users.updateName(userToReturn.$id, item.name);
88
+ }
89
+ if (item.phone &&
90
+ item.phone !== userToReturn.phone &&
91
+ item.phone.length < 15 &&
92
+ item.phone.startsWith("+") &&
93
+ (_.isUndefined(userToReturn.phone) || _.isEmpty(userToReturn.phone))) {
94
+ const userFoundWithPhone = await this.users.list([
95
+ Query.equal("phone", item.phone),
96
+ ]);
97
+ if (userFoundWithPhone.total === 0) {
98
+ userToReturn = await this.users.updatePhone(userToReturn.$id, item.phone);
99
+ }
79
100
  }
80
101
  }
81
- if (item.password) {
82
- userToReturn = await this.users.updatePassword(userToReturn.$id, item.password.toLowerCase());
102
+ if (item.$createdAt && item.$updatedAt) {
103
+ console.log("$createdAt and $updatedAt are not yet supported, sorry about that!");
83
104
  }
84
- if (item.name && item.name !== userToReturn.name) {
85
- userToReturn = await this.users.updateName(userToReturn.$id, item.name);
105
+ if (item.labels && item.labels.length) {
106
+ userToReturn = await this.users.updateLabels(userToReturn.$id, item.labels);
86
107
  }
87
- if (item.phone &&
88
- item.phone !== userToReturn.phone &&
89
- item.phone.length < 15 &&
90
- item.phone.startsWith("+") &&
91
- (_.isUndefined(userToReturn.phone) || _.isEmpty(userToReturn.phone))) {
92
- const userFoundWithPhone = await this.users.list([
93
- Query.equal("phone", item.phone),
94
- ]);
95
- if (userFoundWithPhone.total === 0) {
96
- userToReturn = await this.users.updatePhone(userToReturn.$id, item.phone);
97
- }
108
+ if (item.prefs && Object.keys(item.prefs).length) {
109
+ await this.users.updatePrefs(userToReturn.$id, item.prefs);
110
+ userToReturn.prefs = item.prefs;
98
111
  }
112
+ return userToReturn;
99
113
  }
100
- if (item.$createdAt && item.$updatedAt) {
101
- console.log("$createdAt and $updatedAt are not yet supported, sorry about that!");
102
- }
103
- if (item.labels && item.labels.length) {
104
- userToReturn = await this.users.updateLabels(userToReturn.$id, item.labels);
105
- }
106
- if (item.prefs && Object.keys(item.prefs).length) {
107
- userToReturn = await this.users.updatePrefs(userToReturn.$id, item.prefs);
114
+ catch (error) {
115
+ return userToReturn;
108
116
  }
109
- return userToReturn;
110
117
  }
111
118
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "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": "0.0.15",
4
+ "version": "0.0.17",
5
5
  "main": "src/main.ts",
6
6
  "type": "module",
7
7
  "repository": {
@@ -284,6 +284,12 @@ export class ImportController {
284
284
  const user = await usersController.createUserAndReturn(
285
285
  userToCreate.data
286
286
  );
287
+ if (!user) {
288
+ logger.error(
289
+ `Skipping user & contact creation for ${item} because of an error...`
290
+ );
291
+ return;
292
+ }
287
293
  createIdToUse = user.$id;
288
294
  context.docId = createIdToUse;
289
295
  context = { ...context, ...user };
@@ -393,28 +399,41 @@ export class ImportController {
393
399
  finalItem
394
400
  );
395
401
  if (!existing) {
396
- const createdDoc = await this.database.createDocument(
397
- context.dbId,
398
- context.collId,
399
- id || ID.unique(),
400
- finalItem
401
- );
402
- context.docId = createdDoc.$id;
403
- context.createdDoc = createdDoc;
404
- context = { ...context, ...createdDoc };
402
+ try {
403
+ const createdDoc = await this.database.createDocument(
404
+ context.dbId,
405
+ context.collId,
406
+ id || ID.unique(),
407
+ finalItem
408
+ );
409
+ context.docId = createdDoc.$id;
410
+ context.createdDoc = createdDoc;
411
+ context = { ...context, ...createdDoc };
405
412
 
406
- // Populate document cache for updates
407
- if (updateDefs) {
408
- updateDefs.forEach((def) => {
409
- if (def.updateMapping) {
410
- this.documentCache.set(
411
- `${finalItem[def.updateMapping.targetField]}`,
412
- context
413
- );
414
- }
415
- });
413
+ // Populate document cache for updates
414
+ if (updateDefs) {
415
+ updateDefs.forEach((def) => {
416
+ if (def.updateMapping) {
417
+ this.documentCache.set(
418
+ `${finalItem[def.updateMapping.targetField]}`,
419
+ context
420
+ );
421
+ }
422
+ });
423
+ }
424
+ return context;
425
+ } catch (error: any) {
426
+ logger.error(
427
+ `An error occurred during creation -- ${context}, id: ${id}, ${finalItem}}`
428
+ );
429
+ if (error.type === "document_already_exists") {
430
+ logger.warn(
431
+ `Document already exists, retrying creation. -- ${context}, id: ${id}, ${finalItem}}`
432
+ );
433
+ await this.handleCreate(context, finalItem, updateDefs, ID.unique());
434
+ }
435
+ return;
416
436
  }
417
- return context;
418
437
  } else {
419
438
  console.log("Document already exists, skipping creation.");
420
439
  return existing;
@@ -49,96 +49,105 @@ export class UsersController {
49
49
  }
50
50
 
51
51
  async createUserAndReturn(item: AuthUserCreate) {
52
- // Attempt to find an existing user by email or phone.
53
- let foundUsers: Models.User<Models.Preferences>[] = [];
54
- if (item.email) {
55
- const foundUsersByEmail = await this.users.list([
56
- Query.equal("email", item.email),
57
- ]);
58
- foundUsers = foundUsersByEmail.users;
59
- }
60
- if (item.phone) {
61
- const foundUsersByPhone = await this.users.list([
62
- Query.equal("phone", item.phone),
63
- ]);
64
- foundUsers = foundUsers.length
65
- ? foundUsers.concat(foundUsersByPhone.users)
66
- : foundUsersByPhone.users;
67
- }
68
-
69
- let userToReturn = foundUsers[0] || undefined;
70
-
71
- if (!userToReturn) {
72
- userToReturn = await this.users.create(
73
- item.userId || ID.unique(),
74
- item.email || undefined,
75
- item.phone && item.phone.length < 15 && item.phone.startsWith("+")
76
- ? item.phone
77
- : undefined,
78
- item.password?.toLowerCase() || `changeMe${item.email}`.toLowerCase(),
79
- item.name || undefined
80
- );
81
- } else {
82
- // Update user details as necessary, ensuring email uniqueness if attempting an update.
83
- if (
84
- item.email &&
85
- item.email !== userToReturn.email &&
86
- !_.isEmpty(item.email) &&
87
- !_.isUndefined(item.email)
88
- ) {
89
- const emailExists = await this.users.list([
52
+ let userToReturn: Models.User<Models.Preferences> | undefined = undefined;
53
+ try {
54
+ // Attempt to find an existing user by email or phone.
55
+ let foundUsers: Models.User<Models.Preferences>[] = [];
56
+ if (item.email) {
57
+ const foundUsersByEmail = await this.users.list([
90
58
  Query.equal("email", item.email),
91
59
  ]);
92
- if (emailExists.users.length === 0) {
93
- userToReturn = await this.users.updateEmail(
60
+ foundUsers = foundUsersByEmail.users;
61
+ }
62
+ if (item.phone) {
63
+ const foundUsersByPhone = await this.users.list([
64
+ Query.equal("phone", item.phone),
65
+ ]);
66
+ foundUsers = foundUsers.length
67
+ ? foundUsers.concat(foundUsersByPhone.users)
68
+ : foundUsersByPhone.users;
69
+ }
70
+
71
+ userToReturn = foundUsers[0] || undefined;
72
+
73
+ if (!userToReturn) {
74
+ userToReturn = await this.users.create(
75
+ item.userId || ID.unique(),
76
+ item.email || undefined,
77
+ item.phone && item.phone.length < 15 && item.phone.startsWith("+")
78
+ ? item.phone
79
+ : undefined,
80
+ item.password?.toLowerCase() || `changeMe${item.email}`.toLowerCase(),
81
+ item.name || undefined
82
+ );
83
+ } else {
84
+ // Update user details as necessary, ensuring email uniqueness if attempting an update.
85
+ if (
86
+ item.email &&
87
+ item.email !== userToReturn.email &&
88
+ !_.isEmpty(item.email) &&
89
+ !_.isUndefined(item.email)
90
+ ) {
91
+ const emailExists = await this.users.list([
92
+ Query.equal("email", item.email),
93
+ ]);
94
+ if (emailExists.users.length === 0) {
95
+ userToReturn = await this.users.updateEmail(
96
+ userToReturn.$id,
97
+ item.email
98
+ );
99
+ } else {
100
+ console.log("Email update skipped: Email already exists.");
101
+ }
102
+ }
103
+ if (item.password) {
104
+ userToReturn = await this.users.updatePassword(
94
105
  userToReturn.$id,
95
- item.email
106
+ item.password.toLowerCase()
96
107
  );
97
- } else {
98
- console.log("Email update skipped: Email already exists.");
108
+ }
109
+ if (item.name && item.name !== userToReturn.name) {
110
+ userToReturn = await this.users.updateName(
111
+ userToReturn.$id,
112
+ item.name
113
+ );
114
+ }
115
+ if (
116
+ item.phone &&
117
+ item.phone !== userToReturn.phone &&
118
+ item.phone.length < 15 &&
119
+ item.phone.startsWith("+") &&
120
+ (_.isUndefined(userToReturn.phone) || _.isEmpty(userToReturn.phone))
121
+ ) {
122
+ const userFoundWithPhone = await this.users.list([
123
+ Query.equal("phone", item.phone),
124
+ ]);
125
+ if (userFoundWithPhone.total === 0) {
126
+ userToReturn = await this.users.updatePhone(
127
+ userToReturn.$id,
128
+ item.phone
129
+ );
130
+ }
99
131
  }
100
132
  }
101
- if (item.password) {
102
- userToReturn = await this.users.updatePassword(
103
- userToReturn.$id,
104
- item.password.toLowerCase()
133
+ if (item.$createdAt && item.$updatedAt) {
134
+ console.log(
135
+ "$createdAt and $updatedAt are not yet supported, sorry about that!"
105
136
  );
106
137
  }
107
- if (item.name && item.name !== userToReturn.name) {
108
- userToReturn = await this.users.updateName(userToReturn.$id, item.name);
138
+ if (item.labels && item.labels.length) {
139
+ userToReturn = await this.users.updateLabels(
140
+ userToReturn.$id,
141
+ item.labels
142
+ );
109
143
  }
110
- if (
111
- item.phone &&
112
- item.phone !== userToReturn.phone &&
113
- item.phone.length < 15 &&
114
- item.phone.startsWith("+") &&
115
- (_.isUndefined(userToReturn.phone) || _.isEmpty(userToReturn.phone))
116
- ) {
117
- const userFoundWithPhone = await this.users.list([
118
- Query.equal("phone", item.phone),
119
- ]);
120
- if (userFoundWithPhone.total === 0) {
121
- userToReturn = await this.users.updatePhone(
122
- userToReturn.$id,
123
- item.phone
124
- );
125
- }
144
+ if (item.prefs && Object.keys(item.prefs).length) {
145
+ await this.users.updatePrefs(userToReturn.$id, item.prefs);
146
+ userToReturn.prefs = item.prefs;
126
147
  }
148
+ return userToReturn;
149
+ } catch (error) {
150
+ return userToReturn;
127
151
  }
128
- if (item.$createdAt && item.$updatedAt) {
129
- console.log(
130
- "$createdAt and $updatedAt are not yet supported, sorry about that!"
131
- );
132
- }
133
- if (item.labels && item.labels.length) {
134
- userToReturn = await this.users.updateLabels(
135
- userToReturn.$id,
136
- item.labels
137
- );
138
- }
139
- if (item.prefs && Object.keys(item.prefs).length) {
140
- userToReturn = await this.users.updatePrefs(userToReturn.$id, item.prefs);
141
- }
142
- return userToReturn;
143
152
  }
144
153
  }