appwrite-utils-cli 1.8.9 → 1.9.2

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 (34) hide show
  1. package/dist/adapters/DatabaseAdapter.d.ts +9 -0
  2. package/dist/adapters/LegacyAdapter.js +1 -1
  3. package/dist/adapters/TablesDBAdapter.js +29 -4
  4. package/dist/cli/commands/databaseCommands.d.ts +1 -0
  5. package/dist/cli/commands/databaseCommands.js +90 -0
  6. package/dist/config/ConfigManager.d.ts +5 -0
  7. package/dist/config/ConfigManager.js +1 -1
  8. package/dist/config/services/ConfigDiscoveryService.d.ts +43 -47
  9. package/dist/config/services/ConfigDiscoveryService.js +155 -207
  10. package/dist/config/services/ConfigLoaderService.js +2 -7
  11. package/dist/config/yamlConfig.d.ts +2 -2
  12. package/dist/functions/methods.js +14 -2
  13. package/dist/main.js +9 -1
  14. package/dist/migrations/appwriteToX.d.ts +1 -1
  15. package/dist/migrations/dataLoader.d.ts +3 -3
  16. package/dist/shared/functionManager.js +14 -2
  17. package/dist/storage/schemas.d.ts +4 -4
  18. package/dist/utils/projectConfig.d.ts +4 -1
  19. package/dist/utils/projectConfig.js +41 -6
  20. package/dist/utilsController.d.ts +1 -0
  21. package/dist/utilsController.js +2 -1
  22. package/package.json +2 -1
  23. package/src/adapters/DatabaseAdapter.ts +12 -0
  24. package/src/adapters/LegacyAdapter.ts +28 -28
  25. package/src/adapters/TablesDBAdapter.ts +46 -4
  26. package/src/cli/commands/databaseCommands.ts +141 -11
  27. package/src/config/ConfigManager.ts +10 -1
  28. package/src/config/services/ConfigDiscoveryService.ts +180 -233
  29. package/src/config/services/ConfigLoaderService.ts +2 -10
  30. package/src/functions/methods.ts +15 -2
  31. package/src/main.ts +213 -204
  32. package/src/shared/functionManager.ts +15 -3
  33. package/src/utils/projectConfig.ts +57 -16
  34. package/src/utilsController.ts +73 -72
@@ -1,20 +1,20 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
+ import { findUp } from "find-up";
3
4
  import { MessageFormatter } from "../../shared/messageFormatter.js";
4
5
  import { shouldIgnoreDirectory } from "../../utils/directoryUtils.js";
5
6
  /**
6
7
  * Service for discovering Appwrite configuration files and collection/table definitions.
7
8
  *
9
+ * Uses find-up for intelligent searching with git repository boundary detection:
10
+ * 1. Finds .git directory to establish repo root boundary
11
+ * 2. Searches UP from current directory to repo root
12
+ * 3. Searches DOWN recursively within repo root
13
+ *
8
14
  * Search Priority:
9
15
  * 1. YAML configs (.appwrite/config.yaml, .appwrite/config.yml, etc.)
10
- * 2. TypeScript configs (appwriteConfig.ts)
11
- * 3. JSON configs (appwrite.json, appwrite.config.json)
12
- *
13
- * Features:
14
- * - Searches up directory tree (max 5 levels)
15
- * - Ignores common directories (node_modules, .git, etc.)
16
- * - Discovers both collections/ and tables/ directories
17
- * - Recursive subdirectory scanning for .appwrite folders
16
+ * 2. JSON configs (appwrite.config.json, appwrite.json)
17
+ * 3. TypeScript configs (appwriteConfig.ts)
18
18
  */
19
19
  export class ConfigDiscoveryService {
20
20
  /**
@@ -28,184 +28,156 @@ export class ConfigDiscoveryService {
28
28
  "appwrite.yaml",
29
29
  "appwrite.yml",
30
30
  ];
31
- /**
32
- * TypeScript configuration file names to search for
33
- */
34
- TS_FILENAMES = ["appwriteConfig.ts"];
35
31
  /**
36
32
  * JSON configuration file names to search for
37
33
  */
38
- JSON_FILENAMES = ["appwrite.json", "appwrite.config.json"];
34
+ JSON_FILENAMES = ["appwrite.config.json", "appwrite.json"];
39
35
  /**
40
- * Maximum levels to search up the directory tree
41
- */
42
- MAX_SEARCH_DEPTH = 5;
43
- /**
44
- * Finds any configuration file with priority: YAML → TypeScript → JSON
45
- * @param startDir The directory to start searching from
46
- * @returns Path to the configuration file or null if not found
36
+ * TypeScript configuration file names to search for
47
37
  */
48
- findConfig(startDir) {
49
- // Try YAML first (highest priority)
50
- const yamlConfig = this.findYamlConfig(startDir);
51
- if (yamlConfig) {
52
- return yamlConfig;
53
- }
54
- // Try TypeScript second
55
- const tsConfig = this.findTypeScriptConfig(startDir);
56
- if (tsConfig) {
57
- return tsConfig;
58
- }
59
- // Try JSON last (lowest priority)
60
- const jsonConfig = this.findProjectConfig(startDir);
61
- if (jsonConfig) {
62
- return jsonConfig;
63
- }
64
- return null;
65
- }
38
+ TS_FILENAMES = ["appwriteConfig.ts"];
66
39
  /**
67
- * Finds YAML configuration files
68
- * Searches current directory, subdirectories, and parent directory
40
+ * Finds the git repository root directory
69
41
  * @param startDir The directory to start searching from
70
- * @returns Path to the YAML config file or null if not found
42
+ * @returns Path to the repository root, or startDir if no .git found
71
43
  */
72
- findYamlConfig(startDir) {
73
- // First check current directory for YAML configs
74
- for (const fileName of this.YAML_FILENAMES) {
75
- const configPath = path.join(startDir, fileName);
76
- if (fs.existsSync(configPath)) {
77
- return configPath;
78
- }
79
- }
80
- // Recursively search subdirectories for .appwrite folders
81
- const yamlConfigInSubdirs = this.findYamlConfigRecursive(startDir);
82
- if (yamlConfigInSubdirs) {
83
- return yamlConfigInSubdirs;
84
- }
85
- // Check one level up to avoid infinite traversal
86
- const parentDir = path.dirname(startDir);
87
- if (parentDir !== startDir && path.basename(parentDir) !== "node_modules") {
88
- for (const fileName of this.YAML_FILENAMES) {
89
- const configPath = path.join(parentDir, fileName);
90
- if (fs.existsSync(configPath)) {
91
- return configPath;
92
- }
93
- }
94
- }
95
- return null;
44
+ async findRepoRoot(startDir) {
45
+ const gitDir = await findUp(".git", {
46
+ cwd: startDir,
47
+ type: "directory",
48
+ });
49
+ return gitDir ? path.dirname(gitDir) : startDir;
96
50
  }
97
51
  /**
98
- * Recursively searches for YAML configs in .appwrite subdirectories
99
- * @param dir The directory to search
100
- * @param depth Current search depth
101
- * @returns Path to YAML config or null
52
+ * Recursively searches downward for files matching patterns
53
+ * @param dir Directory to search in
54
+ * @param patterns File patterns to match
55
+ * @param maxDepth Maximum depth to search
56
+ * @param currentDepth Current recursion depth
57
+ * @returns First matching file path or null
102
58
  */
103
- findYamlConfigRecursive(dir, depth = 0) {
104
- // Limit search depth to prevent infinite recursion
105
- if (depth > this.MAX_SEARCH_DEPTH) {
59
+ async searchDownward(dir, patterns, maxDepth = 5, currentDepth = 0) {
60
+ if (currentDepth > maxDepth)
106
61
  return null;
107
- }
108
- if (shouldIgnoreDirectory(path.basename(dir))) {
62
+ if (shouldIgnoreDirectory(path.basename(dir)))
109
63
  return null;
110
- }
111
64
  try {
112
- const entries = fs.readdirSync(dir, { withFileTypes: true });
65
+ const entries = await fs.promises.readdir(dir, { withFileTypes: true });
66
+ // Check current directory for matches
67
+ for (const pattern of patterns) {
68
+ const fullPath = path.join(dir, pattern);
69
+ if (fs.existsSync(fullPath)) {
70
+ return fullPath;
71
+ }
72
+ }
73
+ // Recurse into subdirectories
113
74
  for (const entry of entries) {
114
75
  if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
115
- const fullPath = path.join(dir, entry.name);
116
- // Check if this is an .appwrite directory
117
- if (entry.name === ".appwrite") {
118
- const configPaths = [
119
- path.join(fullPath, "config.yaml"),
120
- path.join(fullPath, "config.yml"),
121
- path.join(fullPath, "appwriteConfig.yaml"),
122
- path.join(fullPath, "appwriteConfig.yml"),
123
- ];
124
- for (const configPath of configPaths) {
125
- if (fs.existsSync(configPath)) {
126
- return configPath;
127
- }
128
- }
129
- }
130
- // Recurse into other directories with increased depth
131
- const result = this.findYamlConfigRecursive(fullPath, depth + 1);
76
+ const result = await this.searchDownward(path.join(dir, entry.name), patterns, maxDepth, currentDepth + 1);
132
77
  if (result)
133
78
  return result;
134
79
  }
135
80
  }
136
81
  }
137
82
  catch (error) {
138
- // Ignore directory access errors
83
+ // Ignore permission errors
139
84
  }
140
85
  return null;
141
86
  }
142
87
  /**
143
- * Finds TypeScript configuration files (appwriteConfig.ts)
88
+ * Finds any configuration file with configurable priority
144
89
  * @param startDir The directory to start searching from
145
- * @returns Path to the TypeScript config file or null if not found
146
- */
147
- findTypeScriptConfig(startDir) {
148
- return this.findTypeScriptConfigRecursive(startDir);
149
- }
150
- /**
151
- * Recursively searches for TypeScript configuration files
152
- * @param dir The directory to search
153
- * @param depth Current search depth
154
- * @returns Path to TypeScript config or null
90
+ * @param preferJson If true, prioritizes appwrite.config.json over YAML (default: false)
91
+ * @returns Path to the configuration file or null if not found
92
+ *
93
+ * Default priority: YAML → JSON → TypeScript
94
+ * With preferJson=true: JSON → YAML → TypeScript
155
95
  */
156
- findTypeScriptConfigRecursive(dir, depth = 0) {
157
- // Limit search depth to prevent infinite recursion
158
- if (depth > 10) {
159
- return null;
96
+ async findConfig(startDir, preferJson = false) {
97
+ // Find repo root to establish boundary
98
+ const repoRoot = await this.findRepoRoot(startDir);
99
+ if (preferJson) {
100
+ // Try JSON first when --appwrite-config flag is used
101
+ const jsonConfig = await this.findProjectConfig(startDir, repoRoot);
102
+ if (jsonConfig)
103
+ return jsonConfig;
104
+ // Try YAML second
105
+ const yamlConfig = await this.findYamlConfig(startDir, repoRoot);
106
+ if (yamlConfig)
107
+ return yamlConfig;
108
+ // Try TypeScript last (lowest priority)
109
+ const tsConfig = await this.findTypeScriptConfig(startDir, repoRoot);
110
+ if (tsConfig)
111
+ return tsConfig;
160
112
  }
161
- if (shouldIgnoreDirectory(path.basename(dir))) {
162
- return null;
163
- }
164
- try {
165
- const entries = fs.readdirSync(dir, { withFileTypes: true });
166
- // First check current directory for appwriteConfig.ts
167
- for (const entry of entries) {
168
- if (entry.isFile() && this.TS_FILENAMES.includes(entry.name)) {
169
- return path.join(dir, entry.name);
170
- }
171
- }
172
- // Then search subdirectories
173
- for (const entry of entries) {
174
- if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
175
- const result = this.findTypeScriptConfigRecursive(path.join(dir, entry.name), depth + 1);
176
- if (result)
177
- return result;
178
- }
179
- }
180
- }
181
- catch (error) {
182
- // Ignore directory access errors
113
+ else {
114
+ // Default priority: YAML → JSON → TypeScript
115
+ const yamlConfig = await this.findYamlConfig(startDir, repoRoot);
116
+ if (yamlConfig)
117
+ return yamlConfig;
118
+ const jsonConfig = await this.findProjectConfig(startDir, repoRoot);
119
+ if (jsonConfig)
120
+ return jsonConfig;
121
+ const tsConfig = await this.findTypeScriptConfig(startDir, repoRoot);
122
+ if (tsConfig)
123
+ return tsConfig;
183
124
  }
184
125
  return null;
185
126
  }
186
127
  /**
187
- * Finds project configuration JSON files (appwrite.json, appwrite.config.json)
188
- * Searches up to 5 levels up the directory tree
128
+ * Finds YAML configuration files
129
+ * Searches UP to repo root, then DOWN from repo root
130
+ * @param startDir The directory to start searching from
131
+ * @param repoRoot The repository root boundary
132
+ * @returns Path to the YAML config file or null if not found
133
+ */
134
+ async findYamlConfig(startDir, repoRoot) {
135
+ const boundary = repoRoot || (await this.findRepoRoot(startDir));
136
+ // Search UP to repo root
137
+ const upwardResult = await findUp(this.YAML_FILENAMES, {
138
+ cwd: startDir,
139
+ stopAt: boundary,
140
+ });
141
+ if (upwardResult)
142
+ return upwardResult;
143
+ // Search DOWN from repo root
144
+ return await this.searchDownward(boundary, this.YAML_FILENAMES);
145
+ }
146
+ /**
147
+ * Finds JSON project configuration files (appwrite.config.json, appwrite.json)
189
148
  * @param startDir The directory to start searching from
149
+ * @param repoRoot The repository root boundary
190
150
  * @returns Path to the JSON config file or null if not found
191
151
  */
192
- findProjectConfig(startDir = process.cwd()) {
193
- let currentDir = startDir;
194
- // Search up to MAX_SEARCH_DEPTH levels up the directory tree
195
- for (let i = 0; i < this.MAX_SEARCH_DEPTH; i++) {
196
- for (const configName of this.JSON_FILENAMES) {
197
- const configPath = path.join(currentDir, configName);
198
- if (fs.existsSync(configPath)) {
199
- return configPath;
200
- }
201
- }
202
- const parentDir = path.dirname(currentDir);
203
- if (parentDir === currentDir) {
204
- break; // Reached filesystem root
205
- }
206
- currentDir = parentDir;
207
- }
208
- return null;
152
+ async findProjectConfig(startDir, repoRoot) {
153
+ const boundary = repoRoot || (await this.findRepoRoot(startDir));
154
+ // Search UP to repo root
155
+ const upwardResult = await findUp(this.JSON_FILENAMES, {
156
+ cwd: startDir,
157
+ stopAt: boundary,
158
+ });
159
+ if (upwardResult)
160
+ return upwardResult;
161
+ // Search DOWN from repo root
162
+ return await this.searchDownward(boundary, this.JSON_FILENAMES);
163
+ }
164
+ /**
165
+ * Finds TypeScript configuration files (appwriteConfig.ts)
166
+ * @param startDir The directory to start searching from
167
+ * @param repoRoot The repository root boundary
168
+ * @returns Path to the TypeScript config file or null if not found
169
+ */
170
+ async findTypeScriptConfig(startDir, repoRoot) {
171
+ const boundary = repoRoot || (await this.findRepoRoot(startDir));
172
+ // Search UP to repo root
173
+ const upwardResult = await findUp(this.TS_FILENAMES, {
174
+ cwd: startDir,
175
+ stopAt: boundary,
176
+ });
177
+ if (upwardResult)
178
+ return upwardResult;
179
+ // Search DOWN from repo root
180
+ return await this.searchDownward(boundary, this.TS_FILENAMES);
209
181
  }
210
182
  /**
211
183
  * Discovers collection YAML files in a collections/ directory
@@ -298,62 +270,36 @@ export class ConfigDiscoveryService {
298
270
  * @param startDir The directory to start searching from
299
271
  * @returns Path to .appwrite directory or null if not found
300
272
  */
301
- findAppwriteDirectory(startDir) {
302
- let currentDir = startDir;
303
- // Search up to MAX_SEARCH_DEPTH levels up the directory tree
304
- for (let i = 0; i < this.MAX_SEARCH_DEPTH; i++) {
305
- const appwriteDir = path.join(currentDir, ".appwrite");
306
- if (fs.existsSync(appwriteDir) && fs.statSync(appwriteDir).isDirectory()) {
307
- return appwriteDir;
308
- }
309
- const parentDir = path.dirname(currentDir);
310
- if (parentDir === currentDir) {
311
- break; // Reached filesystem root
312
- }
313
- currentDir = parentDir;
314
- }
315
- return null;
273
+ async findAppwriteDirectory(startDir) {
274
+ const repoRoot = await this.findRepoRoot(startDir);
275
+ // Search UP to repo root
276
+ const upwardResult = await findUp(".appwrite", {
277
+ cwd: startDir,
278
+ type: "directory",
279
+ stopAt: repoRoot,
280
+ });
281
+ if (upwardResult)
282
+ return upwardResult;
283
+ // Search DOWN from repo root
284
+ return await this.searchDownward(repoRoot, [".appwrite"]);
316
285
  }
317
286
  /**
318
287
  * Finds the functions directory
319
288
  * @param startDir The directory to start searching from
320
289
  * @returns Path to functions directory or null if not found
321
290
  */
322
- findFunctionsDirectory(startDir) {
323
- return this.findFunctionsDirectoryRecursive(startDir);
324
- }
325
- /**
326
- * Recursively searches for the functions directory
327
- * @param dir The directory to search
328
- * @param depth Current search depth
329
- * @returns Path to functions directory or null
330
- */
331
- findFunctionsDirectoryRecursive(dir, depth = 0) {
332
- // Limit search depth to prevent infinite recursion
333
- if (depth > this.MAX_SEARCH_DEPTH) {
334
- return null;
335
- }
336
- if (shouldIgnoreDirectory(path.basename(dir))) {
337
- return null;
338
- }
339
- try {
340
- const files = fs.readdirSync(dir, { withFileTypes: true });
341
- for (const entry of files) {
342
- if (!entry.isDirectory() || shouldIgnoreDirectory(entry.name)) {
343
- continue;
344
- }
345
- if (entry.name === "functions") {
346
- return path.join(dir, entry.name);
347
- }
348
- const result = this.findFunctionsDirectoryRecursive(path.join(dir, entry.name), depth + 1);
349
- if (result)
350
- return result;
351
- }
352
- }
353
- catch (error) {
354
- // Ignore directory access errors
355
- }
356
- return null;
291
+ async findFunctionsDirectory(startDir) {
292
+ const repoRoot = await this.findRepoRoot(startDir);
293
+ // Search UP to repo root
294
+ const upwardResult = await findUp("functions", {
295
+ cwd: startDir,
296
+ type: "directory",
297
+ stopAt: repoRoot,
298
+ });
299
+ if (upwardResult)
300
+ return upwardResult;
301
+ // Search DOWN from repo root
302
+ return await this.searchDownward(repoRoot, ["functions"]);
357
303
  }
358
304
  /**
359
305
  * Gets a summary of all discoverable configuration files
@@ -361,14 +307,16 @@ export class ConfigDiscoveryService {
361
307
  * @param startDir The directory to start searching from
362
308
  * @returns Object containing paths to all discovered config types
363
309
  */
364
- getConfigurationSummary(startDir) {
310
+ async getConfigurationSummary(startDir) {
311
+ const repoRoot = await this.findRepoRoot(startDir);
365
312
  return {
366
- yaml: this.findYamlConfig(startDir),
367
- typescript: this.findTypeScriptConfig(startDir),
368
- json: this.findProjectConfig(startDir),
369
- appwriteDirectory: this.findAppwriteDirectory(startDir),
370
- functionsDirectory: this.findFunctionsDirectory(startDir),
371
- selectedConfig: this.findConfig(startDir),
313
+ yaml: await this.findYamlConfig(startDir, repoRoot),
314
+ typescript: await this.findTypeScriptConfig(startDir, repoRoot),
315
+ json: await this.findProjectConfig(startDir, repoRoot),
316
+ appwriteDirectory: await this.findAppwriteDirectory(startDir),
317
+ functionsDirectory: await this.findFunctionsDirectory(startDir),
318
+ selectedConfig: await this.findConfig(startDir),
319
+ repoRoot,
372
320
  };
373
321
  }
374
322
  }
@@ -244,18 +244,13 @@ export class ConfigLoaderService {
244
244
  if (!projectConfig) {
245
245
  throw new Error(`Failed to load project config from: ${jsonPath}`);
246
246
  }
247
- // Convert project config to AppwriteConfig format
248
- const appwriteConfig = projectConfigToAppwriteConfig(projectConfig);
247
+ // Convert project config to AppwriteConfig format (includes function path normalization)
248
+ const appwriteConfig = projectConfigToAppwriteConfig(projectConfig, jsonPath);
249
249
  // Get collections from project config
250
250
  const collections = getCollectionsFromProject(projectConfig);
251
251
  if (collections.length > 0) {
252
252
  appwriteConfig.collections = collections;
253
253
  }
254
- // Normalize function paths
255
- const configDir = path.dirname(jsonPath);
256
- if (appwriteConfig.functions) {
257
- appwriteConfig.functions = appwriteConfig.functions.map(func => this.normalizeFunctionPath(func, configDir));
258
- }
259
254
  MessageFormatter.success(`Loaded project config from: ${jsonPath}`, {
260
255
  prefix: "Config",
261
256
  });
@@ -288,7 +288,7 @@ export declare const createSessionPreservingYamlConfig: (configPath: string, ses
288
288
  $updatedAt?: string | undefined;
289
289
  error?: string | undefined;
290
290
  xdefault?: string | null | undefined;
291
- encrypted?: boolean | undefined;
291
+ encrypt?: boolean | undefined;
292
292
  } | {
293
293
  key: string;
294
294
  required: boolean;
@@ -506,7 +506,7 @@ export declare const createSessionPreservingYamlConfig: (configPath: string, ses
506
506
  $updatedAt?: string | undefined;
507
507
  error?: string | undefined;
508
508
  xdefault?: string | null | undefined;
509
- encrypted?: boolean | undefined;
509
+ encrypt?: boolean | undefined;
510
510
  } | {
511
511
  key: string;
512
512
  required: boolean;
@@ -2,7 +2,7 @@ import { AppwriteException, Client, Functions, Query, Runtime, } from "node-appw
2
2
  import { join, dirname } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import fs from "node:fs";
5
- import {} from "appwrite-utils";
5
+ import { EventTypeSchema, } from "appwrite-utils";
6
6
  import chalk from "chalk";
7
7
  import { extract as extractTar } from "tar";
8
8
  import { MessageFormatter } from "../shared/messageFormatter.js";
@@ -10,6 +10,7 @@ import { expandTildePath, normalizeFunctionName } from "./pathResolution.js";
10
10
  /**
11
11
  * Validates and filters events array for Appwrite functions
12
12
  * - Filters out empty/invalid strings
13
+ * - Validates against EventTypeSchema
13
14
  * - Limits to 100 items maximum (Appwrite limit)
14
15
  * - Returns empty array if input is invalid
15
16
  */
@@ -17,7 +18,18 @@ const validateEvents = (events) => {
17
18
  if (!events || !Array.isArray(events))
18
19
  return [];
19
20
  return events
20
- .filter(event => event && typeof event === 'string' && event.trim().length > 0)
21
+ .filter(event => {
22
+ if (!event || typeof event !== 'string' || event.trim().length === 0) {
23
+ return false;
24
+ }
25
+ // Validate against EventTypeSchema
26
+ const result = EventTypeSchema.safeParse(event);
27
+ if (!result.success) {
28
+ MessageFormatter.warning(`Invalid event type "${event}" will be filtered out`, { prefix: "Functions" });
29
+ return false;
30
+ }
31
+ return true;
32
+ })
21
33
  .slice(0, 100);
22
34
  };
23
35
  export const listFunctions = async (client, queries, search) => {
package/dist/main.js CHANGED
@@ -217,6 +217,11 @@ const argv = yargs(hideBin(process.argv))
217
217
  .option("config", {
218
218
  type: "string",
219
219
  description: "Path to Appwrite configuration file (appwriteConfig.ts)",
220
+ })
221
+ .option("appwriteConfig", {
222
+ alias: ["appwrite-config", "use-appwrite-config"],
223
+ type: "boolean",
224
+ description: "Prefer loading from appwrite.config.json instead of config.yaml",
220
225
  })
221
226
  .option("it", {
222
227
  alias: ["interactive", "i"],
@@ -557,7 +562,7 @@ async function main() {
557
562
  }
558
563
  // Create controller with session authentication support using singleton
559
564
  const controller = UtilsController.getInstance(process.cwd(), finalDirectConfig);
560
- // Pass session authentication options to the controller
565
+ // Pass session authentication and config options to the controller
561
566
  const initOptions = {};
562
567
  if (argv.useSession || argv.sessionCookie) {
563
568
  initOptions.useSession = true;
@@ -565,6 +570,9 @@ async function main() {
565
570
  initOptions.sessionCookie = argv.sessionCookie;
566
571
  }
567
572
  }
573
+ if (argv.appwriteConfig) {
574
+ initOptions.preferJson = true;
575
+ }
568
576
  await controller.init(initOptions);
569
577
  if (argv.setup) {
570
578
  await setupDirsFiles(false, process.cwd());
@@ -20,7 +20,7 @@ export declare class AppwriteToX {
20
20
  $updatedAt?: string | undefined;
21
21
  error?: string | undefined;
22
22
  xdefault?: string | null | undefined;
23
- encrypted?: boolean | undefined;
23
+ encrypt?: boolean | undefined;
24
24
  } | {
25
25
  key: string;
26
26
  required: boolean;
@@ -21,7 +21,7 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
21
21
  min: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
22
22
  max: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
23
23
  elements: z.ZodOptional<z.ZodArray<z.ZodString>>;
24
- encrypted: z.ZodOptional<z.ZodBoolean>;
24
+ encrypt: z.ZodOptional<z.ZodBoolean>;
25
25
  relatedCollection: z.ZodOptional<z.ZodString>;
26
26
  relationType: z.ZodOptional<z.ZodString>;
27
27
  twoWay: z.ZodOptional<z.ZodBoolean>;
@@ -46,7 +46,7 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
46
46
  type: z.ZodLiteral<"string">;
47
47
  size: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
48
48
  xdefault: z.ZodOptional<z.ZodNullable<z.ZodString>>;
49
- encrypted: z.ZodOptional<z.ZodBoolean>;
49
+ encrypt: z.ZodOptional<z.ZodBoolean>;
50
50
  }, z.core.$strip>, z.ZodObject<{
51
51
  array: z.ZodOptional<z.ZodBoolean>;
52
52
  format: z.ZodOptional<z.ZodString>;
@@ -394,7 +394,7 @@ export declare class DataLoader {
394
394
  $updatedAt?: string | undefined;
395
395
  error?: string | undefined;
396
396
  xdefault?: string | null | undefined;
397
- encrypted?: boolean | undefined;
397
+ encrypt?: boolean | undefined;
398
398
  } | {
399
399
  key: string;
400
400
  required: boolean;
@@ -1,5 +1,5 @@
1
1
  import { Client, Functions, Runtime } from "node-appwrite";
2
- import {} from "appwrite-utils";
2
+ import { EventTypeSchema } from "appwrite-utils";
3
3
  import { join, relative, resolve, basename } from "node:path";
4
4
  import fs from "node:fs";
5
5
  import chalk from "chalk";
@@ -9,6 +9,7 @@ import { MessageFormatter } from "./messageFormatter.js";
9
9
  /**
10
10
  * Validates and filters events array for Appwrite functions
11
11
  * - Filters out empty/invalid strings
12
+ * - Validates against EventTypeSchema
12
13
  * - Limits to 100 items maximum (Appwrite limit)
13
14
  * - Returns empty array if input is invalid
14
15
  */
@@ -16,7 +17,18 @@ const validateEvents = (events) => {
16
17
  if (!events || !Array.isArray(events))
17
18
  return [];
18
19
  return events
19
- .filter(event => event && typeof event === 'string' && event.trim().length > 0)
20
+ .filter(event => {
21
+ if (!event || typeof event !== 'string' || event.trim().length === 0) {
22
+ return false;
23
+ }
24
+ // Validate against EventTypeSchema
25
+ const result = EventTypeSchema.safeParse(event);
26
+ if (!result.success) {
27
+ MessageFormatter.warning(`Invalid event type "${event}" will be filtered out`, { prefix: "Functions" });
28
+ return false;
29
+ }
30
+ return true;
31
+ })
20
32
  .slice(0, 100);
21
33
  };
22
34
  // Concurrency limits
@@ -90,7 +90,7 @@ export declare const getMigrationCollectionSchemas: () => {
90
90
  $updatedAt?: string | undefined;
91
91
  error?: string | undefined;
92
92
  xdefault?: string | null | undefined;
93
- encrypted?: boolean | undefined;
93
+ encrypt?: boolean | undefined;
94
94
  } | {
95
95
  key: string;
96
96
  required: boolean;
@@ -307,7 +307,7 @@ export declare const getMigrationCollectionSchemas: () => {
307
307
  $updatedAt?: string | undefined;
308
308
  error?: string | undefined;
309
309
  xdefault?: string | null | undefined;
310
- encrypted?: boolean | undefined;
310
+ encrypt?: boolean | undefined;
311
311
  } | {
312
312
  key: string;
313
313
  required: boolean;
@@ -473,7 +473,7 @@ export declare const getMigrationCollectionSchemas: () => {
473
473
  $updatedAt?: string | undefined;
474
474
  error?: string | undefined;
475
475
  xdefault?: string | null | undefined;
476
- encrypted?: boolean | undefined;
476
+ encrypt?: boolean | undefined;
477
477
  } | {
478
478
  key: string;
479
479
  required: boolean;
@@ -690,7 +690,7 @@ export declare const getMigrationCollectionSchemas: () => {
690
690
  $updatedAt?: string | undefined;
691
691
  error?: string | undefined;
692
692
  xdefault?: string | null | undefined;
693
- encrypted?: boolean | undefined;
693
+ encrypt?: boolean | undefined;
694
694
  } | {
695
695
  key: string;
696
696
  required: boolean;