appwrite-utils-cli 1.2.7 → 1.2.8

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.
@@ -492,6 +492,12 @@ export declare const convertYamlToAppwriteConfig: (yamlConfig: YamlConfig) => Ap
492
492
  export declare const loadYamlConfig: (configPath: string) => Promise<AppwriteConfig | null>;
493
493
  export declare const findYamlConfig: (startDir: string) => string | null;
494
494
  export declare const generateYamlConfigTemplate: (outputPath: string) => void;
495
+ /**
496
+ * Converts AppwriteConfig back to YAML format and writes to file
497
+ * @param configPath Path to the YAML config file
498
+ * @param config The AppwriteConfig to convert and save
499
+ */
500
+ export declare const writeYamlConfig: (configPath: string, config: AppwriteConfig) => Promise<void>;
495
501
  /**
496
502
  * Adds a new function to the YAML config file
497
503
  * @param configPath Path to the YAML config file
@@ -206,7 +206,7 @@ export const convertYamlToAppwriteConfig = (yamlConfig) => {
206
206
  templateBranch: func.templateBranch || "",
207
207
  specification: func.specification || "s-0.5vcpu-512mb",
208
208
  })),
209
- collections: [],
209
+ collections: [], // Note: Collections are managed separately in YAML configs via individual collection files
210
210
  };
211
211
  return appwriteConfig;
212
212
  };
@@ -397,6 +397,132 @@ export const generateYamlConfigTemplate = (outputPath) => {
397
397
  const finalContent = schemaReference + "# Appwrite Project Configuration\n" + yamlContent;
398
398
  fs.writeFileSync(outputPath, finalContent, "utf8");
399
399
  };
400
+ /**
401
+ * Converts AppwriteConfig back to YAML format and writes to file
402
+ * @param configPath Path to the YAML config file
403
+ * @param config The AppwriteConfig to convert and save
404
+ */
405
+ export const writeYamlConfig = async (configPath, config) => {
406
+ try {
407
+ // Convert AppwriteConfig back to YAML format
408
+ const yamlConfig = {
409
+ appwrite: {
410
+ endpoint: config.appwriteEndpoint,
411
+ project: config.appwriteProject,
412
+ key: config.appwriteKey,
413
+ },
414
+ logging: {
415
+ enabled: config.logging?.enabled || false,
416
+ level: config.logging?.level || "info",
417
+ directory: config.logging?.logDirectory,
418
+ console: config.logging?.console || false,
419
+ },
420
+ backups: {
421
+ enabled: config.enableBackups !== false,
422
+ interval: config.backupInterval || 3600,
423
+ retention: config.backupRetention || 30,
424
+ cleanup: config.enableBackupCleanup !== false,
425
+ },
426
+ data: {
427
+ enableMockData: config.enableMockData || false,
428
+ documentBucketId: config.documentBucketId || "documents",
429
+ usersCollectionName: config.usersCollectionName || "Members",
430
+ importDirectory: config.schemaConfig?.importDirectory || "importData",
431
+ },
432
+ schemas: {
433
+ outputDirectory: config.schemaConfig?.outputDirectory || "schemas",
434
+ yamlSchemaDirectory: config.schemaConfig?.yamlSchemaDirectory || ".yaml_schemas",
435
+ },
436
+ migrations: {
437
+ enabled: config.useMigrations !== false,
438
+ },
439
+ databases: config.databases?.map(db => ({
440
+ id: db.$id,
441
+ name: db.name,
442
+ bucket: db.bucket ? {
443
+ id: db.bucket.$id,
444
+ name: db.bucket.name,
445
+ permissions: db.bucket.permissions || [],
446
+ fileSecurity: db.bucket.fileSecurity,
447
+ enabled: db.bucket.enabled,
448
+ maximumFileSize: db.bucket.maximumFileSize,
449
+ allowedFileExtensions: db.bucket.allowedFileExtensions,
450
+ compression: db.bucket.compression,
451
+ encryption: db.bucket.encryption,
452
+ antivirus: db.bucket.antivirus,
453
+ } : undefined,
454
+ })) || [],
455
+ buckets: config.buckets?.map(bucket => ({
456
+ id: bucket.$id,
457
+ name: bucket.name,
458
+ permissions: bucket.permissions || [],
459
+ fileSecurity: bucket.fileSecurity,
460
+ enabled: bucket.enabled,
461
+ maximumFileSize: bucket.maximumFileSize,
462
+ allowedFileExtensions: bucket.allowedFileExtensions,
463
+ compression: bucket.compression,
464
+ encryption: bucket.encryption,
465
+ antivirus: bucket.antivirus,
466
+ })) || [],
467
+ functions: config.functions?.map(func => ({
468
+ id: func.$id,
469
+ name: func.name,
470
+ runtime: func.runtime,
471
+ execute: func.execute,
472
+ events: func.events,
473
+ schedule: func.schedule,
474
+ timeout: func.timeout,
475
+ enabled: func.enabled,
476
+ logging: func.logging,
477
+ entrypoint: func.entrypoint,
478
+ commands: func.commands,
479
+ scopes: func.scopes,
480
+ installationId: func.installationId,
481
+ providerRepositoryId: func.providerRepositoryId,
482
+ providerBranch: func.providerBranch,
483
+ providerSilentMode: func.providerSilentMode,
484
+ providerRootDirectory: func.providerRootDirectory,
485
+ templateRepository: func.templateRepository,
486
+ templateOwner: func.templateOwner,
487
+ templateRootDirectory: func.templateRootDirectory,
488
+ // templateBranch: func.templateBranch, // Not available in AppwriteFunction type
489
+ specification: func.specification,
490
+ })) || [],
491
+ };
492
+ // Write YAML config
493
+ const yamlContent = yaml.dump(yamlConfig, {
494
+ indent: 2,
495
+ lineWidth: 120,
496
+ sortKeys: false,
497
+ });
498
+ // Preserve schema reference if it exists
499
+ let finalContent = yamlContent;
500
+ if (fs.existsSync(configPath)) {
501
+ const existingContent = fs.readFileSync(configPath, "utf8");
502
+ const lines = existingContent.split('\n');
503
+ const schemaLine = lines.find(line => line.startsWith('# yaml-language-server:'));
504
+ const commentLine = lines.find(line => line.startsWith('# Appwrite Project Configuration'));
505
+ if (schemaLine) {
506
+ finalContent = schemaLine + '\n';
507
+ if (commentLine) {
508
+ finalContent += commentLine + '\n';
509
+ }
510
+ finalContent += yamlContent;
511
+ }
512
+ }
513
+ else {
514
+ // Add schema reference for new files
515
+ const schemaReference = "# yaml-language-server: $schema=./.yaml_schemas/appwrite-config.schema.json\n";
516
+ finalContent = schemaReference + "# Appwrite Project Configuration\n" + yamlContent;
517
+ }
518
+ fs.writeFileSync(configPath, finalContent, "utf8");
519
+ console.log(`✅ Updated YAML configuration at ${configPath}`);
520
+ }
521
+ catch (error) {
522
+ console.error("❌ Error writing YAML config:", error instanceof Error ? error.message : error);
523
+ throw error;
524
+ }
525
+ };
400
526
  /**
401
527
  * Adds a new function to the YAML config file
402
528
  * @param configPath Path to the YAML config file
@@ -7,6 +7,8 @@ export declare class SchemaGenerator {
7
7
  updateYamlCollections(): void;
8
8
  updateTsSchemas(): void;
9
9
  updateConfig(config: AppwriteConfig): void;
10
+ private updateYamlConfig;
11
+ private updateTypeScriptConfig;
10
12
  private extractRelationships;
11
13
  private addRelationship;
12
14
  generateSchemas(options?: {
@@ -155,6 +155,33 @@ export class SchemaGenerator {
155
155
  });
156
156
  }
157
157
  updateConfig(config) {
158
+ // Check if user is using YAML config
159
+ const { findYamlConfig, writeYamlConfig } = require("../config/yamlConfig.js");
160
+ const yamlConfigPath = findYamlConfig(this.appwriteFolderPath);
161
+ if (yamlConfigPath) {
162
+ // User has YAML config - update it and generate individual collection files
163
+ this.updateYamlConfig(config, yamlConfigPath);
164
+ }
165
+ else {
166
+ // User has TypeScript config - update the TS file
167
+ this.updateTypeScriptConfig(config);
168
+ }
169
+ }
170
+ async updateYamlConfig(config, yamlConfigPath) {
171
+ try {
172
+ const { writeYamlConfig } = await import("../config/yamlConfig.js");
173
+ // Write the main YAML config (without collections)
174
+ await writeYamlConfig(yamlConfigPath, config);
175
+ // Generate individual collection YAML files
176
+ this.updateYamlCollections();
177
+ console.log("✅ Updated YAML configuration and collection files");
178
+ }
179
+ catch (error) {
180
+ console.error("❌ Error updating YAML config:", error instanceof Error ? error.message : error);
181
+ throw error;
182
+ }
183
+ }
184
+ updateTypeScriptConfig(config) {
158
185
  const configPath = path.join(this.appwriteFolderPath, "appwriteConfig.ts");
159
186
  const configContent = `import { type AppwriteConfig } from "appwrite-utils";
160
187
 
@@ -175,7 +202,7 @@ const appwriteConfig: AppwriteConfig = {
175
202
  $id: func.$id || ulid(),
176
203
  name: func.name,
177
204
  runtime: func.runtime,
178
- dirPath: func.dirPath || `functions/${func.name}`,
205
+ dirPath: func.dirPath || "functions/" + func.name,
179
206
  entrypoint: func.entrypoint || "src/index.ts",
180
207
  execute: func.execute || [],
181
208
  events: func.events || [],
@@ -191,12 +218,14 @@ const appwriteConfig: AppwriteConfig = {
191
218
  providerSilentMode: func.providerSilentMode,
192
219
  providerRootDirectory: func.providerRootDirectory,
193
220
  specification: func.specification,
194
- })), null, 4)}
221
+ })), null, 4)},
222
+ collections: ${JSON.stringify(config.collections, null, 4)}
195
223
  };
196
224
 
197
225
  export default appwriteConfig;
198
226
  `;
199
227
  fs.writeFileSync(configPath, configContent, { encoding: "utf-8" });
228
+ console.log("✅ Updated TypeScript configuration file");
200
229
  }
201
230
  extractRelationships() {
202
231
  if (!this.config.collections) {
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.2.7",
4
+ "version": "1.2.8",
5
5
  "main": "src/main.ts",
6
6
  "type": "module",
7
7
  "repository": {
@@ -216,7 +216,7 @@ export const convertYamlToAppwriteConfig = (yamlConfig: YamlConfig): AppwriteCon
216
216
  templateBranch: func.templateBranch || "",
217
217
  specification: func.specification || "s-0.5vcpu-512mb",
218
218
  })),
219
- collections: [],
219
+ collections: [], // Note: Collections are managed separately in YAML configs via individual collection files
220
220
  };
221
221
 
222
222
  return appwriteConfig;
@@ -427,6 +427,135 @@ export const generateYamlConfigTemplate = (outputPath: string) => {
427
427
  fs.writeFileSync(outputPath, finalContent, "utf8");
428
428
  };
429
429
 
430
+ /**
431
+ * Converts AppwriteConfig back to YAML format and writes to file
432
+ * @param configPath Path to the YAML config file
433
+ * @param config The AppwriteConfig to convert and save
434
+ */
435
+ export const writeYamlConfig = async (configPath: string, config: AppwriteConfig): Promise<void> => {
436
+ try {
437
+ // Convert AppwriteConfig back to YAML format
438
+ const yamlConfig: YamlConfig = {
439
+ appwrite: {
440
+ endpoint: config.appwriteEndpoint,
441
+ project: config.appwriteProject,
442
+ key: config.appwriteKey,
443
+ },
444
+ logging: {
445
+ enabled: config.logging?.enabled || false,
446
+ level: config.logging?.level || "info",
447
+ directory: config.logging?.logDirectory,
448
+ console: config.logging?.console || false,
449
+ },
450
+ backups: {
451
+ enabled: config.enableBackups !== false,
452
+ interval: config.backupInterval || 3600,
453
+ retention: config.backupRetention || 30,
454
+ cleanup: config.enableBackupCleanup !== false,
455
+ },
456
+ data: {
457
+ enableMockData: config.enableMockData || false,
458
+ documentBucketId: config.documentBucketId || "documents",
459
+ usersCollectionName: config.usersCollectionName || "Members",
460
+ importDirectory: config.schemaConfig?.importDirectory || "importData",
461
+ },
462
+ schemas: {
463
+ outputDirectory: config.schemaConfig?.outputDirectory || "schemas",
464
+ yamlSchemaDirectory: config.schemaConfig?.yamlSchemaDirectory || ".yaml_schemas",
465
+ },
466
+ migrations: {
467
+ enabled: config.useMigrations !== false,
468
+ },
469
+ databases: config.databases?.map(db => ({
470
+ id: db.$id,
471
+ name: db.name,
472
+ bucket: db.bucket ? {
473
+ id: db.bucket.$id,
474
+ name: db.bucket.name,
475
+ permissions: db.bucket.permissions || [],
476
+ fileSecurity: db.bucket.fileSecurity,
477
+ enabled: db.bucket.enabled,
478
+ maximumFileSize: db.bucket.maximumFileSize,
479
+ allowedFileExtensions: db.bucket.allowedFileExtensions,
480
+ compression: db.bucket.compression as "none" | "gzip" | "zstd",
481
+ encryption: db.bucket.encryption,
482
+ antivirus: db.bucket.antivirus,
483
+ } : undefined,
484
+ })) || [],
485
+ buckets: config.buckets?.map(bucket => ({
486
+ id: bucket.$id,
487
+ name: bucket.name,
488
+ permissions: bucket.permissions || [],
489
+ fileSecurity: bucket.fileSecurity,
490
+ enabled: bucket.enabled,
491
+ maximumFileSize: bucket.maximumFileSize,
492
+ allowedFileExtensions: bucket.allowedFileExtensions,
493
+ compression: bucket.compression as "none" | "gzip" | "zstd",
494
+ encryption: bucket.encryption,
495
+ antivirus: bucket.antivirus,
496
+ })) || [],
497
+ functions: config.functions?.map(func => ({
498
+ id: func.$id,
499
+ name: func.name,
500
+ runtime: func.runtime,
501
+ execute: func.execute,
502
+ events: func.events,
503
+ schedule: func.schedule,
504
+ timeout: func.timeout,
505
+ enabled: func.enabled,
506
+ logging: func.logging,
507
+ entrypoint: func.entrypoint,
508
+ commands: func.commands,
509
+ scopes: func.scopes,
510
+ installationId: func.installationId,
511
+ providerRepositoryId: func.providerRepositoryId,
512
+ providerBranch: func.providerBranch,
513
+ providerSilentMode: func.providerSilentMode,
514
+ providerRootDirectory: func.providerRootDirectory,
515
+ templateRepository: func.templateRepository,
516
+ templateOwner: func.templateOwner,
517
+ templateRootDirectory: func.templateRootDirectory,
518
+ // templateBranch: func.templateBranch, // Not available in AppwriteFunction type
519
+ specification: func.specification,
520
+ })) || [],
521
+ };
522
+
523
+ // Write YAML config
524
+ const yamlContent = yaml.dump(yamlConfig, {
525
+ indent: 2,
526
+ lineWidth: 120,
527
+ sortKeys: false,
528
+ });
529
+
530
+ // Preserve schema reference if it exists
531
+ let finalContent = yamlContent;
532
+ if (fs.existsSync(configPath)) {
533
+ const existingContent = fs.readFileSync(configPath, "utf8");
534
+ const lines = existingContent.split('\n');
535
+ const schemaLine = lines.find(line => line.startsWith('# yaml-language-server:'));
536
+ const commentLine = lines.find(line => line.startsWith('# Appwrite Project Configuration'));
537
+
538
+ if (schemaLine) {
539
+ finalContent = schemaLine + '\n';
540
+ if (commentLine) {
541
+ finalContent += commentLine + '\n';
542
+ }
543
+ finalContent += yamlContent;
544
+ }
545
+ } else {
546
+ // Add schema reference for new files
547
+ const schemaReference = "# yaml-language-server: $schema=./.yaml_schemas/appwrite-config.schema.json\n";
548
+ finalContent = schemaReference + "# Appwrite Project Configuration\n" + yamlContent;
549
+ }
550
+
551
+ fs.writeFileSync(configPath, finalContent, "utf8");
552
+ console.log(`✅ Updated YAML configuration at ${configPath}`);
553
+ } catch (error) {
554
+ console.error("❌ Error writing YAML config:", error instanceof Error ? error.message : error);
555
+ throw error;
556
+ }
557
+ };
558
+
430
559
  /**
431
560
  * Adds a new function to the YAML config file
432
561
  * @param configPath Path to the YAML config file
@@ -198,6 +198,37 @@ export class SchemaGenerator {
198
198
  }
199
199
 
200
200
  public updateConfig(config: AppwriteConfig): void {
201
+ // Check if user is using YAML config
202
+ const { findYamlConfig, writeYamlConfig } = require("../config/yamlConfig.js");
203
+ const yamlConfigPath = findYamlConfig(this.appwriteFolderPath);
204
+
205
+ if (yamlConfigPath) {
206
+ // User has YAML config - update it and generate individual collection files
207
+ this.updateYamlConfig(config, yamlConfigPath);
208
+ } else {
209
+ // User has TypeScript config - update the TS file
210
+ this.updateTypeScriptConfig(config);
211
+ }
212
+ }
213
+
214
+ private async updateYamlConfig(config: AppwriteConfig, yamlConfigPath: string): Promise<void> {
215
+ try {
216
+ const { writeYamlConfig } = await import("../config/yamlConfig.js");
217
+
218
+ // Write the main YAML config (without collections)
219
+ await writeYamlConfig(yamlConfigPath, config);
220
+
221
+ // Generate individual collection YAML files
222
+ this.updateYamlCollections();
223
+
224
+ console.log("✅ Updated YAML configuration and collection files");
225
+ } catch (error) {
226
+ console.error("❌ Error updating YAML config:", error instanceof Error ? error.message : error);
227
+ throw error;
228
+ }
229
+ }
230
+
231
+ private updateTypeScriptConfig(config: AppwriteConfig): void {
201
232
  const configPath = path.join(this.appwriteFolderPath, "appwriteConfig.ts");
202
233
  const configContent = `import { type AppwriteConfig } from "appwrite-utils";
203
234
 
@@ -219,7 +250,7 @@ const appwriteConfig: AppwriteConfig = {
219
250
  $id: func.$id || ulid(),
220
251
  name: func.name,
221
252
  runtime: func.runtime,
222
- dirPath: func.dirPath || `functions/${func.name}`,
253
+ dirPath: func.dirPath || "functions/" + func.name,
223
254
  entrypoint: func.entrypoint || "src/index.ts",
224
255
  execute: func.execute || [],
225
256
  events: func.events || [],
@@ -238,12 +269,14 @@ const appwriteConfig: AppwriteConfig = {
238
269
  })),
239
270
  null,
240
271
  4
241
- )}
272
+ )},
273
+ collections: ${JSON.stringify(config.collections, null, 4)}
242
274
  };
243
275
 
244
276
  export default appwriteConfig;
245
277
  `;
246
278
  fs.writeFileSync(configPath, configContent, { encoding: "utf-8" });
279
+ console.log("✅ Updated TypeScript configuration file");
247
280
  }
248
281
 
249
282
  private extractRelationships(): void {
@@ -128,4 +128,5 @@ export function sanitizeFilename(name: string): string {
128
128
  */
129
129
  export function getCollectionYamlFilename(collection: Collection | CollectionCreate): string {
130
130
  return `${sanitizeFilename(collection.name)}.yaml`;
131
- }
131
+ }
132
+