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.
- package/CHANGELOG.md +6 -1
- package/README.md +42 -13
- package/dist/adapters/TablesDBAdapter.js +1 -1
- package/dist/cli/commands/functionCommands.js +30 -3
- package/dist/cli/commands/schemaCommands.js +39 -4
- package/dist/cli/commands/storageCommands.d.ts +5 -0
- package/dist/cli/commands/storageCommands.js +143 -0
- package/dist/collections/attributes.js +7 -7
- package/dist/collections/methods.js +1 -1
- package/dist/collections/tableOperations.js +2 -2
- package/dist/interactiveCLI.d.ts +1 -0
- package/dist/interactiveCLI.js +30 -0
- package/dist/main.js +17 -0
- package/dist/migrations/appwriteToX.js +1 -1
- package/dist/migrations/yaml/generateImportSchemas.js +2 -2
- package/dist/setupCommands.js +6 -0
- package/dist/shared/attributeMapper.js +2 -2
- package/dist/shared/jsonSchemaGenerator.js +3 -1
- package/dist/shared/pydanticModelGenerator.d.ts +17 -0
- package/dist/shared/pydanticModelGenerator.js +615 -0
- package/dist/shared/schemaGenerator.d.ts +3 -2
- package/dist/shared/schemaGenerator.js +22 -9
- package/dist/storage/methods.js +50 -7
- package/dist/utils/configDiscovery.js +2 -3
- package/dist/utils/constantsGenerator.d.ts +20 -8
- package/dist/utils/constantsGenerator.js +37 -25
- package/dist/utils/projectConfig.js +1 -1
- package/dist/utils/yamlConverter.d.ts +2 -2
- package/dist/utils/yamlConverter.js +2 -2
- package/package.json +1 -1
- package/src/adapters/TablesDBAdapter.ts +1 -1
- package/src/cli/commands/functionCommands.ts +28 -3
- package/src/cli/commands/schemaCommands.ts +59 -22
- package/src/cli/commands/storageCommands.ts +152 -0
- package/src/collections/attributes.ts +7 -7
- package/src/collections/methods.ts +7 -7
- package/src/collections/tableOperations.ts +2 -2
- package/src/interactiveCLI.ts +42 -12
- package/src/main.ts +32 -9
- package/src/migrations/appwriteToX.ts +1 -1
- package/src/migrations/yaml/generateImportSchemas.ts +7 -7
- package/src/setupCommands.ts +6 -0
- package/src/shared/attributeMapper.ts +2 -2
- package/src/shared/jsonSchemaGenerator.ts +4 -2
- package/src/shared/pydanticModelGenerator.ts +618 -0
- package/src/shared/schemaGenerator.ts +38 -25
- package/src/storage/methods.ts +67 -23
- package/src/utils/configDiscovery.ts +40 -41
- package/src/utils/constantsGenerator.ts +43 -26
- package/src/utils/projectConfig.ts +11 -11
- 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).
|
|
329
|
-
encrypt: (attribute as any).
|
|
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).
|
|
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
|
-
|
|
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.
|
|
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", "
|
|
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
|
-
"
|
|
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).
|
|
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.
|
|
264
|
+
if (prop === 'encrypt') return na.encrypt;
|
|
265
265
|
return na[prop];
|
|
266
266
|
};
|
|
267
267
|
const getOldVal = (prop: string) => {
|
package/src/interactiveCLI.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
566
|
-
tableSchema.$defs.column.properties.
|
|
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
|
+
}
|
package/src/setupCommands.ts
CHANGED
|
@@ -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).
|
|
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).
|
|
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.
|
|
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
|
}
|