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.
@@ -0,0 +1,352 @@
1
+ import fs from "fs/promises";
2
+ import path from "path";
3
+ import { type AppwriteConfig } from "appwrite-utils";
4
+ import { MessageFormatter } from "../shared/messageFormatter.js";
5
+
6
+ export type SupportedLanguage =
7
+ | "typescript"
8
+ | "javascript"
9
+ | "python"
10
+ | "php"
11
+ | "dart"
12
+ | "json"
13
+ | "env";
14
+
15
+ interface Constants {
16
+ databases: Record<string, string>;
17
+ collections: Record<string, string>;
18
+ buckets: Record<string, string>;
19
+ functions: Record<string, string>;
20
+ }
21
+
22
+ export class ConstantsGenerator {
23
+ private config: AppwriteConfig;
24
+ private constants: Constants;
25
+
26
+ constructor(config: AppwriteConfig) {
27
+ this.config = config;
28
+ this.constants = this.extractConstants();
29
+ }
30
+
31
+ private extractConstants(): Constants {
32
+ const constants: Constants = {
33
+ databases: {},
34
+ collections: {},
35
+ buckets: {},
36
+ functions: {}
37
+ };
38
+
39
+ // Extract database IDs
40
+ this.config.databases?.forEach(db => {
41
+ if (db.$id) {
42
+ const key = this.toConstantName(db.name || db.$id);
43
+ constants.databases[key] = db.$id;
44
+ }
45
+ });
46
+
47
+ // Extract collection IDs
48
+ this.config.collections?.forEach(collection => {
49
+ if (collection.$id) {
50
+ const key = this.toConstantName(collection.name || collection.$id);
51
+ constants.collections[key] = collection.$id;
52
+ }
53
+ });
54
+
55
+ // Extract bucket IDs
56
+ this.config.buckets?.forEach(bucket => {
57
+ if (bucket.$id) {
58
+ const key = this.toConstantName(bucket.name || bucket.$id);
59
+ constants.buckets[key] = bucket.$id;
60
+ }
61
+ });
62
+
63
+ // Extract function IDs
64
+ this.config.functions?.forEach(func => {
65
+ if (func.$id) {
66
+ const key = this.toConstantName(func.name || func.$id);
67
+ constants.functions[key] = func.$id;
68
+ }
69
+ });
70
+
71
+ return constants;
72
+ }
73
+
74
+ private toConstantName(name: string): string {
75
+ return name
76
+ .replace(/[^a-zA-Z0-9]/g, '_')
77
+ .replace(/_+/g, '_')
78
+ .replace(/^_|_$/g, '')
79
+ .toUpperCase();
80
+ }
81
+
82
+ private toCamelCase(name: string): string {
83
+ return name
84
+ .toLowerCase()
85
+ .replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
86
+ }
87
+
88
+ private toSnakeCase(name: string): string {
89
+ return name.toLowerCase();
90
+ }
91
+
92
+ generateTypeScript(): string {
93
+ const { databases, collections, buckets, functions } = this.constants;
94
+
95
+ return `// Auto-generated Appwrite constants
96
+ // Generated on ${new Date().toISOString()}
97
+
98
+ export const DATABASE_IDS = {
99
+ ${Object.entries(databases).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
100
+ } as const;
101
+
102
+ export const COLLECTION_IDS = {
103
+ ${Object.entries(collections).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
104
+ } as const;
105
+
106
+ export const BUCKET_IDS = {
107
+ ${Object.entries(buckets).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
108
+ } as const;
109
+
110
+ export const FUNCTION_IDS = {
111
+ ${Object.entries(functions).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
112
+ } as const;
113
+
114
+ // Type helpers
115
+ export type DatabaseId = typeof DATABASE_IDS[keyof typeof DATABASE_IDS];
116
+ export type CollectionId = typeof COLLECTION_IDS[keyof typeof COLLECTION_IDS];
117
+ export type BucketId = typeof BUCKET_IDS[keyof typeof BUCKET_IDS];
118
+ export type FunctionId = typeof FUNCTION_IDS[keyof typeof FUNCTION_IDS];
119
+
120
+ // Helper objects for runtime use
121
+ export const ALL_DATABASE_IDS = Object.values(DATABASE_IDS);
122
+ export const ALL_COLLECTION_IDS = Object.values(COLLECTION_IDS);
123
+ export const ALL_BUCKET_IDS = Object.values(BUCKET_IDS);
124
+ export const ALL_FUNCTION_IDS = Object.values(FUNCTION_IDS);
125
+ `;
126
+ }
127
+
128
+ generateJavaScript(): string {
129
+ const { databases, collections, buckets, functions } = this.constants;
130
+
131
+ return `// Auto-generated Appwrite constants
132
+ // Generated on ${new Date().toISOString()}
133
+
134
+ export const DATABASE_IDS = {
135
+ ${Object.entries(databases).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
136
+ };
137
+
138
+ export const COLLECTION_IDS = {
139
+ ${Object.entries(collections).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
140
+ };
141
+
142
+ export const BUCKET_IDS = {
143
+ ${Object.entries(buckets).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
144
+ };
145
+
146
+ export const FUNCTION_IDS = {
147
+ ${Object.entries(functions).map(([key, value]) => ` ${key}: "${value}"`).join(',\n')}
148
+ };
149
+
150
+ // Helper arrays for runtime use
151
+ export const ALL_DATABASE_IDS = Object.values(DATABASE_IDS);
152
+ export const ALL_COLLECTION_IDS = Object.values(COLLECTION_IDS);
153
+ export const ALL_BUCKET_IDS = Object.values(BUCKET_IDS);
154
+ export const ALL_FUNCTION_IDS = Object.values(FUNCTION_IDS);
155
+ `;
156
+ }
157
+
158
+ generatePython(): string {
159
+ const { databases, collections, buckets, functions } = this.constants;
160
+
161
+ return `# Auto-generated Appwrite constants
162
+ # Generated on ${new Date().toISOString()}
163
+
164
+ class DatabaseIds:
165
+ """Database ID constants"""
166
+ ${Object.entries(databases).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
167
+
168
+ class CollectionIds:
169
+ """Collection ID constants"""
170
+ ${Object.entries(collections).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
171
+
172
+ class BucketIds:
173
+ """Bucket ID constants"""
174
+ ${Object.entries(buckets).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
175
+
176
+ class FunctionIds:
177
+ """Function ID constants"""
178
+ ${Object.entries(functions).map(([key, value]) => ` ${key} = "${value}"`).join('\n')}
179
+
180
+ # Helper dictionaries for runtime use
181
+ DATABASE_ID_MAP = {
182
+ ${Object.entries(databases).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
183
+ }
184
+
185
+ COLLECTION_ID_MAP = {
186
+ ${Object.entries(collections).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
187
+ }
188
+
189
+ BUCKET_ID_MAP = {
190
+ ${Object.entries(buckets).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
191
+ }
192
+
193
+ FUNCTION_ID_MAP = {
194
+ ${Object.entries(functions).map(([key, value]) => ` "${this.toSnakeCase(key)}": "${value}"`).join(',\n')}
195
+ }
196
+ `;
197
+ }
198
+
199
+ generatePHP(): string {
200
+ const { databases, collections, buckets, functions } = this.constants;
201
+
202
+ return `<?php
203
+ // Auto-generated Appwrite constants
204
+ // Generated on ${new Date().toISOString()}
205
+
206
+ class AppwriteConstants {
207
+
208
+ const DATABASE_IDS = [
209
+ ${Object.entries(databases).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
210
+ ];
211
+
212
+ const COLLECTION_IDS = [
213
+ ${Object.entries(collections).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
214
+ ];
215
+
216
+ const BUCKET_IDS = [
217
+ ${Object.entries(buckets).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
218
+ ];
219
+
220
+ const FUNCTION_IDS = [
221
+ ${Object.entries(functions).map(([key, value]) => ` '${key}' => '${value}'`).join(',\n')}
222
+ ];
223
+
224
+ /**
225
+ * Get all database IDs as array
226
+ */
227
+ public static function getAllDatabaseIds(): array {
228
+ return array_values(self::DATABASE_IDS);
229
+ }
230
+
231
+ /**
232
+ * Get all collection IDs as array
233
+ */
234
+ public static function getAllCollectionIds(): array {
235
+ return array_values(self::COLLECTION_IDS);
236
+ }
237
+
238
+ /**
239
+ * Get all bucket IDs as array
240
+ */
241
+ public static function getAllBucketIds(): array {
242
+ return array_values(self::BUCKET_IDS);
243
+ }
244
+
245
+ /**
246
+ * Get all function IDs as array
247
+ */
248
+ public static function getAllFunctionIds(): array {
249
+ return array_values(self::FUNCTION_IDS);
250
+ }
251
+ }
252
+ `;
253
+ }
254
+
255
+ generateDart(): string {
256
+ const { databases, collections, buckets, functions } = this.constants;
257
+
258
+ return `// Auto-generated Appwrite constants
259
+ // Generated on ${new Date().toISOString()}
260
+
261
+ class AppwriteConstants {
262
+
263
+ static const Map<String, String> databaseIds = {
264
+ ${Object.entries(databases).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
265
+ };
266
+
267
+ static const Map<String, String> collectionIds = {
268
+ ${Object.entries(collections).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
269
+ };
270
+
271
+ static const Map<String, String> bucketIds = {
272
+ ${Object.entries(buckets).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
273
+ };
274
+
275
+ static const Map<String, String> functionIds = {
276
+ ${Object.entries(functions).map(([key, value]) => ` '${this.toCamelCase(key)}': '${value}'`).join(',\n')}
277
+ };
278
+
279
+ // Helper getters for individual IDs
280
+ ${Object.entries(databases).map(([key, value]) => ` static String get ${this.toCamelCase(key)}DatabaseId => '${value}';`).join('\n')}
281
+
282
+ ${Object.entries(collections).map(([key, value]) => ` static String get ${this.toCamelCase(key)}CollectionId => '${value}';`).join('\n')}
283
+
284
+ ${Object.entries(buckets).map(([key, value]) => ` static String get ${this.toCamelCase(key)}BucketId => '${value}';`).join('\n')}
285
+
286
+ ${Object.entries(functions).map(([key, value]) => ` static String get ${this.toCamelCase(key)}FunctionId => '${value}';`).join('\n')}
287
+ }
288
+ `;
289
+ }
290
+
291
+ generateJSON(): string {
292
+ return JSON.stringify({
293
+ meta: {
294
+ generated: new Date().toISOString(),
295
+ generator: "appwrite-utils-cli"
296
+ },
297
+ databases: this.constants.databases,
298
+ collections: this.constants.collections,
299
+ buckets: this.constants.buckets,
300
+ functions: this.constants.functions
301
+ }, null, 2);
302
+ }
303
+
304
+ generateEnv(): string {
305
+ const { databases, collections, buckets, functions } = this.constants;
306
+
307
+ const lines = [
308
+ "# Auto-generated Appwrite constants",
309
+ `# Generated on ${new Date().toISOString()}`,
310
+ "",
311
+ "# Database IDs",
312
+ ...Object.entries(databases).map(([key, value]) => `DATABASE_${key}=${value}`),
313
+ "",
314
+ "# Collection IDs",
315
+ ...Object.entries(collections).map(([key, value]) => `COLLECTION_${key}=${value}`),
316
+ "",
317
+ "# Bucket IDs",
318
+ ...Object.entries(buckets).map(([key, value]) => `BUCKET_${key}=${value}`),
319
+ "",
320
+ "# Function IDs",
321
+ ...Object.entries(functions).map(([key, value]) => `FUNCTION_${key}=${value}`)
322
+ ];
323
+
324
+ return lines.join('\n');
325
+ }
326
+
327
+ async generateFiles(languages: SupportedLanguage[], outputDir: string): Promise<void> {
328
+ await fs.mkdir(outputDir, { recursive: true });
329
+
330
+ const generators = {
331
+ typescript: () => ({ content: this.generateTypeScript(), filename: "appwrite-constants.ts" }),
332
+ javascript: () => ({ content: this.generateJavaScript(), filename: "appwrite-constants.js" }),
333
+ python: () => ({ content: this.generatePython(), filename: "appwrite_constants.py" }),
334
+ php: () => ({ content: this.generatePHP(), filename: "AppwriteConstants.php" }),
335
+ dart: () => ({ content: this.generateDart(), filename: "appwrite_constants.dart" }),
336
+ json: () => ({ content: this.generateJSON(), filename: "appwrite-constants.json" }),
337
+ env: () => ({ content: this.generateEnv(), filename: ".env.appwrite" })
338
+ };
339
+
340
+ for (const language of languages) {
341
+ const generator = generators[language];
342
+ if (generator) {
343
+ const { content, filename } = generator();
344
+ const filePath = path.join(outputDir, filename);
345
+ await fs.writeFile(filePath, content, 'utf-8');
346
+ MessageFormatter.success(`Generated ${language} constants: ${filePath}`, { prefix: "Constants" });
347
+ } else {
348
+ MessageFormatter.error(`Unsupported language: ${language}`, undefined, { prefix: "Constants" });
349
+ }
350
+ }
351
+ }
352
+ }
@@ -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
  /**
12
13
  * Recursively searches for configuration files starting from the given directory.
@@ -88,7 +89,6 @@ const findAppwriteConfigTS = (dir: string, depth: number = 0): string | null =>
88
89
  // First check current directory for appwriteConfig.ts
89
90
  for (const entry of entries) {
90
91
  if (entry.isFile() && entry.name === "appwriteConfig.ts") {
91
- console.log(`Found appwriteConfig.ts at: ${path.join(dir, entry.name)}`);
92
92
  return path.join(dir, entry.name);
93
93
  }
94
94
  }
@@ -102,7 +102,6 @@ const findAppwriteConfigTS = (dir: string, depth: number = 0): string | null =>
102
102
  }
103
103
  } catch (error) {
104
104
  // Ignore directory access errors
105
- console.log(`Error accessing directory ${dir}:`, error);
106
105
  }
107
106
 
108
107
  return null;
@@ -149,7 +148,6 @@ export const loadConfigWithPath = async (
149
148
  const unregister = register(); // Register tsx enhancement
150
149
 
151
150
  try {
152
- console.log(`Loading TypeScript config from: ${configPath}`);
153
151
  const configUrl = pathToFileURL(configPath).href;
154
152
  const configModule = (await import(configUrl));
155
153
  config = configModule.default?.default || configModule.default || configModule;
@@ -239,7 +237,6 @@ export const loadConfig = async (
239
237
  // First try to find and load YAML config
240
238
  const yamlConfigPath = findYamlConfig(configDir);
241
239
  if (yamlConfigPath) {
242
- console.log(`Loading YAML config from: ${yamlConfigPath}`);
243
240
  config = await loadYamlConfig(yamlConfigPath);
244
241
  actualConfigPath = yamlConfigPath;
245
242
  }
@@ -253,7 +250,6 @@ export const loadConfig = async (
253
250
  const unregister = register(); // Register tsx enhancement
254
251
 
255
252
  try {
256
- console.log(`Loading TypeScript config from: ${configPath}`);
257
253
  const configUrl = pathToFileURL(configPath).href;
258
254
  const configModule = (await import(configUrl));
259
255
  config = configModule.default?.default || configModule.default || configModule;
@@ -332,6 +328,11 @@ export const loadConfig = async (
332
328
  config.collections = config.collections || [];
333
329
  }
334
330
 
331
+ // Log successful config loading
332
+ if (actualConfigPath) {
333
+ MessageFormatter.success(`Loaded config from: ${actualConfigPath}`, { prefix: "Config" });
334
+ }
335
+
335
336
  return config;
336
337
  };
337
338