appwrite-utils-cli 1.5.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +199 -0
- package/README.md +251 -29
- package/dist/adapters/AdapterFactory.d.ts +10 -3
- package/dist/adapters/AdapterFactory.js +213 -17
- package/dist/adapters/TablesDBAdapter.js +60 -17
- package/dist/backups/operations/bucketBackup.d.ts +19 -0
- package/dist/backups/operations/bucketBackup.js +197 -0
- package/dist/backups/operations/collectionBackup.d.ts +30 -0
- package/dist/backups/operations/collectionBackup.js +201 -0
- package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
- package/dist/backups/operations/comprehensiveBackup.js +238 -0
- package/dist/backups/schemas/bucketManifest.d.ts +93 -0
- package/dist/backups/schemas/bucketManifest.js +33 -0
- package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
- package/dist/backups/schemas/comprehensiveManifest.js +32 -0
- package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
- package/dist/backups/tracking/centralizedTracking.js +274 -0
- package/dist/cli/commands/configCommands.d.ts +8 -0
- package/dist/cli/commands/configCommands.js +160 -0
- package/dist/cli/commands/databaseCommands.d.ts +13 -0
- package/dist/cli/commands/databaseCommands.js +478 -0
- package/dist/cli/commands/functionCommands.d.ts +7 -0
- package/dist/cli/commands/functionCommands.js +289 -0
- package/dist/cli/commands/schemaCommands.d.ts +7 -0
- package/dist/cli/commands/schemaCommands.js +134 -0
- package/dist/cli/commands/transferCommands.d.ts +5 -0
- package/dist/cli/commands/transferCommands.js +384 -0
- package/dist/collections/attributes.d.ts +5 -4
- package/dist/collections/attributes.js +539 -246
- package/dist/collections/indexes.js +39 -37
- package/dist/collections/methods.d.ts +2 -16
- package/dist/collections/methods.js +90 -538
- package/dist/collections/transferOperations.d.ts +7 -0
- package/dist/collections/transferOperations.js +331 -0
- package/dist/collections/wipeOperations.d.ts +16 -0
- package/dist/collections/wipeOperations.js +328 -0
- package/dist/config/configMigration.d.ts +87 -0
- package/dist/config/configMigration.js +390 -0
- package/dist/config/configValidation.d.ts +66 -0
- package/dist/config/configValidation.js +358 -0
- package/dist/config/yamlConfig.d.ts +455 -1
- package/dist/config/yamlConfig.js +145 -52
- package/dist/databases/methods.js +3 -2
- package/dist/databases/setup.d.ts +1 -2
- package/dist/databases/setup.js +9 -87
- package/dist/examples/yamlTerminologyExample.d.ts +42 -0
- package/dist/examples/yamlTerminologyExample.js +269 -0
- package/dist/functions/deployments.js +11 -10
- package/dist/functions/methods.d.ts +1 -1
- package/dist/functions/methods.js +5 -4
- package/dist/init.js +9 -9
- package/dist/interactiveCLI.d.ts +8 -17
- package/dist/interactiveCLI.js +181 -1172
- package/dist/main.js +364 -21
- package/dist/migrations/afterImportActions.js +22 -30
- package/dist/migrations/appwriteToX.js +71 -25
- package/dist/migrations/dataLoader.js +35 -26
- package/dist/migrations/importController.js +29 -30
- package/dist/migrations/relationships.js +13 -12
- package/dist/migrations/services/ImportOrchestrator.js +16 -19
- package/dist/migrations/transfer.js +46 -46
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +3 -1
- package/dist/migrations/yaml/YamlImportConfigLoader.js +6 -3
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +9 -3
- package/dist/migrations/yaml/YamlImportIntegration.js +22 -11
- package/dist/migrations/yaml/generateImportSchemas.d.ts +14 -1
- package/dist/migrations/yaml/generateImportSchemas.js +736 -7
- package/dist/schemas/authUser.d.ts +1 -1
- package/dist/setupController.js +3 -2
- package/dist/shared/backupMetadataSchema.d.ts +94 -0
- package/dist/shared/backupMetadataSchema.js +38 -0
- package/dist/shared/backupTracking.d.ts +18 -0
- package/dist/shared/backupTracking.js +176 -0
- package/dist/shared/confirmationDialogs.js +15 -15
- package/dist/shared/errorUtils.d.ts +54 -0
- package/dist/shared/errorUtils.js +95 -0
- package/dist/shared/functionManager.js +20 -19
- package/dist/shared/indexManager.js +12 -11
- package/dist/shared/jsonSchemaGenerator.js +10 -26
- package/dist/shared/logging.d.ts +51 -0
- package/dist/shared/logging.js +70 -0
- package/dist/shared/messageFormatter.d.ts +2 -0
- package/dist/shared/messageFormatter.js +10 -0
- package/dist/shared/migrationHelpers.d.ts +6 -16
- package/dist/shared/migrationHelpers.js +24 -21
- package/dist/shared/operationLogger.d.ts +8 -1
- package/dist/shared/operationLogger.js +11 -24
- package/dist/shared/operationQueue.d.ts +28 -1
- package/dist/shared/operationQueue.js +268 -66
- package/dist/shared/operationsTable.d.ts +26 -0
- package/dist/shared/operationsTable.js +286 -0
- package/dist/shared/operationsTableSchema.d.ts +48 -0
- package/dist/shared/operationsTableSchema.js +35 -0
- package/dist/shared/relationshipExtractor.d.ts +56 -0
- package/dist/shared/relationshipExtractor.js +138 -0
- package/dist/shared/schemaGenerator.d.ts +19 -1
- package/dist/shared/schemaGenerator.js +56 -75
- package/dist/storage/backupCompression.d.ts +20 -0
- package/dist/storage/backupCompression.js +67 -0
- package/dist/storage/methods.d.ts +16 -2
- package/dist/storage/methods.js +98 -14
- package/dist/users/methods.js +9 -8
- package/dist/utils/configDiscovery.d.ts +78 -0
- package/dist/utils/configDiscovery.js +430 -0
- package/dist/utils/directoryUtils.d.ts +22 -0
- package/dist/utils/directoryUtils.js +59 -0
- package/dist/utils/getClientFromConfig.d.ts +17 -8
- package/dist/utils/getClientFromConfig.js +162 -17
- package/dist/utils/helperFunctions.d.ts +16 -2
- package/dist/utils/helperFunctions.js +19 -5
- package/dist/utils/loadConfigs.d.ts +34 -9
- package/dist/utils/loadConfigs.js +236 -316
- package/dist/utils/pathResolvers.d.ts +53 -0
- package/dist/utils/pathResolvers.js +72 -0
- package/dist/utils/projectConfig.d.ts +119 -0
- package/dist/utils/projectConfig.js +171 -0
- package/dist/utils/retryFailedPromises.js +4 -2
- package/dist/utils/sessionAuth.d.ts +48 -0
- package/dist/utils/sessionAuth.js +164 -0
- package/dist/utils/sessionPreservationExample.d.ts +1666 -0
- package/dist/utils/sessionPreservationExample.js +101 -0
- package/dist/utils/setupFiles.js +301 -41
- package/dist/utils/typeGuards.d.ts +35 -0
- package/dist/utils/typeGuards.js +57 -0
- package/dist/utils/versionDetection.js +145 -9
- package/dist/utils/yamlConverter.d.ts +53 -3
- package/dist/utils/yamlConverter.js +232 -13
- package/dist/utils/yamlLoader.d.ts +70 -0
- package/dist/utils/yamlLoader.js +263 -0
- package/dist/utilsController.d.ts +36 -3
- package/dist/utilsController.js +186 -56
- package/package.json +12 -2
- package/src/adapters/AdapterFactory.ts +263 -35
- package/src/adapters/TablesDBAdapter.ts +225 -36
- package/src/backups/operations/bucketBackup.ts +277 -0
- package/src/backups/operations/collectionBackup.ts +310 -0
- package/src/backups/operations/comprehensiveBackup.ts +342 -0
- package/src/backups/schemas/bucketManifest.ts +78 -0
- package/src/backups/schemas/comprehensiveManifest.ts +76 -0
- package/src/backups/tracking/centralizedTracking.ts +352 -0
- package/src/cli/commands/configCommands.ts +194 -0
- package/src/cli/commands/databaseCommands.ts +635 -0
- package/src/cli/commands/functionCommands.ts +379 -0
- package/src/cli/commands/schemaCommands.ts +163 -0
- package/src/cli/commands/transferCommands.ts +457 -0
- package/src/collections/attributes.ts +900 -621
- package/src/collections/attributes.ts.backup +1555 -0
- package/src/collections/indexes.ts +116 -114
- package/src/collections/methods.ts +295 -968
- package/src/collections/transferOperations.ts +516 -0
- package/src/collections/wipeOperations.ts +501 -0
- package/src/config/README.md +274 -0
- package/src/config/configMigration.ts +575 -0
- package/src/config/configValidation.ts +445 -0
- package/src/config/yamlConfig.ts +168 -55
- package/src/databases/methods.ts +3 -2
- package/src/databases/setup.ts +11 -138
- package/src/examples/yamlTerminologyExample.ts +341 -0
- package/src/functions/deployments.ts +14 -12
- package/src/functions/methods.ts +11 -11
- package/src/functions/templates/hono-typescript/README.md +286 -0
- package/src/functions/templates/hono-typescript/package.json +26 -0
- package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
- package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
- package/src/functions/templates/hono-typescript/src/app.ts +180 -0
- package/src/functions/templates/hono-typescript/src/context.ts +103 -0
- package/src/functions/templates/hono-typescript/src/index.ts +54 -0
- package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
- package/src/functions/templates/hono-typescript/tsconfig.json +20 -0
- package/src/functions/templates/typescript-node/package.json +2 -1
- package/src/functions/templates/typescript-node/src/context.ts +103 -0
- package/src/functions/templates/typescript-node/src/index.ts +18 -12
- package/src/functions/templates/uv/pyproject.toml +1 -0
- package/src/functions/templates/uv/src/context.py +125 -0
- package/src/functions/templates/uv/src/index.py +35 -5
- package/src/init.ts +9 -11
- package/src/interactiveCLI.ts +278 -1596
- package/src/main.ts +418 -24
- package/src/migrations/afterImportActions.ts +71 -44
- package/src/migrations/appwriteToX.ts +100 -34
- package/src/migrations/dataLoader.ts +48 -34
- package/src/migrations/importController.ts +44 -39
- package/src/migrations/relationships.ts +28 -18
- package/src/migrations/services/ImportOrchestrator.ts +24 -27
- package/src/migrations/transfer.ts +159 -121
- package/src/migrations/yaml/YamlImportConfigLoader.ts +11 -4
- package/src/migrations/yaml/YamlImportIntegration.ts +47 -20
- package/src/migrations/yaml/generateImportSchemas.ts +751 -12
- package/src/setupController.ts +3 -2
- package/src/shared/backupMetadataSchema.ts +93 -0
- package/src/shared/backupTracking.ts +211 -0
- package/src/shared/confirmationDialogs.ts +19 -19
- package/src/shared/errorUtils.ts +110 -0
- package/src/shared/functionManager.ts +21 -20
- package/src/shared/indexManager.ts +12 -11
- package/src/shared/jsonSchemaGenerator.ts +38 -52
- package/src/shared/logging.ts +75 -0
- package/src/shared/messageFormatter.ts +14 -1
- package/src/shared/migrationHelpers.ts +45 -38
- package/src/shared/operationLogger.ts +11 -36
- package/src/shared/operationQueue.ts +322 -93
- package/src/shared/operationsTable.ts +338 -0
- package/src/shared/operationsTableSchema.ts +60 -0
- package/src/shared/relationshipExtractor.ts +214 -0
- package/src/shared/schemaGenerator.ts +179 -219
- package/src/storage/backupCompression.ts +88 -0
- package/src/storage/methods.ts +131 -34
- package/src/users/methods.ts +11 -9
- package/src/utils/configDiscovery.ts +502 -0
- package/src/utils/directoryUtils.ts +61 -0
- package/src/utils/getClientFromConfig.ts +205 -22
- package/src/utils/helperFunctions.ts +23 -5
- package/src/utils/loadConfigs.ts +313 -345
- package/src/utils/pathResolvers.ts +81 -0
- package/src/utils/projectConfig.ts +299 -0
- package/src/utils/retryFailedPromises.ts +4 -2
- package/src/utils/sessionAuth.ts +230 -0
- package/src/utils/setupFiles.ts +322 -54
- package/src/utils/typeGuards.ts +65 -0
- package/src/utils/versionDetection.ts +218 -64
- package/src/utils/yamlConverter.ts +296 -13
- package/src/utils/yamlLoader.ts +364 -0
- package/src/utilsController.ts +314 -110
- package/tests/README.md +497 -0
- package/tests/adapters/AdapterFactory.test.ts +277 -0
- package/tests/integration/syncOperations.test.ts +463 -0
- package/tests/jest.config.js +25 -0
- package/tests/migration/configMigration.test.ts +546 -0
- package/tests/setup.ts +62 -0
- package/tests/testUtils.ts +340 -0
- package/tests/utils/loadConfigs.test.ts +350 -0
- package/tests/validation/configValidation.test.ts +412 -0
- package/src/utils/schemaStrings.ts +0 -517
@@ -7,17 +7,24 @@
|
|
7
7
|
*/
|
8
8
|
|
9
9
|
import type { AppwriteConfig } from "appwrite-utils";
|
10
|
-
import { detectAppwriteVersionCached, type ApiMode, type VersionDetectionResult } from "../utils/versionDetection.js";
|
10
|
+
import { detectAppwriteVersionCached, isVersionAtLeast, type ApiMode, type VersionDetectionResult } from "../utils/versionDetection.js";
|
11
11
|
import type { DatabaseAdapter } from './DatabaseAdapter.js';
|
12
12
|
import { TablesDBAdapter } from './TablesDBAdapter.js';
|
13
13
|
import { LegacyAdapter } from './LegacyAdapter.js';
|
14
|
+
import { logger } from '../shared/logging.js';
|
15
|
+
import { getClientWithAuth } from '../utils/getClientFromConfig.js';
|
16
|
+
import { isValidSessionCookie } from '../utils/sessionAuth.js';
|
17
|
+
import { MessageFormatter } from '../shared/messageFormatter.js';
|
14
18
|
|
15
19
|
export interface AdapterFactoryConfig {
|
16
20
|
appwriteEndpoint: string;
|
17
21
|
appwriteProject: string;
|
18
|
-
appwriteKey
|
22
|
+
appwriteKey?: string; // Made optional to support session-only auth
|
19
23
|
apiMode?: 'auto' | 'legacy' | 'tablesdb';
|
20
24
|
forceRefresh?: boolean; // Skip detection cache
|
25
|
+
sessionCookie?: string; // Session authentication support
|
26
|
+
authMethod?: 'session' | 'apikey' | 'auto'; // Authentication method preference
|
27
|
+
preConfiguredClient?: any; // Pre-configured authenticated client
|
21
28
|
}
|
22
29
|
|
23
30
|
export interface AdapterFactoryResult {
|
@@ -38,12 +45,36 @@ export class AdapterFactory {
|
|
38
45
|
* Create a database adapter based on configuration and detection
|
39
46
|
*/
|
40
47
|
static async create(config: AdapterFactoryConfig): Promise<AdapterFactoryResult> {
|
48
|
+
const startTime = Date.now();
|
49
|
+
|
50
|
+
// Validate authentication configuration
|
51
|
+
this.validateAuthConfig(config);
|
52
|
+
|
41
53
|
const cacheKey = `${config.appwriteEndpoint}:${config.appwriteProject}:${config.apiMode || 'auto'}`;
|
42
|
-
|
54
|
+
|
55
|
+
logger.info('Creating database adapter', {
|
56
|
+
endpoint: config.appwriteEndpoint,
|
57
|
+
project: config.appwriteProject,
|
58
|
+
requestedApiMode: config.apiMode || 'auto',
|
59
|
+
authMethod: config.authMethod || 'auto',
|
60
|
+
hasSessionCookie: !!config.sessionCookie,
|
61
|
+
hasPreConfiguredClient: !!config.preConfiguredClient,
|
62
|
+
forceRefresh: config.forceRefresh,
|
63
|
+
cacheKey,
|
64
|
+
operation: 'AdapterFactory.create'
|
65
|
+
});
|
66
|
+
|
43
67
|
// Check cache first (unless force refresh)
|
44
68
|
if (!config.forceRefresh) {
|
45
69
|
const cached = this.getCachedAdapter(cacheKey);
|
46
70
|
if (cached) {
|
71
|
+
const cacheAge = Date.now() - cached.timestamp;
|
72
|
+
logger.info('Using cached adapter', {
|
73
|
+
cacheKey,
|
74
|
+
cacheAge,
|
75
|
+
apiMode: cached.adapter.getApiMode(),
|
76
|
+
operation: 'AdapterFactory.create'
|
77
|
+
});
|
47
78
|
return {
|
48
79
|
adapter: cached.adapter,
|
49
80
|
apiMode: cached.adapter.getApiMode(),
|
@@ -55,27 +86,84 @@ export class AdapterFactory {
|
|
55
86
|
// Determine API mode
|
56
87
|
let apiMode: ApiMode;
|
57
88
|
let detectionResult: VersionDetectionResult | undefined;
|
58
|
-
|
89
|
+
|
59
90
|
if (config.apiMode && config.apiMode !== 'auto') {
|
60
91
|
// Use explicitly configured mode
|
61
92
|
apiMode = config.apiMode;
|
93
|
+
logger.info('Using explicitly configured API mode', {
|
94
|
+
apiMode,
|
95
|
+
endpoint: config.appwriteEndpoint,
|
96
|
+
operation: 'AdapterFactory.create'
|
97
|
+
});
|
62
98
|
} else {
|
63
99
|
// Auto-detect API mode
|
100
|
+
logger.info('Starting API mode auto-detection', {
|
101
|
+
endpoint: config.appwriteEndpoint,
|
102
|
+
project: config.appwriteProject,
|
103
|
+
forceRefresh: config.forceRefresh,
|
104
|
+
operation: 'AdapterFactory.create'
|
105
|
+
});
|
106
|
+
|
107
|
+
const detectionStartTime = Date.now();
|
108
|
+
// For version detection, we need some form of authentication
|
109
|
+
const authKey = config.appwriteKey || '';
|
64
110
|
detectionResult = await detectAppwriteVersionCached(
|
65
111
|
config.appwriteEndpoint,
|
66
112
|
config.appwriteProject,
|
67
|
-
|
113
|
+
authKey,
|
68
114
|
config.forceRefresh
|
69
115
|
);
|
116
|
+
const detectionDuration = Date.now() - detectionStartTime;
|
117
|
+
|
70
118
|
apiMode = detectionResult.apiMode;
|
119
|
+
|
120
|
+
logger.info('API mode detection completed', {
|
121
|
+
apiMode,
|
122
|
+
detectionMethod: detectionResult.detectionMethod,
|
123
|
+
confidence: detectionResult.confidence,
|
124
|
+
serverVersion: detectionResult.serverVersion,
|
125
|
+
detectionDuration,
|
126
|
+
endpoint: config.appwriteEndpoint,
|
127
|
+
operation: 'AdapterFactory.create'
|
128
|
+
});
|
129
|
+
|
130
|
+
// Add version-based safety check to prevent using TablesDB on old servers
|
131
|
+
if (detectionResult.serverVersion &&
|
132
|
+
!isVersionAtLeast(detectionResult.serverVersion, '1.8.0') &&
|
133
|
+
apiMode === 'tablesdb') {
|
134
|
+
logger.warn('Overriding TablesDB detection - server version too old', {
|
135
|
+
serverVersion: detectionResult.serverVersion,
|
136
|
+
detectedMode: apiMode,
|
137
|
+
overrideMode: 'legacy',
|
138
|
+
operation: 'AdapterFactory.create'
|
139
|
+
});
|
140
|
+
apiMode = 'legacy';
|
141
|
+
}
|
71
142
|
}
|
72
143
|
|
73
144
|
// Create appropriate adapter
|
145
|
+
logger.info('Creating adapter instance', {
|
146
|
+
apiMode,
|
147
|
+
endpoint: config.appwriteEndpoint,
|
148
|
+
operation: 'AdapterFactory.create'
|
149
|
+
});
|
150
|
+
|
151
|
+
const adapterStartTime = Date.now();
|
74
152
|
const result = await this.createAdapter(config, apiMode);
|
75
|
-
|
153
|
+
const adapterDuration = Date.now() - adapterStartTime;
|
154
|
+
|
76
155
|
// Cache the result
|
77
156
|
this.setCachedAdapter(cacheKey, result.adapter);
|
78
|
-
|
157
|
+
|
158
|
+
const totalDuration = Date.now() - startTime;
|
159
|
+
logger.info('Adapter creation completed', {
|
160
|
+
apiMode,
|
161
|
+
adapterDuration,
|
162
|
+
totalDuration,
|
163
|
+
cached: true,
|
164
|
+
operation: 'AdapterFactory.create'
|
165
|
+
});
|
166
|
+
|
79
167
|
return {
|
80
168
|
...result,
|
81
169
|
apiMode,
|
@@ -116,24 +204,76 @@ export class AdapterFactory {
|
|
116
204
|
private static async createTablesDBAdapter(
|
117
205
|
config: AdapterFactoryConfig
|
118
206
|
): Promise<{ adapter: DatabaseAdapter; client: any }> {
|
207
|
+
const startTime = Date.now();
|
208
|
+
|
119
209
|
try {
|
210
|
+
logger.info('Loading TablesDB SDK', {
|
211
|
+
endpoint: config.appwriteEndpoint,
|
212
|
+
operation: 'createTablesDBAdapter'
|
213
|
+
});
|
214
|
+
|
120
215
|
// Dynamic import of TablesDB SDK
|
216
|
+
const importStartTime = Date.now();
|
121
217
|
const { Client, TablesDB } = await import('node-appwrite-tablesdb');
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
218
|
+
const importDuration = Date.now() - importStartTime;
|
219
|
+
|
220
|
+
logger.debug('TablesDB SDK import successful', {
|
221
|
+
importDuration,
|
222
|
+
operation: 'createTablesDBAdapter'
|
223
|
+
});
|
224
|
+
|
225
|
+
// Use pre-configured client or create session-aware client with TablesDB Client
|
226
|
+
let client: any;
|
227
|
+
if (config.preConfiguredClient) {
|
228
|
+
client = config.preConfiguredClient;
|
229
|
+
} else {
|
230
|
+
client = new Client()
|
231
|
+
.setEndpoint(config.appwriteEndpoint)
|
232
|
+
.setProject(config.appwriteProject);
|
233
|
+
|
234
|
+
// Set authentication method based on priority
|
235
|
+
if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
|
236
|
+
(client as any).setSession(config.sessionCookie);
|
237
|
+
logger.debug('Using session authentication for TablesDB adapter', {
|
238
|
+
project: config.appwriteProject,
|
239
|
+
operation: 'createTablesDBAdapter'
|
240
|
+
});
|
241
|
+
} else if (config.appwriteKey) {
|
242
|
+
client.setKey(config.appwriteKey);
|
243
|
+
logger.debug('Using API key authentication for TablesDB adapter', {
|
244
|
+
project: config.appwriteProject,
|
245
|
+
operation: 'createTablesDBAdapter'
|
246
|
+
});
|
247
|
+
}
|
248
|
+
}
|
249
|
+
|
128
250
|
const tablesDB = new TablesDB(client);
|
129
251
|
const adapter = new TablesDBAdapter(tablesDB);
|
130
|
-
|
252
|
+
|
253
|
+
const totalDuration = Date.now() - startTime;
|
254
|
+
logger.info('TablesDB adapter created successfully', {
|
255
|
+
totalDuration,
|
256
|
+
importDuration,
|
257
|
+
endpoint: config.appwriteEndpoint,
|
258
|
+
operation: 'createTablesDBAdapter'
|
259
|
+
});
|
260
|
+
|
131
261
|
return { adapter, client };
|
132
|
-
|
262
|
+
|
133
263
|
} catch (error) {
|
134
|
-
|
135
|
-
|
136
|
-
|
264
|
+
const errorDuration = Date.now() - startTime;
|
265
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
266
|
+
|
267
|
+
MessageFormatter.warning('Failed to create TablesDB adapter - falling back to legacy', { prefix: "Adapter" });
|
268
|
+
|
269
|
+
logger.warn('TablesDB adapter creation failed, falling back to legacy', {
|
270
|
+
error: errorMessage,
|
271
|
+
errorDuration,
|
272
|
+
endpoint: config.appwriteEndpoint,
|
273
|
+
operation: 'createTablesDBAdapter'
|
274
|
+
});
|
275
|
+
|
276
|
+
// Fallback to legacy adapter if TablesDB creation fails
|
137
277
|
return this.createLegacyAdapter(config);
|
138
278
|
}
|
139
279
|
}
|
@@ -144,22 +284,74 @@ export class AdapterFactory {
|
|
144
284
|
private static async createLegacyAdapter(
|
145
285
|
config: AdapterFactoryConfig
|
146
286
|
): Promise<{ adapter: DatabaseAdapter; client: any }> {
|
287
|
+
const startTime = Date.now();
|
288
|
+
|
147
289
|
try {
|
290
|
+
logger.info('Loading legacy Appwrite SDK', {
|
291
|
+
endpoint: config.appwriteEndpoint,
|
292
|
+
operation: 'createLegacyAdapter'
|
293
|
+
});
|
294
|
+
|
148
295
|
// Dynamic import of legacy SDK
|
296
|
+
const importStartTime = Date.now();
|
149
297
|
const { Client, Databases } = await import('node-appwrite');
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
298
|
+
const importDuration = Date.now() - importStartTime;
|
299
|
+
|
300
|
+
logger.debug('Legacy SDK import successful', {
|
301
|
+
importDuration,
|
302
|
+
operation: 'createLegacyAdapter'
|
303
|
+
});
|
304
|
+
|
305
|
+
// Use pre-configured client or create session-aware client with Legacy Client
|
306
|
+
let client: any;
|
307
|
+
if (config.preConfiguredClient) {
|
308
|
+
client = config.preConfiguredClient;
|
309
|
+
} else {
|
310
|
+
client = new Client()
|
311
|
+
.setEndpoint(config.appwriteEndpoint)
|
312
|
+
.setProject(config.appwriteProject);
|
313
|
+
|
314
|
+
// Set authentication method based on priority
|
315
|
+
if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
|
316
|
+
(client as any).setSession(config.sessionCookie);
|
317
|
+
logger.debug('Using session authentication for Legacy adapter', {
|
318
|
+
project: config.appwriteProject,
|
319
|
+
operation: 'createLegacyAdapter'
|
320
|
+
});
|
321
|
+
} else if (config.appwriteKey) {
|
322
|
+
client.setKey(config.appwriteKey);
|
323
|
+
logger.debug('Using API key authentication for Legacy adapter', {
|
324
|
+
project: config.appwriteProject,
|
325
|
+
operation: 'createLegacyAdapter'
|
326
|
+
});
|
327
|
+
}
|
328
|
+
}
|
329
|
+
|
156
330
|
const databases = new Databases(client);
|
157
331
|
const adapter = new LegacyAdapter(databases);
|
158
|
-
|
332
|
+
|
333
|
+
const totalDuration = Date.now() - startTime;
|
334
|
+
logger.info('Legacy adapter created successfully', {
|
335
|
+
totalDuration,
|
336
|
+
importDuration,
|
337
|
+
endpoint: config.appwriteEndpoint,
|
338
|
+
operation: 'createLegacyAdapter'
|
339
|
+
});
|
340
|
+
|
159
341
|
return { adapter, client };
|
160
|
-
|
342
|
+
|
161
343
|
} catch (error) {
|
162
|
-
|
344
|
+
const errorDuration = Date.now() - startTime;
|
345
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
346
|
+
|
347
|
+
logger.error('Failed to load legacy Appwrite SDK', {
|
348
|
+
error: errorMessage,
|
349
|
+
errorDuration,
|
350
|
+
endpoint: config.appwriteEndpoint,
|
351
|
+
operation: 'createLegacyAdapter'
|
352
|
+
});
|
353
|
+
|
354
|
+
throw new Error(`Failed to load legacy Appwrite SDK: ${errorMessage}`);
|
163
355
|
}
|
164
356
|
}
|
165
357
|
|
@@ -198,6 +390,39 @@ export class AdapterFactory {
|
|
198
390
|
static clearCache(): void {
|
199
391
|
this.cache.clear();
|
200
392
|
}
|
393
|
+
|
394
|
+
/**
|
395
|
+
* Validate authentication configuration
|
396
|
+
*/
|
397
|
+
private static validateAuthConfig(config: AdapterFactoryConfig): void {
|
398
|
+
const hasApiKey = config.appwriteKey && config.appwriteKey.trim().length > 0;
|
399
|
+
const hasSessionCookie = config.sessionCookie && isValidSessionCookie(config.sessionCookie);
|
400
|
+
const hasPreConfiguredClient = !!config.preConfiguredClient;
|
401
|
+
|
402
|
+
// Must have at least one authentication method
|
403
|
+
if (!hasApiKey && !hasSessionCookie && !hasPreConfiguredClient) {
|
404
|
+
throw new Error(
|
405
|
+
`No valid authentication method provided for project ${config.appwriteProject}. ` +
|
406
|
+
`Please provide an API key, session cookie, or pre-configured client.`
|
407
|
+
);
|
408
|
+
}
|
409
|
+
|
410
|
+
// Validate session cookie format if provided
|
411
|
+
if (config.sessionCookie && !isValidSessionCookie(config.sessionCookie)) {
|
412
|
+
throw new Error(
|
413
|
+
`Invalid session cookie format provided for project ${config.appwriteProject}. ` +
|
414
|
+
`Session cookie must be a valid JWT token.`
|
415
|
+
);
|
416
|
+
}
|
417
|
+
|
418
|
+
logger.debug('Authentication configuration validated', {
|
419
|
+
hasApiKey,
|
420
|
+
hasSessionCookie,
|
421
|
+
hasPreConfiguredClient,
|
422
|
+
authMethod: config.authMethod || 'auto',
|
423
|
+
operation: 'validateAuthConfig'
|
424
|
+
});
|
425
|
+
}
|
201
426
|
|
202
427
|
/**
|
203
428
|
* Test connection and API capabilities
|
@@ -254,16 +479,18 @@ export class AdapterFactory {
|
|
254
479
|
export async function createDatabaseAdapter(
|
255
480
|
endpoint: string,
|
256
481
|
project: string,
|
257
|
-
apiKey
|
258
|
-
mode: 'auto' | 'legacy' | 'tablesdb' = 'auto'
|
482
|
+
apiKey?: string,
|
483
|
+
mode: 'auto' | 'legacy' | 'tablesdb' = 'auto',
|
484
|
+
sessionCookie?: string
|
259
485
|
): Promise<DatabaseAdapter> {
|
260
486
|
const result = await AdapterFactory.create({
|
261
487
|
appwriteEndpoint: endpoint,
|
262
488
|
appwriteProject: project,
|
263
489
|
appwriteKey: apiKey,
|
264
|
-
apiMode: mode
|
490
|
+
apiMode: mode,
|
491
|
+
sessionCookie
|
265
492
|
});
|
266
|
-
|
493
|
+
|
267
494
|
return result.adapter;
|
268
495
|
}
|
269
496
|
|
@@ -273,21 +500,22 @@ export async function createDatabaseAdapter(
|
|
273
500
|
export async function getApiCapabilities(
|
274
501
|
endpoint: string,
|
275
502
|
project: string,
|
276
|
-
apiKey
|
503
|
+
apiKey?: string,
|
504
|
+
sessionCookie?: string
|
277
505
|
): Promise<{
|
278
506
|
apiMode: ApiMode;
|
279
507
|
terminology: { container: string; item: string; service: string };
|
280
508
|
capabilities: string[];
|
281
509
|
}> {
|
282
|
-
const adapter = await createDatabaseAdapter(endpoint, project, apiKey, 'auto');
|
510
|
+
const adapter = await createDatabaseAdapter(endpoint, project, apiKey, 'auto', sessionCookie);
|
283
511
|
const metadata = adapter.getMetadata();
|
284
|
-
|
512
|
+
|
285
513
|
const capabilities = [];
|
286
514
|
if (metadata.capabilities.bulkOperations) capabilities.push('Bulk Operations');
|
287
515
|
if (metadata.capabilities.advancedQueries) capabilities.push('Advanced Queries');
|
288
516
|
if (metadata.capabilities.realtime) capabilities.push('Realtime');
|
289
517
|
if (metadata.capabilities.transactions) capabilities.push('Transactions');
|
290
|
-
|
518
|
+
|
291
519
|
return {
|
292
520
|
apiMode: metadata.apiMode,
|
293
521
|
terminology: metadata.terminology,
|