@njdamstra/appwrite-utils-cli 1.8.9
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 +19 -0
- package/README.md +1133 -0
- package/dist/adapters/AdapterFactory.d.ts +94 -0
- package/dist/adapters/AdapterFactory.js +405 -0
- package/dist/adapters/DatabaseAdapter.d.ts +233 -0
- package/dist/adapters/DatabaseAdapter.js +50 -0
- package/dist/adapters/LegacyAdapter.d.ts +50 -0
- package/dist/adapters/LegacyAdapter.js +612 -0
- package/dist/adapters/TablesDBAdapter.d.ts +45 -0
- package/dist/adapters/TablesDBAdapter.js +571 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.js +12 -0
- 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 +166 -0
- package/dist/cli/commands/databaseCommands.d.ts +13 -0
- package/dist/cli/commands/databaseCommands.js +554 -0
- package/dist/cli/commands/functionCommands.d.ts +7 -0
- package/dist/cli/commands/functionCommands.js +330 -0
- package/dist/cli/commands/schemaCommands.d.ts +7 -0
- package/dist/cli/commands/schemaCommands.js +169 -0
- package/dist/cli/commands/storageCommands.d.ts +5 -0
- package/dist/cli/commands/storageCommands.js +143 -0
- package/dist/cli/commands/transferCommands.d.ts +5 -0
- package/dist/cli/commands/transferCommands.js +384 -0
- package/dist/collections/attributes.d.ts +13 -0
- package/dist/collections/attributes.js +1364 -0
- package/dist/collections/indexes.d.ts +12 -0
- package/dist/collections/indexes.js +217 -0
- package/dist/collections/methods.d.ts +19 -0
- package/dist/collections/methods.js +682 -0
- package/dist/collections/tableOperations.d.ts +86 -0
- package/dist/collections/tableOperations.js +434 -0
- package/dist/collections/transferOperations.d.ts +8 -0
- package/dist/collections/transferOperations.js +412 -0
- package/dist/collections/wipeOperations.d.ts +16 -0
- package/dist/collections/wipeOperations.js +233 -0
- package/dist/config/ConfigManager.d.ts +445 -0
- package/dist/config/ConfigManager.js +625 -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/index.d.ts +8 -0
- package/dist/config/index.js +7 -0
- package/dist/config/services/ConfigDiscoveryService.d.ts +126 -0
- package/dist/config/services/ConfigDiscoveryService.js +374 -0
- package/dist/config/services/ConfigLoaderService.d.ts +129 -0
- package/dist/config/services/ConfigLoaderService.js +540 -0
- package/dist/config/services/ConfigMergeService.d.ts +208 -0
- package/dist/config/services/ConfigMergeService.js +308 -0
- package/dist/config/services/ConfigValidationService.d.ts +214 -0
- package/dist/config/services/ConfigValidationService.js +310 -0
- package/dist/config/services/SessionAuthService.d.ts +225 -0
- package/dist/config/services/SessionAuthService.js +456 -0
- package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +1 -0
- package/dist/config/services/__tests__/ConfigMergeService.test.js +271 -0
- package/dist/config/services/index.d.ts +13 -0
- package/dist/config/services/index.js +10 -0
- package/dist/config/yamlConfig.d.ts +722 -0
- package/dist/config/yamlConfig.js +702 -0
- package/dist/databases/methods.d.ts +6 -0
- package/dist/databases/methods.js +35 -0
- package/dist/databases/setup.d.ts +5 -0
- package/dist/databases/setup.js +45 -0
- package/dist/examples/yamlTerminologyExample.d.ts +42 -0
- package/dist/examples/yamlTerminologyExample.js +272 -0
- package/dist/functions/deployments.d.ts +4 -0
- package/dist/functions/deployments.js +146 -0
- package/dist/functions/fnConfigDiscovery.d.ts +3 -0
- package/dist/functions/fnConfigDiscovery.js +108 -0
- package/dist/functions/methods.d.ts +16 -0
- package/dist/functions/methods.js +162 -0
- package/dist/functions/pathResolution.d.ts +37 -0
- package/dist/functions/pathResolution.js +185 -0
- package/dist/functions/templates/count-docs-in-collection/README.md +54 -0
- package/dist/functions/templates/count-docs-in-collection/src/main.ts +159 -0
- package/dist/functions/templates/count-docs-in-collection/src/request.ts +9 -0
- package/dist/functions/templates/hono-typescript/README.md +286 -0
- package/dist/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
- package/dist/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
- package/dist/functions/templates/hono-typescript/src/app.ts +180 -0
- package/dist/functions/templates/hono-typescript/src/context.ts +103 -0
- package/dist/functions/templates/hono-typescript/src/index.ts +54 -0
- package/dist/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
- package/dist/functions/templates/typescript-node/README.md +32 -0
- package/dist/functions/templates/typescript-node/src/context.ts +103 -0
- package/dist/functions/templates/typescript-node/src/index.ts +29 -0
- package/dist/functions/templates/uv/README.md +31 -0
- package/dist/functions/templates/uv/pyproject.toml +30 -0
- package/dist/functions/templates/uv/src/__init__.py +0 -0
- package/dist/functions/templates/uv/src/context.py +125 -0
- package/dist/functions/templates/uv/src/index.py +46 -0
- package/dist/init.d.ts +2 -0
- package/dist/init.js +57 -0
- package/dist/interactiveCLI.d.ts +31 -0
- package/dist/interactiveCLI.js +898 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +1172 -0
- package/dist/migrations/afterImportActions.d.ts +17 -0
- package/dist/migrations/afterImportActions.js +306 -0
- package/dist/migrations/appwriteToX.d.ts +211 -0
- package/dist/migrations/appwriteToX.js +491 -0
- package/dist/migrations/comprehensiveTransfer.d.ts +147 -0
- package/dist/migrations/comprehensiveTransfer.js +1317 -0
- package/dist/migrations/dataLoader.d.ts +753 -0
- package/dist/migrations/dataLoader.js +1250 -0
- package/dist/migrations/importController.d.ts +23 -0
- package/dist/migrations/importController.js +268 -0
- package/dist/migrations/importDataActions.d.ts +50 -0
- package/dist/migrations/importDataActions.js +230 -0
- package/dist/migrations/relationships.d.ts +29 -0
- package/dist/migrations/relationships.js +204 -0
- package/dist/migrations/services/DataTransformationService.d.ts +55 -0
- package/dist/migrations/services/DataTransformationService.js +158 -0
- package/dist/migrations/services/FileHandlerService.d.ts +75 -0
- package/dist/migrations/services/FileHandlerService.js +236 -0
- package/dist/migrations/services/ImportOrchestrator.d.ts +97 -0
- package/dist/migrations/services/ImportOrchestrator.js +485 -0
- package/dist/migrations/services/RateLimitManager.d.ts +138 -0
- package/dist/migrations/services/RateLimitManager.js +279 -0
- package/dist/migrations/services/RelationshipResolver.d.ts +120 -0
- package/dist/migrations/services/RelationshipResolver.js +332 -0
- package/dist/migrations/services/UserMappingService.d.ts +109 -0
- package/dist/migrations/services/UserMappingService.js +277 -0
- package/dist/migrations/services/ValidationService.d.ts +74 -0
- package/dist/migrations/services/ValidationService.js +260 -0
- package/dist/migrations/transfer.d.ts +26 -0
- package/dist/migrations/transfer.js +608 -0
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +131 -0
- package/dist/migrations/yaml/YamlImportConfigLoader.js +383 -0
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +93 -0
- package/dist/migrations/yaml/YamlImportIntegration.js +341 -0
- package/dist/migrations/yaml/generateImportSchemas.d.ts +30 -0
- package/dist/migrations/yaml/generateImportSchemas.js +1327 -0
- package/dist/schemas/authUser.d.ts +24 -0
- package/dist/schemas/authUser.js +17 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.js +5 -0
- package/dist/setupCommands.d.ts +58 -0
- package/dist/setupCommands.js +490 -0
- package/dist/setupController.d.ts +9 -0
- package/dist/setupController.js +34 -0
- package/dist/shared/attributeMapper.d.ts +20 -0
- package/dist/shared/attributeMapper.js +203 -0
- 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.d.ts +75 -0
- package/dist/shared/confirmationDialogs.js +236 -0
- package/dist/shared/errorUtils.d.ts +54 -0
- package/dist/shared/errorUtils.js +95 -0
- package/dist/shared/functionManager.d.ts +48 -0
- package/dist/shared/functionManager.js +336 -0
- package/dist/shared/indexManager.d.ts +24 -0
- package/dist/shared/indexManager.js +151 -0
- package/dist/shared/jsonSchemaGenerator.d.ts +50 -0
- package/dist/shared/jsonSchemaGenerator.js +290 -0
- package/dist/shared/logging.d.ts +61 -0
- package/dist/shared/logging.js +116 -0
- package/dist/shared/messageFormatter.d.ts +39 -0
- package/dist/shared/messageFormatter.js +162 -0
- package/dist/shared/migrationHelpers.d.ts +61 -0
- package/dist/shared/migrationHelpers.js +145 -0
- package/dist/shared/operationLogger.d.ts +10 -0
- package/dist/shared/operationLogger.js +12 -0
- package/dist/shared/operationQueue.d.ts +40 -0
- package/dist/shared/operationQueue.js +311 -0
- 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/progressManager.d.ts +62 -0
- package/dist/shared/progressManager.js +215 -0
- package/dist/shared/pydanticModelGenerator.d.ts +17 -0
- package/dist/shared/pydanticModelGenerator.js +615 -0
- package/dist/shared/relationshipExtractor.d.ts +56 -0
- package/dist/shared/relationshipExtractor.js +138 -0
- package/dist/shared/schemaGenerator.d.ts +40 -0
- package/dist/shared/schemaGenerator.js +556 -0
- package/dist/shared/selectionDialogs.d.ts +214 -0
- package/dist/shared/selectionDialogs.js +544 -0
- package/dist/storage/backupCompression.d.ts +20 -0
- package/dist/storage/backupCompression.js +67 -0
- package/dist/storage/methods.d.ts +32 -0
- package/dist/storage/methods.js +472 -0
- package/dist/storage/schemas.d.ts +842 -0
- package/dist/storage/schemas.js +175 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +3 -0
- package/dist/users/methods.d.ts +16 -0
- package/dist/users/methods.js +277 -0
- package/dist/utils/ClientFactory.d.ts +87 -0
- package/dist/utils/ClientFactory.js +212 -0
- package/dist/utils/configDiscovery.d.ts +78 -0
- package/dist/utils/configDiscovery.js +472 -0
- package/dist/utils/configMigration.d.ts +1 -0
- package/dist/utils/configMigration.js +261 -0
- package/dist/utils/constantsGenerator.d.ts +31 -0
- package/dist/utils/constantsGenerator.js +321 -0
- package/dist/utils/dataConverters.d.ts +46 -0
- package/dist/utils/dataConverters.js +139 -0
- package/dist/utils/directoryUtils.d.ts +22 -0
- package/dist/utils/directoryUtils.js +59 -0
- package/dist/utils/getClientFromConfig.d.ts +39 -0
- package/dist/utils/getClientFromConfig.js +199 -0
- package/dist/utils/helperFunctions.d.ts +63 -0
- package/dist/utils/helperFunctions.js +156 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/loadConfigs.d.ts +50 -0
- package/dist/utils/loadConfigs.js +358 -0
- 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.d.ts +2 -0
- package/dist/utils/retryFailedPromises.js +23 -0
- package/dist/utils/sessionAuth.d.ts +48 -0
- package/dist/utils/sessionAuth.js +164 -0
- package/dist/utils/setupFiles.d.ts +4 -0
- package/dist/utils/setupFiles.js +1192 -0
- package/dist/utils/typeGuards.d.ts +35 -0
- package/dist/utils/typeGuards.js +57 -0
- package/dist/utils/validationRules.d.ts +43 -0
- package/dist/utils/validationRules.js +42 -0
- package/dist/utils/versionDetection.d.ts +58 -0
- package/dist/utils/versionDetection.js +251 -0
- package/dist/utils/yamlConverter.d.ts +100 -0
- package/dist/utils/yamlConverter.js +428 -0
- package/dist/utils/yamlLoader.d.ts +70 -0
- package/dist/utils/yamlLoader.js +267 -0
- package/dist/utilsController.d.ts +106 -0
- package/dist/utilsController.js +863 -0
- package/package.json +75 -0
- package/scripts/copy-templates.ts +23 -0
- package/src/adapters/AdapterFactory.ts +510 -0
- package/src/adapters/DatabaseAdapter.ts +306 -0
- package/src/adapters/LegacyAdapter.ts +841 -0
- package/src/adapters/TablesDBAdapter.ts +773 -0
- package/src/adapters/index.ts +37 -0
- 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 +201 -0
- package/src/cli/commands/databaseCommands.ts +749 -0
- package/src/cli/commands/functionCommands.ts +418 -0
- package/src/cli/commands/schemaCommands.ts +200 -0
- package/src/cli/commands/storageCommands.ts +152 -0
- package/src/cli/commands/transferCommands.ts +457 -0
- package/src/collections/attributes.ts +2054 -0
- package/src/collections/attributes.ts.backup +1555 -0
- package/src/collections/indexes.ts +352 -0
- package/src/collections/methods.ts +745 -0
- package/src/collections/tableOperations.ts +506 -0
- package/src/collections/transferOperations.ts +590 -0
- package/src/collections/wipeOperations.ts +346 -0
- package/src/config/ConfigManager.ts +808 -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/index.ts +10 -0
- package/src/config/services/ConfigDiscoveryService.ts +463 -0
- package/src/config/services/ConfigLoaderService.ts +740 -0
- package/src/config/services/ConfigMergeService.ts +388 -0
- package/src/config/services/ConfigValidationService.ts +394 -0
- package/src/config/services/SessionAuthService.ts +565 -0
- package/src/config/services/__tests__/ConfigMergeService.test.ts +351 -0
- package/src/config/services/index.ts +29 -0
- package/src/config/yamlConfig.ts +761 -0
- package/src/databases/methods.ts +49 -0
- package/src/databases/setup.ts +77 -0
- package/src/examples/yamlTerminologyExample.ts +346 -0
- package/src/functions/deployments.ts +220 -0
- package/src/functions/fnConfigDiscovery.ts +103 -0
- package/src/functions/methods.ts +271 -0
- package/src/functions/pathResolution.ts +227 -0
- package/src/functions/templates/count-docs-in-collection/README.md +54 -0
- package/src/functions/templates/count-docs-in-collection/src/main.ts +159 -0
- package/src/functions/templates/count-docs-in-collection/src/request.ts +9 -0
- package/src/functions/templates/hono-typescript/README.md +286 -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/typescript-node/README.md +32 -0
- package/src/functions/templates/typescript-node/src/context.ts +103 -0
- package/src/functions/templates/typescript-node/src/index.ts +29 -0
- package/src/functions/templates/uv/README.md +31 -0
- package/src/functions/templates/uv/pyproject.toml +30 -0
- package/src/functions/templates/uv/src/__init__.py +0 -0
- package/src/functions/templates/uv/src/context.py +125 -0
- package/src/functions/templates/uv/src/index.py +46 -0
- package/src/init.ts +62 -0
- package/src/interactiveCLI.ts +1136 -0
- package/src/main.ts +1661 -0
- package/src/migrations/afterImportActions.ts +580 -0
- package/src/migrations/appwriteToX.ts +664 -0
- package/src/migrations/comprehensiveTransfer.ts +2285 -0
- package/src/migrations/dataLoader.ts +1702 -0
- package/src/migrations/importController.ts +428 -0
- package/src/migrations/importDataActions.ts +315 -0
- package/src/migrations/relationships.ts +334 -0
- package/src/migrations/services/DataTransformationService.ts +196 -0
- package/src/migrations/services/FileHandlerService.ts +311 -0
- package/src/migrations/services/ImportOrchestrator.ts +666 -0
- package/src/migrations/services/RateLimitManager.ts +363 -0
- package/src/migrations/services/RelationshipResolver.ts +461 -0
- package/src/migrations/services/UserMappingService.ts +345 -0
- package/src/migrations/services/ValidationService.ts +349 -0
- package/src/migrations/transfer.ts +1068 -0
- package/src/migrations/yaml/YamlImportConfigLoader.ts +439 -0
- package/src/migrations/yaml/YamlImportIntegration.ts +446 -0
- package/src/migrations/yaml/generateImportSchemas.ts +1354 -0
- package/src/schemas/authUser.ts +23 -0
- package/src/setup.ts +8 -0
- package/src/setupCommands.ts +603 -0
- package/src/setupController.ts +43 -0
- package/src/shared/attributeMapper.ts +229 -0
- package/src/shared/backupMetadataSchema.ts +93 -0
- package/src/shared/backupTracking.ts +211 -0
- package/src/shared/confirmationDialogs.ts +327 -0
- package/src/shared/errorUtils.ts +110 -0
- package/src/shared/functionManager.ts +525 -0
- package/src/shared/indexManager.ts +254 -0
- package/src/shared/jsonSchemaGenerator.ts +383 -0
- package/src/shared/logging.ts +149 -0
- package/src/shared/messageFormatter.ts +208 -0
- package/src/shared/migrationHelpers.ts +232 -0
- package/src/shared/operationLogger.ts +20 -0
- package/src/shared/operationQueue.ts +377 -0
- package/src/shared/operationsTable.ts +338 -0
- package/src/shared/operationsTableSchema.ts +60 -0
- package/src/shared/progressManager.ts +278 -0
- package/src/shared/pydanticModelGenerator.ts +618 -0
- package/src/shared/relationshipExtractor.ts +214 -0
- package/src/shared/schemaGenerator.ts +644 -0
- package/src/shared/selectionDialogs.ts +749 -0
- package/src/storage/backupCompression.ts +88 -0
- package/src/storage/methods.ts +698 -0
- package/src/storage/schemas.ts +205 -0
- package/src/types/node-appwrite-tablesdb.d.ts +44 -0
- package/src/types.ts +9 -0
- package/src/users/methods.ts +359 -0
- package/src/utils/ClientFactory.ts +240 -0
- package/src/utils/configDiscovery.ts +557 -0
- package/src/utils/configMigration.ts +348 -0
- package/src/utils/constantsGenerator.ts +369 -0
- package/src/utils/dataConverters.ts +159 -0
- package/src/utils/directoryUtils.ts +61 -0
- package/src/utils/getClientFromConfig.ts +257 -0
- package/src/utils/helperFunctions.ts +228 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/loadConfigs.ts +449 -0
- package/src/utils/pathResolvers.ts +81 -0
- package/src/utils/projectConfig.ts +299 -0
- package/src/utils/retryFailedPromises.ts +29 -0
- package/src/utils/sessionAuth.ts +230 -0
- package/src/utils/setupFiles.ts +1238 -0
- package/src/utils/typeGuards.ts +65 -0
- package/src/utils/validationRules.ts +88 -0
- package/src/utils/versionDetection.ts +292 -0
- package/src/utils/yamlConverter.ts +542 -0
- package/src/utils/yamlLoader.ts +371 -0
- package/src/utilsController.ts +1203 -0
- 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/tsconfig.json +44 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
import { SchemaGenerator } from "../shared/schemaGenerator.js";
|
|
2
|
+
import { findYamlConfig } from "../config/yamlConfig.js";
|
|
3
|
+
import { Client, Compression, Databases, Query, Storage, } from "node-appwrite";
|
|
4
|
+
import { fetchAllCollections } from "../collections/methods.js";
|
|
5
|
+
import { fetchAllDatabases } from "../databases/methods.js";
|
|
6
|
+
import { CollectionSchema, attributeSchema, AppwriteConfigSchema, permissionsSchema, attributesSchema, indexesSchema, parseAttribute, } from "@njdamstra/appwrite-utils";
|
|
7
|
+
import { getDatabaseFromConfig } from "./afterImportActions.js";
|
|
8
|
+
import { getAdapterFromConfig } from "../utils/getClientFromConfig.js";
|
|
9
|
+
import { listBuckets } from "../storage/methods.js";
|
|
10
|
+
import { listFunctions, listFunctionDeployments, getFunction } from "../functions/methods.js";
|
|
11
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
|
12
|
+
import { isLegacyDatabases } from "../utils/typeGuards.js";
|
|
13
|
+
/**
|
|
14
|
+
* Convert between collection and table terminology based on data structure
|
|
15
|
+
*/
|
|
16
|
+
function normalizeCollectionOrTable(collection) {
|
|
17
|
+
// Check if this is a table (has columns) or collection (has attributes)
|
|
18
|
+
const isTable = collection.columns && Array.isArray(collection.columns);
|
|
19
|
+
if (isTable) {
|
|
20
|
+
// Table structure - convert columns to attributes
|
|
21
|
+
MessageFormatter.debug(`Detected table structure: ${collection.name || collection.tableName}`, { prefix: "Migration" });
|
|
22
|
+
return {
|
|
23
|
+
...collection,
|
|
24
|
+
attributes: collection.columns || [],
|
|
25
|
+
permissions: collection.$permissions || collection.permissions || [],
|
|
26
|
+
name: collection.name || collection.tableName,
|
|
27
|
+
$id: collection.$id || collection.tableId,
|
|
28
|
+
enabled: collection.enabled ?? true
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// Collection structure - use as-is with fallbacks
|
|
33
|
+
MessageFormatter.debug(`Detected collection structure: ${collection.name}`, { prefix: "Migration" });
|
|
34
|
+
return {
|
|
35
|
+
...collection,
|
|
36
|
+
attributes: collection.attributes || [],
|
|
37
|
+
permissions: collection.$permissions || collection.permissions || [],
|
|
38
|
+
name: collection.name,
|
|
39
|
+
$id: collection.$id,
|
|
40
|
+
enabled: collection.enabled ?? true
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export class AppwriteToX {
|
|
45
|
+
config;
|
|
46
|
+
storage;
|
|
47
|
+
updatedConfig;
|
|
48
|
+
collToAttributeMap = new Map();
|
|
49
|
+
appwriteFolderPath;
|
|
50
|
+
adapter;
|
|
51
|
+
apiMode;
|
|
52
|
+
databaseApiModes = new Map();
|
|
53
|
+
constructor(config, appwriteFolderPath, storage) {
|
|
54
|
+
this.config = config;
|
|
55
|
+
this.updatedConfig = config;
|
|
56
|
+
this.storage = storage;
|
|
57
|
+
this.appwriteFolderPath = appwriteFolderPath;
|
|
58
|
+
this.ensureClientInitialized();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Initialize adapter for database operations with API mode detection
|
|
62
|
+
*/
|
|
63
|
+
async initializeAdapter() {
|
|
64
|
+
if (!this.adapter) {
|
|
65
|
+
try {
|
|
66
|
+
const { adapter, apiMode } = await getAdapterFromConfig(this.config);
|
|
67
|
+
this.adapter = adapter;
|
|
68
|
+
this.apiMode = apiMode;
|
|
69
|
+
MessageFormatter.info(`Initialized database adapter with API mode: ${apiMode}`, { prefix: "Migration" });
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
MessageFormatter.warning(`Failed to initialize adapter, falling back to legacy client: ${error instanceof Error ? error.message : 'Unknown error'}`, { prefix: "Migration" });
|
|
73
|
+
// Fallback to legacy client initialization
|
|
74
|
+
this.ensureClientInitialized();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
ensureClientInitialized() {
|
|
79
|
+
if (!this.config.appwriteClient) {
|
|
80
|
+
const client = new Client();
|
|
81
|
+
client
|
|
82
|
+
.setEndpoint(this.config.appwriteEndpoint)
|
|
83
|
+
.setProject(this.config.appwriteProject)
|
|
84
|
+
.setKey(this.config.appwriteKey);
|
|
85
|
+
this.config.appwriteClient = client;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Function to parse a single permission string
|
|
89
|
+
parsePermissionString = (permissionString) => {
|
|
90
|
+
const match = permissionString.match(/^(\w+)\('([^']+)'\)$/);
|
|
91
|
+
if (!match) {
|
|
92
|
+
throw new Error(`Invalid permission format: ${permissionString}`);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
permission: match[1],
|
|
96
|
+
target: match[2],
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
// Function to parse an array of permission strings
|
|
100
|
+
parsePermissionsArray = (permissions) => {
|
|
101
|
+
if (permissions.length === 0) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
const parsedPermissions = permissionsSchema.parse(permissions);
|
|
105
|
+
// Validate the parsed permissions using Zod
|
|
106
|
+
return parsedPermissions ?? [];
|
|
107
|
+
};
|
|
108
|
+
updateCollectionConfigAttributes = (collection) => {
|
|
109
|
+
// Normalize collection/table structure to handle both TablesDB and Legacy formats
|
|
110
|
+
const normalizedCollection = normalizeCollectionOrTable(collection);
|
|
111
|
+
for (const attribute of normalizedCollection.attributes) {
|
|
112
|
+
if (!attribute) {
|
|
113
|
+
MessageFormatter.warning("Skipping null/undefined attribute in updateCollectionConfigAttributes", { prefix: "Migration" });
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const attributeParsed = attributeSchema.parse(attribute);
|
|
117
|
+
this.collToAttributeMap
|
|
118
|
+
.get(normalizedCollection.name)
|
|
119
|
+
?.push(attributeParsed);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Fetch collections/tables using the appropriate adapter or legacy client
|
|
124
|
+
*/
|
|
125
|
+
async fetchCollectionsOrTables(databaseId, db) {
|
|
126
|
+
// Try to use adapter first
|
|
127
|
+
if (this.adapter) {
|
|
128
|
+
try {
|
|
129
|
+
const result = await this.adapter.listTables({ databaseId });
|
|
130
|
+
const items = result.tables || result.collections || [];
|
|
131
|
+
MessageFormatter.info(`Fetched ${items.length} items using ${this.apiMode} adapter`, { prefix: "Migration" });
|
|
132
|
+
return items;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
MessageFormatter.warning(`Adapter fetch failed, falling back to legacy: ${error instanceof Error ? error.message : 'Unknown error'}`, { prefix: "Migration" });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Fallback to legacy method
|
|
139
|
+
try {
|
|
140
|
+
const collections = await fetchAllCollections(databaseId, db);
|
|
141
|
+
MessageFormatter.info(`Fetched ${collections.length} collections using legacy client`, { prefix: "Migration" });
|
|
142
|
+
return collections;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
MessageFormatter.error("Failed to fetch collections with both adapter and legacy methods", error instanceof Error ? error : new Error(String(error)), { prefix: "Migration" });
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get collection/table using the appropriate adapter or legacy client
|
|
151
|
+
*/
|
|
152
|
+
async getCollectionOrTable(databaseId, collectionId) {
|
|
153
|
+
// Try to use adapter first
|
|
154
|
+
if (this.adapter) {
|
|
155
|
+
try {
|
|
156
|
+
const result = await this.adapter.getTable({ databaseId, tableId: collectionId });
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
MessageFormatter.warning(`Adapter get failed, falling back to legacy: ${error instanceof Error ? error.message : 'Unknown error'}`, { prefix: "Migration" });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Fallback to legacy method
|
|
164
|
+
const db = getDatabaseFromConfig(this.config);
|
|
165
|
+
return await db.getCollection(databaseId, collectionId);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Detect API mode for a specific database by testing adapter capabilities
|
|
169
|
+
*/
|
|
170
|
+
async detectDatabaseApiMode(databaseId) {
|
|
171
|
+
// If we already detected this database, return cached result
|
|
172
|
+
if (this.databaseApiModes.has(databaseId)) {
|
|
173
|
+
return this.databaseApiModes.get(databaseId);
|
|
174
|
+
}
|
|
175
|
+
// If we have a global adapter, use its API mode as default
|
|
176
|
+
if (this.apiMode) {
|
|
177
|
+
this.databaseApiModes.set(databaseId, this.apiMode);
|
|
178
|
+
MessageFormatter.debug(`Using global API mode for database ${databaseId}: ${this.apiMode}`, { prefix: "Migration" });
|
|
179
|
+
return this.apiMode;
|
|
180
|
+
}
|
|
181
|
+
// Default to legacy if no adapter available
|
|
182
|
+
const defaultMode = 'legacy';
|
|
183
|
+
this.databaseApiModes.set(databaseId, defaultMode);
|
|
184
|
+
MessageFormatter.debug(`Defaulting to legacy mode for database ${databaseId}`, { prefix: "Migration" });
|
|
185
|
+
return defaultMode;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get API mode context for schema generation
|
|
189
|
+
*/
|
|
190
|
+
getSchemaGeneratorApiContext() {
|
|
191
|
+
const databaseModes = {};
|
|
192
|
+
// Get API mode for each database
|
|
193
|
+
for (const db of this.updatedConfig.databases || []) {
|
|
194
|
+
const apiMode = this.databaseApiModes.get(db.$id) || this.apiMode || 'legacy';
|
|
195
|
+
databaseModes[db.$id] = apiMode;
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
apiMode: this.apiMode || 'legacy',
|
|
199
|
+
databaseApiModes: databaseModes,
|
|
200
|
+
adapterMetadata: this.adapter?.getMetadata()
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
async appwriteSync(config, databases, databaseSelections, bucketSelections) {
|
|
204
|
+
// Initialize adapter for proper API mode detection and usage
|
|
205
|
+
await this.initializeAdapter();
|
|
206
|
+
const db = getDatabaseFromConfig(config);
|
|
207
|
+
if (!databases) {
|
|
208
|
+
try {
|
|
209
|
+
MessageFormatter.info("Fetching remote databases...", { prefix: "Migration" });
|
|
210
|
+
databases = await fetchAllDatabases(db);
|
|
211
|
+
MessageFormatter.info(`Found ${databases.length} remote databases`, { prefix: "Migration" });
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
MessageFormatter.error("Failed to fetch remote databases", error instanceof Error ? error : new Error(String(error)), { prefix: "Migration" });
|
|
215
|
+
throw new Error(`Database fetch failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Filter databases based on selection if provided
|
|
219
|
+
let databasesToProcess = databases;
|
|
220
|
+
if (databaseSelections && databaseSelections.length > 0) {
|
|
221
|
+
databasesToProcess = databases?.filter(db => databaseSelections.some(selection => selection.databaseId === db.$id)) || [];
|
|
222
|
+
MessageFormatter.info(`Filtered to ${databasesToProcess.length} selected databases`, { prefix: "Migration" });
|
|
223
|
+
}
|
|
224
|
+
let updatedConfig = { ...config };
|
|
225
|
+
// Initialize databases array if it doesn't exist
|
|
226
|
+
if (!updatedConfig.databases) {
|
|
227
|
+
updatedConfig.databases = [];
|
|
228
|
+
}
|
|
229
|
+
// Sync remote databases to local config - add missing ones
|
|
230
|
+
MessageFormatter.info(`Syncing ${databasesToProcess.length} remote databases with local config...`, { prefix: "Migration" });
|
|
231
|
+
let addedCount = 0;
|
|
232
|
+
let updatedCount = 0;
|
|
233
|
+
for (const remoteDb of databasesToProcess) {
|
|
234
|
+
// Check if this database already exists in the config
|
|
235
|
+
const existingDbIndex = updatedConfig.databases.findIndex((localDb) => localDb.$id === remoteDb.$id);
|
|
236
|
+
if (existingDbIndex === -1) {
|
|
237
|
+
// Database doesn't exist locally, add it
|
|
238
|
+
MessageFormatter.success(`Adding new database to config: ${remoteDb.name} (${remoteDb.$id})`, { prefix: "Migration" });
|
|
239
|
+
updatedConfig.databases.push({
|
|
240
|
+
$id: remoteDb.$id,
|
|
241
|
+
name: remoteDb.name,
|
|
242
|
+
});
|
|
243
|
+
addedCount++;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// Database exists, update name if different
|
|
247
|
+
if (updatedConfig.databases[existingDbIndex].name !== remoteDb.name) {
|
|
248
|
+
MessageFormatter.info(`Updating database name: ${updatedConfig.databases[existingDbIndex].name} -> ${remoteDb.name}`, { prefix: "Migration" });
|
|
249
|
+
updatedConfig.databases[existingDbIndex].name = remoteDb.name;
|
|
250
|
+
updatedCount++;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
MessageFormatter.success(`Database sync summary: ${addedCount} added, ${updatedCount} updated, ${updatedConfig.databases.length} total`, { prefix: "Migration" });
|
|
255
|
+
// Fetch all buckets
|
|
256
|
+
const allBuckets = await listBuckets(this.storage);
|
|
257
|
+
// Filter buckets based on selection if provided
|
|
258
|
+
let matchedBuckets = allBuckets.buckets;
|
|
259
|
+
if (bucketSelections && bucketSelections.length > 0) {
|
|
260
|
+
matchedBuckets = allBuckets.buckets.filter(bucket => bucketSelections.some(selection => selection.bucketId === bucket.$id));
|
|
261
|
+
MessageFormatter.info(`Filtered to ${matchedBuckets.length} selected buckets`, { prefix: "Migration" });
|
|
262
|
+
}
|
|
263
|
+
// Loop through each database
|
|
264
|
+
for (const database of databasesToProcess) {
|
|
265
|
+
// Detect API mode for this specific database
|
|
266
|
+
const dbApiMode = await this.detectDatabaseApiMode(database.$id);
|
|
267
|
+
MessageFormatter.info(`Processing database '${database.name}' with API mode: ${dbApiMode}`, { prefix: "Migration" });
|
|
268
|
+
// Match bucket to database (from filtered buckets if selections provided)
|
|
269
|
+
const matchedBucket = matchedBuckets.find((bucket) => bucket.$id.toLowerCase().includes(database.$id.toLowerCase()));
|
|
270
|
+
if (matchedBucket) {
|
|
271
|
+
const dbConfig = updatedConfig.databases.find((db) => db.$id === database.$id);
|
|
272
|
+
if (dbConfig) {
|
|
273
|
+
dbConfig.bucket = {
|
|
274
|
+
$id: matchedBucket.$id,
|
|
275
|
+
name: matchedBucket.name,
|
|
276
|
+
enabled: matchedBucket.enabled,
|
|
277
|
+
maximumFileSize: matchedBucket.maximumFileSize,
|
|
278
|
+
allowedFileExtensions: matchedBucket.allowedFileExtensions,
|
|
279
|
+
compression: matchedBucket.compression,
|
|
280
|
+
encryption: matchedBucket.encryption,
|
|
281
|
+
antivirus: matchedBucket.antivirus,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Use adapter-aware collection/table fetching with proper API mode detection
|
|
286
|
+
const collections = await this.fetchCollectionsOrTables(database.$id, db);
|
|
287
|
+
// Filter collections based on table selection if provided
|
|
288
|
+
let collectionsToProcess = collections;
|
|
289
|
+
if (databaseSelections && databaseSelections.length > 0) {
|
|
290
|
+
const dbSelection = databaseSelections.find(selection => selection.databaseId === database.$id);
|
|
291
|
+
if (dbSelection && dbSelection.tableIds.length > 0) {
|
|
292
|
+
collectionsToProcess = collections.filter(collection => dbSelection.tableIds.includes(collection.$id));
|
|
293
|
+
MessageFormatter.info(`Filtered to ${collectionsToProcess.length} selected tables for database '${database.name}'`, { prefix: "Migration" });
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Loop through each collection in the current database
|
|
297
|
+
if (!updatedConfig.collections) {
|
|
298
|
+
updatedConfig.collections = [];
|
|
299
|
+
}
|
|
300
|
+
MessageFormatter.info(`Processing ${collectionsToProcess.length} collections/tables in database '${database.name}'`, { prefix: "Migration" });
|
|
301
|
+
let processedCount = 0;
|
|
302
|
+
let errorCount = 0;
|
|
303
|
+
for (const collection of collectionsToProcess) {
|
|
304
|
+
try {
|
|
305
|
+
if (!collection) {
|
|
306
|
+
MessageFormatter.warning("Skipping null/undefined collection", { prefix: "Migration" });
|
|
307
|
+
errorCount++;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
// Normalize collection/table structure to handle both TablesDB and Legacy formats
|
|
311
|
+
const normalizedCollection = normalizeCollectionOrTable(collection);
|
|
312
|
+
MessageFormatter.processing(`Processing ${normalizedCollection.name} (${normalizedCollection.$id})`, { prefix: "Migration" });
|
|
313
|
+
const existingCollectionIndex = updatedConfig.collections.findIndex((c) => c.name === normalizedCollection.name);
|
|
314
|
+
// Parse the collection permissions and attributes using normalized structure
|
|
315
|
+
const collPermissions = this.parsePermissionsArray(normalizedCollection.permissions);
|
|
316
|
+
// Process attributes with proper error handling
|
|
317
|
+
let collAttributes = [];
|
|
318
|
+
try {
|
|
319
|
+
collAttributes = normalizedCollection.attributes
|
|
320
|
+
.map((attr) => {
|
|
321
|
+
if (!attr) {
|
|
322
|
+
MessageFormatter.warning("Skipping null/undefined attribute", { prefix: "Migration" });
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
return parseAttribute(attr);
|
|
326
|
+
})
|
|
327
|
+
.filter((attribute) => attribute !== null &&
|
|
328
|
+
(attribute.type !== "relationship" ? true : attribute.side !== "child"));
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
MessageFormatter.error(`Error processing attributes for ${normalizedCollection.name}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Migration" });
|
|
332
|
+
// Continue with empty attributes array
|
|
333
|
+
collAttributes = [];
|
|
334
|
+
}
|
|
335
|
+
for (const attribute of collAttributes) {
|
|
336
|
+
if (attribute.type === "relationship" &&
|
|
337
|
+
attribute.relatedCollection) {
|
|
338
|
+
MessageFormatter.info(`Fetching related collection for ID: ${attribute.relatedCollection}`, { prefix: "Migration" });
|
|
339
|
+
try {
|
|
340
|
+
const relatedCollectionPulled = await this.getCollectionOrTable(database.$id, attribute.relatedCollection);
|
|
341
|
+
MessageFormatter.info(`Fetched Collection Name: ${relatedCollectionPulled.name}`, { prefix: "Migration" });
|
|
342
|
+
attribute.relatedCollection = relatedCollectionPulled.name;
|
|
343
|
+
MessageFormatter.info(`Updated attribute.relatedCollection to: ${attribute.relatedCollection}`, { prefix: "Migration" });
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
MessageFormatter.error("Error fetching related collection", error instanceof Error ? error : new Error(String(error)), { prefix: "Migration" });
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
this.collToAttributeMap.set(normalizedCollection.name, collAttributes);
|
|
351
|
+
// Process indexes with proper error handling using normalized collection
|
|
352
|
+
let collIndexes = [];
|
|
353
|
+
try {
|
|
354
|
+
const finalIndexes = (normalizedCollection.indexes || collection.indexes || []).map((index) => {
|
|
355
|
+
if (!index) {
|
|
356
|
+
MessageFormatter.warning("Skipping null/undefined index", { prefix: "Migration" });
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
...index,
|
|
361
|
+
// Convert TablesDB 'columns' to expected 'attributes' for schema validation
|
|
362
|
+
attributes: index.attributes || index.columns || [],
|
|
363
|
+
orders: index.orders?.filter((order) => {
|
|
364
|
+
return order !== null && order;
|
|
365
|
+
}),
|
|
366
|
+
};
|
|
367
|
+
}).filter((index) => index !== null);
|
|
368
|
+
collIndexes = indexesSchema.parse(finalIndexes) ?? [];
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
MessageFormatter.error(`Error processing indexes for ${normalizedCollection.name}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Migration" });
|
|
372
|
+
// Continue with empty indexes array
|
|
373
|
+
collIndexes = [];
|
|
374
|
+
}
|
|
375
|
+
// Prepare the collection object to be added or updated using normalized data
|
|
376
|
+
const collToPush = CollectionSchema.parse({
|
|
377
|
+
$id: normalizedCollection.$id,
|
|
378
|
+
name: normalizedCollection.name,
|
|
379
|
+
enabled: normalizedCollection.enabled,
|
|
380
|
+
documentSecurity: collection.documentSecurity, // Use original collection for this field
|
|
381
|
+
$createdAt: collection.$createdAt, // Use original collection for timestamps
|
|
382
|
+
$updatedAt: collection.$updatedAt,
|
|
383
|
+
$permissions: collPermissions.length > 0 ? collPermissions : undefined,
|
|
384
|
+
indexes: collIndexes.length > 0 ? collIndexes : undefined,
|
|
385
|
+
attributes: collAttributes.length > 0 ? collAttributes : undefined,
|
|
386
|
+
});
|
|
387
|
+
if (existingCollectionIndex !== -1) {
|
|
388
|
+
// Update existing collection
|
|
389
|
+
updatedConfig.collections[existingCollectionIndex] = collToPush;
|
|
390
|
+
MessageFormatter.debug(`Updated existing collection: ${normalizedCollection.name}`, { prefix: "Migration" });
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
// Add new collection
|
|
394
|
+
updatedConfig.collections.push(collToPush);
|
|
395
|
+
MessageFormatter.debug(`Added new collection: ${normalizedCollection.name}`, { prefix: "Migration" });
|
|
396
|
+
}
|
|
397
|
+
processedCount++;
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
MessageFormatter.error(`Error processing collection: ${collection?.name || 'unknown'}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Migration" });
|
|
401
|
+
errorCount++;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
MessageFormatter.success(`Database '${database.name}' processing complete: ${processedCount} collections processed, ${errorCount} errors`, { prefix: "Migration" });
|
|
405
|
+
}
|
|
406
|
+
// Add unmatched buckets as global buckets
|
|
407
|
+
// Use filtered buckets if selections provided, otherwise use all buckets
|
|
408
|
+
const sourceBuckets = bucketSelections && bucketSelections.length > 0 ? matchedBuckets : allBuckets.buckets;
|
|
409
|
+
const globalBuckets = sourceBuckets.filter((bucket) => !updatedConfig.databases.some((db) => db.bucket && db.bucket.$id === bucket.$id));
|
|
410
|
+
updatedConfig.buckets = globalBuckets.map((bucket) => ({
|
|
411
|
+
$id: bucket.$id,
|
|
412
|
+
name: bucket.name,
|
|
413
|
+
enabled: bucket.enabled,
|
|
414
|
+
maximumFileSize: bucket.maximumFileSize,
|
|
415
|
+
allowedFileExtensions: bucket.allowedFileExtensions,
|
|
416
|
+
compression: bucket.compression,
|
|
417
|
+
encryption: bucket.encryption,
|
|
418
|
+
antivirus: bucket.antivirus,
|
|
419
|
+
}));
|
|
420
|
+
const remoteFunctions = await listFunctions(this.config.appwriteClient, [
|
|
421
|
+
Query.limit(1000),
|
|
422
|
+
]);
|
|
423
|
+
// Fetch full details per function to ensure 'scopes' and other fields are present
|
|
424
|
+
const detailedFunctions = [];
|
|
425
|
+
for (const f of remoteFunctions.functions) {
|
|
426
|
+
try {
|
|
427
|
+
const full = await getFunction(this.config.appwriteClient, f.$id);
|
|
428
|
+
detailedFunctions.push(full);
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
detailedFunctions.push(f);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
this.updatedConfig.functions = detailedFunctions.map((func) => ({
|
|
435
|
+
$id: func.$id,
|
|
436
|
+
name: func.name,
|
|
437
|
+
runtime: func.runtime,
|
|
438
|
+
execute: func.execute,
|
|
439
|
+
events: func.events || [],
|
|
440
|
+
schedule: func.schedule || "",
|
|
441
|
+
timeout: func.timeout || 15,
|
|
442
|
+
enabled: func.enabled !== false,
|
|
443
|
+
logging: func.logging !== false,
|
|
444
|
+
entrypoint: func.entrypoint || "src/index.ts",
|
|
445
|
+
commands: func.commands || "npm install",
|
|
446
|
+
scopes: Array.isArray(func.scopes) ? func.scopes : [],
|
|
447
|
+
dirPath: `functions/${func.name}`,
|
|
448
|
+
specification: func.specification,
|
|
449
|
+
}));
|
|
450
|
+
// Make sure to update the config with all changes including databases
|
|
451
|
+
updatedConfig.functions = this.updatedConfig.functions;
|
|
452
|
+
this.updatedConfig = updatedConfig;
|
|
453
|
+
MessageFormatter.success(`Sync completed - ${updatedConfig.databases.length} databases, ${updatedConfig.collections?.length || 0} collections, ${updatedConfig.buckets?.length || 0} buckets, ${updatedConfig.functions?.length || 0} functions`, { prefix: "Migration" });
|
|
454
|
+
}
|
|
455
|
+
async toSchemas(databases, databaseSelections, bucketSelections) {
|
|
456
|
+
try {
|
|
457
|
+
MessageFormatter.info("Starting sync-from-Appwrite process...", { prefix: "Migration" });
|
|
458
|
+
await this.appwriteSync(this.config, databases, databaseSelections, bucketSelections);
|
|
459
|
+
const generator = new SchemaGenerator(this.updatedConfig, this.appwriteFolderPath);
|
|
460
|
+
// Pass API mode context to the schema generator
|
|
461
|
+
const apiContext = this.getSchemaGeneratorApiContext();
|
|
462
|
+
// Extend the config with API mode information for schema generation
|
|
463
|
+
const configWithApiContext = {
|
|
464
|
+
...this.updatedConfig,
|
|
465
|
+
apiMode: apiContext.apiMode,
|
|
466
|
+
databaseApiModes: apiContext.databaseApiModes,
|
|
467
|
+
adapterMetadata: apiContext.adapterMetadata
|
|
468
|
+
};
|
|
469
|
+
// Check if this is a YAML-based project
|
|
470
|
+
const yamlConfigPath = findYamlConfig(this.appwriteFolderPath);
|
|
471
|
+
const isYamlProject = !!yamlConfigPath;
|
|
472
|
+
if (isYamlProject) {
|
|
473
|
+
MessageFormatter.info("Detected YAML configuration - generating YAML collection definitions", { prefix: "Migration" });
|
|
474
|
+
generator.updateYamlCollections();
|
|
475
|
+
await generator.updateConfig(configWithApiContext, true);
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
MessageFormatter.info("Generating TypeScript collection definitions", { prefix: "Migration" });
|
|
479
|
+
generator.updateTsSchemas();
|
|
480
|
+
await generator.updateConfig(configWithApiContext, false);
|
|
481
|
+
}
|
|
482
|
+
MessageFormatter.info("Generating Zod schemas from synced collections...", { prefix: "Migration" });
|
|
483
|
+
await generator.generateSchemas();
|
|
484
|
+
MessageFormatter.success("Sync-from-Appwrite process completed successfully", { prefix: "Migration" });
|
|
485
|
+
}
|
|
486
|
+
catch (error) {
|
|
487
|
+
MessageFormatter.error("Error during sync-from-Appwrite process", error instanceof Error ? error : new Error(String(error)), { prefix: "Migration" });
|
|
488
|
+
throw error;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
export interface ComprehensiveTransferOptions {
|
|
2
|
+
sourceEndpoint: string;
|
|
3
|
+
sourceProject: string;
|
|
4
|
+
sourceKey: string;
|
|
5
|
+
targetEndpoint: string;
|
|
6
|
+
targetProject: string;
|
|
7
|
+
targetKey: string;
|
|
8
|
+
transferUsers?: boolean;
|
|
9
|
+
transferTeams?: boolean;
|
|
10
|
+
transferDatabases?: boolean;
|
|
11
|
+
transferBuckets?: boolean;
|
|
12
|
+
transferFunctions?: boolean;
|
|
13
|
+
concurrencyLimit?: number;
|
|
14
|
+
dryRun?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface TransferResults {
|
|
17
|
+
users: {
|
|
18
|
+
transferred: number;
|
|
19
|
+
skipped: number;
|
|
20
|
+
failed: number;
|
|
21
|
+
};
|
|
22
|
+
teams: {
|
|
23
|
+
transferred: number;
|
|
24
|
+
skipped: number;
|
|
25
|
+
failed: number;
|
|
26
|
+
};
|
|
27
|
+
databases: {
|
|
28
|
+
transferred: number;
|
|
29
|
+
skipped: number;
|
|
30
|
+
failed: number;
|
|
31
|
+
};
|
|
32
|
+
buckets: {
|
|
33
|
+
transferred: number;
|
|
34
|
+
skipped: number;
|
|
35
|
+
failed: number;
|
|
36
|
+
};
|
|
37
|
+
functions: {
|
|
38
|
+
transferred: number;
|
|
39
|
+
skipped: number;
|
|
40
|
+
failed: number;
|
|
41
|
+
};
|
|
42
|
+
totalTime: number;
|
|
43
|
+
}
|
|
44
|
+
export declare class ComprehensiveTransfer {
|
|
45
|
+
private options;
|
|
46
|
+
private sourceClient;
|
|
47
|
+
private targetClient;
|
|
48
|
+
private sourceUsers;
|
|
49
|
+
private targetUsers;
|
|
50
|
+
private sourceTeams;
|
|
51
|
+
private targetTeams;
|
|
52
|
+
private sourceDatabases;
|
|
53
|
+
private targetDatabases;
|
|
54
|
+
private sourceStorage;
|
|
55
|
+
private targetStorage;
|
|
56
|
+
private sourceFunctions;
|
|
57
|
+
private targetFunctions;
|
|
58
|
+
private limit;
|
|
59
|
+
private userLimit;
|
|
60
|
+
private fileLimit;
|
|
61
|
+
private results;
|
|
62
|
+
private startTime;
|
|
63
|
+
private tempDir;
|
|
64
|
+
private cachedMaxFileSize?;
|
|
65
|
+
private sourceAdapter?;
|
|
66
|
+
private targetAdapter?;
|
|
67
|
+
constructor(options: ComprehensiveTransferOptions);
|
|
68
|
+
execute(): Promise<TransferResults>;
|
|
69
|
+
private transferAllUsers;
|
|
70
|
+
private transferAllTeams;
|
|
71
|
+
private transferAllDatabases;
|
|
72
|
+
/**
|
|
73
|
+
* Phase 1: Create database structure (collections, attributes, indexes) without transferring documents
|
|
74
|
+
*/
|
|
75
|
+
private createDatabaseStructure;
|
|
76
|
+
/**
|
|
77
|
+
* Phase 2: Transfer documents to all collections in the database
|
|
78
|
+
*/
|
|
79
|
+
private transferDatabaseDocuments;
|
|
80
|
+
private transferAllBuckets;
|
|
81
|
+
private createBucketWithFallback;
|
|
82
|
+
private transferBucketFiles;
|
|
83
|
+
private validateAndDownloadFile;
|
|
84
|
+
private transferAllFunctions;
|
|
85
|
+
private downloadFunction;
|
|
86
|
+
/**
|
|
87
|
+
* Helper method to fetch all collections from a database
|
|
88
|
+
*/
|
|
89
|
+
private fetchAllCollections;
|
|
90
|
+
/**
|
|
91
|
+
* Helper method to fetch all buckets with pagination
|
|
92
|
+
*/
|
|
93
|
+
private fetchAllBuckets;
|
|
94
|
+
/**
|
|
95
|
+
* Helper method to parse attribute objects (simplified version of parseAttribute)
|
|
96
|
+
*/
|
|
97
|
+
private parseAttribute;
|
|
98
|
+
/**
|
|
99
|
+
* Helper method to create collection attributes with status checking
|
|
100
|
+
*/
|
|
101
|
+
private createCollectionAttributesWithStatusCheck;
|
|
102
|
+
/**
|
|
103
|
+
* Helper method to create collection indexes with status checking
|
|
104
|
+
*/
|
|
105
|
+
private createCollectionIndexesWithStatusCheck;
|
|
106
|
+
/**
|
|
107
|
+
* Helper method to transfer documents between databases using bulk operations with content and permission-based filtering
|
|
108
|
+
*/
|
|
109
|
+
private transferDocumentsBetweenDatabases;
|
|
110
|
+
/**
|
|
111
|
+
* Fetch target documents by IDs in batches to check existence and permissions
|
|
112
|
+
*/
|
|
113
|
+
private fetchTargetDocumentsBatch;
|
|
114
|
+
/**
|
|
115
|
+
* Transfer documents using bulk operations with proper batch size handling
|
|
116
|
+
*/
|
|
117
|
+
private transferDocumentsBulk;
|
|
118
|
+
/**
|
|
119
|
+
* Direct HTTP implementation of bulk upsert API
|
|
120
|
+
*/
|
|
121
|
+
private bulkUpsertDocuments;
|
|
122
|
+
/**
|
|
123
|
+
* Transfer documents individually with rate limiting
|
|
124
|
+
*/
|
|
125
|
+
private transferDocumentsIndividual;
|
|
126
|
+
/**
|
|
127
|
+
* Update documents individually with content and/or permission changes
|
|
128
|
+
*/
|
|
129
|
+
private updateDocumentsIndividual;
|
|
130
|
+
/**
|
|
131
|
+
* Utility method to chunk arrays
|
|
132
|
+
*/
|
|
133
|
+
private chunkArray;
|
|
134
|
+
/**
|
|
135
|
+
* Helper method to fetch all teams with pagination
|
|
136
|
+
*/
|
|
137
|
+
private fetchAllTeams;
|
|
138
|
+
/**
|
|
139
|
+
* Helper method to fetch all memberships for a team with pagination
|
|
140
|
+
*/
|
|
141
|
+
private fetchAllMemberships;
|
|
142
|
+
/**
|
|
143
|
+
* Helper method to transfer team memberships
|
|
144
|
+
*/
|
|
145
|
+
private transferTeamMemberships;
|
|
146
|
+
private printSummary;
|
|
147
|
+
}
|