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,5 +1,6 @@
|
|
|
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
|
|
|
@@ -16,16 +17,15 @@ export interface DiscoveryResult {
|
|
|
16
17
|
/**
|
|
17
18
|
* Service for discovering Appwrite configuration files and collection/table definitions.
|
|
18
19
|
*
|
|
20
|
+
* Uses find-up for intelligent searching with git repository boundary detection:
|
|
21
|
+
* 1. Finds .git directory to establish repo root boundary
|
|
22
|
+
* 2. Searches UP from current directory to repo root
|
|
23
|
+
* 3. Searches DOWN recursively within repo root
|
|
24
|
+
*
|
|
19
25
|
* Search Priority:
|
|
20
26
|
* 1. YAML configs (.appwrite/config.yaml, .appwrite/config.yml, etc.)
|
|
21
|
-
* 2.
|
|
22
|
-
* 3.
|
|
23
|
-
*
|
|
24
|
-
* Features:
|
|
25
|
-
* - Searches up directory tree (max 5 levels)
|
|
26
|
-
* - Ignores common directories (node_modules, .git, etc.)
|
|
27
|
-
* - Discovers both collections/ and tables/ directories
|
|
28
|
-
* - Recursive subdirectory scanning for .appwrite folders
|
|
27
|
+
* 2. JSON configs (appwrite.config.json, appwrite.json)
|
|
28
|
+
* 3. TypeScript configs (appwriteConfig.ts)
|
|
29
29
|
*/
|
|
30
30
|
export class ConfigDiscoveryService {
|
|
31
31
|
/**
|
|
@@ -40,212 +40,188 @@ export class ConfigDiscoveryService {
|
|
|
40
40
|
"appwrite.yml",
|
|
41
41
|
];
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
* TypeScript configuration file names to search for
|
|
45
|
-
*/
|
|
46
|
-
private readonly TS_FILENAMES = ["appwriteConfig.ts"];
|
|
47
|
-
|
|
48
43
|
/**
|
|
49
44
|
* JSON configuration file names to search for
|
|
50
45
|
*/
|
|
51
|
-
private readonly JSON_FILENAMES = ["appwrite.json", "appwrite.
|
|
46
|
+
private readonly JSON_FILENAMES = ["appwrite.config.json", "appwrite.json"];
|
|
52
47
|
|
|
53
48
|
/**
|
|
54
|
-
*
|
|
49
|
+
* TypeScript configuration file names to search for
|
|
55
50
|
*/
|
|
56
|
-
private readonly
|
|
51
|
+
private readonly TS_FILENAMES = ["appwriteConfig.ts"];
|
|
57
52
|
|
|
58
53
|
/**
|
|
59
|
-
* Finds
|
|
54
|
+
* Finds the git repository root directory
|
|
60
55
|
* @param startDir The directory to start searching from
|
|
61
|
-
* @returns Path to the
|
|
56
|
+
* @returns Path to the repository root, or startDir if no .git found
|
|
62
57
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Try TypeScript second
|
|
71
|
-
const tsConfig = this.findTypeScriptConfig(startDir);
|
|
72
|
-
if (tsConfig) {
|
|
73
|
-
return tsConfig;
|
|
74
|
-
}
|
|
58
|
+
private async findRepoRoot(startDir: string): Promise<string> {
|
|
59
|
+
const gitDir = await findUp(".git", {
|
|
60
|
+
cwd: startDir,
|
|
61
|
+
type: "directory",
|
|
62
|
+
});
|
|
75
63
|
|
|
76
|
-
|
|
77
|
-
const jsonConfig = this.findProjectConfig(startDir);
|
|
78
|
-
if (jsonConfig) {
|
|
79
|
-
return jsonConfig;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return null;
|
|
64
|
+
return gitDir ? path.dirname(gitDir) : startDir;
|
|
83
65
|
}
|
|
84
66
|
|
|
85
67
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* @param
|
|
89
|
-
* @
|
|
68
|
+
* Recursively searches downward for files matching patterns
|
|
69
|
+
* @param dir Directory to search in
|
|
70
|
+
* @param patterns File patterns to match
|
|
71
|
+
* @param maxDepth Maximum depth to search
|
|
72
|
+
* @param currentDepth Current recursion depth
|
|
73
|
+
* @returns First matching file path or null
|
|
90
74
|
*/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
75
|
+
private async searchDownward(
|
|
76
|
+
dir: string,
|
|
77
|
+
patterns: string[],
|
|
78
|
+
maxDepth: number = 5,
|
|
79
|
+
currentDepth: number = 0
|
|
80
|
+
): Promise<string | null> {
|
|
81
|
+
if (currentDepth > maxDepth) return null;
|
|
82
|
+
if (shouldIgnoreDirectory(path.basename(dir))) return null;
|
|
99
83
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (yamlConfigInSubdirs) {
|
|
103
|
-
return yamlConfigInSubdirs;
|
|
104
|
-
}
|
|
84
|
+
try {
|
|
85
|
+
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
105
86
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (fs.existsSync(configPath)) {
|
|
112
|
-
return configPath;
|
|
87
|
+
// Check current directory for matches
|
|
88
|
+
for (const pattern of patterns) {
|
|
89
|
+
const fullPath = path.join(dir, pattern);
|
|
90
|
+
if (fs.existsSync(fullPath)) {
|
|
91
|
+
return fullPath;
|
|
113
92
|
}
|
|
114
93
|
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Recursively searches for YAML configs in .appwrite subdirectories
|
|
122
|
-
* @param dir The directory to search
|
|
123
|
-
* @param depth Current search depth
|
|
124
|
-
* @returns Path to YAML config or null
|
|
125
|
-
*/
|
|
126
|
-
private findYamlConfigRecursive(dir: string, depth: number = 0): string | null {
|
|
127
|
-
// Limit search depth to prevent infinite recursion
|
|
128
|
-
if (depth > this.MAX_SEARCH_DEPTH) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (shouldIgnoreDirectory(path.basename(dir))) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
try {
|
|
137
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
138
94
|
|
|
95
|
+
// Recurse into subdirectories
|
|
139
96
|
for (const entry of entries) {
|
|
140
97
|
if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
path.join(fullPath, "config.yml"),
|
|
148
|
-
path.join(fullPath, "appwriteConfig.yaml"),
|
|
149
|
-
path.join(fullPath, "appwriteConfig.yml"),
|
|
150
|
-
];
|
|
151
|
-
|
|
152
|
-
for (const configPath of configPaths) {
|
|
153
|
-
if (fs.existsSync(configPath)) {
|
|
154
|
-
return configPath;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Recurse into other directories with increased depth
|
|
160
|
-
const result = this.findYamlConfigRecursive(fullPath, depth + 1);
|
|
98
|
+
const result = await this.searchDownward(
|
|
99
|
+
path.join(dir, entry.name),
|
|
100
|
+
patterns,
|
|
101
|
+
maxDepth,
|
|
102
|
+
currentDepth + 1
|
|
103
|
+
);
|
|
161
104
|
if (result) return result;
|
|
162
105
|
}
|
|
163
106
|
}
|
|
164
107
|
} catch (error) {
|
|
165
|
-
// Ignore
|
|
108
|
+
// Ignore permission errors
|
|
166
109
|
}
|
|
167
110
|
|
|
168
111
|
return null;
|
|
169
112
|
}
|
|
170
113
|
|
|
171
114
|
/**
|
|
172
|
-
* Finds
|
|
115
|
+
* Finds any configuration file with configurable priority
|
|
173
116
|
* @param startDir The directory to start searching from
|
|
174
|
-
* @
|
|
117
|
+
* @param preferJson If true, prioritizes appwrite.config.json over YAML (default: false)
|
|
118
|
+
* @returns Path to the configuration file or null if not found
|
|
119
|
+
*
|
|
120
|
+
* Default priority: YAML → JSON → TypeScript
|
|
121
|
+
* With preferJson=true: JSON → YAML → TypeScript
|
|
175
122
|
*/
|
|
176
|
-
public
|
|
177
|
-
|
|
123
|
+
public async findConfig(startDir: string, preferJson: boolean = false): Promise<string | null> {
|
|
124
|
+
// Find repo root to establish boundary
|
|
125
|
+
const repoRoot = await this.findRepoRoot(startDir);
|
|
126
|
+
|
|
127
|
+
if (preferJson) {
|
|
128
|
+
// Try JSON first when --appwrite-config flag is used
|
|
129
|
+
const jsonConfig = await this.findProjectConfig(startDir, repoRoot);
|
|
130
|
+
if (jsonConfig) return jsonConfig;
|
|
131
|
+
|
|
132
|
+
// Try YAML second
|
|
133
|
+
const yamlConfig = await this.findYamlConfig(startDir, repoRoot);
|
|
134
|
+
if (yamlConfig) return yamlConfig;
|
|
135
|
+
|
|
136
|
+
// Try TypeScript last (lowest priority)
|
|
137
|
+
const tsConfig = await this.findTypeScriptConfig(startDir, repoRoot);
|
|
138
|
+
if (tsConfig) return tsConfig;
|
|
139
|
+
} else {
|
|
140
|
+
// Default priority: YAML → JSON → TypeScript
|
|
141
|
+
const yamlConfig = await this.findYamlConfig(startDir, repoRoot);
|
|
142
|
+
if (yamlConfig) return yamlConfig;
|
|
143
|
+
|
|
144
|
+
const jsonConfig = await this.findProjectConfig(startDir, repoRoot);
|
|
145
|
+
if (jsonConfig) return jsonConfig;
|
|
146
|
+
|
|
147
|
+
const tsConfig = await this.findTypeScriptConfig(startDir, repoRoot);
|
|
148
|
+
if (tsConfig) return tsConfig;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return null;
|
|
178
152
|
}
|
|
179
153
|
|
|
180
154
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* @param
|
|
184
|
-
* @
|
|
155
|
+
* Finds YAML configuration files
|
|
156
|
+
* Searches UP to repo root, then DOWN from repo root
|
|
157
|
+
* @param startDir The directory to start searching from
|
|
158
|
+
* @param repoRoot The repository root boundary
|
|
159
|
+
* @returns Path to the YAML config file or null if not found
|
|
185
160
|
*/
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
return path.join(dir, entry.name);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Then search subdirectories
|
|
207
|
-
for (const entry of entries) {
|
|
208
|
-
if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
|
|
209
|
-
const result = this.findTypeScriptConfigRecursive(
|
|
210
|
-
path.join(dir, entry.name),
|
|
211
|
-
depth + 1
|
|
212
|
-
);
|
|
213
|
-
if (result) return result;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
} catch (error) {
|
|
217
|
-
// Ignore directory access errors
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return null;
|
|
161
|
+
public async findYamlConfig(
|
|
162
|
+
startDir: string,
|
|
163
|
+
repoRoot?: string
|
|
164
|
+
): Promise<string | null> {
|
|
165
|
+
const boundary = repoRoot || (await this.findRepoRoot(startDir));
|
|
166
|
+
|
|
167
|
+
// Search UP to repo root
|
|
168
|
+
const upwardResult = await findUp(this.YAML_FILENAMES, {
|
|
169
|
+
cwd: startDir,
|
|
170
|
+
stopAt: boundary,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (upwardResult) return upwardResult;
|
|
174
|
+
|
|
175
|
+
// Search DOWN from repo root
|
|
176
|
+
return await this.searchDownward(boundary, this.YAML_FILENAMES);
|
|
221
177
|
}
|
|
222
178
|
|
|
223
179
|
/**
|
|
224
|
-
* Finds project configuration
|
|
225
|
-
* Searches up to 5 levels up the directory tree
|
|
180
|
+
* Finds JSON project configuration files (appwrite.config.json, appwrite.json)
|
|
226
181
|
* @param startDir The directory to start searching from
|
|
182
|
+
* @param repoRoot The repository root boundary
|
|
227
183
|
* @returns Path to the JSON config file or null if not found
|
|
228
184
|
*/
|
|
229
|
-
public findProjectConfig(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
185
|
+
public async findProjectConfig(
|
|
186
|
+
startDir: string,
|
|
187
|
+
repoRoot?: string
|
|
188
|
+
): Promise<string | null> {
|
|
189
|
+
const boundary = repoRoot || (await this.findRepoRoot(startDir));
|
|
190
|
+
|
|
191
|
+
// Search UP to repo root
|
|
192
|
+
const upwardResult = await findUp(this.JSON_FILENAMES, {
|
|
193
|
+
cwd: startDir,
|
|
194
|
+
stopAt: boundary,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
if (upwardResult) return upwardResult;
|
|
198
|
+
|
|
199
|
+
// Search DOWN from repo root
|
|
200
|
+
return await this.searchDownward(boundary, this.JSON_FILENAMES);
|
|
201
|
+
}
|
|
247
202
|
|
|
248
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Finds TypeScript configuration files (appwriteConfig.ts)
|
|
205
|
+
* @param startDir The directory to start searching from
|
|
206
|
+
* @param repoRoot The repository root boundary
|
|
207
|
+
* @returns Path to the TypeScript config file or null if not found
|
|
208
|
+
*/
|
|
209
|
+
public async findTypeScriptConfig(
|
|
210
|
+
startDir: string,
|
|
211
|
+
repoRoot?: string
|
|
212
|
+
): Promise<string | null> {
|
|
213
|
+
const boundary = repoRoot || (await this.findRepoRoot(startDir));
|
|
214
|
+
|
|
215
|
+
// Search UP to repo root
|
|
216
|
+
const upwardResult = await findUp(this.TS_FILENAMES, {
|
|
217
|
+
cwd: startDir,
|
|
218
|
+
stopAt: boundary,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
if (upwardResult) return upwardResult;
|
|
222
|
+
|
|
223
|
+
// Search DOWN from repo root
|
|
224
|
+
return await this.searchDownward(boundary, this.TS_FILENAMES);
|
|
249
225
|
}
|
|
250
226
|
|
|
251
227
|
/**
|
|
@@ -367,24 +343,20 @@ export class ConfigDiscoveryService {
|
|
|
367
343
|
* @param startDir The directory to start searching from
|
|
368
344
|
* @returns Path to .appwrite directory or null if not found
|
|
369
345
|
*/
|
|
370
|
-
public findAppwriteDirectory(startDir: string): string | null {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
// Search up to MAX_SEARCH_DEPTH levels up the directory tree
|
|
374
|
-
for (let i = 0; i < this.MAX_SEARCH_DEPTH; i++) {
|
|
375
|
-
const appwriteDir = path.join(currentDir, ".appwrite");
|
|
376
|
-
if (fs.existsSync(appwriteDir) && fs.statSync(appwriteDir).isDirectory()) {
|
|
377
|
-
return appwriteDir;
|
|
378
|
-
}
|
|
346
|
+
public async findAppwriteDirectory(startDir: string): Promise<string | null> {
|
|
347
|
+
const repoRoot = await this.findRepoRoot(startDir);
|
|
379
348
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
}
|
|
349
|
+
// Search UP to repo root
|
|
350
|
+
const upwardResult = await findUp(".appwrite", {
|
|
351
|
+
cwd: startDir,
|
|
352
|
+
type: "directory",
|
|
353
|
+
stopAt: repoRoot,
|
|
354
|
+
});
|
|
386
355
|
|
|
387
|
-
return
|
|
356
|
+
if (upwardResult) return upwardResult;
|
|
357
|
+
|
|
358
|
+
// Search DOWN from repo root
|
|
359
|
+
return await this.searchDownward(repoRoot, [".appwrite"]);
|
|
388
360
|
}
|
|
389
361
|
|
|
390
362
|
/**
|
|
@@ -392,49 +364,20 @@ export class ConfigDiscoveryService {
|
|
|
392
364
|
* @param startDir The directory to start searching from
|
|
393
365
|
* @returns Path to functions directory or null if not found
|
|
394
366
|
*/
|
|
395
|
-
public findFunctionsDirectory(startDir: string): string | null {
|
|
396
|
-
|
|
397
|
-
}
|
|
367
|
+
public async findFunctionsDirectory(startDir: string): Promise<string | null> {
|
|
368
|
+
const repoRoot = await this.findRepoRoot(startDir);
|
|
398
369
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
private findFunctionsDirectoryRecursive(dir: string, depth: number = 0): string | null {
|
|
406
|
-
// Limit search depth to prevent infinite recursion
|
|
407
|
-
if (depth > this.MAX_SEARCH_DEPTH) {
|
|
408
|
-
return null;
|
|
409
|
-
}
|
|
370
|
+
// Search UP to repo root
|
|
371
|
+
const upwardResult = await findUp("functions", {
|
|
372
|
+
cwd: startDir,
|
|
373
|
+
type: "directory",
|
|
374
|
+
stopAt: repoRoot,
|
|
375
|
+
});
|
|
410
376
|
|
|
411
|
-
if (
|
|
412
|
-
return null;
|
|
413
|
-
}
|
|
377
|
+
if (upwardResult) return upwardResult;
|
|
414
378
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
for (const entry of files) {
|
|
419
|
-
if (!entry.isDirectory() || shouldIgnoreDirectory(entry.name)) {
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
if (entry.name === "functions") {
|
|
424
|
-
return path.join(dir, entry.name);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const result = this.findFunctionsDirectoryRecursive(
|
|
428
|
-
path.join(dir, entry.name),
|
|
429
|
-
depth + 1
|
|
430
|
-
);
|
|
431
|
-
if (result) return result;
|
|
432
|
-
}
|
|
433
|
-
} catch (error) {
|
|
434
|
-
// Ignore directory access errors
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return null;
|
|
379
|
+
// Search DOWN from repo root
|
|
380
|
+
return await this.searchDownward(repoRoot, ["functions"]);
|
|
438
381
|
}
|
|
439
382
|
|
|
440
383
|
/**
|
|
@@ -443,21 +386,25 @@ export class ConfigDiscoveryService {
|
|
|
443
386
|
* @param startDir The directory to start searching from
|
|
444
387
|
* @returns Object containing paths to all discovered config types
|
|
445
388
|
*/
|
|
446
|
-
public getConfigurationSummary(startDir: string): {
|
|
389
|
+
public async getConfigurationSummary(startDir: string): Promise<{
|
|
447
390
|
yaml: string | null;
|
|
448
391
|
typescript: string | null;
|
|
449
392
|
json: string | null;
|
|
450
393
|
appwriteDirectory: string | null;
|
|
451
394
|
functionsDirectory: string | null;
|
|
452
395
|
selectedConfig: string | null;
|
|
453
|
-
|
|
396
|
+
repoRoot: string;
|
|
397
|
+
}> {
|
|
398
|
+
const repoRoot = await this.findRepoRoot(startDir);
|
|
399
|
+
|
|
454
400
|
return {
|
|
455
|
-
yaml: this.findYamlConfig(startDir),
|
|
456
|
-
typescript: this.findTypeScriptConfig(startDir),
|
|
457
|
-
json: this.findProjectConfig(startDir),
|
|
458
|
-
appwriteDirectory: this.findAppwriteDirectory(startDir),
|
|
459
|
-
functionsDirectory: this.findFunctionsDirectory(startDir),
|
|
460
|
-
selectedConfig: this.findConfig(startDir),
|
|
401
|
+
yaml: await this.findYamlConfig(startDir, repoRoot),
|
|
402
|
+
typescript: await this.findTypeScriptConfig(startDir, repoRoot),
|
|
403
|
+
json: await this.findProjectConfig(startDir, repoRoot),
|
|
404
|
+
appwriteDirectory: await this.findAppwriteDirectory(startDir),
|
|
405
|
+
functionsDirectory: await this.findFunctionsDirectory(startDir),
|
|
406
|
+
selectedConfig: await this.findConfig(startDir),
|
|
407
|
+
repoRoot,
|
|
461
408
|
};
|
|
462
409
|
}
|
|
463
410
|
}
|
|
@@ -336,8 +336,8 @@ export class ConfigLoaderService {
|
|
|
336
336
|
throw new Error(`Failed to load project config from: ${jsonPath}`);
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
// Convert project config to AppwriteConfig format
|
|
340
|
-
const appwriteConfig = projectConfigToAppwriteConfig(projectConfig);
|
|
339
|
+
// Convert project config to AppwriteConfig format (includes function path normalization)
|
|
340
|
+
const appwriteConfig = projectConfigToAppwriteConfig(projectConfig, jsonPath);
|
|
341
341
|
|
|
342
342
|
// Get collections from project config
|
|
343
343
|
const collections = getCollectionsFromProject(projectConfig);
|
|
@@ -345,14 +345,6 @@ export class ConfigLoaderService {
|
|
|
345
345
|
appwriteConfig.collections = collections;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
// Normalize function paths
|
|
349
|
-
const configDir = path.dirname(jsonPath);
|
|
350
|
-
if (appwriteConfig.functions) {
|
|
351
|
-
appwriteConfig.functions = appwriteConfig.functions.map(func =>
|
|
352
|
-
this.normalizeFunctionPath(func, configDir)
|
|
353
|
-
);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
348
|
MessageFormatter.success(`Loaded project config from: ${jsonPath}`, {
|
|
357
349
|
prefix: "Config",
|
|
358
350
|
});
|
package/src/functions/methods.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
type FunctionScope,
|
|
14
14
|
type Specification,
|
|
15
15
|
type Runtime as AppwriteUtilsRuntime,
|
|
16
|
+
EventTypeSchema,
|
|
16
17
|
} from "appwrite-utils";
|
|
17
18
|
import chalk from "chalk";
|
|
18
19
|
import { extract as extractTar } from "tar";
|
|
@@ -22,14 +23,26 @@ import { expandTildePath, normalizeFunctionName } from "./pathResolution.js";
|
|
|
22
23
|
/**
|
|
23
24
|
* Validates and filters events array for Appwrite functions
|
|
24
25
|
* - Filters out empty/invalid strings
|
|
26
|
+
* - Validates against EventTypeSchema
|
|
25
27
|
* - Limits to 100 items maximum (Appwrite limit)
|
|
26
28
|
* - Returns empty array if input is invalid
|
|
27
29
|
*/
|
|
28
30
|
const validateEvents = (events?: string[]): string[] => {
|
|
29
31
|
if (!events || !Array.isArray(events)) return [];
|
|
30
|
-
|
|
32
|
+
|
|
31
33
|
return events
|
|
32
|
-
.filter(event =>
|
|
34
|
+
.filter(event => {
|
|
35
|
+
if (!event || typeof event !== 'string' || event.trim().length === 0) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// Validate against EventTypeSchema
|
|
39
|
+
const result = EventTypeSchema.safeParse(event);
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
MessageFormatter.warning(`Invalid event type "${event}" will be filtered out`, { prefix: "Functions" });
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
})
|
|
33
46
|
.slice(0, 100);
|
|
34
47
|
};
|
|
35
48
|
|