appwrite-utils-cli 1.5.2 → 1.6.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 (233) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +251 -29
  3. package/dist/adapters/AdapterFactory.d.ts +10 -3
  4. package/dist/adapters/AdapterFactory.js +213 -17
  5. package/dist/adapters/TablesDBAdapter.js +60 -17
  6. package/dist/backups/operations/bucketBackup.d.ts +19 -0
  7. package/dist/backups/operations/bucketBackup.js +197 -0
  8. package/dist/backups/operations/collectionBackup.d.ts +30 -0
  9. package/dist/backups/operations/collectionBackup.js +201 -0
  10. package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
  11. package/dist/backups/operations/comprehensiveBackup.js +238 -0
  12. package/dist/backups/schemas/bucketManifest.d.ts +93 -0
  13. package/dist/backups/schemas/bucketManifest.js +33 -0
  14. package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
  15. package/dist/backups/schemas/comprehensiveManifest.js +32 -0
  16. package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
  17. package/dist/backups/tracking/centralizedTracking.js +274 -0
  18. package/dist/cli/commands/configCommands.d.ts +8 -0
  19. package/dist/cli/commands/configCommands.js +160 -0
  20. package/dist/cli/commands/databaseCommands.d.ts +13 -0
  21. package/dist/cli/commands/databaseCommands.js +478 -0
  22. package/dist/cli/commands/functionCommands.d.ts +7 -0
  23. package/dist/cli/commands/functionCommands.js +289 -0
  24. package/dist/cli/commands/schemaCommands.d.ts +7 -0
  25. package/dist/cli/commands/schemaCommands.js +134 -0
  26. package/dist/cli/commands/transferCommands.d.ts +5 -0
  27. package/dist/cli/commands/transferCommands.js +384 -0
  28. package/dist/collections/attributes.d.ts +5 -4
  29. package/dist/collections/attributes.js +539 -246
  30. package/dist/collections/indexes.js +39 -37
  31. package/dist/collections/methods.d.ts +2 -16
  32. package/dist/collections/methods.js +90 -538
  33. package/dist/collections/transferOperations.d.ts +7 -0
  34. package/dist/collections/transferOperations.js +331 -0
  35. package/dist/collections/wipeOperations.d.ts +16 -0
  36. package/dist/collections/wipeOperations.js +328 -0
  37. package/dist/config/configMigration.d.ts +87 -0
  38. package/dist/config/configMigration.js +390 -0
  39. package/dist/config/configValidation.d.ts +66 -0
  40. package/dist/config/configValidation.js +358 -0
  41. package/dist/config/yamlConfig.d.ts +455 -1
  42. package/dist/config/yamlConfig.js +145 -52
  43. package/dist/databases/methods.js +3 -2
  44. package/dist/databases/setup.d.ts +1 -2
  45. package/dist/databases/setup.js +9 -87
  46. package/dist/examples/yamlTerminologyExample.d.ts +42 -0
  47. package/dist/examples/yamlTerminologyExample.js +269 -0
  48. package/dist/functions/deployments.js +11 -10
  49. package/dist/functions/methods.d.ts +1 -1
  50. package/dist/functions/methods.js +5 -4
  51. package/dist/init.js +9 -9
  52. package/dist/interactiveCLI.d.ts +8 -17
  53. package/dist/interactiveCLI.js +181 -1172
  54. package/dist/main.js +364 -21
  55. package/dist/migrations/afterImportActions.js +22 -30
  56. package/dist/migrations/appwriteToX.js +71 -25
  57. package/dist/migrations/dataLoader.js +35 -26
  58. package/dist/migrations/importController.js +29 -30
  59. package/dist/migrations/relationships.js +13 -12
  60. package/dist/migrations/services/ImportOrchestrator.js +16 -19
  61. package/dist/migrations/transfer.js +46 -46
  62. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +3 -1
  63. package/dist/migrations/yaml/YamlImportConfigLoader.js +6 -3
  64. package/dist/migrations/yaml/YamlImportIntegration.d.ts +9 -3
  65. package/dist/migrations/yaml/YamlImportIntegration.js +22 -11
  66. package/dist/migrations/yaml/generateImportSchemas.d.ts +14 -1
  67. package/dist/migrations/yaml/generateImportSchemas.js +736 -7
  68. package/dist/schemas/authUser.d.ts +1 -1
  69. package/dist/setupController.js +3 -2
  70. package/dist/shared/backupMetadataSchema.d.ts +94 -0
  71. package/dist/shared/backupMetadataSchema.js +38 -0
  72. package/dist/shared/backupTracking.d.ts +18 -0
  73. package/dist/shared/backupTracking.js +176 -0
  74. package/dist/shared/confirmationDialogs.js +15 -15
  75. package/dist/shared/errorUtils.d.ts +54 -0
  76. package/dist/shared/errorUtils.js +95 -0
  77. package/dist/shared/functionManager.js +20 -19
  78. package/dist/shared/indexManager.js +12 -11
  79. package/dist/shared/jsonSchemaGenerator.js +10 -26
  80. package/dist/shared/logging.d.ts +51 -0
  81. package/dist/shared/logging.js +70 -0
  82. package/dist/shared/messageFormatter.d.ts +2 -0
  83. package/dist/shared/messageFormatter.js +10 -0
  84. package/dist/shared/migrationHelpers.d.ts +6 -16
  85. package/dist/shared/migrationHelpers.js +24 -21
  86. package/dist/shared/operationLogger.d.ts +8 -1
  87. package/dist/shared/operationLogger.js +11 -24
  88. package/dist/shared/operationQueue.d.ts +28 -1
  89. package/dist/shared/operationQueue.js +268 -66
  90. package/dist/shared/operationsTable.d.ts +26 -0
  91. package/dist/shared/operationsTable.js +286 -0
  92. package/dist/shared/operationsTableSchema.d.ts +48 -0
  93. package/dist/shared/operationsTableSchema.js +35 -0
  94. package/dist/shared/relationshipExtractor.d.ts +56 -0
  95. package/dist/shared/relationshipExtractor.js +138 -0
  96. package/dist/shared/schemaGenerator.d.ts +19 -1
  97. package/dist/shared/schemaGenerator.js +56 -75
  98. package/dist/storage/backupCompression.d.ts +20 -0
  99. package/dist/storage/backupCompression.js +67 -0
  100. package/dist/storage/methods.d.ts +16 -2
  101. package/dist/storage/methods.js +98 -14
  102. package/dist/users/methods.js +9 -8
  103. package/dist/utils/configDiscovery.d.ts +78 -0
  104. package/dist/utils/configDiscovery.js +430 -0
  105. package/dist/utils/directoryUtils.d.ts +22 -0
  106. package/dist/utils/directoryUtils.js +59 -0
  107. package/dist/utils/getClientFromConfig.d.ts +17 -8
  108. package/dist/utils/getClientFromConfig.js +162 -17
  109. package/dist/utils/helperFunctions.d.ts +16 -2
  110. package/dist/utils/helperFunctions.js +19 -5
  111. package/dist/utils/loadConfigs.d.ts +34 -9
  112. package/dist/utils/loadConfigs.js +236 -316
  113. package/dist/utils/pathResolvers.d.ts +53 -0
  114. package/dist/utils/pathResolvers.js +72 -0
  115. package/dist/utils/projectConfig.d.ts +119 -0
  116. package/dist/utils/projectConfig.js +171 -0
  117. package/dist/utils/retryFailedPromises.js +4 -2
  118. package/dist/utils/sessionAuth.d.ts +48 -0
  119. package/dist/utils/sessionAuth.js +164 -0
  120. package/dist/utils/sessionPreservationExample.d.ts +1666 -0
  121. package/dist/utils/sessionPreservationExample.js +101 -0
  122. package/dist/utils/setupFiles.js +301 -41
  123. package/dist/utils/typeGuards.d.ts +35 -0
  124. package/dist/utils/typeGuards.js +57 -0
  125. package/dist/utils/versionDetection.js +145 -9
  126. package/dist/utils/yamlConverter.d.ts +53 -3
  127. package/dist/utils/yamlConverter.js +232 -13
  128. package/dist/utils/yamlLoader.d.ts +70 -0
  129. package/dist/utils/yamlLoader.js +263 -0
  130. package/dist/utilsController.d.ts +36 -3
  131. package/dist/utilsController.js +186 -56
  132. package/package.json +12 -2
  133. package/src/adapters/AdapterFactory.ts +263 -35
  134. package/src/adapters/TablesDBAdapter.ts +225 -36
  135. package/src/backups/operations/bucketBackup.ts +277 -0
  136. package/src/backups/operations/collectionBackup.ts +310 -0
  137. package/src/backups/operations/comprehensiveBackup.ts +342 -0
  138. package/src/backups/schemas/bucketManifest.ts +78 -0
  139. package/src/backups/schemas/comprehensiveManifest.ts +76 -0
  140. package/src/backups/tracking/centralizedTracking.ts +352 -0
  141. package/src/cli/commands/configCommands.ts +194 -0
  142. package/src/cli/commands/databaseCommands.ts +635 -0
  143. package/src/cli/commands/functionCommands.ts +379 -0
  144. package/src/cli/commands/schemaCommands.ts +163 -0
  145. package/src/cli/commands/transferCommands.ts +457 -0
  146. package/src/collections/attributes.ts +900 -621
  147. package/src/collections/attributes.ts.backup +1555 -0
  148. package/src/collections/indexes.ts +116 -114
  149. package/src/collections/methods.ts +295 -968
  150. package/src/collections/transferOperations.ts +516 -0
  151. package/src/collections/wipeOperations.ts +501 -0
  152. package/src/config/README.md +274 -0
  153. package/src/config/configMigration.ts +575 -0
  154. package/src/config/configValidation.ts +445 -0
  155. package/src/config/yamlConfig.ts +168 -55
  156. package/src/databases/methods.ts +3 -2
  157. package/src/databases/setup.ts +11 -138
  158. package/src/examples/yamlTerminologyExample.ts +341 -0
  159. package/src/functions/deployments.ts +14 -12
  160. package/src/functions/methods.ts +11 -11
  161. package/src/functions/templates/hono-typescript/README.md +286 -0
  162. package/src/functions/templates/hono-typescript/package.json +26 -0
  163. package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
  164. package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
  165. package/src/functions/templates/hono-typescript/src/app.ts +180 -0
  166. package/src/functions/templates/hono-typescript/src/context.ts +103 -0
  167. package/src/functions/templates/hono-typescript/src/index.ts +54 -0
  168. package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
  169. package/src/functions/templates/hono-typescript/tsconfig.json +20 -0
  170. package/src/functions/templates/typescript-node/package.json +2 -1
  171. package/src/functions/templates/typescript-node/src/context.ts +103 -0
  172. package/src/functions/templates/typescript-node/src/index.ts +18 -12
  173. package/src/functions/templates/uv/pyproject.toml +1 -0
  174. package/src/functions/templates/uv/src/context.py +125 -0
  175. package/src/functions/templates/uv/src/index.py +35 -5
  176. package/src/init.ts +9 -11
  177. package/src/interactiveCLI.ts +278 -1596
  178. package/src/main.ts +418 -24
  179. package/src/migrations/afterImportActions.ts +71 -44
  180. package/src/migrations/appwriteToX.ts +100 -34
  181. package/src/migrations/dataLoader.ts +48 -34
  182. package/src/migrations/importController.ts +44 -39
  183. package/src/migrations/relationships.ts +28 -18
  184. package/src/migrations/services/ImportOrchestrator.ts +24 -27
  185. package/src/migrations/transfer.ts +159 -121
  186. package/src/migrations/yaml/YamlImportConfigLoader.ts +11 -4
  187. package/src/migrations/yaml/YamlImportIntegration.ts +47 -20
  188. package/src/migrations/yaml/generateImportSchemas.ts +751 -12
  189. package/src/setupController.ts +3 -2
  190. package/src/shared/backupMetadataSchema.ts +93 -0
  191. package/src/shared/backupTracking.ts +211 -0
  192. package/src/shared/confirmationDialogs.ts +19 -19
  193. package/src/shared/errorUtils.ts +110 -0
  194. package/src/shared/functionManager.ts +21 -20
  195. package/src/shared/indexManager.ts +12 -11
  196. package/src/shared/jsonSchemaGenerator.ts +38 -52
  197. package/src/shared/logging.ts +75 -0
  198. package/src/shared/messageFormatter.ts +14 -1
  199. package/src/shared/migrationHelpers.ts +45 -38
  200. package/src/shared/operationLogger.ts +11 -36
  201. package/src/shared/operationQueue.ts +322 -93
  202. package/src/shared/operationsTable.ts +338 -0
  203. package/src/shared/operationsTableSchema.ts +60 -0
  204. package/src/shared/relationshipExtractor.ts +214 -0
  205. package/src/shared/schemaGenerator.ts +179 -219
  206. package/src/storage/backupCompression.ts +88 -0
  207. package/src/storage/methods.ts +131 -34
  208. package/src/users/methods.ts +11 -9
  209. package/src/utils/configDiscovery.ts +502 -0
  210. package/src/utils/directoryUtils.ts +61 -0
  211. package/src/utils/getClientFromConfig.ts +205 -22
  212. package/src/utils/helperFunctions.ts +23 -5
  213. package/src/utils/loadConfigs.ts +313 -345
  214. package/src/utils/pathResolvers.ts +81 -0
  215. package/src/utils/projectConfig.ts +299 -0
  216. package/src/utils/retryFailedPromises.ts +4 -2
  217. package/src/utils/sessionAuth.ts +230 -0
  218. package/src/utils/setupFiles.ts +322 -54
  219. package/src/utils/typeGuards.ts +65 -0
  220. package/src/utils/versionDetection.ts +218 -64
  221. package/src/utils/yamlConverter.ts +296 -13
  222. package/src/utils/yamlLoader.ts +364 -0
  223. package/src/utilsController.ts +314 -110
  224. package/tests/README.md +497 -0
  225. package/tests/adapters/AdapterFactory.test.ts +277 -0
  226. package/tests/integration/syncOperations.test.ts +463 -0
  227. package/tests/jest.config.js +25 -0
  228. package/tests/migration/configMigration.test.ts +546 -0
  229. package/tests/setup.ts +62 -0
  230. package/tests/testUtils.ts +340 -0
  231. package/tests/utils/loadConfigs.test.ts +350 -0
  232. package/tests/validation/configValidation.test.ts +412 -0
  233. package/src/utils/schemaStrings.ts +0 -517
@@ -3,6 +3,7 @@ import { Databases, IndexType, Query, type Models } from "node-appwrite";
3
3
  import { delay, tryAwaitWithRetry } from "../utils/helperFunctions.js";
4
4
  import chalk from "chalk";
5
5
  import pLimit from "p-limit";
6
+ import { MessageFormatter } from "./messageFormatter.js";
6
7
 
7
8
  // Concurrency limits for different operations
8
9
  const indexLimit = pLimit(3); // Low limit for index operations
@@ -48,7 +49,7 @@ export const createOrUpdateIndex = async (
48
49
 
49
50
  if (forceRecreate || !indexesSame(existingIndex, index)) {
50
51
  if (verbose) {
51
- console.log(chalk.yellow(`⚠ Updating index ${index.key} in collection ${collectionId}`));
52
+ MessageFormatter.warning(`Updating index ${index.key} in collection ${collectionId}`, { prefix: "Index Manager" });
52
53
  }
53
54
 
54
55
  // Delete existing index
@@ -60,14 +61,14 @@ export const createOrUpdateIndex = async (
60
61
  shouldCreate = true;
61
62
  } else {
62
63
  if (verbose) {
63
- console.log(chalk.green(`✓ Index ${index.key} is up to date`));
64
+ MessageFormatter.success(`Index ${index.key} is up to date`, { prefix: "Index Manager" });
64
65
  }
65
66
  return existingIndex;
66
67
  }
67
68
  } else {
68
69
  shouldCreate = true;
69
70
  if (verbose) {
70
- console.log(chalk.blue(`+ Creating index ${index.key} in collection ${collectionId}`));
71
+ MessageFormatter.info(`Creating index ${index.key} in collection ${collectionId}`, { prefix: "Index Manager" });
71
72
  }
72
73
  }
73
74
 
@@ -84,7 +85,7 @@ export const createOrUpdateIndex = async (
84
85
  });
85
86
 
86
87
  if (verbose) {
87
- console.log(chalk.green(`✓ Created index ${index.key}`));
88
+ MessageFormatter.success(`Created index ${index.key}`, { prefix: "Index Manager" });
88
89
  }
89
90
 
90
91
  return newIndex;
@@ -111,7 +112,7 @@ export const createOrUpdateIndexes = async (
111
112
  }
112
113
 
113
114
  if (verbose) {
114
- console.log(chalk.blue(`Processing ${indexes.length} indexes for collection ${collectionId}`));
115
+ MessageFormatter.info(`Processing ${indexes.length} indexes for collection ${collectionId}`, { prefix: "Index Manager" });
115
116
  }
116
117
 
117
118
  // Process indexes sequentially to avoid conflicts
@@ -122,13 +123,13 @@ export const createOrUpdateIndexes = async (
122
123
  // Add delay between index operations to prevent rate limiting
123
124
  await delay(250);
124
125
  } catch (error) {
125
- console.error(chalk.red(`❌ Failed to process index ${index.key}:`), error);
126
+ MessageFormatter.error(`Failed to process index ${index.key}`, error as Error, { prefix: "Index Manager" });
126
127
  throw error;
127
128
  }
128
129
  }
129
130
 
130
131
  if (verbose) {
131
- console.log(chalk.green(`✓ Completed processing indexes for collection ${collectionId}`));
132
+ MessageFormatter.success(`Completed processing indexes for collection ${collectionId}`, { prefix: "Index Manager" });
132
133
  }
133
134
  };
134
135
 
@@ -184,7 +185,7 @@ export const deleteObsoleteIndexes = async (
184
185
  }
185
186
 
186
187
  if (verbose) {
187
- console.log(chalk.yellow(`🗑️ Removing ${obsoleteIndexes.length} obsolete indexes from collection ${collection.name}`));
188
+ MessageFormatter.warning(`Removing ${obsoleteIndexes.length} obsolete indexes from collection ${collection.name}`, { prefix: "Index Manager" });
188
189
  }
189
190
 
190
191
  // Process deletions with rate limiting
@@ -196,7 +197,7 @@ export const deleteObsoleteIndexes = async (
196
197
  });
197
198
 
198
199
  if (verbose) {
199
- console.log(chalk.gray(`🗑️ Deleted obsolete index ${index.key}`));
200
+ MessageFormatter.info(`Deleted obsolete index ${index.key}`, { prefix: "Index Manager" });
200
201
  }
201
202
 
202
203
  await delay(250);
@@ -245,8 +246,8 @@ export const validateIndexConfiguration = (
245
246
  }
246
247
 
247
248
  if (verbose && errors.length > 0) {
248
- console.log(chalk.red(`❌ Index validation errors:`));
249
- errors.forEach(error => console.log(chalk.red(` - ${error}`)));
249
+ MessageFormatter.error("Index validation errors", undefined, { prefix: "Index Manager" });
250
+ errors.forEach(error => MessageFormatter.error(` - ${error}`, undefined, { prefix: "Index Manager" }));
250
251
  }
251
252
 
252
253
  return { valid: errors.length === 0, errors };
@@ -3,6 +3,12 @@ import path from "path";
3
3
  import type { AppwriteConfig, Attribute, CollectionCreate } from "appwrite-utils";
4
4
  import { toCamelCase, toPascalCase } from "../utils/index.js";
5
5
  import chalk from "chalk";
6
+ import {
7
+ extractSimpleRelationships,
8
+ resolveCollectionName,
9
+ type SimpleRelationship
10
+ } from "./relationshipExtractor.js";
11
+ import { MessageFormatter } from "./messageFormatter.js";
6
12
 
7
13
  export interface JsonSchemaProperty {
8
14
  type: string | string[];
@@ -33,43 +39,23 @@ export interface JsonSchema {
33
39
  definitions?: Record<string, JsonSchemaProperty>;
34
40
  }
35
41
 
36
- export class JsonSchemaGenerator {
37
- private config: AppwriteConfig;
38
- private appwriteFolderPath: string;
39
- private relationshipMap = new Map<string, any[]>();
40
-
41
- constructor(config: AppwriteConfig, appwriteFolderPath: string) {
42
- this.config = config;
43
- this.appwriteFolderPath = appwriteFolderPath;
44
- this.extractRelationships();
45
- }
46
-
47
- private resolveCollectionName = (idOrName: string): string => {
48
- const col = this.config.collections?.find(
49
- (c) => c.$id === (idOrName as any) || c.name === idOrName
50
- );
51
- return col?.name ?? idOrName;
52
- };
42
+ export class JsonSchemaGenerator {
43
+ private config: AppwriteConfig;
44
+ private appwriteFolderPath: string;
45
+ private relationshipMap = new Map<string, SimpleRelationship[]>();
53
46
 
54
- private extractRelationships(): void {
55
- if (!this.config.collections) return;
47
+ constructor(config: AppwriteConfig, appwriteFolderPath: string) {
48
+ this.config = config;
49
+ this.appwriteFolderPath = appwriteFolderPath;
50
+ this.extractRelationships();
51
+ }
56
52
 
57
- this.config.collections.forEach((collection) => {
58
- if (!collection.attributes) return;
59
-
60
- collection.attributes.forEach((attr) => {
61
- if (attr.type === "relationship" && attr.relatedCollection) {
62
- const relationships = this.relationshipMap.get(collection.name) || [];
63
- relationships.push({
64
- attributeKey: attr.key,
65
- relatedCollection: this.resolveCollectionName(attr.relatedCollection),
66
- relationType: attr.relationType,
67
- isArray: attr.relationType === "oneToMany" || attr.relationType === "manyToMany"
68
- });
69
- this.relationshipMap.set(collection.name, relationships);
70
- }
71
- });
72
- });
53
+ private resolveCollectionName = (idOrName: string): string => {
54
+ return resolveCollectionName(this.config, idOrName);
55
+ };
56
+
57
+ private extractRelationships(): void {
58
+ this.relationshipMap = extractSimpleRelationships(this.config);
73
59
  }
74
60
 
75
61
  private attributeToJsonSchemaProperty(attribute: Attribute): JsonSchemaProperty {
@@ -160,14 +146,14 @@ export class JsonSchemaGenerator {
160
146
  }
161
147
  break;
162
148
 
163
- case "relationship":
164
- if (attribute.relatedCollection) {
165
- // For relationships, reference the related collection schema
166
- schema.$ref = `#/definitions/${toPascalCase(this.resolveCollectionName(attribute.relatedCollection))}`;
167
- } else {
168
- schema.type = "string";
169
- }
170
- break;
149
+ case "relationship":
150
+ if (attribute.relatedCollection) {
151
+ // For relationships, reference the related collection schema
152
+ schema.$ref = `#/definitions/${toPascalCase(this.resolveCollectionName(attribute.relatedCollection))}`;
153
+ } else {
154
+ schema.type = "string";
155
+ }
156
+ break;
171
157
 
172
158
  default:
173
159
  schema.type = "string";
@@ -254,7 +240,7 @@ export class JsonSchemaGenerator {
254
240
 
255
241
  if (!this.config.collections) {
256
242
  if (verbose) {
257
- console.log(chalk.yellow("No collections found in config"));
243
+ MessageFormatter.warning("No collections found in config", { prefix: "Schema" });
258
244
  }
259
245
  return;
260
246
  }
@@ -266,7 +252,7 @@ export class JsonSchemaGenerator {
266
252
  }
267
253
 
268
254
  if (verbose) {
269
- console.log(chalk.blue(`Generating JSON schemas for ${this.config.collections.length} collections...`));
255
+ MessageFormatter.processing(`Generating JSON schemas for ${this.config.collections.length} collections...`, { prefix: "Schema" });
270
256
  }
271
257
 
272
258
  this.config.collections.forEach((collection) => {
@@ -277,9 +263,9 @@ export class JsonSchemaGenerator {
277
263
  if (outputFormat === "json" || outputFormat === "both") {
278
264
  const jsonPath = path.join(jsonSchemasPath, `${camelCaseName}.json`);
279
265
  fs.writeFileSync(jsonPath, JSON.stringify(schema, null, 2), { encoding: "utf-8" });
280
-
266
+
281
267
  if (verbose) {
282
- console.log(chalk.green(`✓ JSON schema written to ${jsonPath}`));
268
+ MessageFormatter.success(`JSON schema written to ${jsonPath}`, { prefix: "Schema" });
283
269
  }
284
270
  }
285
271
 
@@ -288,9 +274,9 @@ export class JsonSchemaGenerator {
288
274
  const tsContent = this.generateTypeScriptSchema(schema, collection.name);
289
275
  const tsPath = path.join(jsonSchemasPath, `${camelCaseName}.schema.ts`);
290
276
  fs.writeFileSync(tsPath, tsContent, { encoding: "utf-8" });
291
-
277
+
292
278
  if (verbose) {
293
- console.log(chalk.green(`✓ TypeScript schema written to ${tsPath}`));
279
+ MessageFormatter.success(`TypeScript schema written to ${tsPath}`, { prefix: "Schema" });
294
280
  }
295
281
  }
296
282
  });
@@ -301,7 +287,7 @@ export class JsonSchemaGenerator {
301
287
  }
302
288
 
303
289
  if (verbose) {
304
- console.log(chalk.green("JSON schema generation completed"));
290
+ MessageFormatter.success("JSON schema generation completed", { prefix: "Schema" });
305
291
  }
306
292
  }
307
293
 
@@ -358,7 +344,7 @@ export default jsonSchemas;
358
344
  fs.writeFileSync(indexPath, indexContent, { encoding: "utf-8" });
359
345
 
360
346
  if (verbose) {
361
- console.log(chalk.green(`✓ Index file written to ${indexPath}`));
347
+ MessageFormatter.success(`Index file written to ${indexPath}`, { prefix: "Schema" });
362
348
  }
363
349
  }
364
350
 
@@ -392,4 +378,4 @@ export default jsonSchemas;
392
378
 
393
379
  return { valid: errors.length === 0, errors };
394
380
  }
395
- }
381
+ }
@@ -9,6 +9,36 @@ export interface LoggingConfig {
9
9
  console: boolean;
10
10
  }
11
11
 
12
+ /**
13
+ * Predefined logging configurations for common debugging scenarios
14
+ */
15
+ export const LOGGING_PRESETS = {
16
+ /** Minimal logging - errors only to console */
17
+ minimal: {
18
+ enabled: false,
19
+ level: 'error',
20
+ console: true
21
+ },
22
+ /** Standard logging - info level to file and console */
23
+ standard: {
24
+ enabled: true,
25
+ level: 'info',
26
+ console: true
27
+ },
28
+ /** Debug logging - verbose debug output for troubleshooting */
29
+ debug: {
30
+ enabled: true,
31
+ level: 'debug',
32
+ console: true
33
+ },
34
+ /** Silent - no logging output */
35
+ silent: {
36
+ enabled: false,
37
+ level: 'error',
38
+ console: false
39
+ }
40
+ } as const;
41
+
12
42
  const DEFAULT_LOGGING_CONFIG: LoggingConfig = {
13
43
  enabled: false,
14
44
  level: "info",
@@ -21,6 +51,18 @@ export const configureLogging = (config: Partial<LoggingConfig> = {}) => {
21
51
  loggingConfig = { ...DEFAULT_LOGGING_CONFIG, ...config };
22
52
  };
23
53
 
54
+ /**
55
+ * Configure logging using a preset
56
+ */
57
+ export const configureLoggingPreset = (preset: keyof typeof LOGGING_PRESETS, logDirectory?: string) => {
58
+ const presetConfig = LOGGING_PRESETS[preset];
59
+ configureLogging({
60
+ ...presetConfig,
61
+ ...(logDirectory && { logDirectory })
62
+ });
63
+ updateLogger();
64
+ };
65
+
24
66
  const createLogger = () => {
25
67
  const transports: winston.transport[] = [];
26
68
 
@@ -72,3 +114,36 @@ export let logger = createLogger();
72
114
  export const updateLogger = () => {
73
115
  logger = createLogger();
74
116
  };
117
+
118
+ /**
119
+ * Enable debug logging for troubleshooting push process issues
120
+ * This is a convenience function for quickly enabling comprehensive logging
121
+ */
122
+ export const enableDebugLogging = (logDirectory?: string) => {
123
+ configureLogging({
124
+ enabled: true,
125
+ level: 'debug',
126
+ console: true,
127
+ logDirectory
128
+ });
129
+ updateLogger();
130
+ logger.info('Debug logging enabled for push process troubleshooting', {
131
+ level: 'debug',
132
+ console: true,
133
+ logDirectory: logDirectory || 'zlogs',
134
+ operation: 'enableDebugLogging'
135
+ });
136
+ };
137
+
138
+ /**
139
+ * Disable logging (reset to default)
140
+ */
141
+ export const disableLogging = () => {
142
+ configureLogging(DEFAULT_LOGGING_CONFIG);
143
+ updateLogger();
144
+ };
145
+
146
+ /**
147
+ * Get current logging configuration
148
+ */
149
+ export const getLoggingConfig = () => ({ ...loggingConfig });
@@ -74,12 +74,25 @@ export class MessageFormatter {
74
74
  console.log(chalk.gray(JSON.stringify(data, null, 2)));
75
75
  }
76
76
  }
77
-
77
+
78
78
  if (!options.skipLogging) {
79
79
  logger.debug(`DEBUG: ${options.prefix ? `${options.prefix}: ` : ""}${message}`, data);
80
80
  }
81
81
  }
82
82
 
83
+ static processing(message: string, options: MessageOptions = {}) {
84
+ const formatted = `${chalk.cyan("⚙️")} ${options.prefix ? `${options.prefix}: ` : ""}${message}`;
85
+ console.log(formatted);
86
+
87
+ if (!options.skipLogging) {
88
+ logger.info(`PROCESSING: ${options.prefix ? `${options.prefix}: ` : ""}${message}`);
89
+ }
90
+ }
91
+
92
+ static divider() {
93
+ console.log(chalk.gray("─".repeat(60)));
94
+ }
95
+
83
96
  static banner(title: string, subtitle?: string) {
84
97
  const divider = chalk.cyan("═".repeat(60));
85
98
  console.log(`\n${divider}`);
@@ -4,6 +4,13 @@ import { AttributeMappingsSchema } from "appwrite-utils";
4
4
  import { z } from "zod";
5
5
  import { logger } from "./logging.js";
6
6
  import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
7
+ import {
8
+ findOrCreateOperation as findOrCreateOp,
9
+ updateOperation as updateOp,
10
+ getOperation as getOp
11
+ } from "./operationsTable.js";
12
+ import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
13
+ import { MessageFormatter } from "./messageFormatter.js";
7
14
 
8
15
  /**
9
16
  * Object that contains the context for an action that needs to be executed after import
@@ -29,15 +36,9 @@ export type ContextObject = z.infer<typeof ContextObject>;
29
36
  export const createOrFindAfterImportOperation = async (
30
37
  database: Databases,
31
38
  collectionId: string,
32
- context: ContextObject,
33
- useMigrations: boolean = true
39
+ context: ContextObject
34
40
  ) => {
35
- if (!useMigrations) {
36
- logger.info("Migrations disabled, skipping after import operation tracking");
37
- return;
38
- }
39
-
40
- let operation = await findOrCreateOperation(
41
+ let operation = await findOrCreateOperationLegacy(
41
42
  database,
42
43
  collectionId,
43
44
  "afterImportAction"
@@ -75,14 +76,8 @@ export const addBatch = async (database: Databases, data: string) => {
75
76
 
76
77
  export const getAfterImportOperations = async (
77
78
  database: Databases,
78
- collectionId: string,
79
- useMigrations: boolean = true
79
+ collectionId: string
80
80
  ) => {
81
- if (!useMigrations) {
82
- logger.info("Migrations disabled, returning empty operations list");
83
- return [];
84
- }
85
-
86
81
  let lastDocumentId: string | undefined;
87
82
  const allOperations = [];
88
83
  let total = 0;
@@ -116,7 +111,8 @@ export const getAfterImportOperations = async (
116
111
  return allOps;
117
112
  };
118
113
 
119
- export const findOrCreateOperation = async (
114
+ // Legacy function for backward compatibility with old migrations database
115
+ const findOrCreateOperationLegacy = async (
120
116
  database: Databases,
121
117
  collectionId: string,
122
118
  operationType: string,
@@ -133,9 +129,8 @@ export const findOrCreateOperation = async (
133
129
  );
134
130
 
135
131
  if (operations.documents.length > 0) {
136
- return OperationSchema.parse(operations.documents[0]); // Assuming the first document is the operation we want
132
+ return OperationSchema.parse(operations.documents[0]);
137
133
  } else {
138
- // Create a new operation document
139
134
  const op = await tryAwaitWithRetry(
140
135
  async () =>
141
136
  await database.createDocument(
@@ -158,26 +153,37 @@ export const findOrCreateOperation = async (
158
153
  }
159
154
  };
160
155
 
156
+ export const findOrCreateOperation = async (
157
+ db: DatabaseAdapter,
158
+ databaseId: string,
159
+ operationType: string,
160
+ collectionId?: string,
161
+ data?: any
162
+ ): Promise<any> => {
163
+ // Use new operations table system
164
+ return await findOrCreateOp(db, databaseId, operationType, {
165
+ targetCollection: collectionId,
166
+ data: data
167
+ });
168
+ };
169
+
161
170
  export const updateOperation = async (
162
- database: Databases,
171
+ db: DatabaseAdapter,
172
+ databaseId: string,
163
173
  operationId: string,
164
- updateFields: any,
165
- useMigrations: boolean = true
166
- ) => {
167
- if (!useMigrations) {
168
- logger.info("Migrations disabled, skipping operation update");
169
- return;
170
- }
174
+ updates: any
175
+ ): Promise<any> => {
176
+ // Use new operations table system
177
+ return await updateOp(db, databaseId, operationId, updates);
178
+ };
171
179
 
172
- await tryAwaitWithRetry(
173
- async () =>
174
- await database.updateDocument(
175
- "migrations",
176
- "currentOperations",
177
- operationId,
178
- updateFields
179
- )
180
- );
180
+ export const getOperation = async (
181
+ db: DatabaseAdapter,
182
+ databaseId: string,
183
+ operationId: string
184
+ ): Promise<any> => {
185
+ // Use new operations table system
186
+ return await getOp(db, databaseId, operationId);
181
187
  };
182
188
 
183
189
  // Actual max 1073741824
@@ -193,10 +199,11 @@ export const splitIntoBatches = (data: any[]): any[][] => {
193
199
  data.forEach((item, index) => {
194
200
  const itemLength = JSON.stringify(item).length;
195
201
  if (itemLength > maxDataLength) {
196
- console.log(
197
- item,
198
- `Large item found at index ${index} with length ${itemLength}:`
202
+ MessageFormatter.warning(
203
+ `Large item found at index ${index} with length ${itemLength}`,
204
+ { prefix: "Batch Splitter" }
199
205
  );
206
+ logger.debug("Large item data:", item);
200
207
  }
201
208
  // Check if adding the current item would exceed the max length or max items per batch
202
209
  if (
@@ -1,45 +1,20 @@
1
1
  import type { Databases, Models } from "node-appwrite";
2
2
  import type { OperationCreate } from "../storage/schemas.js";
3
- import { tryAwaitWithRetry } from "appwrite-utils";
4
- import { ulid } from "ulidx";
5
3
 
4
+ /**
5
+ * Legacy operation logger - deprecated
6
+ * This function is maintained for backward compatibility but no longer performs any logging.
7
+ * The operations table system has been refactored to use the dynamic adapter pattern.
8
+ *
9
+ * @deprecated This function will be removed in a future version
10
+ */
6
11
  export const logOperation = async (
7
12
  db: Databases,
8
13
  dbId: string,
9
14
  operationDetails: OperationCreate,
10
- operationId?: string,
11
- useMigrations: boolean = true
15
+ operationId?: string
12
16
  ): Promise<Models.Document | null> => {
13
- if (!useMigrations) {
14
- console.log("Migrations disabled, skipping operation logging");
15
- return null;
16
- }
17
- try {
18
- let operation;
19
- if (operationId) {
20
- // Update existing operation log
21
- operation = await tryAwaitWithRetry(
22
- async () =>
23
- await db.updateDocument(
24
- "migrations",
25
- "currentOperations",
26
- operationId,
27
- operationDetails
28
- )
29
- );
30
- } else {
31
- // Create new operation log
32
- operation = await db.createDocument(
33
- "migrations",
34
- "currentOperations",
35
- ulid(),
36
- operationDetails
37
- );
38
- }
39
- console.log(`Operation logged: ${operation.$id}`);
40
- return operation;
41
- } catch (error) {
42
- console.error(`Error logging operation: ${error}`);
43
- throw error;
44
- }
17
+ // No-op: Operations logging has been moved to the new operations table system
18
+ // Callers should migrate to using operationsTable.ts functions directly
19
+ return null;
45
20
  };