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
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @fileoverview Session Preservation Usage Examples
3
+ *
4
+ * This file demonstrates how to use the enhanced config loading functions
5
+ * with session preservation capabilities.
6
+ */
7
+ import { loadConfig, loadConfigWithPath, createSessionPreservation } from './loadConfigs.js';
8
+ /**
9
+ * Example 1: Basic session preservation
10
+ */
11
+ export async function loadConfigWithSession(configDir, sessionCookie) {
12
+ const config = await loadConfig(configDir, {
13
+ validate: true,
14
+ preserveAuth: {
15
+ sessionCookie,
16
+ authMethod: "session"
17
+ }
18
+ });
19
+ console.log('Config loaded with session auth:', {
20
+ authMethod: config.authMethod,
21
+ hasSessionCookie: !!config.sessionCookie
22
+ });
23
+ return config;
24
+ }
25
+ /**
26
+ * Example 2: Using the helper function for cleaner code
27
+ */
28
+ export async function loadConfigWithSessionHelper(configDir, sessionCookie, email, expiresAt) {
29
+ const sessionPreservation = createSessionPreservation(sessionCookie, email, expiresAt);
30
+ const result = await loadConfigWithPath(configDir, {
31
+ validate: true,
32
+ reportValidation: true,
33
+ preserveAuth: sessionPreservation
34
+ });
35
+ console.log('Config loaded with session metadata:', {
36
+ authMethod: result.config.authMethod,
37
+ sessionMetadata: result.config.sessionMetadata,
38
+ configPath: result.actualConfigPath
39
+ });
40
+ return result;
41
+ }
42
+ /**
43
+ * Example 3: Preserving existing appwriteClient with session context
44
+ */
45
+ export async function loadConfigPreservingClient(configDir, existingClient, sessionCookie) {
46
+ const config = await loadConfig(configDir, {
47
+ preserveAuth: {
48
+ sessionCookie,
49
+ authMethod: "session"
50
+ }
51
+ });
52
+ // Preserve existing client if it has session authentication
53
+ if (existingClient && !config.appwriteClient) {
54
+ config.appwriteClient = existingClient;
55
+ }
56
+ return config;
57
+ }
58
+ /**
59
+ * Example 4: Auto-detection with fallback
60
+ */
61
+ export async function loadConfigWithAutoAuth(configDir, sessionCookie, apiKey) {
62
+ let preserveAuth;
63
+ if (sessionCookie) {
64
+ preserveAuth = {
65
+ sessionCookie,
66
+ authMethod: "session"
67
+ };
68
+ }
69
+ else if (apiKey) {
70
+ preserveAuth = {
71
+ authMethod: "apikey"
72
+ };
73
+ }
74
+ else {
75
+ preserveAuth = {
76
+ authMethod: "auto"
77
+ };
78
+ }
79
+ const config = await loadConfig(configDir, {
80
+ validate: true,
81
+ preserveAuth
82
+ });
83
+ console.log('Auto-detected auth method:', config.authMethod);
84
+ return config;
85
+ }
86
+ /**
87
+ * Example 5: Backward compatibility - no changes to existing calls
88
+ */
89
+ export async function existingUsageStillWorks(configDir) {
90
+ // This should work exactly as before - no session preservation
91
+ const config = await loadConfig(configDir, {
92
+ validate: true,
93
+ strictMode: false
94
+ });
95
+ // Should use default auth method (auto or apikey)
96
+ console.log('Traditional loading still works:', {
97
+ authMethod: config.authMethod,
98
+ hasSession: !!config.sessionCookie
99
+ });
100
+ return config;
101
+ }
@@ -7,6 +7,9 @@ import { findYamlConfig } from "../config/yamlConfig.js";
7
7
  import { ID } from "node-appwrite";
8
8
  import { ulid } from "ulidx";
9
9
  import { generateYamlConfigTemplate } from "../config/yamlConfig.js";
10
+ import { loadAppwriteProjectConfig, findAppwriteProjectConfig, getProjectDirectoryName, isTablesDBProject } from "./projectConfig.js";
11
+ import { hasSessionAuth, getSessionAuth } from "./sessionAuth.js";
12
+ import { MessageFormatter } from "../shared/messageFormatter.js";
10
13
  // Example base configuration using types from appwrite-utils
11
14
  const baseConfig = {
12
15
  appwriteEndpoint: "https://cloud.appwrite.io/v1",
@@ -14,13 +17,13 @@ const baseConfig = {
14
17
  appwriteKey: "YOUR_API_KEY",
15
18
  appwriteClient: null,
16
19
  apiMode: "auto", // Enable dual API support - auto-detect TablesDB vs legacy
20
+ authMethod: "auto", // Default to auto-detect authentication method
17
21
  logging: {
18
22
  enabled: false,
19
23
  level: "info",
20
24
  console: false,
21
25
  },
22
26
  enableBackups: true,
23
- useMigrations: true,
24
27
  backupInterval: 3600,
25
28
  backupRetention: 30,
26
29
  enableBackupCleanup: true,
@@ -190,7 +193,7 @@ importDefs: []
190
193
  `;
191
194
  const collectionFilePath = path.join(collectionsFolder, `${collectionName}.yaml`);
192
195
  writeFileSync(collectionFilePath, yamlCollection);
193
- console.log(`✨ Created YAML collection: ${collectionFilePath}`);
196
+ MessageFormatter.success(`Created YAML collection: ${collectionFilePath}`, { prefix: "Setup" });
194
197
  }
195
198
  else {
196
199
  // Create TypeScript collection
@@ -218,7 +221,7 @@ const ${collectionName}: Partial<CollectionCreate> = {
218
221
  export default ${collectionName};`;
219
222
  const collectionFilePath = path.join(collectionsFolder, `${collectionName}.ts`);
220
223
  writeFileSync(collectionFilePath, emptyCollection);
221
- console.log(`✨ Created TypeScript collection: ${collectionFilePath}`);
224
+ MessageFormatter.success(`Created TypeScript collection: ${collectionFilePath}`, { prefix: "Setup" });
222
225
  }
223
226
  };
224
227
  export const generateYamlConfig = (currentDir, useAppwriteDir = true) => {
@@ -229,8 +232,8 @@ export const generateYamlConfig = (currentDir, useAppwriteDir = true) => {
229
232
  }
230
233
  const configPath = path.join(configDir, "config.yaml");
231
234
  generateYamlConfigTemplate(configPath);
232
- console.log(`✨ Generated YAML config template at: ${configPath}`);
233
- console.log("📝 Please update the configuration with your Appwrite project details.");
235
+ MessageFormatter.success(`Generated YAML config template at: ${configPath}`, { prefix: "Setup" });
236
+ MessageFormatter.info("Please update the configuration with your Appwrite project details.", { prefix: "Setup" });
234
237
  return configPath;
235
238
  };
236
239
  export const setupDirsFiles = async (example = false, currentDir, useYaml = true) => {
@@ -242,21 +245,48 @@ export const setupDirsFiles = async (example = false, currentDir, useYaml = true
242
245
  const appwriteSchemaFolder = path.join(appwriteFolder, "schemas");
243
246
  const appwriteYamlSchemaFolder = path.join(appwriteFolder, ".yaml_schemas");
244
247
  const appwriteDataFolder = path.join(appwriteFolder, "importData");
245
- // Decide between collections or tables folder
248
+ // Enhanced version detection with multiple sources
246
249
  let useTables = false;
250
+ let detectionSource = "default";
247
251
  try {
248
- // Try reading YAML config if present to detect version
249
- const yamlPath = findYamlConfig(basePath);
250
- if (yamlPath) {
251
- const cfg = await loadYamlConfig(yamlPath);
252
- if (cfg) {
253
- const ver = await fetchServerVersion(cfg.appwriteEndpoint);
254
- if (isVersionAtLeast(ver || undefined, '1.8.0'))
255
- useTables = true;
252
+ // Priority 1: Check for existing appwrite.json project config
253
+ const projectConfigPath = findAppwriteProjectConfig(basePath);
254
+ if (projectConfigPath) {
255
+ const projectConfig = loadAppwriteProjectConfig(projectConfigPath);
256
+ if (projectConfig) {
257
+ useTables = isTablesDBProject(projectConfig);
258
+ detectionSource = "appwrite.json";
259
+ MessageFormatter.info(`Detected ${useTables ? 'TablesDB' : 'Collections'} project from ${projectConfigPath}`, { prefix: "Setup" });
260
+ }
261
+ }
262
+ // Priority 2: Try reading existing YAML config for version detection
263
+ if (!useTables && detectionSource === "default") {
264
+ const yamlPath = findYamlConfig(basePath);
265
+ if (yamlPath) {
266
+ const cfg = await loadYamlConfig(yamlPath);
267
+ if (cfg) {
268
+ // Try session auth first, then API key for version detection
269
+ let endpoint = cfg.appwriteEndpoint;
270
+ let projectId = cfg.appwriteProject;
271
+ if (hasSessionAuth(endpoint, projectId)) {
272
+ MessageFormatter.info("Using session authentication for version detection", { prefix: "Setup" });
273
+ }
274
+ const ver = await fetchServerVersion(endpoint);
275
+ if (isVersionAtLeast(ver || undefined, '1.8.0')) {
276
+ useTables = true;
277
+ detectionSource = "server-version";
278
+ MessageFormatter.info(`Detected TablesDB support (Appwrite ${ver})`, { prefix: "Setup" });
279
+ }
280
+ else {
281
+ MessageFormatter.info(`Using Collections API (Appwrite ${ver || 'unknown'})`, { prefix: "Setup" });
282
+ }
283
+ }
256
284
  }
257
285
  }
258
286
  }
259
- catch { }
287
+ catch (error) {
288
+ MessageFormatter.warning(`Version detection failed, defaulting to Collections API: ${error instanceof Error ? error.message : String(error)}`, { prefix: "Setup" });
289
+ }
260
290
  const targetFolderName = useTables ? "tables" : "collections";
261
291
  const collectionsFolder = path.join(appwriteFolder, targetFolderName);
262
292
  // Create directory structure
@@ -293,13 +323,30 @@ export default appwriteConfig;
293
323
  writeFileSync(collectionFilePath, collection.content);
294
324
  });
295
325
  }
296
- // Create YAML collection example if using YAML config
326
+ // Create YAML collection/table example if using YAML config
297
327
  if (useYaml) {
298
- const yamlCollectionExample = `# yaml-language-server: $schema=../.yaml_schemas/collection.schema.json
299
- # Example Collection Definition
300
- name: ExampleCollection
301
- id: example_collection_${Date.now()}
302
- documentSecurity: false
328
+ const terminology = useTables
329
+ ? {
330
+ container: "table",
331
+ fields: "columns",
332
+ security: "rowSecurity",
333
+ schemaRef: "table.schema.json",
334
+ containerName: "Table",
335
+ fieldName: "Column"
336
+ }
337
+ : {
338
+ container: "collection",
339
+ fields: "attributes",
340
+ security: "documentSecurity",
341
+ schemaRef: "collection.schema.json",
342
+ containerName: "Collection",
343
+ fieldName: "Attribute"
344
+ };
345
+ const yamlExample = `# yaml-language-server: $schema=../.yaml_schemas/${terminology.schemaRef}
346
+ # Example ${terminology.containerName} Definition
347
+ name: Example${terminology.containerName}
348
+ id: example_${terminology.container}_${Date.now()}
349
+ ${terminology.security}: false
303
350
  enabled: true
304
351
  permissions:
305
352
  - permission: read
@@ -310,7 +357,7 @@ permissions:
310
357
  target: users
311
358
  - permission: delete
312
359
  target: users
313
- attributes:
360
+ ${terminology.fields}:
314
361
  - key: title
315
362
  type: string
316
363
  size: 255
@@ -324,7 +371,13 @@ attributes:
324
371
  - key: isActive
325
372
  type: boolean
326
373
  required: false
327
- default: true
374
+ default: true${useTables ? `
375
+ - key: uniqueCode
376
+ type: string
377
+ size: 50
378
+ required: false
379
+ unique: true
380
+ description: "Unique identifier code (TablesDB feature)"` : ''}
328
381
  indexes:
329
382
  - key: title_search
330
383
  type: fulltext
@@ -332,10 +385,210 @@ indexes:
332
385
  - title
333
386
  importDefs: []
334
387
  `;
335
- const yamlCollectionPath = path.join(collectionsFolder, "ExampleCollection.yaml");
336
- writeFileSync(yamlCollectionPath, yamlCollectionExample);
337
- // Create JSON schema for collection definitions
338
- const collectionJsonSchema = {
388
+ const yamlExamplePath = path.join(collectionsFolder, `Example${terminology.containerName}.yaml`);
389
+ writeFileSync(yamlExamplePath, yamlExample);
390
+ MessageFormatter.info(`Created example ${terminology.container} definition with ${terminology.fields} terminology`, { prefix: "Setup" });
391
+ // Create JSON schema for collection/table definitions
392
+ const containerJsonSchema = useTables ? {
393
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
394
+ "$id": "https://appwrite-utils.dev/schemas/table.schema.json",
395
+ "title": "Appwrite Table Definition",
396
+ "description": "Schema for defining Appwrite tables in YAML (TablesDB API)",
397
+ "type": "object",
398
+ "properties": {
399
+ "name": {
400
+ "type": "string",
401
+ "description": "The name of the table"
402
+ },
403
+ "id": {
404
+ "type": "string",
405
+ "description": "The ID of the table (optional, auto-generated if not provided)",
406
+ "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$"
407
+ },
408
+ "rowSecurity": {
409
+ "type": "boolean",
410
+ "default": false,
411
+ "description": "Enable row-level permissions"
412
+ },
413
+ "enabled": {
414
+ "type": "boolean",
415
+ "default": true,
416
+ "description": "Whether the table is enabled"
417
+ },
418
+ "permissions": {
419
+ "type": "array",
420
+ "description": "Table-level permissions",
421
+ "items": {
422
+ "type": "object",
423
+ "properties": {
424
+ "permission": {
425
+ "type": "string",
426
+ "enum": ["read", "create", "update", "delete"],
427
+ "description": "The permission type"
428
+ },
429
+ "target": {
430
+ "type": "string",
431
+ "description": "Permission target (e.g., 'any', 'users', 'users/verified', 'label:admin')"
432
+ }
433
+ },
434
+ "required": ["permission", "target"],
435
+ "additionalProperties": false
436
+ }
437
+ },
438
+ "columns": {
439
+ "type": "array",
440
+ "description": "Table columns (fields)",
441
+ "items": {
442
+ "type": "object",
443
+ "properties": {
444
+ "key": {
445
+ "type": "string",
446
+ "description": "Column name",
447
+ "pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
448
+ },
449
+ "type": {
450
+ "type": "string",
451
+ "enum": ["string", "integer", "double", "boolean", "datetime", "email", "ip", "url", "enum", "relationship"],
452
+ "description": "Column data type"
453
+ },
454
+ "size": {
455
+ "type": "number",
456
+ "description": "Maximum size for string columns",
457
+ "minimum": 1,
458
+ "maximum": 1073741824
459
+ },
460
+ "required": {
461
+ "type": "boolean",
462
+ "default": false,
463
+ "description": "Whether the column is required"
464
+ },
465
+ "array": {
466
+ "type": "boolean",
467
+ "default": false,
468
+ "description": "Whether the column is an array"
469
+ },
470
+ "unique": {
471
+ "type": "boolean",
472
+ "default": false,
473
+ "description": "Whether the column values must be unique (TablesDB feature)"
474
+ },
475
+ "default": {
476
+ "description": "Default value for the column"
477
+ },
478
+ "description": {
479
+ "type": "string",
480
+ "description": "Column description"
481
+ },
482
+ "min": {
483
+ "type": "number",
484
+ "description": "Minimum value for numeric columns"
485
+ },
486
+ "max": {
487
+ "type": "number",
488
+ "description": "Maximum value for numeric columns"
489
+ },
490
+ "elements": {
491
+ "type": "array",
492
+ "items": {
493
+ "type": "string"
494
+ },
495
+ "description": "Allowed values for enum columns"
496
+ },
497
+ "relatedCollection": {
498
+ "type": "string",
499
+ "description": "Related table name for relationship columns"
500
+ },
501
+ "relationType": {
502
+ "type": "string",
503
+ "enum": ["oneToOne", "oneToMany", "manyToOne", "manyToMany"],
504
+ "description": "Type of relationship"
505
+ },
506
+ "twoWay": {
507
+ "type": "boolean",
508
+ "description": "Whether the relationship is bidirectional"
509
+ },
510
+ "twoWayKey": {
511
+ "type": "string",
512
+ "description": "Key name for the reverse relationship"
513
+ },
514
+ "onDelete": {
515
+ "type": "string",
516
+ "enum": ["cascade", "restrict", "setNull"],
517
+ "description": "Action to take when related row is deleted"
518
+ },
519
+ "side": {
520
+ "type": "string",
521
+ "enum": ["parent", "child"],
522
+ "description": "Side of the relationship"
523
+ }
524
+ },
525
+ "required": ["key", "type"],
526
+ "additionalProperties": false,
527
+ "allOf": [
528
+ {
529
+ "if": {
530
+ "properties": { "type": { "const": "enum" } }
531
+ },
532
+ "then": {
533
+ "required": ["elements"]
534
+ }
535
+ },
536
+ {
537
+ "if": {
538
+ "properties": { "type": { "const": "relationship" } }
539
+ },
540
+ "then": {
541
+ "required": ["relatedCollection", "relationType"]
542
+ }
543
+ }
544
+ ]
545
+ }
546
+ },
547
+ "indexes": {
548
+ "type": "array",
549
+ "description": "Database indexes for the table",
550
+ "items": {
551
+ "type": "object",
552
+ "properties": {
553
+ "key": {
554
+ "type": "string",
555
+ "description": "Index name"
556
+ },
557
+ "type": {
558
+ "type": "string",
559
+ "enum": ["key", "fulltext", "unique"],
560
+ "description": "Index type"
561
+ },
562
+ "attributes": {
563
+ "type": "array",
564
+ "items": {
565
+ "type": "string"
566
+ },
567
+ "description": "Columns to index",
568
+ "minItems": 1
569
+ },
570
+ "orders": {
571
+ "type": "array",
572
+ "items": {
573
+ "type": "string",
574
+ "enum": ["ASC", "DESC"]
575
+ },
576
+ "description": "Sort order for each column"
577
+ }
578
+ },
579
+ "required": ["key", "type", "attributes"],
580
+ "additionalProperties": false
581
+ }
582
+ },
583
+ "importDefs": {
584
+ "type": "array",
585
+ "description": "Import definitions for data migration",
586
+ "default": []
587
+ }
588
+ },
589
+ "required": ["name"],
590
+ "additionalProperties": false
591
+ } : {
339
592
  "$schema": "https://json-schema.org/draft/2020-12/schema",
340
593
  "$id": "https://appwrite-utils.dev/schemas/collection.schema.json",
341
594
  "title": "Appwrite Collection Definition",
@@ -534,8 +787,9 @@ importDefs: []
534
787
  if (!existsSync(appwriteYamlSchemaFolder)) {
535
788
  mkdirSync(appwriteYamlSchemaFolder, { recursive: true });
536
789
  }
537
- const collectionSchemaPath = path.join(appwriteYamlSchemaFolder, "collection.schema.json");
538
- writeFileSync(collectionSchemaPath, JSON.stringify(collectionJsonSchema, null, 2));
790
+ const schemaFileName = useTables ? "table.schema.json" : "collection.schema.json";
791
+ const containerSchemaPath = path.join(appwriteYamlSchemaFolder, schemaFileName);
792
+ writeFileSync(containerSchemaPath, JSON.stringify(containerJsonSchema, null, 2));
539
793
  // Create JSON schema for appwriteConfig.yaml
540
794
  const configJsonSchema = {
541
795
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -897,20 +1151,26 @@ importDefs: []
897
1151
  }
898
1152
  // Remove the nested .appwrite folder creation since we're using .appwrite as the main folder
899
1153
  const configType = useYaml ? "YAML" : "TypeScript";
900
- console.log(`✨ Created ${configType} config and setup files/directories in .appwrite/ folder.`);
1154
+ const terminology = useTables ? "tables" : "collections";
1155
+ const containerType = useTables ? "TablesDB" : "Collections";
1156
+ MessageFormatter.success(`Created ${configType} config and setup files/directories in .appwrite/ folder.`, { prefix: "Setup" });
1157
+ MessageFormatter.info(`Project configured for ${containerType} API (${detectionSource} detection)`, { prefix: "Setup" });
901
1158
  if (useYaml) {
902
- console.log("🔧 You can now configure your project in .appwrite/config.yaml");
903
- console.log("📁 Collections can be defined in .appwrite/collections/ as .ts or .yaml files");
904
- console.log("📊 Schemas will be generated in .appwrite/schemas/");
905
- console.log("📦 Import data can be placed in .appwrite/importData/");
1159
+ MessageFormatter.info("You can now configure your project in .appwrite/config.yaml", { prefix: "Setup" });
1160
+ MessageFormatter.info(`${useTables ? 'Tables' : 'Collections'} can be defined in .appwrite/${terminology}/ as .ts or .yaml files`, { prefix: "Setup" });
1161
+ MessageFormatter.info("Schemas will be generated in .appwrite/schemas/", { prefix: "Setup" });
1162
+ MessageFormatter.info("Import data can be placed in .appwrite/importData/", { prefix: "Setup" });
1163
+ if (useTables) {
1164
+ MessageFormatter.info("TablesDB features: unique constraints, enhanced performance, row-level security", { prefix: "Setup" });
1165
+ }
906
1166
  }
907
1167
  else {
908
- console.log("🔧 You can now configure logging in your .appwrite/appwriteConfig.ts file:");
909
- console.log(" logging: {");
910
- console.log(" enabled: true,");
911
- console.log(" level: 'info',");
912
- console.log(" console: true,");
913
- console.log(" logDirectory: './logs' // optional custom directory");
914
- console.log(" }");
1168
+ MessageFormatter.info("You can now configure logging in your .appwrite/appwriteConfig.ts file:", { prefix: "Setup" });
1169
+ MessageFormatter.info(" logging: {", { prefix: "Setup" });
1170
+ MessageFormatter.info(" enabled: true,", { prefix: "Setup" });
1171
+ MessageFormatter.info(" level: 'info',", { prefix: "Setup" });
1172
+ MessageFormatter.info(" console: true,", { prefix: "Setup" });
1173
+ MessageFormatter.info(" logDirectory: './logs' // optional custom directory", { prefix: "Setup" });
1174
+ MessageFormatter.info(" }", { prefix: "Setup" });
915
1175
  }
916
1176
  };
@@ -0,0 +1,35 @@
1
+ import type { Databases } from "node-appwrite";
2
+ import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
3
+ /**
4
+ * Type guard and validation utilities
5
+ */
6
+ /**
7
+ * Type guard to check if object is a DatabaseAdapter
8
+ * @param db - Object to check
9
+ * @returns True if object is DatabaseAdapter
10
+ */
11
+ export declare function isDatabaseAdapter(db: Databases | DatabaseAdapter): db is DatabaseAdapter;
12
+ /**
13
+ * Type guard to check if object is legacy Databases instance
14
+ * @param db - Object to check
15
+ * @returns True if object is Databases (not DatabaseAdapter)
16
+ */
17
+ export declare function isLegacyDatabases(db: Databases | DatabaseAdapter): db is Databases;
18
+ /**
19
+ * Checks if object has metadata property
20
+ * @param obj - Object to check
21
+ * @returns True if object has metadata
22
+ */
23
+ export declare function hasMetadata(obj: any): boolean;
24
+ /**
25
+ * Type guard for collection create objects
26
+ * @param obj - Object to check
27
+ * @returns True if object looks like CollectionCreate
28
+ */
29
+ export declare function isCollectionCreate(obj: any): boolean;
30
+ /**
31
+ * Type guard for table create objects
32
+ * @param obj - Object to check
33
+ * @returns True if object looks like TableCreate
34
+ */
35
+ export declare function isTableCreate(obj: any): boolean;
@@ -0,0 +1,57 @@
1
+ import { logger } from "../shared/logging.js";
2
+ /**
3
+ * Type guard and validation utilities
4
+ */
5
+ /**
6
+ * Type guard to check if object is a DatabaseAdapter
7
+ * @param db - Object to check
8
+ * @returns True if object is DatabaseAdapter
9
+ */
10
+ export function isDatabaseAdapter(db) {
11
+ const isAdapter = 'getMetadata' in db && typeof db.getMetadata === 'function';
12
+ logger.debug('Adapter type detection', {
13
+ isAdapter,
14
+ hasGetMetadata: 'getMetadata' in db,
15
+ getMetadataType: typeof db.getMetadata,
16
+ operation: 'isDatabaseAdapter'
17
+ });
18
+ return isAdapter;
19
+ }
20
+ /**
21
+ * Type guard to check if object is legacy Databases instance
22
+ * @param db - Object to check
23
+ * @returns True if object is Databases (not DatabaseAdapter)
24
+ */
25
+ export function isLegacyDatabases(db) {
26
+ return !isDatabaseAdapter(db);
27
+ }
28
+ /**
29
+ * Checks if object has metadata property
30
+ * @param obj - Object to check
31
+ * @returns True if object has metadata
32
+ */
33
+ export function hasMetadata(obj) {
34
+ return obj && typeof obj === 'object' && 'metadata' in obj;
35
+ }
36
+ /**
37
+ * Type guard for collection create objects
38
+ * @param obj - Object to check
39
+ * @returns True if object looks like CollectionCreate
40
+ */
41
+ export function isCollectionCreate(obj) {
42
+ return obj &&
43
+ typeof obj === 'object' &&
44
+ 'name' in obj &&
45
+ ('$id' in obj || 'collectionId' in obj);
46
+ }
47
+ /**
48
+ * Type guard for table create objects
49
+ * @param obj - Object to check
50
+ * @returns True if object looks like TableCreate
51
+ */
52
+ export function isTableCreate(obj) {
53
+ return obj &&
54
+ typeof obj === 'object' &&
55
+ 'name' in obj &&
56
+ ('tableId' in obj || '$id' in obj);
57
+ }