appwrite-utils-cli 1.3.5 → 1.4.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 (116) hide show
  1. package/dist/adapters/AdapterFactory.d.ts +87 -0
  2. package/dist/adapters/AdapterFactory.js +217 -0
  3. package/dist/adapters/DatabaseAdapter.d.ts +217 -0
  4. package/dist/adapters/DatabaseAdapter.js +50 -0
  5. package/dist/adapters/LegacyAdapter.d.ts +49 -0
  6. package/dist/adapters/LegacyAdapter.js +382 -0
  7. package/dist/adapters/TablesDBAdapter.d.ts +55 -0
  8. package/dist/adapters/TablesDBAdapter.js +302 -0
  9. package/dist/adapters/index.d.ts +11 -0
  10. package/dist/adapters/index.js +12 -0
  11. package/dist/collections/attributes.js +41 -22
  12. package/dist/collections/methods.d.ts +4 -3
  13. package/dist/collections/methods.js +34 -14
  14. package/dist/config/yamlConfig.d.ts +40 -437
  15. package/dist/config/yamlConfig.js +8 -2
  16. package/dist/databases/setup.js +2 -2
  17. package/dist/main.js +0 -0
  18. package/dist/migrations/appwriteToX.d.ts +26 -37
  19. package/dist/migrations/comprehensiveTransfer.js +4 -4
  20. package/dist/migrations/dataLoader.d.ts +124 -1484
  21. package/dist/migrations/dataLoader.js +2 -1
  22. package/dist/migrations/relationships.d.ts +2 -3
  23. package/dist/migrations/relationships.js +1 -1
  24. package/dist/migrations/services/UserMappingService.js +1 -1
  25. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +24 -279
  26. package/dist/migrations/yaml/YamlImportConfigLoader.js +7 -2
  27. package/dist/schemas/authUser.d.ts +7 -47
  28. package/dist/schemas/authUser.js +1 -1
  29. package/dist/shared/jsonSchemaGenerator.d.ts +0 -2
  30. package/dist/shared/jsonSchemaGenerator.js +4 -17
  31. package/dist/shared/migrationHelpers.d.ts +17 -119
  32. package/dist/shared/operationQueue.js +16 -7
  33. package/dist/shared/schemaGenerator.js +2 -17
  34. package/dist/storage/schemas.d.ts +149 -296
  35. package/dist/users/methods.d.ts +2 -2
  36. package/dist/utils/configMigration.js +0 -1
  37. package/dist/utils/getClientFromConfig.d.ts +26 -0
  38. package/dist/utils/getClientFromConfig.js +37 -0
  39. package/dist/utils/loadConfigs.js +0 -2
  40. package/dist/utils/schemaStrings.js +2 -17
  41. package/dist/utils/setupFiles.js +2 -0
  42. package/dist/utils/versionDetection.d.ts +56 -0
  43. package/dist/utils/versionDetection.js +217 -0
  44. package/dist/utils/yamlConverter.d.ts +0 -1
  45. package/dist/utils/yamlConverter.js +0 -2
  46. package/dist/utilsController.js +2 -0
  47. package/package.json +3 -2
  48. package/src/adapters/AdapterFactory.ts +296 -0
  49. package/src/adapters/DatabaseAdapter.ts +290 -0
  50. package/src/adapters/LegacyAdapter.ts +667 -0
  51. package/src/adapters/TablesDBAdapter.ts +429 -0
  52. package/src/adapters/index.ts +37 -0
  53. package/src/collections/attributes.ts +347 -153
  54. package/src/collections/methods.ts +43 -28
  55. package/src/config/yamlConfig.ts +8 -2
  56. package/src/databases/setup.ts +2 -2
  57. package/src/migrations/afterImportActions.ts +2 -2
  58. package/src/migrations/comprehensiveTransfer.ts +4 -0
  59. package/src/migrations/dataLoader.ts +2 -1
  60. package/src/migrations/relationships.ts +1 -1
  61. package/src/migrations/services/UserMappingService.ts +1 -1
  62. package/src/migrations/yaml/YamlImportConfigLoader.ts +7 -2
  63. package/src/schemas/authUser.ts +1 -1
  64. package/src/shared/jsonSchemaGenerator.ts +4 -19
  65. package/src/shared/operationQueue.ts +20 -13
  66. package/src/shared/schemaGenerator.ts +2 -16
  67. package/src/types/node-appwrite-tablesdb.d.ts +44 -0
  68. package/src/users/methods.ts +2 -2
  69. package/src/utils/configMigration.ts +0 -1
  70. package/src/utils/getClientFromConfig.ts +56 -0
  71. package/src/utils/loadConfigs.ts +0 -2
  72. package/src/utils/schemaStrings.ts +2 -16
  73. package/src/utils/setupFiles.ts +2 -0
  74. package/src/utils/versionDetection.ts +265 -0
  75. package/src/utils/yamlConverter.ts +0 -2
  76. package/src/utilsController.ts +2 -0
  77. package/dist/functions/openapi.d.ts +0 -4
  78. package/dist/functions/openapi.js +0 -60
  79. package/dist/migrations/attributes.d.ts +0 -4
  80. package/dist/migrations/attributes.js +0 -301
  81. package/dist/migrations/backup.d.ts +0 -687
  82. package/dist/migrations/backup.js +0 -175
  83. package/dist/migrations/collections.d.ts +0 -22
  84. package/dist/migrations/collections.js +0 -347
  85. package/dist/migrations/converters.d.ts +0 -46
  86. package/dist/migrations/converters.js +0 -139
  87. package/dist/migrations/databases.d.ts +0 -2
  88. package/dist/migrations/databases.js +0 -28
  89. package/dist/migrations/dbHelpers.d.ts +0 -5
  90. package/dist/migrations/dbHelpers.js +0 -57
  91. package/dist/migrations/helper.d.ts +0 -3
  92. package/dist/migrations/helper.js +0 -21
  93. package/dist/migrations/indexes.d.ts +0 -4
  94. package/dist/migrations/indexes.js +0 -19
  95. package/dist/migrations/logging.d.ts +0 -10
  96. package/dist/migrations/logging.js +0 -46
  97. package/dist/migrations/migrationHelper.d.ts +0 -173
  98. package/dist/migrations/migrationHelper.js +0 -130
  99. package/dist/migrations/openapi.d.ts +0 -4
  100. package/dist/migrations/openapi.js +0 -60
  101. package/dist/migrations/queue.d.ts +0 -13
  102. package/dist/migrations/queue.js +0 -79
  103. package/dist/migrations/schemaStrings.d.ts +0 -14
  104. package/dist/migrations/schemaStrings.js +0 -478
  105. package/dist/migrations/setupDatabase.d.ts +0 -6
  106. package/dist/migrations/setupDatabase.js +0 -115
  107. package/dist/migrations/storage.d.ts +0 -10
  108. package/dist/migrations/storage.js +0 -340
  109. package/dist/migrations/users.d.ts +0 -16
  110. package/dist/migrations/users.js +0 -276
  111. package/dist/migrations/validationRules.d.ts +0 -43
  112. package/dist/migrations/validationRules.js +0 -42
  113. package/dist/shared/attributeManager.d.ts +0 -17
  114. package/dist/shared/attributeManager.js +0 -272
  115. package/src/functions/openapi.ts +0 -83
  116. package/src/shared/attributeManager.ts +0 -428
@@ -0,0 +1,302 @@
1
+ /**
2
+ * TablesDBAdapter - Native TablesDB API Implementation
3
+ *
4
+ * This adapter provides direct access to the new Appwrite TablesDB API
5
+ * without any translation layer. It uses object notation parameters
6
+ * and returns Models.Row instead of Models.Document.
7
+ */
8
+ import { BaseAdapter, AdapterError } from './DatabaseAdapter.js';
9
+ /**
10
+ * TablesDBAdapter implementation for native TablesDB API
11
+ */
12
+ export class TablesDBAdapter extends BaseAdapter {
13
+ tablesDB;
14
+ constructor(client) {
15
+ super(client, 'tablesdb');
16
+ // Assuming TablesDB service is available on the client
17
+ this.tablesDB = client.tablesDB || client;
18
+ }
19
+ // Row (Document) Operations
20
+ async listRows(params) {
21
+ try {
22
+ const result = await this.tablesDB.listRows(params);
23
+ return {
24
+ data: result.rows,
25
+ rows: result.rows,
26
+ total: result.total
27
+ };
28
+ }
29
+ catch (error) {
30
+ throw new AdapterError(`Failed to list rows: ${error instanceof Error ? error.message : 'Unknown error'}`, 'LIST_ROWS_FAILED', error instanceof Error ? error : undefined);
31
+ }
32
+ }
33
+ async createRow(params) {
34
+ try {
35
+ const result = await this.tablesDB.createRow(params);
36
+ return {
37
+ data: result,
38
+ rows: [result]
39
+ };
40
+ }
41
+ catch (error) {
42
+ throw new AdapterError(`Failed to create row: ${error instanceof Error ? error.message : 'Unknown error'}`, 'CREATE_ROW_FAILED', error instanceof Error ? error : undefined);
43
+ }
44
+ }
45
+ async updateRow(params) {
46
+ try {
47
+ const result = await this.tablesDB.updateRow(params);
48
+ return {
49
+ data: result,
50
+ rows: [result]
51
+ };
52
+ }
53
+ catch (error) {
54
+ throw new AdapterError(`Failed to update row: ${error instanceof Error ? error.message : 'Unknown error'}`, 'UPDATE_ROW_FAILED', error instanceof Error ? error : undefined);
55
+ }
56
+ }
57
+ async deleteRow(params) {
58
+ try {
59
+ const result = await this.tablesDB.deleteRow(params);
60
+ return { data: result };
61
+ }
62
+ catch (error) {
63
+ throw new AdapterError(`Failed to delete row: ${error instanceof Error ? error.message : 'Unknown error'}`, 'DELETE_ROW_FAILED', error instanceof Error ? error : undefined);
64
+ }
65
+ }
66
+ async getRow(params) {
67
+ try {
68
+ const result = await this.tablesDB.getRow(params);
69
+ return {
70
+ data: result,
71
+ rows: [result]
72
+ };
73
+ }
74
+ catch (error) {
75
+ throw new AdapterError(`Failed to get row: ${error instanceof Error ? error.message : 'Unknown error'}`, 'GET_ROW_FAILED', error instanceof Error ? error : undefined);
76
+ }
77
+ }
78
+ // Table (Collection) Operations
79
+ async listTables(params) {
80
+ try {
81
+ const result = await this.tablesDB.listTables(params);
82
+ return {
83
+ data: result.tables,
84
+ tables: result.tables,
85
+ total: result.total
86
+ };
87
+ }
88
+ catch (error) {
89
+ throw new AdapterError(`Failed to list tables: ${error instanceof Error ? error.message : 'Unknown error'}`, 'LIST_TABLES_FAILED', error instanceof Error ? error : undefined);
90
+ }
91
+ }
92
+ async createTable(params) {
93
+ try {
94
+ const result = await this.tablesDB.createTable(params);
95
+ return {
96
+ data: result,
97
+ tables: [result]
98
+ };
99
+ }
100
+ catch (error) {
101
+ throw new AdapterError(`Failed to create table: ${error instanceof Error ? error.message : 'Unknown error'}`, 'CREATE_TABLE_FAILED', error instanceof Error ? error : undefined);
102
+ }
103
+ }
104
+ async updateTable(params) {
105
+ try {
106
+ const result = await this.tablesDB.updateTable(params);
107
+ return {
108
+ data: result,
109
+ tables: [result]
110
+ };
111
+ }
112
+ catch (error) {
113
+ throw new AdapterError(`Failed to update table: ${error instanceof Error ? error.message : 'Unknown error'}`, 'UPDATE_TABLE_FAILED', error instanceof Error ? error : undefined);
114
+ }
115
+ }
116
+ async deleteTable(params) {
117
+ try {
118
+ const result = await this.tablesDB.deleteTable(params);
119
+ return { data: result };
120
+ }
121
+ catch (error) {
122
+ throw new AdapterError(`Failed to delete table: ${error instanceof Error ? error.message : 'Unknown error'}`, 'DELETE_TABLE_FAILED', error instanceof Error ? error : undefined);
123
+ }
124
+ }
125
+ async getTable(params) {
126
+ try {
127
+ const result = await this.tablesDB.getTable(params);
128
+ return {
129
+ data: result,
130
+ tables: [result]
131
+ };
132
+ }
133
+ catch (error) {
134
+ throw new AdapterError(`Failed to get table: ${error instanceof Error ? error.message : 'Unknown error'}`, 'GET_TABLE_FAILED', error instanceof Error ? error : undefined);
135
+ }
136
+ }
137
+ // Index Operations
138
+ async listIndexes(params) {
139
+ try {
140
+ const result = await this.tablesDB.listIndexes(params);
141
+ return {
142
+ data: result.indexes,
143
+ total: result.total
144
+ };
145
+ }
146
+ catch (error) {
147
+ throw new AdapterError(`Failed to list indexes: ${error instanceof Error ? error.message : 'Unknown error'}`, 'LIST_INDEXES_FAILED', error instanceof Error ? error : undefined);
148
+ }
149
+ }
150
+ async createIndex(params) {
151
+ try {
152
+ const result = await this.tablesDB.createIndex(params);
153
+ return { data: result };
154
+ }
155
+ catch (error) {
156
+ throw new AdapterError(`Failed to create index: ${error instanceof Error ? error.message : 'Unknown error'}`, 'CREATE_INDEX_FAILED', error instanceof Error ? error : undefined);
157
+ }
158
+ }
159
+ async deleteIndex(params) {
160
+ try {
161
+ const result = await this.tablesDB.deleteIndex(params);
162
+ return { data: result };
163
+ }
164
+ catch (error) {
165
+ throw new AdapterError(`Failed to delete index: ${error instanceof Error ? error.message : 'Unknown error'}`, 'DELETE_INDEX_FAILED', error instanceof Error ? error : undefined);
166
+ }
167
+ }
168
+ // Attribute Operations
169
+ async createAttribute(params) {
170
+ try {
171
+ // TablesDB may have different method names for attribute operations
172
+ const result = await this.tablesDB.createAttribute(params);
173
+ return { data: result };
174
+ }
175
+ catch (error) {
176
+ throw new AdapterError(`Failed to create attribute: ${error instanceof Error ? error.message : 'Unknown error'}`, 'CREATE_ATTRIBUTE_FAILED', error instanceof Error ? error : undefined);
177
+ }
178
+ }
179
+ async updateAttribute(params) {
180
+ try {
181
+ const result = await this.tablesDB.updateAttribute(params);
182
+ return { data: result };
183
+ }
184
+ catch (error) {
185
+ throw new AdapterError(`Failed to update attribute: ${error instanceof Error ? error.message : 'Unknown error'}`, 'UPDATE_ATTRIBUTE_FAILED', error instanceof Error ? error : undefined);
186
+ }
187
+ }
188
+ async deleteAttribute(params) {
189
+ try {
190
+ const result = await this.tablesDB.deleteAttribute(params);
191
+ return { data: result };
192
+ }
193
+ catch (error) {
194
+ throw new AdapterError(`Failed to delete attribute: ${error instanceof Error ? error.message : 'Unknown error'}`, 'DELETE_ATTRIBUTE_FAILED', error instanceof Error ? error : undefined);
195
+ }
196
+ }
197
+ // Bulk Operations (Native TablesDB Support)
198
+ async bulkCreateRows(params) {
199
+ try {
200
+ const result = await this.tablesDB.bulkCreateRows(params);
201
+ return {
202
+ data: result.rows,
203
+ rows: result.rows,
204
+ total: result.rows?.length || 0
205
+ };
206
+ }
207
+ catch (error) {
208
+ throw new AdapterError(`Failed to bulk create rows: ${error instanceof Error ? error.message : 'Unknown error'}`, 'BULK_CREATE_ROWS_FAILED', error instanceof Error ? error : undefined);
209
+ }
210
+ }
211
+ async bulkUpsertRows(params) {
212
+ try {
213
+ const result = await this.tablesDB.bulkUpsertRows(params);
214
+ return {
215
+ data: result.rows,
216
+ rows: result.rows,
217
+ total: result.rows?.length || 0
218
+ };
219
+ }
220
+ catch (error) {
221
+ throw new AdapterError(`Failed to bulk upsert rows: ${error instanceof Error ? error.message : 'Unknown error'}`, 'BULK_UPSERT_ROWS_FAILED', error instanceof Error ? error : undefined);
222
+ }
223
+ }
224
+ async bulkDeleteRows(params) {
225
+ try {
226
+ const result = await this.tablesDB.bulkDeleteRows(params);
227
+ return {
228
+ data: result,
229
+ total: params.rowIds.length
230
+ };
231
+ }
232
+ catch (error) {
233
+ throw new AdapterError(`Failed to bulk delete rows: ${error instanceof Error ? error.message : 'Unknown error'}`, 'BULK_DELETE_ROWS_FAILED', error instanceof Error ? error : undefined);
234
+ }
235
+ }
236
+ // Metadata and Capabilities
237
+ getMetadata() {
238
+ return {
239
+ apiMode: 'tablesdb',
240
+ terminology: {
241
+ container: 'table',
242
+ item: 'row',
243
+ service: 'TablesDB'
244
+ },
245
+ capabilities: {
246
+ bulkOperations: true,
247
+ advancedQueries: true,
248
+ realtime: true,
249
+ transactions: true // TablesDB may support transactions
250
+ }
251
+ };
252
+ }
253
+ supportsBulkOperations() {
254
+ return true; // TablesDB natively supports bulk operations
255
+ }
256
+ // Advanced TablesDB Features
257
+ /**
258
+ * Execute a transaction (if supported by TablesDB)
259
+ */
260
+ async executeTransaction(operations) {
261
+ if (!this.tablesDB.transaction) {
262
+ throw new AdapterError('Transactions are not supported in this TablesDB version', 'TRANSACTIONS_NOT_SUPPORTED');
263
+ }
264
+ try {
265
+ const result = await this.tablesDB.transaction(operations);
266
+ return { data: result };
267
+ }
268
+ catch (error) {
269
+ throw new AdapterError(`Transaction failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'TRANSACTION_FAILED', error instanceof Error ? error : undefined);
270
+ }
271
+ }
272
+ /**
273
+ * Subscribe to real-time updates (if supported)
274
+ */
275
+ subscribeToTable(params, callback) {
276
+ if (!this.tablesDB.subscribe) {
277
+ throw new AdapterError('Real-time subscriptions are not supported', 'REALTIME_NOT_SUPPORTED');
278
+ }
279
+ try {
280
+ return this.tablesDB.subscribe(`databases.${params.databaseId}.tables.${params.tableId}.rows`, callback);
281
+ }
282
+ catch (error) {
283
+ throw new AdapterError(`Failed to subscribe to table: ${error instanceof Error ? error.message : 'Unknown error'}`, 'SUBSCRIPTION_FAILED', error instanceof Error ? error : undefined);
284
+ }
285
+ }
286
+ /**
287
+ * Get table statistics (if available in TablesDB)
288
+ */
289
+ async getTableStats(params) {
290
+ try {
291
+ if (!this.tablesDB.getTableStats) {
292
+ // Fallback to basic table info
293
+ return this.getTable(params);
294
+ }
295
+ const result = await this.tablesDB.getTableStats(params);
296
+ return { data: result };
297
+ }
298
+ catch (error) {
299
+ throw new AdapterError(`Failed to get table stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 'GET_TABLE_STATS_FAILED', error instanceof Error ? error : undefined);
300
+ }
301
+ }
302
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Adapters Module - Unified Database API for Appwrite
3
+ *
4
+ * This module exports all adapter classes and utilities for working with
5
+ * both legacy Appwrite (collections/documents) and TablesDB (tables/rows) APIs.
6
+ */
7
+ export { AdapterFactory, type AdapterFactoryConfig, type AdapterFactoryResult } from './AdapterFactory.js';
8
+ export { type DatabaseAdapter, type CreateRowParams, type UpdateRowParams, type ListRowsParams, type DeleteRowParams, type CreateTableParams, type UpdateTableParams, type ListTablesParams, type DeleteTableParams, type GetTableParams, type BulkCreateRowsParams, type BulkUpsertRowsParams, type BulkDeleteRowsParams, type CreateIndexParams, type ListIndexesParams, type DeleteIndexParams, type CreateAttributeParams, type UpdateAttributeParams, type DeleteAttributeParams, type ApiResponse, type AdapterMetadata, BaseAdapter } from './DatabaseAdapter.js';
9
+ export { TablesDBAdapter } from './TablesDBAdapter.js';
10
+ export { LegacyAdapter } from './LegacyAdapter.js';
11
+ export { createDatabaseAdapter, getApiCapabilities } from './AdapterFactory.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Adapters Module - Unified Database API for Appwrite
3
+ *
4
+ * This module exports all adapter classes and utilities for working with
5
+ * both legacy Appwrite (collections/documents) and TablesDB (tables/rows) APIs.
6
+ */
7
+ export { AdapterFactory } from './AdapterFactory.js';
8
+ export { BaseAdapter } from './DatabaseAdapter.js';
9
+ export { TablesDBAdapter } from './TablesDBAdapter.js';
10
+ export { LegacyAdapter } from './LegacyAdapter.js';
11
+ // Convenience exports
12
+ export { createDatabaseAdapter, getApiCapabilities } from './AdapterFactory.js';
@@ -29,19 +29,19 @@ retryCount = 0, maxRetries = 5) => {
29
29
  }
30
30
  console.log(chalk.gray(`Attribute '${attributeKey}' status: ${attribute.status}`));
31
31
  switch (attribute.status) {
32
- case 'available':
32
+ case "available":
33
33
  console.log(chalk.green(`✅ Attribute '${attributeKey}' is now available`));
34
34
  return true;
35
- case 'failed':
35
+ case "failed":
36
36
  console.log(chalk.red(`❌ Attribute '${attributeKey}' failed: ${attribute.error}`));
37
37
  return false;
38
- case 'stuck':
38
+ case "stuck":
39
39
  console.log(chalk.yellow(`⚠️ Attribute '${attributeKey}' is stuck, will retry...`));
40
40
  return false;
41
- case 'processing':
41
+ case "processing":
42
42
  // Continue waiting
43
43
  break;
44
- case 'deleting':
44
+ case "deleting":
45
45
  console.log(chalk.yellow(`Attribute '${attributeKey}' is being deleted`));
46
46
  break;
47
47
  default:
@@ -254,7 +254,8 @@ export const createOrUpdateAttribute = async (db, dbId, collection, attribute) =
254
254
  // Relationship attribute logic with adjustments
255
255
  let collectionFoundViaRelatedCollection;
256
256
  let relatedCollectionId;
257
- if (finalAttribute.type === "relationship") {
257
+ if (finalAttribute.type === "relationship" &&
258
+ finalAttribute.relatedCollection) {
258
259
  if (nameToIdMapping.has(finalAttribute.relatedCollection)) {
259
260
  relatedCollectionId = nameToIdMapping.get(finalAttribute.relatedCollection);
260
261
  try {
@@ -277,9 +278,9 @@ export const createOrUpdateAttribute = async (db, dbId, collection, attribute) =
277
278
  nameToIdMapping.set(finalAttribute.relatedCollection, relatedCollectionId);
278
279
  }
279
280
  }
280
- // Only queue relationship attributes that have dependencies
281
- if (finalAttribute.type === "relationship" && !(relatedCollectionId && collectionFoundViaRelatedCollection)) {
282
- // console.log(`Enqueueing operation for attribute: ${finalAttribute.key}`);
281
+ // ONLY queue relationship attributes that have actual unresolved dependencies
282
+ if (!(relatedCollectionId && collectionFoundViaRelatedCollection)) {
283
+ console.log(chalk.yellow(`⏳ Queueing relationship attribute '${finalAttribute.key}' - related collection '${finalAttribute.relatedCollection}' not found yet`));
283
284
  enqueueOperation({
284
285
  type: "attribute",
285
286
  collectionId: collection.$id,
@@ -302,35 +303,49 @@ export const createOrUpdateAttribute = async (db, dbId, collection, attribute) =
302
303
  else {
303
304
  await tryAwaitWithRetry(async () => await db.updateStringAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault !== undefined && !finalAttribute.required
304
305
  ? finalAttribute.xdefault
305
- : null));
306
+ : null, finalAttribute.size));
306
307
  }
307
308
  break;
308
309
  case "integer":
309
310
  if (action === "create") {
310
311
  if (finalAttribute.min &&
311
312
  BigInt(finalAttribute.min) === BigInt(-9223372036854776000)) {
312
- delete finalAttribute.min;
313
+ finalAttribute.min = undefined;
313
314
  }
314
315
  if (finalAttribute.max &&
315
316
  BigInt(finalAttribute.max) === BigInt(9223372036854776000)) {
316
- delete finalAttribute.max;
317
+ finalAttribute.max = undefined;
317
318
  }
318
- await tryAwaitWithRetry(async () => await db.createIntegerAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.min !== undefined ? finalAttribute.min : -2147483647, finalAttribute.max !== undefined ? finalAttribute.max : 2147483647, finalAttribute.xdefault !== undefined && !finalAttribute.required
319
+ const minValue = finalAttribute.min !== undefined && finalAttribute.min !== null
320
+ ? parseInt(finalAttribute.min)
321
+ : -9007199254740991;
322
+ const maxValue = finalAttribute.max !== undefined && finalAttribute.max !== null
323
+ ? parseInt(finalAttribute.max)
324
+ : 9007199254740991;
325
+ console.log(`DEBUG: Creating integer attribute '${finalAttribute.key}' with min=${minValue}, max=${maxValue}, minType=${typeof minValue}, maxType=${typeof maxValue}`);
326
+ await tryAwaitWithRetry(async () => await db.createIntegerAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, minValue, maxValue, finalAttribute.xdefault !== undefined && !finalAttribute.required
319
327
  ? finalAttribute.xdefault
320
328
  : null, finalAttribute.array || false));
321
329
  }
322
330
  else {
323
331
  if (finalAttribute.min &&
324
332
  BigInt(finalAttribute.min) === BigInt(-9223372036854776000)) {
325
- delete finalAttribute.min;
333
+ finalAttribute.min = undefined;
326
334
  }
327
335
  if (finalAttribute.max &&
328
336
  BigInt(finalAttribute.max) === BigInt(9223372036854776000)) {
329
- delete finalAttribute.max;
337
+ finalAttribute.max = undefined;
330
338
  }
331
- await tryAwaitWithRetry(async () => await db.updateIntegerAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.min !== undefined ? finalAttribute.min : -2147483647, finalAttribute.max !== undefined ? finalAttribute.max : 2147483647, finalAttribute.xdefault !== undefined && !finalAttribute.required
339
+ const minValue = finalAttribute.min !== undefined && finalAttribute.min !== null
340
+ ? parseInt(finalAttribute.min)
341
+ : 9007199254740991;
342
+ const maxValue = finalAttribute.max !== undefined && finalAttribute.max !== null
343
+ ? parseInt(finalAttribute.max)
344
+ : 9007199254740991;
345
+ console.log(`DEBUG: Updating integer attribute '${finalAttribute.key}' with min=${minValue}, max=${maxValue}, minType=${typeof minValue}, maxType=${typeof maxValue}`);
346
+ await tryAwaitWithRetry(async () => await db.updateIntegerAttribute(dbId, collection.$id, finalAttribute.key, finalAttribute.required || false, finalAttribute.xdefault !== undefined && !finalAttribute.required
332
347
  ? finalAttribute.xdefault
333
- : null));
348
+ : null, minValue, maxValue));
334
349
  }
335
350
  break;
336
351
  case "double":
@@ -469,15 +484,16 @@ export const createUpdateCollectionAttributesWithStatusCheck = async (db, dbId,
469
484
  }
470
485
  const existingAttributesMap = new Map();
471
486
  try {
487
+ const parsedAttributes = currentCollection.attributes.map((attr) =>
472
488
  // @ts-expect-error
473
- const parsedAttributes = currentCollection.attributes.map((attr) => parseAttribute(attr));
474
- parsedAttributes.forEach(attr => existingAttributesMap.set(attr.key, attr));
489
+ parseAttribute(attr));
490
+ parsedAttributes.forEach((attr) => existingAttributesMap.set(attr.key, attr));
475
491
  }
476
492
  catch (error) {
477
493
  console.log(chalk.yellow(`Warning: Could not parse existing attributes: ${error}`));
478
494
  }
479
495
  // Filter to only attributes that need processing (new or changed)
480
- const attributesToProcess = attributes.filter(attribute => {
496
+ const attributesToProcess = attributes.filter((attribute) => {
481
497
  const existing = existingAttributesMap.get(attribute.key);
482
498
  if (!existing) {
483
499
  console.log(chalk.blue(`➕ New attribute: ${attribute.key}`));
@@ -500,7 +516,8 @@ export const createUpdateCollectionAttributesWithStatusCheck = async (db, dbId,
500
516
  let remainingAttributes = [...attributesToProcess];
501
517
  let overallRetryCount = 0;
502
518
  const maxOverallRetries = 3;
503
- while (remainingAttributes.length > 0 && overallRetryCount < maxOverallRetries) {
519
+ while (remainingAttributes.length > 0 &&
520
+ overallRetryCount < maxOverallRetries) {
504
521
  const attributesToProcessThisRound = [...remainingAttributes];
505
522
  remainingAttributes = []; // Reset for next iteration
506
523
  console.log(chalk.blue(`\n=== Attempt ${overallRetryCount + 1}/${maxOverallRetries} - Processing ${attributesToProcessThisRound.length} attributes ===`));
@@ -544,7 +561,9 @@ export const createUpdateCollectionAttributesWithStatusCheck = async (db, dbId,
544
561
  }
545
562
  // If we get here, some attributes still failed after all retries
546
563
  if (attributesToProcess.length > 0) {
547
- console.log(chalk.red(`\n❌ Failed to create ${attributesToProcess.length} attributes after ${maxOverallRetries} attempts: ${attributesToProcess.map(a => a.key).join(', ')}`));
564
+ console.log(chalk.red(`\n❌ Failed to create ${attributesToProcess.length} attributes after ${maxOverallRetries} attempts: ${attributesToProcess
565
+ .map((a) => a.key)
566
+ .join(", ")}`));
548
567
  console.log(chalk.red(`This may indicate a fundamental issue with the attribute definitions or Appwrite instance`));
549
568
  return false;
550
569
  }
@@ -1,8 +1,9 @@
1
1
  import { Databases, type Models } from "node-appwrite";
2
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>;
3
+ import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
4
+ export declare const documentExists: (db: Databases | DatabaseAdapter, dbId: string, targetCollectionId: string, toCreateObject: any) => Promise<Models.Document | null>;
5
+ export declare const checkForCollection: (db: Databases | DatabaseAdapter, dbId: string, collection: Partial<CollectionCreate>) => Promise<Models.Collection | null>;
6
+ export declare const fetchAndCacheCollectionByName: (db: Databases | DatabaseAdapter, dbId: string, collectionName: string) => Promise<Models.Collection | undefined>;
6
7
  export declare const wipeDatabase: (database: Databases, databaseId: string) => Promise<{
7
8
  collectionId: string;
8
9
  collectionName: string;
@@ -1,5 +1,6 @@
1
1
  import { Client, Databases, ID, Permission, Query, } from "node-appwrite";
2
- import { nameToIdMapping, processQueue } from "../shared/operationQueue.js";
2
+ import { getAdapterFromConfig } from "../utils/getClientFromConfig.js";
3
+ import { nameToIdMapping, processQueue, queuedOperations } from "../shared/operationQueue.js";
3
4
  import { createUpdateCollectionAttributes, createUpdateCollectionAttributesWithStatusCheck } from "./attributes.js";
4
5
  import { createOrUpdateIndexes, createOrUpdateIndexesWithStatusCheck } from "./indexes.js";
5
6
  import { SchemaGenerator } from "../shared/schemaGenerator.js";
@@ -9,7 +10,9 @@ import { MessageFormatter } from "../shared/messageFormatter.js";
9
10
  import { ProgressManager } from "../shared/progressManager.js";
10
11
  import chalk from "chalk";
11
12
  export const documentExists = async (db, dbId, targetCollectionId, toCreateObject) => {
12
- const collection = await db.getCollection(dbId, targetCollectionId);
13
+ const collection = await (db instanceof Databases ?
14
+ db.getCollection(dbId, targetCollectionId) :
15
+ db.getTable({ databaseId: dbId, tableId: targetCollectionId }));
13
16
  const attributes = collection.attributes;
14
17
  let arrayTypeAttributes = attributes
15
18
  .filter((attribute) => attribute.array === true)
@@ -46,16 +49,22 @@ export const documentExists = async (db, dbId, targetCollectionId, toCreateObjec
46
49
  // Convert to Query parameters
47
50
  const validQueryParams = validMappedEntries.map(([key, value]) => Query.equal(key, value));
48
51
  // Execute the query with the validated and prepared parameters
49
- const result = await db.listDocuments(dbId, targetCollectionId, validQueryParams);
50
- return result.documents[0] || null;
52
+ const result = await (db instanceof Databases ?
53
+ db.listDocuments(dbId, targetCollectionId, validQueryParams) :
54
+ db.listRows({ databaseId: dbId, tableId: targetCollectionId, queries: validQueryParams }));
55
+ const items = db instanceof Databases ? result.documents : (result.rows || result.documents);
56
+ return items?.[0] || null;
51
57
  };
52
58
  export const checkForCollection = async (db, dbId, collection) => {
53
59
  try {
54
60
  MessageFormatter.progress(`Checking for collection with name: ${collection.name}`, { prefix: "Collections" });
55
- const response = await tryAwaitWithRetry(async () => await db.listCollections(dbId, [Query.equal("name", collection.name)]));
56
- if (response.collections.length > 0) {
57
- MessageFormatter.info(`Collection found: ${response.collections[0].$id}`, { prefix: "Collections" });
58
- return { ...collection, ...response.collections[0] };
61
+ const response = await tryAwaitWithRetry(async () => db instanceof Databases ?
62
+ await db.listCollections(dbId, [Query.equal("name", collection.name)]) :
63
+ await db.listTables({ databaseId: dbId, queries: [Query.equal("name", collection.name)] }));
64
+ const items = db instanceof Databases ? response.collections : (response.tables || response.collections);
65
+ if (items && items.length > 0) {
66
+ MessageFormatter.info(`Collection found: ${items[0].$id}`, { prefix: "Collections" });
67
+ return { ...collection, ...items[0] };
59
68
  }
60
69
  else {
61
70
  MessageFormatter.info(`No collection found with name: ${collection.name}`, { prefix: "Collections" });
@@ -72,13 +81,18 @@ export const fetchAndCacheCollectionByName = async (db, dbId, collectionName) =>
72
81
  if (nameToIdMapping.has(collectionName)) {
73
82
  const collectionId = nameToIdMapping.get(collectionName);
74
83
  MessageFormatter.debug(`Collection found in cache: ${collectionId}`, undefined, { prefix: "Collections" });
75
- return await tryAwaitWithRetry(async () => await db.getCollection(dbId, collectionId));
84
+ return await tryAwaitWithRetry(async () => db instanceof Databases ?
85
+ await db.getCollection(dbId, collectionId) :
86
+ await db.getTable({ databaseId: dbId, tableId: collectionId }));
76
87
  }
77
88
  else {
78
89
  MessageFormatter.progress(`Fetching collection by name: ${collectionName}`, { prefix: "Collections" });
79
- const collectionsPulled = await tryAwaitWithRetry(async () => await db.listCollections(dbId, [Query.equal("name", collectionName)]));
80
- if (collectionsPulled.total > 0) {
81
- const collection = collectionsPulled.collections[0];
90
+ const collectionsPulled = await tryAwaitWithRetry(async () => db instanceof Databases ?
91
+ await db.listCollections(dbId, [Query.equal("name", collectionName)]) :
92
+ await db.listTables({ databaseId: dbId, queries: [Query.equal("name", collectionName)] }));
93
+ const items = db instanceof Databases ? collectionsPulled.collections : (collectionsPulled.tables || collectionsPulled.collections);
94
+ if ((collectionsPulled.total || items?.length) > 0) {
95
+ const collection = items[0];
82
96
  MessageFormatter.info(`Collection found: ${collection.$id}`, { prefix: "Collections" });
83
97
  nameToIdMapping.set(collectionName, collection.$id);
84
98
  return collection;
@@ -281,8 +295,14 @@ export const createOrUpdateCollections = async (database, databaseId, config, de
281
295
  // Add delay after creating indexes
282
296
  await delay(250);
283
297
  }
284
- // Process any remaining tasks in the queue
285
- await processQueue(database, databaseId);
298
+ // Process any remaining tasks in the queue (only if there are operations to process)
299
+ if (queuedOperations.length > 0) {
300
+ MessageFormatter.info(`Processing ${queuedOperations.length} queued operations (relationship dependencies)`, { prefix: "Collections" });
301
+ await processQueue(database, databaseId);
302
+ }
303
+ else {
304
+ MessageFormatter.info("No queued operations to process", { prefix: "Collections" });
305
+ }
286
306
  };
287
307
  export const generateMockData = async (database, databaseId, configCollections) => {
288
308
  for (const { collection, mockFunction } of configCollections) {