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.
- 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 +181 -1172
- 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 +278 -1596
- 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
@@ -11,8 +11,8 @@ export declare const AuthUserSchema: z.ZodObject<{
|
|
11
11
|
}, z.core.$strip>;
|
12
12
|
export type AuthUser = z.infer<typeof AuthUserSchema>;
|
13
13
|
export declare const AuthUserCreateSchema: z.ZodObject<{
|
14
|
-
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
15
14
|
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
15
|
+
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
16
16
|
$createdAt: z.ZodOptional<z.ZodString>;
|
17
17
|
$updatedAt: z.ZodOptional<z.ZodString>;
|
18
18
|
phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
package/dist/setupController.js
CHANGED
@@ -2,6 +2,7 @@ import { setupDirsFiles } from "./utils/setupFiles.js";
|
|
2
2
|
import { loadConfig } from "./utils/loadConfigs.js";
|
3
3
|
import path from "path";
|
4
4
|
import fs from "fs";
|
5
|
+
import { MessageFormatter } from "./shared/messageFormatter.js";
|
5
6
|
export class SetupController {
|
6
7
|
currentDir;
|
7
8
|
config = null;
|
@@ -10,7 +11,7 @@ export class SetupController {
|
|
10
11
|
}
|
11
12
|
async runSetup(withExampleData = false) {
|
12
13
|
await setupDirsFiles(withExampleData, this.currentDir);
|
13
|
-
|
14
|
+
MessageFormatter.success("Setup completed successfully", { prefix: "Setup" });
|
14
15
|
}
|
15
16
|
async loadConfig() {
|
16
17
|
if (this.hasExistingConfig()) {
|
@@ -20,7 +21,7 @@ export class SetupController {
|
|
20
21
|
return this.config;
|
21
22
|
}
|
22
23
|
catch (error) {
|
23
|
-
|
24
|
+
MessageFormatter.error("Error loading config", error, { prefix: "Setup" });
|
24
25
|
return null;
|
25
26
|
}
|
26
27
|
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
import { z } from "zod";
|
2
|
+
/**
|
3
|
+
* Schema for centralized backup tracking table (_appwrite_backups)
|
4
|
+
*
|
5
|
+
* Tracks all backups created for databases, buckets, and comprehensive backups
|
6
|
+
*/
|
7
|
+
export type BackupType = 'database' | 'bucket' | 'comprehensive';
|
8
|
+
export type BackupFormat = 'json' | 'zip';
|
9
|
+
export type BackupStatus = 'completed' | 'partial' | 'failed';
|
10
|
+
export type RestorationStatus = 'completed' | 'partial' | 'failed' | 'not_restored';
|
11
|
+
export declare const BACKUP_TYPES: readonly ["database", "bucket", "comprehensive"];
|
12
|
+
export declare const BACKUP_FORMATS: readonly ["json", "zip"];
|
13
|
+
export declare const BACKUP_STATUSES: readonly ["completed", "partial", "failed"];
|
14
|
+
export declare const RESTORATION_STATUSES: readonly ["completed", "partial", "failed", "not_restored"];
|
15
|
+
export declare const BackupTypeSchema: z.ZodEnum<{
|
16
|
+
bucket: "bucket";
|
17
|
+
database: "database";
|
18
|
+
comprehensive: "comprehensive";
|
19
|
+
}>;
|
20
|
+
export declare const BackupFormatSchema: z.ZodEnum<{
|
21
|
+
json: "json";
|
22
|
+
zip: "zip";
|
23
|
+
}>;
|
24
|
+
export declare const BackupStatusSchema: z.ZodEnum<{
|
25
|
+
completed: "completed";
|
26
|
+
failed: "failed";
|
27
|
+
partial: "partial";
|
28
|
+
}>;
|
29
|
+
export declare const RestorationStatusSchema: z.ZodEnum<{
|
30
|
+
completed: "completed";
|
31
|
+
failed: "failed";
|
32
|
+
partial: "partial";
|
33
|
+
not_restored: "not_restored";
|
34
|
+
}>;
|
35
|
+
export interface BackupMetadata {
|
36
|
+
$id: string;
|
37
|
+
$createdAt: string;
|
38
|
+
$updatedAt: string;
|
39
|
+
backupType: BackupType;
|
40
|
+
backupId: string;
|
41
|
+
manifestFileId?: string;
|
42
|
+
format: BackupFormat;
|
43
|
+
sizeBytes: number;
|
44
|
+
databaseId?: string;
|
45
|
+
bucketId?: string;
|
46
|
+
comprehensiveBackupId?: string;
|
47
|
+
collections?: number;
|
48
|
+
documents?: number;
|
49
|
+
fileCount?: number;
|
50
|
+
status: BackupStatus;
|
51
|
+
error?: string;
|
52
|
+
restoredAt?: string;
|
53
|
+
restorationStatus: RestorationStatus;
|
54
|
+
restorationError?: string;
|
55
|
+
}
|
56
|
+
export declare const BackupMetadataSchema: z.ZodObject<{
|
57
|
+
$id: z.ZodString;
|
58
|
+
$createdAt: z.ZodString;
|
59
|
+
$updatedAt: z.ZodString;
|
60
|
+
backupType: z.ZodEnum<{
|
61
|
+
bucket: "bucket";
|
62
|
+
database: "database";
|
63
|
+
comprehensive: "comprehensive";
|
64
|
+
}>;
|
65
|
+
backupId: z.ZodString;
|
66
|
+
manifestFileId: z.ZodOptional<z.ZodString>;
|
67
|
+
format: z.ZodEnum<{
|
68
|
+
json: "json";
|
69
|
+
zip: "zip";
|
70
|
+
}>;
|
71
|
+
sizeBytes: z.ZodNumber;
|
72
|
+
databaseId: z.ZodOptional<z.ZodString>;
|
73
|
+
bucketId: z.ZodOptional<z.ZodString>;
|
74
|
+
comprehensiveBackupId: z.ZodOptional<z.ZodString>;
|
75
|
+
collections: z.ZodOptional<z.ZodNumber>;
|
76
|
+
documents: z.ZodOptional<z.ZodNumber>;
|
77
|
+
fileCount: z.ZodOptional<z.ZodNumber>;
|
78
|
+
status: z.ZodEnum<{
|
79
|
+
completed: "completed";
|
80
|
+
failed: "failed";
|
81
|
+
partial: "partial";
|
82
|
+
}>;
|
83
|
+
error: z.ZodOptional<z.ZodString>;
|
84
|
+
restoredAt: z.ZodOptional<z.ZodString>;
|
85
|
+
restorationStatus: z.ZodDefault<z.ZodEnum<{
|
86
|
+
completed: "completed";
|
87
|
+
failed: "failed";
|
88
|
+
partial: "partial";
|
89
|
+
not_restored: "not_restored";
|
90
|
+
}>>;
|
91
|
+
restorationError: z.ZodOptional<z.ZodString>;
|
92
|
+
}, z.core.$strip>;
|
93
|
+
export declare const BACKUP_TABLE_ID = "appwrite_backups";
|
94
|
+
export declare const BACKUP_TABLE_NAME = "Backup Tracking";
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { z } from "zod";
|
2
|
+
export const BACKUP_TYPES = ['database', 'bucket', 'comprehensive'];
|
3
|
+
export const BACKUP_FORMATS = ['json', 'zip'];
|
4
|
+
export const BACKUP_STATUSES = ['completed', 'partial', 'failed'];
|
5
|
+
export const RESTORATION_STATUSES = ['completed', 'partial', 'failed', 'not_restored'];
|
6
|
+
export const BackupTypeSchema = z.enum(['database', 'bucket', 'comprehensive']);
|
7
|
+
export const BackupFormatSchema = z.enum(['json', 'zip']);
|
8
|
+
export const BackupStatusSchema = z.enum(['completed', 'partial', 'failed']);
|
9
|
+
export const RestorationStatusSchema = z.enum(['completed', 'partial', 'failed', 'not_restored']);
|
10
|
+
export const BackupMetadataSchema = z.object({
|
11
|
+
$id: z.string(),
|
12
|
+
$createdAt: z.string(),
|
13
|
+
$updatedAt: z.string(),
|
14
|
+
// Core backup info
|
15
|
+
backupType: BackupTypeSchema,
|
16
|
+
backupId: z.string(),
|
17
|
+
manifestFileId: z.string().optional(),
|
18
|
+
format: BackupFormatSchema,
|
19
|
+
sizeBytes: z.number(),
|
20
|
+
// Resource identification
|
21
|
+
databaseId: z.string().optional(),
|
22
|
+
bucketId: z.string().optional(),
|
23
|
+
comprehensiveBackupId: z.string().optional(),
|
24
|
+
// Database-specific metrics
|
25
|
+
collections: z.number().optional(),
|
26
|
+
documents: z.number().optional(),
|
27
|
+
// Bucket-specific metrics
|
28
|
+
fileCount: z.number().optional(),
|
29
|
+
// Status tracking
|
30
|
+
status: BackupStatusSchema,
|
31
|
+
error: z.string().optional(),
|
32
|
+
// Restoration tracking
|
33
|
+
restoredAt: z.string().optional(),
|
34
|
+
restorationStatus: RestorationStatusSchema.default('not_restored'),
|
35
|
+
restorationError: z.string().optional()
|
36
|
+
});
|
37
|
+
export const BACKUP_TABLE_ID = "appwrite_backups";
|
38
|
+
export const BACKUP_TABLE_NAME = "Backup Tracking";
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
|
2
|
+
import { type BackupMetadata } from "./backupMetadataSchema.js";
|
3
|
+
/**
|
4
|
+
* Creates the backup tracking table in the specified database
|
5
|
+
*/
|
6
|
+
export declare function createBackupTrackingTable(db: DatabaseAdapter, databaseId: string): Promise<void>;
|
7
|
+
/**
|
8
|
+
* Records backup metadata in the tracking table
|
9
|
+
*/
|
10
|
+
export declare function recordBackup(db: DatabaseAdapter, databaseId: string, metadata: Omit<BackupMetadata, '$id' | '$createdAt' | '$updatedAt'>): Promise<BackupMetadata>;
|
11
|
+
/**
|
12
|
+
* Lists all backups for a database, sorted by creation date (newest first)
|
13
|
+
*/
|
14
|
+
export declare function listBackups(db: DatabaseAdapter, databaseId: string): Promise<BackupMetadata[]>;
|
15
|
+
/**
|
16
|
+
* Gets the most recent backup for a database
|
17
|
+
*/
|
18
|
+
export declare function getLastBackup(db: DatabaseAdapter, databaseId: string): Promise<BackupMetadata | null>;
|
@@ -0,0 +1,176 @@
|
|
1
|
+
import { logger } from "./logging.js";
|
2
|
+
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
3
|
+
import { Query, ID } from "node-appwrite";
|
4
|
+
import { BACKUP_TABLE_ID, BACKUP_TABLE_NAME, BackupMetadataSchema } from "./backupMetadataSchema.js";
|
5
|
+
/**
|
6
|
+
* Checks if backup tracking table exists in database
|
7
|
+
*/
|
8
|
+
async function tableExists(db, databaseId) {
|
9
|
+
try {
|
10
|
+
await db.getTable({ databaseId, tableId: BACKUP_TABLE_ID });
|
11
|
+
return true;
|
12
|
+
}
|
13
|
+
catch (error) {
|
14
|
+
return false;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
/**
|
18
|
+
* Creates the backup tracking table in the specified database
|
19
|
+
*/
|
20
|
+
export async function createBackupTrackingTable(db, databaseId) {
|
21
|
+
// Check if table already exists
|
22
|
+
const exists = await tableExists(db, databaseId);
|
23
|
+
if (exists) {
|
24
|
+
logger.debug("Backup tracking table already exists", {
|
25
|
+
databaseId,
|
26
|
+
tableId: BACKUP_TABLE_ID
|
27
|
+
});
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
logger.info("Creating backup tracking table", {
|
31
|
+
databaseId,
|
32
|
+
tableId: BACKUP_TABLE_ID
|
33
|
+
});
|
34
|
+
// Create table
|
35
|
+
await tryAwaitWithRetry(async () => {
|
36
|
+
await db.createTable({
|
37
|
+
databaseId,
|
38
|
+
id: BACKUP_TABLE_ID,
|
39
|
+
name: BACKUP_TABLE_NAME
|
40
|
+
});
|
41
|
+
});
|
42
|
+
// Create attributes
|
43
|
+
const attributes = [
|
44
|
+
{
|
45
|
+
key: "backupId",
|
46
|
+
type: "string",
|
47
|
+
size: 50,
|
48
|
+
required: true
|
49
|
+
},
|
50
|
+
{
|
51
|
+
key: "databaseId",
|
52
|
+
type: "string",
|
53
|
+
size: 50,
|
54
|
+
required: true
|
55
|
+
},
|
56
|
+
{
|
57
|
+
key: "sizeBytes",
|
58
|
+
type: "integer",
|
59
|
+
required: true
|
60
|
+
},
|
61
|
+
{
|
62
|
+
key: "collections",
|
63
|
+
type: "integer",
|
64
|
+
required: true
|
65
|
+
},
|
66
|
+
{
|
67
|
+
key: "documents",
|
68
|
+
type: "integer",
|
69
|
+
required: true
|
70
|
+
},
|
71
|
+
{
|
72
|
+
key: "format",
|
73
|
+
type: "enum",
|
74
|
+
elements: ["json", "zip"],
|
75
|
+
required: true
|
76
|
+
},
|
77
|
+
{
|
78
|
+
key: "status",
|
79
|
+
type: "enum",
|
80
|
+
elements: ["completed", "failed"],
|
81
|
+
required: true
|
82
|
+
},
|
83
|
+
{
|
84
|
+
key: "error",
|
85
|
+
type: "string",
|
86
|
+
size: 10000,
|
87
|
+
required: false
|
88
|
+
}
|
89
|
+
];
|
90
|
+
for (const attr of attributes) {
|
91
|
+
await tryAwaitWithRetry(async () => {
|
92
|
+
await db.createAttribute({
|
93
|
+
databaseId,
|
94
|
+
tableId: BACKUP_TABLE_ID,
|
95
|
+
...attr
|
96
|
+
});
|
97
|
+
});
|
98
|
+
}
|
99
|
+
logger.info("Backup tracking table created successfully", {
|
100
|
+
databaseId,
|
101
|
+
tableId: BACKUP_TABLE_ID
|
102
|
+
});
|
103
|
+
}
|
104
|
+
/**
|
105
|
+
* Records backup metadata in the tracking table
|
106
|
+
*/
|
107
|
+
export async function recordBackup(db, databaseId, metadata) {
|
108
|
+
// Ensure tracking table exists
|
109
|
+
await createBackupTrackingTable(db, databaseId);
|
110
|
+
// Create backup record
|
111
|
+
const result = await db.createRow({
|
112
|
+
databaseId,
|
113
|
+
tableId: BACKUP_TABLE_ID,
|
114
|
+
id: ID.unique(),
|
115
|
+
data: {
|
116
|
+
backupId: metadata.backupId,
|
117
|
+
databaseId: metadata.databaseId,
|
118
|
+
sizeBytes: metadata.sizeBytes,
|
119
|
+
collections: metadata.collections,
|
120
|
+
documents: metadata.documents,
|
121
|
+
format: metadata.format,
|
122
|
+
status: metadata.status,
|
123
|
+
error: metadata.error
|
124
|
+
}
|
125
|
+
});
|
126
|
+
logger.info("Recorded backup metadata", {
|
127
|
+
backupId: metadata.backupId,
|
128
|
+
databaseId: metadata.databaseId,
|
129
|
+
format: metadata.format
|
130
|
+
});
|
131
|
+
return result.data;
|
132
|
+
}
|
133
|
+
/**
|
134
|
+
* Lists all backups for a database, sorted by creation date (newest first)
|
135
|
+
*/
|
136
|
+
export async function listBackups(db, databaseId) {
|
137
|
+
try {
|
138
|
+
const result = await db.listRows({
|
139
|
+
databaseId,
|
140
|
+
tableId: BACKUP_TABLE_ID,
|
141
|
+
queries: [
|
142
|
+
Query.orderDesc("$createdAt"),
|
143
|
+
Query.limit(100) // Limit to last 100 backups
|
144
|
+
]
|
145
|
+
});
|
146
|
+
return (result.rows || []);
|
147
|
+
}
|
148
|
+
catch (error) {
|
149
|
+
// Table might not exist yet
|
150
|
+
logger.debug("No backup tracking table found", { databaseId });
|
151
|
+
return [];
|
152
|
+
}
|
153
|
+
}
|
154
|
+
/**
|
155
|
+
* Gets the most recent backup for a database
|
156
|
+
*/
|
157
|
+
export async function getLastBackup(db, databaseId) {
|
158
|
+
try {
|
159
|
+
const result = await db.listRows({
|
160
|
+
databaseId,
|
161
|
+
tableId: BACKUP_TABLE_ID,
|
162
|
+
queries: [
|
163
|
+
Query.orderDesc("$createdAt"),
|
164
|
+
Query.limit(1)
|
165
|
+
]
|
166
|
+
});
|
167
|
+
if (result.rows && result.rows.length > 0) {
|
168
|
+
return result.rows[0];
|
169
|
+
}
|
170
|
+
return null;
|
171
|
+
}
|
172
|
+
catch (error) {
|
173
|
+
logger.debug("No backup found or table doesn't exist", { databaseId });
|
174
|
+
return null;
|
175
|
+
}
|
176
|
+
}
|
@@ -9,16 +9,16 @@ export class ConfirmationDialogs {
|
|
9
9
|
if (options.skipConfirmation) {
|
10
10
|
return true;
|
11
11
|
}
|
12
|
-
MessageFormatter.warning(`You are about to perform a destructive operation
|
13
|
-
|
14
|
-
|
12
|
+
MessageFormatter.warning(`You are about to perform a destructive operation:`, { skipLogging: true });
|
13
|
+
MessageFormatter.error(`Operation: ${options.operation}`, undefined, { skipLogging: true });
|
14
|
+
MessageFormatter.warning(`Targets: ${options.targets.join(", ")}`, { skipLogging: true });
|
15
15
|
if (options.consequences && options.consequences.length > 0) {
|
16
|
-
|
16
|
+
MessageFormatter.error("This will:", undefined, { skipLogging: true });
|
17
17
|
options.consequences.forEach(consequence => {
|
18
|
-
|
18
|
+
MessageFormatter.error(` • ${consequence}`, undefined, { skipLogging: true });
|
19
19
|
});
|
20
20
|
}
|
21
|
-
|
21
|
+
MessageFormatter.error("⚠️ THIS ACTION CANNOT BE UNDONE!", undefined, { skipLogging: true });
|
22
22
|
if (options.requireExplicitConfirmation && options.confirmationText) {
|
23
23
|
const { confirmation } = await inquirer.prompt([{
|
24
24
|
type: 'input',
|
@@ -47,9 +47,9 @@ export class ConfirmationDialogs {
|
|
47
47
|
static async promptForBackup(options) {
|
48
48
|
const message = options.backupMessage ||
|
49
49
|
`Create a backup before performing ${options.operation} on: ${options.targets.join(", ")}?`;
|
50
|
-
|
50
|
+
MessageFormatter.info("🛡️ Backup Recommendation", { skipLogging: true });
|
51
51
|
if (options.recommendBackup !== false) {
|
52
|
-
|
52
|
+
MessageFormatter.warning("It's strongly recommended to create a backup before proceeding.", { skipLogging: true });
|
53
53
|
}
|
54
54
|
const { choice } = await inquirer.prompt([{
|
55
55
|
type: 'list',
|
@@ -68,11 +68,11 @@ export class ConfirmationDialogs {
|
|
68
68
|
* Shows a final confirmation before proceeding with an operation
|
69
69
|
*/
|
70
70
|
static async finalConfirmation(operation, details) {
|
71
|
-
|
71
|
+
MessageFormatter.success(`Ready to perform: ${operation}`, { skipLogging: true });
|
72
72
|
if (details && details.length > 0) {
|
73
|
-
|
73
|
+
MessageFormatter.debug("Details:", undefined, { skipLogging: true });
|
74
74
|
details.forEach(detail => {
|
75
|
-
|
75
|
+
MessageFormatter.debug(` • ${detail}`, undefined, { skipLogging: true });
|
76
76
|
});
|
77
77
|
}
|
78
78
|
const { proceed } = await inquirer.prompt([{
|
@@ -152,17 +152,17 @@ export class ConfirmationDialogs {
|
|
152
152
|
Object.entries(summary).forEach(([key, value]) => {
|
153
153
|
const formattedKey = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
|
154
154
|
if (Array.isArray(value)) {
|
155
|
-
|
155
|
+
MessageFormatter.info(`● ${formattedKey}:`, { skipLogging: true });
|
156
156
|
value.forEach(item => {
|
157
|
-
|
157
|
+
MessageFormatter.debug(` • ${item}`, undefined, { skipLogging: true });
|
158
158
|
});
|
159
159
|
}
|
160
160
|
else {
|
161
|
-
|
161
|
+
MessageFormatter.info(`● ${formattedKey}: ${String(value)}`, { skipLogging: true });
|
162
162
|
}
|
163
163
|
});
|
164
164
|
if (options.warningMessage) {
|
165
|
-
|
165
|
+
MessageFormatter.warning(`⚠️ ${options.warningMessage}`, { skipLogging: true });
|
166
166
|
}
|
167
167
|
if (options.confirmationRequired !== false) {
|
168
168
|
const { confirmed } = await inquirer.prompt([{
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/**
|
2
|
+
* Shared error handling utilities for consistent error processing
|
3
|
+
*/
|
4
|
+
/**
|
5
|
+
* Extracts error message from unknown error type
|
6
|
+
* @param error - Error of unknown type
|
7
|
+
* @returns String error message
|
8
|
+
*/
|
9
|
+
export declare function getErrorMessage(error: unknown): string;
|
10
|
+
/**
|
11
|
+
* Normalizes unknown error to Error instance
|
12
|
+
* @param error - Error of unknown type
|
13
|
+
* @returns Normalized Error object
|
14
|
+
*/
|
15
|
+
export declare function normalizeError(error: unknown): Error;
|
16
|
+
/**
|
17
|
+
* Checks if error is a conflict error (409)
|
18
|
+
* @param error - Error object to check
|
19
|
+
* @returns True if error is a conflict (duplicate resource)
|
20
|
+
*/
|
21
|
+
export declare function isConflictError(error: any): boolean;
|
22
|
+
/**
|
23
|
+
* Checks if error is a Cloudflare error (522)
|
24
|
+
* @param error - Error object to check
|
25
|
+
* @returns True if error is from Cloudflare connection timeout
|
26
|
+
*/
|
27
|
+
export declare function isCloudflareError(error: any): boolean;
|
28
|
+
/**
|
29
|
+
* Checks if error is authentication/authorization related
|
30
|
+
* @param error - Error object to check
|
31
|
+
* @returns True if error is auth-related (401, 403)
|
32
|
+
*/
|
33
|
+
export declare function isAuthError(error: any): boolean;
|
34
|
+
/**
|
35
|
+
* Error categorization helpers for smart fallback logic
|
36
|
+
*/
|
37
|
+
/**
|
38
|
+
* Checks if an error is retryable (network issues, rate limits, etc.)
|
39
|
+
* @param errorMessage - Error message to check
|
40
|
+
* @returns True if error is retryable
|
41
|
+
*/
|
42
|
+
export declare function isRetryableError(errorMessage: string): boolean;
|
43
|
+
/**
|
44
|
+
* Checks if an error indicates bulk operations are not supported
|
45
|
+
* @param errorMessage - Error message to check
|
46
|
+
* @returns True if bulk operations not supported
|
47
|
+
*/
|
48
|
+
export declare function isBulkNotSupportedError(errorMessage: string): boolean;
|
49
|
+
/**
|
50
|
+
* Checks if an error is critical (authentication, authorization, permissions)
|
51
|
+
* @param errorMessage - Error message to check
|
52
|
+
* @returns True if error is critical
|
53
|
+
*/
|
54
|
+
export declare function isCriticalError(errorMessage: string): boolean;
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/**
|
2
|
+
* Shared error handling utilities for consistent error processing
|
3
|
+
*/
|
4
|
+
/**
|
5
|
+
* Extracts error message from unknown error type
|
6
|
+
* @param error - Error of unknown type
|
7
|
+
* @returns String error message
|
8
|
+
*/
|
9
|
+
export function getErrorMessage(error) {
|
10
|
+
return error instanceof Error ? error.message : String(error);
|
11
|
+
}
|
12
|
+
/**
|
13
|
+
* Normalizes unknown error to Error instance
|
14
|
+
* @param error - Error of unknown type
|
15
|
+
* @returns Normalized Error object
|
16
|
+
*/
|
17
|
+
export function normalizeError(error) {
|
18
|
+
return error instanceof Error ? error : new Error(String(error));
|
19
|
+
}
|
20
|
+
/**
|
21
|
+
* Checks if error is a conflict error (409)
|
22
|
+
* @param error - Error object to check
|
23
|
+
* @returns True if error is a conflict (duplicate resource)
|
24
|
+
*/
|
25
|
+
export function isConflictError(error) {
|
26
|
+
return error?.code === 409 || (error?.message?.toLowerCase().includes('already exists') ?? false);
|
27
|
+
}
|
28
|
+
/**
|
29
|
+
* Checks if error is a Cloudflare error (522)
|
30
|
+
* @param error - Error object to check
|
31
|
+
* @returns True if error is from Cloudflare connection timeout
|
32
|
+
*/
|
33
|
+
export function isCloudflareError(error) {
|
34
|
+
return error?.code === 522 || error?.code === "522";
|
35
|
+
}
|
36
|
+
/**
|
37
|
+
* Checks if error is authentication/authorization related
|
38
|
+
* @param error - Error object to check
|
39
|
+
* @returns True if error is auth-related (401, 403)
|
40
|
+
*/
|
41
|
+
export function isAuthError(error) {
|
42
|
+
const code = error?.code;
|
43
|
+
return code === 401 || code === 403 || code === "401" || code === "403";
|
44
|
+
}
|
45
|
+
/**
|
46
|
+
* Error categorization helpers for smart fallback logic
|
47
|
+
*/
|
48
|
+
/**
|
49
|
+
* Checks if an error is retryable (network issues, rate limits, etc.)
|
50
|
+
* @param errorMessage - Error message to check
|
51
|
+
* @returns True if error is retryable
|
52
|
+
*/
|
53
|
+
export function isRetryableError(errorMessage) {
|
54
|
+
const retryableErrors = [
|
55
|
+
"rate limit",
|
56
|
+
"timeout",
|
57
|
+
"network",
|
58
|
+
"temporary",
|
59
|
+
"503",
|
60
|
+
"502",
|
61
|
+
"429"
|
62
|
+
];
|
63
|
+
return retryableErrors.some(error => errorMessage.toLowerCase().includes(error));
|
64
|
+
}
|
65
|
+
/**
|
66
|
+
* Checks if an error indicates bulk operations are not supported
|
67
|
+
* @param errorMessage - Error message to check
|
68
|
+
* @returns True if bulk operations not supported
|
69
|
+
*/
|
70
|
+
export function isBulkNotSupportedError(errorMessage) {
|
71
|
+
const notSupportedErrors = [
|
72
|
+
"method not found",
|
73
|
+
"not implemented",
|
74
|
+
"unsupported",
|
75
|
+
"not available",
|
76
|
+
"404"
|
77
|
+
];
|
78
|
+
return notSupportedErrors.some(error => errorMessage.toLowerCase().includes(error));
|
79
|
+
}
|
80
|
+
/**
|
81
|
+
* Checks if an error is critical (authentication, authorization, permissions)
|
82
|
+
* @param errorMessage - Error message to check
|
83
|
+
* @returns True if error is critical
|
84
|
+
*/
|
85
|
+
export function isCriticalError(errorMessage) {
|
86
|
+
const criticalErrors = [
|
87
|
+
"authentication",
|
88
|
+
"authorization",
|
89
|
+
"permission",
|
90
|
+
"forbidden",
|
91
|
+
"401",
|
92
|
+
"403"
|
93
|
+
];
|
94
|
+
return criticalErrors.some(error => errorMessage.toLowerCase().includes(error));
|
95
|
+
}
|