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
package/README.md ADDED
@@ -0,0 +1,80 @@
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 and setup 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 should 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
+ ## Usage
25
+
26
+ 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:
27
+
28
+ ### Initialization
29
+
30
+ Set up your Appwrite project with necessary configurations:
31
+
32
+ ```bash
33
+ appwrite-setup
34
+ ```
35
+
36
+ To generate an example configuration file:
37
+
38
+ ```bash
39
+ appwrite-setup --example
40
+ ```
41
+
42
+ ### Running Migrations and Tasks
43
+
44
+ Run migration and management tasks with specific flags according to your needs:
45
+
46
+ ```bash
47
+ appwrite-migrate --args
48
+ ```
49
+
50
+ Replace `--args` with the appropriate options:
51
+
52
+ - `--prod`: Run tasks in the production environment.
53
+ - `--staging`: Run tasks in the staging environment.
54
+ - `--dev`: Run tasks in the development environment.
55
+ - `--wipe`: Wipe all databases.
56
+ - `--wipe-docs` or `--wipeDocs`: Wipe all documents in the databases.
57
+ - `--generate`: Generate TypeScript schemas from database schemas.
58
+ - `--import`: Import data into your databases.
59
+ - `--backup`: Perform a backup of your databases.
60
+ - `--wipe-users` or `--wipeUsers`: Wipe all user data.
61
+
62
+ For example, to run migrations in a development environment and import data:
63
+
64
+ ```bash
65
+ appwrite-migrate --dev --import
66
+ ```
67
+
68
+ To initialize your project, generate schemas, but not import data:
69
+
70
+ ```bash
71
+ appwrite-migrate --init
72
+ ```
73
+
74
+ 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.
75
+
76
+ ### Roadmap
77
+
78
+ - Syncing configuration
79
+ - Better file format for config (potentially)
80
+ - Separation of collections and import configuration from main config
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import { UtilsController } from "./utilsController.js";
3
+ const args = process.argv.slice(2);
4
+ async function main() {
5
+ const controller = new UtilsController();
6
+ await controller.init();
7
+ let runProd = false;
8
+ let runStaging = false;
9
+ let runDev = false;
10
+ let doBackup = false;
11
+ let wipeDatabases = false;
12
+ let wipeUsers = false;
13
+ let generateSchemas = false;
14
+ let importData = false;
15
+ let wipeDocuments = false;
16
+ if (args.includes("--prod")) {
17
+ runProd = true;
18
+ }
19
+ if (args.includes("--staging")) {
20
+ runStaging = true;
21
+ }
22
+ if (args.includes("--dev")) {
23
+ runDev = true;
24
+ }
25
+ if (args.includes("--wipe")) {
26
+ wipeDatabases = true;
27
+ }
28
+ if (args.includes("--wipe-docs") || args.includes("--wipeDocs")) {
29
+ wipeDocuments = true;
30
+ }
31
+ if (args.includes("--generate")) {
32
+ generateSchemas = true;
33
+ }
34
+ if (args.includes("--import")) {
35
+ importData = true;
36
+ }
37
+ if (args.includes("--backup")) {
38
+ doBackup = true;
39
+ }
40
+ if (args.includes("--wipe-users") || args.includes("--wipeUsers")) {
41
+ wipeUsers = true;
42
+ }
43
+ if (args.includes("--init")) {
44
+ await controller.run({
45
+ runProd: runProd,
46
+ runStaging: runStaging,
47
+ runDev: runDev,
48
+ doBackup: doBackup,
49
+ wipeDatabases: wipeDatabases,
50
+ wipeUsers: wipeUsers,
51
+ wipeDocumentStorage: wipeDocuments,
52
+ generateSchemas: true,
53
+ generateMockData: false,
54
+ importData: false,
55
+ checkDuplicates: false,
56
+ });
57
+ }
58
+ else {
59
+ await controller.run({
60
+ runProd: runProd,
61
+ runStaging: runStaging,
62
+ runDev: runDev,
63
+ doBackup: doBackup,
64
+ wipeDatabases: wipeDatabases,
65
+ wipeDocumentStorage: wipeDocuments,
66
+ generateSchemas: generateSchemas,
67
+ generateMockData: false,
68
+ wipeUsers: wipeUsers,
69
+ importData: importData,
70
+ checkDuplicates: false,
71
+ });
72
+ }
73
+ }
74
+ main().catch(console.error);
@@ -0,0 +1,12 @@
1
+ import { type Models } from "node-appwrite";
2
+ import type { AppwriteConfig } from "./schema.js";
3
+ export interface AfterImportActions {
4
+ [key: string]: (config: AppwriteConfig, ...args: any[]) => Promise<any>;
5
+ }
6
+ export declare const afterImportActions: {
7
+ updateCreatedDocument: (config: AppwriteConfig, dbId: string, collId: string, docId: string, data: any) => Promise<void>;
8
+ checkAndUpdateFieldInDocument: (config: AppwriteConfig, dbId: string, collId: string, docId: string, fieldName: string, oldFieldValue: any, newFieldValue: any) => Promise<void>;
9
+ setFieldFromOtherCollectionDocument: (config: AppwriteConfig, dbId: string, collIdOrName: string, docId: string, fieldName: string, otherCollIdOrName: string, otherDocId: string, otherFieldName: string) => Promise<void>;
10
+ createOrGetBucket: (config: AppwriteConfig, bucketName: string, bucketId?: string, permissions?: string[], fileSecurity?: boolean, enabled?: boolean, maxFileSize?: number, allowedExtensions?: string[], compression?: string, encryption?: boolean, antivirus?: boolean) => Promise<Models.Bucket | undefined>;
11
+ createFileAndUpdateField: (config: AppwriteConfig, dbId: string, collId: string, docId: string, fieldName: string, bucketId: string, filePath: string, fileName: string) => Promise<void>;
12
+ };
@@ -0,0 +1,196 @@
1
+ import { Databases, Storage, InputFile, Query, ID, Client, } from "node-appwrite";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ import os from "os";
5
+ const getDatabaseFromConfig = (config) => {
6
+ if (!config.appwriteClient) {
7
+ config.appwriteClient = new Client()
8
+ .setEndpoint(config.appwriteEndpoint)
9
+ .setProject(config.appwriteProject)
10
+ .setKey(config.appwriteKey);
11
+ }
12
+ return new Databases(config.appwriteClient);
13
+ };
14
+ const getStorageFromConfig = (config) => {
15
+ if (!config.appwriteClient) {
16
+ config.appwriteClient = new Client()
17
+ .setEndpoint(config.appwriteEndpoint)
18
+ .setProject(config.appwriteProject)
19
+ .setKey(config.appwriteKey);
20
+ }
21
+ return new Storage(config.appwriteClient);
22
+ };
23
+ export const afterImportActions = {
24
+ updateCreatedDocument: async (config, dbId, collId, docId, data) => {
25
+ try {
26
+ const db = getDatabaseFromConfig(config);
27
+ await db.updateDocument(dbId, collId, docId, data);
28
+ }
29
+ catch (error) {
30
+ console.error("Error updating document: ", error);
31
+ }
32
+ },
33
+ checkAndUpdateFieldInDocument: async (config, dbId, collId, docId, fieldName, oldFieldValue, newFieldValue) => {
34
+ try {
35
+ const db = getDatabaseFromConfig(config);
36
+ const doc = await db.getDocument(dbId, collId, docId);
37
+ if (doc[fieldName] == oldFieldValue) {
38
+ await db.updateDocument(dbId, collId, docId, {
39
+ [fieldName]: newFieldValue,
40
+ });
41
+ }
42
+ }
43
+ catch (error) {
44
+ console.error("Error updating document: ", error);
45
+ }
46
+ },
47
+ setFieldFromOtherCollectionDocument: async (config, dbId, collIdOrName, docId, fieldName, otherCollIdOrName, otherDocId, otherFieldName) => {
48
+ const db = getDatabaseFromConfig(config);
49
+ // Helper function to find a collection ID by name or return the ID if given
50
+ const findCollectionId = async (collectionIdentifier) => {
51
+ const collectionsPulled = await db.listCollections(dbId, [
52
+ Query.limit(25),
53
+ Query.equal("name", collectionIdentifier),
54
+ ]);
55
+ if (collectionsPulled.total > 0) {
56
+ return collectionsPulled.collections[0].$id;
57
+ }
58
+ else {
59
+ // Assuming the passed identifier might directly be an ID if not found by name
60
+ return collectionIdentifier;
61
+ }
62
+ };
63
+ try {
64
+ // Resolve the IDs for both the target and other collections
65
+ const targetCollectionId = await findCollectionId(collIdOrName);
66
+ const otherCollectionId = await findCollectionId(otherCollIdOrName);
67
+ // Retrieve the "other" document
68
+ const otherDoc = await db.getDocument(dbId, otherCollectionId, otherDocId);
69
+ const valueToSet = otherDoc[otherFieldName];
70
+ if (valueToSet) {
71
+ // Update the target document
72
+ await db.updateDocument(dbId, targetCollectionId, docId, {
73
+ [fieldName]: valueToSet,
74
+ });
75
+ }
76
+ console.log(`Field ${fieldName} updated successfully in document ${docId}.`);
77
+ }
78
+ catch (error) {
79
+ console.error("Error setting field from other collection document: ", error);
80
+ }
81
+ },
82
+ createOrGetBucket: async (config, bucketName, bucketId, permissions, fileSecurity, enabled, maxFileSize, allowedExtensions, compression, encryption, antivirus) => {
83
+ try {
84
+ const storage = getStorageFromConfig(config);
85
+ const bucket = await storage.listBuckets([
86
+ Query.equal("name", bucketName),
87
+ ]);
88
+ if (bucket.buckets.length > 0) {
89
+ return bucket.buckets[0];
90
+ }
91
+ else if (bucketId) {
92
+ try {
93
+ return await storage.getBucket(bucketId);
94
+ }
95
+ catch (error) {
96
+ return await storage.createBucket(bucketId, bucketName, permissions, fileSecurity, enabled, maxFileSize, allowedExtensions, compression, encryption, antivirus);
97
+ }
98
+ }
99
+ else {
100
+ return await storage.createBucket(bucketId || ID.unique(), bucketName, permissions, fileSecurity, enabled, maxFileSize, allowedExtensions, compression, encryption, antivirus);
101
+ }
102
+ }
103
+ catch (error) {
104
+ console.error("Error creating or getting bucket: ", error);
105
+ }
106
+ },
107
+ createFileAndUpdateField: async (config, dbId, collId, docId, fieldName, bucketId, filePath, fileName) => {
108
+ try {
109
+ const db = getDatabaseFromConfig(config);
110
+ const storage = getStorageFromConfig(config);
111
+ const collection = await db.getCollection(dbId, collId);
112
+ const attributes = collection.attributes;
113
+ const attribute = attributes.find((a) => a.key === fieldName);
114
+ // console.log(
115
+ // `Processing field ${fieldName} in collection ${collId} for document ${docId} in database ${dbId} in bucket ${bucketId} with path ${filePath} and name ${fileName}...`
116
+ // );
117
+ let isArray = false;
118
+ if (!attribute) {
119
+ console.log(`Field ${fieldName} not found in collection ${collId}, weird, skipping...`);
120
+ return;
121
+ }
122
+ else if (attribute.array === true) {
123
+ isArray = true;
124
+ }
125
+ // Define a helper function to check if a value is a URL
126
+ const isUrl = (value) => typeof value === "string" &&
127
+ (value.startsWith("http://") || value.startsWith("https://"));
128
+ const doc = await db.getDocument(dbId, collId, docId);
129
+ const existingFieldValue = doc[fieldName];
130
+ // Handle the case where the field is an array
131
+ let updateData = isArray ? [] : "";
132
+ if (isArray && Array.isArray(existingFieldValue)) {
133
+ updateData = existingFieldValue.filter((val) => !isUrl(val)); // Remove URLs from the array
134
+ }
135
+ // Process file upload and update logic
136
+ if (isUrl(filePath)) {
137
+ // Create a temporary directory
138
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "appwrite_tmp"));
139
+ const tempFilePath = path.join(tempDir, fileName);
140
+ // Download the file using fetch
141
+ const response = await fetch(filePath);
142
+ if (!response.ok)
143
+ console.error(`Failed to fetch ${filePath}: ${response.statusText} for document ${docId} with field ${fieldName}`);
144
+ // Use arrayBuffer if buffer is not available
145
+ const arrayBuffer = await response.arrayBuffer();
146
+ const buffer = Buffer.from(arrayBuffer);
147
+ fs.writeFileSync(tempFilePath, buffer);
148
+ // Create InputFile from the downloaded file
149
+ const inputFile = InputFile.fromPath(tempFilePath, fileName);
150
+ // Use the full file name (with extension) for creating the file
151
+ const file = await storage.createFile(bucketId, ID.unique(), inputFile);
152
+ console.log("Created file from URL: ", file.$id);
153
+ // After uploading, adjust the updateData based on whether the field is an array or not
154
+ if (isArray) {
155
+ updateData = [...updateData, file.$id]; // Append the new file ID
156
+ }
157
+ else {
158
+ updateData = file.$id; // Set the new file ID
159
+ }
160
+ // console.log(
161
+ // "Updating document with file: ",
162
+ // doc.$id,
163
+ // `${fieldName}: `,
164
+ // updateData
165
+ // );
166
+ // If the file was downloaded, delete it after uploading
167
+ fs.unlinkSync(tempFilePath);
168
+ }
169
+ else {
170
+ const files = fs.readdirSync(filePath);
171
+ const fileFullName = files.find((file) => file.includes(fileName));
172
+ if (!fileFullName) {
173
+ console.error(`File starting with '${fileName}' not found in '${filePath}'`);
174
+ return;
175
+ }
176
+ const pathToFile = path.join(filePath, fileFullName);
177
+ const inputFile = InputFile.fromPath(pathToFile, fileName);
178
+ const file = await storage.createFile(bucketId, ID.unique(), inputFile);
179
+ if (isArray) {
180
+ updateData = [...updateData, file.$id]; // Append the new file ID
181
+ }
182
+ else {
183
+ updateData = file.$id; // Set the new file ID
184
+ }
185
+ await db.updateDocument(dbId, collId, doc.$id, {
186
+ [fieldName]: updateData,
187
+ });
188
+ console.log("Created file from path: ", file.$id);
189
+ }
190
+ }
191
+ catch (error) {
192
+ console.error("Error creating file and updating field: ", error);
193
+ console.log(`Params were: dbId: ${dbId}, collId: ${collId}, docId: ${docId}, fieldName: ${fieldName}, filePath: ${filePath}, fileName: ${fileName}`);
194
+ }
195
+ },
196
+ };
@@ -0,0 +1,4 @@
1
+ import { type Databases, type Models } from "node-appwrite";
2
+ import type { Attribute } from "./schema.js";
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,158 @@
1
+ import { Query } from "node-appwrite";
2
+ import { nameToIdMapping, enqueueOperation } from "./queue.js";
3
+ export const createOrUpdateAttribute = async (db, dbId, collection, attribute) => {
4
+ let action = "create";
5
+ let foundAttribute;
6
+ try {
7
+ foundAttribute = await db.getAttribute(dbId, collection.$id, attribute.key);
8
+ }
9
+ catch (error) {
10
+ foundAttribute = undefined;
11
+ }
12
+ let numSameAttributes = 0;
13
+ if (foundAttribute && foundAttribute.key === attribute.key) {
14
+ numSameAttributes++;
15
+ return;
16
+ }
17
+ else if (foundAttribute) {
18
+ action = "update";
19
+ }
20
+ // Relationship attribute logic with adjustments
21
+ let collectionFoundViaRelatedCollection;
22
+ let relatedCollectionId;
23
+ if (attribute.type === "relationship") {
24
+ if (nameToIdMapping.has(attribute.relatedCollection)) {
25
+ relatedCollectionId = nameToIdMapping.get(attribute.relatedCollection);
26
+ try {
27
+ collectionFoundViaRelatedCollection = await db.getCollection(dbId, relatedCollectionId);
28
+ }
29
+ catch (e) {
30
+ console.log(`Collection not found: ${attribute.relatedCollection} when nameToIdMapping was set`);
31
+ collectionFoundViaRelatedCollection = undefined;
32
+ }
33
+ }
34
+ else {
35
+ const collectionsPulled = await db.listCollections(dbId, [
36
+ Query.equal("name", attribute.relatedCollection),
37
+ ]);
38
+ if (collectionsPulled.total > 0) {
39
+ collectionFoundViaRelatedCollection = collectionsPulled.collections[0];
40
+ relatedCollectionId = collectionFoundViaRelatedCollection.$id;
41
+ nameToIdMapping.set(attribute.relatedCollection, relatedCollectionId);
42
+ }
43
+ }
44
+ if (!(relatedCollectionId && collectionFoundViaRelatedCollection)) {
45
+ console.log(`Enqueueing operation for attribute: ${attribute.key}`);
46
+ enqueueOperation({
47
+ type: "attribute",
48
+ collectionId: collection.$id,
49
+ collection: collection,
50
+ attribute,
51
+ dependencies: [attribute.relatedCollection],
52
+ });
53
+ return;
54
+ }
55
+ }
56
+ switch (attribute.type) {
57
+ case "string":
58
+ if (action === "create") {
59
+ await db.createStringAttribute(dbId, collection.$id, attribute.key, attribute.size, attribute.required, attribute.xdefault || undefined, attribute.array, attribute.encrypted);
60
+ }
61
+ else {
62
+ await db.updateStringAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined);
63
+ }
64
+ break;
65
+ case "integer":
66
+ if (action === "create") {
67
+ await db.createIntegerAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.min, attribute.max, attribute.xdefault || undefined, attribute.array);
68
+ }
69
+ else {
70
+ await db.updateIntegerAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.min || 0, attribute.max || 2147483647, attribute.xdefault || undefined);
71
+ }
72
+ break;
73
+ case "float":
74
+ if (action === "create") {
75
+ await db.createFloatAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.min, attribute.max, attribute.xdefault || undefined, attribute.array);
76
+ }
77
+ else {
78
+ await db.updateFloatAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.min || 0, attribute.max || 2147483647, attribute.xdefault || undefined);
79
+ }
80
+ break;
81
+ case "boolean":
82
+ if (action === "create") {
83
+ await db.createBooleanAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined, attribute.array);
84
+ }
85
+ else {
86
+ await db.updateBooleanAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined);
87
+ }
88
+ break;
89
+ case "datetime":
90
+ if (action === "create") {
91
+ await db.createDatetimeAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined, attribute.array);
92
+ }
93
+ else {
94
+ await db.updateDatetimeAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined);
95
+ }
96
+ break;
97
+ case "email":
98
+ if (action === "create") {
99
+ await db.createEmailAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined, attribute.array);
100
+ }
101
+ else {
102
+ await db.updateEmailAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined);
103
+ }
104
+ break;
105
+ case "ip":
106
+ if (action === "create") {
107
+ await db.createIpAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined, attribute.array);
108
+ }
109
+ else {
110
+ await db.updateIpAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined);
111
+ }
112
+ break;
113
+ case "url":
114
+ if (action === "create") {
115
+ await db.createUrlAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined, attribute.array);
116
+ }
117
+ else {
118
+ await db.updateUrlAttribute(dbId, collection.$id, attribute.key, attribute.required, attribute.xdefault || undefined);
119
+ }
120
+ break;
121
+ case "enum":
122
+ if (action === "create") {
123
+ await db.createEnumAttribute(dbId, collection.$id, attribute.key, attribute.elements, attribute.required, attribute.xdefault || undefined, attribute.array);
124
+ }
125
+ else {
126
+ await db.updateEnumAttribute(dbId, collection.$id, attribute.key, attribute.elements, attribute.required, attribute.xdefault || undefined);
127
+ }
128
+ break;
129
+ case "relationship":
130
+ if (action === "create") {
131
+ await db.createRelationshipAttribute(dbId, collection.$id, relatedCollectionId, attribute.relationType, attribute.twoWay, attribute.key, attribute.twoWayKey, attribute.onDelete);
132
+ }
133
+ else {
134
+ await db.updateRelationshipAttribute(dbId, collection.$id, attribute.key, attribute.onDelete);
135
+ }
136
+ break;
137
+ default:
138
+ console.error("Invalid attribute type");
139
+ break;
140
+ }
141
+ };
142
+ export const createUpdateCollectionAttributes = async (db, dbId, collection, attributes) => {
143
+ console.log(`Creating/Updating attributes for collection: ${collection.name}`);
144
+ const batchSize = 3; // Size of each batch
145
+ for (let i = 0; i < attributes.length; i += batchSize) {
146
+ // Slice the attributes array to get a batch of at most batchSize elements
147
+ const batch = attributes.slice(i, i + batchSize);
148
+ const attributePromises = batch.map((attribute) => createOrUpdateAttribute(db, dbId, collection, attribute));
149
+ // Await the completion of all promises in the current batch
150
+ const results = await Promise.allSettled(attributePromises);
151
+ results.forEach((result) => {
152
+ if (result.status === "rejected") {
153
+ console.error("An attribute promise was rejected:", result.reason);
154
+ }
155
+ });
156
+ }
157
+ console.log(`Finished creating/updating attributes for collection: ${collection.name}`);
158
+ };