appwrite-utils-cli 1.8.2 → 1.8.5

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/README.md +42 -13
  3. package/dist/adapters/TablesDBAdapter.js +1 -1
  4. package/dist/cli/commands/functionCommands.js +30 -3
  5. package/dist/cli/commands/schemaCommands.js +39 -4
  6. package/dist/cli/commands/storageCommands.d.ts +5 -0
  7. package/dist/cli/commands/storageCommands.js +143 -0
  8. package/dist/collections/attributes.js +7 -7
  9. package/dist/collections/methods.js +1 -1
  10. package/dist/collections/tableOperations.js +2 -2
  11. package/dist/interactiveCLI.d.ts +1 -0
  12. package/dist/interactiveCLI.js +30 -0
  13. package/dist/main.js +17 -0
  14. package/dist/migrations/appwriteToX.js +1 -1
  15. package/dist/migrations/yaml/generateImportSchemas.js +2 -2
  16. package/dist/setupCommands.js +6 -0
  17. package/dist/shared/attributeMapper.js +2 -2
  18. package/dist/shared/jsonSchemaGenerator.js +3 -1
  19. package/dist/shared/pydanticModelGenerator.d.ts +17 -0
  20. package/dist/shared/pydanticModelGenerator.js +615 -0
  21. package/dist/shared/schemaGenerator.d.ts +3 -2
  22. package/dist/shared/schemaGenerator.js +22 -9
  23. package/dist/storage/methods.js +50 -7
  24. package/dist/utils/configDiscovery.js +2 -3
  25. package/dist/utils/constantsGenerator.d.ts +20 -8
  26. package/dist/utils/constantsGenerator.js +37 -25
  27. package/dist/utils/projectConfig.js +1 -1
  28. package/dist/utils/yamlConverter.d.ts +2 -2
  29. package/dist/utils/yamlConverter.js +2 -2
  30. package/package.json +1 -1
  31. package/src/adapters/TablesDBAdapter.ts +1 -1
  32. package/src/cli/commands/functionCommands.ts +28 -3
  33. package/src/cli/commands/schemaCommands.ts +59 -22
  34. package/src/cli/commands/storageCommands.ts +152 -0
  35. package/src/collections/attributes.ts +7 -7
  36. package/src/collections/methods.ts +7 -7
  37. package/src/collections/tableOperations.ts +2 -2
  38. package/src/interactiveCLI.ts +42 -12
  39. package/src/main.ts +32 -9
  40. package/src/migrations/appwriteToX.ts +1 -1
  41. package/src/migrations/yaml/generateImportSchemas.ts +7 -7
  42. package/src/setupCommands.ts +6 -0
  43. package/src/shared/attributeMapper.ts +2 -2
  44. package/src/shared/jsonSchemaGenerator.ts +4 -2
  45. package/src/shared/pydanticModelGenerator.ts +618 -0
  46. package/src/shared/schemaGenerator.ts +38 -25
  47. package/src/storage/methods.ts +67 -23
  48. package/src/utils/configDiscovery.ts +40 -41
  49. package/src/utils/constantsGenerator.ts +43 -26
  50. package/src/utils/projectConfig.ts +11 -11
  51. package/src/utils/yamlConverter.ts +40 -40
@@ -325,8 +325,8 @@ const createAttributeViaAdapter = async (
325
325
  ...((attribute as any).size && { size: (attribute as any).size }),
326
326
  ...((attribute as any).xdefault !== undefined &&
327
327
  !attribute.required && { default: (attribute as any).xdefault }),
328
- ...((attribute as any).encrypted && {
329
- encrypt: (attribute as any).encrypted,
328
+ ...((attribute as any).encrypt && {
329
+ encrypt: (attribute as any).encrypt,
330
330
  }),
331
331
  ...((attribute as any).min !== undefined && {
332
332
  min: (attribute as any).min,
@@ -408,7 +408,7 @@ const updateAttributeViaAdapter = async (
408
408
  size: (attribute as any).size,
409
409
  min: (attribute as any).min,
410
410
  max: (attribute as any).max,
411
- encrypt: (attribute as any).encrypted ?? (attribute as any).encrypt,
411
+ encrypt: (attribute as any).encrypt,
412
412
  elements: (attribute as any).elements,
413
413
  relatedCollection: (attribute as any).relatedCollection,
414
414
  relationType: (attribute as any).relationType,
@@ -458,7 +458,7 @@ const createLegacyAttribute = async (
458
458
  ? (attribute as any).xdefault
459
459
  : undefined,
460
460
  array: attribute.array || false,
461
- encrypted: (attribute as any).encrypted,
461
+ encrypt: (attribute as any).encrypt,
462
462
  };
463
463
  logger.debug(`Creating string attribute '${attribute.key}'`, {
464
464
  ...stringParams,
@@ -472,7 +472,7 @@ const createLegacyAttribute = async (
472
472
  stringParams.required,
473
473
  stringParams.defaultValue,
474
474
  stringParams.array,
475
- stringParams.encrypted
475
+ stringParams.encrypt
476
476
  );
477
477
  break;
478
478
  case "integer":
@@ -1055,7 +1055,7 @@ const getComparableFields = (type: string): string[] => {
1055
1055
 
1056
1056
  switch (type) {
1057
1057
  case "string":
1058
- return [...baseFields, "size", "encrypted"];
1058
+ return [...baseFields, "size", "encrypt"];
1059
1059
 
1060
1060
  case "integer":
1061
1061
  case "double":
@@ -1088,7 +1088,7 @@ const getComparableFields = (type: string): string[] => {
1088
1088
  "key",
1089
1089
  "type",
1090
1090
  "array",
1091
- "encrypted",
1091
+ "encrypt",
1092
1092
  "required",
1093
1093
  "size",
1094
1094
  "min",
@@ -176,13 +176,13 @@ export const fetchAndCacheCollectionByName = async (
176
176
  }
177
177
  };
178
178
 
179
- export const generateSchemas = async (
180
- config: AppwriteConfig,
181
- appwriteFolderPath: string
182
- ): Promise<void> => {
183
- const schemaGenerator = new SchemaGenerator(config, appwriteFolderPath);
184
- schemaGenerator.generateSchemas();
185
- };
179
+ export const generateSchemas = async (
180
+ config: AppwriteConfig,
181
+ appwriteFolderPath: string
182
+ ): Promise<void> => {
183
+ const schemaGenerator = new SchemaGenerator(config, appwriteFolderPath);
184
+ await schemaGenerator.generateSchemas();
185
+ };
186
186
 
187
187
  export const createOrUpdateCollections = async (
188
188
  database: Databases,
@@ -115,7 +115,7 @@ export function normalizeAttributeToComparable(attr: Attribute): ComparableColum
115
115
 
116
116
  if (t === 'string') {
117
117
  base.size = (attr as any).size ?? 255;
118
- base.encrypt = !!((attr as any).encrypted ?? (attr as any).encrypt);
118
+ base.encrypt = !!((attr as any).encrypt);
119
119
  }
120
120
  if (t === 'integer' || t === 'float' || t === 'double') {
121
121
  const min = toNumber((attr as any).min);
@@ -261,7 +261,7 @@ function compareColumnProperties(
261
261
  const getNewVal = (prop: string) => {
262
262
  const na = newAttribute as any;
263
263
  if (prop === 'default') return na.xdefault;
264
- if (prop === 'encrypt') return na.encrypted ?? na.encrypt;
264
+ if (prop === 'encrypt') return na.encrypt;
265
265
  return na[prop];
266
266
  };
267
267
  const getOldVal = (prop: string) => {
@@ -42,11 +42,12 @@ import { findYamlConfig } from "./config/yamlConfig.js";
42
42
  // Import command modules
43
43
  import { configCommands } from "./cli/commands/configCommands.js";
44
44
  import { databaseCommands } from "./cli/commands/databaseCommands.js";
45
- import { functionCommands } from "./cli/commands/functionCommands.js";
45
+ import { functionCommands } from "./cli/commands/functionCommands.js";
46
+ import { storageCommands } from "./cli/commands/storageCommands.js";
46
47
  import { transferCommands } from "./cli/commands/transferCommands.js";
47
48
  import { schemaCommands } from "./cli/commands/schemaCommands.js";
48
49
 
49
- enum CHOICES {
50
+ enum CHOICES {
50
51
  MIGRATE_CONFIG = "🔄 Migrate TypeScript config to YAML (.appwrite structure)",
51
52
  VALIDATE_CONFIG = "✅ Validate configuration (collections/tables conflicts)",
52
53
  MIGRATE_COLLECTIONS_TO_TABLES = "🔀 Migrate collections to tables format",
@@ -67,11 +68,12 @@ enum CHOICES {
67
68
  GENERATE_CONSTANTS = "📋 Generate cross-language constants (TypeScript, Python, PHP, Dart, etc.)",
68
69
  IMPORT_DATA = "📥 Import data",
69
70
  RELOAD_CONFIG = "🔄 Reload configuration files",
70
- UPDATE_FUNCTION_SPEC = "⚙️ Update function specifications",
71
- EXIT = "👋 Exit",
72
- }
71
+ UPDATE_FUNCTION_SPEC = "⚙️ Update function specifications",
72
+ MANAGE_BUCKETS = "🪣 Manage storage buckets",
73
+ EXIT = "👋 Exit",
74
+ }
73
75
 
74
- export class InteractiveCLI {
76
+ export class InteractiveCLI {
75
77
  private controller: UtilsController | undefined;
76
78
  private isUsingTypeScriptConfig: boolean = false;
77
79
 
@@ -180,10 +182,13 @@ export class InteractiveCLI {
180
182
  case CHOICES.RELOAD_CONFIG:
181
183
  await configCommands.reloadConfigWithSessionPreservation(this);
182
184
  break;
183
- case CHOICES.UPDATE_FUNCTION_SPEC:
184
- await this.initControllerIfNeeded();
185
- await functionCommands.updateFunctionSpec(this);
186
- break;
185
+ case CHOICES.UPDATE_FUNCTION_SPEC:
186
+ await this.initControllerIfNeeded();
187
+ await functionCommands.updateFunctionSpec(this);
188
+ break;
189
+ case CHOICES.MANAGE_BUCKETS:
190
+ await this.manageBuckets();
191
+ break;
187
192
  case CHOICES.EXIT:
188
193
  MessageFormatter.success("Goodbye!");
189
194
  process.exit(0);
@@ -191,7 +196,7 @@ export class InteractiveCLI {
191
196
  }
192
197
  }
193
198
 
194
- private async initControllerIfNeeded(directConfig?: {
199
+ private async initControllerIfNeeded(directConfig?: {
195
200
  appwriteEndpoint: string;
196
201
  appwriteProject: string;
197
202
  appwriteKey: string;
@@ -222,7 +227,32 @@ export class InteractiveCLI {
222
227
  }
223
228
  // If no directConfig provided, keep existing controller
224
229
  }
225
- }
230
+ }
231
+
232
+ private async manageBuckets(): Promise<void> {
233
+ await this.initControllerIfNeeded();
234
+ while (true) {
235
+ const { action } = await inquirer.prompt([
236
+ {
237
+ type: 'list',
238
+ name: 'action',
239
+ message: chalk.blue('Bucket management'),
240
+ choices: [
241
+ { name: 'Create bucket', value: 'create' },
242
+ { name: 'Delete buckets', value: 'delete' },
243
+ { name: 'Back', value: 'back' },
244
+ ],
245
+ },
246
+ ]);
247
+
248
+ if (action === 'back') break;
249
+ if (action === 'create') {
250
+ await storageCommands.createBucket(this);
251
+ } else if (action === 'delete') {
252
+ await storageCommands.deleteBuckets(this);
253
+ }
254
+ }
255
+ }
226
256
 
227
257
  private async selectDatabases(
228
258
  databases: Models.Database[],
package/src/main.ts CHANGED
@@ -41,7 +41,7 @@ if (!(globalThis as any).require) {
41
41
  (globalThis as any).require = require;
42
42
  }
43
43
 
44
- interface CliOptions {
44
+ interface CliOptions {
45
45
  config?: string;
46
46
  it?: boolean;
47
47
  dbIds?: string;
@@ -86,8 +86,13 @@ interface CliOptions {
86
86
  session?: string;
87
87
  listBackups?: boolean;
88
88
  autoSync?: boolean;
89
- selectBuckets?: boolean;
90
- }
89
+ selectBuckets?: boolean;
90
+ // New schema/constant CLI flags
91
+ generateSchemas?: boolean;
92
+ schemaFormat?: 'zod' | 'json' | 'pydantic' | 'both' | 'all';
93
+ schemaOutDir?: string;
94
+ constantsInclude?: string;
95
+ }
91
96
 
92
97
  type ParsedArgv = ArgumentsCamelCase<CliOptions>;
93
98
 
@@ -567,12 +572,30 @@ const argv = yargs(hideBin(process.argv))
567
572
  "Comma-separated list of languages for constants (typescript,javascript,python,php,dart,json,env)",
568
573
  default: "typescript",
569
574
  })
570
- .option("constantsOutput", {
571
- type: "string",
572
- description:
573
- "Output directory for generated constants files (default: config-folder/constants)",
574
- default: "auto",
575
- })
575
+ .option("constantsOutput", {
576
+ type: "string",
577
+ description:
578
+ "Output directory for generated constants files (default: config-folder/constants)",
579
+ default: "auto",
580
+ })
581
+ .option("constantsInclude", {
582
+ type: "string",
583
+ description:
584
+ "Comma-separated categories to include: databases,collections,buckets,functions",
585
+ })
586
+ .option("generateSchemas", {
587
+ type: "boolean",
588
+ description: "Generate schemas/models without interactive prompts",
589
+ })
590
+ .option("schemaFormat", {
591
+ type: "string",
592
+ choices: ["zod", "json", "pydantic", "both", "all"],
593
+ description: "Schema format: zod, json, pydantic, both (zod+json), or all",
594
+ })
595
+ .option("schemaOutDir", {
596
+ type: "string",
597
+ description: "Output directory for generated schemas (absolute path respected)",
598
+ })
576
599
  .option("migrateCollectionsToTables", {
577
600
  alias: ["migrate-collections"],
578
601
  type: "boolean",
@@ -638,7 +638,7 @@ export class AppwriteToX {
638
638
  }
639
639
 
640
640
  MessageFormatter.info("Generating Zod schemas from synced collections...", { prefix: "Migration" });
641
- generator.generateSchemas();
641
+ await generator.generateSchemas();
642
642
  MessageFormatter.success("Sync-from-Appwrite process completed successfully", { prefix: "Migration" });
643
643
  } catch (error) {
644
644
  MessageFormatter.error(
@@ -562,12 +562,12 @@ export function generateTableSchema(): any {
562
562
  // Add column definition (similar to attribute but with table terminology)
563
563
  tableSchema.$defs.column = JSON.parse(JSON.stringify(tableSchema.$defs.attribute));
564
564
 
565
- // Add encrypted property (table-specific feature)
566
- tableSchema.$defs.column.properties.encrypted = {
567
- "type": "boolean",
568
- "description": "Whether the column should be encrypted",
569
- "default": false
570
- };
565
+ // Add encrypt property (table-specific feature)
566
+ tableSchema.$defs.column.properties.encrypt = {
567
+ "type": "boolean",
568
+ "description": "Whether the column should be encrypted",
569
+ "default": false
570
+ };
571
571
 
572
572
  // Replace relatedCollection with relatedTable for table terminology
573
573
  delete tableSchema.$defs.column.properties.relatedCollection;
@@ -1351,4 +1351,4 @@ options:
1351
1351
  fs.writeFileSync(examplePath, example.content);
1352
1352
  logger.info(`Created import example: ${examplePath}`);
1353
1353
  }
1354
- }
1354
+ }
@@ -328,6 +328,12 @@ export function createYamlValidationSchema(
328
328
  "default": false,
329
329
  "description": `Whether the ${useTables ? 'column' : 'attribute'} is an array`
330
330
  },
331
+ // Encryption flag for string types
332
+ "encrypt": {
333
+ "type": "boolean",
334
+ "default": false,
335
+ "description": `Enable encryption for string ${useTables ? 'columns' : 'attributes'}`
336
+ },
331
337
  ...(useTables ? {
332
338
  "unique": {
333
339
  "type": "boolean",
@@ -20,7 +20,7 @@ export function mapToCreateAttributeParams(
20
20
  const required = !!(attr as any).required;
21
21
  const array = !!(attr as any).array;
22
22
  const xdefault = (attr as any).xdefault;
23
- const encrypt = (attr as any).encrypted ?? (attr as any).encrypt;
23
+ const encrypt = (attr as any).encrypt;
24
24
 
25
25
  // Numeric helpers
26
26
  const rawMin = ensureNumber((attr as any).min);
@@ -184,7 +184,7 @@ export function mapToUpdateAttributeParams(
184
184
  }
185
185
  setIfDefined("array", (attr as any).array);
186
186
  // encrypt only applies to string types
187
- if (type === "string") setIfDefined("encrypt", (attr as any).encrypted ?? (attr as any).encrypt);
187
+ if (type === "string") setIfDefined("encrypt", (attr as any).encrypt);
188
188
 
189
189
  // Numeric normalization
190
190
  const toNum = (n: any) => (n === null || n === undefined ? undefined : (Number(n)));
@@ -236,7 +236,7 @@ export class JsonSchemaGenerator {
236
236
  outputDirectory?: string;
237
237
  verbose?: boolean;
238
238
  } = {}): void {
239
- const { outputFormat = "both", outputDirectory = "schemas", verbose = false } = options;
239
+ const { outputFormat = "both", outputDirectory = "schemas", verbose = false } = options;
240
240
 
241
241
  if (!this.config.collections) {
242
242
  if (verbose) {
@@ -246,7 +246,9 @@ export class JsonSchemaGenerator {
246
246
  }
247
247
 
248
248
  // Create JSON schemas directory using provided outputDirectory
249
- const jsonSchemasPath = path.join(this.appwriteFolderPath, outputDirectory);
249
+ const jsonSchemasPath = path.isAbsolute(outputDirectory)
250
+ ? outputDirectory
251
+ : path.join(this.appwriteFolderPath, outputDirectory);
250
252
  if (!fs.existsSync(jsonSchemasPath)) {
251
253
  fs.mkdirSync(jsonSchemasPath, { recursive: true });
252
254
  }