appwrite-utils-cli 0.0.285 → 0.9.0

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 (109) hide show
  1. package/README.md +122 -96
  2. package/dist/collections/attributes.d.ts +4 -0
  3. package/dist/collections/attributes.js +224 -0
  4. package/dist/collections/indexes.d.ts +4 -0
  5. package/dist/collections/indexes.js +27 -0
  6. package/dist/collections/methods.d.ts +16 -0
  7. package/dist/collections/methods.js +216 -0
  8. package/dist/databases/methods.d.ts +6 -0
  9. package/dist/databases/methods.js +33 -0
  10. package/dist/interactiveCLI.d.ts +19 -0
  11. package/dist/interactiveCLI.js +555 -0
  12. package/dist/main.js +227 -62
  13. package/dist/migrations/afterImportActions.js +37 -40
  14. package/dist/migrations/appwriteToX.d.ts +26 -25
  15. package/dist/migrations/appwriteToX.js +42 -6
  16. package/dist/migrations/attributes.js +21 -20
  17. package/dist/migrations/backup.d.ts +93 -87
  18. package/dist/migrations/collections.d.ts +6 -0
  19. package/dist/migrations/collections.js +149 -20
  20. package/dist/migrations/converters.d.ts +2 -18
  21. package/dist/migrations/converters.js +13 -2
  22. package/dist/migrations/dataLoader.d.ts +276 -161
  23. package/dist/migrations/dataLoader.js +535 -292
  24. package/dist/migrations/databases.js +8 -2
  25. package/dist/migrations/helper.d.ts +3 -0
  26. package/dist/migrations/helper.js +21 -0
  27. package/dist/migrations/importController.d.ts +5 -2
  28. package/dist/migrations/importController.js +125 -88
  29. package/dist/migrations/importDataActions.d.ts +9 -1
  30. package/dist/migrations/importDataActions.js +15 -3
  31. package/dist/migrations/indexes.js +3 -2
  32. package/dist/migrations/logging.js +20 -8
  33. package/dist/migrations/migrationHelper.d.ts +9 -4
  34. package/dist/migrations/migrationHelper.js +6 -5
  35. package/dist/migrations/openapi.d.ts +1 -1
  36. package/dist/migrations/openapi.js +33 -18
  37. package/dist/migrations/queue.js +3 -2
  38. package/dist/migrations/relationships.d.ts +2 -2
  39. package/dist/migrations/schemaStrings.js +53 -41
  40. package/dist/migrations/setupDatabase.d.ts +2 -4
  41. package/dist/migrations/setupDatabase.js +24 -105
  42. package/dist/migrations/storage.d.ts +3 -1
  43. package/dist/migrations/storage.js +110 -16
  44. package/dist/migrations/transfer.d.ts +30 -0
  45. package/dist/migrations/transfer.js +337 -0
  46. package/dist/migrations/users.d.ts +2 -1
  47. package/dist/migrations/users.js +78 -43
  48. package/dist/schemas/authUser.d.ts +2 -2
  49. package/dist/storage/methods.d.ts +15 -0
  50. package/dist/storage/methods.js +207 -0
  51. package/dist/storage/schemas.d.ts +687 -0
  52. package/dist/storage/schemas.js +175 -0
  53. package/dist/utils/getClientFromConfig.d.ts +4 -0
  54. package/dist/utils/getClientFromConfig.js +16 -0
  55. package/dist/utils/helperFunctions.d.ts +11 -1
  56. package/dist/utils/helperFunctions.js +38 -0
  57. package/dist/utils/retryFailedPromises.d.ts +2 -0
  58. package/dist/utils/retryFailedPromises.js +21 -0
  59. package/dist/utils/schemaStrings.d.ts +13 -0
  60. package/dist/utils/schemaStrings.js +403 -0
  61. package/dist/utils/setupFiles.js +110 -61
  62. package/dist/utilsController.d.ts +40 -22
  63. package/dist/utilsController.js +164 -84
  64. package/package.json +13 -15
  65. package/src/collections/attributes.ts +483 -0
  66. package/src/collections/indexes.ts +53 -0
  67. package/src/collections/methods.ts +331 -0
  68. package/src/databases/methods.ts +47 -0
  69. package/src/init.ts +64 -64
  70. package/src/interactiveCLI.ts +767 -0
  71. package/src/main.ts +292 -83
  72. package/src/migrations/afterImportActions.ts +553 -490
  73. package/src/migrations/appwriteToX.ts +237 -174
  74. package/src/migrations/attributes.ts +483 -422
  75. package/src/migrations/backup.ts +205 -205
  76. package/src/migrations/collections.ts +545 -300
  77. package/src/migrations/converters.ts +161 -150
  78. package/src/migrations/dataLoader.ts +1615 -1304
  79. package/src/migrations/databases.ts +44 -25
  80. package/src/migrations/dbHelpers.ts +92 -92
  81. package/src/migrations/helper.ts +40 -0
  82. package/src/migrations/importController.ts +448 -384
  83. package/src/migrations/importDataActions.ts +315 -307
  84. package/src/migrations/indexes.ts +40 -37
  85. package/src/migrations/logging.ts +29 -16
  86. package/src/migrations/migrationHelper.ts +207 -201
  87. package/src/migrations/openapi.ts +83 -70
  88. package/src/migrations/queue.ts +118 -119
  89. package/src/migrations/relationships.ts +324 -324
  90. package/src/migrations/schemaStrings.ts +472 -460
  91. package/src/migrations/setupDatabase.ts +118 -219
  92. package/src/migrations/storage.ts +538 -358
  93. package/src/migrations/transfer.ts +608 -0
  94. package/src/migrations/users.ts +362 -285
  95. package/src/migrations/validationRules.ts +63 -63
  96. package/src/schemas/authUser.ts +23 -23
  97. package/src/setup.ts +8 -8
  98. package/src/storage/methods.ts +371 -0
  99. package/src/storage/schemas.ts +205 -0
  100. package/src/types.ts +9 -9
  101. package/src/utils/getClientFromConfig.ts +17 -0
  102. package/src/utils/helperFunctions.ts +181 -127
  103. package/src/utils/index.ts +2 -2
  104. package/src/utils/loadConfigs.ts +59 -59
  105. package/src/utils/retryFailedPromises.ts +27 -0
  106. package/src/utils/schemaStrings.ts +473 -0
  107. package/src/utils/setupFiles.ts +228 -182
  108. package/src/utilsController.ts +325 -194
  109. package/tsconfig.json +37 -37
package/README.md CHANGED
@@ -1,96 +1,122 @@
1
- # appwrite-utils-cli
2
-
3
- ## Overview
4
-
5
- `appwrite-utils-cli` is a powerful command-line interface tool designed for Appwrite developers who need to manage database migrations, schema generation, data import, and much more. This CLI tool facilitates complex tasks like setting up databases, running migrations, generating schemas, and managing backups efficiently, making it an indispensable part of your Appwrite project management.
6
-
7
- ## Features
8
-
9
- - **Easy Configuration**: Initialize your Appwrite project configurations interactively directly from the command line.
10
- - **Database Migrations**: Control the migration process with options to target production, staging, or development environments.
11
- - **Schema Generation**: Generate and manage TypeScript schemas directly from your Appwrite database schemas.
12
- - **Data Import**: Facilitate the import of data into your Appwrite databases with comprehensive command-line support.
13
- - **Backup Management**: Create backups of your Appwrite databases to ensure data integrity and safety.
14
- - **Flexible Database Management**: Includes commands to wipe databases, documents, or user data, providing flexibility in managing your database state during development or testing.
15
-
16
- ## Installation
17
-
18
- To use `appwrite-utils-cli`, you can install it globally via npm to make it accessible from anywhere in your command line:
19
-
20
- ```bash
21
- npm install -g appwrite-utils-cli
22
- ```
23
-
24
- However, due to the nature of the speed at which I am developing this project, I would recommend the following command:
25
-
26
- ```bash
27
- npx --package=appwrite-utils-cli@latest appwrite-migrate --arg1 --arg2 --arg3
28
- ```
29
-
30
- **DO NOT INSTALL THIS LOCALLY INTO YOUR PROJECT, IT IS MEANT TO BE USED AS A COMMAND LINE TOOL ONLY**
31
-
32
- ## Usage
33
-
34
- After installation, you can access the tool directly from your command line using the provided commands. Here's how you can use the different functionalities:
35
-
36
- ### Initialization
37
-
38
- Interactively set up your Appwrite project with necessary configurations:
39
-
40
- ```bash
41
- npx --package=appwrite-utils-cli@latest appwrite-init
42
- ```
43
-
44
- ### Running Migrations and Tasks
45
-
46
- Run migration and management tasks with specific flags according to your needs:
47
-
48
- ```bash
49
- npx --package=appwrite-utils-cli@latest appwrite-migrate --args
50
- ```
51
-
52
- Replace `--args` with the appropriate options:
53
-
54
- - `--prod`: Run tasks in the production environment.
55
- - `--staging`: Run tasks in the staging environment.
56
- - `--dev`: Run tasks in the development environment.
57
- - `--wipe`: Wipe all databases.
58
- - `--wipe-docs` or `--wipeDocs`: Wipe all documents in the databases.
59
- - `--generate`: Generate TypeScript schemas from database schemas.
60
- - `--import`: Import data into your databases.
61
- - `--backup`: Perform a backup of your databases.
62
- - `--wipe-users` or `--wipeUsers`: Wipe all user data.
63
- - `--write-data` or `--writeData`: Write converted imported data to file
64
- - `--sync`: Synchronize your project's config and generate schema for your database
65
- - `--endpoint`: Set a different endpoint for the migration target
66
- - `--project`: Set a different project ID for the migration target
67
- - `--key`: Set a different API key for the migration target
68
-
69
- ### OpenAPI Generation (almost done, in progress)
70
-
71
- Recently, I have also added an optional OpenAPI generation for each attribute in the schema. This is because I needed it and because I felt it would be nice to have. This is done using [this package](https://github.com/asteasolutions/zod-to-openapi), many thanks to them.
72
-
73
- To use it, add a `description` to any attribute or collection, and it will export that schema to the `appwrite/openapi` folder
74
-
75
- This setup ensures that developers have robust tools at their fingertips to manage complex Appwrite projects effectively from the command line. I also have added logging automatically for information and errors as the console can be hard to keep up with.
76
-
77
- ### Roadmap
78
-
79
- - Syncing configuration (DONE)
80
- - Better file format for config (potentially)
81
- - Separation of collections and import configuration from main config
82
-
83
- ### Changelog
84
-
85
- - 0.0.275: THINGS ARE NOW IN TYPESCRIPT WOOHOO. No but for reaal, super happy to report that everything has been converted to TypeScript, just way too many changes, I hope you enjoy it!
86
- - 0.0.274: Small improvement for attribute handling, rather than getting it every attribute, I check the collections attributes
87
- - 0.0.273: Small fix for relationship attribute comparisons
88
- - 0.0.272: That's what I get for not testing lmao, also updated logic for checking for existing attributes to take the `format` into consideration from the database (URL's are not of `type: "url"`, they are of `format: "url"`)
89
- - 0.0.271: Small change to update attributes that are different from each other by deleting the attribute and recreating, as we cannot update most things
90
- - 0.0.270: Fixed enums in `--sync`, added optional OpenAPI generation (in progress, almost done, but wanted to push other changes), added `--endpoint`, `--project`, `--key` as optional parameters to change the target destination (shoutout to [pingu24k](https://github.com/pingu2k4) for pointing out these bugs and suggesting those changes for endpoint customization)
91
- - 0.0.254: Added `--sync` to synchronize your Appwrite instance with your local `appwriteConfig.yaml` and generate schemas
92
- - 0.0.253: Added `--writeData` (or `--write-data`) to command to write the output of the import data to a file called dataLoaderOutput in your root dir
93
- - 0.0.23: Added batching to user deletion
94
- - 0.0.22: Converted all import processes except `postImportActions` and Relationship Resolution to the local data import, so it should be much faster.
95
- - 0.0.6: Added `setTargetFieldFromOtherCollectionDocumentsByMatchingField` for the below, but setting a different field than the field you matched. The names are long, but at least you know what's going on lmao.
96
- - 0.0.5: Added `setFieldFromOtherCollectionDocuments` to set an array of ID's for instance from another collection as a `postImportAction`
1
+ # appwrite-utils-cli
2
+
3
+ ## Overview
4
+
5
+ `appwrite-utils-cli` is a powerful command-line interface tool designed for Appwrite developers who need to manage database migrations, schema generation, data import, and much more. This CLI tool facilitates complex tasks like setting up databases, running migrations, generating schemas, and managing backups efficiently, making it an indispensable part of your Appwrite project management.
6
+
7
+ ## Features
8
+
9
+ - **Interactive Mode**: Run the CLI in interactive mode for a guided experience through all available options.
10
+ - **Easy Configuration**: Initialize your Appwrite project configurations interactively directly from the command line.
11
+ - **Database Migrations**: Control the migration process with options to target specific databases and collections.
12
+ - **Schema Generation**: Generate and manage TypeScript schemas directly from your Appwrite database schemas.
13
+ - **Data Import**: Facilitate the import of data into your Appwrite databases with comprehensive command-line support.
14
+ - **Backup Management**: Create backups of your Appwrite databases to ensure data integrity and safety.
15
+ - **Flexible Database Management**: Includes commands to wipe databases, documents, or user data, providing flexibility in managing your database state during development or testing.
16
+ - **Data Transfer**: Transfer data between databases, collections, and even between local and remote Appwrite instances.
17
+ - **Configuration Synchronization**: Sync your local Appwrite configuration with your remote Appwrite project.
18
+
19
+ ## Installation
20
+
21
+ To use `appwrite-utils-cli`, you can install it globally via npm to make it accessible from anywhere in your command line:
22
+
23
+ ```bash
24
+ npm install -g appwrite-utils-cli
25
+ ```
26
+
27
+ However, due to the rapid development of this project, it's recommended to use the following command:
28
+
29
+ ```bash
30
+ npx --package=appwrite-utils-cli@latest appwrite-migrate [options]
31
+ ```
32
+
33
+ **Note: Do not install this locally into your project. It is meant to be used as a command-line tool only.**
34
+
35
+ ## Usage
36
+
37
+ After installation, you can access the tool directly from your command line using the provided commands.
38
+
39
+ ### Interactive Mode
40
+
41
+ Run the CLI in interactive mode:
42
+
43
+ ```bash
44
+ npx --package=appwrite-utils-cli@latest appwrite-migrate --it
45
+ ```
46
+
47
+ This will guide you through all available options interactively.
48
+
49
+ ### Non-Interactive Mode
50
+
51
+ You can also use specific flags to run tasks without the interactive prompt:
52
+
53
+ ```bash
54
+ npx --package=appwrite-utils-cli@latest appwrite-migrate [options]
55
+ ```
56
+
57
+ Available options:
58
+
59
+ - `--it`: Run in interactive mode
60
+ - `--dbIds`: Comma-separated list of database IDs to operate on
61
+ - `--collectionIds`: Comma-separated list of collection IDs to operate on
62
+ - `--bucketIds`: Comma-separated list of bucket IDs to operate on
63
+ - `--wipe`: Wipe data (all: everything, docs: only documents, users: only user data)
64
+ - `--generate`: Generate TypeScript schemas from database schemas
65
+ - `--import`: Import data into your databases
66
+ - `--backup`: Perform a backup of your databases
67
+ - `--writeData`: Write converted imported data to file
68
+ - `--push`: Push your local Appwrite config to your configured Appwrite Project
69
+ - `--sync`: Synchronize by pulling your Appwrite config from your configured Appwrite Project
70
+ - `--endpoint`: Set the Appwrite endpoint
71
+ - `--projectId`: Set the Appwrite project ID
72
+ - `--apiKey`: Set the Appwrite API key
73
+ - `--transfer`: Transfer data between databases or collections
74
+ - `--fromDbId`: Set the source database ID for transfer
75
+ - `--toDbId`: Set the destination database ID for transfer
76
+ - `--fromCollectionId`: Set the source collection ID for transfer
77
+ - `--toCollectionId`: Set the destination collection ID for transfer
78
+ - `--fromBucketId`: Set the source bucket ID for transfer
79
+ - `--toBucketId`: Set the destination bucket ID for transfer
80
+ - `--remoteEndpoint`: Set the remote Appwrite endpoint for transfers
81
+ - `--remoteProjectId`: Set the remote Appwrite project ID for transfers
82
+ - `--remoteApiKey`: Set the remote Appwrite API key for transfers
83
+
84
+ ## Examples
85
+
86
+ ### Transfer Databases
87
+
88
+ Transfer databases within the same project or from a local to a remote project:
89
+
90
+ ```bash
91
+ npx appwrite-utils-cli appwrite-migrate --transfer --fromDbId sourceDbId --toDbId targetDbId --remoteEndpoint https://appwrite.otherserver.com --remoteProjectId yourProjectId --remoteApiKey yourApiKey
92
+ ```
93
+
94
+ ### Transfer Specific Collections
95
+
96
+ Transfer specific collections from one place to another, with all of their data:
97
+
98
+ ```bash
99
+ npx appwrite-utils-cli appwrite-migrate --transfer --fromDbId sourceDbId --toDbId targetDbId --fromCollectionId sourceCollectionId --toCollectionId targetCollectionId --remoteEndpoint https://appwrite.otherserver.com --remoteProjectId yourProjectId --remoteApiKey yourApiKey
100
+ ```
101
+
102
+ ### Transfer Buckets
103
+
104
+ Transfer files between buckets:
105
+
106
+ ```bash
107
+ npx appwrite-utils-cli appwrite-migrate --transfer --fromBucketId sourceBucketId --toBucketId targetBucketId --remoteEndpoint https://appwrite.otherserver.com --remoteProjectId yourProjectId --remoteApiKey yourApiKey
108
+ ```
109
+
110
+ ## Additional Notes
111
+
112
+ - If you run out of RAM during large data imports, you can increase Node's memory allocation:
113
+
114
+ ```bash
115
+ export NODE_OPTIONS="--max-old-space-size=16384"
116
+ ```
117
+
118
+ This sets the allocation to 16GB. For most cases, 8GB (`8192`) should be sufficient.
119
+
120
+ - The CLI now supports OpenAPI generation for each attribute in the schema. Add a `description` to any attribute or collection, and it will export that schema to the `appwrite/openapi` folder.
121
+
122
+ This updated CLI ensures that developers have robust tools at their fingertips to manage complex Appwrite projects effectively from the command line, with both interactive and non-interactive modes available for flexibility.
@@ -0,0 +1,4 @@
1
+ import { type Databases, type Models } from "node-appwrite";
2
+ import { type Attribute } from "appwrite-utils";
3
+ export declare const createOrUpdateAttribute: (db: Databases, dbId: string, collection: Models.Collection, attribute: Attribute) => Promise<void>;
4
+ export declare const createUpdateCollectionAttributes: (db: Databases, dbId: string, collection: Models.Collection, attributes: Attribute[]) => Promise<void>;
@@ -0,0 +1,224 @@
1
+ import { Query } from "node-appwrite";
2
+ import { attributeSchema, parseAttribute, } from "appwrite-utils";
3
+ import { nameToIdMapping, enqueueOperation } from "../migrations/queue.js";
4
+ import _ from "lodash";
5
+ import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
6
+ const attributesSame = (databaseAttribute, configAttribute) => {
7
+ return (databaseAttribute.key == configAttribute.key &&
8
+ databaseAttribute.type == configAttribute.type &&
9
+ databaseAttribute.array == configAttribute.array);
10
+ };
11
+ export const createOrUpdateAttribute = async (db, dbId, collection, attribute) => {
12
+ let action = "create";
13
+ let foundAttribute;
14
+ const updateEnabled = false;
15
+ let finalAttribute = attribute;
16
+ try {
17
+ const collectionAttr = collection.attributes.find(
18
+ // @ts-expect-error
19
+ (attr) => attr.key === attribute.key);
20
+ foundAttribute = parseAttribute(collectionAttr);
21
+ }
22
+ catch (error) {
23
+ foundAttribute = undefined;
24
+ }
25
+ if (foundAttribute &&
26
+ attributesSame(foundAttribute, attribute) &&
27
+ updateEnabled) {
28
+ // Check if mutable properties have changed and set action to "update" if necessary
29
+ const requiredChanged = "required" in foundAttribute && "required" in attribute
30
+ ? foundAttribute.required !== attribute.required
31
+ : false;
32
+ // const xdefaultChanged =
33
+ // "xdefault" in foundAttribute && "xdefault" in attribute
34
+ // ? foundAttribute.xdefault !== attribute.xdefault
35
+ // : false;
36
+ const onDeleteChanged = foundAttribute.type === "relationship" &&
37
+ attribute.type === "relationship" &&
38
+ "onDelete" in foundAttribute &&
39
+ "onDelete" in attribute
40
+ ? foundAttribute.onDelete !== attribute.onDelete
41
+ : false;
42
+ if (requiredChanged || onDeleteChanged) {
43
+ console.log(`Required changed: ${requiredChanged}\nOnDelete changed: ${onDeleteChanged}`);
44
+ console.log(`Found attribute: ${JSON.stringify(foundAttribute, null, 2)}`);
45
+ console.log(`Attribute: ${JSON.stringify(attribute, null, 2)}`);
46
+ finalAttribute = {
47
+ ...attribute,
48
+ ...foundAttribute,
49
+ };
50
+ action = "update";
51
+ }
52
+ else {
53
+ // If no properties that can be updated have changed, return early
54
+ return;
55
+ }
56
+ }
57
+ else if (foundAttribute &&
58
+ !attributesSame(foundAttribute, attribute) &&
59
+ updateEnabled) {
60
+ console.log(`Deleting attribute with same key ${attribute.key} -- but different values -- ${JSON.stringify(attribute, null, 2)} -- ${JSON.stringify(foundAttribute, null, 2)}`);
61
+ await db.deleteAttribute(dbId, collection.$id, attribute.key);
62
+ // After deletion, you might want to create the attribute anew
63
+ finalAttribute = attribute;
64
+ action = "create";
65
+ }
66
+ else if (!updateEnabled && foundAttribute) {
67
+ return;
68
+ }
69
+ // Relationship attribute logic with adjustments
70
+ let collectionFoundViaRelatedCollection;
71
+ let relatedCollectionId;
72
+ if (finalAttribute.type === "relationship") {
73
+ if (nameToIdMapping.has(finalAttribute.relatedCollection)) {
74
+ relatedCollectionId = nameToIdMapping.get(finalAttribute.relatedCollection);
75
+ try {
76
+ collectionFoundViaRelatedCollection = await db.getCollection(dbId, relatedCollectionId);
77
+ }
78
+ catch (e) {
79
+ console.log(`Collection not found: ${finalAttribute.relatedCollection} when nameToIdMapping was set`);
80
+ collectionFoundViaRelatedCollection = undefined;
81
+ }
82
+ }
83
+ else {
84
+ const collectionsPulled = await db.listCollections(dbId, [
85
+ Query.equal("name", finalAttribute.relatedCollection),
86
+ ]);
87
+ if (collectionsPulled.total > 0) {
88
+ collectionFoundViaRelatedCollection = collectionsPulled.collections[0];
89
+ relatedCollectionId = collectionFoundViaRelatedCollection.$id;
90
+ nameToIdMapping.set(finalAttribute.relatedCollection, relatedCollectionId);
91
+ }
92
+ }
93
+ if (!(relatedCollectionId && collectionFoundViaRelatedCollection)) {
94
+ console.log(`Enqueueing operation for attribute: ${finalAttribute.key}`);
95
+ enqueueOperation({
96
+ type: "attribute",
97
+ collectionId: collection.$id,
98
+ collection: collection,
99
+ attribute,
100
+ dependencies: [finalAttribute.relatedCollection],
101
+ });
102
+ return;
103
+ }
104
+ }
105
+ finalAttribute = attributeSchema.parse(finalAttribute);
106
+ switch (finalAttribute.type) {
107
+ case "string":
108
+ if (action === "create") {
109
+ await tryAwaitWithRetry(async () => await db.createStringAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.size, finalAttribute.required || false, finalAttribute.xdefault || undefined, finalAttribute.array || false, finalAttribute.encrypted));
110
+ }
111
+ else {
112
+ await tryAwaitWithRetry(async () => await db.updateStringAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined));
113
+ }
114
+ break;
115
+ case "integer":
116
+ if (action === "create") {
117
+ if (finalAttribute.min &&
118
+ BigInt(finalAttribute.min) === BigInt(-9223372036854776000)) {
119
+ delete finalAttribute.min;
120
+ }
121
+ if (finalAttribute.max &&
122
+ BigInt(finalAttribute.max) === BigInt(9223372036854776000)) {
123
+ delete finalAttribute.max;
124
+ }
125
+ await tryAwaitWithRetry(async () => await db.createIntegerAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.min, finalAttribute.max, finalAttribute.xdefault || undefined, finalAttribute.array));
126
+ }
127
+ else {
128
+ if (finalAttribute.min &&
129
+ BigInt(finalAttribute.min) === BigInt(-9223372036854776000)) {
130
+ delete finalAttribute.min;
131
+ }
132
+ if (finalAttribute.max &&
133
+ BigInt(finalAttribute.max) === BigInt(9223372036854776000)) {
134
+ delete finalAttribute.max;
135
+ }
136
+ await tryAwaitWithRetry(async () => await db.updateIntegerAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.min || 0, finalAttribute.max || 2147483647, finalAttribute.xdefault || undefined));
137
+ }
138
+ break;
139
+ case "float":
140
+ if (action === "create") {
141
+ await tryAwaitWithRetry(async () => await db.createFloatAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.min, finalAttribute.max, finalAttribute.xdefault || undefined, finalAttribute.array));
142
+ }
143
+ else {
144
+ await tryAwaitWithRetry(async () => await db.updateFloatAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.min || 0, finalAttribute.max || 2147483647, finalAttribute.xdefault || undefined));
145
+ }
146
+ break;
147
+ case "boolean":
148
+ if (action === "create") {
149
+ await tryAwaitWithRetry(async () => await db.createBooleanAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined, finalAttribute.array));
150
+ }
151
+ else {
152
+ await tryAwaitWithRetry(async () => await db.updateBooleanAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || null));
153
+ }
154
+ break;
155
+ case "datetime":
156
+ if (action === "create") {
157
+ await tryAwaitWithRetry(async () => await db.createDatetimeAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined, finalAttribute.array));
158
+ }
159
+ else {
160
+ await tryAwaitWithRetry(async () => await db.updateDatetimeAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined));
161
+ }
162
+ break;
163
+ case "email":
164
+ if (action === "create") {
165
+ await tryAwaitWithRetry(async () => await db.createEmailAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined, finalAttribute.array));
166
+ }
167
+ else {
168
+ await tryAwaitWithRetry(async () => await db.updateEmailAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined));
169
+ }
170
+ break;
171
+ case "ip":
172
+ if (action === "create") {
173
+ await tryAwaitWithRetry(async () => await db.createIpAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined, finalAttribute.array));
174
+ }
175
+ else {
176
+ await tryAwaitWithRetry(async () => await db.updateIpAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined));
177
+ }
178
+ break;
179
+ case "url":
180
+ if (action === "create") {
181
+ await tryAwaitWithRetry(async () => await db.createUrlAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined, finalAttribute.array));
182
+ }
183
+ else {
184
+ await tryAwaitWithRetry(async () => await db.updateUrlAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault || undefined));
185
+ }
186
+ break;
187
+ case "enum":
188
+ if (action === "create") {
189
+ await tryAwaitWithRetry(async () => await db.createEnumAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.elements, finalAttribute.required || false, finalAttribute.xdefault || undefined, finalAttribute.array));
190
+ }
191
+ else {
192
+ await tryAwaitWithRetry(async () => await db.updateEnumAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.elements, finalAttribute.required || false, finalAttribute.xdefault || undefined));
193
+ }
194
+ break;
195
+ case "relationship":
196
+ if (action === "create") {
197
+ await tryAwaitWithRetry(async () => await db.createRelationshipAttribute(dbId, collection.$id, relatedCollectionId, finalAttribute.relationType, finalAttribute.twoWay, finalAttribute.key, finalAttribute.twoWayKey, finalAttribute.onDelete));
198
+ }
199
+ else {
200
+ await tryAwaitWithRetry(async () => await db.updateRelationshipAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.onDelete));
201
+ }
202
+ break;
203
+ default:
204
+ console.error("Invalid attribute type");
205
+ break;
206
+ }
207
+ };
208
+ export const createUpdateCollectionAttributes = async (db, dbId, collection, attributes) => {
209
+ console.log(`Creating/Updating attributes for collection: ${collection.name}`);
210
+ const batchSize = 3; // Size of each batch
211
+ for (let i = 0; i < attributes.length; i += batchSize) {
212
+ // Slice the attributes array to get a batch of at most batchSize elements
213
+ const batch = attributes.slice(i, i + batchSize);
214
+ const attributePromises = batch.map((attribute) => createOrUpdateAttribute(db, dbId, collection, attribute));
215
+ // Await the completion of all promises in the current batch
216
+ const results = await Promise.allSettled(attributePromises);
217
+ results.forEach((result) => {
218
+ if (result.status === "rejected") {
219
+ console.error("An attribute promise was rejected:", result.reason);
220
+ }
221
+ });
222
+ }
223
+ console.log(`Finished creating/updating attributes for collection: ${collection.name}`);
224
+ };
@@ -0,0 +1,4 @@
1
+ import { type Index } from "appwrite-utils";
2
+ import { Databases, type Models } from "node-appwrite";
3
+ export declare const createOrUpdateIndex: (dbId: string, db: Databases, collectionId: string, index: Index) => Promise<Models.Index | null>;
4
+ export declare const createOrUpdateIndexes: (dbId: string, db: Databases, collectionId: string, indexes: Index[]) => Promise<void>;
@@ -0,0 +1,27 @@
1
+ import { indexSchema } from "appwrite-utils";
2
+ import { Databases, IndexType, Query } from "node-appwrite";
3
+ import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
4
+ export const createOrUpdateIndex = async (dbId, db, collectionId, index) => {
5
+ const existingIndex = await db.listIndexes(dbId, collectionId, [
6
+ Query.equal("key", index.key),
7
+ ]);
8
+ let createIndex = false;
9
+ let newIndex = null;
10
+ if (existingIndex.total > 0 &&
11
+ existingIndex.indexes.some((index) => (index.key === index.key &&
12
+ index.type === index.type &&
13
+ index.attributes === index.attributes) ||
14
+ JSON.stringify(index) === JSON.stringify(index))) {
15
+ await db.deleteIndex(dbId, collectionId, existingIndex.indexes[0].key);
16
+ createIndex = true;
17
+ }
18
+ if (createIndex) {
19
+ newIndex = await db.createIndex(dbId, collectionId, index.key, index.type, index.attributes, index.orders);
20
+ }
21
+ return newIndex;
22
+ };
23
+ export const createOrUpdateIndexes = async (dbId, db, collectionId, indexes) => {
24
+ for (const index of indexes) {
25
+ await tryAwaitWithRetry(async () => await createOrUpdateIndex(dbId, db, collectionId, index));
26
+ }
27
+ };
@@ -0,0 +1,16 @@
1
+ import { Databases, type Models } from "node-appwrite";
2
+ import type { AppwriteConfig, CollectionCreate } from "appwrite-utils";
3
+ export declare const documentExists: (db: Databases, dbId: string, targetCollectionId: string, toCreateObject: any) => Promise<Models.Document | null>;
4
+ export declare const checkForCollection: (db: Databases, dbId: string, collection: Partial<CollectionCreate>) => Promise<Models.Collection | null>;
5
+ export declare const fetchAndCacheCollectionByName: (db: Databases, dbId: string, collectionName: string) => Promise<Models.Collection | undefined>;
6
+ export declare const wipeDatabase: (database: Databases, databaseId: string) => Promise<{
7
+ collectionId: string;
8
+ collectionName: string;
9
+ }[]>;
10
+ export declare const generateSchemas: (config: AppwriteConfig, appwriteFolderPath: string) => Promise<void>;
11
+ export declare const createOrUpdateCollections: (database: Databases, databaseId: string, config: AppwriteConfig, deletedCollections?: {
12
+ collectionId: string;
13
+ collectionName: string;
14
+ }[]) => Promise<void>;
15
+ export declare const generateMockData: (database: Databases, databaseId: string, configCollections: any[]) => Promise<void>;
16
+ export declare const fetchAllCollections: (dbId: string, database: Databases) => Promise<Models.Collection[]>;