appwrite-utils-cli 1.5.1 → 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 +186 -1171
- 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 +276 -1591
- 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
@@ -3,11 +3,20 @@ import yaml from "js-yaml";
|
|
3
3
|
import fs from "fs";
|
4
4
|
import path from "path";
|
5
5
|
import { AppwriteConfigSchema, RuntimeSchema, FunctionScopes, FunctionSpecifications, permissionsSchema, PermissionToAppwritePermission } from "appwrite-utils";
|
6
|
+
import { shouldIgnoreDirectory } from "../utils/directoryUtils.js";
|
7
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
6
8
|
const YamlConfigSchema = z.object({
|
7
9
|
appwrite: z.object({
|
8
10
|
endpoint: z.string().default("https://cloud.appwrite.io/v1"),
|
9
11
|
project: z.string(),
|
10
12
|
key: z.string(),
|
13
|
+
// Session authentication support
|
14
|
+
sessionCookie: z.string().optional(),
|
15
|
+
authMethod: z.enum(["session", "apikey", "auto"]).optional().default("auto"),
|
16
|
+
sessionMetadata: z.object({
|
17
|
+
email: z.string().optional(),
|
18
|
+
expiresAt: z.string().optional(),
|
19
|
+
}).optional(),
|
11
20
|
}),
|
12
21
|
logging: z
|
13
22
|
.object({
|
@@ -46,12 +55,14 @@ const YamlConfigSchema = z.object({
|
|
46
55
|
outputDirectory: z.string().default("schemas"),
|
47
56
|
yamlSchemaDirectory: z.string().default(".yaml_schemas"),
|
48
57
|
collectionsDirectory: z.string().default("collections"),
|
58
|
+
tablesDirectory: z.string().default("tables"),
|
49
59
|
})
|
50
60
|
.optional()
|
51
61
|
.default({
|
52
62
|
outputDirectory: "schemas",
|
53
63
|
yamlSchemaDirectory: ".yaml_schemas",
|
54
64
|
collectionsDirectory: "collections",
|
65
|
+
tablesDirectory: "tables",
|
55
66
|
}),
|
56
67
|
migrations: z
|
57
68
|
.object({
|
@@ -140,6 +151,10 @@ export const convertYamlToAppwriteConfig = (yamlConfig) => {
|
|
140
151
|
appwriteEndpoint: yamlConfig.appwrite.endpoint,
|
141
152
|
appwriteProject: yamlConfig.appwrite.project,
|
142
153
|
appwriteKey: yamlConfig.appwrite.key,
|
154
|
+
// Session authentication support from YAML
|
155
|
+
sessionCookie: yamlConfig.appwrite.sessionCookie,
|
156
|
+
authMethod: yamlConfig.appwrite.authMethod || "auto",
|
157
|
+
sessionMetadata: yamlConfig.appwrite.sessionMetadata,
|
143
158
|
apiMode: "auto", // Default to auto-detect for dual API support
|
144
159
|
appwriteClient: null,
|
145
160
|
logging: {
|
@@ -155,12 +170,12 @@ export const convertYamlToAppwriteConfig = (yamlConfig) => {
|
|
155
170
|
enableMockData: yamlConfig.data.enableMockData,
|
156
171
|
documentBucketId: yamlConfig.data.documentBucketId,
|
157
172
|
usersCollectionName: yamlConfig.data.usersCollectionName,
|
158
|
-
useMigrations: yamlConfig.migrations.enabled,
|
159
173
|
schemaConfig: {
|
160
174
|
outputDirectory: yamlConfig.schemas.outputDirectory,
|
161
175
|
yamlSchemaDirectory: yamlConfig.schemas.yamlSchemaDirectory,
|
162
176
|
importDirectory: yamlConfig.data.importDirectory,
|
163
177
|
collectionsDirectory: yamlConfig.schemas.collectionsDirectory || "collections",
|
178
|
+
tablesDirectory: yamlConfig.schemas.tablesDirectory || "tables",
|
164
179
|
},
|
165
180
|
databases: yamlConfig.databases.map((db) => ({
|
166
181
|
$id: db.id,
|
@@ -226,6 +241,46 @@ export const convertYamlToAppwriteConfig = (yamlConfig) => {
|
|
226
241
|
};
|
227
242
|
return appwriteConfig;
|
228
243
|
};
|
244
|
+
/**
|
245
|
+
* Load YAML config with optional session preservation
|
246
|
+
* Maintains authentication priority: explicit session > YAML file > system prefs
|
247
|
+
*/
|
248
|
+
export const loadYamlConfigWithSession = async (configPath, sessionOptions) => {
|
249
|
+
try {
|
250
|
+
const fileContent = fs.readFileSync(configPath, "utf8");
|
251
|
+
const yamlData = yaml.load(fileContent);
|
252
|
+
const yamlConfig = YamlConfigSchema.parse(yamlData);
|
253
|
+
const appwriteConfig = convertYamlToAppwriteConfig(yamlConfig);
|
254
|
+
// Apply session preservation if provided (explicit overrides take priority)
|
255
|
+
if (sessionOptions) {
|
256
|
+
if (sessionOptions.sessionCookie) {
|
257
|
+
appwriteConfig.sessionCookie = sessionOptions.sessionCookie;
|
258
|
+
}
|
259
|
+
if (sessionOptions.authMethod) {
|
260
|
+
appwriteConfig.authMethod = sessionOptions.authMethod;
|
261
|
+
}
|
262
|
+
if (sessionOptions.sessionMetadata) {
|
263
|
+
appwriteConfig.sessionMetadata = sessionOptions.sessionMetadata;
|
264
|
+
}
|
265
|
+
}
|
266
|
+
return appwriteConfig;
|
267
|
+
}
|
268
|
+
catch (error) {
|
269
|
+
if (error instanceof z.ZodError) {
|
270
|
+
MessageFormatter.error("YAML config validation failed", undefined, { prefix: "Config" });
|
271
|
+
error.issues.forEach((err) => {
|
272
|
+
MessageFormatter.error(`${err.path.join('.')} → ${err.message}`, undefined, { prefix: "Config" });
|
273
|
+
});
|
274
|
+
}
|
275
|
+
else {
|
276
|
+
MessageFormatter.error("Error loading YAML config", error instanceof Error ? error : undefined, { prefix: "Config" });
|
277
|
+
if (error instanceof Error && error.stack) {
|
278
|
+
MessageFormatter.debug("Stack trace", error.stack, { prefix: "Config" });
|
279
|
+
}
|
280
|
+
}
|
281
|
+
return null;
|
282
|
+
}
|
283
|
+
};
|
229
284
|
export const loadYamlConfig = async (configPath) => {
|
230
285
|
try {
|
231
286
|
const fileContent = fs.readFileSync(configPath, "utf8");
|
@@ -235,15 +290,15 @@ export const loadYamlConfig = async (configPath) => {
|
|
235
290
|
}
|
236
291
|
catch (error) {
|
237
292
|
if (error instanceof z.ZodError) {
|
238
|
-
|
293
|
+
MessageFormatter.error("YAML config validation failed", undefined, { prefix: "Config" });
|
239
294
|
error.issues.forEach((err) => {
|
240
|
-
|
295
|
+
MessageFormatter.error(`${err.path.join('.')} → ${err.message}`, undefined, { prefix: "Config" });
|
241
296
|
});
|
242
297
|
}
|
243
298
|
else {
|
244
|
-
|
299
|
+
MessageFormatter.error("Error loading YAML config", error instanceof Error ? error : undefined, { prefix: "Config" });
|
245
300
|
if (error instanceof Error && error.stack) {
|
246
|
-
|
301
|
+
MessageFormatter.debug("Stack trace", error.stack, { prefix: "Config" });
|
247
302
|
}
|
248
303
|
}
|
249
304
|
return null;
|
@@ -288,45 +343,6 @@ export const findYamlConfig = (startDir) => {
|
|
288
343
|
}
|
289
344
|
return null;
|
290
345
|
};
|
291
|
-
const shouldIgnoreDirectory = (dirName) => {
|
292
|
-
const ignoredDirs = [
|
293
|
-
'node_modules',
|
294
|
-
'dist',
|
295
|
-
'build',
|
296
|
-
'coverage',
|
297
|
-
'.next',
|
298
|
-
'.nuxt',
|
299
|
-
'.cache',
|
300
|
-
'.git',
|
301
|
-
'.svn',
|
302
|
-
'.hg',
|
303
|
-
'__pycache__',
|
304
|
-
'.pytest_cache',
|
305
|
-
'.mypy_cache',
|
306
|
-
'venv',
|
307
|
-
'.venv',
|
308
|
-
'env',
|
309
|
-
'.env',
|
310
|
-
'target',
|
311
|
-
'out',
|
312
|
-
'bin',
|
313
|
-
'obj',
|
314
|
-
'.vs',
|
315
|
-
'.vscode',
|
316
|
-
'.idea',
|
317
|
-
'temp',
|
318
|
-
'tmp',
|
319
|
-
'.tmp',
|
320
|
-
'logs',
|
321
|
-
'log',
|
322
|
-
'.DS_Store',
|
323
|
-
'Thumbs.db'
|
324
|
-
];
|
325
|
-
return ignoredDirs.includes(dirName) ||
|
326
|
-
dirName.startsWith('.git') ||
|
327
|
-
dirName.startsWith('node_modules') ||
|
328
|
-
(dirName.startsWith('.') && dirName !== '.appwrite');
|
329
|
-
};
|
330
346
|
const findYamlConfigRecursive = (dir, depth = 0) => {
|
331
347
|
// Limit search depth to prevent infinite recursion
|
332
348
|
if (depth > 5) {
|
@@ -372,6 +388,9 @@ export const generateYamlConfigTemplate = (outputPath) => {
|
|
372
388
|
endpoint: "https://cloud.appwrite.io/v1",
|
373
389
|
project: "YOUR_PROJECT_ID",
|
374
390
|
key: "YOUR_API_KEY",
|
391
|
+
authMethod: "auto",
|
392
|
+
// Optional session authentication (leave empty to use API key)
|
393
|
+
// sessionCookie: "session_cookie_from_appwrite_cli",
|
375
394
|
},
|
376
395
|
logging: {
|
377
396
|
enabled: false,
|
@@ -394,6 +413,7 @@ export const generateYamlConfigTemplate = (outputPath) => {
|
|
394
413
|
outputDirectory: "schemas",
|
395
414
|
yamlSchemaDirectory: ".yaml_schemas",
|
396
415
|
collectionsDirectory: "collections",
|
416
|
+
tablesDirectory: "tables",
|
397
417
|
},
|
398
418
|
migrations: {
|
399
419
|
enabled: true,
|
@@ -406,14 +426,38 @@ export const generateYamlConfigTemplate = (outputPath) => {
|
|
406
426
|
buckets: [],
|
407
427
|
functions: [],
|
408
428
|
};
|
409
|
-
|
429
|
+
let yamlContent = yaml.dump(template, {
|
410
430
|
indent: 2,
|
411
431
|
lineWidth: 120,
|
412
432
|
sortKeys: false,
|
413
433
|
});
|
414
|
-
// Add
|
434
|
+
// Add inline comments to the schemas section
|
435
|
+
yamlContent = yamlContent.replace(/schemas:\s*\n(\s*)outputDirectory: schemas\n(\s*)yamlSchemaDirectory: \.yaml_schemas\n(\s*)collectionsDirectory: collections\n(\s*)tablesDirectory: tables/, `schemas:
|
436
|
+
$1outputDirectory: schemas
|
437
|
+
$2yamlSchemaDirectory: .yaml_schemas
|
438
|
+
$3# Directory for legacy Databases API collection definitions
|
439
|
+
$3collectionsDirectory: collections
|
440
|
+
$4# Directory for new TablesDB API table definitions
|
441
|
+
$4tablesDirectory: tables`);
|
442
|
+
// Add schema reference header and documentation
|
415
443
|
const schemaReference = "# yaml-language-server: $schema=./.yaml_schemas/appwrite-config.schema.json\n";
|
416
|
-
const
|
444
|
+
const documentation = `# Appwrite Project Configuration
|
445
|
+
#
|
446
|
+
# Authentication Configuration:
|
447
|
+
# - key: Standard API key authentication
|
448
|
+
# - sessionCookie: Session cookie from Appwrite CLI authentication
|
449
|
+
# - authMethod: "auto" (detects available method), "session" (prefer session), "apikey" (prefer API key)
|
450
|
+
# - Priority: Explicit CLI args > YAML config > ~/.appwrite/prefs.json > Error
|
451
|
+
#
|
452
|
+
# Directory Configuration:
|
453
|
+
# - collectionsDirectory: Use for legacy Databases API (default: "collections")
|
454
|
+
# - tablesDirectory: Use for new TablesDB API (default: "tables")
|
455
|
+
# - API mode is auto-detected based on server version, or set explicitly via apiMode
|
456
|
+
#
|
457
|
+
# For dual API support, both directories can coexist with different definitions
|
458
|
+
|
459
|
+
`;
|
460
|
+
const finalContent = schemaReference + documentation + yamlContent;
|
417
461
|
fs.writeFileSync(outputPath, finalContent, "utf8");
|
418
462
|
};
|
419
463
|
/**
|
@@ -429,6 +473,10 @@ export const writeYamlConfig = async (configPath, config) => {
|
|
429
473
|
endpoint: config.appwriteEndpoint,
|
430
474
|
project: config.appwriteProject,
|
431
475
|
key: config.appwriteKey,
|
476
|
+
// Include session authentication fields
|
477
|
+
sessionCookie: config.sessionCookie,
|
478
|
+
authMethod: config.authMethod || "auto",
|
479
|
+
sessionMetadata: config.sessionMetadata,
|
432
480
|
},
|
433
481
|
logging: {
|
434
482
|
enabled: config.logging?.enabled || false,
|
@@ -452,9 +500,10 @@ export const writeYamlConfig = async (configPath, config) => {
|
|
452
500
|
outputDirectory: config.schemaConfig?.outputDirectory || "schemas",
|
453
501
|
yamlSchemaDirectory: config.schemaConfig?.yamlSchemaDirectory || ".yaml_schemas",
|
454
502
|
collectionsDirectory: config.schemaConfig?.collectionsDirectory || "collections",
|
503
|
+
tablesDirectory: config.schemaConfig?.tablesDirectory || "tables",
|
455
504
|
},
|
456
505
|
migrations: {
|
457
|
-
enabled:
|
506
|
+
enabled: true,
|
458
507
|
},
|
459
508
|
databases: config.databases?.map(db => ({
|
460
509
|
id: db.$id,
|
@@ -541,10 +590,10 @@ export const writeYamlConfig = async (configPath, config) => {
|
|
541
590
|
finalContent = schemaReference + "# Appwrite Project Configuration\n" + yamlContent;
|
542
591
|
}
|
543
592
|
fs.writeFileSync(configPath, finalContent, "utf8");
|
544
|
-
|
593
|
+
MessageFormatter.success(`Updated YAML configuration at ${configPath}`, { prefix: "Config" });
|
545
594
|
}
|
546
595
|
catch (error) {
|
547
|
-
|
596
|
+
MessageFormatter.error("Error writing YAML config", error instanceof Error ? error : undefined, { prefix: "Config" });
|
548
597
|
throw error;
|
549
598
|
}
|
550
599
|
};
|
@@ -600,10 +649,54 @@ export const addFunctionToYamlConfig = async (configPath, newFunction) => {
|
|
600
649
|
finalContent = schemaLine + '\n' + updatedYamlContent;
|
601
650
|
}
|
602
651
|
fs.writeFileSync(configPath, finalContent, "utf8");
|
603
|
-
|
652
|
+
MessageFormatter.success(`Added function "${newFunction.name}" to YAML config`, { prefix: "Config" });
|
604
653
|
}
|
605
654
|
catch (error) {
|
606
|
-
|
655
|
+
MessageFormatter.error("Error adding function to YAML config", error instanceof Error ? error : undefined, { prefix: "Config" });
|
607
656
|
throw error;
|
608
657
|
}
|
609
658
|
};
|
659
|
+
/**
|
660
|
+
* Extract session options from AppwriteConfig for YAML operations
|
661
|
+
* Useful for preserving session state during config reloads
|
662
|
+
*/
|
663
|
+
export const extractSessionOptionsFromConfig = (config) => {
|
664
|
+
return {
|
665
|
+
sessionCookie: config.sessionCookie,
|
666
|
+
authMethod: config.authMethod,
|
667
|
+
sessionMetadata: config.sessionMetadata,
|
668
|
+
};
|
669
|
+
};
|
670
|
+
/**
|
671
|
+
* Create session-preserved YAML config operations
|
672
|
+
* Maintains authentication state during config file updates
|
673
|
+
*/
|
674
|
+
export const createSessionPreservingYamlConfig = (configPath, sessionOptions) => {
|
675
|
+
return {
|
676
|
+
load: () => loadYamlConfigWithSession(configPath, sessionOptions),
|
677
|
+
write: (config) => {
|
678
|
+
// Merge session options into config before writing
|
679
|
+
const enhancedConfig = {
|
680
|
+
...config,
|
681
|
+
sessionCookie: sessionOptions.sessionCookie || config.sessionCookie,
|
682
|
+
authMethod: sessionOptions.authMethod || config.authMethod,
|
683
|
+
sessionMetadata: sessionOptions.sessionMetadata || config.sessionMetadata,
|
684
|
+
};
|
685
|
+
return writeYamlConfig(configPath, enhancedConfig);
|
686
|
+
},
|
687
|
+
addFunction: (func) => addFunctionToYamlConfig(configPath, func),
|
688
|
+
};
|
689
|
+
};
|
690
|
+
/**
|
691
|
+
* Determine if YAML config has session authentication configured
|
692
|
+
*/
|
693
|
+
export const hasYamlSessionAuth = (configPath) => {
|
694
|
+
try {
|
695
|
+
const fileContent = fs.readFileSync(configPath, "utf8");
|
696
|
+
const yamlData = yaml.load(fileContent);
|
697
|
+
return !!(yamlData?.appwrite?.sessionCookie && yamlData.appwrite.sessionCookie.trim());
|
698
|
+
}
|
699
|
+
catch (error) {
|
700
|
+
return false;
|
701
|
+
}
|
702
|
+
};
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { Databases, Query } from "node-appwrite";
|
2
2
|
import { delay, tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
3
3
|
import { fetchAllCollections } from "../collections/methods.js";
|
4
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
4
5
|
export const fetchAllDatabases = async (database) => {
|
5
6
|
const databases = await tryAwaitWithRetry(async () => await database.list([Query.limit(25)]));
|
6
7
|
const allDatabases = databases.databases;
|
@@ -21,11 +22,11 @@ export const fetchAllDatabases = async (database) => {
|
|
21
22
|
return allDatabases;
|
22
23
|
};
|
23
24
|
export const wipeDatabase = async (database, databaseId) => {
|
24
|
-
|
25
|
+
MessageFormatter.info(`Wiping database: ${databaseId}`, { prefix: "Database" });
|
25
26
|
const existingCollections = await fetchAllCollections(databaseId, database);
|
26
27
|
let collectionsDeleted = [];
|
27
28
|
for (const { $id: collectionId, name } of existingCollections) {
|
28
|
-
|
29
|
+
MessageFormatter.info(`Deleting collection: ${collectionId}`, { prefix: "Database" });
|
29
30
|
collectionsDeleted.push({ collectionId, collectionName: name });
|
30
31
|
await tryAwaitWithRetry(async () => await database.deleteCollection(databaseId, collectionId));
|
31
32
|
await delay(100);
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Databases, type Models } from "node-appwrite";
|
2
2
|
import { type AppwriteConfig } from "appwrite-utils";
|
3
|
-
export declare const setupMigrationDatabase: (config: AppwriteConfig) => Promise<void>;
|
4
3
|
export declare const ensureDatabasesExist: (config: AppwriteConfig, databasesToEnsure?: Models.Database[]) => Promise<void>;
|
5
|
-
export declare const wipeOtherDatabases: (database: Databases, databasesToKeep: Models.Database[]
|
4
|
+
export declare const wipeOtherDatabases: (database: Databases, databasesToKeep: Models.Database[]) => Promise<void>;
|
6
5
|
export declare const ensureCollectionsExist: (config: AppwriteConfig, database: Models.Database, collectionsToEnsure?: Models.Collection[]) => Promise<void>;
|
package/dist/databases/setup.js
CHANGED
@@ -1,111 +1,33 @@
|
|
1
1
|
import { Databases, Query } from "node-appwrite";
|
2
|
-
import {
|
3
|
-
import { getMigrationCollectionSchemas } from "../storage/schemas.js";
|
4
|
-
import { areCollectionNamesSame, delay, toCamelCase, tryAwaitWithRetry, } from "../utils/index.js";
|
2
|
+
import { tryAwaitWithRetry } from "../utils/index.js";
|
5
3
|
import {} from "appwrite-utils";
|
6
4
|
import { ulid } from "ulidx";
|
7
|
-
|
8
|
-
if (!config.useMigrations) {
|
9
|
-
console.log("Migrations database disabled, skipping setup");
|
10
|
-
return;
|
11
|
-
}
|
12
|
-
console.log("---------------------------------");
|
13
|
-
console.log("Starting Migrations Setup");
|
14
|
-
console.log("---------------------------------");
|
15
|
-
const database = new Databases(config.appwriteClient);
|
16
|
-
if (!config.appwriteClient) {
|
17
|
-
throw new Error("Appwrite client is not initialized in the config");
|
18
|
-
}
|
19
|
-
let db;
|
20
|
-
const migrationCollectionsSetup = getMigrationCollectionSchemas();
|
21
|
-
try {
|
22
|
-
db = await tryAwaitWithRetry(async () => await database.get("migrations"), undefined, true);
|
23
|
-
console.log("Migrations database found");
|
24
|
-
}
|
25
|
-
catch (e) {
|
26
|
-
db = await tryAwaitWithRetry(async () => await database.create("migrations", "Migrations", true));
|
27
|
-
console.log("Migrations database created");
|
28
|
-
}
|
29
|
-
if (!db) {
|
30
|
-
console.error("Failed to create or retrieve the migrations database");
|
31
|
-
return;
|
32
|
-
}
|
33
|
-
for (const [collectionName, { collection, attributes }] of Object.entries(migrationCollectionsSetup)) {
|
34
|
-
const collectionId = toCamelCase(collectionName);
|
35
|
-
let collectionFound;
|
36
|
-
try {
|
37
|
-
collectionFound = await tryAwaitWithRetry(async () => await database.getCollection(db.$id, collectionId), undefined, true);
|
38
|
-
console.log(`Collection found: ${collectionId}`);
|
39
|
-
}
|
40
|
-
catch (e) {
|
41
|
-
console.log(`Collection not found: ${collectionId}`);
|
42
|
-
try {
|
43
|
-
collectionFound = await tryAwaitWithRetry(async () => await database.createCollection(db.$id, collectionId, collectionName, undefined, collection.documentSecurity, collection.enabled), undefined, true);
|
44
|
-
console.log(`Collection created: ${collectionId}`);
|
45
|
-
}
|
46
|
-
catch (createError) {
|
47
|
-
console.error(`Failed to create collection: ${collectionId}`, createError);
|
48
|
-
continue;
|
49
|
-
}
|
50
|
-
}
|
51
|
-
if (!collectionFound) {
|
52
|
-
console.error(`Failed to create or retrieve collection: ${collectionId}`);
|
53
|
-
continue;
|
54
|
-
}
|
55
|
-
for (const attribute of attributes) {
|
56
|
-
try {
|
57
|
-
await createOrUpdateAttributeWithStatusCheck(database, db.$id, collectionFound, attribute);
|
58
|
-
await delay(100);
|
59
|
-
console.log(`Attribute created/updated: ${attribute.key}`);
|
60
|
-
}
|
61
|
-
catch (attrError) {
|
62
|
-
console.error(`Failed to create/update attribute: ${attribute.key}`, attrError);
|
63
|
-
}
|
64
|
-
}
|
65
|
-
}
|
66
|
-
console.log("---------------------------------");
|
67
|
-
console.log("Migrations Setup Complete");
|
68
|
-
console.log("---------------------------------");
|
69
|
-
};
|
5
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
70
6
|
export const ensureDatabasesExist = async (config, databasesToEnsure) => {
|
71
7
|
if (!config.appwriteClient) {
|
72
8
|
throw new Error("Appwrite client is not initialized in the config");
|
73
9
|
}
|
74
10
|
const database = new Databases(config.appwriteClient);
|
75
|
-
|
76
|
-
const databasesToCreate = [...(databasesToEnsure || config.databases || [])];
|
11
|
+
const databasesToCreate = databasesToEnsure || config.databases || [];
|
77
12
|
if (!databasesToCreate.length) {
|
78
|
-
|
13
|
+
MessageFormatter.info("No databases to create");
|
79
14
|
return;
|
80
15
|
}
|
81
16
|
const existingDatabases = await tryAwaitWithRetry(async () => await database.list([Query.limit(500)]));
|
82
|
-
const migrationsDatabase = existingDatabases.databases.find((d) => d.name.toLowerCase().trim().replace(" ", "") === "migrations");
|
83
|
-
if (config.useMigrations && existingDatabases.databases.length !== 0 && migrationsDatabase) {
|
84
|
-
console.log("Creating all databases including migrations");
|
85
|
-
// Ensure migrations exists, but do not mutate the caller's array
|
86
|
-
if (!databasesToCreate.some((d) => d.$id === migrationsDatabase.$id)) {
|
87
|
-
databasesToCreate.push(migrationsDatabase);
|
88
|
-
}
|
89
|
-
}
|
90
17
|
for (const db of databasesToCreate) {
|
91
18
|
if (!existingDatabases.databases.some((d) => d.name === db.name)) {
|
92
19
|
await tryAwaitWithRetry(async () => await database.create(db.$id || ulid(), db.name, true));
|
93
|
-
|
20
|
+
MessageFormatter.success(`${db.name} database created`);
|
94
21
|
}
|
95
22
|
}
|
96
23
|
};
|
97
|
-
export const wipeOtherDatabases = async (database, databasesToKeep
|
98
|
-
|
24
|
+
export const wipeOtherDatabases = async (database, databasesToKeep) => {
|
25
|
+
MessageFormatter.info(`Databases to keep: ${databasesToKeep.map(db => db.name).join(", ")}`);
|
99
26
|
const allDatabases = await tryAwaitWithRetry(async () => await database.list([Query.limit(500)]));
|
100
|
-
const migrationsDatabase = allDatabases.databases.find((d) => d.name.toLowerCase().trim().replace(" ", "") === "migrations");
|
101
|
-
if (useMigrations && allDatabases.databases.length !== 0 && migrationsDatabase) {
|
102
|
-
console.log("Wiping all databases except migrations");
|
103
|
-
databasesToKeep.push(migrationsDatabase);
|
104
|
-
}
|
105
27
|
for (const db of allDatabases.databases) {
|
106
28
|
if (!databasesToKeep.some((d) => d.name === db.name)) {
|
107
29
|
await tryAwaitWithRetry(async () => await database.delete(db.$id));
|
108
|
-
|
30
|
+
MessageFormatter.success(`Deleted database: ${db.name}`);
|
109
31
|
}
|
110
32
|
}
|
111
33
|
};
|
@@ -117,7 +39,7 @@ export const ensureCollectionsExist = async (config, database, collectionsToEnsu
|
|
117
39
|
for (const collection of collectionsToCreate) {
|
118
40
|
if (!existingCollections.collections.some((c) => c.name === collection.name)) {
|
119
41
|
await tryAwaitWithRetry(async () => await databaseClient.createCollection(database.$id, ulid(), collection.name, undefined, true, true));
|
120
|
-
|
42
|
+
MessageFormatter.success(`${collection.name} collection created in ${database.name}`);
|
121
43
|
}
|
122
44
|
}
|
123
45
|
};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/**
|
2
|
+
* Example demonstrating YAML import/export with dual terminology support
|
3
|
+
*
|
4
|
+
* This example shows how to:
|
5
|
+
* 1. Generate YAML files for both collections and tables
|
6
|
+
* 2. Load and convert between terminologies
|
7
|
+
* 3. Validate terminology consistency
|
8
|
+
* 4. Migrate between formats
|
9
|
+
*/
|
10
|
+
import type { CollectionCreate } from "appwrite-utils";
|
11
|
+
/**
|
12
|
+
* Example 1: Generate YAML templates for both collection and table formats
|
13
|
+
*/
|
14
|
+
export declare function generateTemplateExamples(outputDir: string): Promise<void>;
|
15
|
+
/**
|
16
|
+
* Example 2: Convert existing collection definition to different formats
|
17
|
+
*/
|
18
|
+
export declare function convertCollectionFormats(collection: CollectionCreate): void;
|
19
|
+
/**
|
20
|
+
* Example 3: Load and process YAML files with mixed terminologies
|
21
|
+
*/
|
22
|
+
export declare function processYamlFiles(baseDir: string): Promise<void>;
|
23
|
+
/**
|
24
|
+
* Example 4: Migrate between terminologies
|
25
|
+
*/
|
26
|
+
export declare function migrateTerminology(baseDir: string): Promise<void>;
|
27
|
+
/**
|
28
|
+
* Example 5: Validate terminology consistency
|
29
|
+
*/
|
30
|
+
export declare function validateTerminology(baseDir: string): Promise<void>;
|
31
|
+
/**
|
32
|
+
* Example 6: Import configuration with terminology support
|
33
|
+
*/
|
34
|
+
export declare function importConfigurationExample(appwriteFolderPath: string): Promise<void>;
|
35
|
+
/**
|
36
|
+
* Example 7: Manual terminology conversion
|
37
|
+
*/
|
38
|
+
export declare function manualTerminologyConversion(): void;
|
39
|
+
/**
|
40
|
+
* Main example runner
|
41
|
+
*/
|
42
|
+
export declare function runYamlTerminologyExamples(outputDir: string): Promise<void>;
|