appwrite-utils-cli 1.5.1 → 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 +186 -1171
  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 +276 -1591
  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
@@ -0,0 +1,238 @@
1
+ import { ID } from "node-appwrite";
2
+ import { InputFile } from "node-appwrite/file";
3
+ import { ulid } from "ulidx";
4
+ import { MessageFormatter } from "../../shared/messageFormatter.js";
5
+ import { logger } from "../../shared/logging.js";
6
+ import { backupDatabase } from "../../storage/methods.js";
7
+ import { backupBucket } from "./bucketBackup.js";
8
+ import { recordCentralizedBackup, createCentralizedBackupTrackingTable } from "../tracking/centralizedTracking.js";
9
+ import { fetchAllDatabases } from "../../databases/methods.js";
10
+ /**
11
+ * Orchestrates comprehensive backup of ALL databases and ALL storage buckets
12
+ */
13
+ export async function comprehensiveBackup(config, databases, storage, adapter, options) {
14
+ const startTime = Date.now();
15
+ const backupId = ulid();
16
+ const errors = [];
17
+ const databaseBackups = [];
18
+ const bucketBackups = [];
19
+ let totalSizeBytes = 0;
20
+ try {
21
+ // Ensure tracking table exists
22
+ await createCentralizedBackupTrackingTable(adapter, options.trackingDatabaseId);
23
+ // Initialize backup bucket
24
+ const backupBucketId = "appwrite-backups";
25
+ MessageFormatter.info(`Starting comprehensive backup ${backupId}`, { prefix: "Backup" });
26
+ // Phase 1: Backup ALL databases
27
+ if (!options.skipDatabases) {
28
+ MessageFormatter.info("Phase 1: Backing up ALL databases", { prefix: "Backup" });
29
+ const allDatabases = await fetchAllDatabases(databases);
30
+ // Validate each database exists before attempting backup
31
+ const validDatabases = [];
32
+ const skippedDatabases = [];
33
+ MessageFormatter.info(`Validating ${allDatabases.length} databases...`, { prefix: "Backup" });
34
+ for (const db of allDatabases) {
35
+ try {
36
+ await databases.get(db.$id); // Validate existence
37
+ validDatabases.push(db);
38
+ }
39
+ catch (error) {
40
+ skippedDatabases.push(`${db.name} (${db.$id})`);
41
+ MessageFormatter.warning(`Database ${db.name} not found - skipping`, { prefix: "Backup" });
42
+ logger.warn('Database validation failed', {
43
+ databaseId: db.$id,
44
+ databaseName: db.name,
45
+ error: error instanceof Error ? error.message : String(error)
46
+ });
47
+ }
48
+ }
49
+ if (skippedDatabases.length > 0) {
50
+ MessageFormatter.info(`Skipped ${skippedDatabases.length} invalid databases: ${skippedDatabases.join(', ')}`, { prefix: "Backup" });
51
+ }
52
+ MessageFormatter.info(`Found ${validDatabases.length} valid databases to backup`, { prefix: "Backup" });
53
+ for (const db of validDatabases) {
54
+ try {
55
+ if (options.onProgress) {
56
+ options.onProgress(`Backing up database: ${db.name}`);
57
+ }
58
+ MessageFormatter.info(`Backing up database: ${db.name} (${db.$id})`, { prefix: "Backup" });
59
+ // Use existing backupDatabase function
60
+ const dbBackupResult = await backupDatabase(config, databases, db.$id, storage, options.backupFormat || 'zip');
61
+ // Create database manifest with complete data
62
+ const manifestData = {
63
+ version: "1.0",
64
+ databaseId: dbBackupResult.databaseId,
65
+ databaseName: dbBackupResult.databaseName,
66
+ format: dbBackupResult.format,
67
+ collectionCount: dbBackupResult.collectionCount,
68
+ documentCount: dbBackupResult.documentCount,
69
+ backupFileId: dbBackupResult.backupFileId,
70
+ createdAt: new Date().toISOString()
71
+ };
72
+ const manifestBuffer = Buffer.from(JSON.stringify(manifestData, null, 2), 'utf-8');
73
+ const manifestFile = await storage.createFile(backupBucketId, ID.unique(), InputFile.fromBuffer(new Uint8Array(manifestBuffer), `${db.$id}-manifest.json`));
74
+ databaseBackups.push({
75
+ databaseId: dbBackupResult.databaseId,
76
+ databaseName: dbBackupResult.databaseName,
77
+ backupFileId: dbBackupResult.backupFileId,
78
+ manifestFileId: manifestFile.$id,
79
+ collectionCount: dbBackupResult.collectionCount,
80
+ documentCount: dbBackupResult.documentCount,
81
+ sizeBytes: dbBackupResult.backupSizeBytes,
82
+ status: 'completed'
83
+ });
84
+ totalSizeBytes += dbBackupResult.backupSizeBytes;
85
+ // Record individual database backup in tracking
86
+ await recordCentralizedBackup(adapter, options.trackingDatabaseId, {
87
+ backupType: 'database',
88
+ backupId: dbBackupResult.backupFileId,
89
+ manifestFileId: manifestFile.$id,
90
+ format: dbBackupResult.format,
91
+ sizeBytes: dbBackupResult.backupSizeBytes,
92
+ databaseId: dbBackupResult.databaseId,
93
+ collections: dbBackupResult.collectionCount,
94
+ documents: dbBackupResult.documentCount,
95
+ status: 'completed',
96
+ restorationStatus: 'not_restored'
97
+ });
98
+ MessageFormatter.success(`Database ${db.name} backed up successfully`, { prefix: "Backup" });
99
+ }
100
+ catch (error) {
101
+ const errorMsg = `Failed to backup database ${db.name}: ${error instanceof Error ? error.message : String(error)}`;
102
+ errors.push(errorMsg);
103
+ logger.error(errorMsg);
104
+ databaseBackups.push({
105
+ databaseId: db.$id,
106
+ databaseName: db.name,
107
+ backupFileId: '',
108
+ manifestFileId: '',
109
+ collectionCount: 0,
110
+ documentCount: 0,
111
+ sizeBytes: 0,
112
+ status: 'failed',
113
+ error: errorMsg
114
+ });
115
+ }
116
+ }
117
+ }
118
+ // Phase 2: Backup ALL storage buckets
119
+ if (!options.skipBuckets) {
120
+ MessageFormatter.info("Phase 2: Backing up ALL storage buckets", { prefix: "Backup" });
121
+ const allBuckets = await storage.listBuckets();
122
+ const bucketsToBackup = allBuckets.buckets.filter(b => b.$id !== backupBucketId);
123
+ MessageFormatter.info(`Found ${bucketsToBackup.length} buckets to backup`, { prefix: "Backup" });
124
+ for (const bucket of bucketsToBackup) {
125
+ try {
126
+ if (options.onProgress) {
127
+ options.onProgress(`Backing up bucket: ${bucket.name}`);
128
+ }
129
+ MessageFormatter.info(`Backing up bucket: ${bucket.name} (${bucket.$id})`, { prefix: "Backup" });
130
+ const bucketBackupResult = await backupBucket(storage, bucket.$id, backupBucketId, {
131
+ parallelDownloads: options.parallelDownloads || 10,
132
+ onProgress: (current, total, fileName) => {
133
+ if (options.onProgress) {
134
+ options.onProgress(`Downloading ${fileName} (${current}/${total})`);
135
+ }
136
+ }
137
+ });
138
+ bucketBackups.push({
139
+ bucketId: bucket.$id,
140
+ bucketName: bucket.name,
141
+ backupFileId: bucketBackupResult.backupFileId,
142
+ manifestFileId: bucketBackupResult.manifestFileId,
143
+ fileCount: bucketBackupResult.fileCount,
144
+ sizeBytes: bucketBackupResult.totalSizeBytes,
145
+ status: bucketBackupResult.status,
146
+ error: bucketBackupResult.errors?.join('; ')
147
+ });
148
+ totalSizeBytes += bucketBackupResult.zipSizeBytes;
149
+ // Record individual bucket backup in tracking
150
+ await recordCentralizedBackup(adapter, options.trackingDatabaseId, {
151
+ backupType: 'bucket',
152
+ backupId: bucketBackupResult.backupFileId,
153
+ manifestFileId: bucketBackupResult.manifestFileId,
154
+ format: 'zip',
155
+ sizeBytes: bucketBackupResult.zipSizeBytes,
156
+ bucketId: bucket.$id,
157
+ fileCount: bucketBackupResult.fileCount,
158
+ status: bucketBackupResult.status,
159
+ error: bucketBackupResult.errors?.join('; '),
160
+ restorationStatus: 'not_restored'
161
+ });
162
+ MessageFormatter.success(`Bucket ${bucket.name} backed up successfully`, { prefix: "Backup" });
163
+ }
164
+ catch (error) {
165
+ const errorMsg = `Failed to backup bucket ${bucket.name}: ${error instanceof Error ? error.message : String(error)}`;
166
+ errors.push(errorMsg);
167
+ logger.error(errorMsg);
168
+ bucketBackups.push({
169
+ bucketId: bucket.$id,
170
+ bucketName: bucket.name,
171
+ backupFileId: '',
172
+ manifestFileId: '',
173
+ fileCount: 0,
174
+ sizeBytes: 0,
175
+ status: 'failed',
176
+ error: errorMsg
177
+ });
178
+ }
179
+ }
180
+ }
181
+ // Phase 3: Create comprehensive manifest
182
+ MessageFormatter.info("Creating comprehensive backup manifest", { prefix: "Backup" });
183
+ const comprehensiveStatus = errors.length === 0 ? 'completed' :
184
+ (databaseBackups.length > 0 || bucketBackups.length > 0) ? 'partial' :
185
+ 'failed';
186
+ const manifest = {
187
+ version: "1.0",
188
+ backupId,
189
+ createdAt: new Date().toISOString(),
190
+ databases: databaseBackups,
191
+ buckets: bucketBackups,
192
+ totalSizeBytes,
193
+ status: comprehensiveStatus,
194
+ errors: errors.length > 0 ? errors : undefined
195
+ };
196
+ // Upload comprehensive manifest
197
+ const manifestFileName = `comprehensive-${backupId}.json`;
198
+ const manifestBuffer = Buffer.from(JSON.stringify(manifest, null, 2), 'utf-8');
199
+ const manifestFile = await storage.createFile(backupBucketId, ID.unique(), InputFile.fromBuffer(new Uint8Array(manifestBuffer), manifestFileName));
200
+ // Record comprehensive backup in tracking
201
+ await recordCentralizedBackup(adapter, options.trackingDatabaseId, {
202
+ backupType: 'comprehensive',
203
+ backupId,
204
+ manifestFileId: manifestFile.$id,
205
+ format: 'zip',
206
+ sizeBytes: totalSizeBytes,
207
+ comprehensiveBackupId: backupId,
208
+ status: comprehensiveStatus,
209
+ error: errors.length > 0 ? errors.join('; ') : undefined,
210
+ restorationStatus: 'not_restored'
211
+ });
212
+ const duration = Date.now() - startTime;
213
+ MessageFormatter.success(`Comprehensive backup ${comprehensiveStatus} in ${(duration / 1000).toFixed(2)}s`, { prefix: "Backup" });
214
+ MessageFormatter.info(`Backed up ${databaseBackups.length} databases and ${bucketBackups.length} buckets (${MessageFormatter.formatBytes(totalSizeBytes)})`, { prefix: "Backup" });
215
+ return {
216
+ backupId,
217
+ manifestFileId: manifestFile.$id,
218
+ databaseBackups,
219
+ bucketBackups,
220
+ totalSizeBytes,
221
+ status: comprehensiveStatus,
222
+ errors
223
+ };
224
+ }
225
+ catch (error) {
226
+ const errorMsg = `Comprehensive backup failed: ${error instanceof Error ? error.message : String(error)}`;
227
+ MessageFormatter.error(errorMsg, error instanceof Error ? error : new Error(errorMsg), { prefix: "Backup" });
228
+ return {
229
+ backupId,
230
+ manifestFileId: '',
231
+ databaseBackups,
232
+ bucketBackups,
233
+ totalSizeBytes,
234
+ status: 'failed',
235
+ errors: [errorMsg, ...errors]
236
+ };
237
+ }
238
+ }
@@ -0,0 +1,93 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Schema for bucket backup manifest
4
+ *
5
+ * This manifest is stored alongside bucket backup ZIPs to describe
6
+ * the bucket configuration and files that were backed up.
7
+ */
8
+ export interface BucketFileMetadata {
9
+ $id: string;
10
+ name: string;
11
+ size: number;
12
+ mimeType: string;
13
+ $permissions: string[];
14
+ chunksCount: number;
15
+ signature: string;
16
+ $createdAt: string;
17
+ $updatedAt: string;
18
+ }
19
+ export interface BucketConfiguration {
20
+ $permissions: string[];
21
+ fileSecurity: boolean;
22
+ enabled: boolean;
23
+ maximumFileSize: number;
24
+ allowedFileExtensions: string[];
25
+ compression: string;
26
+ encryption: boolean;
27
+ antivirus: boolean;
28
+ }
29
+ export interface BucketManifest {
30
+ version: string;
31
+ bucketId: string;
32
+ bucketName: string;
33
+ createdAt: string;
34
+ fileCount: number;
35
+ totalSizeBytes: number;
36
+ compression: 'gzip' | 'none';
37
+ files: BucketFileMetadata[];
38
+ bucketConfiguration: BucketConfiguration;
39
+ }
40
+ export declare const BucketFileMetadataSchema: z.ZodObject<{
41
+ $id: z.ZodString;
42
+ name: z.ZodString;
43
+ size: z.ZodNumber;
44
+ mimeType: z.ZodString;
45
+ $permissions: z.ZodArray<z.ZodString>;
46
+ chunksCount: z.ZodNumber;
47
+ signature: z.ZodString;
48
+ $createdAt: z.ZodString;
49
+ $updatedAt: z.ZodString;
50
+ }, z.core.$strip>;
51
+ export declare const BucketConfigurationSchema: z.ZodObject<{
52
+ $permissions: z.ZodArray<z.ZodString>;
53
+ fileSecurity: z.ZodBoolean;
54
+ enabled: z.ZodBoolean;
55
+ maximumFileSize: z.ZodNumber;
56
+ allowedFileExtensions: z.ZodArray<z.ZodString>;
57
+ compression: z.ZodString;
58
+ encryption: z.ZodBoolean;
59
+ antivirus: z.ZodBoolean;
60
+ }, z.core.$strip>;
61
+ export declare const BucketManifestSchema: z.ZodObject<{
62
+ version: z.ZodDefault<z.ZodString>;
63
+ bucketId: z.ZodString;
64
+ bucketName: z.ZodString;
65
+ createdAt: z.ZodString;
66
+ fileCount: z.ZodNumber;
67
+ totalSizeBytes: z.ZodNumber;
68
+ compression: z.ZodEnum<{
69
+ none: "none";
70
+ gzip: "gzip";
71
+ }>;
72
+ files: z.ZodArray<z.ZodObject<{
73
+ $id: z.ZodString;
74
+ name: z.ZodString;
75
+ size: z.ZodNumber;
76
+ mimeType: z.ZodString;
77
+ $permissions: z.ZodArray<z.ZodString>;
78
+ chunksCount: z.ZodNumber;
79
+ signature: z.ZodString;
80
+ $createdAt: z.ZodString;
81
+ $updatedAt: z.ZodString;
82
+ }, z.core.$strip>>;
83
+ bucketConfiguration: z.ZodObject<{
84
+ $permissions: z.ZodArray<z.ZodString>;
85
+ fileSecurity: z.ZodBoolean;
86
+ enabled: z.ZodBoolean;
87
+ maximumFileSize: z.ZodNumber;
88
+ allowedFileExtensions: z.ZodArray<z.ZodString>;
89
+ compression: z.ZodString;
90
+ encryption: z.ZodBoolean;
91
+ antivirus: z.ZodBoolean;
92
+ }, z.core.$strip>;
93
+ }, z.core.$strip>;
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ export const BucketFileMetadataSchema = z.object({
3
+ $id: z.string(),
4
+ name: z.string(),
5
+ size: z.number(),
6
+ mimeType: z.string(),
7
+ $permissions: z.array(z.string()),
8
+ chunksCount: z.number(),
9
+ signature: z.string(),
10
+ $createdAt: z.string(),
11
+ $updatedAt: z.string()
12
+ });
13
+ export const BucketConfigurationSchema = z.object({
14
+ $permissions: z.array(z.string()),
15
+ fileSecurity: z.boolean(),
16
+ enabled: z.boolean(),
17
+ maximumFileSize: z.number(),
18
+ allowedFileExtensions: z.array(z.string()),
19
+ compression: z.string(),
20
+ encryption: z.boolean(),
21
+ antivirus: z.boolean()
22
+ });
23
+ export const BucketManifestSchema = z.object({
24
+ version: z.string().default("1.0"),
25
+ bucketId: z.string(),
26
+ bucketName: z.string(),
27
+ createdAt: z.string(),
28
+ fileCount: z.number(),
29
+ totalSizeBytes: z.number(),
30
+ compression: z.enum(['gzip', 'none']),
31
+ files: z.array(BucketFileMetadataSchema),
32
+ bucketConfiguration: BucketConfigurationSchema
33
+ });
@@ -0,0 +1,108 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Schema for comprehensive backup manifest
4
+ *
5
+ * This manifest tracks all databases and buckets included in a comprehensive backup,
6
+ * allowing for complete system restoration.
7
+ */
8
+ export interface DatabaseBackupReference {
9
+ databaseId: string;
10
+ databaseName: string;
11
+ backupFileId: string;
12
+ manifestFileId: string;
13
+ collectionCount: number;
14
+ documentCount: number;
15
+ sizeBytes: number;
16
+ status: 'completed' | 'partial' | 'failed';
17
+ error?: string;
18
+ }
19
+ export interface BucketBackupReference {
20
+ bucketId: string;
21
+ bucketName: string;
22
+ backupFileId: string;
23
+ manifestFileId: string;
24
+ fileCount: number;
25
+ sizeBytes: number;
26
+ status: 'completed' | 'partial' | 'failed';
27
+ error?: string;
28
+ }
29
+ export interface ComprehensiveManifest {
30
+ version: string;
31
+ backupId: string;
32
+ createdAt: string;
33
+ databases: DatabaseBackupReference[];
34
+ buckets: BucketBackupReference[];
35
+ totalSizeBytes: number;
36
+ status: 'completed' | 'partial' | 'failed';
37
+ errors?: string[];
38
+ }
39
+ export declare const DatabaseBackupReferenceSchema: z.ZodObject<{
40
+ databaseId: z.ZodString;
41
+ databaseName: z.ZodString;
42
+ backupFileId: z.ZodString;
43
+ manifestFileId: z.ZodString;
44
+ collectionCount: z.ZodNumber;
45
+ documentCount: z.ZodNumber;
46
+ sizeBytes: z.ZodNumber;
47
+ status: z.ZodEnum<{
48
+ completed: "completed";
49
+ failed: "failed";
50
+ partial: "partial";
51
+ }>;
52
+ error: z.ZodOptional<z.ZodString>;
53
+ }, z.core.$strip>;
54
+ export declare const BucketBackupReferenceSchema: z.ZodObject<{
55
+ bucketId: z.ZodString;
56
+ bucketName: z.ZodString;
57
+ backupFileId: z.ZodString;
58
+ manifestFileId: z.ZodString;
59
+ fileCount: z.ZodNumber;
60
+ sizeBytes: z.ZodNumber;
61
+ status: z.ZodEnum<{
62
+ completed: "completed";
63
+ failed: "failed";
64
+ partial: "partial";
65
+ }>;
66
+ error: z.ZodOptional<z.ZodString>;
67
+ }, z.core.$strip>;
68
+ export declare const ComprehensiveManifestSchema: z.ZodObject<{
69
+ version: z.ZodDefault<z.ZodString>;
70
+ backupId: z.ZodString;
71
+ createdAt: z.ZodString;
72
+ databases: z.ZodArray<z.ZodObject<{
73
+ databaseId: z.ZodString;
74
+ databaseName: z.ZodString;
75
+ backupFileId: z.ZodString;
76
+ manifestFileId: z.ZodString;
77
+ collectionCount: z.ZodNumber;
78
+ documentCount: z.ZodNumber;
79
+ sizeBytes: z.ZodNumber;
80
+ status: z.ZodEnum<{
81
+ completed: "completed";
82
+ failed: "failed";
83
+ partial: "partial";
84
+ }>;
85
+ error: z.ZodOptional<z.ZodString>;
86
+ }, z.core.$strip>>;
87
+ buckets: z.ZodArray<z.ZodObject<{
88
+ bucketId: z.ZodString;
89
+ bucketName: z.ZodString;
90
+ backupFileId: z.ZodString;
91
+ manifestFileId: z.ZodString;
92
+ fileCount: z.ZodNumber;
93
+ sizeBytes: z.ZodNumber;
94
+ status: z.ZodEnum<{
95
+ completed: "completed";
96
+ failed: "failed";
97
+ partial: "partial";
98
+ }>;
99
+ error: z.ZodOptional<z.ZodString>;
100
+ }, z.core.$strip>>;
101
+ totalSizeBytes: z.ZodNumber;
102
+ status: z.ZodEnum<{
103
+ completed: "completed";
104
+ failed: "failed";
105
+ partial: "partial";
106
+ }>;
107
+ errors: z.ZodOptional<z.ZodArray<z.ZodString>>;
108
+ }, z.core.$strip>;
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+ export const DatabaseBackupReferenceSchema = z.object({
3
+ databaseId: z.string(),
4
+ databaseName: z.string(),
5
+ backupFileId: z.string(),
6
+ manifestFileId: z.string(),
7
+ collectionCount: z.number(),
8
+ documentCount: z.number(),
9
+ sizeBytes: z.number(),
10
+ status: z.enum(['completed', 'partial', 'failed']),
11
+ error: z.string().optional()
12
+ });
13
+ export const BucketBackupReferenceSchema = z.object({
14
+ bucketId: z.string(),
15
+ bucketName: z.string(),
16
+ backupFileId: z.string(),
17
+ manifestFileId: z.string(),
18
+ fileCount: z.number(),
19
+ sizeBytes: z.number(),
20
+ status: z.enum(['completed', 'partial', 'failed']),
21
+ error: z.string().optional()
22
+ });
23
+ export const ComprehensiveManifestSchema = z.object({
24
+ version: z.string().default("1.0"),
25
+ backupId: z.string(),
26
+ createdAt: z.string(),
27
+ databases: z.array(DatabaseBackupReferenceSchema),
28
+ buckets: z.array(BucketBackupReferenceSchema),
29
+ totalSizeBytes: z.number(),
30
+ status: z.enum(['completed', 'partial', 'failed']),
31
+ errors: z.array(z.string()).optional()
32
+ });
@@ -0,0 +1,34 @@
1
+ import type { DatabaseAdapter } from "../../adapters/DatabaseAdapter.js";
2
+ import { type BackupMetadata, type BackupType } from "../../shared/backupMetadataSchema.js";
3
+ /**
4
+ * Creates the centralized backup tracking table with enhanced schema
5
+ */
6
+ export declare function createCentralizedBackupTrackingTable(db: DatabaseAdapter, databaseId: string): Promise<void>;
7
+ /**
8
+ * Records backup metadata in the centralized tracking table
9
+ */
10
+ export declare function recordCentralizedBackup(db: DatabaseAdapter, trackingDatabaseId: string, metadata: Omit<BackupMetadata, '$id' | '$createdAt' | '$updatedAt'>): Promise<BackupMetadata>;
11
+ /**
12
+ * Lists all backups of a specific type, sorted by creation date (newest first)
13
+ */
14
+ export declare function listCentralizedBackups(db: DatabaseAdapter, trackingDatabaseId: string, options?: {
15
+ backupType?: BackupType;
16
+ resourceId?: string;
17
+ limit?: number;
18
+ }): Promise<BackupMetadata[]>;
19
+ /**
20
+ * Gets a specific backup by its backup file ID
21
+ */
22
+ export declare function getCentralizedBackup(db: DatabaseAdapter, trackingDatabaseId: string, backupId: string): Promise<BackupMetadata | null>;
23
+ /**
24
+ * Updates restoration status for a backup
25
+ */
26
+ export declare function updateRestorationStatus(db: DatabaseAdapter, trackingDatabaseId: string, backupRecordId: string, restorationData: {
27
+ restoredAt: string;
28
+ restorationStatus: 'completed' | 'partial' | 'failed';
29
+ restorationError?: string;
30
+ }): Promise<void>;
31
+ /**
32
+ * Gets the most recent comprehensive backup
33
+ */
34
+ export declare function getLastComprehensiveBackup(db: DatabaseAdapter, trackingDatabaseId: string): Promise<BackupMetadata | null>;