appwrite-utils-cli 1.9.7 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONFIG_TODO.md +1189 -1189
- package/README.md +1004 -1004
- package/SELECTION_DIALOGS.md +145 -145
- package/SERVICE_IMPLEMENTATION_REPORT.md +462 -462
- package/package.json +6 -3
- package/scripts/copy-templates.ts +23 -23
- package/src/adapters/index.ts +11 -37
- package/src/backups/operations/bucketBackup.ts +277 -277
- package/src/backups/operations/collectionBackup.ts +310 -310
- package/src/backups/operations/comprehensiveBackup.ts +342 -342
- package/src/backups/schemas/bucketManifest.ts +78 -78
- package/src/backups/schemas/comprehensiveManifest.ts +76 -76
- package/src/backups/tracking/centralizedTracking.ts +352 -352
- package/src/cli/commands/configCommands.ts +265 -201
- package/src/cli/commands/databaseCommands.ts +931 -879
- package/src/cli/commands/functionCommands.ts +333 -332
- package/src/cli/commands/importFileCommands.ts +815 -0
- package/src/cli/commands/schemaCommands.ts +141 -141
- package/src/cli/commands/storageCommands.ts +2 -3
- package/src/cli/commands/transferCommands.ts +454 -457
- package/src/collections/attributes.ts.backup +1555 -1555
- package/src/collections/{attributes.ts → columns.ts} +15 -10
- package/src/collections/indexes.ts +350 -352
- package/src/collections/methods.ts +714 -700
- package/src/collections/tableOperations.ts +29 -8
- package/src/collections/transferOperations.ts +376 -377
- package/src/collections/wipeOperations.ts +449 -346
- package/src/databases/methods.ts +49 -49
- package/src/databases/setup.ts +77 -77
- package/src/examples/yamlTerminologyExample.ts +346 -346
- package/src/functions/deployments.ts +221 -220
- package/src/functions/fnConfigDiscovery.ts +2 -2
- package/src/functions/methods.ts +284 -284
- package/src/functions/templates/count-docs-in-collection/README.md +53 -53
- package/src/functions/templates/count-docs-in-collection/src/main.ts +159 -159
- package/src/functions/templates/count-docs-in-collection/src/request.ts +8 -8
- package/src/functions/templates/hono-typescript/README.md +285 -285
- package/src/functions/templates/hono-typescript/src/adapters/request.ts +73 -73
- package/src/functions/templates/hono-typescript/src/adapters/response.ts +105 -105
- package/src/functions/templates/hono-typescript/src/app.ts +179 -179
- package/src/functions/templates/hono-typescript/src/context.ts +102 -102
- package/src/functions/templates/hono-typescript/src/{index.ts → main.ts} +53 -53
- package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +118 -118
- package/src/functions/templates/typescript-node/README.md +31 -31
- package/src/functions/templates/typescript-node/src/context.ts +102 -102
- package/src/functions/templates/typescript-node/src/{index.ts → main.ts} +29 -29
- package/src/functions/templates/uv/README.md +30 -30
- package/src/functions/templates/uv/pyproject.toml +29 -29
- package/src/functions/templates/uv/src/context.py +124 -124
- package/src/functions/templates/uv/src/{index.py → main.py} +45 -45
- package/src/init.ts +62 -62
- package/src/interactiveCLI.ts +1095 -1030
- package/src/main.ts +1517 -1670
- package/src/migrations/afterImportActions.ts +579 -580
- package/src/migrations/appwriteToX.ts +634 -630
- package/src/migrations/comprehensiveTransfer.ts +2149 -2149
- package/src/migrations/dataLoader.ts +1729 -1702
- package/src/migrations/importController.ts +440 -428
- package/src/migrations/importDataActions.ts +315 -315
- package/src/migrations/relationships.ts +333 -334
- package/src/migrations/services/DataTransformationService.ts +195 -195
- package/src/migrations/services/FileHandlerService.ts +310 -310
- package/src/migrations/services/ImportOrchestrator.ts +674 -665
- package/src/migrations/services/RateLimitManager.ts +362 -362
- package/src/migrations/services/RelationshipResolver.ts +460 -460
- package/src/migrations/services/UserMappingService.ts +344 -344
- package/src/migrations/services/ValidationService.ts +333 -333
- package/src/migrations/transfer.ts +987 -942
- package/src/migrations/yaml/YamlImportConfigLoader.ts +438 -438
- package/src/migrations/yaml/YamlImportIntegration.ts +438 -438
- package/src/migrations/yaml/generateImportSchemas.ts +1347 -1347
- package/src/schemas/authUser.ts +23 -23
- package/src/setup.ts +8 -8
- package/src/setupCommands.ts +5 -6
- package/src/setupController.ts +42 -42
- package/src/shared/backupMetadataSchema.ts +93 -93
- package/src/shared/backupTracking.ts +211 -211
- package/src/shared/confirmationDialogs.ts +326 -326
- package/src/shared/migrationHelpers.ts +232 -232
- package/src/shared/operationLogger.ts +20 -20
- package/src/shared/operationQueue.ts +326 -327
- package/src/shared/operationsTable.ts +338 -338
- package/src/shared/operationsTableSchema.ts +60 -60
- package/src/shared/progressManager.ts +277 -277
- package/src/shared/relationshipExtractor.ts +214 -214
- package/src/shared/selectionDialogs.ts +775 -722
- package/src/storage/backupCompression.ts +88 -88
- package/src/storage/methods.ts +695 -682
- package/src/storage/schemas.ts +205 -205
- package/src/tables/indexManager.ts +408 -408
- package/src/types/node-appwrite-tablesdb.d.ts +43 -43
- package/src/types.ts +9 -9
- package/src/users/methods.ts +358 -359
- package/src/utils/configMigration.ts +347 -347
- package/src/utils/index.ts +2 -2
- package/src/utils/loadConfigs.ts +457 -449
- package/src/utils/setupFiles.ts +1236 -1238
- package/src/utilsController.ts +1263 -1213
- package/tests/README.md +496 -496
- package/tests/adapters/AdapterFactory.test.ts +276 -276
- package/tests/integration/syncOperations.test.ts +462 -462
- package/tests/jest.config.js +24 -24
- package/tests/migration/configMigration.test.ts +545 -545
- package/tests/setup.ts +61 -61
- package/tests/testUtils.ts +339 -339
- package/tests/utils/loadConfigs.test.ts +349 -349
- package/tests/validation/configValidation.test.ts +411 -411
- package/tsconfig.json +44 -44
- package/.appwrite/.yaml_schemas/appwrite-config.schema.json +0 -380
- package/.appwrite/.yaml_schemas/collection.schema.json +0 -255
- package/.appwrite/collections/Categories.yaml +0 -182
- package/.appwrite/collections/ExampleCollection.yaml +0 -36
- package/.appwrite/collections/Posts.yaml +0 -227
- package/.appwrite/collections/Users.yaml +0 -149
- package/.appwrite/config.yaml +0 -109
- package/.appwrite/import/README.md +0 -148
- package/.appwrite/import/categories-import.yaml +0 -129
- package/.appwrite/import/posts-import.yaml +0 -208
- package/.appwrite/import/users-import.yaml +0 -130
- package/.appwrite/importData/categories.json +0 -194
- package/.appwrite/importData/posts.json +0 -270
- package/.appwrite/importData/users.json +0 -220
- package/.appwrite/schemas/categories.json +0 -128
- package/.appwrite/schemas/exampleCollection.json +0 -52
- package/.appwrite/schemas/posts.json +0 -173
- package/.appwrite/schemas/users.json +0 -125
- package/dist/adapters/AdapterFactory.d.ts +0 -94
- package/dist/adapters/AdapterFactory.js +0 -420
- package/dist/adapters/DatabaseAdapter.d.ts +0 -243
- package/dist/adapters/DatabaseAdapter.js +0 -50
- package/dist/adapters/LegacyAdapter.d.ts +0 -50
- package/dist/adapters/LegacyAdapter.js +0 -615
- package/dist/adapters/TablesDBAdapter.d.ts +0 -45
- package/dist/adapters/TablesDBAdapter.js +0 -611
- package/dist/adapters/index.d.ts +0 -11
- package/dist/adapters/index.js +0 -12
- package/dist/backups/operations/bucketBackup.d.ts +0 -19
- package/dist/backups/operations/bucketBackup.js +0 -197
- package/dist/backups/operations/collectionBackup.d.ts +0 -30
- package/dist/backups/operations/collectionBackup.js +0 -201
- package/dist/backups/operations/comprehensiveBackup.d.ts +0 -25
- package/dist/backups/operations/comprehensiveBackup.js +0 -238
- package/dist/backups/schemas/bucketManifest.d.ts +0 -93
- package/dist/backups/schemas/bucketManifest.js +0 -33
- package/dist/backups/schemas/comprehensiveManifest.d.ts +0 -108
- package/dist/backups/schemas/comprehensiveManifest.js +0 -32
- package/dist/backups/tracking/centralizedTracking.d.ts +0 -34
- package/dist/backups/tracking/centralizedTracking.js +0 -274
- package/dist/cli/commands/configCommands.d.ts +0 -8
- package/dist/cli/commands/configCommands.js +0 -166
- package/dist/cli/commands/databaseCommands.d.ts +0 -14
- package/dist/cli/commands/databaseCommands.js +0 -644
- package/dist/cli/commands/functionCommands.d.ts +0 -7
- package/dist/cli/commands/functionCommands.js +0 -330
- package/dist/cli/commands/schemaCommands.d.ts +0 -7
- package/dist/cli/commands/schemaCommands.js +0 -169
- package/dist/cli/commands/storageCommands.d.ts +0 -5
- package/dist/cli/commands/storageCommands.js +0 -143
- package/dist/cli/commands/transferCommands.d.ts +0 -5
- package/dist/cli/commands/transferCommands.js +0 -384
- package/dist/collections/attributes.d.ts +0 -13
- package/dist/collections/attributes.js +0 -1333
- package/dist/collections/indexes.d.ts +0 -12
- package/dist/collections/indexes.js +0 -217
- package/dist/collections/methods.d.ts +0 -19
- package/dist/collections/methods.js +0 -587
- package/dist/collections/tableOperations.d.ts +0 -86
- package/dist/collections/tableOperations.js +0 -447
- package/dist/collections/transferOperations.d.ts +0 -8
- package/dist/collections/transferOperations.js +0 -412
- package/dist/collections/wipeOperations.d.ts +0 -16
- package/dist/collections/wipeOperations.js +0 -233
- package/dist/config/ConfigManager.d.ts +0 -450
- package/dist/config/ConfigManager.js +0 -650
- package/dist/config/configMigration.d.ts +0 -87
- package/dist/config/configMigration.js +0 -390
- package/dist/config/configValidation.d.ts +0 -66
- package/dist/config/configValidation.js +0 -358
- package/dist/config/index.d.ts +0 -8
- package/dist/config/index.js +0 -7
- package/dist/config/services/ConfigDiscoveryService.d.ts +0 -122
- package/dist/config/services/ConfigDiscoveryService.js +0 -322
- package/dist/config/services/ConfigLoaderService.d.ts +0 -129
- package/dist/config/services/ConfigLoaderService.js +0 -535
- package/dist/config/services/ConfigMergeService.d.ts +0 -208
- package/dist/config/services/ConfigMergeService.js +0 -308
- package/dist/config/services/ConfigValidationService.d.ts +0 -214
- package/dist/config/services/ConfigValidationService.js +0 -310
- package/dist/config/services/SessionAuthService.d.ts +0 -225
- package/dist/config/services/SessionAuthService.js +0 -456
- package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +0 -1
- package/dist/config/services/__tests__/ConfigMergeService.test.js +0 -271
- package/dist/config/services/index.d.ts +0 -13
- package/dist/config/services/index.js +0 -10
- package/dist/config/yamlConfig.d.ts +0 -722
- package/dist/config/yamlConfig.js +0 -702
- package/dist/databases/methods.d.ts +0 -6
- package/dist/databases/methods.js +0 -35
- package/dist/databases/setup.d.ts +0 -5
- package/dist/databases/setup.js +0 -45
- package/dist/examples/yamlTerminologyExample.d.ts +0 -42
- package/dist/examples/yamlTerminologyExample.js +0 -272
- package/dist/functions/deployments.d.ts +0 -4
- package/dist/functions/deployments.js +0 -146
- package/dist/functions/fnConfigDiscovery.d.ts +0 -3
- package/dist/functions/fnConfigDiscovery.js +0 -108
- package/dist/functions/methods.d.ts +0 -16
- package/dist/functions/methods.js +0 -174
- package/dist/functions/pathResolution.d.ts +0 -37
- package/dist/functions/pathResolution.js +0 -185
- package/dist/functions/templates/count-docs-in-collection/README.md +0 -54
- package/dist/functions/templates/count-docs-in-collection/package.json +0 -25
- package/dist/functions/templates/count-docs-in-collection/src/main.ts +0 -159
- package/dist/functions/templates/count-docs-in-collection/src/request.ts +0 -9
- package/dist/functions/templates/count-docs-in-collection/tsconfig.json +0 -28
- package/dist/functions/templates/hono-typescript/README.md +0 -286
- package/dist/functions/templates/hono-typescript/package.json +0 -26
- package/dist/functions/templates/hono-typescript/src/adapters/request.ts +0 -74
- package/dist/functions/templates/hono-typescript/src/adapters/response.ts +0 -106
- package/dist/functions/templates/hono-typescript/src/app.ts +0 -180
- package/dist/functions/templates/hono-typescript/src/context.ts +0 -103
- package/dist/functions/templates/hono-typescript/src/index.ts +0 -54
- package/dist/functions/templates/hono-typescript/src/middleware/appwrite.ts +0 -119
- package/dist/functions/templates/hono-typescript/tsconfig.json +0 -20
- package/dist/functions/templates/typescript-node/README.md +0 -32
- package/dist/functions/templates/typescript-node/package.json +0 -25
- package/dist/functions/templates/typescript-node/src/context.ts +0 -103
- package/dist/functions/templates/typescript-node/src/index.ts +0 -29
- package/dist/functions/templates/typescript-node/tsconfig.json +0 -28
- package/dist/functions/templates/uv/README.md +0 -31
- package/dist/functions/templates/uv/pyproject.toml +0 -30
- package/dist/functions/templates/uv/src/__init__.py +0 -0
- package/dist/functions/templates/uv/src/context.py +0 -125
- package/dist/functions/templates/uv/src/index.py +0 -46
- package/dist/init.d.ts +0 -2
- package/dist/init.js +0 -57
- package/dist/interactiveCLI.d.ts +0 -31
- package/dist/interactiveCLI.js +0 -898
- package/dist/main.d.ts +0 -2
- package/dist/main.js +0 -1180
- package/dist/migrations/afterImportActions.d.ts +0 -17
- package/dist/migrations/afterImportActions.js +0 -306
- package/dist/migrations/appwriteToX.d.ts +0 -211
- package/dist/migrations/appwriteToX.js +0 -491
- package/dist/migrations/comprehensiveTransfer.d.ts +0 -147
- package/dist/migrations/comprehensiveTransfer.js +0 -1317
- package/dist/migrations/dataLoader.d.ts +0 -753
- package/dist/migrations/dataLoader.js +0 -1250
- package/dist/migrations/importController.d.ts +0 -23
- package/dist/migrations/importController.js +0 -268
- package/dist/migrations/importDataActions.d.ts +0 -50
- package/dist/migrations/importDataActions.js +0 -230
- package/dist/migrations/relationships.d.ts +0 -29
- package/dist/migrations/relationships.js +0 -204
- package/dist/migrations/services/DataTransformationService.d.ts +0 -55
- package/dist/migrations/services/DataTransformationService.js +0 -158
- package/dist/migrations/services/FileHandlerService.d.ts +0 -75
- package/dist/migrations/services/FileHandlerService.js +0 -236
- package/dist/migrations/services/ImportOrchestrator.d.ts +0 -97
- package/dist/migrations/services/ImportOrchestrator.js +0 -485
- package/dist/migrations/services/RateLimitManager.d.ts +0 -138
- package/dist/migrations/services/RateLimitManager.js +0 -279
- package/dist/migrations/services/RelationshipResolver.d.ts +0 -120
- package/dist/migrations/services/RelationshipResolver.js +0 -332
- package/dist/migrations/services/UserMappingService.d.ts +0 -109
- package/dist/migrations/services/UserMappingService.js +0 -277
- package/dist/migrations/services/ValidationService.d.ts +0 -74
- package/dist/migrations/services/ValidationService.js +0 -260
- package/dist/migrations/transfer.d.ts +0 -26
- package/dist/migrations/transfer.js +0 -608
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +0 -131
- package/dist/migrations/yaml/YamlImportConfigLoader.js +0 -383
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +0 -93
- package/dist/migrations/yaml/YamlImportIntegration.js +0 -341
- package/dist/migrations/yaml/generateImportSchemas.d.ts +0 -30
- package/dist/migrations/yaml/generateImportSchemas.js +0 -1327
- package/dist/schemas/authUser.d.ts +0 -24
- package/dist/schemas/authUser.js +0 -17
- package/dist/setup.d.ts +0 -2
- package/dist/setup.js +0 -5
- package/dist/setupCommands.d.ts +0 -58
- package/dist/setupCommands.js +0 -490
- package/dist/setupController.d.ts +0 -9
- package/dist/setupController.js +0 -34
- package/dist/shared/attributeMapper.d.ts +0 -20
- package/dist/shared/attributeMapper.js +0 -203
- package/dist/shared/backupMetadataSchema.d.ts +0 -94
- package/dist/shared/backupMetadataSchema.js +0 -38
- package/dist/shared/backupTracking.d.ts +0 -18
- package/dist/shared/backupTracking.js +0 -176
- package/dist/shared/confirmationDialogs.d.ts +0 -75
- package/dist/shared/confirmationDialogs.js +0 -236
- package/dist/shared/errorUtils.d.ts +0 -54
- package/dist/shared/errorUtils.js +0 -95
- package/dist/shared/functionManager.d.ts +0 -48
- package/dist/shared/functionManager.js +0 -348
- package/dist/shared/jsonSchemaGenerator.d.ts +0 -50
- package/dist/shared/jsonSchemaGenerator.js +0 -290
- package/dist/shared/logging.d.ts +0 -61
- package/dist/shared/logging.js +0 -116
- package/dist/shared/messageFormatter.d.ts +0 -39
- package/dist/shared/messageFormatter.js +0 -162
- package/dist/shared/migrationHelpers.d.ts +0 -61
- package/dist/shared/migrationHelpers.js +0 -145
- package/dist/shared/operationLogger.d.ts +0 -10
- package/dist/shared/operationLogger.js +0 -12
- package/dist/shared/operationQueue.d.ts +0 -40
- package/dist/shared/operationQueue.js +0 -311
- package/dist/shared/operationsTable.d.ts +0 -26
- package/dist/shared/operationsTable.js +0 -286
- package/dist/shared/operationsTableSchema.d.ts +0 -48
- package/dist/shared/operationsTableSchema.js +0 -35
- package/dist/shared/progressManager.d.ts +0 -62
- package/dist/shared/progressManager.js +0 -215
- package/dist/shared/pydanticModelGenerator.d.ts +0 -17
- package/dist/shared/pydanticModelGenerator.js +0 -615
- package/dist/shared/relationshipExtractor.d.ts +0 -56
- package/dist/shared/relationshipExtractor.js +0 -138
- package/dist/shared/schemaGenerator.d.ts +0 -40
- package/dist/shared/schemaGenerator.js +0 -556
- package/dist/shared/selectionDialogs.d.ts +0 -214
- package/dist/shared/selectionDialogs.js +0 -544
- package/dist/storage/backupCompression.d.ts +0 -20
- package/dist/storage/backupCompression.js +0 -67
- package/dist/storage/methods.d.ts +0 -32
- package/dist/storage/methods.js +0 -472
- package/dist/storage/schemas.d.ts +0 -842
- package/dist/storage/schemas.js +0 -175
- package/dist/tables/indexManager.d.ts +0 -65
- package/dist/tables/indexManager.js +0 -294
- package/dist/types.d.ts +0 -4
- package/dist/types.js +0 -3
- package/dist/users/methods.d.ts +0 -16
- package/dist/users/methods.js +0 -277
- package/dist/utils/ClientFactory.d.ts +0 -87
- package/dist/utils/ClientFactory.js +0 -212
- package/dist/utils/configDiscovery.d.ts +0 -78
- package/dist/utils/configDiscovery.js +0 -472
- package/dist/utils/configMigration.d.ts +0 -1
- package/dist/utils/configMigration.js +0 -261
- package/dist/utils/constantsGenerator.d.ts +0 -31
- package/dist/utils/constantsGenerator.js +0 -321
- package/dist/utils/dataConverters.d.ts +0 -46
- package/dist/utils/dataConverters.js +0 -139
- package/dist/utils/directoryUtils.d.ts +0 -22
- package/dist/utils/directoryUtils.js +0 -59
- package/dist/utils/getClientFromConfig.d.ts +0 -39
- package/dist/utils/getClientFromConfig.js +0 -199
- package/dist/utils/helperFunctions.d.ts +0 -63
- package/dist/utils/helperFunctions.js +0 -156
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.js +0 -2
- package/dist/utils/loadConfigs.d.ts +0 -50
- package/dist/utils/loadConfigs.js +0 -358
- package/dist/utils/pathResolvers.d.ts +0 -53
- package/dist/utils/pathResolvers.js +0 -72
- package/dist/utils/projectConfig.d.ts +0 -122
- package/dist/utils/projectConfig.js +0 -206
- package/dist/utils/retryFailedPromises.d.ts +0 -2
- package/dist/utils/retryFailedPromises.js +0 -23
- package/dist/utils/sessionAuth.d.ts +0 -48
- package/dist/utils/sessionAuth.js +0 -164
- package/dist/utils/setupFiles.d.ts +0 -4
- package/dist/utils/setupFiles.js +0 -1192
- package/dist/utils/typeGuards.d.ts +0 -35
- package/dist/utils/typeGuards.js +0 -57
- package/dist/utils/validationRules.d.ts +0 -43
- package/dist/utils/validationRules.js +0 -42
- package/dist/utils/versionDetection.d.ts +0 -58
- package/dist/utils/versionDetection.js +0 -251
- package/dist/utils/yamlConverter.d.ts +0 -100
- package/dist/utils/yamlConverter.js +0 -428
- package/dist/utils/yamlLoader.d.ts +0 -70
- package/dist/utils/yamlLoader.js +0 -267
- package/dist/utilsController.d.ts +0 -107
- package/dist/utilsController.js +0 -873
- package/src/adapters/AdapterFactory.ts +0 -529
- package/src/adapters/DatabaseAdapter.ts +0 -319
- package/src/adapters/LegacyAdapter.ts +0 -844
- package/src/adapters/TablesDBAdapter.ts +0 -823
- package/src/config/ConfigManager.ts +0 -849
- package/src/config/README.md +0 -274
- package/src/config/configMigration.ts +0 -575
- package/src/config/configValidation.ts +0 -445
- package/src/config/index.ts +0 -10
- package/src/config/services/ConfigDiscoveryService.ts +0 -410
- package/src/config/services/ConfigLoaderService.ts +0 -732
- package/src/config/services/ConfigMergeService.ts +0 -388
- package/src/config/services/ConfigValidationService.ts +0 -394
- package/src/config/services/SessionAuthService.ts +0 -565
- package/src/config/services/__tests__/ConfigMergeService.test.ts +0 -351
- package/src/config/services/index.ts +0 -29
- package/src/config/yamlConfig.ts +0 -761
- package/src/functions/pathResolution.ts +0 -227
- package/src/functions/templates/count-docs-in-collection/package.json +0 -25
- package/src/functions/templates/count-docs-in-collection/tsconfig.json +0 -28
- package/src/functions/templates/hono-typescript/package.json +0 -26
- package/src/functions/templates/hono-typescript/tsconfig.json +0 -20
- package/src/functions/templates/typescript-node/package.json +0 -25
- package/src/functions/templates/typescript-node/tsconfig.json +0 -28
- package/src/shared/attributeMapper.ts +0 -229
- package/src/shared/errorUtils.ts +0 -110
- package/src/shared/functionManager.ts +0 -537
- package/src/shared/jsonSchemaGenerator.ts +0 -383
- package/src/shared/logging.ts +0 -149
- package/src/shared/messageFormatter.ts +0 -208
- package/src/shared/pydanticModelGenerator.ts +0 -618
- package/src/shared/schemaGenerator.ts +0 -644
- package/src/utils/ClientFactory.ts +0 -240
- package/src/utils/configDiscovery.ts +0 -557
- package/src/utils/constantsGenerator.ts +0 -369
- package/src/utils/dataConverters.ts +0 -159
- package/src/utils/directoryUtils.ts +0 -61
- package/src/utils/getClientFromConfig.ts +0 -257
- package/src/utils/helperFunctions.ts +0 -228
- package/src/utils/pathResolvers.ts +0 -81
- package/src/utils/projectConfig.ts +0 -340
- package/src/utils/retryFailedPromises.ts +0 -29
- package/src/utils/sessionAuth.ts +0 -230
- package/src/utils/typeGuards.ts +0 -65
- package/src/utils/validationRules.ts +0 -88
- package/src/utils/versionDetection.ts +0 -292
- package/src/utils/yamlConverter.ts +0 -542
- package/src/utils/yamlLoader.ts +0 -371
- package/tmp-sync-test/.appwrite/collections/TestCollection.yaml +0 -7
|
@@ -1,587 +0,0 @@
|
|
|
1
|
-
import { Databases, ID, Permission, Query, } from "node-appwrite";
|
|
2
|
-
import { getAdapterFromConfig } from "../utils/getClientFromConfig.js";
|
|
3
|
-
import { nameToIdMapping, processQueue, queuedOperations, clearProcessingState, isCollectionProcessed, markCollectionProcessed, enqueueOperation } from "../shared/operationQueue.js";
|
|
4
|
-
import { logger } from "../shared/logging.js";
|
|
5
|
-
// Legacy attribute/index helpers removed in favor of unified adapter path
|
|
6
|
-
import { SchemaGenerator } from "../shared/schemaGenerator.js";
|
|
7
|
-
import { isNull, isUndefined, isNil, isPlainObject, isString, } from "es-toolkit";
|
|
8
|
-
import { delay, tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
|
9
|
-
import { MessageFormatter } from "../shared/messageFormatter.js";
|
|
10
|
-
import { isLegacyDatabases } from "../utils/typeGuards.js";
|
|
11
|
-
import { mapToCreateAttributeParams, mapToUpdateAttributeParams } from "../shared/attributeMapper.js";
|
|
12
|
-
import { diffTableColumns, isIndexEqualToIndex, diffColumnsDetailed, executeColumnOperations } from "./tableOperations.js";
|
|
13
|
-
import { createOrUpdateIndexesViaAdapter, deleteObsoleteIndexesViaAdapter } from "../tables/indexManager.js";
|
|
14
|
-
// Re-export wipe operations
|
|
15
|
-
export { wipeDatabase, wipeCollection, wipeAllTables, wipeTableRows, } from "./wipeOperations.js";
|
|
16
|
-
// Re-export transfer operations
|
|
17
|
-
export { transferDocumentsBetweenDbsLocalToLocal, transferDocumentsBetweenDbsLocalToRemote, } from "./transferOperations.js";
|
|
18
|
-
export const documentExists = async (db, dbId, targetCollectionId, toCreateObject) => {
|
|
19
|
-
const collection = await (isLegacyDatabases(db) ?
|
|
20
|
-
db.getCollection(dbId, targetCollectionId) :
|
|
21
|
-
db.getTable({ databaseId: dbId, tableId: targetCollectionId }));
|
|
22
|
-
const attributes = collection.attributes;
|
|
23
|
-
let arrayTypeAttributes = attributes
|
|
24
|
-
.filter((attribute) => attribute.array === true)
|
|
25
|
-
.map((attribute) => attribute.key);
|
|
26
|
-
const isJsonString = (str) => {
|
|
27
|
-
try {
|
|
28
|
-
const json = JSON.parse(str);
|
|
29
|
-
return typeof json === "object" && json !== null;
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
// Convert object to entries and filter
|
|
36
|
-
const validEntries = Object.entries(toCreateObject).filter(([key, value]) => !arrayTypeAttributes.includes(key) &&
|
|
37
|
-
!key.startsWith("$") &&
|
|
38
|
-
!isNull(value) &&
|
|
39
|
-
!isUndefined(value) &&
|
|
40
|
-
!isNil(value) &&
|
|
41
|
-
!isPlainObject(value) &&
|
|
42
|
-
!Array.isArray(value) &&
|
|
43
|
-
!(isString(value) && isJsonString(value)) &&
|
|
44
|
-
(isString(value) ? value.length < 4096 && value.length > 0 : true));
|
|
45
|
-
// Map and filter valid entries
|
|
46
|
-
const validMappedEntries = validEntries
|
|
47
|
-
.map(([key, value]) => [
|
|
48
|
-
key,
|
|
49
|
-
isString(value) || typeof value === "number" || typeof value === "boolean"
|
|
50
|
-
? value
|
|
51
|
-
: null,
|
|
52
|
-
])
|
|
53
|
-
.filter(([key, value]) => !isNull(value) && isString(key))
|
|
54
|
-
.slice(0, 25);
|
|
55
|
-
// Convert to Query parameters
|
|
56
|
-
const validQueryParams = validMappedEntries.map(([key, value]) => Query.equal(key, value));
|
|
57
|
-
// Execute the query with the validated and prepared parameters
|
|
58
|
-
const result = await (isLegacyDatabases(db) ?
|
|
59
|
-
db.listDocuments(dbId, targetCollectionId, validQueryParams) :
|
|
60
|
-
db.listRows({ databaseId: dbId, tableId: targetCollectionId, queries: validQueryParams }));
|
|
61
|
-
const items = isLegacyDatabases(db) ? result.documents : (result.rows || result.documents);
|
|
62
|
-
return items?.[0] || null;
|
|
63
|
-
};
|
|
64
|
-
export const checkForCollection = async (db, dbId, collection) => {
|
|
65
|
-
try {
|
|
66
|
-
MessageFormatter.progress(`Checking for collection with name: ${collection.name}`, { prefix: "Collections" });
|
|
67
|
-
const response = await tryAwaitWithRetry(async () => isLegacyDatabases(db) ?
|
|
68
|
-
await db.listCollections(dbId, [Query.equal("name", collection.name)]) :
|
|
69
|
-
await db.listTables({ databaseId: dbId, queries: [Query.equal("name", collection.name)] }));
|
|
70
|
-
const items = isLegacyDatabases(db) ? response.collections : (response.tables || response.collections);
|
|
71
|
-
if (items && items.length > 0) {
|
|
72
|
-
MessageFormatter.info(`Collection found: ${items[0].$id}`, { prefix: "Collections" });
|
|
73
|
-
// Return remote collection for update operations (don't merge local config over it)
|
|
74
|
-
return items[0];
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
MessageFormatter.info(`No collection found with name: ${collection.name}`, { prefix: "Collections" });
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
83
|
-
MessageFormatter.error(`Error checking for collection: ${collection.name}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Collections" });
|
|
84
|
-
logger.error('Collection check failed', {
|
|
85
|
-
collectionName: collection.name,
|
|
86
|
-
dbId,
|
|
87
|
-
error: errorMessage,
|
|
88
|
-
operation: 'checkForCollection'
|
|
89
|
-
});
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
// Helper function to fetch and cache collection by name
|
|
94
|
-
export const fetchAndCacheCollectionByName = async (db, dbId, collectionName) => {
|
|
95
|
-
if (nameToIdMapping.has(collectionName)) {
|
|
96
|
-
const collectionId = nameToIdMapping.get(collectionName);
|
|
97
|
-
MessageFormatter.debug(`Collection found in cache: ${collectionId}`, undefined, { prefix: "Collections" });
|
|
98
|
-
return await tryAwaitWithRetry(async () => isLegacyDatabases(db) ?
|
|
99
|
-
await db.getCollection(dbId, collectionId) :
|
|
100
|
-
await db.getTable({ databaseId: dbId, tableId: collectionId }));
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
MessageFormatter.progress(`Fetching collection by name: ${collectionName}`, { prefix: "Collections" });
|
|
104
|
-
const collectionsPulled = await tryAwaitWithRetry(async () => isLegacyDatabases(db) ?
|
|
105
|
-
await db.listCollections(dbId, [Query.equal("name", collectionName)]) :
|
|
106
|
-
await db.listTables({ databaseId: dbId, queries: [Query.equal("name", collectionName)] }));
|
|
107
|
-
const items = isLegacyDatabases(db) ? collectionsPulled.collections : (collectionsPulled.tables || collectionsPulled.collections);
|
|
108
|
-
if ((collectionsPulled.total || items?.length) > 0) {
|
|
109
|
-
const collection = items[0];
|
|
110
|
-
MessageFormatter.info(`Collection found: ${collection.$id}`, { prefix: "Collections" });
|
|
111
|
-
nameToIdMapping.set(collectionName, collection.$id);
|
|
112
|
-
return collection;
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
MessageFormatter.warning(`Collection not found by name: ${collectionName}`, { prefix: "Collections" });
|
|
116
|
-
return undefined;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
export const generateSchemas = async (config, appwriteFolderPath) => {
|
|
121
|
-
const schemaGenerator = new SchemaGenerator(config, appwriteFolderPath);
|
|
122
|
-
await schemaGenerator.generateSchemas();
|
|
123
|
-
};
|
|
124
|
-
export const createOrUpdateCollections = async (database, databaseId, config, deletedCollections, selectedCollections = []) => {
|
|
125
|
-
// Clear processing state at the start of a new operation
|
|
126
|
-
clearProcessingState();
|
|
127
|
-
// Always use adapter path (LegacyAdapter translates when pre-1.8)
|
|
128
|
-
const { adapter } = await getAdapterFromConfig(config);
|
|
129
|
-
await createOrUpdateCollectionsViaAdapter(adapter, databaseId, config, deletedCollections, selectedCollections);
|
|
130
|
-
};
|
|
131
|
-
// New: Adapter-based implementation for TablesDB with state management
|
|
132
|
-
export const createOrUpdateCollectionsViaAdapter = async (adapter, databaseId, config, deletedCollections, selectedCollections = []) => {
|
|
133
|
-
const collectionsToProcess = selectedCollections.length > 0 ? selectedCollections : (config.collections || []);
|
|
134
|
-
if (!collectionsToProcess || collectionsToProcess.length === 0)
|
|
135
|
-
return;
|
|
136
|
-
const usedIds = new Set();
|
|
137
|
-
MessageFormatter.info(`Processing ${collectionsToProcess.length} tables via adapter with intelligent state management`, { prefix: "Tables" });
|
|
138
|
-
// Helpers for attribute operations through adapter
|
|
139
|
-
const createAttr = async (tableId, attr) => {
|
|
140
|
-
const params = mapToCreateAttributeParams(attr, { databaseId, tableId });
|
|
141
|
-
await adapter.createAttribute(params);
|
|
142
|
-
await delay(150);
|
|
143
|
-
};
|
|
144
|
-
const updateAttr = async (tableId, attr) => {
|
|
145
|
-
const params = mapToUpdateAttributeParams(attr, { databaseId, tableId });
|
|
146
|
-
await adapter.updateAttribute(params);
|
|
147
|
-
await delay(150);
|
|
148
|
-
};
|
|
149
|
-
// Local queue for unresolved relationships
|
|
150
|
-
const relQueue = [];
|
|
151
|
-
for (const collection of collectionsToProcess) {
|
|
152
|
-
const { attributes, indexes, ...collectionData } = collection;
|
|
153
|
-
// Check if this table has already been processed in this session (per database)
|
|
154
|
-
if (collectionData.$id && isCollectionProcessed(collectionData.$id, databaseId)) {
|
|
155
|
-
MessageFormatter.info(`Table '${collectionData.name}' already processed, skipping`, { prefix: "Tables" });
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
// Prepare permissions as strings (reuse Permission helper)
|
|
159
|
-
const permissions = [];
|
|
160
|
-
if (collection.$permissions && collection.$permissions.length > 0) {
|
|
161
|
-
for (const p of collection.$permissions) {
|
|
162
|
-
if (typeof p === 'string')
|
|
163
|
-
permissions.push(p);
|
|
164
|
-
else {
|
|
165
|
-
switch (p.permission) {
|
|
166
|
-
case 'read':
|
|
167
|
-
permissions.push(Permission.read(p.target));
|
|
168
|
-
break;
|
|
169
|
-
case 'create':
|
|
170
|
-
permissions.push(Permission.create(p.target));
|
|
171
|
-
break;
|
|
172
|
-
case 'update':
|
|
173
|
-
permissions.push(Permission.update(p.target));
|
|
174
|
-
break;
|
|
175
|
-
case 'delete':
|
|
176
|
-
permissions.push(Permission.delete(p.target));
|
|
177
|
-
break;
|
|
178
|
-
case 'write':
|
|
179
|
-
permissions.push(Permission.write(p.target));
|
|
180
|
-
break;
|
|
181
|
-
default: break;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// Find existing table — prefer lookup by ID (if provided), then by name
|
|
187
|
-
let table;
|
|
188
|
-
let tableId;
|
|
189
|
-
// 1) Try by explicit $id first (handles rename scenarios)
|
|
190
|
-
if (collectionData.$id) {
|
|
191
|
-
try {
|
|
192
|
-
const byId = await adapter.getTable({ databaseId, tableId: collectionData.$id });
|
|
193
|
-
table = byId.data || byId.tables?.[0];
|
|
194
|
-
if (table?.$id) {
|
|
195
|
-
MessageFormatter.info(`Found existing table by ID: ${table.$id}`, { prefix: 'Tables' });
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
catch {
|
|
199
|
-
// Not found by ID; fall back to name lookup
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
// 2) If not found by ID, try by name
|
|
203
|
-
if (!table) {
|
|
204
|
-
const list = await adapter.listTables({ databaseId, queries: [Query.equal('name', collectionData.name)] });
|
|
205
|
-
const items = list.tables || [];
|
|
206
|
-
table = items[0];
|
|
207
|
-
if (table?.$id) {
|
|
208
|
-
// If local has $id that differs from remote, prefer remote (IDs are immutable)
|
|
209
|
-
if (collectionData.$id && collectionData.$id !== table.$id) {
|
|
210
|
-
MessageFormatter.warning(`Config $id '${collectionData.$id}' differs from existing table ID '${table.$id}'. Using existing table.`, { prefix: 'Tables' });
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
if (!table) {
|
|
215
|
-
// Determine ID (prefer provided $id or re-use deleted one)
|
|
216
|
-
let foundColl = deletedCollections?.find((coll) => coll.collectionName.toLowerCase().trim().replace(" ", "") === collectionData.name.toLowerCase().trim().replace(" ", ""));
|
|
217
|
-
if (collectionData.$id)
|
|
218
|
-
tableId = collectionData.$id;
|
|
219
|
-
else if (foundColl && !usedIds.has(foundColl.collectionId))
|
|
220
|
-
tableId = foundColl.collectionId;
|
|
221
|
-
else
|
|
222
|
-
tableId = ID.unique();
|
|
223
|
-
usedIds.add(tableId);
|
|
224
|
-
const res = await adapter.createTable({
|
|
225
|
-
databaseId,
|
|
226
|
-
id: tableId,
|
|
227
|
-
name: collectionData.name,
|
|
228
|
-
permissions,
|
|
229
|
-
documentSecurity: !!collectionData.documentSecurity,
|
|
230
|
-
enabled: collectionData.enabled !== false
|
|
231
|
-
});
|
|
232
|
-
table = res.data || res;
|
|
233
|
-
nameToIdMapping.set(collectionData.name, tableId);
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
tableId = table.$id;
|
|
237
|
-
await adapter.updateTable({
|
|
238
|
-
databaseId,
|
|
239
|
-
id: tableId,
|
|
240
|
-
name: collectionData.name,
|
|
241
|
-
permissions,
|
|
242
|
-
documentSecurity: !!collectionData.documentSecurity,
|
|
243
|
-
enabled: collectionData.enabled !== false
|
|
244
|
-
});
|
|
245
|
-
// Cache the existing table ID
|
|
246
|
-
nameToIdMapping.set(collectionData.name, tableId);
|
|
247
|
-
}
|
|
248
|
-
// Add small delay after table create/update
|
|
249
|
-
await delay(250);
|
|
250
|
-
// Create/Update attributes: non-relationship first using enhanced planning
|
|
251
|
-
const nonRel = (attributes || []).filter((a) => a.type !== 'relationship');
|
|
252
|
-
if (nonRel.length > 0) {
|
|
253
|
-
// Fetch existing columns once
|
|
254
|
-
const tableInfo = await adapter.getTable({ databaseId, tableId });
|
|
255
|
-
const existingCols = tableInfo.data?.columns || tableInfo.data?.attributes || [];
|
|
256
|
-
// Plan with icons
|
|
257
|
-
const plan = diffColumnsDetailed(nonRel, existingCols);
|
|
258
|
-
const plus = plan.toCreate.map((a) => a.key);
|
|
259
|
-
const plusminus = plan.toUpdate.map((u) => u.attribute.key);
|
|
260
|
-
const minus = plan.toRecreate.map((r) => r.newAttribute.key);
|
|
261
|
-
const skip = plan.unchanged;
|
|
262
|
-
// Compute deletions (remote extras not present locally)
|
|
263
|
-
const desiredKeysForDelete = new Set((attributes || []).map((a) => a.key));
|
|
264
|
-
const extraRemoteKeys = (existingCols || [])
|
|
265
|
-
.map((c) => c?.key)
|
|
266
|
-
.filter((k) => !!k && !desiredKeysForDelete.has(k));
|
|
267
|
-
const parts = [];
|
|
268
|
-
if (plus.length)
|
|
269
|
-
parts.push(`➕ ${plus.length} (${plus.join(', ')})`);
|
|
270
|
-
if (plusminus.length)
|
|
271
|
-
parts.push(`🔧 ${plusminus.length} (${plusminus.join(', ')})`);
|
|
272
|
-
if (minus.length)
|
|
273
|
-
parts.push(`♻️ ${minus.length} (${minus.join(', ')})`);
|
|
274
|
-
if (skip.length)
|
|
275
|
-
parts.push(`⏭️ ${skip.length}`);
|
|
276
|
-
parts.push(`🗑️ ${extraRemoteKeys.length}${extraRemoteKeys.length ? ` (${extraRemoteKeys.join(', ')})` : ''}`);
|
|
277
|
-
MessageFormatter.info(`Plan → ${parts.join(' | ') || 'no changes'}`, { prefix: 'Attributes' });
|
|
278
|
-
// Execute
|
|
279
|
-
const colResults = await executeColumnOperations(adapter, databaseId, tableId, plan);
|
|
280
|
-
if (colResults.success.length > 0) {
|
|
281
|
-
MessageFormatter.success(`Processed ${colResults.success.length} ops`, { prefix: 'Attributes' });
|
|
282
|
-
}
|
|
283
|
-
if (colResults.errors.length > 0) {
|
|
284
|
-
MessageFormatter.error(`${colResults.errors.length} attribute operations failed:`, undefined, { prefix: 'Attributes' });
|
|
285
|
-
for (const err of colResults.errors) {
|
|
286
|
-
MessageFormatter.error(` ${err.column}: ${err.error}`, undefined, { prefix: 'Attributes' });
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
MessageFormatter.info(`Summary → ➕ ${plan.toCreate.length} | 🔧 ${plan.toUpdate.length} | ♻️ ${plan.toRecreate.length} | ⏭️ ${plan.unchanged.length}`, { prefix: 'Attributes' });
|
|
290
|
-
}
|
|
291
|
-
// Relationship attributes — resolve relatedCollection to ID, then diff and create/update with recreate support
|
|
292
|
-
const relsAll = (attributes || []).filter((a) => a.type === 'relationship');
|
|
293
|
-
if (relsAll.length > 0) {
|
|
294
|
-
const relsResolved = [];
|
|
295
|
-
const relsDeferred = [];
|
|
296
|
-
// Resolve related collections (names -> IDs) using cache or lookup.
|
|
297
|
-
// If not resolvable yet (target table created later in the same push), queue for later.
|
|
298
|
-
for (const attr of relsAll) {
|
|
299
|
-
const relNameOrId = attr.relatedCollection;
|
|
300
|
-
if (!relNameOrId)
|
|
301
|
-
continue;
|
|
302
|
-
let relId = nameToIdMapping.get(relNameOrId) || relNameOrId;
|
|
303
|
-
let resolved = false;
|
|
304
|
-
if (nameToIdMapping.has(relNameOrId)) {
|
|
305
|
-
resolved = true;
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
// Try resolve by name
|
|
309
|
-
try {
|
|
310
|
-
const relList = await adapter.listTables({ databaseId, queries: [Query.equal('name', relNameOrId)] });
|
|
311
|
-
const relItems = relList.tables || [];
|
|
312
|
-
if (relItems[0]?.$id) {
|
|
313
|
-
relId = relItems[0].$id;
|
|
314
|
-
nameToIdMapping.set(relNameOrId, relId);
|
|
315
|
-
resolved = true;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
catch { }
|
|
319
|
-
// If the relNameOrId looks like an ID but isn't resolved yet, attempt a direct get
|
|
320
|
-
if (!resolved && relNameOrId && relNameOrId.length >= 10) {
|
|
321
|
-
try {
|
|
322
|
-
const probe = await adapter.getTable({ databaseId, tableId: relNameOrId });
|
|
323
|
-
if (probe.data?.$id) {
|
|
324
|
-
nameToIdMapping.set(relNameOrId, relNameOrId);
|
|
325
|
-
relId = relNameOrId;
|
|
326
|
-
resolved = true;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
catch { }
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
if (resolved && relId && typeof relId === 'string') {
|
|
333
|
-
attr.relatedCollection = relId;
|
|
334
|
-
relsResolved.push(attr);
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
// Defer until related table exists; queue a surgical operation
|
|
338
|
-
enqueueOperation({
|
|
339
|
-
type: 'attribute',
|
|
340
|
-
collectionId: tableId,
|
|
341
|
-
attribute: attr,
|
|
342
|
-
dependencies: [relNameOrId]
|
|
343
|
-
});
|
|
344
|
-
relsDeferred.push(attr);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
// Compute a detailed plan for immediately resolvable relationships
|
|
348
|
-
const tableInfo2 = await adapter.getTable({ databaseId, tableId });
|
|
349
|
-
const existingCols2 = tableInfo2.data?.columns || tableInfo2.data?.attributes || [];
|
|
350
|
-
const relPlan = diffColumnsDetailed(relsResolved, existingCols2);
|
|
351
|
-
// Relationship plan with icons (includes recreates)
|
|
352
|
-
{
|
|
353
|
-
const parts = [];
|
|
354
|
-
if (relPlan.toCreate.length)
|
|
355
|
-
parts.push(`➕ ${relPlan.toCreate.length} (${relPlan.toCreate.map((a) => a.key).join(', ')})`);
|
|
356
|
-
if (relPlan.toUpdate.length)
|
|
357
|
-
parts.push(`🔧 ${relPlan.toUpdate.length} (${relPlan.toUpdate.map((u) => u.attribute?.key ?? u.key).join(', ')})`);
|
|
358
|
-
if (relPlan.toRecreate.length)
|
|
359
|
-
parts.push(`♻️ ${relPlan.toRecreate.length} (${relPlan.toRecreate.map((r) => r.newAttribute?.key ?? r?.key).join(', ')})`);
|
|
360
|
-
if (relPlan.unchanged.length)
|
|
361
|
-
parts.push(`⏭️ ${relPlan.unchanged.length}`);
|
|
362
|
-
MessageFormatter.info(`Plan → ${parts.join(' | ') || 'no changes'}`, { prefix: 'Relationships' });
|
|
363
|
-
}
|
|
364
|
-
// Execute plan using the same operation executor to properly handle deletes/recreates
|
|
365
|
-
const relResults = await executeColumnOperations(adapter, databaseId, tableId, relPlan);
|
|
366
|
-
if (relResults.success.length > 0) {
|
|
367
|
-
const totalRelationships = relPlan.toCreate.length + relPlan.toUpdate.length + relPlan.toRecreate.length + relPlan.unchanged.length;
|
|
368
|
-
const activeRelationships = relPlan.toCreate.length + relPlan.toUpdate.length + relPlan.toRecreate.length;
|
|
369
|
-
if (relResults.success.length !== activeRelationships) {
|
|
370
|
-
// Show both counts when they differ (usually due to recreations)
|
|
371
|
-
MessageFormatter.success(`Processed ${relResults.success.length} operations for ${activeRelationships} relationship${activeRelationships === 1 ? '' : 's'}`, { prefix: 'Relationships' });
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
MessageFormatter.success(`Processed ${relResults.success.length} relationship${relResults.success.length === 1 ? '' : 's'}`, { prefix: 'Relationships' });
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
if (relResults.errors.length > 0) {
|
|
378
|
-
MessageFormatter.error(`${relResults.errors.length} relationship operations failed:`, undefined, { prefix: 'Relationships' });
|
|
379
|
-
for (const err of relResults.errors) {
|
|
380
|
-
MessageFormatter.error(` ${err.column}: ${err.error}`, undefined, { prefix: 'Relationships' });
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
if (relsDeferred.length > 0) {
|
|
384
|
-
MessageFormatter.info(`Deferred ${relsDeferred.length} relationship(s) until related tables become available`, { prefix: 'Relationships' });
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
// Wait for all attributes to become available before creating indexes
|
|
388
|
-
const allAttrKeys = [
|
|
389
|
-
...nonRel.map((a) => a.key),
|
|
390
|
-
...relsAll.filter((a) => a.relatedCollection).map((a) => a.key)
|
|
391
|
-
];
|
|
392
|
-
if (allAttrKeys.length > 0) {
|
|
393
|
-
for (const attrKey of allAttrKeys) {
|
|
394
|
-
const maxWait = 60000; // 60 seconds
|
|
395
|
-
const startTime = Date.now();
|
|
396
|
-
let lastStatus = '';
|
|
397
|
-
while (Date.now() - startTime < maxWait) {
|
|
398
|
-
try {
|
|
399
|
-
const tableData = await adapter.getTable({ databaseId, tableId });
|
|
400
|
-
const attrs = tableData.data?.columns || tableData.data?.attributes || [];
|
|
401
|
-
const attr = attrs.find((a) => a.key === attrKey);
|
|
402
|
-
if (attr) {
|
|
403
|
-
if (attr.status === 'available') {
|
|
404
|
-
break; // Attribute is ready
|
|
405
|
-
}
|
|
406
|
-
if (attr.status === 'failed' || attr.status === 'stuck') {
|
|
407
|
-
throw new Error(`Attribute ${attrKey} failed to create: ${attr.error || 'unknown error'}`);
|
|
408
|
-
}
|
|
409
|
-
// Still processing, continue waiting
|
|
410
|
-
lastStatus = attr.status;
|
|
411
|
-
}
|
|
412
|
-
await delay(2000); // Check every 2 seconds
|
|
413
|
-
}
|
|
414
|
-
catch (e) {
|
|
415
|
-
// If we can't check status, assume it's processing and continue
|
|
416
|
-
await delay(2000);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
// Timeout check
|
|
420
|
-
if (Date.now() - startTime >= maxWait) {
|
|
421
|
-
MessageFormatter.warning(`Attribute ${attrKey} did not become available within ${maxWait / 1000}s (last status: ${lastStatus}). Proceeding anyway.`, { prefix: 'Attributes' });
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
// Index management: create/update indexes using clean adapter-based system
|
|
426
|
-
const localTableConfig = config.collections?.find(c => c.name === collectionData.name || c.$id === collectionData.$id);
|
|
427
|
-
const idxs = (localTableConfig?.indexes ?? indexes ?? []);
|
|
428
|
-
// Create/update indexes with proper planning and execution
|
|
429
|
-
await createOrUpdateIndexesViaAdapter(adapter, databaseId, tableId, idxs, indexes);
|
|
430
|
-
// Handle obsolete index deletions
|
|
431
|
-
const desiredIndexKeys = new Set((indexes || []).map((i) => i.key));
|
|
432
|
-
await deleteObsoleteIndexesViaAdapter(adapter, databaseId, tableId, desiredIndexKeys);
|
|
433
|
-
// Deletions: remove columns/attributes that are present remotely but not in desired config
|
|
434
|
-
try {
|
|
435
|
-
const desiredKeys = new Set((attributes || []).map((a) => a.key));
|
|
436
|
-
const tableInfo3 = await adapter.getTable({ databaseId, tableId });
|
|
437
|
-
const existingCols3 = tableInfo3.data?.columns || tableInfo3.data?.attributes || [];
|
|
438
|
-
const toDelete = existingCols3
|
|
439
|
-
.filter((col) => col?.key && !desiredKeys.has(col.key))
|
|
440
|
-
.map((col) => col.key);
|
|
441
|
-
if (toDelete.length > 0) {
|
|
442
|
-
MessageFormatter.info(`Plan → 🗑️ ${toDelete.length} (${toDelete.join(', ')})`, { prefix: 'Attributes' });
|
|
443
|
-
const deleted = [];
|
|
444
|
-
const errors = [];
|
|
445
|
-
for (const key of toDelete) {
|
|
446
|
-
try {
|
|
447
|
-
// Drop any indexes that reference this attribute to avoid server errors
|
|
448
|
-
try {
|
|
449
|
-
const idxRes = await adapter.listIndexes({ databaseId, tableId });
|
|
450
|
-
const ilist = idxRes.data || idxRes.indexes || [];
|
|
451
|
-
for (const idx of ilist) {
|
|
452
|
-
const attrs = Array.isArray(idx.attributes)
|
|
453
|
-
? idx.attributes
|
|
454
|
-
: (Array.isArray(idx.columns) ? idx.columns : []);
|
|
455
|
-
if (attrs.includes(key)) {
|
|
456
|
-
MessageFormatter.info(`🗑️ Deleting index '${idx.key}' referencing '${key}'`, { prefix: 'Indexes' });
|
|
457
|
-
await adapter.deleteIndex({ databaseId, tableId, key: idx.key });
|
|
458
|
-
await delay(500);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
catch { }
|
|
463
|
-
await adapter.deleteAttribute({ databaseId, tableId, key });
|
|
464
|
-
// Wait briefly for deletion to settle
|
|
465
|
-
const start = Date.now();
|
|
466
|
-
const maxWaitMs = 60000;
|
|
467
|
-
while (Date.now() - start < maxWaitMs) {
|
|
468
|
-
try {
|
|
469
|
-
const tinfo = await adapter.getTable({ databaseId, tableId });
|
|
470
|
-
const cols = tinfo.data?.columns || tinfo.data?.attributes || [];
|
|
471
|
-
const found = cols.find((c) => c.key === key);
|
|
472
|
-
if (!found)
|
|
473
|
-
break;
|
|
474
|
-
if (found.status && found.status !== 'deleting')
|
|
475
|
-
break;
|
|
476
|
-
}
|
|
477
|
-
catch { }
|
|
478
|
-
await delay(1000);
|
|
479
|
-
}
|
|
480
|
-
deleted.push(key);
|
|
481
|
-
}
|
|
482
|
-
catch (e) {
|
|
483
|
-
errors.push({ key, error: e?.message || String(e) });
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
if (deleted.length) {
|
|
487
|
-
MessageFormatter.success(`Deleted ${deleted.length} attributes: ${deleted.join(', ')}`, { prefix: 'Attributes' });
|
|
488
|
-
}
|
|
489
|
-
if (errors.length) {
|
|
490
|
-
MessageFormatter.error(`${errors.length} deletions failed`, undefined, { prefix: 'Attributes' });
|
|
491
|
-
errors.forEach(er => MessageFormatter.error(` ${er.key}: ${er.error}`, undefined, { prefix: 'Attributes' }));
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
else {
|
|
495
|
-
MessageFormatter.info(`Plan → 🗑️ 0`, { prefix: 'Attributes' });
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
catch (e) {
|
|
499
|
-
MessageFormatter.warning(`Could not evaluate deletions: ${e?.message || e}`, { prefix: 'Attributes' });
|
|
500
|
-
}
|
|
501
|
-
// Mark this table as fully processed for this database to prevent re-processing in the same DB only
|
|
502
|
-
markCollectionProcessed(tableId, collectionData.name, databaseId);
|
|
503
|
-
}
|
|
504
|
-
// Process queued relationships once mapping likely populated
|
|
505
|
-
if (relQueue.length > 0) {
|
|
506
|
-
MessageFormatter.info(`🔧 Processing ${relQueue.length} queued relationship attributes for tables`, { prefix: "Tables" });
|
|
507
|
-
for (const { tableId, attr } of relQueue) {
|
|
508
|
-
const relNameOrId = attr.relatedCollection;
|
|
509
|
-
if (!relNameOrId)
|
|
510
|
-
continue;
|
|
511
|
-
const relId = nameToIdMapping.get(relNameOrId) || relNameOrId;
|
|
512
|
-
if (relId) {
|
|
513
|
-
attr.relatedCollection = relId;
|
|
514
|
-
try {
|
|
515
|
-
await adapter.createAttribute({
|
|
516
|
-
databaseId,
|
|
517
|
-
tableId,
|
|
518
|
-
key: attr.key,
|
|
519
|
-
type: attr.type,
|
|
520
|
-
size: attr.size,
|
|
521
|
-
required: !!attr.required,
|
|
522
|
-
default: attr.xdefault,
|
|
523
|
-
array: !!attr.array,
|
|
524
|
-
min: attr.min,
|
|
525
|
-
max: attr.max,
|
|
526
|
-
elements: attr.elements,
|
|
527
|
-
relatedCollection: relId,
|
|
528
|
-
relationType: attr.relationType,
|
|
529
|
-
twoWay: attr.twoWay,
|
|
530
|
-
twoWayKey: attr.twoWayKey,
|
|
531
|
-
onDelete: attr.onDelete,
|
|
532
|
-
side: attr.side
|
|
533
|
-
});
|
|
534
|
-
await delay(150);
|
|
535
|
-
MessageFormatter.info(`✅ Successfully processed queued relationship: ${attr.key}`, { prefix: "Tables" });
|
|
536
|
-
}
|
|
537
|
-
catch (e) {
|
|
538
|
-
MessageFormatter.error(`Failed queued relationship ${attr.key}`, e instanceof Error ? e : new Error(String(e)), { prefix: 'Attributes' });
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
else {
|
|
542
|
-
MessageFormatter.warning(`Could not resolve relationship ${attr.key} -> ${relNameOrId}`, { prefix: "Tables" });
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
// Process any remaining queued operations to complete relationship sync
|
|
547
|
-
try {
|
|
548
|
-
MessageFormatter.info(`🔄 Processing final operation queue for database ${databaseId}`, { prefix: "Tables" });
|
|
549
|
-
await processQueue(adapter, databaseId);
|
|
550
|
-
MessageFormatter.info(`✅ Operation queue processing completed`, { prefix: "Tables" });
|
|
551
|
-
}
|
|
552
|
-
catch (error) {
|
|
553
|
-
MessageFormatter.error(`Failed to process operation queue`, error instanceof Error ? error : new Error(String(error)), { prefix: 'Tables' });
|
|
554
|
-
}
|
|
555
|
-
};
|
|
556
|
-
export const generateMockData = async (database, databaseId, configCollections) => {
|
|
557
|
-
for (const { collection, mockFunction } of configCollections) {
|
|
558
|
-
if (mockFunction) {
|
|
559
|
-
MessageFormatter.progress(`Generating mock data for collection: ${collection.name}`, { prefix: "Mock Data" });
|
|
560
|
-
const mockData = mockFunction();
|
|
561
|
-
for (const data of mockData) {
|
|
562
|
-
await database.createDocument(databaseId, collection.$id, ID.unique(), data);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
};
|
|
567
|
-
export const fetchAllCollections = async (dbId, database) => {
|
|
568
|
-
MessageFormatter.progress(`Fetching all collections for database ID: ${dbId}`, { prefix: "Collections" });
|
|
569
|
-
let collections = [];
|
|
570
|
-
let moreCollections = true;
|
|
571
|
-
let lastCollectionId;
|
|
572
|
-
while (moreCollections) {
|
|
573
|
-
const queries = [Query.limit(500)];
|
|
574
|
-
if (lastCollectionId) {
|
|
575
|
-
queries.push(Query.cursorAfter(lastCollectionId));
|
|
576
|
-
}
|
|
577
|
-
const response = await tryAwaitWithRetry(async () => await database.listCollections(dbId, queries));
|
|
578
|
-
collections = collections.concat(response.collections);
|
|
579
|
-
moreCollections = response.collections.length === 500;
|
|
580
|
-
if (moreCollections) {
|
|
581
|
-
lastCollectionId =
|
|
582
|
-
response.collections[response.collections.length - 1].$id;
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
MessageFormatter.success(`Fetched a total of ${collections.length} collections`, { prefix: "Collections" });
|
|
586
|
-
return collections;
|
|
587
|
-
};
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type { Attribute } from "appwrite-utils";
|
|
2
|
-
interface ColumnPropertyChange {
|
|
3
|
-
property: string;
|
|
4
|
-
oldValue: any;
|
|
5
|
-
newValue: any;
|
|
6
|
-
requiresRecreate: boolean;
|
|
7
|
-
}
|
|
8
|
-
interface ColumnOperationPlan {
|
|
9
|
-
toCreate: Attribute[];
|
|
10
|
-
toUpdate: Array<{
|
|
11
|
-
attribute: Attribute;
|
|
12
|
-
changes: ColumnPropertyChange[];
|
|
13
|
-
}>;
|
|
14
|
-
toRecreate: Array<{
|
|
15
|
-
oldAttribute: any;
|
|
16
|
-
newAttribute: Attribute;
|
|
17
|
-
}>;
|
|
18
|
-
toDelete: Array<{
|
|
19
|
-
attribute: any;
|
|
20
|
-
}>;
|
|
21
|
-
unchanged: string[];
|
|
22
|
-
}
|
|
23
|
-
type ComparableColumn = {
|
|
24
|
-
key: string;
|
|
25
|
-
type: string;
|
|
26
|
-
required?: boolean;
|
|
27
|
-
array?: boolean;
|
|
28
|
-
default?: any;
|
|
29
|
-
size?: number;
|
|
30
|
-
min?: number;
|
|
31
|
-
max?: number;
|
|
32
|
-
elements?: string[];
|
|
33
|
-
encrypt?: boolean;
|
|
34
|
-
relatedCollection?: string;
|
|
35
|
-
relationType?: string;
|
|
36
|
-
twoWay?: boolean;
|
|
37
|
-
twoWayKey?: string;
|
|
38
|
-
onDelete?: string;
|
|
39
|
-
side?: string;
|
|
40
|
-
};
|
|
41
|
-
export declare function normalizeAttributeToComparable(attr: Attribute): ComparableColumn;
|
|
42
|
-
export declare function normalizeColumnToComparable(col: any): ComparableColumn;
|
|
43
|
-
export declare function isColumnEqualToColumn(a: any, b: any): boolean;
|
|
44
|
-
export declare function isIndexEqualToIndex(a: any, b: any): boolean;
|
|
45
|
-
/**
|
|
46
|
-
* Enhanced version of columns diff with detailed change analysis
|
|
47
|
-
* Order: desired first, then existing (matches internal usage here)
|
|
48
|
-
*/
|
|
49
|
-
export declare function diffColumnsDetailed(desiredAttributes: Attribute[], existingColumns: any[]): ColumnOperationPlan;
|
|
50
|
-
/**
|
|
51
|
-
* Returns true if there is any difference between existing columns and desired attributes
|
|
52
|
-
*/
|
|
53
|
-
export declare function areTableColumnsDiff(existingColumns: any[], desired: Attribute[]): boolean;
|
|
54
|
-
export declare function diffTableColumns(existingColumns: any[], desired: Attribute[]): {
|
|
55
|
-
toCreate: Attribute[];
|
|
56
|
-
toUpdate: Attribute[];
|
|
57
|
-
unchanged: string[];
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Execute the column operation plan using the adapter
|
|
61
|
-
*/
|
|
62
|
-
export declare function executeColumnOperations(adapter: any, databaseId: string, tableId: string, plan: ColumnOperationPlan): Promise<{
|
|
63
|
-
success: string[];
|
|
64
|
-
errors: Array<{
|
|
65
|
-
column: string;
|
|
66
|
-
error: string;
|
|
67
|
-
}>;
|
|
68
|
-
}>;
|
|
69
|
-
/**
|
|
70
|
-
* Integration function for methods.ts - processes columns using enhanced logic
|
|
71
|
-
*/
|
|
72
|
-
export declare function processTableColumns(adapter: any, databaseId: string, tableId: string, desiredAttributes: Attribute[], existingColumns?: any[]): Promise<{
|
|
73
|
-
totalProcessed: number;
|
|
74
|
-
success: string[];
|
|
75
|
-
errors: Array<{
|
|
76
|
-
column: string;
|
|
77
|
-
error: string;
|
|
78
|
-
}>;
|
|
79
|
-
summary: {
|
|
80
|
-
created: number;
|
|
81
|
-
updated: number;
|
|
82
|
-
recreated: number;
|
|
83
|
-
unchanged: number;
|
|
84
|
-
};
|
|
85
|
-
}>;
|
|
86
|
-
export {};
|