appwrite-utils-cli 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +478 -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 +181 -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 +278 -1596
  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,430 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import {} from "appwrite-utils";
4
+ import { register } from "tsx/esm/api";
5
+ import { pathToFileURL } from "node:url";
6
+ import yaml from "js-yaml";
7
+ import { z } from "zod";
8
+ import { MessageFormatter } from "../shared/messageFormatter.js";
9
+ import { shouldIgnoreDirectory } from "./directoryUtils.js";
10
+ import { resolveCollectionsDir, resolveTablesDir } from "./pathResolvers.js";
11
+ import { findYamlConfig } from "../config/yamlConfig.js";
12
+ /**
13
+ * Recursively searches for TypeScript configuration files (appwriteConfig.ts)
14
+ * @param dir The directory to start the search from
15
+ * @param depth Current search depth for recursion limiting
16
+ * @returns Path to the config file or null if not found
17
+ */
18
+ export const findAppwriteConfigTS = (dir, depth = 0) => {
19
+ // Limit search depth to prevent infinite recursion
20
+ if (depth > 10) {
21
+ return null;
22
+ }
23
+ if (shouldIgnoreDirectory(path.basename(dir))) {
24
+ return null;
25
+ }
26
+ try {
27
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
28
+ // First check current directory for appwriteConfig.ts
29
+ for (const entry of entries) {
30
+ if (entry.isFile() && entry.name === "appwriteConfig.ts") {
31
+ return path.join(dir, entry.name);
32
+ }
33
+ }
34
+ // Then search subdirectories
35
+ for (const entry of entries) {
36
+ if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
37
+ const result = findAppwriteConfigTS(path.join(dir, entry.name), depth + 1);
38
+ if (result)
39
+ return result;
40
+ }
41
+ }
42
+ }
43
+ catch (error) {
44
+ // Ignore directory access errors
45
+ }
46
+ return null;
47
+ };
48
+ /**
49
+ * Recursively searches for configuration files starting from the given directory.
50
+ * Priority: 1) YAML configs in .appwrite directories, 2) appwriteConfig.ts files in subdirectories
51
+ * @param dir The directory to start the search from
52
+ * @returns The directory path where the config was found, suitable for passing to loadConfig()
53
+ */
54
+ export const findAppwriteConfig = (dir) => {
55
+ // First try to find YAML config (already searches recursively for .appwrite dirs)
56
+ const yamlConfig = findYamlConfig(dir);
57
+ if (yamlConfig) {
58
+ // Return the directory containing the config file
59
+ return path.dirname(yamlConfig);
60
+ }
61
+ // Fall back to TypeScript config search
62
+ const tsConfigPath = findAppwriteConfigTS(dir);
63
+ if (tsConfigPath) {
64
+ return path.dirname(tsConfigPath);
65
+ }
66
+ return null;
67
+ };
68
+ /**
69
+ * Recursively searches for the functions directory
70
+ * @param dir The directory to start searching from
71
+ * @param depth Current search depth for recursion limiting
72
+ * @returns Path to the functions directory or null if not found
73
+ */
74
+ export const findFunctionsDir = (dir, depth = 0) => {
75
+ // Limit search depth to prevent infinite recursion
76
+ if (depth > 5) {
77
+ return null;
78
+ }
79
+ if (shouldIgnoreDirectory(path.basename(dir))) {
80
+ return null;
81
+ }
82
+ try {
83
+ const files = fs.readdirSync(dir, { withFileTypes: true });
84
+ for (const entry of files) {
85
+ if (!entry.isDirectory() || shouldIgnoreDirectory(entry.name)) {
86
+ continue;
87
+ }
88
+ if (entry.name === "functions") {
89
+ return path.join(dir, entry.name);
90
+ }
91
+ const result = findFunctionsDir(path.join(dir, entry.name), depth + 1);
92
+ if (result)
93
+ return result;
94
+ }
95
+ }
96
+ catch (error) {
97
+ // Ignore directory access errors
98
+ }
99
+ return null;
100
+ };
101
+ // YAML Collection Schema
102
+ const YamlCollectionSchema = z.object({
103
+ name: z.string(),
104
+ id: z.string().optional(),
105
+ documentSecurity: z.boolean().default(false),
106
+ enabled: z.boolean().default(true),
107
+ permissions: z.array(z.object({
108
+ permission: z.string(),
109
+ target: z.string()
110
+ })).optional().default([]),
111
+ attributes: z.array(z.object({
112
+ key: z.string(),
113
+ type: z.string(),
114
+ size: z.number().optional(),
115
+ required: z.boolean().default(false),
116
+ array: z.boolean().optional(),
117
+ default: z.any().optional(),
118
+ min: z.number().optional(),
119
+ max: z.number().optional(),
120
+ elements: z.array(z.string()).optional(),
121
+ relatedCollection: z.string().optional(),
122
+ relationType: z.string().optional(),
123
+ twoWay: z.boolean().optional(),
124
+ twoWayKey: z.string().optional(),
125
+ onDelete: z.string().optional(),
126
+ side: z.string().optional()
127
+ })).optional().default([]),
128
+ indexes: z.array(z.object({
129
+ key: z.string(),
130
+ type: z.string(),
131
+ attributes: z.array(z.string()),
132
+ orders: z.array(z.string()).optional()
133
+ })).optional().default([]),
134
+ importDefs: z.array(z.any()).optional().default([])
135
+ });
136
+ /**
137
+ * Loads a YAML collection file and converts it to CollectionCreate format
138
+ * @param filePath Path to the YAML collection file
139
+ * @returns CollectionCreate object or null if loading fails
140
+ */
141
+ export const loadYamlCollection = (filePath) => {
142
+ try {
143
+ const fileContent = fs.readFileSync(filePath, "utf8");
144
+ const yamlData = yaml.load(fileContent);
145
+ const parsedCollection = YamlCollectionSchema.parse(yamlData);
146
+ // Convert YAML collection to CollectionCreate format
147
+ const collection = {
148
+ name: parsedCollection.name,
149
+ $id: parsedCollection.id || parsedCollection.name.toLowerCase().replace(/\s+/g, '_'),
150
+ documentSecurity: parsedCollection.documentSecurity,
151
+ enabled: parsedCollection.enabled,
152
+ $permissions: parsedCollection.permissions.map(p => ({
153
+ permission: p.permission,
154
+ target: p.target
155
+ })),
156
+ attributes: parsedCollection.attributes.map(attr => ({
157
+ key: attr.key,
158
+ type: attr.type,
159
+ size: attr.size,
160
+ required: attr.required,
161
+ array: attr.array,
162
+ xdefault: attr.default,
163
+ min: attr.min,
164
+ max: attr.max,
165
+ elements: attr.elements,
166
+ relatedCollection: attr.relatedCollection,
167
+ relationType: attr.relationType,
168
+ twoWay: attr.twoWay,
169
+ twoWayKey: attr.twoWayKey,
170
+ onDelete: attr.onDelete,
171
+ side: attr.side
172
+ })),
173
+ indexes: parsedCollection.indexes.map(idx => ({
174
+ key: idx.key,
175
+ type: idx.type,
176
+ attributes: idx.attributes,
177
+ orders: idx.orders
178
+ })),
179
+ importDefs: parsedCollection.importDefs && Array.isArray(parsedCollection.importDefs) && parsedCollection.importDefs.length > 0 ? parsedCollection.importDefs : []
180
+ };
181
+ return collection;
182
+ }
183
+ catch (error) {
184
+ MessageFormatter.error(`Error loading YAML collection from ${filePath}`, error, { prefix: "Config" });
185
+ return null;
186
+ }
187
+ };
188
+ /**
189
+ * Loads a YAML table file and converts it to table format
190
+ * @param filePath Path to the YAML table file
191
+ * @returns Table object or null if loading fails
192
+ */
193
+ export const loadYamlTable = (filePath) => {
194
+ try {
195
+ const fileContent = fs.readFileSync(filePath, "utf8");
196
+ const yamlData = yaml.load(fileContent);
197
+ // For now, use the collection schema as base and adapt for tables
198
+ const parsedTable = YamlCollectionSchema.parse(yamlData);
199
+ // Convert YAML table to TableCreate format
200
+ const table = {
201
+ name: parsedTable.name,
202
+ tableId: yamlData.tableId || parsedTable.id || parsedTable.name.toLowerCase().replace(/\s+/g, '_'),
203
+ documentSecurity: parsedTable.documentSecurity,
204
+ enabled: parsedTable.enabled,
205
+ $permissions: parsedTable.permissions.map(p => ({
206
+ permission: p.permission,
207
+ target: p.target
208
+ })),
209
+ attributes: parsedTable.attributes.map(attr => ({
210
+ key: attr.key,
211
+ type: attr.type,
212
+ size: attr.size,
213
+ required: attr.required,
214
+ array: attr.array,
215
+ xdefault: attr.default,
216
+ min: attr.min,
217
+ max: attr.max,
218
+ elements: attr.elements,
219
+ relatedCollection: attr.relatedCollection,
220
+ relationType: attr.relationType,
221
+ twoWay: attr.twoWay,
222
+ twoWayKey: attr.twoWayKey,
223
+ onDelete: attr.onDelete,
224
+ side: attr.side
225
+ })),
226
+ indexes: parsedTable.indexes.map(idx => ({
227
+ key: idx.key,
228
+ type: idx.type,
229
+ attributes: idx.attributes,
230
+ orders: idx.orders
231
+ })),
232
+ importDefs: parsedTable.importDefs,
233
+ databaseId: yamlData.databaseId,
234
+ // Add backward compatibility field
235
+ $id: yamlData.$id || parsedTable.id
236
+ };
237
+ return table;
238
+ }
239
+ catch (error) {
240
+ MessageFormatter.error(`Error loading YAML table from ${filePath}`, error, { prefix: "Config" });
241
+ return null;
242
+ }
243
+ };
244
+ /**
245
+ * Discovers and loads collections from a collections/ directory
246
+ * @param collectionsDir Path to the collections directory
247
+ * @returns Discovery result with loaded collections and metadata
248
+ */
249
+ export const discoverCollections = async (collectionsDir) => {
250
+ const collections = [];
251
+ const loadedNames = new Set();
252
+ const conflicts = [];
253
+ if (!fs.existsSync(collectionsDir)) {
254
+ return { collections, loadedNames, conflicts };
255
+ }
256
+ const unregister = register(); // Register tsx for collections
257
+ try {
258
+ const collectionFiles = fs.readdirSync(collectionsDir);
259
+ MessageFormatter.success(`Loading from collections/ directory: ${collectionFiles.length} files found`, { prefix: "Config" });
260
+ for (const file of collectionFiles) {
261
+ if (file === "index.ts") {
262
+ continue;
263
+ }
264
+ const filePath = path.join(collectionsDir, file);
265
+ let collection = null;
266
+ // Handle YAML collections
267
+ if (file.endsWith('.yaml') || file.endsWith('.yml')) {
268
+ collection = loadYamlCollection(filePath);
269
+ }
270
+ // Handle TypeScript collections
271
+ else if (file.endsWith('.ts')) {
272
+ const fileUrl = pathToFileURL(filePath).href;
273
+ const collectionModule = (await import(fileUrl));
274
+ const importedCollection = collectionModule.default?.default || collectionModule.default || collectionModule;
275
+ if (importedCollection) {
276
+ collection = importedCollection;
277
+ // Ensure importDefs are properly loaded
278
+ if (collectionModule.importDefs || collection.importDefs) {
279
+ collection.importDefs = collectionModule.importDefs || collection.importDefs;
280
+ }
281
+ }
282
+ }
283
+ if (collection) {
284
+ const collectionName = collection.name || collection.$id || file;
285
+ loadedNames.add(collectionName);
286
+ collections.push(collection);
287
+ }
288
+ }
289
+ }
290
+ finally {
291
+ unregister(); // Unregister tsx when done
292
+ }
293
+ return { collections, loadedNames, conflicts };
294
+ };
295
+ /**
296
+ * Discovers and loads tables from a tables/ directory
297
+ * @param tablesDir Path to the tables directory
298
+ * @param existingNames Set of already-loaded collection names to check for conflicts
299
+ * @returns Discovery result with loaded tables and metadata
300
+ */
301
+ export const discoverTables = async (tablesDir, existingNames = new Set()) => {
302
+ const tables = [];
303
+ const loadedNames = new Set();
304
+ const conflicts = [];
305
+ if (!fs.existsSync(tablesDir)) {
306
+ return { tables, loadedNames, conflicts };
307
+ }
308
+ const unregister = register(); // Register tsx for tables
309
+ try {
310
+ const tableFiles = fs.readdirSync(tablesDir);
311
+ MessageFormatter.success(`Loading from tables/ directory: ${tableFiles.length} files found`, { prefix: "Config" });
312
+ for (const file of tableFiles) {
313
+ if (file === "index.ts") {
314
+ continue;
315
+ }
316
+ const filePath = path.join(tablesDir, file);
317
+ let table = null;
318
+ // Handle YAML tables
319
+ if (file.endsWith('.yaml') || file.endsWith('.yml')) {
320
+ table = loadYamlTable(filePath);
321
+ }
322
+ // Handle TypeScript tables
323
+ else if (file.endsWith('.ts')) {
324
+ const fileUrl = pathToFileURL(filePath).href;
325
+ const tableModule = (await import(fileUrl));
326
+ const importedTable = tableModule.default?.default || tableModule.default || tableModule;
327
+ if (importedTable) {
328
+ table = importedTable;
329
+ // Ensure importDefs are properly loaded
330
+ if (tableModule.importDefs || table.importDefs) {
331
+ table.importDefs = tableModule.importDefs || table.importDefs;
332
+ }
333
+ }
334
+ }
335
+ if (table) {
336
+ const tableName = table.name || table.tableId || table.$id || file;
337
+ // Check for naming conflicts with existing collections
338
+ if (existingNames.has(tableName)) {
339
+ conflicts.push({
340
+ name: tableName,
341
+ source1: "collections/",
342
+ source2: "tables/"
343
+ });
344
+ MessageFormatter.warning(`Skipping duplicate '${tableName}' from tables/ (collections/ takes priority)`, { prefix: "Config" });
345
+ }
346
+ else {
347
+ loadedNames.add(tableName);
348
+ // Mark as coming from tables directory
349
+ table._isFromTablesDir = true;
350
+ tables.push(table);
351
+ }
352
+ }
353
+ }
354
+ }
355
+ finally {
356
+ unregister(); // Unregister tsx when done
357
+ }
358
+ return { tables, loadedNames, conflicts };
359
+ };
360
+ /**
361
+ * Discovers and loads collections/tables from legacy single directory structure
362
+ * @param configFileDir Directory containing the config file
363
+ * @param dirName Directory name to search for ('collections' or 'tables')
364
+ * @returns Array of discovered collections/tables
365
+ */
366
+ export const discoverLegacyDirectory = async (configFileDir, dirName) => {
367
+ const legacyDir = path.join(configFileDir, dirName);
368
+ const items = [];
369
+ if (!fs.existsSync(legacyDir)) {
370
+ return items;
371
+ }
372
+ MessageFormatter.info(`Using legacy single directory: ${dirName}/`, { prefix: "Config" });
373
+ const unregister = register(); // Register tsx for legacy collections
374
+ try {
375
+ const collectionFiles = fs.readdirSync(legacyDir);
376
+ for (const file of collectionFiles) {
377
+ if (file === "index.ts") {
378
+ continue;
379
+ }
380
+ const filePath = path.join(legacyDir, file);
381
+ // Handle YAML collections
382
+ if (file.endsWith('.yaml') || file.endsWith('.yml')) {
383
+ const collection = loadYamlCollection(filePath);
384
+ if (collection) {
385
+ if (dirName === 'tables') {
386
+ // Mark as coming from tables directory
387
+ const table = {
388
+ ...collection,
389
+ _isFromTablesDir: true,
390
+ tableId: collection.$id || collection.name.toLowerCase().replace(/\s+/g, '_')
391
+ };
392
+ items.push(table);
393
+ }
394
+ else {
395
+ items.push(collection);
396
+ }
397
+ }
398
+ continue;
399
+ }
400
+ // Handle TypeScript collections
401
+ if (file.endsWith('.ts')) {
402
+ const fileUrl = pathToFileURL(filePath).href;
403
+ const collectionModule = (await import(fileUrl));
404
+ const collection = collectionModule.default?.default || collectionModule.default || collectionModule;
405
+ if (collection) {
406
+ // Ensure importDefs are properly loaded
407
+ if (collectionModule.importDefs || collection.importDefs) {
408
+ collection.importDefs = collectionModule.importDefs || collection.importDefs;
409
+ }
410
+ if (dirName === 'tables') {
411
+ // Mark as coming from tables directory
412
+ const table = {
413
+ ...collection,
414
+ _isFromTablesDir: true,
415
+ tableId: collection.$id || collection.name.toLowerCase().replace(/\s+/g, '_')
416
+ };
417
+ items.push(table);
418
+ }
419
+ else {
420
+ items.push(collection);
421
+ }
422
+ }
423
+ }
424
+ }
425
+ }
426
+ finally {
427
+ unregister(); // Unregister tsx when done
428
+ }
429
+ return items;
430
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Directory utility functions for filtering and managing directory traversal
3
+ */
4
+ /**
5
+ * List of directories that should be ignored during recursive searches
6
+ * Includes common build outputs, dependencies, caches, and system folders
7
+ */
8
+ export declare const IGNORED_DIRECTORIES: string[];
9
+ /**
10
+ * Determines if a directory should be ignored during recursive file operations
11
+ *
12
+ * @param dirName - The name of the directory to check
13
+ * @returns true if the directory should be ignored, false otherwise
14
+ *
15
+ * @remarks
16
+ * A directory is ignored if:
17
+ * - It matches one of the entries in IGNORED_DIRECTORIES
18
+ * - It starts with '.git' prefix
19
+ * - It starts with 'node_modules' prefix
20
+ * - It starts with '.' (hidden directory) except for '.appwrite'
21
+ */
22
+ export declare const shouldIgnoreDirectory: (dirName: string) => boolean;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Directory utility functions for filtering and managing directory traversal
3
+ */
4
+ /**
5
+ * List of directories that should be ignored during recursive searches
6
+ * Includes common build outputs, dependencies, caches, and system folders
7
+ */
8
+ export const IGNORED_DIRECTORIES = [
9
+ 'node_modules',
10
+ 'dist',
11
+ 'build',
12
+ 'coverage',
13
+ '.next',
14
+ '.nuxt',
15
+ '.cache',
16
+ '.git',
17
+ '.svn',
18
+ '.hg',
19
+ '__pycache__',
20
+ '.pytest_cache',
21
+ '.mypy_cache',
22
+ 'venv',
23
+ '.venv',
24
+ 'env',
25
+ '.env',
26
+ 'target',
27
+ 'out',
28
+ 'bin',
29
+ 'obj',
30
+ '.vs',
31
+ '.vscode',
32
+ '.idea',
33
+ 'temp',
34
+ 'tmp',
35
+ '.tmp',
36
+ 'logs',
37
+ 'log',
38
+ '.DS_Store',
39
+ 'Thumbs.db'
40
+ ];
41
+ /**
42
+ * Determines if a directory should be ignored during recursive file operations
43
+ *
44
+ * @param dirName - The name of the directory to check
45
+ * @returns true if the directory should be ignored, false otherwise
46
+ *
47
+ * @remarks
48
+ * A directory is ignored if:
49
+ * - It matches one of the entries in IGNORED_DIRECTORIES
50
+ * - It starts with '.git' prefix
51
+ * - It starts with 'node_modules' prefix
52
+ * - It starts with '.' (hidden directory) except for '.appwrite'
53
+ */
54
+ export const shouldIgnoreDirectory = (dirName) => {
55
+ return IGNORED_DIRECTORIES.includes(dirName) ||
56
+ dirName.startsWith('.git') ||
57
+ dirName.startsWith('node_modules') ||
58
+ (dirName.startsWith('.') && dirName !== '.appwrite');
59
+ };
@@ -2,29 +2,38 @@ import { type AppwriteConfig } from "appwrite-utils";
2
2
  import { Client } from "node-appwrite";
3
3
  import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
4
4
  /**
5
- * Legacy function - returns basic Client for backwards compatibility
6
- * @deprecated Use getAdapterFromConfig for dual API support
5
+ * Enhanced client creation from config with session authentication support
6
+ * @deprecated Use getAdapterFromConfig for dual API support with session auth
7
7
  */
8
- export declare const getClientFromConfig: (config: AppwriteConfig) => Client | undefined;
8
+ export declare const getClientFromConfig: (config: AppwriteConfig, sessionCookie?: string) => Client | undefined;
9
+ /**
10
+ * Enhanced client creation with session authentication support
11
+ * Priority: explicit session > session from prefs > API key
12
+ */
13
+ export declare const getClientWithAuth: (endpoint: string, project: string, key?: string, sessionCookie?: string) => Client;
9
14
  /**
10
15
  * Legacy function - returns basic Client
11
- * @deprecated Use createDatabaseAdapter for dual API support
16
+ * @deprecated Use getClientWithAuth for session support or createDatabaseAdapter for dual API support
12
17
  */
13
18
  export declare const getClient: (endpoint: string, project: string, key: string) => Client;
14
19
  /**
15
- * Modern adapter-based client creation with dual API support
20
+ * Modern adapter-based client creation with dual API support and session authentication
16
21
  * Returns both adapter and legacy client for compatibility
17
22
  */
18
- export declare const getAdapterFromConfig: (config: AppwriteConfig, forceRefresh?: boolean) => Promise<{
23
+ export declare const getAdapterFromConfig: (config: AppwriteConfig, forceRefresh?: boolean, sessionCookie?: string) => Promise<{
19
24
  adapter: DatabaseAdapter;
20
25
  client: Client;
21
26
  apiMode: "legacy" | "tablesdb";
22
27
  }>;
23
28
  /**
24
- * Create adapter from individual parameters
29
+ * Create adapter from individual parameters with session authentication support
25
30
  */
26
- export declare const getAdapter: (endpoint: string, project: string, key: string, apiMode?: "auto" | "legacy" | "tablesdb") => Promise<{
31
+ export declare const getAdapter: (endpoint: string, project: string, key?: string, apiMode?: "auto" | "legacy" | "tablesdb", sessionCookie?: string) => Promise<{
27
32
  adapter: DatabaseAdapter;
28
33
  client: Client;
29
34
  apiMode: "legacy" | "tablesdb";
30
35
  }>;
36
+ /**
37
+ * Check if session authentication is available for a project
38
+ */
39
+ export declare const checkSessionAuth: (endpoint: string, project: string) => boolean;