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.
- package/CHANGELOG.md +199 -0
- package/README.md +251 -29
- package/dist/adapters/AdapterFactory.d.ts +10 -3
- package/dist/adapters/AdapterFactory.js +213 -17
- package/dist/adapters/TablesDBAdapter.js +60 -17
- package/dist/backups/operations/bucketBackup.d.ts +19 -0
- package/dist/backups/operations/bucketBackup.js +197 -0
- package/dist/backups/operations/collectionBackup.d.ts +30 -0
- package/dist/backups/operations/collectionBackup.js +201 -0
- package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
- package/dist/backups/operations/comprehensiveBackup.js +238 -0
- package/dist/backups/schemas/bucketManifest.d.ts +93 -0
- package/dist/backups/schemas/bucketManifest.js +33 -0
- package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
- package/dist/backups/schemas/comprehensiveManifest.js +32 -0
- package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
- package/dist/backups/tracking/centralizedTracking.js +274 -0
- package/dist/cli/commands/configCommands.d.ts +8 -0
- package/dist/cli/commands/configCommands.js +160 -0
- package/dist/cli/commands/databaseCommands.d.ts +13 -0
- package/dist/cli/commands/databaseCommands.js +478 -0
- package/dist/cli/commands/functionCommands.d.ts +7 -0
- package/dist/cli/commands/functionCommands.js +289 -0
- package/dist/cli/commands/schemaCommands.d.ts +7 -0
- package/dist/cli/commands/schemaCommands.js +134 -0
- package/dist/cli/commands/transferCommands.d.ts +5 -0
- package/dist/cli/commands/transferCommands.js +384 -0
- package/dist/collections/attributes.d.ts +5 -4
- package/dist/collections/attributes.js +539 -246
- package/dist/collections/indexes.js +39 -37
- package/dist/collections/methods.d.ts +2 -16
- package/dist/collections/methods.js +90 -538
- package/dist/collections/transferOperations.d.ts +7 -0
- package/dist/collections/transferOperations.js +331 -0
- package/dist/collections/wipeOperations.d.ts +16 -0
- package/dist/collections/wipeOperations.js +328 -0
- package/dist/config/configMigration.d.ts +87 -0
- package/dist/config/configMigration.js +390 -0
- package/dist/config/configValidation.d.ts +66 -0
- package/dist/config/configValidation.js +358 -0
- package/dist/config/yamlConfig.d.ts +455 -1
- package/dist/config/yamlConfig.js +145 -52
- package/dist/databases/methods.js +3 -2
- package/dist/databases/setup.d.ts +1 -2
- package/dist/databases/setup.js +9 -87
- package/dist/examples/yamlTerminologyExample.d.ts +42 -0
- package/dist/examples/yamlTerminologyExample.js +269 -0
- package/dist/functions/deployments.js +11 -10
- package/dist/functions/methods.d.ts +1 -1
- package/dist/functions/methods.js +5 -4
- package/dist/init.js +9 -9
- package/dist/interactiveCLI.d.ts +8 -17
- package/dist/interactiveCLI.js +186 -1171
- package/dist/main.js +364 -21
- package/dist/migrations/afterImportActions.js +22 -30
- package/dist/migrations/appwriteToX.js +71 -25
- package/dist/migrations/dataLoader.js +35 -26
- package/dist/migrations/importController.js +29 -30
- package/dist/migrations/relationships.js +13 -12
- package/dist/migrations/services/ImportOrchestrator.js +16 -19
- package/dist/migrations/transfer.js +46 -46
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +3 -1
- package/dist/migrations/yaml/YamlImportConfigLoader.js +6 -3
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +9 -3
- package/dist/migrations/yaml/YamlImportIntegration.js +22 -11
- package/dist/migrations/yaml/generateImportSchemas.d.ts +14 -1
- package/dist/migrations/yaml/generateImportSchemas.js +736 -7
- package/dist/schemas/authUser.d.ts +1 -1
- package/dist/setupController.js +3 -2
- package/dist/shared/backupMetadataSchema.d.ts +94 -0
- package/dist/shared/backupMetadataSchema.js +38 -0
- package/dist/shared/backupTracking.d.ts +18 -0
- package/dist/shared/backupTracking.js +176 -0
- package/dist/shared/confirmationDialogs.js +15 -15
- package/dist/shared/errorUtils.d.ts +54 -0
- package/dist/shared/errorUtils.js +95 -0
- package/dist/shared/functionManager.js +20 -19
- package/dist/shared/indexManager.js +12 -11
- package/dist/shared/jsonSchemaGenerator.js +10 -26
- package/dist/shared/logging.d.ts +51 -0
- package/dist/shared/logging.js +70 -0
- package/dist/shared/messageFormatter.d.ts +2 -0
- package/dist/shared/messageFormatter.js +10 -0
- package/dist/shared/migrationHelpers.d.ts +6 -16
- package/dist/shared/migrationHelpers.js +24 -21
- package/dist/shared/operationLogger.d.ts +8 -1
- package/dist/shared/operationLogger.js +11 -24
- package/dist/shared/operationQueue.d.ts +28 -1
- package/dist/shared/operationQueue.js +268 -66
- package/dist/shared/operationsTable.d.ts +26 -0
- package/dist/shared/operationsTable.js +286 -0
- package/dist/shared/operationsTableSchema.d.ts +48 -0
- package/dist/shared/operationsTableSchema.js +35 -0
- package/dist/shared/relationshipExtractor.d.ts +56 -0
- package/dist/shared/relationshipExtractor.js +138 -0
- package/dist/shared/schemaGenerator.d.ts +19 -1
- package/dist/shared/schemaGenerator.js +56 -75
- package/dist/storage/backupCompression.d.ts +20 -0
- package/dist/storage/backupCompression.js +67 -0
- package/dist/storage/methods.d.ts +16 -2
- package/dist/storage/methods.js +98 -14
- package/dist/users/methods.js +9 -8
- package/dist/utils/configDiscovery.d.ts +78 -0
- package/dist/utils/configDiscovery.js +430 -0
- package/dist/utils/directoryUtils.d.ts +22 -0
- package/dist/utils/directoryUtils.js +59 -0
- package/dist/utils/getClientFromConfig.d.ts +17 -8
- package/dist/utils/getClientFromConfig.js +162 -17
- package/dist/utils/helperFunctions.d.ts +16 -2
- package/dist/utils/helperFunctions.js +19 -5
- package/dist/utils/loadConfigs.d.ts +34 -9
- package/dist/utils/loadConfigs.js +236 -316
- package/dist/utils/pathResolvers.d.ts +53 -0
- package/dist/utils/pathResolvers.js +72 -0
- package/dist/utils/projectConfig.d.ts +119 -0
- package/dist/utils/projectConfig.js +171 -0
- package/dist/utils/retryFailedPromises.js +4 -2
- package/dist/utils/sessionAuth.d.ts +48 -0
- package/dist/utils/sessionAuth.js +164 -0
- package/dist/utils/sessionPreservationExample.d.ts +1666 -0
- package/dist/utils/sessionPreservationExample.js +101 -0
- package/dist/utils/setupFiles.js +301 -41
- package/dist/utils/typeGuards.d.ts +35 -0
- package/dist/utils/typeGuards.js +57 -0
- package/dist/utils/versionDetection.js +145 -9
- package/dist/utils/yamlConverter.d.ts +53 -3
- package/dist/utils/yamlConverter.js +232 -13
- package/dist/utils/yamlLoader.d.ts +70 -0
- package/dist/utils/yamlLoader.js +263 -0
- package/dist/utilsController.d.ts +36 -3
- package/dist/utilsController.js +186 -56
- package/package.json +12 -2
- package/src/adapters/AdapterFactory.ts +263 -35
- package/src/adapters/TablesDBAdapter.ts +225 -36
- package/src/backups/operations/bucketBackup.ts +277 -0
- package/src/backups/operations/collectionBackup.ts +310 -0
- package/src/backups/operations/comprehensiveBackup.ts +342 -0
- package/src/backups/schemas/bucketManifest.ts +78 -0
- package/src/backups/schemas/comprehensiveManifest.ts +76 -0
- package/src/backups/tracking/centralizedTracking.ts +352 -0
- package/src/cli/commands/configCommands.ts +194 -0
- package/src/cli/commands/databaseCommands.ts +635 -0
- package/src/cli/commands/functionCommands.ts +379 -0
- package/src/cli/commands/schemaCommands.ts +163 -0
- package/src/cli/commands/transferCommands.ts +457 -0
- package/src/collections/attributes.ts +900 -621
- package/src/collections/attributes.ts.backup +1555 -0
- package/src/collections/indexes.ts +116 -114
- package/src/collections/methods.ts +295 -968
- package/src/collections/transferOperations.ts +516 -0
- package/src/collections/wipeOperations.ts +501 -0
- package/src/config/README.md +274 -0
- package/src/config/configMigration.ts +575 -0
- package/src/config/configValidation.ts +445 -0
- package/src/config/yamlConfig.ts +168 -55
- package/src/databases/methods.ts +3 -2
- package/src/databases/setup.ts +11 -138
- package/src/examples/yamlTerminologyExample.ts +341 -0
- package/src/functions/deployments.ts +14 -12
- package/src/functions/methods.ts +11 -11
- package/src/functions/templates/hono-typescript/README.md +286 -0
- package/src/functions/templates/hono-typescript/package.json +26 -0
- package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
- package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
- package/src/functions/templates/hono-typescript/src/app.ts +180 -0
- package/src/functions/templates/hono-typescript/src/context.ts +103 -0
- package/src/functions/templates/hono-typescript/src/index.ts +54 -0
- package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
- package/src/functions/templates/hono-typescript/tsconfig.json +20 -0
- package/src/functions/templates/typescript-node/package.json +2 -1
- package/src/functions/templates/typescript-node/src/context.ts +103 -0
- package/src/functions/templates/typescript-node/src/index.ts +18 -12
- package/src/functions/templates/uv/pyproject.toml +1 -0
- package/src/functions/templates/uv/src/context.py +125 -0
- package/src/functions/templates/uv/src/index.py +35 -5
- package/src/init.ts +9 -11
- package/src/interactiveCLI.ts +276 -1591
- package/src/main.ts +418 -24
- package/src/migrations/afterImportActions.ts +71 -44
- package/src/migrations/appwriteToX.ts +100 -34
- package/src/migrations/dataLoader.ts +48 -34
- package/src/migrations/importController.ts +44 -39
- package/src/migrations/relationships.ts +28 -18
- package/src/migrations/services/ImportOrchestrator.ts +24 -27
- package/src/migrations/transfer.ts +159 -121
- package/src/migrations/yaml/YamlImportConfigLoader.ts +11 -4
- package/src/migrations/yaml/YamlImportIntegration.ts +47 -20
- package/src/migrations/yaml/generateImportSchemas.ts +751 -12
- package/src/setupController.ts +3 -2
- package/src/shared/backupMetadataSchema.ts +93 -0
- package/src/shared/backupTracking.ts +211 -0
- package/src/shared/confirmationDialogs.ts +19 -19
- package/src/shared/errorUtils.ts +110 -0
- package/src/shared/functionManager.ts +21 -20
- package/src/shared/indexManager.ts +12 -11
- package/src/shared/jsonSchemaGenerator.ts +38 -52
- package/src/shared/logging.ts +75 -0
- package/src/shared/messageFormatter.ts +14 -1
- package/src/shared/migrationHelpers.ts +45 -38
- package/src/shared/operationLogger.ts +11 -36
- package/src/shared/operationQueue.ts +322 -93
- package/src/shared/operationsTable.ts +338 -0
- package/src/shared/operationsTableSchema.ts +60 -0
- package/src/shared/relationshipExtractor.ts +214 -0
- package/src/shared/schemaGenerator.ts +179 -219
- package/src/storage/backupCompression.ts +88 -0
- package/src/storage/methods.ts +131 -34
- package/src/users/methods.ts +11 -9
- package/src/utils/configDiscovery.ts +502 -0
- package/src/utils/directoryUtils.ts +61 -0
- package/src/utils/getClientFromConfig.ts +205 -22
- package/src/utils/helperFunctions.ts +23 -5
- package/src/utils/loadConfigs.ts +313 -345
- package/src/utils/pathResolvers.ts +81 -0
- package/src/utils/projectConfig.ts +299 -0
- package/src/utils/retryFailedPromises.ts +4 -2
- package/src/utils/sessionAuth.ts +230 -0
- package/src/utils/setupFiles.ts +322 -54
- package/src/utils/typeGuards.ts +65 -0
- package/src/utils/versionDetection.ts +218 -64
- package/src/utils/yamlConverter.ts +296 -13
- package/src/utils/yamlLoader.ts +364 -0
- package/src/utilsController.ts +314 -110
- package/tests/README.md +497 -0
- package/tests/adapters/AdapterFactory.test.ts +277 -0
- package/tests/integration/syncOperations.test.ts +463 -0
- package/tests/jest.config.js +25 -0
- package/tests/migration/configMigration.test.ts +546 -0
- package/tests/setup.ts +62 -0
- package/tests/testUtils.ts +340 -0
- package/tests/utils/loadConfigs.test.ts +350 -0
- package/tests/validation/configValidation.test.ts +412 -0
- 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>;
|