appwrite-utils-cli 1.0.5 → 1.0.7
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/README.md +96 -0
- package/dist/config/yamlConfig.js +0 -9
- package/dist/interactiveCLI.d.ts +1 -0
- package/dist/interactiveCLI.js +83 -17
- package/dist/main.js +43 -0
- package/dist/utils/constantsGenerator.d.ts +19 -0
- package/dist/utils/constantsGenerator.js +309 -0
- package/dist/utils/loadConfigs.js +5 -5
- package/package.json +1 -1
- package/src/config/yamlConfig.ts +0 -9
- package/src/interactiveCLI.ts +90 -17
- package/src/main.ts +53 -0
- package/src/utils/constantsGenerator.ts +352 -0
- package/src/utils/loadConfigs.ts +6 -5
@@ -0,0 +1,309 @@
|
|
1
|
+
import fs from "fs/promises";
|
2
|
+
import path from "path";
|
3
|
+
import {} from "appwrite-utils";
|
4
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
5
|
+
export class ConstantsGenerator {
|
6
|
+
config;
|
7
|
+
constants;
|
8
|
+
constructor(config) {
|
9
|
+
this.config = config;
|
10
|
+
this.constants = this.extractConstants();
|
11
|
+
}
|
12
|
+
extractConstants() {
|
13
|
+
const constants = {
|
14
|
+
databases: {},
|
15
|
+
collections: {},
|
16
|
+
buckets: {},
|
17
|
+
functions: {}
|
18
|
+
};
|
19
|
+
// Extract database IDs
|
20
|
+
this.config.databases?.forEach(db => {
|
21
|
+
if (db.$id) {
|
22
|
+
const key = this.toConstantName(db.name || db.$id);
|
23
|
+
constants.databases[key] = db.$id;
|
24
|
+
}
|
25
|
+
});
|
26
|
+
// Extract collection IDs
|
27
|
+
this.config.collections?.forEach(collection => {
|
28
|
+
if (collection.$id) {
|
29
|
+
const key = this.toConstantName(collection.name || collection.$id);
|
30
|
+
constants.collections[key] = collection.$id;
|
31
|
+
}
|
32
|
+
});
|
33
|
+
// Extract bucket IDs
|
34
|
+
this.config.buckets?.forEach(bucket => {
|
35
|
+
if (bucket.$id) {
|
36
|
+
const key = this.toConstantName(bucket.name || bucket.$id);
|
37
|
+
constants.buckets[key] = bucket.$id;
|
38
|
+
}
|
39
|
+
});
|
40
|
+
// Extract function IDs
|
41
|
+
this.config.functions?.forEach(func => {
|
42
|
+
if (func.$id) {
|
43
|
+
const key = this.toConstantName(func.name || func.$id);
|
44
|
+
constants.functions[key] = func.$id;
|
45
|
+
}
|
46
|
+
});
|
47
|
+
return constants;
|
48
|
+
}
|
49
|
+
toConstantName(name) {
|
50
|
+
return name
|
51
|
+
.replace(/[^a-zA-Z0-9]/g, '_')
|
52
|
+
.replace(/_+/g, '_')
|
53
|
+
.replace(/^_|_$/g, '')
|
54
|
+
.toUpperCase();
|
55
|
+
}
|
56
|
+
toCamelCase(name) {
|
57
|
+
return name
|
58
|
+
.toLowerCase()
|
59
|
+
.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
60
|
+
}
|
61
|
+
toSnakeCase(name) {
|
62
|
+
return name.toLowerCase();
|
63
|
+
}
|
64
|
+
generateTypeScript() {
|
65
|
+
const { databases, collections, buckets, functions } = this.constants;
|
66
|
+
return `// Auto-generated Appwrite constants
|
67
|
+
// Generated on ${new Date().toISOString()}
|
68
|
+
|
69
|
+
export const DATABASE_IDS = {
|
70
|
+
${Object.entries(databases).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
71
|
+
} as const;
|
72
|
+
|
73
|
+
export const COLLECTION_IDS = {
|
74
|
+
${Object.entries(collections).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
75
|
+
} as const;
|
76
|
+
|
77
|
+
export const BUCKET_IDS = {
|
78
|
+
${Object.entries(buckets).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
79
|
+
} as const;
|
80
|
+
|
81
|
+
export const FUNCTION_IDS = {
|
82
|
+
${Object.entries(functions).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
83
|
+
} as const;
|
84
|
+
|
85
|
+
// Type helpers
|
86
|
+
export type DatabaseId = typeof DATABASE_IDS[keyof typeof DATABASE_IDS];
|
87
|
+
export type CollectionId = typeof COLLECTION_IDS[keyof typeof COLLECTION_IDS];
|
88
|
+
export type BucketId = typeof BUCKET_IDS[keyof typeof BUCKET_IDS];
|
89
|
+
export type FunctionId = typeof FUNCTION_IDS[keyof typeof FUNCTION_IDS];
|
90
|
+
|
91
|
+
// Helper objects for runtime use
|
92
|
+
export const ALL_DATABASE_IDS = Object.values(DATABASE_IDS);
|
93
|
+
export const ALL_COLLECTION_IDS = Object.values(COLLECTION_IDS);
|
94
|
+
export const ALL_BUCKET_IDS = Object.values(BUCKET_IDS);
|
95
|
+
export const ALL_FUNCTION_IDS = Object.values(FUNCTION_IDS);
|
96
|
+
`;
|
97
|
+
}
|
98
|
+
generateJavaScript() {
|
99
|
+
const { databases, collections, buckets, functions } = this.constants;
|
100
|
+
return `// Auto-generated Appwrite constants
|
101
|
+
// Generated on ${new Date().toISOString()}
|
102
|
+
|
103
|
+
export const DATABASE_IDS = {
|
104
|
+
${Object.entries(databases).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
105
|
+
};
|
106
|
+
|
107
|
+
export const COLLECTION_IDS = {
|
108
|
+
${Object.entries(collections).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
109
|
+
};
|
110
|
+
|
111
|
+
export const BUCKET_IDS = {
|
112
|
+
${Object.entries(buckets).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
113
|
+
};
|
114
|
+
|
115
|
+
export const FUNCTION_IDS = {
|
116
|
+
${Object.entries(functions).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
|
117
|
+
};
|
118
|
+
|
119
|
+
// Helper arrays for runtime use
|
120
|
+
export const ALL_DATABASE_IDS = Object.values(DATABASE_IDS);
|
121
|
+
export const ALL_COLLECTION_IDS = Object.values(COLLECTION_IDS);
|
122
|
+
export const ALL_BUCKET_IDS = Object.values(BUCKET_IDS);
|
123
|
+
export const ALL_FUNCTION_IDS = Object.values(FUNCTION_IDS);
|
124
|
+
`;
|
125
|
+
}
|
126
|
+
generatePython() {
|
127
|
+
const { databases, collections, buckets, functions } = this.constants;
|
128
|
+
return `# Auto-generated Appwrite constants
|
129
|
+
# Generated on ${new Date().toISOString()}
|
130
|
+
|
131
|
+
class DatabaseIds:
|
132
|
+
"""Database ID constants"""
|
133
|
+
${Object.entries(databases).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
|
134
|
+
|
135
|
+
class CollectionIds:
|
136
|
+
"""Collection ID constants"""
|
137
|
+
${Object.entries(collections).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
|
138
|
+
|
139
|
+
class BucketIds:
|
140
|
+
"""Bucket ID constants"""
|
141
|
+
${Object.entries(buckets).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
|
142
|
+
|
143
|
+
class FunctionIds:
|
144
|
+
"""Function ID constants"""
|
145
|
+
${Object.entries(functions).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
|
146
|
+
|
147
|
+
# Helper dictionaries for runtime use
|
148
|
+
DATABASE_ID_MAP = {
|
149
|
+
${Object.entries(databases).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
|
150
|
+
}
|
151
|
+
|
152
|
+
COLLECTION_ID_MAP = {
|
153
|
+
${Object.entries(collections).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
|
154
|
+
}
|
155
|
+
|
156
|
+
BUCKET_ID_MAP = {
|
157
|
+
${Object.entries(buckets).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
|
158
|
+
}
|
159
|
+
|
160
|
+
FUNCTION_ID_MAP = {
|
161
|
+
${Object.entries(functions).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
|
162
|
+
}
|
163
|
+
`;
|
164
|
+
}
|
165
|
+
generatePHP() {
|
166
|
+
const { databases, collections, buckets, functions } = this.constants;
|
167
|
+
return `<?php
|
168
|
+
// Auto-generated Appwrite constants
|
169
|
+
// Generated on ${new Date().toISOString()}
|
170
|
+
|
171
|
+
class AppwriteConstants {
|
172
|
+
|
173
|
+
const DATABASE_IDS = [
|
174
|
+
${Object.entries(databases).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
|
175
|
+
];
|
176
|
+
|
177
|
+
const COLLECTION_IDS = [
|
178
|
+
${Object.entries(collections).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
|
179
|
+
];
|
180
|
+
|
181
|
+
const BUCKET_IDS = [
|
182
|
+
${Object.entries(buckets).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
|
183
|
+
];
|
184
|
+
|
185
|
+
const FUNCTION_IDS = [
|
186
|
+
${Object.entries(functions).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
|
187
|
+
];
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Get all database IDs as array
|
191
|
+
*/
|
192
|
+
public static function getAllDatabaseIds(): array {
|
193
|
+
return array_values(self::DATABASE_IDS);
|
194
|
+
}
|
195
|
+
|
196
|
+
/**
|
197
|
+
* Get all collection IDs as array
|
198
|
+
*/
|
199
|
+
public static function getAllCollectionIds(): array {
|
200
|
+
return array_values(self::COLLECTION_IDS);
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* Get all bucket IDs as array
|
205
|
+
*/
|
206
|
+
public static function getAllBucketIds(): array {
|
207
|
+
return array_values(self::BUCKET_IDS);
|
208
|
+
}
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Get all function IDs as array
|
212
|
+
*/
|
213
|
+
public static function getAllFunctionIds(): array {
|
214
|
+
return array_values(self::FUNCTION_IDS);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
`;
|
218
|
+
}
|
219
|
+
generateDart() {
|
220
|
+
const { databases, collections, buckets, functions } = this.constants;
|
221
|
+
return `// Auto-generated Appwrite constants
|
222
|
+
// Generated on ${new Date().toISOString()}
|
223
|
+
|
224
|
+
class AppwriteConstants {
|
225
|
+
|
226
|
+
static const Map<String, String> databaseIds = {
|
227
|
+
${Object.entries(databases).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
|
228
|
+
};
|
229
|
+
|
230
|
+
static const Map<String, String> collectionIds = {
|
231
|
+
${Object.entries(collections).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
|
232
|
+
};
|
233
|
+
|
234
|
+
static const Map<String, String> bucketIds = {
|
235
|
+
${Object.entries(buckets).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
|
236
|
+
};
|
237
|
+
|
238
|
+
static const Map<String, String> functionIds = {
|
239
|
+
${Object.entries(functions).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
|
240
|
+
};
|
241
|
+
|
242
|
+
// Helper getters for individual IDs
|
243
|
+
${Object.entries(databases).map(([key, value]) => ` static String get ${this.toCamelCase(key)}DatabaseId => '${value}';`).join('\n')}
|
244
|
+
|
245
|
+
${Object.entries(collections).map(([key, value]) => ` static String get ${this.toCamelCase(key)}CollectionId => '${value}';`).join('\n')}
|
246
|
+
|
247
|
+
${Object.entries(buckets).map(([key, value]) => ` static String get ${this.toCamelCase(key)}BucketId => '${value}';`).join('\n')}
|
248
|
+
|
249
|
+
${Object.entries(functions).map(([key, value]) => ` static String get ${this.toCamelCase(key)}FunctionId => '${value}';`).join('\n')}
|
250
|
+
}
|
251
|
+
`;
|
252
|
+
}
|
253
|
+
generateJSON() {
|
254
|
+
return JSON.stringify({
|
255
|
+
meta: {
|
256
|
+
generated: new Date().toISOString(),
|
257
|
+
generator: "appwrite-utils-cli"
|
258
|
+
},
|
259
|
+
databases: this.constants.databases,
|
260
|
+
collections: this.constants.collections,
|
261
|
+
buckets: this.constants.buckets,
|
262
|
+
functions: this.constants.functions
|
263
|
+
}, null, 2);
|
264
|
+
}
|
265
|
+
generateEnv() {
|
266
|
+
const { databases, collections, buckets, functions } = this.constants;
|
267
|
+
const lines = [
|
268
|
+
"# Auto-generated Appwrite constants",
|
269
|
+
`# Generated on ${new Date().toISOString()}`,
|
270
|
+
"",
|
271
|
+
"# Database IDs",
|
272
|
+
...Object.entries(databases).map(([key, value]) => `DATABASE_${key}=${value}`),
|
273
|
+
"",
|
274
|
+
"# Collection IDs",
|
275
|
+
...Object.entries(collections).map(([key, value]) => `COLLECTION_${key}=${value}`),
|
276
|
+
"",
|
277
|
+
"# Bucket IDs",
|
278
|
+
...Object.entries(buckets).map(([key, value]) => `BUCKET_${key}=${value}`),
|
279
|
+
"",
|
280
|
+
"# Function IDs",
|
281
|
+
...Object.entries(functions).map(([key, value]) => `FUNCTION_${key}=${value}`)
|
282
|
+
];
|
283
|
+
return lines.join('\n');
|
284
|
+
}
|
285
|
+
async generateFiles(languages, outputDir) {
|
286
|
+
await fs.mkdir(outputDir, { recursive: true });
|
287
|
+
const generators = {
|
288
|
+
typescript: () => ({ content: this.generateTypeScript(), filename: "appwrite-constants.ts" }),
|
289
|
+
javascript: () => ({ content: this.generateJavaScript(), filename: "appwrite-constants.js" }),
|
290
|
+
python: () => ({ content: this.generatePython(), filename: "appwrite_constants.py" }),
|
291
|
+
php: () => ({ content: this.generatePHP(), filename: "AppwriteConstants.php" }),
|
292
|
+
dart: () => ({ content: this.generateDart(), filename: "appwrite_constants.dart" }),
|
293
|
+
json: () => ({ content: this.generateJSON(), filename: "appwrite-constants.json" }),
|
294
|
+
env: () => ({ content: this.generateEnv(), filename: ".env.appwrite" })
|
295
|
+
};
|
296
|
+
for (const language of languages) {
|
297
|
+
const generator = generators[language];
|
298
|
+
if (generator) {
|
299
|
+
const { content, filename } = generator();
|
300
|
+
const filePath = path.join(outputDir, filename);
|
301
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
302
|
+
MessageFormatter.success(`Generated ${language} constants: ${filePath}`, { prefix: "Constants" });
|
303
|
+
}
|
304
|
+
else {
|
305
|
+
MessageFormatter.error(`Unsupported language: ${language}`, undefined, { prefix: "Constants" });
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
}
|
@@ -7,6 +7,7 @@ import chalk from "chalk";
|
|
7
7
|
import { findYamlConfig, loadYamlConfig } from "../config/yamlConfig.js";
|
8
8
|
import yaml from "js-yaml";
|
9
9
|
import { z } from "zod";
|
10
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
10
11
|
/**
|
11
12
|
* Recursively searches for configuration files starting from the given directory.
|
12
13
|
* Priority: 1) YAML configs in .appwrite directories, 2) appwriteConfig.ts files in subdirectories
|
@@ -79,7 +80,6 @@ const findAppwriteConfigTS = (dir, depth = 0) => {
|
|
79
80
|
// First check current directory for appwriteConfig.ts
|
80
81
|
for (const entry of entries) {
|
81
82
|
if (entry.isFile() && entry.name === "appwriteConfig.ts") {
|
82
|
-
console.log(`Found appwriteConfig.ts at: ${path.join(dir, entry.name)}`);
|
83
83
|
return path.join(dir, entry.name);
|
84
84
|
}
|
85
85
|
}
|
@@ -94,7 +94,6 @@ const findAppwriteConfigTS = (dir, depth = 0) => {
|
|
94
94
|
}
|
95
95
|
catch (error) {
|
96
96
|
// Ignore directory access errors
|
97
|
-
console.log(`Error accessing directory ${dir}:`, error);
|
98
97
|
}
|
99
98
|
return null;
|
100
99
|
};
|
@@ -134,7 +133,6 @@ export const loadConfigWithPath = async (configDir) => {
|
|
134
133
|
if (fs.existsSync(configPath)) {
|
135
134
|
const unregister = register(); // Register tsx enhancement
|
136
135
|
try {
|
137
|
-
console.log(`Loading TypeScript config from: ${configPath}`);
|
138
136
|
const configUrl = pathToFileURL(configPath).href;
|
139
137
|
const configModule = (await import(configUrl));
|
140
138
|
config = configModule.default?.default || configModule.default || configModule;
|
@@ -214,7 +212,6 @@ export const loadConfig = async (configDir) => {
|
|
214
212
|
// First try to find and load YAML config
|
215
213
|
const yamlConfigPath = findYamlConfig(configDir);
|
216
214
|
if (yamlConfigPath) {
|
217
|
-
console.log(`Loading YAML config from: ${yamlConfigPath}`);
|
218
215
|
config = await loadYamlConfig(yamlConfigPath);
|
219
216
|
actualConfigPath = yamlConfigPath;
|
220
217
|
}
|
@@ -225,7 +222,6 @@ export const loadConfig = async (configDir) => {
|
|
225
222
|
if (fs.existsSync(configPath)) {
|
226
223
|
const unregister = register(); // Register tsx enhancement
|
227
224
|
try {
|
228
|
-
console.log(`Loading TypeScript config from: ${configPath}`);
|
229
225
|
const configUrl = pathToFileURL(configPath).href;
|
230
226
|
const configModule = (await import(configUrl));
|
231
227
|
config = configModule.default?.default || configModule.default || configModule;
|
@@ -300,6 +296,10 @@ export const loadConfig = async (configDir) => {
|
|
300
296
|
else {
|
301
297
|
config.collections = config.collections || [];
|
302
298
|
}
|
299
|
+
// Log successful config loading
|
300
|
+
if (actualConfigPath) {
|
301
|
+
MessageFormatter.success(`Loaded config from: ${actualConfigPath}`, { prefix: "Config" });
|
302
|
+
}
|
303
303
|
return config;
|
304
304
|
};
|
305
305
|
export const findFunctionsDir = (dir, depth = 0) => {
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "appwrite-utils-cli",
|
3
3
|
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
4
|
-
"version": "1.0.
|
4
|
+
"version": "1.0.7",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
package/src/config/yamlConfig.ts
CHANGED
@@ -256,18 +256,14 @@ export const findYamlConfig = (startDir: string): string | null => {
|
|
256
256
|
path.join(startDir, "appwrite.yml"),
|
257
257
|
];
|
258
258
|
|
259
|
-
console.log(`DEBUG: Checking YAML paths in ${startDir}:`);
|
260
259
|
for (const configPath of possiblePaths) {
|
261
|
-
console.log(` - ${configPath}: ${fs.existsSync(configPath)}`);
|
262
260
|
if (fs.existsSync(configPath)) {
|
263
261
|
return configPath;
|
264
262
|
}
|
265
263
|
}
|
266
264
|
|
267
265
|
// Recursively search subdirectories for .appwrite folders
|
268
|
-
console.log(`DEBUG: Starting recursive search from ${startDir}`);
|
269
266
|
const yamlConfigInSubdirs = findYamlConfigRecursive(startDir);
|
270
|
-
console.log(`DEBUG: Recursive search result: ${yamlConfigInSubdirs}`);
|
271
267
|
if (yamlConfigInSubdirs) {
|
272
268
|
return yamlConfigInSubdirs;
|
273
269
|
}
|
@@ -336,27 +332,22 @@ const shouldIgnoreDirectory = (dirName: string): boolean => {
|
|
336
332
|
const findYamlConfigRecursive = (dir: string, depth: number = 0): string | null => {
|
337
333
|
// Limit search depth to prevent infinite recursion
|
338
334
|
if (depth > 5) {
|
339
|
-
console.log(`DEBUG: Stopping search at depth ${depth} in ${dir}`);
|
340
335
|
return null;
|
341
336
|
}
|
342
337
|
|
343
338
|
if (shouldIgnoreDirectory(path.basename(dir))) {
|
344
|
-
console.log(`DEBUG: Ignoring directory ${dir}`);
|
345
339
|
return null;
|
346
340
|
}
|
347
341
|
|
348
342
|
try {
|
349
343
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
350
|
-
console.log(`DEBUG: Searching directory ${dir} at depth ${depth}, found ${entries.length} entries`);
|
351
344
|
|
352
345
|
for (const entry of entries) {
|
353
346
|
if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
|
354
347
|
const fullPath = path.join(dir, entry.name);
|
355
|
-
console.log(`DEBUG: Checking subdirectory: ${fullPath}`);
|
356
348
|
|
357
349
|
// Check if this is an .appwrite directory
|
358
350
|
if (entry.name === ".appwrite") {
|
359
|
-
console.log(`DEBUG: Found .appwrite directory at ${fullPath}`);
|
360
351
|
const configPaths = [
|
361
352
|
path.join(fullPath, "appwriteConfig.yaml"),
|
362
353
|
path.join(fullPath, "appwriteConfig.yml"),
|
package/src/interactiveCLI.ts
CHANGED
@@ -41,6 +41,7 @@ import {
|
|
41
41
|
} from "./functions/methods.js";
|
42
42
|
import { deployLocalFunction } from "./functions/deployments.js";
|
43
43
|
import { join } from "node:path";
|
44
|
+
import path from "path";
|
44
45
|
import fs from "node:fs";
|
45
46
|
import { SchemaGenerator } from "./shared/schemaGenerator.js";
|
46
47
|
import { ConfirmationDialogs } from "./shared/confirmationDialogs.js";
|
@@ -51,23 +52,24 @@ import { findYamlConfig, addFunctionToYamlConfig } from "./config/yamlConfig.js"
|
|
51
52
|
|
52
53
|
enum CHOICES {
|
53
54
|
MIGRATE_CONFIG = "🔄 Migrate TypeScript config to YAML (.appwrite structure)",
|
54
|
-
CREATE_COLLECTION_CONFIG = "Create collection config file",
|
55
|
-
CREATE_FUNCTION = "Create a new function, from scratch or using a template",
|
56
|
-
DEPLOY_FUNCTION = "Deploy function(s)",
|
57
|
-
DELETE_FUNCTION = "Delete function",
|
58
|
-
SETUP_DIRS_FILES = "Setup directories and files",
|
59
|
-
SETUP_DIRS_FILES_WITH_EXAMPLE_DATA = "Setup directories and files with example data",
|
60
|
-
SYNC_DB = "Push local config to Appwrite",
|
61
|
-
SYNCHRONIZE_CONFIGURATIONS = "Synchronize configurations - Pull from Appwrite and write to local config",
|
62
|
-
TRANSFER_DATA = "Transfer data",
|
63
|
-
BACKUP_DATABASE = "Backup database",
|
64
|
-
WIPE_DATABASE = "Wipe database",
|
65
|
-
WIPE_COLLECTIONS = "Wipe collections",
|
66
|
-
GENERATE_SCHEMAS = "Generate schemas",
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
55
|
+
CREATE_COLLECTION_CONFIG = "📄 Create collection config file",
|
56
|
+
CREATE_FUNCTION = "⚡ Create a new function, from scratch or using a template",
|
57
|
+
DEPLOY_FUNCTION = "🚀 Deploy function(s)",
|
58
|
+
DELETE_FUNCTION = "🗑️ Delete function",
|
59
|
+
SETUP_DIRS_FILES = "📁 Setup directories and files",
|
60
|
+
SETUP_DIRS_FILES_WITH_EXAMPLE_DATA = "📁✨ Setup directories and files with example data",
|
61
|
+
SYNC_DB = "⬆️ Push local config to Appwrite",
|
62
|
+
SYNCHRONIZE_CONFIGURATIONS = "🔄 Synchronize configurations - Pull from Appwrite and write to local config",
|
63
|
+
TRANSFER_DATA = "📦 Transfer data",
|
64
|
+
BACKUP_DATABASE = "💾 Backup database",
|
65
|
+
WIPE_DATABASE = "🧹 Wipe database",
|
66
|
+
WIPE_COLLECTIONS = "🧹 Wipe collections",
|
67
|
+
GENERATE_SCHEMAS = "🏗️ Generate schemas",
|
68
|
+
GENERATE_CONSTANTS = "📋 Generate cross-language constants (TypeScript, Python, PHP, Dart, etc.)",
|
69
|
+
IMPORT_DATA = "📥 Import data",
|
70
|
+
RELOAD_CONFIG = "🔄 Reload configuration files",
|
71
|
+
UPDATE_FUNCTION_SPEC = "⚙️ Update function specifications",
|
72
|
+
EXIT = "👋 Exit",
|
71
73
|
}
|
72
74
|
|
73
75
|
export class InteractiveCLI {
|
@@ -159,6 +161,10 @@ export class InteractiveCLI {
|
|
159
161
|
await this.initControllerIfNeeded();
|
160
162
|
await this.generateSchemas();
|
161
163
|
break;
|
164
|
+
case CHOICES.GENERATE_CONSTANTS:
|
165
|
+
await this.initControllerIfNeeded();
|
166
|
+
await this.generateConstants();
|
167
|
+
break;
|
162
168
|
case CHOICES.IMPORT_DATA:
|
163
169
|
await this.initControllerIfNeeded();
|
164
170
|
await this.importData();
|
@@ -1595,6 +1601,73 @@ export class InteractiveCLI {
|
|
1595
1601
|
MessageFormatter.success("Schema generation completed", { prefix: "Schemas" });
|
1596
1602
|
}
|
1597
1603
|
|
1604
|
+
private async generateConstants(): Promise<void> {
|
1605
|
+
console.log(chalk.yellow("Generating cross-language constants..."));
|
1606
|
+
|
1607
|
+
if (!this.controller?.config) {
|
1608
|
+
MessageFormatter.error("No configuration found", undefined, { prefix: "Constants" });
|
1609
|
+
return;
|
1610
|
+
}
|
1611
|
+
|
1612
|
+
// Prompt for languages
|
1613
|
+
const { languages } = await inquirer.prompt([
|
1614
|
+
{
|
1615
|
+
type: "checkbox",
|
1616
|
+
name: "languages",
|
1617
|
+
message: "Select languages for constants generation:",
|
1618
|
+
choices: [
|
1619
|
+
{ name: "TypeScript", value: "typescript", checked: true },
|
1620
|
+
{ name: "JavaScript", value: "javascript" },
|
1621
|
+
{ name: "Python", value: "python" },
|
1622
|
+
{ name: "PHP", value: "php" },
|
1623
|
+
{ name: "Dart", value: "dart" },
|
1624
|
+
{ name: "JSON", value: "json" },
|
1625
|
+
{ name: "Environment Variables", value: "env" },
|
1626
|
+
],
|
1627
|
+
validate: (input) => {
|
1628
|
+
if (input.length === 0) {
|
1629
|
+
return "Please select at least one language";
|
1630
|
+
}
|
1631
|
+
return true;
|
1632
|
+
},
|
1633
|
+
},
|
1634
|
+
]);
|
1635
|
+
|
1636
|
+
// Determine default output directory based on config location
|
1637
|
+
const configPath = this.controller!.getAppwriteFolderPath();
|
1638
|
+
const defaultOutputDir = configPath
|
1639
|
+
? path.join(configPath, "constants")
|
1640
|
+
: path.join(process.cwd(), "constants");
|
1641
|
+
|
1642
|
+
// Prompt for output directory
|
1643
|
+
const { outputDir } = await inquirer.prompt([
|
1644
|
+
{
|
1645
|
+
type: "input",
|
1646
|
+
name: "outputDir",
|
1647
|
+
message: "Output directory for constants files:",
|
1648
|
+
default: defaultOutputDir,
|
1649
|
+
validate: (input) => {
|
1650
|
+
if (!input.trim()) {
|
1651
|
+
return "Output directory cannot be empty";
|
1652
|
+
}
|
1653
|
+
return true;
|
1654
|
+
},
|
1655
|
+
},
|
1656
|
+
]);
|
1657
|
+
|
1658
|
+
try {
|
1659
|
+
const { ConstantsGenerator } = await import("./utils/constantsGenerator.js");
|
1660
|
+
const generator = new ConstantsGenerator(this.controller.config);
|
1661
|
+
|
1662
|
+
MessageFormatter.info(`Generating constants for: ${languages.join(", ")}`, { prefix: "Constants" });
|
1663
|
+
await generator.generateFiles(languages, outputDir);
|
1664
|
+
|
1665
|
+
MessageFormatter.success(`Constants generated in ${outputDir}`, { prefix: "Constants" });
|
1666
|
+
} catch (error) {
|
1667
|
+
MessageFormatter.error("Failed to generate constants", error instanceof Error ? error : new Error(String(error)), { prefix: "Constants" });
|
1668
|
+
}
|
1669
|
+
}
|
1670
|
+
|
1598
1671
|
private async importData(): Promise<void> {
|
1599
1672
|
console.log(chalk.yellow("Importing data..."));
|
1600
1673
|
|
package/src/main.ts
CHANGED
@@ -15,6 +15,7 @@ import chalk from "chalk";
|
|
15
15
|
import { listSpecifications } from "./functions/methods.js";
|
16
16
|
import { MessageFormatter } from "./shared/messageFormatter.js";
|
17
17
|
import { ConfirmationDialogs } from "./shared/confirmationDialogs.js";
|
18
|
+
import path from "path";
|
18
19
|
|
19
20
|
interface CliOptions {
|
20
21
|
config?: string;
|
@@ -49,6 +50,9 @@ interface CliOptions {
|
|
49
50
|
functionId?: string;
|
50
51
|
specification?: string;
|
51
52
|
migrateConfig?: boolean;
|
53
|
+
generateConstants?: boolean;
|
54
|
+
constantsLanguages?: string;
|
55
|
+
constantsOutput?: string;
|
52
56
|
}
|
53
57
|
|
54
58
|
type ParsedArgv = ArgumentsCamelCase<CliOptions>;
|
@@ -203,6 +207,21 @@ const argv = yargs(hideBin(process.argv))
|
|
203
207
|
type: "boolean",
|
204
208
|
description: "Migrate appwriteConfig.ts to .appwrite structure with YAML configuration",
|
205
209
|
})
|
210
|
+
.option("generateConstants", {
|
211
|
+
alias: ["constants"],
|
212
|
+
type: "boolean",
|
213
|
+
description: "Generate cross-language constants file with database, collection, bucket, and function IDs",
|
214
|
+
})
|
215
|
+
.option("constantsLanguages", {
|
216
|
+
type: "string",
|
217
|
+
description: "Comma-separated list of languages for constants (typescript,javascript,python,php,dart,json,env)",
|
218
|
+
default: "typescript",
|
219
|
+
})
|
220
|
+
.option("constantsOutput", {
|
221
|
+
type: "string",
|
222
|
+
description: "Output directory for generated constants files (default: config-folder/constants)",
|
223
|
+
default: "auto",
|
224
|
+
})
|
206
225
|
.parse() as ParsedArgv;
|
207
226
|
|
208
227
|
async function main() {
|
@@ -235,6 +254,40 @@ async function main() {
|
|
235
254
|
return;
|
236
255
|
}
|
237
256
|
|
257
|
+
if (argv.generateConstants) {
|
258
|
+
const { ConstantsGenerator } = await import("./utils/constantsGenerator.js");
|
259
|
+
type SupportedLanguage = import("./utils/constantsGenerator.js").SupportedLanguage;
|
260
|
+
|
261
|
+
if (!controller.config) {
|
262
|
+
MessageFormatter.error("No Appwrite configuration found", undefined, { prefix: "Constants" });
|
263
|
+
return;
|
264
|
+
}
|
265
|
+
|
266
|
+
const languages = argv.constantsLanguages!.split(",").map(l => l.trim()) as SupportedLanguage[];
|
267
|
+
|
268
|
+
// Determine output directory - use config folder/constants by default, or custom path if specified
|
269
|
+
let outputDir: string;
|
270
|
+
if (argv.constantsOutput === "auto") {
|
271
|
+
// Default case: use config directory + constants, fallback to current directory
|
272
|
+
const configPath = controller.getAppwriteFolderPath();
|
273
|
+
outputDir = configPath
|
274
|
+
? path.join(configPath, "constants")
|
275
|
+
: path.join(process.cwd(), "constants");
|
276
|
+
} else {
|
277
|
+
// Custom output directory specified
|
278
|
+
outputDir = argv.constantsOutput!;
|
279
|
+
}
|
280
|
+
|
281
|
+
MessageFormatter.info(`Generating constants for languages: ${languages.join(", ")}`, { prefix: "Constants" });
|
282
|
+
|
283
|
+
const generator = new ConstantsGenerator(controller.config);
|
284
|
+
await generator.generateFiles(languages, outputDir);
|
285
|
+
|
286
|
+
operationStats.generatedConstants = languages.length;
|
287
|
+
MessageFormatter.success(`Constants generated in ${outputDir}`, { prefix: "Constants" });
|
288
|
+
return;
|
289
|
+
}
|
290
|
+
|
238
291
|
if (!controller.config) {
|
239
292
|
MessageFormatter.error("No Appwrite connection found", undefined, { prefix: "CLI" });
|
240
293
|
return;
|