appwrite-utils-cli 0.0.1

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.
Files changed (86) hide show
  1. package/README.md +80 -0
  2. package/dist/main.d.ts +2 -0
  3. package/dist/main.js +74 -0
  4. package/dist/migrations/afterImportActions.d.ts +12 -0
  5. package/dist/migrations/afterImportActions.js +196 -0
  6. package/dist/migrations/attributes.d.ts +4 -0
  7. package/dist/migrations/attributes.js +158 -0
  8. package/dist/migrations/backup.d.ts +621 -0
  9. package/dist/migrations/backup.js +159 -0
  10. package/dist/migrations/collections.d.ts +16 -0
  11. package/dist/migrations/collections.js +207 -0
  12. package/dist/migrations/converters.d.ts +179 -0
  13. package/dist/migrations/converters.js +575 -0
  14. package/dist/migrations/dbHelpers.d.ts +5 -0
  15. package/dist/migrations/dbHelpers.js +54 -0
  16. package/dist/migrations/importController.d.ts +44 -0
  17. package/dist/migrations/importController.js +312 -0
  18. package/dist/migrations/importDataActions.d.ts +44 -0
  19. package/dist/migrations/importDataActions.js +219 -0
  20. package/dist/migrations/indexes.d.ts +4 -0
  21. package/dist/migrations/indexes.js +18 -0
  22. package/dist/migrations/logging.d.ts +2 -0
  23. package/dist/migrations/logging.js +14 -0
  24. package/dist/migrations/migrationHelper.d.ts +18 -0
  25. package/dist/migrations/migrationHelper.js +66 -0
  26. package/dist/migrations/queue.d.ts +13 -0
  27. package/dist/migrations/queue.js +79 -0
  28. package/dist/migrations/relationships.d.ts +90 -0
  29. package/dist/migrations/relationships.js +209 -0
  30. package/dist/migrations/schema.d.ts +3142 -0
  31. package/dist/migrations/schema.js +485 -0
  32. package/dist/migrations/schemaStrings.d.ts +12 -0
  33. package/dist/migrations/schemaStrings.js +261 -0
  34. package/dist/migrations/setupDatabase.d.ts +7 -0
  35. package/dist/migrations/setupDatabase.js +151 -0
  36. package/dist/migrations/storage.d.ts +8 -0
  37. package/dist/migrations/storage.js +241 -0
  38. package/dist/migrations/users.d.ts +11 -0
  39. package/dist/migrations/users.js +114 -0
  40. package/dist/migrations/validationRules.d.ts +43 -0
  41. package/dist/migrations/validationRules.js +42 -0
  42. package/dist/schemas/authUser.d.ts +62 -0
  43. package/dist/schemas/authUser.js +17 -0
  44. package/dist/setup.d.ts +2 -0
  45. package/dist/setup.js +5 -0
  46. package/dist/types.d.ts +9 -0
  47. package/dist/types.js +5 -0
  48. package/dist/utils/configSchema.json +742 -0
  49. package/dist/utils/helperFunctions.d.ts +34 -0
  50. package/dist/utils/helperFunctions.js +72 -0
  51. package/dist/utils/index.d.ts +2 -0
  52. package/dist/utils/index.js +2 -0
  53. package/dist/utils/setupFiles.d.ts +2 -0
  54. package/dist/utils/setupFiles.js +276 -0
  55. package/dist/utilsController.d.ts +30 -0
  56. package/dist/utilsController.js +106 -0
  57. package/package.json +34 -0
  58. package/src/main.ts +77 -0
  59. package/src/migrations/afterImportActions.ts +300 -0
  60. package/src/migrations/attributes.ts +315 -0
  61. package/src/migrations/backup.ts +189 -0
  62. package/src/migrations/collections.ts +303 -0
  63. package/src/migrations/converters.ts +628 -0
  64. package/src/migrations/dbHelpers.ts +89 -0
  65. package/src/migrations/importController.ts +509 -0
  66. package/src/migrations/importDataActions.ts +313 -0
  67. package/src/migrations/indexes.ts +37 -0
  68. package/src/migrations/logging.ts +15 -0
  69. package/src/migrations/migrationHelper.ts +100 -0
  70. package/src/migrations/queue.ts +119 -0
  71. package/src/migrations/relationships.ts +336 -0
  72. package/src/migrations/schema.ts +590 -0
  73. package/src/migrations/schemaStrings.ts +310 -0
  74. package/src/migrations/setupDatabase.ts +219 -0
  75. package/src/migrations/storage.ts +351 -0
  76. package/src/migrations/users.ts +148 -0
  77. package/src/migrations/validationRules.ts +63 -0
  78. package/src/schemas/authUser.ts +23 -0
  79. package/src/setup.ts +8 -0
  80. package/src/types.ts +14 -0
  81. package/src/utils/configSchema.json +742 -0
  82. package/src/utils/helperFunctions.ts +111 -0
  83. package/src/utils/index.ts +2 -0
  84. package/src/utils/setupFiles.ts +295 -0
  85. package/src/utilsController.ts +173 -0
  86. package/tsconfig.json +37 -0
@@ -0,0 +1,485 @@
1
+ import { ID, IndexType } from "node-appwrite";
2
+ import { z } from "zod";
3
+ const stringAttributeSchema = z.object({
4
+ key: z.string().describe("The key of the attribute"),
5
+ type: z
6
+ .literal("string")
7
+ .describe("The type of the attribute")
8
+ .default("string"),
9
+ error: z
10
+ .string()
11
+ .describe("The error message if the attribute is invalid")
12
+ .default("Invalid String Attribute Schema"),
13
+ required: z
14
+ .boolean()
15
+ .describe("Whether the attribute is required or not")
16
+ .default(false),
17
+ array: z
18
+ .boolean()
19
+ .optional()
20
+ .default(false)
21
+ .describe("Whether the attribute is an array or not"),
22
+ size: z
23
+ .number()
24
+ .describe("The max length or size of the attribute")
25
+ .optional()
26
+ .default(50),
27
+ xdefault: z.string().nullish().describe("The default value of the attribute"),
28
+ encrypted: z
29
+ .boolean()
30
+ .optional()
31
+ .describe("Whether the attribute is encrypted or not"),
32
+ });
33
+ const integerAttributeSchema = z.object({
34
+ key: z.string().describe("The key of the attribute"),
35
+ type: z
36
+ .literal("integer")
37
+ .describe("The type of the attribute")
38
+ .default("integer"),
39
+ error: z
40
+ .string()
41
+ .describe("The error message if the attribute is invalid")
42
+ .default("Invalid Integer Attribute Schema"),
43
+ required: z
44
+ .boolean()
45
+ .describe("Whether the attribute is required or not")
46
+ .default(false),
47
+ array: z
48
+ .boolean()
49
+ .optional()
50
+ .default(false)
51
+ .describe("Whether the attribute is an array or not"),
52
+ min: z
53
+ .number()
54
+ .int()
55
+ .optional()
56
+ .describe("The minimum value of the attribute"),
57
+ max: z
58
+ .number()
59
+ .int()
60
+ .optional()
61
+ .describe("The maximum value of the attribute"),
62
+ xdefault: z
63
+ .number()
64
+ .int()
65
+ .nullish()
66
+ .describe("The default value of the attribute"),
67
+ });
68
+ const floatAttributeSchema = z.object({
69
+ key: z.string().describe("The key of the attribute"),
70
+ type: z
71
+ .literal("float")
72
+ .describe("The type of the attribute")
73
+ .default("float"),
74
+ error: z
75
+ .string()
76
+ .describe("The error message if the attribute is invalid")
77
+ .default("Invalid Float Attribute Schema"),
78
+ required: z
79
+ .boolean()
80
+ .describe("Whether the attribute is required or not")
81
+ .default(false),
82
+ array: z
83
+ .boolean()
84
+ .optional()
85
+ .default(false)
86
+ .describe("Whether the attribute is an array or not"),
87
+ min: z.number().optional().describe("The minimum value of the attribute"),
88
+ max: z.number().optional().describe("The maximum value of the attribute"),
89
+ xdefault: z.number().nullish().describe("The default value of the attribute"),
90
+ });
91
+ const booleanAttributeSchema = z.object({
92
+ key: z.string().describe("The key of the attribute"),
93
+ type: z
94
+ .literal("boolean")
95
+ .describe("The type of the attribute")
96
+ .default("boolean"),
97
+ error: z
98
+ .string()
99
+ .describe("The error message if the attribute is invalid")
100
+ .default("Invalid Boolean Attribute Schema"),
101
+ required: z
102
+ .boolean()
103
+ .describe("Whether the attribute is required or not")
104
+ .default(false),
105
+ array: z
106
+ .boolean()
107
+ .optional()
108
+ .default(false)
109
+ .describe("Whether the attribute is an array or not"),
110
+ xdefault: z
111
+ .boolean()
112
+ .nullish()
113
+ .describe("The default value of the attribute"),
114
+ });
115
+ const datetimeAttributeSchema = z.object({
116
+ key: z.string().describe("The key of the attribute"),
117
+ type: z
118
+ .literal("datetime")
119
+ .describe("The type of the attribute")
120
+ .default("datetime"),
121
+ error: z
122
+ .string()
123
+ .describe("The error message if the attribute is invalid")
124
+ .default("Invalid Datetime Attribute Schema"),
125
+ required: z
126
+ .boolean()
127
+ .describe("Whether the attribute is required or not")
128
+ .default(false),
129
+ array: z
130
+ .boolean()
131
+ .optional()
132
+ .default(false)
133
+ .describe("Whether the attribute is an array or not"),
134
+ xdefault: z.string().nullish().describe("The default value of the attribute"),
135
+ });
136
+ const emailAttributeSchema = z.object({
137
+ key: z.string().describe("The key of the attribute"),
138
+ type: z
139
+ .literal("email")
140
+ .describe("The type of the attribute")
141
+ .default("email"),
142
+ error: z
143
+ .string()
144
+ .describe("The error message if the attribute is invalid")
145
+ .default("Invalid Email Attribute Schema"),
146
+ required: z
147
+ .boolean()
148
+ .describe("Whether the attribute is required or not")
149
+ .default(false),
150
+ array: z
151
+ .boolean()
152
+ .optional()
153
+ .default(false)
154
+ .describe("Whether the attribute is an array or not"),
155
+ xdefault: z.string().nullish().describe("The default value of the attribute"),
156
+ });
157
+ const ipAttributeSchema = z.object({
158
+ key: z.string().describe("The key of the attribute"),
159
+ type: z.literal("ip").describe("The type of the attribute"),
160
+ error: z
161
+ .string()
162
+ .describe("The error message if the attribute is invalid")
163
+ .default("Invalid IP Attribute Schema"),
164
+ required: z
165
+ .boolean()
166
+ .describe("Whether the attribute is required or not")
167
+ .default(false),
168
+ array: z
169
+ .boolean()
170
+ .optional()
171
+ .default(false)
172
+ .describe("Whether the attribute is an array or not"),
173
+ xdefault: z.string().nullish().describe("The default value of the attribute"),
174
+ });
175
+ const urlAttributeSchema = z.object({
176
+ key: z.string().describe("The key of the attribute"),
177
+ type: z.literal("url").describe("The type of the attribute").default("url"),
178
+ error: z
179
+ .string()
180
+ .describe("The error message if the attribute is invalid")
181
+ .default("Invalid URL Attribute Schema"),
182
+ required: z
183
+ .boolean()
184
+ .describe("Whether the attribute is required or not")
185
+ .default(false),
186
+ array: z
187
+ .boolean()
188
+ .optional()
189
+ .default(false)
190
+ .describe("Whether the attribute is an array or not"),
191
+ xdefault: z.string().nullish().describe("The default value of the attribute"),
192
+ });
193
+ const enumAttributeSchema = z.object({
194
+ key: z.string().describe("The key of the attribute"),
195
+ type: z.literal("enum").describe("The type of the attribute").default("enum"),
196
+ error: z
197
+ .string()
198
+ .describe("The error message if the attribute is invalid")
199
+ .default("Invalid Enum Attribute Schema"),
200
+ required: z
201
+ .boolean()
202
+ .describe("Whether the attribute is required or not")
203
+ .default(false),
204
+ array: z
205
+ .boolean()
206
+ .optional()
207
+ .default(false)
208
+ .describe("Whether the attribute is an array or not"),
209
+ elements: z
210
+ .array(z.string())
211
+ .describe("The elements of the enum attribute")
212
+ .default([]),
213
+ xdefault: z.string().nullish().describe("The default value of the attribute"),
214
+ });
215
+ const relationshipAttributeSchema = z.object({
216
+ key: z.string().describe("The key of the attribute"),
217
+ type: z
218
+ .literal("relationship")
219
+ .describe("The type of the attribute")
220
+ .default("relationship"),
221
+ error: z
222
+ .string()
223
+ .describe("The error message if the attribute is invalid")
224
+ .default("Invalid Relationship Attribute Schema"),
225
+ required: z
226
+ .boolean()
227
+ .describe("Whether the attribute is required or not")
228
+ .default(false),
229
+ array: z
230
+ .boolean()
231
+ .optional()
232
+ .describe("Whether the attribute is an array or not"),
233
+ relatedCollection: z
234
+ .string()
235
+ .describe("The collection ID of the related collection"),
236
+ relationType: z
237
+ .enum(["oneToMany", "manyToOne", "oneToOne", "manyToMany"])
238
+ .describe("The relation type of the relationship attribute"),
239
+ twoWay: z.boolean().describe("Whether the relationship is two way or not"),
240
+ twoWayKey: z
241
+ .string()
242
+ .describe("The ID of the foreign key in the other collection"),
243
+ onDelete: z
244
+ .enum(["setNull", "cascade", "restrict"])
245
+ .describe("The action to take when the related document is deleted")
246
+ .default("setNull"),
247
+ side: z.enum(["parent", "child"]).describe("The side of the relationship"),
248
+ importMapping: z
249
+ .object({
250
+ originalIdField: z
251
+ .string()
252
+ .describe("The field in the import data representing the original ID to match"),
253
+ targetField: z
254
+ .string()
255
+ .optional()
256
+ .describe("The field in the target collection that matches the original ID. Optional, defaults to the same as originalIdField if not provided"),
257
+ })
258
+ .optional()
259
+ .describe("Configuration for mapping and resolving relationships during data import"),
260
+ });
261
+ export const createRelationshipAttributes = (relatedCollection, relationType, twoWay, twoWayKey, onDelete, side) => {
262
+ return relationshipAttributeSchema.parse({
263
+ relatedCollection,
264
+ relationType,
265
+ twoWay,
266
+ twoWayKey,
267
+ onDelete,
268
+ side,
269
+ });
270
+ };
271
+ export const attributeSchema = stringAttributeSchema
272
+ .or(integerAttributeSchema)
273
+ .or(floatAttributeSchema)
274
+ .or(booleanAttributeSchema)
275
+ .or(datetimeAttributeSchema)
276
+ .or(emailAttributeSchema)
277
+ .or(ipAttributeSchema)
278
+ .or(urlAttributeSchema)
279
+ .or(enumAttributeSchema)
280
+ .or(relationshipAttributeSchema);
281
+ export const parseAttribute = (attribute) => {
282
+ if (attribute.type === "string") {
283
+ return stringAttributeSchema.parse(attribute);
284
+ }
285
+ else if (attribute.type === "integer") {
286
+ return integerAttributeSchema.parse(attribute);
287
+ }
288
+ else if (attribute.type === "float") {
289
+ return floatAttributeSchema.parse(attribute);
290
+ }
291
+ else if (attribute.type === "boolean") {
292
+ return booleanAttributeSchema.parse(attribute);
293
+ }
294
+ else if (attribute.type === "datetime") {
295
+ return datetimeAttributeSchema.parse(attribute);
296
+ }
297
+ else if (attribute.type === "email") {
298
+ return emailAttributeSchema.parse(attribute);
299
+ }
300
+ else if (attribute.type === "ip") {
301
+ return ipAttributeSchema.parse(attribute);
302
+ }
303
+ else if (attribute.type === "url") {
304
+ return urlAttributeSchema.parse(attribute);
305
+ }
306
+ else if (attribute.type === "enum") {
307
+ return enumAttributeSchema.parse(attribute);
308
+ }
309
+ else if (attribute.type === "relationship") {
310
+ return relationshipAttributeSchema.parse(attribute);
311
+ }
312
+ else {
313
+ throw new Error("Invalid attribute type");
314
+ }
315
+ };
316
+ export const indexSchema = z.object({
317
+ key: z.string(),
318
+ type: z
319
+ .enum([IndexType.Key, IndexType.Unique, IndexType.Fulltext])
320
+ .optional()
321
+ .default(IndexType.Key),
322
+ status: z.string().optional(),
323
+ error: z.string().optional(),
324
+ attributes: z.array(z.string()),
325
+ orders: z.array(z.string()).optional(),
326
+ });
327
+ export const collectionSchema = z.object({
328
+ $id: z
329
+ .string()
330
+ .optional()
331
+ .default(ID.unique())
332
+ .describe("The ID of the collection, auto generated if not provided"),
333
+ $createdAt: z.string(),
334
+ $updatedAt: z.string(),
335
+ $permissions: z
336
+ .array(z.object({
337
+ permission: z.string(),
338
+ target: z.string(),
339
+ }))
340
+ .default([])
341
+ .describe("The permissions of the collection"),
342
+ databaseId: z
343
+ .string()
344
+ .optional()
345
+ .describe("The ID of the database the collection belongs to"),
346
+ name: z.string().describe("The name of the collection"),
347
+ enabled: z
348
+ .boolean()
349
+ .default(true)
350
+ .describe("Whether the collection is enabled or not"),
351
+ documentSecurity: z
352
+ .boolean()
353
+ .default(false)
354
+ .describe("Whether document security is enabled or not"),
355
+ attributes: z
356
+ .array(attributeSchema)
357
+ .default([])
358
+ .describe("The attributes of the collection"),
359
+ indexes: z
360
+ .array(indexSchema)
361
+ .default([])
362
+ .describe("The indexes of the collection"),
363
+ importDefs: z
364
+ .array(z.object({
365
+ type: z
366
+ .enum(["create", "update"])
367
+ .default("create")
368
+ .optional()
369
+ .describe("The type of import action, if update you should set an object for the originalIdField and targetField"),
370
+ filePath: z.string().describe("The file path of the data to import"),
371
+ basePath: z
372
+ .string()
373
+ .optional()
374
+ .describe("The base path of the import e.g. if you have JSON, and the array is in the RECORDS object, then this would be RECORDS, if nothing then leave it gone"),
375
+ updateMapping: z
376
+ .object({
377
+ originalIdField: z
378
+ .string()
379
+ .describe("The field in the import data representing the original ID to match"),
380
+ targetField: z
381
+ .string()
382
+ .describe("The field in the target collection that matches the original ID. Optional, defaults to the same as originalIdField if not provided"),
383
+ })
384
+ .optional()
385
+ .describe("Configuration for mapping and resolving the update during data import"),
386
+ attributeMappings: z.array(z.object({
387
+ oldKey: z
388
+ .string()
389
+ .optional()
390
+ .describe("The key of the attribute in the old document"),
391
+ oldKeys: z
392
+ .array(z.string())
393
+ .optional()
394
+ .describe("The keys of the attribute in the old document, if there are more than one"),
395
+ targetKey: z
396
+ .string()
397
+ .describe("The key of the attribute in the new document"),
398
+ fileData: z
399
+ .object({
400
+ name: z
401
+ .string()
402
+ .describe("The name of the file, can use template strings"),
403
+ path: z
404
+ .string()
405
+ .describe("The path of the file, relative to the appwrite folder"),
406
+ })
407
+ .optional()
408
+ .describe("The file data to use for the import, if defined it will upload and replace with ID"),
409
+ converters: z
410
+ .array(z.string())
411
+ .describe("The converters to use for the import")
412
+ .default([]),
413
+ validationActions: z
414
+ .array(z.object({
415
+ action: z.string(),
416
+ params: z.array(z.string().startsWith("{").endsWith("}")),
417
+ }))
418
+ .describe("The after import actions and parameter placeholders (they'll be replaced with the actual data) to use for the import")
419
+ .default([]),
420
+ postImportActions: z
421
+ .array(z.object({
422
+ action: z.string(),
423
+ params: z.array(z.string().or(z.record(z.string(), z.any()))),
424
+ }))
425
+ .describe("The after import actions and parameter placeholders (they'll be replaced with the actual data) to use for the import")
426
+ .default([]),
427
+ })),
428
+ }))
429
+ .optional()
430
+ .default([])
431
+ .describe("The import definitions of the collection, if needed"),
432
+ });
433
+ export const CollectionCreateSchema = collectionSchema.omit({
434
+ $createdAt: true,
435
+ $updatedAt: true,
436
+ });
437
+ export const AppwriteConfigSchema = z.object({
438
+ appwriteEndpoint: z.string().default("https://cloud.appwrite.io/v1"),
439
+ appwriteProject: z.string(),
440
+ appwriteKey: z.string(),
441
+ appwriteClient: z.any().or(z.null()).default(null),
442
+ enableDevDatabase: z
443
+ .boolean()
444
+ .default(true)
445
+ .describe("Enable development database alongside production database"),
446
+ enableBackups: z.boolean().default(true).describe("Enable backups"),
447
+ backupInterval: z
448
+ .number()
449
+ .default(3600)
450
+ .describe("Backup interval in seconds"),
451
+ backupRetention: z.number().default(30).describe("Backup retention in days"),
452
+ enableBackupCleanup: z
453
+ .boolean()
454
+ .default(true)
455
+ .describe("Enable backup cleanup"),
456
+ enableMockData: z.boolean().default(false).describe("Enable mock data"),
457
+ enableWipeOtherDatabases: z
458
+ .boolean()
459
+ .default(true)
460
+ .describe("Enable wiping other databases"),
461
+ documentBucketId: z
462
+ .string()
463
+ .default("documents")
464
+ .describe("Documents bucket id for imported documents"),
465
+ usersCollectionName: z
466
+ .string()
467
+ .default("Members")
468
+ .describe("Users collection name for any overflowing data associated with users, will try to match one of the collections by name"),
469
+ databases: z
470
+ .array(z.object({
471
+ $id: z.string(),
472
+ name: z.string(),
473
+ }))
474
+ .default([
475
+ { $id: "dev", name: "Development" },
476
+ { $id: "main", name: "Main" },
477
+ { $id: "migrations", name: "Migrations" },
478
+ ])
479
+ .describe("Databases to create, $id is the id of the database"),
480
+ collections: z
481
+ .array(CollectionCreateSchema)
482
+ .optional()
483
+ .default([])
484
+ .describe("Collections to create, $id is the id of the collection, it'll always check by collection name and $id for existing before creating another"),
485
+ });
@@ -0,0 +1,12 @@
1
+ import type { AppwriteConfig, Attribute } from "./schema.js";
2
+ export declare class SchemaGenerator {
3
+ private relationshipMap;
4
+ private config;
5
+ private appwriteFolderPath;
6
+ constructor(config: AppwriteConfig, appwriteFolderPath: string);
7
+ private extractRelationships;
8
+ private addRelationship;
9
+ generateSchemas(): void;
10
+ createSchemaString: (name: string, attributes: Attribute[]) => string;
11
+ typeToZod: (attribute: Attribute) => string;
12
+ }