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.
- package/dist/adapters/DatabaseAdapter.d.ts +9 -0
- package/dist/adapters/LegacyAdapter.js +1 -1
- package/dist/adapters/TablesDBAdapter.js +29 -4
- package/dist/cli/commands/databaseCommands.d.ts +1 -0
- package/dist/cli/commands/databaseCommands.js +90 -0
- package/dist/config/ConfigManager.d.ts +5 -0
- package/dist/config/ConfigManager.js +1 -1
- package/dist/config/services/ConfigDiscoveryService.d.ts +43 -47
- package/dist/config/services/ConfigDiscoveryService.js +155 -207
- package/dist/config/services/ConfigLoaderService.js +2 -7
- package/dist/config/yamlConfig.d.ts +2 -2
- package/dist/functions/methods.js +14 -2
- package/dist/main.js +9 -1
- package/dist/migrations/appwriteToX.d.ts +1 -1
- package/dist/migrations/dataLoader.d.ts +3 -3
- package/dist/shared/functionManager.js +14 -2
- package/dist/storage/schemas.d.ts +4 -4
- package/dist/utils/projectConfig.d.ts +4 -1
- package/dist/utils/projectConfig.js +41 -6
- package/dist/utilsController.d.ts +1 -0
- package/dist/utilsController.js +2 -1
- package/package.json +2 -1
- package/src/adapters/DatabaseAdapter.ts +12 -0
- package/src/adapters/LegacyAdapter.ts +28 -28
- package/src/adapters/TablesDBAdapter.ts +46 -4
- package/src/cli/commands/databaseCommands.ts +141 -11
- package/src/config/ConfigManager.ts +10 -1
- package/src/config/services/ConfigDiscoveryService.ts +180 -233
- package/src/config/services/ConfigLoaderService.ts +2 -10
- package/src/functions/methods.ts +15 -2
- package/src/main.ts +213 -204
- package/src/shared/functionManager.ts +15 -3
- package/src/utils/projectConfig.ts +57 -16
- 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.
|
|
11
|
-
* 3.
|
|
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.
|
|
34
|
+
JSON_FILENAMES = ["appwrite.config.json", "appwrite.json"];
|
|
39
35
|
/**
|
|
40
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
42
|
+
* @returns Path to the repository root, or startDir if no .git found
|
|
71
43
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
|
99
|
-
* @param dir
|
|
100
|
-
* @param
|
|
101
|
-
* @
|
|
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
|
-
|
|
104
|
-
|
|
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.
|
|
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
|
|
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
|
|
83
|
+
// Ignore permission errors
|
|
139
84
|
}
|
|
140
85
|
return null;
|
|
141
86
|
}
|
|
142
87
|
/**
|
|
143
|
-
* Finds
|
|
88
|
+
* Finds any configuration file with configurable priority
|
|
144
89
|
* @param startDir The directory to start searching from
|
|
145
|
-
* @
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
|
188
|
-
* Searches
|
|
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
|
|
193
|
-
|
|
194
|
-
// Search
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
303
|
-
// Search
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
//
|
|
333
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =>
|
|
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());
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
693
|
+
encrypt?: boolean | undefined;
|
|
694
694
|
} | {
|
|
695
695
|
key: string;
|
|
696
696
|
required: boolean;
|