appwrite-utils-cli 1.5.2 → 1.6.1

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.
Files changed (233) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +251 -29
  3. package/dist/adapters/AdapterFactory.d.ts +10 -3
  4. package/dist/adapters/AdapterFactory.js +213 -17
  5. package/dist/adapters/TablesDBAdapter.js +60 -17
  6. package/dist/backups/operations/bucketBackup.d.ts +19 -0
  7. package/dist/backups/operations/bucketBackup.js +197 -0
  8. package/dist/backups/operations/collectionBackup.d.ts +30 -0
  9. package/dist/backups/operations/collectionBackup.js +201 -0
  10. package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
  11. package/dist/backups/operations/comprehensiveBackup.js +238 -0
  12. package/dist/backups/schemas/bucketManifest.d.ts +93 -0
  13. package/dist/backups/schemas/bucketManifest.js +33 -0
  14. package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
  15. package/dist/backups/schemas/comprehensiveManifest.js +32 -0
  16. package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
  17. package/dist/backups/tracking/centralizedTracking.js +274 -0
  18. package/dist/cli/commands/configCommands.d.ts +8 -0
  19. package/dist/cli/commands/configCommands.js +160 -0
  20. package/dist/cli/commands/databaseCommands.d.ts +13 -0
  21. package/dist/cli/commands/databaseCommands.js +479 -0
  22. package/dist/cli/commands/functionCommands.d.ts +7 -0
  23. package/dist/cli/commands/functionCommands.js +289 -0
  24. package/dist/cli/commands/schemaCommands.d.ts +7 -0
  25. package/dist/cli/commands/schemaCommands.js +134 -0
  26. package/dist/cli/commands/transferCommands.d.ts +5 -0
  27. package/dist/cli/commands/transferCommands.js +384 -0
  28. package/dist/collections/attributes.d.ts +5 -4
  29. package/dist/collections/attributes.js +539 -246
  30. package/dist/collections/indexes.js +39 -37
  31. package/dist/collections/methods.d.ts +2 -16
  32. package/dist/collections/methods.js +90 -538
  33. package/dist/collections/transferOperations.d.ts +7 -0
  34. package/dist/collections/transferOperations.js +331 -0
  35. package/dist/collections/wipeOperations.d.ts +16 -0
  36. package/dist/collections/wipeOperations.js +328 -0
  37. package/dist/config/configMigration.d.ts +87 -0
  38. package/dist/config/configMigration.js +390 -0
  39. package/dist/config/configValidation.d.ts +66 -0
  40. package/dist/config/configValidation.js +358 -0
  41. package/dist/config/yamlConfig.d.ts +455 -1
  42. package/dist/config/yamlConfig.js +145 -52
  43. package/dist/databases/methods.js +3 -2
  44. package/dist/databases/setup.d.ts +1 -2
  45. package/dist/databases/setup.js +9 -87
  46. package/dist/examples/yamlTerminologyExample.d.ts +42 -0
  47. package/dist/examples/yamlTerminologyExample.js +269 -0
  48. package/dist/functions/deployments.js +11 -10
  49. package/dist/functions/methods.d.ts +1 -1
  50. package/dist/functions/methods.js +5 -4
  51. package/dist/init.js +9 -9
  52. package/dist/interactiveCLI.d.ts +8 -17
  53. package/dist/interactiveCLI.js +209 -1172
  54. package/dist/main.js +364 -21
  55. package/dist/migrations/afterImportActions.js +22 -30
  56. package/dist/migrations/appwriteToX.js +71 -25
  57. package/dist/migrations/dataLoader.js +35 -26
  58. package/dist/migrations/importController.js +29 -30
  59. package/dist/migrations/relationships.js +13 -12
  60. package/dist/migrations/services/ImportOrchestrator.js +16 -19
  61. package/dist/migrations/transfer.js +46 -46
  62. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +3 -1
  63. package/dist/migrations/yaml/YamlImportConfigLoader.js +6 -3
  64. package/dist/migrations/yaml/YamlImportIntegration.d.ts +9 -3
  65. package/dist/migrations/yaml/YamlImportIntegration.js +22 -11
  66. package/dist/migrations/yaml/generateImportSchemas.d.ts +14 -1
  67. package/dist/migrations/yaml/generateImportSchemas.js +736 -7
  68. package/dist/schemas/authUser.d.ts +1 -1
  69. package/dist/setupController.js +3 -2
  70. package/dist/shared/backupMetadataSchema.d.ts +94 -0
  71. package/dist/shared/backupMetadataSchema.js +38 -0
  72. package/dist/shared/backupTracking.d.ts +18 -0
  73. package/dist/shared/backupTracking.js +176 -0
  74. package/dist/shared/confirmationDialogs.js +15 -15
  75. package/dist/shared/errorUtils.d.ts +54 -0
  76. package/dist/shared/errorUtils.js +95 -0
  77. package/dist/shared/functionManager.js +20 -19
  78. package/dist/shared/indexManager.js +12 -11
  79. package/dist/shared/jsonSchemaGenerator.js +10 -26
  80. package/dist/shared/logging.d.ts +51 -0
  81. package/dist/shared/logging.js +70 -0
  82. package/dist/shared/messageFormatter.d.ts +2 -0
  83. package/dist/shared/messageFormatter.js +10 -0
  84. package/dist/shared/migrationHelpers.d.ts +6 -16
  85. package/dist/shared/migrationHelpers.js +24 -21
  86. package/dist/shared/operationLogger.d.ts +8 -1
  87. package/dist/shared/operationLogger.js +11 -24
  88. package/dist/shared/operationQueue.d.ts +28 -1
  89. package/dist/shared/operationQueue.js +268 -66
  90. package/dist/shared/operationsTable.d.ts +26 -0
  91. package/dist/shared/operationsTable.js +286 -0
  92. package/dist/shared/operationsTableSchema.d.ts +48 -0
  93. package/dist/shared/operationsTableSchema.js +35 -0
  94. package/dist/shared/relationshipExtractor.d.ts +56 -0
  95. package/dist/shared/relationshipExtractor.js +138 -0
  96. package/dist/shared/schemaGenerator.d.ts +19 -1
  97. package/dist/shared/schemaGenerator.js +56 -75
  98. package/dist/storage/backupCompression.d.ts +20 -0
  99. package/dist/storage/backupCompression.js +67 -0
  100. package/dist/storage/methods.d.ts +16 -2
  101. package/dist/storage/methods.js +98 -14
  102. package/dist/users/methods.js +9 -8
  103. package/dist/utils/configDiscovery.d.ts +78 -0
  104. package/dist/utils/configDiscovery.js +430 -0
  105. package/dist/utils/directoryUtils.d.ts +22 -0
  106. package/dist/utils/directoryUtils.js +59 -0
  107. package/dist/utils/getClientFromConfig.d.ts +17 -8
  108. package/dist/utils/getClientFromConfig.js +162 -17
  109. package/dist/utils/helperFunctions.d.ts +16 -2
  110. package/dist/utils/helperFunctions.js +19 -5
  111. package/dist/utils/loadConfigs.d.ts +34 -9
  112. package/dist/utils/loadConfigs.js +236 -316
  113. package/dist/utils/pathResolvers.d.ts +53 -0
  114. package/dist/utils/pathResolvers.js +72 -0
  115. package/dist/utils/projectConfig.d.ts +119 -0
  116. package/dist/utils/projectConfig.js +171 -0
  117. package/dist/utils/retryFailedPromises.js +4 -2
  118. package/dist/utils/sessionAuth.d.ts +48 -0
  119. package/dist/utils/sessionAuth.js +164 -0
  120. package/dist/utils/sessionPreservationExample.d.ts +1666 -0
  121. package/dist/utils/sessionPreservationExample.js +101 -0
  122. package/dist/utils/setupFiles.js +301 -41
  123. package/dist/utils/typeGuards.d.ts +35 -0
  124. package/dist/utils/typeGuards.js +57 -0
  125. package/dist/utils/versionDetection.js +145 -9
  126. package/dist/utils/yamlConverter.d.ts +53 -3
  127. package/dist/utils/yamlConverter.js +232 -13
  128. package/dist/utils/yamlLoader.d.ts +70 -0
  129. package/dist/utils/yamlLoader.js +263 -0
  130. package/dist/utilsController.d.ts +36 -3
  131. package/dist/utilsController.js +186 -56
  132. package/package.json +12 -2
  133. package/src/adapters/AdapterFactory.ts +263 -35
  134. package/src/adapters/TablesDBAdapter.ts +225 -36
  135. package/src/backups/operations/bucketBackup.ts +277 -0
  136. package/src/backups/operations/collectionBackup.ts +310 -0
  137. package/src/backups/operations/comprehensiveBackup.ts +342 -0
  138. package/src/backups/schemas/bucketManifest.ts +78 -0
  139. package/src/backups/schemas/comprehensiveManifest.ts +76 -0
  140. package/src/backups/tracking/centralizedTracking.ts +352 -0
  141. package/src/cli/commands/configCommands.ts +194 -0
  142. package/src/cli/commands/databaseCommands.ts +635 -0
  143. package/src/cli/commands/functionCommands.ts +379 -0
  144. package/src/cli/commands/schemaCommands.ts +163 -0
  145. package/src/cli/commands/transferCommands.ts +457 -0
  146. package/src/collections/attributes.ts +900 -621
  147. package/src/collections/attributes.ts.backup +1555 -0
  148. package/src/collections/indexes.ts +116 -114
  149. package/src/collections/methods.ts +295 -968
  150. package/src/collections/transferOperations.ts +516 -0
  151. package/src/collections/wipeOperations.ts +501 -0
  152. package/src/config/README.md +274 -0
  153. package/src/config/configMigration.ts +575 -0
  154. package/src/config/configValidation.ts +445 -0
  155. package/src/config/yamlConfig.ts +168 -55
  156. package/src/databases/methods.ts +3 -2
  157. package/src/databases/setup.ts +11 -138
  158. package/src/examples/yamlTerminologyExample.ts +341 -0
  159. package/src/functions/deployments.ts +14 -12
  160. package/src/functions/methods.ts +11 -11
  161. package/src/functions/templates/hono-typescript/README.md +286 -0
  162. package/src/functions/templates/hono-typescript/package.json +26 -0
  163. package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
  164. package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
  165. package/src/functions/templates/hono-typescript/src/app.ts +180 -0
  166. package/src/functions/templates/hono-typescript/src/context.ts +103 -0
  167. package/src/functions/templates/hono-typescript/src/index.ts +54 -0
  168. package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
  169. package/src/functions/templates/hono-typescript/tsconfig.json +20 -0
  170. package/src/functions/templates/typescript-node/package.json +2 -1
  171. package/src/functions/templates/typescript-node/src/context.ts +103 -0
  172. package/src/functions/templates/typescript-node/src/index.ts +18 -12
  173. package/src/functions/templates/uv/pyproject.toml +1 -0
  174. package/src/functions/templates/uv/src/context.py +125 -0
  175. package/src/functions/templates/uv/src/index.py +35 -5
  176. package/src/init.ts +9 -11
  177. package/src/interactiveCLI.ts +274 -1563
  178. package/src/main.ts +418 -24
  179. package/src/migrations/afterImportActions.ts +71 -44
  180. package/src/migrations/appwriteToX.ts +100 -34
  181. package/src/migrations/dataLoader.ts +48 -34
  182. package/src/migrations/importController.ts +44 -39
  183. package/src/migrations/relationships.ts +28 -18
  184. package/src/migrations/services/ImportOrchestrator.ts +24 -27
  185. package/src/migrations/transfer.ts +159 -121
  186. package/src/migrations/yaml/YamlImportConfigLoader.ts +11 -4
  187. package/src/migrations/yaml/YamlImportIntegration.ts +47 -20
  188. package/src/migrations/yaml/generateImportSchemas.ts +751 -12
  189. package/src/setupController.ts +3 -2
  190. package/src/shared/backupMetadataSchema.ts +93 -0
  191. package/src/shared/backupTracking.ts +211 -0
  192. package/src/shared/confirmationDialogs.ts +19 -19
  193. package/src/shared/errorUtils.ts +110 -0
  194. package/src/shared/functionManager.ts +21 -20
  195. package/src/shared/indexManager.ts +12 -11
  196. package/src/shared/jsonSchemaGenerator.ts +38 -52
  197. package/src/shared/logging.ts +75 -0
  198. package/src/shared/messageFormatter.ts +14 -1
  199. package/src/shared/migrationHelpers.ts +45 -38
  200. package/src/shared/operationLogger.ts +11 -36
  201. package/src/shared/operationQueue.ts +322 -93
  202. package/src/shared/operationsTable.ts +338 -0
  203. package/src/shared/operationsTableSchema.ts +60 -0
  204. package/src/shared/relationshipExtractor.ts +214 -0
  205. package/src/shared/schemaGenerator.ts +179 -219
  206. package/src/storage/backupCompression.ts +88 -0
  207. package/src/storage/methods.ts +131 -34
  208. package/src/users/methods.ts +11 -9
  209. package/src/utils/configDiscovery.ts +502 -0
  210. package/src/utils/directoryUtils.ts +61 -0
  211. package/src/utils/getClientFromConfig.ts +205 -22
  212. package/src/utils/helperFunctions.ts +23 -5
  213. package/src/utils/loadConfigs.ts +313 -345
  214. package/src/utils/pathResolvers.ts +81 -0
  215. package/src/utils/projectConfig.ts +299 -0
  216. package/src/utils/retryFailedPromises.ts +4 -2
  217. package/src/utils/sessionAuth.ts +230 -0
  218. package/src/utils/setupFiles.ts +322 -54
  219. package/src/utils/typeGuards.ts +65 -0
  220. package/src/utils/versionDetection.ts +218 -64
  221. package/src/utils/yamlConverter.ts +296 -13
  222. package/src/utils/yamlLoader.ts +364 -0
  223. package/src/utilsController.ts +314 -110
  224. package/tests/README.md +497 -0
  225. package/tests/adapters/AdapterFactory.test.ts +277 -0
  226. package/tests/integration/syncOperations.test.ts +463 -0
  227. package/tests/jest.config.js +25 -0
  228. package/tests/migration/configMigration.test.ts +546 -0
  229. package/tests/setup.ts +62 -0
  230. package/tests/testUtils.ts +340 -0
  231. package/tests/utils/loadConfigs.test.ts +350 -0
  232. package/tests/validation/configValidation.test.ts +412 -0
  233. package/src/utils/schemaStrings.ts +0 -517
@@ -1,13 +1,16 @@
1
1
  import { mkdirSync, writeFileSync, existsSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import type { AppwriteConfig } from "appwrite-utils";
4
- import { findAppwriteConfig } from "./loadConfigs.js";
5
- import { loadYamlConfig } from "../config/yamlConfig.js";
6
- import { fetchServerVersion, isVersionAtLeast } from "./versionDetection.js";
4
+ import { findAppwriteConfig } from "./loadConfigs.js";
5
+ import { loadYamlConfig } from "../config/yamlConfig.js";
6
+ import { fetchServerVersion, isVersionAtLeast } from "./versionDetection.js";
7
7
  import { findYamlConfig } from "../config/yamlConfig.js";
8
8
  import { ID } from "node-appwrite";
9
9
  import { ulid } from "ulidx";
10
10
  import { generateYamlConfigTemplate } from "../config/yamlConfig.js";
11
+ import { loadAppwriteProjectConfig, findAppwriteProjectConfig, getProjectDirectoryName, isTablesDBProject } from "./projectConfig.js";
12
+ import { hasSessionAuth, getSessionAuth } from "./sessionAuth.js";
13
+ import { MessageFormatter } from "../shared/messageFormatter.js";
11
14
 
12
15
  // Example base configuration using types from appwrite-utils
13
16
  const baseConfig: AppwriteConfig = {
@@ -16,13 +19,13 @@ const baseConfig: AppwriteConfig = {
16
19
  appwriteKey: "YOUR_API_KEY",
17
20
  appwriteClient: null,
18
21
  apiMode: "auto", // Enable dual API support - auto-detect TablesDB vs legacy
22
+ authMethod: "auto", // Default to auto-detect authentication method
19
23
  logging: {
20
24
  enabled: false,
21
25
  level: "info",
22
26
  console: false,
23
27
  },
24
28
  enableBackups: true,
25
- useMigrations: true,
26
29
  backupInterval: 3600,
27
30
  backupRetention: 30,
28
31
  enableBackupCleanup: true,
@@ -201,7 +204,7 @@ importDefs: []
201
204
 
202
205
  const collectionFilePath = path.join(collectionsFolder, `${collectionName}.yaml`);
203
206
  writeFileSync(collectionFilePath, yamlCollection);
204
- console.log(`✨ Created YAML collection: ${collectionFilePath}`);
207
+ MessageFormatter.success(`Created YAML collection: ${collectionFilePath}`, { prefix: "Setup" });
205
208
  } else {
206
209
  // Create TypeScript collection
207
210
  const emptyCollection = `import type { CollectionCreate } from "appwrite-utils";
@@ -229,7 +232,7 @@ export default ${collectionName};`;
229
232
 
230
233
  const collectionFilePath = path.join(collectionsFolder, `${collectionName}.ts`);
231
234
  writeFileSync(collectionFilePath, emptyCollection);
232
- console.log(`✨ Created TypeScript collection: ${collectionFilePath}`);
235
+ MessageFormatter.success(`Created TypeScript collection: ${collectionFilePath}`, { prefix: "Setup" });
233
236
  }
234
237
  };
235
238
 
@@ -243,9 +246,9 @@ export const generateYamlConfig = (currentDir?: string, useAppwriteDir: boolean
243
246
 
244
247
  const configPath = path.join(configDir, "config.yaml");
245
248
  generateYamlConfigTemplate(configPath);
246
-
247
- console.log(`✨ Generated YAML config template at: ${configPath}`);
248
- console.log("📝 Please update the configuration with your Appwrite project details.");
249
+
250
+ MessageFormatter.success(`Generated YAML config template at: ${configPath}`, { prefix: "Setup" });
251
+ MessageFormatter.info("Please update the configuration with your Appwrite project details.", { prefix: "Setup" });
249
252
 
250
253
  return configPath;
251
254
  };
@@ -267,30 +270,62 @@ export const setupDirsFiles = async (
267
270
  const appwriteSchemaFolder = path.join(appwriteFolder, "schemas");
268
271
  const appwriteYamlSchemaFolder = path.join(appwriteFolder, ".yaml_schemas");
269
272
  const appwriteDataFolder = path.join(appwriteFolder, "importData");
270
- // Decide between collections or tables folder
271
- let useTables = false;
272
- try {
273
- // Try reading YAML config if present to detect version
274
- const yamlPath = findYamlConfig(basePath);
275
- if (yamlPath) {
276
- const cfg = await loadYamlConfig(yamlPath);
277
- if (cfg) {
278
- const ver = await fetchServerVersion(cfg.appwriteEndpoint);
279
- if (isVersionAtLeast(ver || undefined, '1.8.0')) useTables = true;
280
- }
281
- }
282
- } catch {}
283
- const targetFolderName = useTables ? "tables" : "collections";
284
- const collectionsFolder = path.join(appwriteFolder, targetFolderName);
273
+ // Enhanced version detection with multiple sources
274
+ let useTables = false;
275
+ let detectionSource = "default";
276
+
277
+ try {
278
+ // Priority 1: Check for existing appwrite.json project config
279
+ const projectConfigPath = findAppwriteProjectConfig(basePath);
280
+ if (projectConfigPath) {
281
+ const projectConfig = loadAppwriteProjectConfig(projectConfigPath);
282
+ if (projectConfig) {
283
+ useTables = isTablesDBProject(projectConfig);
284
+ detectionSource = "appwrite.json";
285
+ MessageFormatter.info(`Detected ${useTables ? 'TablesDB' : 'Collections'} project from ${projectConfigPath}`, { prefix: "Setup" });
286
+ }
287
+ }
288
+
289
+ // Priority 2: Try reading existing YAML config for version detection
290
+ if (!useTables && detectionSource === "default") {
291
+ const yamlPath = findYamlConfig(basePath);
292
+ if (yamlPath) {
293
+ const cfg = await loadYamlConfig(yamlPath);
294
+ if (cfg) {
295
+ // Try session auth first, then API key for version detection
296
+ let endpoint = cfg.appwriteEndpoint;
297
+ let projectId = cfg.appwriteProject;
298
+
299
+ if (hasSessionAuth(endpoint, projectId)) {
300
+ MessageFormatter.info("Using session authentication for version detection", { prefix: "Setup" });
301
+ }
302
+
303
+ const ver = await fetchServerVersion(endpoint);
304
+ if (isVersionAtLeast(ver || undefined, '1.8.0')) {
305
+ useTables = true;
306
+ detectionSource = "server-version";
307
+ MessageFormatter.info(`Detected TablesDB support (Appwrite ${ver})`, { prefix: "Setup" });
308
+ } else {
309
+ MessageFormatter.info(`Using Collections API (Appwrite ${ver || 'unknown'})`, { prefix: "Setup" });
310
+ }
311
+ }
312
+ }
313
+ }
314
+ } catch (error) {
315
+ MessageFormatter.warning(`Version detection failed, defaulting to Collections API: ${error instanceof Error ? error.message : String(error)}`, { prefix: "Setup" });
316
+ }
317
+
318
+ const targetFolderName = useTables ? "tables" : "collections";
319
+ const collectionsFolder = path.join(appwriteFolder, targetFolderName);
285
320
 
286
321
  // Create directory structure
287
322
  if (!existsSync(appwriteFolder)) {
288
323
  mkdirSync(appwriteFolder, { recursive: true });
289
324
  }
290
325
 
291
- if (!existsSync(collectionsFolder)) {
292
- mkdirSync(collectionsFolder, { recursive: true });
293
- }
326
+ if (!existsSync(collectionsFolder)) {
327
+ mkdirSync(collectionsFolder, { recursive: true });
328
+ }
294
329
 
295
330
  // Handle configuration file creation - YAML is now default
296
331
  if (useYaml) {
@@ -322,13 +357,31 @@ export default appwriteConfig;
322
357
  });
323
358
  }
324
359
 
325
- // Create YAML collection example if using YAML config
360
+ // Create YAML collection/table example if using YAML config
326
361
  if (useYaml) {
327
- const yamlCollectionExample = `# yaml-language-server: $schema=../.yaml_schemas/collection.schema.json
328
- # Example Collection Definition
329
- name: ExampleCollection
330
- id: example_collection_${Date.now()}
331
- documentSecurity: false
362
+ const terminology = useTables
363
+ ? {
364
+ container: "table",
365
+ fields: "columns",
366
+ security: "rowSecurity",
367
+ schemaRef: "table.schema.json",
368
+ containerName: "Table",
369
+ fieldName: "Column"
370
+ }
371
+ : {
372
+ container: "collection",
373
+ fields: "attributes",
374
+ security: "documentSecurity",
375
+ schemaRef: "collection.schema.json",
376
+ containerName: "Collection",
377
+ fieldName: "Attribute"
378
+ };
379
+
380
+ const yamlExample = `# yaml-language-server: $schema=../.yaml_schemas/${terminology.schemaRef}
381
+ # Example ${terminology.containerName} Definition
382
+ name: Example${terminology.containerName}
383
+ id: example_${terminology.container}_${Date.now()}
384
+ ${terminology.security}: false
332
385
  enabled: true
333
386
  permissions:
334
387
  - permission: read
@@ -339,7 +392,7 @@ permissions:
339
392
  target: users
340
393
  - permission: delete
341
394
  target: users
342
- attributes:
395
+ ${terminology.fields}:
343
396
  - key: title
344
397
  type: string
345
398
  size: 255
@@ -353,7 +406,13 @@ attributes:
353
406
  - key: isActive
354
407
  type: boolean
355
408
  required: false
356
- default: true
409
+ default: true${useTables ? `
410
+ - key: uniqueCode
411
+ type: string
412
+ size: 50
413
+ required: false
414
+ unique: true
415
+ description: "Unique identifier code (TablesDB feature)"` : ''}
357
416
  indexes:
358
417
  - key: title_search
359
418
  type: fulltext
@@ -361,11 +420,212 @@ indexes:
361
420
  - title
362
421
  importDefs: []
363
422
  `;
364
- const yamlCollectionPath = path.join(collectionsFolder, "ExampleCollection.yaml");
365
- writeFileSync(yamlCollectionPath, yamlCollectionExample);
423
+ const yamlExamplePath = path.join(collectionsFolder, `Example${terminology.containerName}.yaml`);
424
+ writeFileSync(yamlExamplePath, yamlExample);
366
425
 
367
- // Create JSON schema for collection definitions
368
- const collectionJsonSchema = {
426
+ MessageFormatter.info(`Created example ${terminology.container} definition with ${terminology.fields} terminology`, { prefix: "Setup" });
427
+
428
+ // Create JSON schema for collection/table definitions
429
+ const containerJsonSchema = useTables ? {
430
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
431
+ "$id": "https://appwrite-utils.dev/schemas/table.schema.json",
432
+ "title": "Appwrite Table Definition",
433
+ "description": "Schema for defining Appwrite tables in YAML (TablesDB API)",
434
+ "type": "object",
435
+ "properties": {
436
+ "name": {
437
+ "type": "string",
438
+ "description": "The name of the table"
439
+ },
440
+ "id": {
441
+ "type": "string",
442
+ "description": "The ID of the table (optional, auto-generated if not provided)",
443
+ "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$"
444
+ },
445
+ "rowSecurity": {
446
+ "type": "boolean",
447
+ "default": false,
448
+ "description": "Enable row-level permissions"
449
+ },
450
+ "enabled": {
451
+ "type": "boolean",
452
+ "default": true,
453
+ "description": "Whether the table is enabled"
454
+ },
455
+ "permissions": {
456
+ "type": "array",
457
+ "description": "Table-level permissions",
458
+ "items": {
459
+ "type": "object",
460
+ "properties": {
461
+ "permission": {
462
+ "type": "string",
463
+ "enum": ["read", "create", "update", "delete"],
464
+ "description": "The permission type"
465
+ },
466
+ "target": {
467
+ "type": "string",
468
+ "description": "Permission target (e.g., 'any', 'users', 'users/verified', 'label:admin')"
469
+ }
470
+ },
471
+ "required": ["permission", "target"],
472
+ "additionalProperties": false
473
+ }
474
+ },
475
+ "columns": {
476
+ "type": "array",
477
+ "description": "Table columns (fields)",
478
+ "items": {
479
+ "type": "object",
480
+ "properties": {
481
+ "key": {
482
+ "type": "string",
483
+ "description": "Column name",
484
+ "pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
485
+ },
486
+ "type": {
487
+ "type": "string",
488
+ "enum": ["string", "integer", "double", "boolean", "datetime", "email", "ip", "url", "enum", "relationship"],
489
+ "description": "Column data type"
490
+ },
491
+ "size": {
492
+ "type": "number",
493
+ "description": "Maximum size for string columns",
494
+ "minimum": 1,
495
+ "maximum": 1073741824
496
+ },
497
+ "required": {
498
+ "type": "boolean",
499
+ "default": false,
500
+ "description": "Whether the column is required"
501
+ },
502
+ "array": {
503
+ "type": "boolean",
504
+ "default": false,
505
+ "description": "Whether the column is an array"
506
+ },
507
+ "unique": {
508
+ "type": "boolean",
509
+ "default": false,
510
+ "description": "Whether the column values must be unique (TablesDB feature)"
511
+ },
512
+ "default": {
513
+ "description": "Default value for the column"
514
+ },
515
+ "description": {
516
+ "type": "string",
517
+ "description": "Column description"
518
+ },
519
+ "min": {
520
+ "type": "number",
521
+ "description": "Minimum value for numeric columns"
522
+ },
523
+ "max": {
524
+ "type": "number",
525
+ "description": "Maximum value for numeric columns"
526
+ },
527
+ "elements": {
528
+ "type": "array",
529
+ "items": {
530
+ "type": "string"
531
+ },
532
+ "description": "Allowed values for enum columns"
533
+ },
534
+ "relatedCollection": {
535
+ "type": "string",
536
+ "description": "Related table name for relationship columns"
537
+ },
538
+ "relationType": {
539
+ "type": "string",
540
+ "enum": ["oneToOne", "oneToMany", "manyToOne", "manyToMany"],
541
+ "description": "Type of relationship"
542
+ },
543
+ "twoWay": {
544
+ "type": "boolean",
545
+ "description": "Whether the relationship is bidirectional"
546
+ },
547
+ "twoWayKey": {
548
+ "type": "string",
549
+ "description": "Key name for the reverse relationship"
550
+ },
551
+ "onDelete": {
552
+ "type": "string",
553
+ "enum": ["cascade", "restrict", "setNull"],
554
+ "description": "Action to take when related row is deleted"
555
+ },
556
+ "side": {
557
+ "type": "string",
558
+ "enum": ["parent", "child"],
559
+ "description": "Side of the relationship"
560
+ }
561
+ },
562
+ "required": ["key", "type"],
563
+ "additionalProperties": false,
564
+ "allOf": [
565
+ {
566
+ "if": {
567
+ "properties": { "type": { "const": "enum" } }
568
+ },
569
+ "then": {
570
+ "required": ["elements"]
571
+ }
572
+ },
573
+ {
574
+ "if": {
575
+ "properties": { "type": { "const": "relationship" } }
576
+ },
577
+ "then": {
578
+ "required": ["relatedCollection", "relationType"]
579
+ }
580
+ }
581
+ ]
582
+ }
583
+ },
584
+ "indexes": {
585
+ "type": "array",
586
+ "description": "Database indexes for the table",
587
+ "items": {
588
+ "type": "object",
589
+ "properties": {
590
+ "key": {
591
+ "type": "string",
592
+ "description": "Index name"
593
+ },
594
+ "type": {
595
+ "type": "string",
596
+ "enum": ["key", "fulltext", "unique"],
597
+ "description": "Index type"
598
+ },
599
+ "attributes": {
600
+ "type": "array",
601
+ "items": {
602
+ "type": "string"
603
+ },
604
+ "description": "Columns to index",
605
+ "minItems": 1
606
+ },
607
+ "orders": {
608
+ "type": "array",
609
+ "items": {
610
+ "type": "string",
611
+ "enum": ["ASC", "DESC"]
612
+ },
613
+ "description": "Sort order for each column"
614
+ }
615
+ },
616
+ "required": ["key", "type", "attributes"],
617
+ "additionalProperties": false
618
+ }
619
+ },
620
+ "importDefs": {
621
+ "type": "array",
622
+ "description": "Import definitions for data migration",
623
+ "default": []
624
+ }
625
+ },
626
+ "required": ["name"],
627
+ "additionalProperties": false
628
+ } : {
369
629
  "$schema": "https://json-schema.org/draft/2020-12/schema",
370
630
  "$id": "https://appwrite-utils.dev/schemas/collection.schema.json",
371
631
  "title": "Appwrite Collection Definition",
@@ -566,8 +826,9 @@ importDefs: []
566
826
  mkdirSync(appwriteYamlSchemaFolder, { recursive: true });
567
827
  }
568
828
 
569
- const collectionSchemaPath = path.join(appwriteYamlSchemaFolder, "collection.schema.json");
570
- writeFileSync(collectionSchemaPath, JSON.stringify(collectionJsonSchema, null, 2));
829
+ const schemaFileName = useTables ? "table.schema.json" : "collection.schema.json";
830
+ const containerSchemaPath = path.join(appwriteYamlSchemaFolder, schemaFileName);
831
+ writeFileSync(containerSchemaPath, JSON.stringify(containerJsonSchema, null, 2));
571
832
 
572
833
  // Create JSON schema for appwriteConfig.yaml
573
834
  const configJsonSchema = {
@@ -935,20 +1196,27 @@ importDefs: []
935
1196
  // Remove the nested .appwrite folder creation since we're using .appwrite as the main folder
936
1197
 
937
1198
  const configType = useYaml ? "YAML" : "TypeScript";
938
- console.log(`✨ Created ${configType} config and setup files/directories in .appwrite/ folder.`);
939
-
1199
+ const terminology = useTables ? "tables" : "collections";
1200
+ const containerType = useTables ? "TablesDB" : "Collections";
1201
+
1202
+ MessageFormatter.success(`Created ${configType} config and setup files/directories in .appwrite/ folder.`, { prefix: "Setup" });
1203
+ MessageFormatter.info(`Project configured for ${containerType} API (${detectionSource} detection)`, { prefix: "Setup" });
1204
+
940
1205
  if (useYaml) {
941
- console.log("🔧 You can now configure your project in .appwrite/config.yaml");
942
- console.log("📁 Collections can be defined in .appwrite/collections/ as .ts or .yaml files");
943
- console.log("📊 Schemas will be generated in .appwrite/schemas/");
944
- console.log("📦 Import data can be placed in .appwrite/importData/");
1206
+ MessageFormatter.info("You can now configure your project in .appwrite/config.yaml", { prefix: "Setup" });
1207
+ MessageFormatter.info(`${useTables ? 'Tables' : 'Collections'} can be defined in .appwrite/${terminology}/ as .ts or .yaml files`, { prefix: "Setup" });
1208
+ MessageFormatter.info("Schemas will be generated in .appwrite/schemas/", { prefix: "Setup" });
1209
+ MessageFormatter.info("Import data can be placed in .appwrite/importData/", { prefix: "Setup" });
1210
+ if (useTables) {
1211
+ MessageFormatter.info("TablesDB features: unique constraints, enhanced performance, row-level security", { prefix: "Setup" });
1212
+ }
945
1213
  } else {
946
- console.log("🔧 You can now configure logging in your .appwrite/appwriteConfig.ts file:");
947
- console.log(" logging: {");
948
- console.log(" enabled: true,");
949
- console.log(" level: 'info',");
950
- console.log(" console: true,");
951
- console.log(" logDirectory: './logs' // optional custom directory");
952
- console.log(" }");
1214
+ MessageFormatter.info("You can now configure logging in your .appwrite/appwriteConfig.ts file:", { prefix: "Setup" });
1215
+ MessageFormatter.info(" logging: {", { prefix: "Setup" });
1216
+ MessageFormatter.info(" enabled: true,", { prefix: "Setup" });
1217
+ MessageFormatter.info(" level: 'info',", { prefix: "Setup" });
1218
+ MessageFormatter.info(" console: true,", { prefix: "Setup" });
1219
+ MessageFormatter.info(" logDirectory: './logs' // optional custom directory", { prefix: "Setup" });
1220
+ MessageFormatter.info(" }", { prefix: "Setup" });
953
1221
  }
954
1222
  };
@@ -0,0 +1,65 @@
1
+ import type { Databases } from "node-appwrite";
2
+ import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
3
+ import { logger } from "../shared/logging.js";
4
+
5
+ /**
6
+ * Type guard and validation utilities
7
+ */
8
+
9
+ /**
10
+ * Type guard to check if object is a DatabaseAdapter
11
+ * @param db - Object to check
12
+ * @returns True if object is DatabaseAdapter
13
+ */
14
+ export function isDatabaseAdapter(db: Databases | DatabaseAdapter): db is DatabaseAdapter {
15
+ const isAdapter = 'getMetadata' in db && typeof db.getMetadata === 'function';
16
+ logger.debug('Adapter type detection', {
17
+ isAdapter,
18
+ hasGetMetadata: 'getMetadata' in db,
19
+ getMetadataType: typeof (db as any).getMetadata,
20
+ operation: 'isDatabaseAdapter'
21
+ });
22
+ return isAdapter;
23
+ }
24
+
25
+ /**
26
+ * Type guard to check if object is legacy Databases instance
27
+ * @param db - Object to check
28
+ * @returns True if object is Databases (not DatabaseAdapter)
29
+ */
30
+ export function isLegacyDatabases(db: Databases | DatabaseAdapter): db is Databases {
31
+ return !isDatabaseAdapter(db);
32
+ }
33
+
34
+ /**
35
+ * Checks if object has metadata property
36
+ * @param obj - Object to check
37
+ * @returns True if object has metadata
38
+ */
39
+ export function hasMetadata(obj: any): boolean {
40
+ return obj && typeof obj === 'object' && 'metadata' in obj;
41
+ }
42
+
43
+ /**
44
+ * Type guard for collection create objects
45
+ * @param obj - Object to check
46
+ * @returns True if object looks like CollectionCreate
47
+ */
48
+ export function isCollectionCreate(obj: any): boolean {
49
+ return obj &&
50
+ typeof obj === 'object' &&
51
+ 'name' in obj &&
52
+ ('$id' in obj || 'collectionId' in obj);
53
+ }
54
+
55
+ /**
56
+ * Type guard for table create objects
57
+ * @param obj - Object to check
58
+ * @returns True if object looks like TableCreate
59
+ */
60
+ export function isTableCreate(obj: any): boolean {
61
+ return obj &&
62
+ typeof obj === 'object' &&
63
+ 'name' in obj &&
64
+ ('tableId' in obj || '$id' in obj);
65
+ }