appwrite-utils-cli 0.10.4 → 0.10.6

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
@@ -147,6 +147,8 @@ This updated CLI ensures that developers have robust tools at their fingertips t
147
147
 
148
148
  ## Changelog
149
149
 
150
+ - 0.10.051: Added `node_modules` and a few others to the ignore
151
+ - 0.10.05: Made deploy function into deploy function(s) -- so you can do more than one at a time
150
152
  - 0.10.04: Fixed stupid progress bar not updating -- also fixed double text
151
153
  - 0.10.03: Fixed `syncDb` to push the configurations properly, accidentally hurt it during `synchronizeConfigurations`
152
154
  - 0.10.02: Updated `wipeCollection` to handle errors gracefully
@@ -9,6 +9,7 @@ import chalk from "chalk";
9
9
  import cliProgress from "cli-progress";
10
10
  import { execSync } from "child_process";
11
11
  import { createFunction, getFunction, updateFunctionSpecifications, } from "./methods.js";
12
+ import ignore from "ignore";
12
13
  const findFunctionDirectory = (basePath, functionName) => {
13
14
  const normalizedName = functionName.toLowerCase().replace(/\s+/g, "-");
14
15
  const dirs = fs.readdirSync(basePath, { withFileTypes: true });
@@ -26,9 +27,18 @@ const findFunctionDirectory = (basePath, functionName) => {
26
27
  }
27
28
  return undefined;
28
29
  };
29
- export const deployFunction = async (client, functionId, codePath, activate = true, entrypoint = "index.js", commands = "npm install") => {
30
+ export const deployFunction = async (client, functionId, codePath, activate = true, entrypoint = "index.js", commands) => {
30
31
  const functions = new Functions(client);
31
- console.log(chalk.blue("📦 Preparing function deployment..."));
32
+ console.log(chalk.blue("Preparing function deployment..."));
33
+ // Setup ignore rules
34
+ const ig = ignore.default();
35
+ ig.add(["node_modules", ".git", ".vscode", ".DS_Store"]); // Common directories to ignore
36
+ // Read .gitignore if it exists
37
+ const gitignorePath = join(codePath, ".gitignore");
38
+ if (fs.existsSync(gitignorePath)) {
39
+ const gitignoreContent = fs.readFileSync(gitignorePath, "utf8");
40
+ ig.add(gitignoreContent);
41
+ }
32
42
  const progressBar = new cliProgress.SingleBar({
33
43
  format: "Uploading |" +
34
44
  chalk.cyan("{bar}") +
@@ -42,6 +52,7 @@ export const deployFunction = async (client, functionId, codePath, activate = tr
42
52
  gzip: true,
43
53
  file: tarPath,
44
54
  cwd: codePath,
55
+ filter: (path) => !ig.ignores(path), // Use ignore to filter files
45
56
  }, ["."]);
46
57
  const fileBuffer = await fs.promises.readFile(tarPath);
47
58
  const fileObject = InputFile.fromBuffer(new Uint8Array(fileBuffer), `function-${functionId}.tar.gz`);
@@ -19,7 +19,7 @@ var CHOICES;
19
19
  (function (CHOICES) {
20
20
  CHOICES["CREATE_COLLECTION_CONFIG"] = "Create collection config file";
21
21
  CHOICES["CREATE_FUNCTION"] = "Create a new function, from scratch or using a template";
22
- CHOICES["DEPLOY_FUNCTION"] = "Deploy function";
22
+ CHOICES["DEPLOY_FUNCTION"] = "Deploy function(s)";
23
23
  CHOICES["DELETE_FUNCTION"] = "Delete function";
24
24
  CHOICES["SETUP_DIRS_FILES"] = "Setup directories and files";
25
25
  CHOICES["SETUP_DIRS_FILES_WITH_EXAMPLE_DATA"] = "Setup directories and files with example data";
@@ -369,73 +369,74 @@ export class InteractiveCLI {
369
369
  console.log(chalk.red("Failed to initialize controller or load config"));
370
370
  return;
371
371
  }
372
- const functions = await this.selectFunctions("Select function to deploy:", false, true);
372
+ const functions = await this.selectFunctions("Select function(s) to deploy:", true, true);
373
373
  if (!functions?.length) {
374
374
  console.log(chalk.red("No function selected"));
375
375
  return;
376
376
  }
377
- const functionConfig = functions[0];
378
- if (!functionConfig) {
379
- console.log(chalk.red("Invalid function configuration"));
380
- return;
381
- }
382
- // Ensure functions array exists
383
- if (!this.controller.config.functions) {
384
- this.controller.config.functions = [];
385
- }
386
- let functionPath = join(this.controller.getAppwriteFolderPath(), "functions", functionConfig.name);
387
- if (!fs.existsSync(functionPath)) {
388
- console.log(chalk.yellow(`Function not found in primary location, searching subdirectories...`));
389
- const foundPath = await this.findFunctionInSubdirectories(this.controller.getAppwriteFolderPath(), functionConfig.name.toLowerCase());
390
- if (foundPath) {
391
- functionPath = foundPath;
392
- functionConfig.dirPath = foundPath;
377
+ for (const functionConfig of functions) {
378
+ if (!functionConfig) {
379
+ console.log(chalk.red("Invalid function configuration"));
380
+ return;
393
381
  }
394
- else {
395
- const { shouldDownload } = await inquirer.prompt([
396
- {
397
- type: "confirm",
398
- name: "shouldDownload",
399
- message: "Function not found locally. Would you like to download the latest deployment?",
400
- default: false,
401
- },
402
- ]);
403
- if (shouldDownload) {
404
- try {
405
- console.log(chalk.blue("Downloading latest deployment..."));
406
- const { path: downloadedPath, function: remoteFunction } = await downloadLatestFunctionDeployment(this.controller.appwriteServer, functionConfig.$id, join(this.controller.getAppwriteFolderPath(), "functions"));
407
- console.log(chalk.green(`✨ Function downloaded to ${downloadedPath}`));
408
- const existingIndex = this.controller.config.functions.findIndex((f) => f?.$id === remoteFunction.$id);
409
- if (existingIndex >= 0) {
410
- // Only update the dirPath if function exists
411
- this.controller.config.functions[existingIndex].dirPath =
412
- downloadedPath;
382
+ // Ensure functions array exists
383
+ if (!this.controller.config.functions) {
384
+ this.controller.config.functions = [];
385
+ }
386
+ let functionPath = join(this.controller.getAppwriteFolderPath(), "functions", functionConfig.name);
387
+ if (!fs.existsSync(functionPath)) {
388
+ console.log(chalk.yellow(`Function not found in primary location, searching subdirectories...`));
389
+ const foundPath = await this.findFunctionInSubdirectories(this.controller.getAppwriteFolderPath(), functionConfig.name.toLowerCase());
390
+ if (foundPath) {
391
+ functionPath = foundPath;
392
+ functionConfig.dirPath = foundPath;
393
+ }
394
+ else {
395
+ const { shouldDownload } = await inquirer.prompt([
396
+ {
397
+ type: "confirm",
398
+ name: "shouldDownload",
399
+ message: "Function not found locally. Would you like to download the latest deployment?",
400
+ default: false,
401
+ },
402
+ ]);
403
+ if (shouldDownload) {
404
+ try {
405
+ console.log(chalk.blue("Downloading latest deployment..."));
406
+ const { path: downloadedPath, function: remoteFunction } = await downloadLatestFunctionDeployment(this.controller.appwriteServer, functionConfig.$id, join(this.controller.getAppwriteFolderPath(), "functions"));
407
+ console.log(chalk.green(`✨ Function downloaded to ${downloadedPath}`));
408
+ const existingIndex = this.controller.config.functions.findIndex((f) => f?.$id === remoteFunction.$id);
409
+ if (existingIndex >= 0) {
410
+ // Only update the dirPath if function exists
411
+ this.controller.config.functions[existingIndex].dirPath =
412
+ downloadedPath;
413
+ }
414
+ await this.controller.reloadConfig();
415
+ functionConfig.dirPath = downloadedPath;
416
+ functionPath = downloadedPath;
417
+ }
418
+ catch (error) {
419
+ console.error(chalk.red("Failed to download function deployment:"), error);
420
+ return;
413
421
  }
414
- await this.controller.reloadConfig();
415
- functionConfig.dirPath = downloadedPath;
416
- functionPath = downloadedPath;
417
422
  }
418
- catch (error) {
419
- console.error(chalk.red("Failed to download function deployment:"), error);
423
+ else {
424
+ console.log(chalk.red(`Function ${functionConfig.name} not found locally. Cannot deploy.`));
420
425
  return;
421
426
  }
422
427
  }
423
- else {
424
- console.log(chalk.red(`Function ${functionConfig.name} not found locally. Cannot deploy.`));
425
- return;
426
- }
427
428
  }
428
- }
429
- if (!this.controller.appwriteServer) {
430
- console.log(chalk.red("Appwrite server not initialized"));
431
- return;
432
- }
433
- try {
434
- await deployLocalFunction(this.controller.appwriteServer, functionConfig.name, functionConfig);
435
- console.log(chalk.green("✨ Function deployed successfully!"));
436
- }
437
- catch (error) {
438
- console.error(chalk.red("Failed to deploy function:"), error);
429
+ if (!this.controller.appwriteServer) {
430
+ console.log(chalk.red("Appwrite server not initialized"));
431
+ return;
432
+ }
433
+ try {
434
+ await deployLocalFunction(this.controller.appwriteServer, functionConfig.name, functionConfig);
435
+ console.log(chalk.green("✨ Function deployed successfully!"));
436
+ }
437
+ catch (error) {
438
+ console.error(chalk.red("Failed to deploy function:"), error);
439
+ }
439
440
  }
440
441
  }
441
442
  async deleteFunction() {
package/dist/main.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,57 +1,58 @@
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.10.04",
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.97",
35
- "chalk": "^5.3.0",
36
- "cli-progress": "^3.12.0",
37
- "commander": "^12.1.0",
38
- "inquirer": "^9.3.6",
39
- "js-yaml": "^4.1.0",
40
- "lodash": "^4.17.21",
41
- "luxon": "^3.5.0",
42
- "nanostores": "^0.10.3",
43
- "node-appwrite": "^14.1.0",
44
- "tar": "^7.4.3",
45
- "tsx": "^4.17.0",
46
- "ulidx": "^2.4.0",
47
- "winston": "^3.14.2",
48
- "zod": "^3.23.8"
49
- },
50
- "devDependencies": {
51
- "@types/cli-progress": "^3.11.6",
52
- "@types/js-yaml": "^4.0.9",
53
- "@types/lodash": "^4.17.7",
54
- "@types/luxon": "^3.4.2",
55
- "typescript": "^5.5.4"
56
- }
57
- }
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.10.06",
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.97",
35
+ "chalk": "^5.3.0",
36
+ "cli-progress": "^3.12.0",
37
+ "commander": "^12.1.0",
38
+ "ignore": "^6.0.2",
39
+ "inquirer": "^9.3.6",
40
+ "js-yaml": "^4.1.0",
41
+ "lodash": "^4.17.21",
42
+ "luxon": "^3.5.0",
43
+ "nanostores": "^0.10.3",
44
+ "node-appwrite": "^14.1.0",
45
+ "tar": "^7.4.3",
46
+ "tsx": "^4.17.0",
47
+ "ulidx": "^2.4.0",
48
+ "winston": "^3.14.2",
49
+ "zod": "^3.23.8"
50
+ },
51
+ "devDependencies": {
52
+ "@types/cli-progress": "^3.11.6",
53
+ "@types/js-yaml": "^4.0.9",
54
+ "@types/lodash": "^4.17.7",
55
+ "@types/luxon": "^3.4.2",
56
+ "typescript": "^5.5.4"
57
+ }
58
+ }
@@ -13,6 +13,7 @@ import {
13
13
  getFunction,
14
14
  updateFunctionSpecifications,
15
15
  } from "./methods.js";
16
+ import ignore from "ignore";
16
17
 
17
18
  const findFunctionDirectory = (
18
19
  basePath: string,
@@ -44,10 +45,21 @@ export const deployFunction = async (
44
45
  codePath: string,
45
46
  activate: boolean = true,
46
47
  entrypoint: string = "index.js",
47
- commands: string = "npm install"
48
+ commands?: string
48
49
  ) => {
49
50
  const functions = new Functions(client);
50
- console.log(chalk.blue("📦 Preparing function deployment..."));
51
+ console.log(chalk.blue("Preparing function deployment..."));
52
+
53
+ // Setup ignore rules
54
+ const ig = ignore.default();
55
+ ig.add(["node_modules", ".git", ".vscode", ".DS_Store"]); // Common directories to ignore
56
+
57
+ // Read .gitignore if it exists
58
+ const gitignorePath = join(codePath, ".gitignore");
59
+ if (fs.existsSync(gitignorePath)) {
60
+ const gitignoreContent = fs.readFileSync(gitignorePath, "utf8");
61
+ ig.add(gitignoreContent);
62
+ }
51
63
 
52
64
  const progressBar = new cliProgress.SingleBar({
53
65
  format:
@@ -60,11 +72,13 @@ export const deployFunction = async (
60
72
  });
61
73
 
62
74
  const tarPath = join(process.cwd(), `function-${functionId}.tar.gz`);
75
+
63
76
  await createTarball(
64
77
  {
65
78
  gzip: true,
66
79
  file: tarPath,
67
80
  cwd: codePath,
81
+ filter: (path) => !ig.ignores(path), // Use ignore to filter files
68
82
  },
69
83
  ["."]
70
84
  );
@@ -47,7 +47,7 @@ import { SchemaGenerator } from "./migrations/schemaStrings.js";
47
47
  enum CHOICES {
48
48
  CREATE_COLLECTION_CONFIG = "Create collection config file",
49
49
  CREATE_FUNCTION = "Create a new function, from scratch or using a template",
50
- DEPLOY_FUNCTION = "Deploy function",
50
+ DEPLOY_FUNCTION = "Deploy function(s)",
51
51
  DELETE_FUNCTION = "Delete function",
52
52
  SETUP_DIRS_FILES = "Setup directories and files",
53
53
  SETUP_DIRS_FILES_WITH_EXAMPLE_DATA = "Setup directories and files with example data",
@@ -494,8 +494,8 @@ export class InteractiveCLI {
494
494
  }
495
495
 
496
496
  const functions = await this.selectFunctions(
497
- "Select function to deploy:",
498
- false,
497
+ "Select function(s) to deploy:",
498
+ true,
499
499
  true
500
500
  );
501
501
 
@@ -504,106 +504,107 @@ export class InteractiveCLI {
504
504
  return;
505
505
  }
506
506
 
507
- const functionConfig = functions[0];
508
- if (!functionConfig) {
509
- console.log(chalk.red("Invalid function configuration"));
510
- return;
511
- }
512
-
513
- // Ensure functions array exists
514
- if (!this.controller.config.functions) {
515
- this.controller.config.functions = [];
516
- }
507
+ for (const functionConfig of functions) {
508
+ if (!functionConfig) {
509
+ console.log(chalk.red("Invalid function configuration"));
510
+ return;
511
+ }
517
512
 
518
- let functionPath = join(
519
- this.controller.getAppwriteFolderPath(),
520
- "functions",
521
- functionConfig.name
522
- );
513
+ // Ensure functions array exists
514
+ if (!this.controller.config.functions) {
515
+ this.controller.config.functions = [];
516
+ }
523
517
 
524
- if (!fs.existsSync(functionPath)) {
525
- console.log(
526
- chalk.yellow(
527
- `Function not found in primary location, searching subdirectories...`
528
- )
529
- );
530
- const foundPath = await this.findFunctionInSubdirectories(
518
+ let functionPath = join(
531
519
  this.controller.getAppwriteFolderPath(),
532
- functionConfig.name.toLowerCase()
520
+ "functions",
521
+ functionConfig.name
533
522
  );
534
523
 
535
- if (foundPath) {
536
- functionPath = foundPath;
537
- functionConfig.dirPath = foundPath;
538
- } else {
539
- const { shouldDownload } = await inquirer.prompt([
540
- {
541
- type: "confirm",
542
- name: "shouldDownload",
543
- message:
544
- "Function not found locally. Would you like to download the latest deployment?",
545
- default: false,
546
- },
547
- ]);
524
+ if (!fs.existsSync(functionPath)) {
525
+ console.log(
526
+ chalk.yellow(
527
+ `Function not found in primary location, searching subdirectories...`
528
+ )
529
+ );
530
+ const foundPath = await this.findFunctionInSubdirectories(
531
+ this.controller.getAppwriteFolderPath(),
532
+ functionConfig.name.toLowerCase()
533
+ );
548
534
 
549
- if (shouldDownload) {
550
- try {
551
- console.log(chalk.blue("Downloading latest deployment..."));
552
- const { path: downloadedPath, function: remoteFunction } =
553
- await downloadLatestFunctionDeployment(
554
- this.controller.appwriteServer!,
555
- functionConfig.$id,
556
- join(this.controller.getAppwriteFolderPath(), "functions")
535
+ if (foundPath) {
536
+ functionPath = foundPath;
537
+ functionConfig.dirPath = foundPath;
538
+ } else {
539
+ const { shouldDownload } = await inquirer.prompt([
540
+ {
541
+ type: "confirm",
542
+ name: "shouldDownload",
543
+ message:
544
+ "Function not found locally. Would you like to download the latest deployment?",
545
+ default: false,
546
+ },
547
+ ]);
548
+
549
+ if (shouldDownload) {
550
+ try {
551
+ console.log(chalk.blue("Downloading latest deployment..."));
552
+ const { path: downloadedPath, function: remoteFunction } =
553
+ await downloadLatestFunctionDeployment(
554
+ this.controller.appwriteServer!,
555
+ functionConfig.$id,
556
+ join(this.controller.getAppwriteFolderPath(), "functions")
557
+ );
558
+ console.log(
559
+ chalk.green(`✨ Function downloaded to ${downloadedPath}`)
557
560
  );
558
- console.log(
559
- chalk.green(`✨ Function downloaded to ${downloadedPath}`)
560
- );
561
561
 
562
- const existingIndex = this.controller.config.functions.findIndex(
563
- (f) => f?.$id === remoteFunction.$id
564
- );
562
+ const existingIndex = this.controller.config.functions.findIndex(
563
+ (f) => f?.$id === remoteFunction.$id
564
+ );
565
565
 
566
- if (existingIndex >= 0) {
567
- // Only update the dirPath if function exists
568
- this.controller.config.functions[existingIndex].dirPath =
569
- downloadedPath;
566
+ if (existingIndex >= 0) {
567
+ // Only update the dirPath if function exists
568
+ this.controller.config.functions[existingIndex].dirPath =
569
+ downloadedPath;
570
+ }
571
+
572
+ await this.controller.reloadConfig();
573
+ functionConfig.dirPath = downloadedPath;
574
+ functionPath = downloadedPath;
575
+ } catch (error) {
576
+ console.error(
577
+ chalk.red("Failed to download function deployment:"),
578
+ error
579
+ );
580
+ return;
570
581
  }
571
-
572
- await this.controller.reloadConfig();
573
- functionConfig.dirPath = downloadedPath;
574
- functionPath = downloadedPath;
575
- } catch (error) {
576
- console.error(
577
- chalk.red("Failed to download function deployment:"),
578
- error
582
+ } else {
583
+ console.log(
584
+ chalk.red(
585
+ `Function ${functionConfig.name} not found locally. Cannot deploy.`
586
+ )
579
587
  );
580
588
  return;
581
589
  }
582
- } else {
583
- console.log(
584
- chalk.red(
585
- `Function ${functionConfig.name} not found locally. Cannot deploy.`
586
- )
587
- );
588
- return;
589
590
  }
590
591
  }
591
- }
592
592
 
593
- if (!this.controller.appwriteServer) {
594
- console.log(chalk.red("Appwrite server not initialized"));
595
- return;
596
- }
593
+ if (!this.controller.appwriteServer) {
594
+ console.log(chalk.red("Appwrite server not initialized"));
595
+ return;
596
+ }
597
597
 
598
- try {
599
- await deployLocalFunction(
600
- this.controller.appwriteServer,
601
- functionConfig.name,
602
- functionConfig
603
- );
604
- console.log(chalk.green("✨ Function deployed successfully!"));
605
- } catch (error) {
606
- console.error(chalk.red("Failed to deploy function:"), error);
598
+ try {
599
+ await deployLocalFunction(
600
+ this.controller.appwriteServer,
601
+ functionConfig.name,
602
+ functionConfig
603
+ );
604
+ console.log(chalk.green("✨ Function deployed successfully!"));
605
+ } catch (error) {
606
+ console.error(chalk.red("Failed to deploy function:"), error);
607
+ }
607
608
  }
608
609
  }
609
610