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 CHANGED
@@ -23,6 +23,7 @@
23
23
  ### Development Tools
24
24
  - **Database Migrations**: Full migration control with progress tracking and operation summaries
25
25
  - **Schema Generation**: Generate TypeScript and JSON schemas from database configurations
26
+ - **Constants Generation**: Generate cross-language constants files (TypeScript, Python, PHP, Dart, JSON, Env) for database, collection, bucket, and function IDs
26
27
  - **Data Transfer**: Transfer data between databases, collections, and instances with real-time progress
27
28
  - **Configuration Sync**: Bidirectional synchronization between local YAML configs and Appwrite projects
28
29
  - **Function Management**: Deploy and manage Appwrite Functions with specification updates
@@ -218,8 +219,53 @@ Available options:
218
219
  - `--functionId`: Function ID to update
219
220
  - `--specification`: New function specification (s-0.5vcpu-512mb to s-8vcpu-8gb)
220
221
 
222
+ ### Constants Generation
223
+ - `--generateConstants` / `--constants`: Generate cross-language constants files with database, collection, bucket, and function IDs
224
+ - `--constantsLanguages`: Comma-separated list of languages for constants generation (default: typescript)
225
+ - Available languages: `typescript`, `javascript`, `python`, `php`, `dart`, `json`, `env`
226
+ - `--constantsOutput`: Output directory for generated constants files (default: config-folder/constants)
227
+
221
228
  ## Examples
222
229
 
230
+ ### Generate Constants
231
+
232
+ Generate cross-language constants files for all your Appwrite resource IDs:
233
+
234
+ ```bash
235
+ # Generate TypeScript constants (default)
236
+ npx appwrite-utils-cli appwrite-migrate --generateConstants
237
+
238
+ # Generate multiple language formats
239
+ npx appwrite-utils-cli appwrite-migrate --generateConstants --constantsLanguages="typescript,python,php,json"
240
+
241
+ # Generate all available formats
242
+ npx appwrite-utils-cli appwrite-migrate --generateConstants --constantsLanguages="typescript,javascript,python,php,dart,json,env"
243
+
244
+ # Generate with custom output directory
245
+ npx appwrite-utils-cli appwrite-migrate --generateConstants --constantsOutput="./my-constants"
246
+ ```
247
+
248
+ This generates constants files in your configuration directory (e.g., `.appwrite/constants/`) containing:
249
+ - Database IDs
250
+ - Collection IDs
251
+ - Bucket IDs
252
+ - Function IDs
253
+
254
+ **Example TypeScript output:**
255
+ ```typescript
256
+ export const DATABASE_IDS = {
257
+ MAIN_DATABASE: "main"
258
+ } as const;
259
+
260
+ export const COLLECTION_IDS = {
261
+ USERS: "01JYDBQTB5W8SCBAYB654CCADQ",
262
+ POSTS: "01JYDBQTB5W8SCBAYB654POSTS"
263
+ } as const;
264
+
265
+ // Type helpers and utility arrays included
266
+ export type DatabaseId = typeof DATABASE_IDS[keyof typeof DATABASE_IDS];
267
+ ```
268
+
223
269
  ### Transfer Databases
224
270
 
225
271
  Transfer databases within the same project or from a local to a remote project:
@@ -281,6 +327,56 @@ This updated CLI ensures that developers have robust tools at their fingertips t
281
327
 
282
328
  ## Changelog
283
329
 
330
+ ### 1.0.7 - Forgot to remove debug logs
331
+
332
+ ### 1.0.6 - Cross-Language Constants Generation
333
+
334
+ **🚀 Enhanced Developer Experience with Multi-Language Constants**
335
+
336
+ #### Constants Generation System
337
+ - **Cross-Language Support**: Generate constants in 7 languages for seamless multi-platform development
338
+ - **TypeScript**: Type-safe constants with `as const` and helper types
339
+ - **JavaScript**: ES6 modules with utility arrays
340
+ - **Python**: Class-based constants with snake_case dictionaries
341
+ - **PHP**: Static class methods and associative arrays
342
+ - **Dart**: Maps with individual getter methods (camelCase)
343
+ - **JSON**: Structured data with metadata for cross-platform integration
344
+ - **Environment Variables**: Prefixed environment variables for deployment
345
+ - **Smart Directory Structure**: Constants generated in `{config-folder}/constants/` by default
346
+ - **CLI Integration**: Both command-line and interactive mode support
347
+ - **Custom Output**: Support for custom output directories when needed
348
+
349
+ #### Resource ID Extraction
350
+ - **Database IDs**: Extract all configured database identifiers
351
+ - **Collection IDs**: Generate constants for all collection ULIDs/names
352
+ - **Bucket IDs**: Include storage bucket identifiers
353
+ - **Function IDs**: Support for Appwrite Function identifiers
354
+ - **Naming Conventions**: Language-appropriate naming (UPPER_CASE, camelCase, snake_case)
355
+
356
+ #### Developer Experience Improvements
357
+ - **Interactive Mode**: Checkbox selection for languages with smart defaults
358
+ - **CLI Commands**: Simple `--generateConstants` with language and output options
359
+ - **Type Safety**: Full TypeScript support with generated types and helpers
360
+ - **Cross-Platform Compatibility**: Enable seamless development across different tech stacks
361
+
362
+ #### Usage Examples
363
+ ```bash
364
+ # Default TypeScript generation
365
+ npx appwrite-utils-cli appwrite-migrate --generateConstants
366
+
367
+ # Multi-language generation
368
+ npx appwrite-utils-cli appwrite-migrate --generateConstants --constantsLanguages="typescript,python,php,json"
369
+
370
+ # All formats with custom output
371
+ npx appwrite-utils-cli appwrite-migrate --generateConstants --constantsLanguages="typescript,javascript,python,php,dart,json,env" --constantsOutput="./constants"
372
+ ```
373
+
374
+ **Migration Benefits**:
375
+ - Eliminates hardcoded resource IDs across codebases
376
+ - Enables type-safe resource access in TypeScript projects
377
+ - Supports multi-language development workflows
378
+ - Maintains constants alongside configuration for easy maintenance
379
+
284
380
  ### 1.0.1 - Function Templates & Attribute Type Improvements
285
381
 
286
382
  **🚀 Enhanced Function Management & Type System Fixes**
@@ -243,17 +243,13 @@ export const findYamlConfig = (startDir) => {
243
243
  path.join(startDir, "appwrite.yaml"),
244
244
  path.join(startDir, "appwrite.yml"),
245
245
  ];
246
- console.log(`DEBUG: Checking YAML paths in ${startDir}:`);
247
246
  for (const configPath of possiblePaths) {
248
- console.log(` - ${configPath}: ${fs.existsSync(configPath)}`);
249
247
  if (fs.existsSync(configPath)) {
250
248
  return configPath;
251
249
  }
252
250
  }
253
251
  // Recursively search subdirectories for .appwrite folders
254
- console.log(`DEBUG: Starting recursive search from ${startDir}`);
255
252
  const yamlConfigInSubdirs = findYamlConfigRecursive(startDir);
256
- console.log(`DEBUG: Recursive search result: ${yamlConfigInSubdirs}`);
257
253
  if (yamlConfigInSubdirs) {
258
254
  return yamlConfigInSubdirs;
259
255
  }
@@ -316,23 +312,18 @@ const shouldIgnoreDirectory = (dirName) => {
316
312
  const findYamlConfigRecursive = (dir, depth = 0) => {
317
313
  // Limit search depth to prevent infinite recursion
318
314
  if (depth > 5) {
319
- console.log(`DEBUG: Stopping search at depth ${depth} in ${dir}`);
320
315
  return null;
321
316
  }
322
317
  if (shouldIgnoreDirectory(path.basename(dir))) {
323
- console.log(`DEBUG: Ignoring directory ${dir}`);
324
318
  return null;
325
319
  }
326
320
  try {
327
321
  const entries = fs.readdirSync(dir, { withFileTypes: true });
328
- console.log(`DEBUG: Searching directory ${dir} at depth ${depth}, found ${entries.length} entries`);
329
322
  for (const entry of entries) {
330
323
  if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
331
324
  const fullPath = path.join(dir, entry.name);
332
- console.log(`DEBUG: Checking subdirectory: ${fullPath}`);
333
325
  // Check if this is an .appwrite directory
334
326
  if (entry.name === ".appwrite") {
335
- console.log(`DEBUG: Found .appwrite directory at ${fullPath}`);
336
327
  const configPaths = [
337
328
  path.join(fullPath, "appwriteConfig.yaml"),
338
329
  path.join(fullPath, "appwriteConfig.yml"),
@@ -24,6 +24,7 @@ export declare class InteractiveCLI {
24
24
  private wipeDatabase;
25
25
  private wipeCollections;
26
26
  private generateSchemas;
27
+ private generateConstants;
27
28
  private importData;
28
29
  private transferData;
29
30
  private getLocalCollections;
@@ -13,6 +13,7 @@ import { DateTime } from "luxon";
13
13
  import { createFunctionTemplate, deleteFunction, downloadLatestFunctionDeployment, getFunction, listFunctions, listSpecifications, } from "./functions/methods.js";
14
14
  import { deployLocalFunction } from "./functions/deployments.js";
15
15
  import { join } from "node:path";
16
+ import path from "path";
16
17
  import fs from "node:fs";
17
18
  import { SchemaGenerator } from "./shared/schemaGenerator.js";
18
19
  import { ConfirmationDialogs } from "./shared/confirmationDialogs.js";
@@ -23,23 +24,24 @@ import { findYamlConfig, addFunctionToYamlConfig } from "./config/yamlConfig.js"
23
24
  var CHOICES;
24
25
  (function (CHOICES) {
25
26
  CHOICES["MIGRATE_CONFIG"] = "\uD83D\uDD04 Migrate TypeScript config to YAML (.appwrite structure)";
26
- CHOICES["CREATE_COLLECTION_CONFIG"] = "Create collection config file";
27
- CHOICES["CREATE_FUNCTION"] = "Create a new function, from scratch or using a template";
28
- CHOICES["DEPLOY_FUNCTION"] = "Deploy function(s)";
29
- CHOICES["DELETE_FUNCTION"] = "Delete function";
30
- CHOICES["SETUP_DIRS_FILES"] = "Setup directories and files";
31
- CHOICES["SETUP_DIRS_FILES_WITH_EXAMPLE_DATA"] = "Setup directories and files with example data";
32
- CHOICES["SYNC_DB"] = "Push local config to Appwrite";
33
- CHOICES["SYNCHRONIZE_CONFIGURATIONS"] = "Synchronize configurations - Pull from Appwrite and write to local config";
34
- CHOICES["TRANSFER_DATA"] = "Transfer data";
35
- CHOICES["BACKUP_DATABASE"] = "Backup database";
36
- CHOICES["WIPE_DATABASE"] = "Wipe database";
37
- CHOICES["WIPE_COLLECTIONS"] = "Wipe collections";
38
- CHOICES["GENERATE_SCHEMAS"] = "Generate schemas";
39
- CHOICES["IMPORT_DATA"] = "Import data";
40
- CHOICES["RELOAD_CONFIG"] = "Reload configuration files";
41
- CHOICES["UPDATE_FUNCTION_SPEC"] = "Update function specifications";
42
- CHOICES["EXIT"] = "Exit";
27
+ CHOICES["CREATE_COLLECTION_CONFIG"] = "\uD83D\uDCC4 Create collection config file";
28
+ CHOICES["CREATE_FUNCTION"] = "\u26A1 Create a new function, from scratch or using a template";
29
+ CHOICES["DEPLOY_FUNCTION"] = "\uD83D\uDE80 Deploy function(s)";
30
+ CHOICES["DELETE_FUNCTION"] = "\uD83D\uDDD1\uFE0F Delete function";
31
+ CHOICES["SETUP_DIRS_FILES"] = "\uD83D\uDCC1 Setup directories and files";
32
+ CHOICES["SETUP_DIRS_FILES_WITH_EXAMPLE_DATA"] = "\uD83D\uDCC1\u2728 Setup directories and files with example data";
33
+ CHOICES["SYNC_DB"] = "\u2B06\uFE0F Push local config to Appwrite";
34
+ CHOICES["SYNCHRONIZE_CONFIGURATIONS"] = "\uD83D\uDD04 Synchronize configurations - Pull from Appwrite and write to local config";
35
+ CHOICES["TRANSFER_DATA"] = "\uD83D\uDCE6 Transfer data";
36
+ CHOICES["BACKUP_DATABASE"] = "\uD83D\uDCBE Backup database";
37
+ CHOICES["WIPE_DATABASE"] = "\uD83E\uDDF9 Wipe database";
38
+ CHOICES["WIPE_COLLECTIONS"] = "\uD83E\uDDF9 Wipe collections";
39
+ CHOICES["GENERATE_SCHEMAS"] = "\uD83C\uDFD7\uFE0F Generate schemas";
40
+ CHOICES["GENERATE_CONSTANTS"] = "\uD83D\uDCCB Generate cross-language constants (TypeScript, Python, PHP, Dart, etc.)";
41
+ CHOICES["IMPORT_DATA"] = "\uD83D\uDCE5 Import data";
42
+ CHOICES["RELOAD_CONFIG"] = "\uD83D\uDD04 Reload configuration files";
43
+ CHOICES["UPDATE_FUNCTION_SPEC"] = "\u2699\uFE0F Update function specifications";
44
+ CHOICES["EXIT"] = "\uD83D\uDC4B Exit";
43
45
  })(CHOICES || (CHOICES = {}));
44
46
  export class InteractiveCLI {
45
47
  currentDir;
@@ -123,6 +125,10 @@ export class InteractiveCLI {
123
125
  await this.initControllerIfNeeded();
124
126
  await this.generateSchemas();
125
127
  break;
128
+ case CHOICES.GENERATE_CONSTANTS:
129
+ await this.initControllerIfNeeded();
130
+ await this.generateConstants();
131
+ break;
126
132
  case CHOICES.IMPORT_DATA:
127
133
  await this.initControllerIfNeeded();
128
134
  await this.importData();
@@ -1167,6 +1173,66 @@ export class InteractiveCLI {
1167
1173
  schemaGenerator.generateSchemas({ format: schemaType, verbose: true });
1168
1174
  MessageFormatter.success("Schema generation completed", { prefix: "Schemas" });
1169
1175
  }
1176
+ async generateConstants() {
1177
+ console.log(chalk.yellow("Generating cross-language constants..."));
1178
+ if (!this.controller?.config) {
1179
+ MessageFormatter.error("No configuration found", undefined, { prefix: "Constants" });
1180
+ return;
1181
+ }
1182
+ // Prompt for languages
1183
+ const { languages } = await inquirer.prompt([
1184
+ {
1185
+ type: "checkbox",
1186
+ name: "languages",
1187
+ message: "Select languages for constants generation:",
1188
+ choices: [
1189
+ { name: "TypeScript", value: "typescript", checked: true },
1190
+ { name: "JavaScript", value: "javascript" },
1191
+ { name: "Python", value: "python" },
1192
+ { name: "PHP", value: "php" },
1193
+ { name: "Dart", value: "dart" },
1194
+ { name: "JSON", value: "json" },
1195
+ { name: "Environment Variables", value: "env" },
1196
+ ],
1197
+ validate: (input) => {
1198
+ if (input.length === 0) {
1199
+ return "Please select at least one language";
1200
+ }
1201
+ return true;
1202
+ },
1203
+ },
1204
+ ]);
1205
+ // Determine default output directory based on config location
1206
+ const configPath = this.controller.getAppwriteFolderPath();
1207
+ const defaultOutputDir = configPath
1208
+ ? path.join(configPath, "constants")
1209
+ : path.join(process.cwd(), "constants");
1210
+ // Prompt for output directory
1211
+ const { outputDir } = await inquirer.prompt([
1212
+ {
1213
+ type: "input",
1214
+ name: "outputDir",
1215
+ message: "Output directory for constants files:",
1216
+ default: defaultOutputDir,
1217
+ validate: (input) => {
1218
+ if (!input.trim()) {
1219
+ return "Output directory cannot be empty";
1220
+ }
1221
+ return true;
1222
+ },
1223
+ },
1224
+ ]);
1225
+ try {
1226
+ const { ConstantsGenerator } = await import("./utils/constantsGenerator.js");
1227
+ const generator = new ConstantsGenerator(this.controller.config);
1228
+ MessageFormatter.info(`Generating constants for: ${languages.join(", ")}`, { prefix: "Constants" });
1229
+ await generator.generateFiles(languages, outputDir);
1230
+ MessageFormatter.success(`Constants generated in ${outputDir}`, { prefix: "Constants" });
1231
+ }
1232
+ catch (error) {
1233
+ MessageFormatter.error("Failed to generate constants", error instanceof Error ? error : new Error(String(error)), { prefix: "Constants" });
1234
+ }
1235
+ }
1170
1236
  async importData() {
1171
1237
  console.log(chalk.yellow("Importing data..."));
1172
1238
  const { doBackup } = await inquirer.prompt([
package/dist/main.js CHANGED
@@ -13,6 +13,7 @@ import chalk from "chalk";
13
13
  import { listSpecifications } from "./functions/methods.js";
14
14
  import { MessageFormatter } from "./shared/messageFormatter.js";
15
15
  import { ConfirmationDialogs } from "./shared/confirmationDialogs.js";
16
+ import path from "path";
16
17
  const argv = yargs(hideBin(process.argv))
17
18
  .option("config", {
18
19
  type: "string",
@@ -158,6 +159,21 @@ const argv = yargs(hideBin(process.argv))
158
159
  alias: ["migrate"],
159
160
  type: "boolean",
160
161
  description: "Migrate appwriteConfig.ts to .appwrite structure with YAML configuration",
162
+ })
163
+ .option("generateConstants", {
164
+ alias: ["constants"],
165
+ type: "boolean",
166
+ description: "Generate cross-language constants file with database, collection, bucket, and function IDs",
167
+ })
168
+ .option("constantsLanguages", {
169
+ type: "string",
170
+ description: "Comma-separated list of languages for constants (typescript,javascript,python,php,dart,json,env)",
171
+ default: "typescript",
172
+ })
173
+ .option("constantsOutput", {
174
+ type: "string",
175
+ description: "Output directory for generated constants files (default: config-folder/constants)",
176
+ default: "auto",
161
177
  })
162
178
  .parse();
163
179
  async function main() {
@@ -186,6 +202,33 @@ async function main() {
186
202
  await migrateConfig(process.cwd());
187
203
  return;
188
204
  }
205
+ if (argv.generateConstants) {
206
+ const { ConstantsGenerator } = await import("./utils/constantsGenerator.js");
207
+ if (!controller.config) {
208
+ MessageFormatter.error("No Appwrite configuration found", undefined, { prefix: "Constants" });
209
+ return;
210
+ }
211
+ const languages = argv.constantsLanguages.split(",").map(l => l.trim());
212
+ // Determine output directory - use config folder/constants by default, or custom path if specified
213
+ let outputDir;
214
+ if (argv.constantsOutput === "auto") {
215
+ // Default case: use config directory + constants, fallback to current directory
216
+ const configPath = controller.getAppwriteFolderPath();
217
+ outputDir = configPath
218
+ ? path.join(configPath, "constants")
219
+ : path.join(process.cwd(), "constants");
220
+ }
221
+ else {
222
+ // Custom output directory specified
223
+ outputDir = argv.constantsOutput;
224
+ }
225
+ MessageFormatter.info(`Generating constants for languages: ${languages.join(", ")}`, { prefix: "Constants" });
226
+ const generator = new ConstantsGenerator(controller.config);
227
+ await generator.generateFiles(languages, outputDir);
228
+ operationStats.generatedConstants = languages.length;
229
+ MessageFormatter.success(`Constants generated in ${outputDir}`, { prefix: "Constants" });
230
+ return;
231
+ }
189
232
  if (!controller.config) {
190
233
  MessageFormatter.error("No Appwrite connection found", undefined, { prefix: "CLI" });
191
234
  return;
@@ -0,0 +1,19 @@
1
+ import { type AppwriteConfig } from "appwrite-utils";
2
+ export type SupportedLanguage = "typescript" | "javascript" | "python" | "php" | "dart" | "json" | "env";
3
+ export declare class ConstantsGenerator {
4
+ private config;
5
+ private constants;
6
+ constructor(config: AppwriteConfig);
7
+ private extractConstants;
8
+ private toConstantName;
9
+ private toCamelCase;
10
+ private toSnakeCase;
11
+ generateTypeScript(): string;
12
+ generateJavaScript(): string;
13
+ generatePython(): string;
14
+ generatePHP(): string;
15
+ generateDart(): string;
16
+ generateJSON(): string;
17
+ generateEnv(): string;
18
+ generateFiles(languages: SupportedLanguage[], outputDir: string): Promise<void>;
19
+ }