appwrite-utils-cli 0.9.2 → 0.9.4

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
@@ -80,6 +80,7 @@ Available options:
80
80
  - `--remoteEndpoint`: Set the remote Appwrite endpoint for transfers
81
81
  - `--remoteProjectId`: Set the remote Appwrite project ID for transfers
82
82
  - `--remoteApiKey`: Set the remote Appwrite API key for transfers
83
+ - `--setup`: Create setup files
83
84
 
84
85
  ## Examples
85
86
 
@@ -123,7 +124,8 @@ This updated CLI ensures that developers have robust tools at their fingertips t
123
124
 
124
125
  ## Changelog
125
126
 
126
- - 0.9.3: Fixed deployment error
127
+ - 0.9.4: Fixed migrations database ensuring it has the required collections
128
+ - 0.9.3: Fixed deployment error && fix lack of existing `appwriteConfig.ts` file from causing error (you want to be able to setup yeah? haha)
127
129
  - 0.9.2: Added changelog back, whoops
128
130
  - 0.0.90: Updated README with new command-line options and fixed alias issues
129
131
  - 0.0.74: Added `--backup` support, even if only one database
@@ -1,8 +1,9 @@
1
- import { UtilsController } from "./utilsController.js";
2
1
  export declare class InteractiveCLI {
2
+ private currentDir;
3
3
  private controller;
4
- constructor(currentDir?: string, utilsController?: UtilsController);
4
+ constructor(currentDir: string);
5
5
  run(): Promise<void>;
6
+ private initControllerIfNeeded;
6
7
  private selectDatabases;
7
8
  private selectCollections;
8
9
  private selectBuckets;
@@ -22,22 +22,14 @@ var CHOICES;
22
22
  CHOICES["EXIT"] = "Exit";
23
23
  })(CHOICES || (CHOICES = {}));
24
24
  export class InteractiveCLI {
25
+ currentDir;
25
26
  controller;
26
- constructor(currentDir, utilsController) {
27
- if (utilsController) {
28
- this.controller = utilsController;
29
- }
30
- else if (currentDir) {
31
- this.controller = new UtilsController(currentDir);
32
- }
33
- else {
34
- throw new Error("Current directory or utils controller is required");
35
- }
27
+ constructor(currentDir) {
28
+ this.currentDir = currentDir;
36
29
  }
37
30
  async run() {
38
31
  console.log("Welcome to Appwrite Utils CLI Tool by Zach Handley");
39
32
  console.log("For more information, visit https://github.com/zachhandley/appwrite-utils");
40
- await this.controller.init();
41
33
  while (true) {
42
34
  const { action } = await inquirer.prompt([
43
35
  {
@@ -52,30 +44,37 @@ export class InteractiveCLI {
52
44
  await this.createCollectionConfig();
53
45
  break;
54
46
  case CHOICES.SETUP_DIRS_FILES:
55
- await setupDirsFiles(false);
47
+ await setupDirsFiles(false, this.currentDir);
56
48
  break;
57
49
  case CHOICES.SETUP_DIRS_FILES_WITH_EXAMPLE_DATA:
58
- await setupDirsFiles(true);
50
+ await setupDirsFiles(true, this.currentDir);
59
51
  break;
60
52
  case CHOICES.SYNCHRONIZE_CONFIGURATIONS:
53
+ await this.initControllerIfNeeded();
61
54
  await this.synchronizeConfigurations();
62
55
  break;
63
56
  case CHOICES.SYNC_DB:
57
+ await this.initControllerIfNeeded();
64
58
  await this.syncDb();
65
59
  break;
66
60
  case CHOICES.TRANSFER_DATA:
61
+ await this.initControllerIfNeeded();
67
62
  await this.transferData();
68
63
  break;
69
64
  case CHOICES.BACKUP_DATABASE:
65
+ await this.initControllerIfNeeded();
70
66
  await this.backupDatabase();
71
67
  break;
72
68
  case CHOICES.WIPE_DATABASE:
69
+ await this.initControllerIfNeeded();
73
70
  await this.wipeDatabase();
74
71
  break;
75
72
  case CHOICES.GENERATE_SCHEMAS:
73
+ await this.initControllerIfNeeded();
76
74
  await this.generateSchemas();
77
75
  break;
78
76
  case CHOICES.IMPORT_DATA:
77
+ await this.initControllerIfNeeded();
79
78
  await this.importData();
80
79
  break;
81
80
  case CHOICES.EXIT:
@@ -84,12 +83,14 @@ export class InteractiveCLI {
84
83
  }
85
84
  }
86
85
  }
86
+ async initControllerIfNeeded() {
87
+ if (!this.controller) {
88
+ this.controller = new UtilsController(this.currentDir);
89
+ await this.controller.init();
90
+ }
91
+ }
87
92
  async selectDatabases(databases, message, multiSelect = true) {
88
93
  const choices = databases.map((db) => ({ name: db.name, value: db }));
89
- if (multiSelect) {
90
- choices.unshift({ name: "Select All", value: "ALL" });
91
- choices.push({ name: "Clear Selection", value: "CLEAR" });
92
- }
93
94
  const { selectedDatabases } = await inquirer.prompt([
94
95
  {
95
96
  type: multiSelect ? "checkbox" : "list",
@@ -100,15 +101,7 @@ export class InteractiveCLI {
100
101
  pageSize: 10,
101
102
  },
102
103
  ]);
103
- if (multiSelect) {
104
- if (selectedDatabases.includes("ALL")) {
105
- return databases;
106
- }
107
- else if (selectedDatabases.includes("CLEAR")) {
108
- return [];
109
- }
110
- }
111
- return selectedDatabases.filter((db) => typeof db !== "string");
104
+ return selectedDatabases;
112
105
  }
113
106
  async selectCollections(database, databasesClient, message, multiSelect = true) {
114
107
  const collections = await fetchAllCollections(database.$id, databasesClient);
@@ -116,10 +109,6 @@ export class InteractiveCLI {
116
109
  name: collection.name,
117
110
  value: collection,
118
111
  }));
119
- if (multiSelect) {
120
- choices.unshift({ name: "Select All", value: "ALL" });
121
- choices.push({ name: "Clear Selection", value: "CLEAR" });
122
- }
123
112
  const { selectedCollections } = await inquirer.prompt([
124
113
  {
125
114
  type: multiSelect ? "checkbox" : "list",
@@ -130,25 +119,13 @@ export class InteractiveCLI {
130
119
  pageSize: 10,
131
120
  },
132
121
  ]);
133
- if (multiSelect) {
134
- if (selectedCollections.includes("ALL")) {
135
- return collections;
136
- }
137
- else if (selectedCollections.includes("CLEAR")) {
138
- return [];
139
- }
140
- }
141
- return selectedCollections.filter((collection) => typeof collection !== "string");
122
+ return selectedCollections;
142
123
  }
143
124
  async selectBuckets(buckets, message, multiSelect = true) {
144
125
  const choices = buckets.map((bucket) => ({
145
126
  name: bucket.name,
146
- value: bucket.$id,
127
+ value: bucket,
147
128
  }));
148
- if (multiSelect) {
149
- choices.unshift({ name: "Select All", value: "ALL" });
150
- choices.push({ name: "Clear Selection", value: "CLEAR" });
151
- }
152
129
  const { selectedBuckets } = await inquirer.prompt([
153
130
  {
154
131
  type: multiSelect ? "checkbox" : "list",
@@ -159,15 +136,7 @@ export class InteractiveCLI {
159
136
  pageSize: 10,
160
137
  },
161
138
  ]);
162
- if (multiSelect) {
163
- if (selectedBuckets.includes("ALL")) {
164
- return buckets;
165
- }
166
- else if (selectedBuckets.includes("CLEAR")) {
167
- return [];
168
- }
169
- }
170
- return selectedBuckets.map((id) => buckets.find((bucket) => bucket.$id === id));
139
+ return selectedBuckets;
171
140
  }
172
141
  async createCollectionConfig() {
173
142
  const { collectionName } = await inquirer.prompt([
@@ -360,7 +329,7 @@ export class InteractiveCLI {
360
329
  throw new Error("Database is not initialized. Is the config file correct and created?");
361
330
  }
362
331
  const databases = await fetchAllDatabases(this.controller.database);
363
- const selectedDatabases = await this.selectDatabases(databases, "Select databases to synchronize (or select none to synchronize all):");
332
+ const selectedDatabases = await this.selectDatabases(databases, "Select databases to synchronize:");
364
333
  console.log("Configuring storage buckets...");
365
334
  const updatedConfig = await this.configureBuckets(this.controller.config, selectedDatabases);
366
335
  console.log("Synchronizing configurations...");
@@ -371,7 +340,7 @@ export class InteractiveCLI {
371
340
  throw new Error("Database is not initialized, is the config file correct & created?");
372
341
  }
373
342
  const databases = await fetchAllDatabases(this.controller.database);
374
- const selectedDatabases = await this.selectDatabases(databases, "Select databases to backup (or select none to backup all):");
343
+ const selectedDatabases = await this.selectDatabases(databases, "Select databases to backup:");
375
344
  for (const db of selectedDatabases) {
376
345
  console.log(`Backing up database: ${db.name}`);
377
346
  await this.controller.backupDatabase(db);
@@ -383,12 +352,12 @@ export class InteractiveCLI {
383
352
  }
384
353
  const databases = await fetchAllDatabases(this.controller.database);
385
354
  const storage = await listBuckets(this.controller.storage);
386
- const selectedDatabases = await this.selectDatabases(databases, "Select databases to wipe (or select none to skip database wipe):");
355
+ const selectedDatabases = await this.selectDatabases(databases, "Select databases to wipe:");
387
356
  const { selectedStorage } = await inquirer.prompt([
388
357
  {
389
358
  type: "checkbox",
390
359
  name: "selectedStorage",
391
- message: "Select storage buckets to wipe (or select none to skip storage wipe):",
360
+ message: "Select storage buckets to wipe:",
392
361
  choices: storage.buckets.map((s) => ({ name: s.name, value: s.$id })),
393
362
  },
394
363
  ]);
@@ -436,7 +405,7 @@ export class InteractiveCLI {
436
405
  const selectedDatabases = await this.selectDatabases(databases, "Select the database(s) to import data into:");
437
406
  let selectedCollections = [];
438
407
  for (const db of selectedDatabases) {
439
- const dbCollections = await this.selectCollections(db, this.controller.database, `Select collections to import data into for database ${db.name} (or select none to import into all):`, true);
408
+ const dbCollections = await this.selectCollections(db, this.controller.database, `Select collections to import data into for database ${db.name}:`, true);
440
409
  selectedCollections = [...selectedCollections, ...dbCollections];
441
410
  }
442
411
  const { shouldWriteFile } = await inquirer.prompt([
@@ -511,7 +480,7 @@ export class InteractiveCLI {
511
480
  }
512
481
  const [fromDb] = await this.selectDatabases(sourceDatabases, "Select the source database:", false);
513
482
  const [targetDb] = await this.selectDatabases(targetDatabases.filter((db) => db.$id !== fromDb.$id), "Select the target database:", false);
514
- const selectedCollections = await this.selectCollections(fromDb, sourceClient, "Select collections to transfer (or select none to transfer all):");
483
+ const selectedCollections = await this.selectCollections(fromDb, sourceClient, "Select collections to transfer):");
515
484
  const { transferStorage } = await inquirer.prompt([
516
485
  {
517
486
  type: "confirm",
package/dist/main.js CHANGED
@@ -110,18 +110,33 @@ const argv = yargs(hideBin(process.argv))
110
110
  .option("remoteApiKey", {
111
111
  type: "string",
112
112
  description: "Set the remote Appwrite API key for transfers",
113
+ })
114
+ .option("setup", {
115
+ type: "boolean",
116
+ description: "Setup the project with example data",
113
117
  })
114
118
  .help()
115
119
  .parse();
116
120
  async function main() {
117
121
  const parsedArgv = (await argv);
118
- const controller = new UtilsController(process.cwd());
119
- await controller.init();
122
+ let controller;
120
123
  if (parsedArgv.it) {
121
- const cli = new InteractiveCLI(process.cwd(), controller);
124
+ try {
125
+ controller = new UtilsController(process.cwd());
126
+ await controller.init();
127
+ }
128
+ catch (error) {
129
+ // If it fails, that means there's no config, more than likely
130
+ console.log("No config found, you probably need to create the setup files");
131
+ }
132
+ const cli = new InteractiveCLI(process.cwd());
122
133
  await cli.run();
123
134
  }
124
135
  else {
136
+ if (!controller) {
137
+ controller = new UtilsController(process.cwd());
138
+ await controller.init();
139
+ }
125
140
  // Handle non-interactive mode with the new options
126
141
  const options = {
127
142
  databases: parsedArgv.dbIds
@@ -9,7 +9,7 @@ export const setupMigrationDatabase = async (config) => {
9
9
  console.log("Starting Migrations Setup");
10
10
  console.log("---------------------------------");
11
11
  const database = new Databases(config.appwriteClient);
12
- let db = null;
12
+ let db;
13
13
  const migrationCollectionsSetup = getMigrationCollectionSchemas();
14
14
  try {
15
15
  db = await tryAwaitWithRetry(async () => await database.get("migrations"), undefined, true);
@@ -19,18 +19,40 @@ export const setupMigrationDatabase = async (config) => {
19
19
  db = await tryAwaitWithRetry(async () => await database.create("migrations", "Migrations", true));
20
20
  console.log("Migrations database created");
21
21
  }
22
+ if (!db) {
23
+ console.error("Failed to create or retrieve the migrations database");
24
+ return;
25
+ }
22
26
  for (const [collectionName, { collection, attributes }] of Object.entries(migrationCollectionsSetup)) {
23
27
  const collectionId = toCamelCase(collectionName);
24
- let collectionFound = null;
28
+ let collectionFound;
25
29
  try {
26
- collectionFound = await tryAwaitWithRetry(async () => await database.getCollection(db.$id, collectionId));
30
+ collectionFound = await tryAwaitWithRetry(async () => await database.getCollection(db.$id, collectionId), undefined, true);
31
+ console.log(`Collection found: ${collectionId}`);
27
32
  }
28
33
  catch (e) {
29
34
  console.log(`Collection not found: ${collectionId}`);
30
- collectionFound = await tryAwaitWithRetry(async () => await database.createCollection(db.$id, collectionId, collectionName, undefined, collection.documentSecurity, collection.enabled));
35
+ try {
36
+ collectionFound = await tryAwaitWithRetry(async () => await database.createCollection(db.$id, collectionId, collectionName, undefined, collection.documentSecurity, collection.enabled), undefined, true);
37
+ console.log(`Collection created: ${collectionId}`);
38
+ }
39
+ catch (createError) {
40
+ console.error(`Failed to create collection: ${collectionId}`, createError);
41
+ continue;
42
+ }
43
+ }
44
+ if (!collectionFound) {
45
+ console.error(`Failed to create or retrieve collection: ${collectionId}`);
46
+ continue;
31
47
  }
32
48
  for (const attribute of attributes) {
33
- await createOrUpdateAttribute(database, db.$id, collectionFound, attribute);
49
+ try {
50
+ await createOrUpdateAttribute(database, db.$id, collectionFound, attribute);
51
+ console.log(`Attribute created/updated: ${attribute.key}`);
52
+ }
53
+ catch (attrError) {
54
+ console.error(`Failed to create/update attribute: ${attribute.key}`, attrError);
55
+ }
34
56
  }
35
57
  }
36
58
  console.log("---------------------------------");
@@ -43,7 +65,7 @@ export const ensureDatabasesExist = async (config) => {
43
65
  const existingDatabases = await tryAwaitWithRetry(async () => await database.list([Query.limit(500)]));
44
66
  const migrationsDatabase = existingDatabases.databases.find((d) => d.name.toLowerCase().trim().replace(" ", "") === "migrations");
45
67
  if (existingDatabases.databases.length !== 0 && migrationsDatabase) {
46
- console.log("Wiping all databases except migrations");
68
+ console.log("Creating all databases except migrations");
47
69
  databasesToEnsure.push(migrationsDatabase);
48
70
  }
49
71
  for (const db of databasesToEnsure) {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export declare class SetupController {
2
+ private currentDir;
3
+ constructor(currentDir: string);
4
+ runSetup(withExampleData?: boolean): Promise<void>;
5
+ hasExistingConfig(): boolean;
6
+ }
@@ -0,0 +1,17 @@
1
+ import { setupDirsFiles } from "./utils/setupFiles.js";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ export class SetupController {
5
+ currentDir;
6
+ constructor(currentDir) {
7
+ this.currentDir = currentDir;
8
+ }
9
+ async runSetup(withExampleData = false) {
10
+ await setupDirsFiles(withExampleData, this.currentDir);
11
+ console.log("Setup completed successfully.");
12
+ }
13
+ hasExistingConfig() {
14
+ const configPath = path.join(this.currentDir, "appwrite", "appwriteConfig.ts");
15
+ return fs.existsSync(configPath);
16
+ }
17
+ }
@@ -17,24 +17,24 @@ export class SchemaGenerator {
17
17
  const collections = this.config.collections;
18
18
  delete this.config.collections;
19
19
  const configPath = path.join(this.appwriteFolderPath, "appwriteConfig.ts");
20
- const configContent = `import { type AppwriteConfig } from "appwrite-utils";
21
-
22
- const appwriteConfig: AppwriteConfig = {
23
- appwriteEndpoint: "${this.config.appwriteEndpoint}",
24
- appwriteProject: "${this.config.appwriteProject}",
25
- appwriteKey: "${this.config.appwriteKey}",
26
- enableBackups: ${this.config.enableBackups},
27
- backupInterval: ${this.config.backupInterval},
28
- backupRetention: ${this.config.backupRetention},
29
- enableBackupCleanup: ${this.config.enableBackupCleanup},
30
- enableMockData: ${this.config.enableMockData},
31
- documentBucketId: "${this.config.documentBucketId}",
32
- usersCollectionName: "${this.config.usersCollectionName}",
33
- databases: ${JSON.stringify(this.config.databases)},
34
- buckets: ${JSON.stringify(this.config.buckets)},
35
- };
36
-
37
- export default appwriteConfig;
20
+ const configContent = `import { type AppwriteConfig } from "appwrite-utils";
21
+
22
+ const appwriteConfig: AppwriteConfig = {
23
+ appwriteEndpoint: "${this.config.appwriteEndpoint}",
24
+ appwriteProject: "${this.config.appwriteProject}",
25
+ appwriteKey: "${this.config.appwriteKey}",
26
+ enableBackups: ${this.config.enableBackups},
27
+ backupInterval: ${this.config.backupInterval},
28
+ backupRetention: ${this.config.backupRetention},
29
+ enableBackupCleanup: ${this.config.enableBackupCleanup},
30
+ enableMockData: ${this.config.enableMockData},
31
+ documentBucketId: "${this.config.documentBucketId}",
32
+ usersCollectionName: "${this.config.usersCollectionName}",
33
+ databases: ${JSON.stringify(this.config.databases)},
34
+ buckets: ${JSON.stringify(this.config.buckets)},
35
+ };
36
+
37
+ export default appwriteConfig;
38
38
  `;
39
39
  fs.writeFileSync(configPath, configContent, { encoding: "utf-8" });
40
40
  const collectionsFolderPath = path.join(this.appwriteFolderPath, "collections");
@@ -44,19 +44,19 @@ export class SchemaGenerator {
44
44
  collections?.forEach((collection) => {
45
45
  const { databaseId, ...collectionWithoutDbId } = collection; // Destructure to exclude databaseId
46
46
  const collectionFilePath = path.join(collectionsFolderPath, `${collection.name}.ts`);
47
- const collectionContent = `import { type CollectionCreate } from "appwrite-utils";
48
-
49
- const ${collection.name}Config: Partial<CollectionCreate> = {
50
- name: "${collection.name}",
51
- $id: "${collection.$id}",
52
- enabled: ${collection.enabled},
53
- documentSecurity: ${collection.documentSecurity},
54
- $permissions: [
47
+ const collectionContent = `import { type CollectionCreate } from "appwrite-utils";
48
+
49
+ const ${collection.name}Config: Partial<CollectionCreate> = {
50
+ name: "${collection.name}",
51
+ $id: "${collection.$id}",
52
+ enabled: ${collection.enabled},
53
+ documentSecurity: ${collection.documentSecurity},
54
+ $permissions: [
55
55
  ${collection.$permissions
56
56
  .map((permission) => `{ permission: "${permission.permission}", target: "${permission.target}" }`)
57
- .join(",\n ")}
58
- ],
59
- attributes: [
57
+ .join(",\n ")}
58
+ ],
59
+ attributes: [
60
60
  ${collection.attributes
61
61
  .map((attr) => {
62
62
  return `{ ${Object.entries(attr)
@@ -84,9 +84,9 @@ export class SchemaGenerator {
84
84
  })
85
85
  .join(", ")} }`;
86
86
  })
87
- .join(",\n ")}
88
- ],
89
- indexes: [
87
+ .join(",\n ")}
88
+ ],
89
+ indexes: [
90
90
  ${(collection.indexes?.map((index) => {
91
91
  // Map each attribute to ensure it is properly quoted
92
92
  const formattedAttributes = index.attributes.map((attr) => `"${attr}"`).join(", ") ?? "";
@@ -94,11 +94,11 @@ export class SchemaGenerator {
94
94
  ?.filter((order) => order !== null)
95
95
  .map((order) => `"${order}"`)
96
96
  .join(", ") ?? ""}] }`;
97
- }) ?? []).join(",\n ")}
98
- ]
99
- };
100
-
101
- export default ${collection.name}Config;
97
+ }) ?? []).join(",\n ")}
98
+ ]
99
+ };
100
+
101
+ export default ${collection.name}Config;
102
102
  `;
103
103
  fs.writeFileSync(collectionFilePath, collectionContent, {
104
104
  encoding: "utf-8",
@@ -1,3 +1,3 @@
1
1
  export declare const customDefinitionsFile = "import type { ConverterFunctions, ValidationRules, AfterImportActions } from \"appwrite-utils\";\n\nexport const customConverterFunctions: ConverterFunctions = {\n // Add your custom converter functions here\n}\nexport const customValidationRules: ValidationRules = {\n // Add your custom validation rules here\n}\nexport const customAfterImportActions: AfterImportActions = {\n // Add your custom after import actions here\n}";
2
2
  export declare const createEmptyCollection: (collectionName: string) => void;
3
- export declare const setupDirsFiles: (example?: boolean) => Promise<void>;
3
+ export declare const setupDirsFiles: (example?: boolean, currentDir?: string) => Promise<void>;
@@ -143,8 +143,8 @@ export default ${collectionName};`;
143
143
  const collectionFilePath = path.join(collectionsFolder, `${collectionName}.ts`);
144
144
  writeFileSync(collectionFilePath, emptyCollection);
145
145
  };
146
- export const setupDirsFiles = async (example = false) => {
147
- const basePath = process.cwd();
146
+ export const setupDirsFiles = async (example = false, currentDir) => {
147
+ const basePath = currentDir || process.cwd();
148
148
  const srcPath = path.join(basePath);
149
149
  // Check if src directory exists in the current working directory
150
150
  if (!existsSync(srcPath)) {
@@ -112,6 +112,8 @@ export class UtilsController {
112
112
  if (!this.database || !this.config)
113
113
  throw new Error("Database or config not initialized");
114
114
  for (const database of databases) {
115
+ if (database.$id === "migrations")
116
+ continue;
115
117
  await this.createOrUpdateCollections(database);
116
118
  }
117
119
  }
package/package.json CHANGED
@@ -1,53 +1,53 @@
1
- {
2
- "name": "appwrite-utils-cli",
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": "0.9.2",
5
- "main": "src/main.ts",
6
- "type": "module",
7
- "repository": {
8
- "type": "git",
9
- "url": "https://github.com/zachhandley/AppwriteUtils"
10
- },
11
- "author": "Zach Handley <zach@blackleafdigital.com> (https://zachhandley.com)",
12
- "keywords": [
13
- "appwrite",
14
- "cli",
15
- "utils",
16
- "migrations",
17
- "data",
18
- "database",
19
- "import",
20
- "migration",
21
- "utility"
22
- ],
23
- "bin": {
24
- "appwrite-migrate": "./dist/main.js"
25
- },
26
- "scripts": {
27
- "build": "bun run tsc",
28
- "start": "tsx --no-cache src/main.ts",
29
- "deploy": "bun run build && npm publish --access public",
30
- "postinstall": "echo 'This package is intended for CLI use only and should not be added as a dependency in other projects.'"
31
- },
32
- "dependencies": {
33
- "@types/inquirer": "^9.0.7",
34
- "appwrite-utils": "^0.3.8",
35
- "commander": "^12.1.0",
36
- "inquirer": "^9.3.6",
37
- "js-yaml": "^4.1.0",
38
- "lodash": "^4.17.21",
39
- "luxon": "^3.5.0",
40
- "nanostores": "^0.10.3",
41
- "node-appwrite": "^13.0.0",
42
- "tsx": "^4.17.0",
43
- "ulidx": "^2.4.0",
44
- "winston": "^3.14.1",
45
- "zod": "^3.23.8"
46
- },
47
- "devDependencies": {
48
- "@types/js-yaml": "^4.0.9",
49
- "@types/lodash": "^4.17.7",
50
- "@types/luxon": "^3.4.2",
51
- "typescript": "^5.5.4"
52
- }
53
- }
1
+ {
2
+ "name": "appwrite-utils-cli",
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": "0.9.4",
5
+ "main": "src/main.ts",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/zachhandley/AppwriteUtils"
10
+ },
11
+ "author": "Zach Handley <zach@blackleafdigital.com> (https://zachhandley.com)",
12
+ "keywords": [
13
+ "appwrite",
14
+ "cli",
15
+ "utils",
16
+ "migrations",
17
+ "data",
18
+ "database",
19
+ "import",
20
+ "migration",
21
+ "utility"
22
+ ],
23
+ "bin": {
24
+ "appwrite-migrate": "./dist/main.js"
25
+ },
26
+ "scripts": {
27
+ "build": "bun run tsc",
28
+ "start": "tsx --no-cache src/main.ts",
29
+ "deploy": "bun run build && npm publish --access public",
30
+ "postinstall": "echo 'This package is intended for CLI use only and should not be added as a dependency in other projects.'"
31
+ },
32
+ "dependencies": {
33
+ "@types/inquirer": "^9.0.7",
34
+ "appwrite-utils": "^0.3.8",
35
+ "commander": "^12.1.0",
36
+ "inquirer": "^9.3.6",
37
+ "js-yaml": "^4.1.0",
38
+ "lodash": "^4.17.21",
39
+ "luxon": "^3.5.0",
40
+ "nanostores": "^0.10.3",
41
+ "node-appwrite": "^13.0.0",
42
+ "tsx": "^4.17.0",
43
+ "ulidx": "^2.4.0",
44
+ "winston": "^3.14.1",
45
+ "zod": "^3.23.8"
46
+ },
47
+ "devDependencies": {
48
+ "@types/js-yaml": "^4.0.9",
49
+ "@types/lodash": "^4.17.7",
50
+ "@types/luxon": "^3.4.2",
51
+ "typescript": "^5.5.4"
52
+ }
53
+ }