@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,664 @@
|
|
|
1
|
+
import { SchemaGenerator } from "../shared/schemaGenerator.js";
|
|
2
|
+
import { findYamlConfig } from "../config/yamlConfig.js";
|
|
3
|
+
import {
|
|
4
|
+
Client,
|
|
5
|
+
Compression,
|
|
6
|
+
Databases,
|
|
7
|
+
Query,
|
|
8
|
+
Storage,
|
|
9
|
+
type Models,
|
|
10
|
+
type Permission,
|
|
11
|
+
} from "node-appwrite";
|
|
12
|
+
import { fetchAllCollections } from "../collections/methods.js";
|
|
13
|
+
import { fetchAllDatabases } from "../databases/methods.js";
|
|
14
|
+
import {
|
|
15
|
+
CollectionSchema,
|
|
16
|
+
attributeSchema,
|
|
17
|
+
type AppwriteConfig,
|
|
18
|
+
AppwriteConfigSchema,
|
|
19
|
+
type ConfigDatabases,
|
|
20
|
+
type Attribute,
|
|
21
|
+
permissionsSchema,
|
|
22
|
+
attributesSchema,
|
|
23
|
+
indexesSchema,
|
|
24
|
+
parseAttribute,
|
|
25
|
+
type Runtime,
|
|
26
|
+
type Specification,
|
|
27
|
+
} from "@njdamstra/appwrite-utils";
|
|
28
|
+
import { getDatabaseFromConfig } from "./afterImportActions.js";
|
|
29
|
+
import { getAdapterFromConfig } from "../utils/getClientFromConfig.js";
|
|
30
|
+
import { listBuckets } from "../storage/methods.js";
|
|
31
|
+
import { listFunctions, listFunctionDeployments, getFunction } from "../functions/methods.js";
|
|
32
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
|
33
|
+
import { isLegacyDatabases } from "../utils/typeGuards.js";
|
|
34
|
+
import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
|
|
35
|
+
import type { DatabaseSelection, BucketSelection } from "../shared/selectionDialogs.js";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert between collection and table terminology based on data structure
|
|
39
|
+
*/
|
|
40
|
+
function normalizeCollectionOrTable(collection: any): {
|
|
41
|
+
attributes: any[];
|
|
42
|
+
permissions: any[];
|
|
43
|
+
name: string;
|
|
44
|
+
$id: string;
|
|
45
|
+
enabled: boolean;
|
|
46
|
+
indexes?: any[];
|
|
47
|
+
} {
|
|
48
|
+
// Check if this is a table (has columns) or collection (has attributes)
|
|
49
|
+
const isTable = collection.columns && Array.isArray(collection.columns);
|
|
50
|
+
|
|
51
|
+
if (isTable) {
|
|
52
|
+
// Table structure - convert columns to attributes
|
|
53
|
+
MessageFormatter.debug(`Detected table structure: ${collection.name || collection.tableName}`, { prefix: "Migration" });
|
|
54
|
+
return {
|
|
55
|
+
...collection,
|
|
56
|
+
attributes: collection.columns || [],
|
|
57
|
+
permissions: collection.$permissions || collection.permissions || [],
|
|
58
|
+
name: collection.name || collection.tableName,
|
|
59
|
+
$id: collection.$id || collection.tableId,
|
|
60
|
+
enabled: collection.enabled ?? true
|
|
61
|
+
};
|
|
62
|
+
} else {
|
|
63
|
+
// Collection structure - use as-is with fallbacks
|
|
64
|
+
MessageFormatter.debug(`Detected collection structure: ${collection.name}`, { prefix: "Migration" });
|
|
65
|
+
return {
|
|
66
|
+
...collection,
|
|
67
|
+
attributes: collection.attributes || [],
|
|
68
|
+
permissions: collection.$permissions || collection.permissions || [],
|
|
69
|
+
name: collection.name,
|
|
70
|
+
$id: collection.$id,
|
|
71
|
+
enabled: collection.enabled ?? true
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export class AppwriteToX {
|
|
77
|
+
config: AppwriteConfig;
|
|
78
|
+
storage: Storage;
|
|
79
|
+
updatedConfig: AppwriteConfig;
|
|
80
|
+
collToAttributeMap = new Map<string, Attribute[]>();
|
|
81
|
+
appwriteFolderPath: string;
|
|
82
|
+
adapter?: DatabaseAdapter;
|
|
83
|
+
apiMode?: 'legacy' | 'tablesdb';
|
|
84
|
+
databaseApiModes = new Map<string, 'legacy' | 'tablesdb'>();
|
|
85
|
+
|
|
86
|
+
constructor(
|
|
87
|
+
config: AppwriteConfig,
|
|
88
|
+
appwriteFolderPath: string,
|
|
89
|
+
storage: Storage
|
|
90
|
+
) {
|
|
91
|
+
this.config = config;
|
|
92
|
+
this.updatedConfig = config;
|
|
93
|
+
this.storage = storage;
|
|
94
|
+
this.appwriteFolderPath = appwriteFolderPath;
|
|
95
|
+
this.ensureClientInitialized();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Initialize adapter for database operations with API mode detection
|
|
100
|
+
*/
|
|
101
|
+
private async initializeAdapter(): Promise<void> {
|
|
102
|
+
if (!this.adapter) {
|
|
103
|
+
try {
|
|
104
|
+
const { adapter, apiMode } = await getAdapterFromConfig(this.config);
|
|
105
|
+
this.adapter = adapter;
|
|
106
|
+
this.apiMode = apiMode;
|
|
107
|
+
MessageFormatter.info(`Initialized database adapter with API mode: ${apiMode}`, { prefix: "Migration" });
|
|
108
|
+
} catch (error) {
|
|
109
|
+
MessageFormatter.warning(
|
|
110
|
+
`Failed to initialize adapter, falling back to legacy client: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
111
|
+
{ prefix: "Migration" }
|
|
112
|
+
);
|
|
113
|
+
// Fallback to legacy client initialization
|
|
114
|
+
this.ensureClientInitialized();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private ensureClientInitialized() {
|
|
120
|
+
if (!this.config.appwriteClient) {
|
|
121
|
+
const client = new Client();
|
|
122
|
+
client
|
|
123
|
+
.setEndpoint(this.config.appwriteEndpoint)
|
|
124
|
+
.setProject(this.config.appwriteProject)
|
|
125
|
+
.setKey(this.config.appwriteKey);
|
|
126
|
+
this.config.appwriteClient = client;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Function to parse a single permission string
|
|
131
|
+
parsePermissionString = (permissionString: string) => {
|
|
132
|
+
const match = permissionString.match(/^(\w+)\('([^']+)'\)$/);
|
|
133
|
+
if (!match) {
|
|
134
|
+
throw new Error(`Invalid permission format: ${permissionString}`);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
permission: match[1],
|
|
138
|
+
target: match[2],
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Function to parse an array of permission strings
|
|
143
|
+
parsePermissionsArray = (permissions: string[]) => {
|
|
144
|
+
if (permissions.length === 0) {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
const parsedPermissions = permissionsSchema.parse(permissions);
|
|
148
|
+
// Validate the parsed permissions using Zod
|
|
149
|
+
return parsedPermissions ?? [];
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
updateCollectionConfigAttributes = (collection: Models.Collection) => {
|
|
153
|
+
// Normalize collection/table structure to handle both TablesDB and Legacy formats
|
|
154
|
+
const normalizedCollection = normalizeCollectionOrTable(collection);
|
|
155
|
+
|
|
156
|
+
for (const attribute of normalizedCollection.attributes) {
|
|
157
|
+
if (!attribute) {
|
|
158
|
+
MessageFormatter.warning("Skipping null/undefined attribute in updateCollectionConfigAttributes", { prefix: "Migration" });
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const attributeParsed = attributeSchema.parse(attribute);
|
|
162
|
+
this.collToAttributeMap
|
|
163
|
+
.get(normalizedCollection.name)
|
|
164
|
+
?.push(attributeParsed);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Fetch collections/tables using the appropriate adapter or legacy client
|
|
170
|
+
*/
|
|
171
|
+
private async fetchCollectionsOrTables(databaseId: string, db: any): Promise<Models.Collection[]> {
|
|
172
|
+
// Try to use adapter first
|
|
173
|
+
if (this.adapter) {
|
|
174
|
+
try {
|
|
175
|
+
const result = await this.adapter.listTables({ databaseId });
|
|
176
|
+
const items = (result as any).tables || result.collections || [];
|
|
177
|
+
MessageFormatter.info(`Fetched ${items.length} items using ${this.apiMode} adapter`, { prefix: "Migration" });
|
|
178
|
+
return items as Models.Collection[];
|
|
179
|
+
} catch (error) {
|
|
180
|
+
MessageFormatter.warning(
|
|
181
|
+
`Adapter fetch failed, falling back to legacy: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
182
|
+
{ prefix: "Migration" }
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Fallback to legacy method
|
|
188
|
+
try {
|
|
189
|
+
const collections = await fetchAllCollections(databaseId, db);
|
|
190
|
+
MessageFormatter.info(`Fetched ${collections.length} collections using legacy client`, { prefix: "Migration" });
|
|
191
|
+
return collections;
|
|
192
|
+
} catch (error) {
|
|
193
|
+
MessageFormatter.error(
|
|
194
|
+
"Failed to fetch collections with both adapter and legacy methods",
|
|
195
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
196
|
+
{ prefix: "Migration" }
|
|
197
|
+
);
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Get collection/table using the appropriate adapter or legacy client
|
|
204
|
+
*/
|
|
205
|
+
private async getCollectionOrTable(databaseId: string, collectionId: string): Promise<Models.Collection> {
|
|
206
|
+
// Try to use adapter first
|
|
207
|
+
if (this.adapter) {
|
|
208
|
+
try {
|
|
209
|
+
const result = await this.adapter.getTable({ databaseId, tableId: collectionId });
|
|
210
|
+
return result as Models.Collection;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
MessageFormatter.warning(
|
|
213
|
+
`Adapter get failed, falling back to legacy: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
214
|
+
{ prefix: "Migration" }
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Fallback to legacy method
|
|
220
|
+
const db = getDatabaseFromConfig(this.config);
|
|
221
|
+
return await db.getCollection(databaseId, collectionId);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Detect API mode for a specific database by testing adapter capabilities
|
|
226
|
+
*/
|
|
227
|
+
private async detectDatabaseApiMode(databaseId: string): Promise<'legacy' | 'tablesdb'> {
|
|
228
|
+
// If we already detected this database, return cached result
|
|
229
|
+
if (this.databaseApiModes.has(databaseId)) {
|
|
230
|
+
return this.databaseApiModes.get(databaseId)!;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// If we have a global adapter, use its API mode as default
|
|
234
|
+
if (this.apiMode) {
|
|
235
|
+
this.databaseApiModes.set(databaseId, this.apiMode);
|
|
236
|
+
MessageFormatter.debug(`Using global API mode for database ${databaseId}: ${this.apiMode}`, { prefix: "Migration" });
|
|
237
|
+
return this.apiMode;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Default to legacy if no adapter available
|
|
241
|
+
const defaultMode = 'legacy';
|
|
242
|
+
this.databaseApiModes.set(databaseId, defaultMode);
|
|
243
|
+
MessageFormatter.debug(`Defaulting to legacy mode for database ${databaseId}`, { prefix: "Migration" });
|
|
244
|
+
return defaultMode;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Get API mode context for schema generation
|
|
249
|
+
*/
|
|
250
|
+
private getSchemaGeneratorApiContext(): any {
|
|
251
|
+
const databaseModes: Record<string, 'legacy' | 'tablesdb'> = {};
|
|
252
|
+
|
|
253
|
+
// Get API mode for each database
|
|
254
|
+
for (const db of this.updatedConfig.databases || []) {
|
|
255
|
+
const apiMode = this.databaseApiModes.get(db.$id) || this.apiMode || 'legacy';
|
|
256
|
+
databaseModes[db.$id] = apiMode;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
apiMode: this.apiMode || 'legacy',
|
|
261
|
+
databaseApiModes: databaseModes,
|
|
262
|
+
adapterMetadata: this.adapter?.getMetadata()
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async appwriteSync(
|
|
267
|
+
config: AppwriteConfig,
|
|
268
|
+
databases?: Models.Database[],
|
|
269
|
+
databaseSelections?: DatabaseSelection[],
|
|
270
|
+
bucketSelections?: BucketSelection[]
|
|
271
|
+
) {
|
|
272
|
+
// Initialize adapter for proper API mode detection and usage
|
|
273
|
+
await this.initializeAdapter();
|
|
274
|
+
|
|
275
|
+
const db = getDatabaseFromConfig(config);
|
|
276
|
+
if (!databases) {
|
|
277
|
+
try {
|
|
278
|
+
MessageFormatter.info("Fetching remote databases...", { prefix: "Migration" });
|
|
279
|
+
databases = await fetchAllDatabases(db);
|
|
280
|
+
MessageFormatter.info(`Found ${databases.length} remote databases`, { prefix: "Migration" });
|
|
281
|
+
} catch (error) {
|
|
282
|
+
MessageFormatter.error(
|
|
283
|
+
"Failed to fetch remote databases",
|
|
284
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
285
|
+
{ prefix: "Migration" }
|
|
286
|
+
);
|
|
287
|
+
throw new Error(`Database fetch failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Filter databases based on selection if provided
|
|
292
|
+
let databasesToProcess = databases;
|
|
293
|
+
if (databaseSelections && databaseSelections.length > 0) {
|
|
294
|
+
databasesToProcess = databases?.filter(db =>
|
|
295
|
+
databaseSelections.some(selection => selection.databaseId === db.$id)
|
|
296
|
+
) || [];
|
|
297
|
+
MessageFormatter.info(`Filtered to ${databasesToProcess.length} selected databases`, { prefix: "Migration" });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
let updatedConfig: AppwriteConfig = { ...config };
|
|
301
|
+
|
|
302
|
+
// Initialize databases array if it doesn't exist
|
|
303
|
+
if (!updatedConfig.databases) {
|
|
304
|
+
updatedConfig.databases = [];
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Sync remote databases to local config - add missing ones
|
|
308
|
+
MessageFormatter.info(`Syncing ${databasesToProcess.length} remote databases with local config...`, { prefix: "Migration" });
|
|
309
|
+
let addedCount = 0;
|
|
310
|
+
let updatedCount = 0;
|
|
311
|
+
|
|
312
|
+
for (const remoteDb of databasesToProcess) {
|
|
313
|
+
// Check if this database already exists in the config
|
|
314
|
+
const existingDbIndex = updatedConfig.databases.findIndex(
|
|
315
|
+
(localDb) => localDb.$id === remoteDb.$id
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
if (existingDbIndex === -1) {
|
|
319
|
+
// Database doesn't exist locally, add it
|
|
320
|
+
MessageFormatter.success(`Adding new database to config: ${remoteDb.name} (${remoteDb.$id})`, { prefix: "Migration" });
|
|
321
|
+
updatedConfig.databases.push({
|
|
322
|
+
$id: remoteDb.$id,
|
|
323
|
+
name: remoteDb.name,
|
|
324
|
+
});
|
|
325
|
+
addedCount++;
|
|
326
|
+
} else {
|
|
327
|
+
// Database exists, update name if different
|
|
328
|
+
if (updatedConfig.databases[existingDbIndex].name !== remoteDb.name) {
|
|
329
|
+
MessageFormatter.info(`Updating database name: ${updatedConfig.databases[existingDbIndex].name} -> ${remoteDb.name}`, { prefix: "Migration" });
|
|
330
|
+
updatedConfig.databases[existingDbIndex].name = remoteDb.name;
|
|
331
|
+
updatedCount++;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
MessageFormatter.success(`Database sync summary: ${addedCount} added, ${updatedCount} updated, ${updatedConfig.databases.length} total`, { prefix: "Migration" });
|
|
337
|
+
|
|
338
|
+
// Fetch all buckets
|
|
339
|
+
const allBuckets = await listBuckets(this.storage);
|
|
340
|
+
|
|
341
|
+
// Filter buckets based on selection if provided
|
|
342
|
+
let matchedBuckets = allBuckets.buckets;
|
|
343
|
+
if (bucketSelections && bucketSelections.length > 0) {
|
|
344
|
+
matchedBuckets = allBuckets.buckets.filter(bucket =>
|
|
345
|
+
bucketSelections.some(selection => selection.bucketId === bucket.$id)
|
|
346
|
+
);
|
|
347
|
+
MessageFormatter.info(`Filtered to ${matchedBuckets.length} selected buckets`, { prefix: "Migration" });
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Loop through each database
|
|
351
|
+
for (const database of databasesToProcess) {
|
|
352
|
+
// Detect API mode for this specific database
|
|
353
|
+
const dbApiMode = await this.detectDatabaseApiMode(database.$id);
|
|
354
|
+
MessageFormatter.info(`Processing database '${database.name}' with API mode: ${dbApiMode}`, { prefix: "Migration" });
|
|
355
|
+
|
|
356
|
+
// Match bucket to database (from filtered buckets if selections provided)
|
|
357
|
+
const matchedBucket = matchedBuckets.find((bucket) =>
|
|
358
|
+
bucket.$id.toLowerCase().includes(database.$id.toLowerCase())
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
if (matchedBucket) {
|
|
362
|
+
const dbConfig = updatedConfig.databases.find(
|
|
363
|
+
(db) => db.$id === database.$id
|
|
364
|
+
);
|
|
365
|
+
if (dbConfig) {
|
|
366
|
+
dbConfig.bucket = {
|
|
367
|
+
$id: matchedBucket.$id,
|
|
368
|
+
name: matchedBucket.name,
|
|
369
|
+
enabled: matchedBucket.enabled,
|
|
370
|
+
maximumFileSize: matchedBucket.maximumFileSize,
|
|
371
|
+
allowedFileExtensions: matchedBucket.allowedFileExtensions,
|
|
372
|
+
compression: matchedBucket.compression as Compression,
|
|
373
|
+
encryption: matchedBucket.encryption,
|
|
374
|
+
antivirus: matchedBucket.antivirus,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Use adapter-aware collection/table fetching with proper API mode detection
|
|
380
|
+
const collections = await this.fetchCollectionsOrTables(database.$id, db);
|
|
381
|
+
|
|
382
|
+
// Filter collections based on table selection if provided
|
|
383
|
+
let collectionsToProcess = collections;
|
|
384
|
+
if (databaseSelections && databaseSelections.length > 0) {
|
|
385
|
+
const dbSelection = databaseSelections.find(selection => selection.databaseId === database.$id);
|
|
386
|
+
if (dbSelection && dbSelection.tableIds.length > 0) {
|
|
387
|
+
collectionsToProcess = collections.filter(collection =>
|
|
388
|
+
dbSelection.tableIds.includes(collection.$id)
|
|
389
|
+
);
|
|
390
|
+
MessageFormatter.info(`Filtered to ${collectionsToProcess.length} selected tables for database '${database.name}'`, { prefix: "Migration" });
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Loop through each collection in the current database
|
|
395
|
+
if (!updatedConfig.collections) {
|
|
396
|
+
updatedConfig.collections = [];
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
MessageFormatter.info(`Processing ${collectionsToProcess.length} collections/tables in database '${database.name}'`, { prefix: "Migration" });
|
|
400
|
+
let processedCount = 0;
|
|
401
|
+
let errorCount = 0;
|
|
402
|
+
|
|
403
|
+
for (const collection of collectionsToProcess) {
|
|
404
|
+
try {
|
|
405
|
+
if (!collection) {
|
|
406
|
+
MessageFormatter.warning("Skipping null/undefined collection", { prefix: "Migration" });
|
|
407
|
+
errorCount++;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Normalize collection/table structure to handle both TablesDB and Legacy formats
|
|
412
|
+
const normalizedCollection = normalizeCollectionOrTable(collection);
|
|
413
|
+
|
|
414
|
+
MessageFormatter.processing(`Processing ${normalizedCollection.name} (${normalizedCollection.$id})`, { prefix: "Migration" });
|
|
415
|
+
const existingCollectionIndex = updatedConfig.collections.findIndex(
|
|
416
|
+
(c) => c.name === normalizedCollection.name
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// Parse the collection permissions and attributes using normalized structure
|
|
420
|
+
const collPermissions = this.parsePermissionsArray(
|
|
421
|
+
normalizedCollection.permissions
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
// Process attributes with proper error handling
|
|
425
|
+
let collAttributes: Attribute[] = [];
|
|
426
|
+
try {
|
|
427
|
+
collAttributes = normalizedCollection.attributes
|
|
428
|
+
.map((attr: any) => {
|
|
429
|
+
if (!attr) {
|
|
430
|
+
MessageFormatter.warning("Skipping null/undefined attribute", { prefix: "Migration" });
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
return parseAttribute(attr);
|
|
434
|
+
})
|
|
435
|
+
.filter((attribute: Attribute | null): attribute is Attribute =>
|
|
436
|
+
attribute !== null &&
|
|
437
|
+
(attribute.type !== "relationship" ? true : attribute.side !== "child")
|
|
438
|
+
);
|
|
439
|
+
} catch (error) {
|
|
440
|
+
MessageFormatter.error(
|
|
441
|
+
`Error processing attributes for ${normalizedCollection.name}`,
|
|
442
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
443
|
+
{ prefix: "Migration" }
|
|
444
|
+
);
|
|
445
|
+
// Continue with empty attributes array
|
|
446
|
+
collAttributes = [];
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
for (const attribute of collAttributes) {
|
|
450
|
+
if (
|
|
451
|
+
attribute.type === "relationship" &&
|
|
452
|
+
attribute.relatedCollection
|
|
453
|
+
) {
|
|
454
|
+
MessageFormatter.info(
|
|
455
|
+
`Fetching related collection for ID: ${attribute.relatedCollection}`,
|
|
456
|
+
{ prefix: "Migration" }
|
|
457
|
+
);
|
|
458
|
+
try {
|
|
459
|
+
const relatedCollectionPulled = await this.getCollectionOrTable(
|
|
460
|
+
database.$id,
|
|
461
|
+
attribute.relatedCollection
|
|
462
|
+
);
|
|
463
|
+
MessageFormatter.info(
|
|
464
|
+
`Fetched Collection Name: ${relatedCollectionPulled.name}`,
|
|
465
|
+
{ prefix: "Migration" }
|
|
466
|
+
);
|
|
467
|
+
attribute.relatedCollection = relatedCollectionPulled.name;
|
|
468
|
+
MessageFormatter.info(
|
|
469
|
+
`Updated attribute.relatedCollection to: ${attribute.relatedCollection}`,
|
|
470
|
+
{ prefix: "Migration" }
|
|
471
|
+
);
|
|
472
|
+
} catch (error) {
|
|
473
|
+
MessageFormatter.error(
|
|
474
|
+
"Error fetching related collection",
|
|
475
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
476
|
+
{ prefix: "Migration" }
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
this.collToAttributeMap.set(normalizedCollection.name, collAttributes);
|
|
482
|
+
|
|
483
|
+
// Process indexes with proper error handling using normalized collection
|
|
484
|
+
let collIndexes: any[] = [];
|
|
485
|
+
try {
|
|
486
|
+
const finalIndexes = (normalizedCollection.indexes || collection.indexes || []).map((index: any) => {
|
|
487
|
+
if (!index) {
|
|
488
|
+
MessageFormatter.warning("Skipping null/undefined index", { prefix: "Migration" });
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
return {
|
|
492
|
+
...index,
|
|
493
|
+
// Convert TablesDB 'columns' to expected 'attributes' for schema validation
|
|
494
|
+
attributes: index.attributes || index.columns || [],
|
|
495
|
+
orders: index.orders?.filter((order: string) => {
|
|
496
|
+
return order !== null && order;
|
|
497
|
+
}),
|
|
498
|
+
};
|
|
499
|
+
}).filter((index: any): index is any => index !== null);
|
|
500
|
+
|
|
501
|
+
collIndexes = indexesSchema.parse(finalIndexes) ?? [];
|
|
502
|
+
} catch (error) {
|
|
503
|
+
MessageFormatter.error(
|
|
504
|
+
`Error processing indexes for ${normalizedCollection.name}`,
|
|
505
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
506
|
+
{ prefix: "Migration" }
|
|
507
|
+
);
|
|
508
|
+
// Continue with empty indexes array
|
|
509
|
+
collIndexes = [];
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Prepare the collection object to be added or updated using normalized data
|
|
513
|
+
const collToPush = CollectionSchema.parse({
|
|
514
|
+
$id: normalizedCollection.$id,
|
|
515
|
+
name: normalizedCollection.name,
|
|
516
|
+
enabled: normalizedCollection.enabled,
|
|
517
|
+
documentSecurity: collection.documentSecurity, // Use original collection for this field
|
|
518
|
+
$createdAt: collection.$createdAt, // Use original collection for timestamps
|
|
519
|
+
$updatedAt: collection.$updatedAt,
|
|
520
|
+
$permissions:
|
|
521
|
+
collPermissions.length > 0 ? collPermissions : undefined,
|
|
522
|
+
indexes: collIndexes.length > 0 ? collIndexes : undefined,
|
|
523
|
+
attributes: collAttributes.length > 0 ? collAttributes : undefined,
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
if (existingCollectionIndex !== -1) {
|
|
527
|
+
// Update existing collection
|
|
528
|
+
updatedConfig.collections[existingCollectionIndex] = collToPush;
|
|
529
|
+
MessageFormatter.debug(`Updated existing collection: ${normalizedCollection.name}`, { prefix: "Migration" });
|
|
530
|
+
} else {
|
|
531
|
+
// Add new collection
|
|
532
|
+
updatedConfig.collections.push(collToPush);
|
|
533
|
+
MessageFormatter.debug(`Added new collection: ${normalizedCollection.name}`, { prefix: "Migration" });
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
processedCount++;
|
|
537
|
+
} catch (error) {
|
|
538
|
+
MessageFormatter.error(
|
|
539
|
+
`Error processing collection: ${collection?.name || 'unknown'}`,
|
|
540
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
541
|
+
{ prefix: "Migration" }
|
|
542
|
+
);
|
|
543
|
+
errorCount++;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
MessageFormatter.success(
|
|
548
|
+
`Database '${database.name}' processing complete: ${processedCount} collections processed, ${errorCount} errors`,
|
|
549
|
+
{ prefix: "Migration" }
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
// Add unmatched buckets as global buckets
|
|
553
|
+
// Use filtered buckets if selections provided, otherwise use all buckets
|
|
554
|
+
const sourceBuckets = bucketSelections && bucketSelections.length > 0 ? matchedBuckets : allBuckets.buckets;
|
|
555
|
+
const globalBuckets = sourceBuckets.filter(
|
|
556
|
+
(bucket) =>
|
|
557
|
+
!updatedConfig.databases.some(
|
|
558
|
+
(db) => db.bucket && db.bucket.$id === bucket.$id
|
|
559
|
+
)
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
updatedConfig.buckets = globalBuckets.map((bucket) => ({
|
|
563
|
+
$id: bucket.$id,
|
|
564
|
+
name: bucket.name,
|
|
565
|
+
enabled: bucket.enabled,
|
|
566
|
+
maximumFileSize: bucket.maximumFileSize,
|
|
567
|
+
allowedFileExtensions: bucket.allowedFileExtensions,
|
|
568
|
+
compression: bucket.compression as Compression,
|
|
569
|
+
encryption: bucket.encryption,
|
|
570
|
+
antivirus: bucket.antivirus,
|
|
571
|
+
}));
|
|
572
|
+
|
|
573
|
+
const remoteFunctions = await listFunctions(this.config.appwriteClient!, [
|
|
574
|
+
Query.limit(1000),
|
|
575
|
+
]);
|
|
576
|
+
|
|
577
|
+
// Fetch full details per function to ensure 'scopes' and other fields are present
|
|
578
|
+
const detailedFunctions: any[] = [];
|
|
579
|
+
for (const f of remoteFunctions.functions) {
|
|
580
|
+
try {
|
|
581
|
+
const full = await getFunction(this.config.appwriteClient!, f.$id);
|
|
582
|
+
detailedFunctions.push(full);
|
|
583
|
+
} catch {
|
|
584
|
+
detailedFunctions.push(f);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
this.updatedConfig.functions = detailedFunctions.map(
|
|
589
|
+
(func: any) => ({
|
|
590
|
+
$id: func.$id,
|
|
591
|
+
name: func.name,
|
|
592
|
+
runtime: func.runtime as Runtime,
|
|
593
|
+
execute: func.execute,
|
|
594
|
+
events: func.events || [],
|
|
595
|
+
schedule: func.schedule || "",
|
|
596
|
+
timeout: func.timeout || 15,
|
|
597
|
+
enabled: func.enabled !== false,
|
|
598
|
+
logging: func.logging !== false,
|
|
599
|
+
entrypoint: func.entrypoint || "src/index.ts",
|
|
600
|
+
commands: func.commands || "npm install",
|
|
601
|
+
scopes: Array.isArray(func.scopes) ? func.scopes : [],
|
|
602
|
+
dirPath: `functions/${func.name}`,
|
|
603
|
+
specification: func.specification as Specification,
|
|
604
|
+
})
|
|
605
|
+
);
|
|
606
|
+
|
|
607
|
+
// Make sure to update the config with all changes including databases
|
|
608
|
+
updatedConfig.functions = this.updatedConfig.functions;
|
|
609
|
+
this.updatedConfig = updatedConfig;
|
|
610
|
+
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" });
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
async toSchemas(
|
|
614
|
+
databases?: Models.Database[],
|
|
615
|
+
databaseSelections?: DatabaseSelection[],
|
|
616
|
+
bucketSelections?: BucketSelection[]
|
|
617
|
+
) {
|
|
618
|
+
try {
|
|
619
|
+
MessageFormatter.info("Starting sync-from-Appwrite process...", { prefix: "Migration" });
|
|
620
|
+
await this.appwriteSync(this.config, databases, databaseSelections, bucketSelections);
|
|
621
|
+
|
|
622
|
+
const generator = new SchemaGenerator(
|
|
623
|
+
this.updatedConfig,
|
|
624
|
+
this.appwriteFolderPath
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
// Pass API mode context to the schema generator
|
|
628
|
+
const apiContext = this.getSchemaGeneratorApiContext();
|
|
629
|
+
|
|
630
|
+
// Extend the config with API mode information for schema generation
|
|
631
|
+
const configWithApiContext = {
|
|
632
|
+
...this.updatedConfig,
|
|
633
|
+
apiMode: apiContext.apiMode,
|
|
634
|
+
databaseApiModes: apiContext.databaseApiModes,
|
|
635
|
+
adapterMetadata: apiContext.adapterMetadata
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// Check if this is a YAML-based project
|
|
639
|
+
const yamlConfigPath = findYamlConfig(this.appwriteFolderPath);
|
|
640
|
+
const isYamlProject = !!yamlConfigPath;
|
|
641
|
+
|
|
642
|
+
if (isYamlProject) {
|
|
643
|
+
MessageFormatter.info("Detected YAML configuration - generating YAML collection definitions", { prefix: "Migration" });
|
|
644
|
+
generator.updateYamlCollections();
|
|
645
|
+
await generator.updateConfig(configWithApiContext, true);
|
|
646
|
+
} else {
|
|
647
|
+
MessageFormatter.info("Generating TypeScript collection definitions", { prefix: "Migration" });
|
|
648
|
+
generator.updateTsSchemas();
|
|
649
|
+
await generator.updateConfig(configWithApiContext, false);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
MessageFormatter.info("Generating Zod schemas from synced collections...", { prefix: "Migration" });
|
|
653
|
+
await generator.generateSchemas();
|
|
654
|
+
MessageFormatter.success("Sync-from-Appwrite process completed successfully", { prefix: "Migration" });
|
|
655
|
+
} catch (error) {
|
|
656
|
+
MessageFormatter.error(
|
|
657
|
+
"Error during sync-from-Appwrite process",
|
|
658
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
659
|
+
{ prefix: "Migration" }
|
|
660
|
+
);
|
|
661
|
+
throw error;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|