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
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
updateDefs
|
|
243
|
-
|
|
244
|
-
|
|
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
|
}
|
package/dist/migrations/users.js
CHANGED
|
@@ -40,72 +40,79 @@ export class UsersController {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
async createUserAndReturn(item) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
75
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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
|
|
82
|
-
|
|
102
|
+
if (item.$createdAt && item.$updatedAt) {
|
|
103
|
+
console.log("$createdAt and $updatedAt are not yet supported, sorry about that!");
|
|
83
104
|
}
|
|
84
|
-
if (item.
|
|
85
|
-
userToReturn = await this.users.
|
|
105
|
+
if (item.labels && item.labels.length) {
|
|
106
|
+
userToReturn = await this.users.updateLabels(userToReturn.$id, item.labels);
|
|
86
107
|
}
|
|
87
|
-
if (item.
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
101
|
-
|
|
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.
|
|
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
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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;
|
package/src/migrations/users.ts
CHANGED
|
@@ -49,96 +49,105 @@ export class UsersController {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async createUserAndReturn(item: AuthUserCreate) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
93
|
-
|
|
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.
|
|
106
|
+
item.password.toLowerCase()
|
|
96
107
|
);
|
|
97
|
-
}
|
|
98
|
-
|
|
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
|
|
102
|
-
|
|
103
|
-
|
|
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.
|
|
108
|
-
userToReturn = await this.users.
|
|
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.
|
|
112
|
-
|
|
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
|
}
|