appwrite-utils-cli 0.10.3 → 0.10.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/README.md +2 -0
- package/dist/functions/deployments.js +12 -4
- package/dist/interactiveCLI.js +59 -59
- package/package.json +1 -1
- package/src/functions/deployments.ts +16 -4
- package/src/interactiveCLI.ts +88 -88
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.05: Made deploy function into deploy function(s) -- so you can do more than one at a time
|
151
|
+
- 0.10.04: Fixed stupid progress bar not updating -- also fixed double text
|
150
152
|
- 0.10.03: Fixed `syncDb` to push the configurations properly, accidentally hurt it during `synchronizeConfigurations`
|
151
153
|
- 0.10.02: Updated `wipeCollection` to handle errors gracefully
|
152
154
|
- 0.10.01: Fixed `predeployCommands` to work
|
@@ -47,25 +47,33 @@ export const deployFunction = async (client, functionId, codePath, activate = tr
|
|
47
47
|
const fileObject = InputFile.fromBuffer(new Uint8Array(fileBuffer), `function-${functionId}.tar.gz`);
|
48
48
|
try {
|
49
49
|
console.log(chalk.blue("🚀 Creating deployment..."));
|
50
|
+
// Start with 1 as default total since we don't know the chunk size yet
|
50
51
|
progressBar.start(1, 0);
|
51
52
|
const functionResponse = await functions.createDeployment(functionId, fileObject, activate, entrypoint, commands, (progress) => {
|
52
53
|
const chunks = progress.chunksUploaded;
|
53
54
|
const total = progress.chunksTotal;
|
54
|
-
if (chunks !== undefined && total) {
|
55
|
-
|
56
|
-
|
55
|
+
if (chunks !== undefined && total !== undefined) {
|
56
|
+
// First chunk, initialize the bar with correct total
|
57
|
+
if (chunks === 0) {
|
58
|
+
progressBar.start(total || 100, 0);
|
57
59
|
}
|
58
60
|
else {
|
59
61
|
progressBar.update(chunks);
|
62
|
+
// Check if upload is complete
|
60
63
|
if (chunks === total) {
|
64
|
+
progressBar.update(total);
|
61
65
|
progressBar.stop();
|
62
66
|
console.log(chalk.green("✅ Upload complete!"));
|
63
67
|
}
|
64
68
|
}
|
65
69
|
}
|
66
70
|
});
|
71
|
+
// Ensure progress bar completes even if callback never fired
|
72
|
+
if (progressBar.getProgress() === 0) {
|
73
|
+
progressBar.update(1);
|
74
|
+
progressBar.stop();
|
75
|
+
}
|
67
76
|
await fs.promises.unlink(tarPath);
|
68
|
-
console.log(chalk.green("✨ Function deployed successfully!"));
|
69
77
|
return functionResponse;
|
70
78
|
}
|
71
79
|
catch (error) {
|
package/dist/interactiveCLI.js
CHANGED
@@ -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";
|
@@ -118,7 +118,7 @@ export class InteractiveCLI {
|
|
118
118
|
break;
|
119
119
|
case CHOICES.EXIT:
|
120
120
|
console.log(chalk.green("Goodbye!"));
|
121
|
-
|
121
|
+
process.exit(0);
|
122
122
|
}
|
123
123
|
}
|
124
124
|
}
|
@@ -369,74 +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:",
|
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
|
378
|
-
|
379
|
-
|
380
|
-
|
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
|
-
console.log(chalk.green(`Found function at: ${foundPath}`));
|
392
|
-
functionPath = foundPath;
|
393
|
-
functionConfig.dirPath = foundPath;
|
377
|
+
for (const functionConfig of functions) {
|
378
|
+
if (!functionConfig) {
|
379
|
+
console.log(chalk.red("Invalid function configuration"));
|
380
|
+
return;
|
394
381
|
}
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
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;
|
414
421
|
}
|
415
|
-
await this.controller.reloadConfig();
|
416
|
-
functionConfig.dirPath = downloadedPath;
|
417
|
-
functionPath = downloadedPath;
|
418
422
|
}
|
419
|
-
|
420
|
-
console.
|
423
|
+
else {
|
424
|
+
console.log(chalk.red(`Function ${functionConfig.name} not found locally. Cannot deploy.`));
|
421
425
|
return;
|
422
426
|
}
|
423
427
|
}
|
424
|
-
else {
|
425
|
-
console.log(chalk.red(`Function ${functionConfig.name} not found locally. Cannot deploy.`));
|
426
|
-
return;
|
427
|
-
}
|
428
428
|
}
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
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
|
+
}
|
440
440
|
}
|
441
441
|
}
|
442
442
|
async deleteFunction() {
|
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": "0.10.
|
4
|
+
"version": "0.10.05",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -77,7 +77,9 @@ export const deployFunction = async (
|
|
77
77
|
|
78
78
|
try {
|
79
79
|
console.log(chalk.blue("🚀 Creating deployment..."));
|
80
|
+
// Start with 1 as default total since we don't know the chunk size yet
|
80
81
|
progressBar.start(1, 0);
|
82
|
+
|
81
83
|
const functionResponse = await functions.createDeployment(
|
82
84
|
functionId,
|
83
85
|
fileObject,
|
@@ -87,12 +89,17 @@ export const deployFunction = async (
|
|
87
89
|
(progress) => {
|
88
90
|
const chunks = progress.chunksUploaded;
|
89
91
|
const total = progress.chunksTotal;
|
90
|
-
|
91
|
-
|
92
|
-
|
92
|
+
|
93
|
+
if (chunks !== undefined && total !== undefined) {
|
94
|
+
// First chunk, initialize the bar with correct total
|
95
|
+
if (chunks === 0) {
|
96
|
+
progressBar.start(total || 100, 0);
|
93
97
|
} else {
|
94
98
|
progressBar.update(chunks);
|
99
|
+
|
100
|
+
// Check if upload is complete
|
95
101
|
if (chunks === total) {
|
102
|
+
progressBar.update(total);
|
96
103
|
progressBar.stop();
|
97
104
|
console.log(chalk.green("✅ Upload complete!"));
|
98
105
|
}
|
@@ -101,8 +108,13 @@ export const deployFunction = async (
|
|
101
108
|
}
|
102
109
|
);
|
103
110
|
|
111
|
+
// Ensure progress bar completes even if callback never fired
|
112
|
+
if (progressBar.getProgress() === 0) {
|
113
|
+
progressBar.update(1);
|
114
|
+
progressBar.stop();
|
115
|
+
}
|
116
|
+
|
104
117
|
await fs.promises.unlink(tarPath);
|
105
|
-
console.log(chalk.green("✨ Function deployed successfully!"));
|
106
118
|
return functionResponse;
|
107
119
|
} catch (error) {
|
108
120
|
progressBar.stop();
|
package/src/interactiveCLI.ts
CHANGED
@@ -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",
|
@@ -154,7 +154,7 @@ export class InteractiveCLI {
|
|
154
154
|
break;
|
155
155
|
case CHOICES.EXIT:
|
156
156
|
console.log(chalk.green("Goodbye!"));
|
157
|
-
|
157
|
+
process.exit(0);
|
158
158
|
}
|
159
159
|
}
|
160
160
|
}
|
@@ -494,8 +494,8 @@ export class InteractiveCLI {
|
|
494
494
|
}
|
495
495
|
|
496
496
|
const functions = await this.selectFunctions(
|
497
|
-
"Select function to deploy:",
|
498
|
-
|
497
|
+
"Select function(s) to deploy:",
|
498
|
+
true,
|
499
499
|
true
|
500
500
|
);
|
501
501
|
|
@@ -504,107 +504,107 @@ export class InteractiveCLI {
|
|
504
504
|
return;
|
505
505
|
}
|
506
506
|
|
507
|
-
const functionConfig
|
508
|
-
|
509
|
-
|
510
|
-
|
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
|
-
|
519
|
-
this.controller.
|
520
|
-
|
521
|
-
|
522
|
-
);
|
513
|
+
// Ensure functions array exists
|
514
|
+
if (!this.controller.config.functions) {
|
515
|
+
this.controller.config.functions = [];
|
516
|
+
}
|
523
517
|
|
524
|
-
|
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
|
-
|
520
|
+
"functions",
|
521
|
+
functionConfig.name
|
533
522
|
);
|
534
523
|
|
535
|
-
if (
|
536
|
-
console.log(
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
"Function not found locally. Would you like to download the latest deployment?",
|
546
|
-
default: false,
|
547
|
-
},
|
548
|
-
]);
|
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
|
+
);
|
549
534
|
|
550
|
-
if (
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
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}`)
|
558
560
|
);
|
559
|
-
console.log(
|
560
|
-
chalk.green(`✨ Function downloaded to ${downloadedPath}`)
|
561
|
-
);
|
562
561
|
|
563
|
-
|
564
|
-
|
565
|
-
|
562
|
+
const existingIndex = this.controller.config.functions.findIndex(
|
563
|
+
(f) => f?.$id === remoteFunction.$id
|
564
|
+
);
|
566
565
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
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;
|
571
581
|
}
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
console.error(
|
578
|
-
chalk.red("Failed to download function deployment:"),
|
579
|
-
error
|
582
|
+
} else {
|
583
|
+
console.log(
|
584
|
+
chalk.red(
|
585
|
+
`Function ${functionConfig.name} not found locally. Cannot deploy.`
|
586
|
+
)
|
580
587
|
);
|
581
588
|
return;
|
582
589
|
}
|
583
|
-
} else {
|
584
|
-
console.log(
|
585
|
-
chalk.red(
|
586
|
-
`Function ${functionConfig.name} not found locally. Cannot deploy.`
|
587
|
-
)
|
588
|
-
);
|
589
|
-
return;
|
590
590
|
}
|
591
591
|
}
|
592
|
-
}
|
593
592
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
593
|
+
if (!this.controller.appwriteServer) {
|
594
|
+
console.log(chalk.red("Appwrite server not initialized"));
|
595
|
+
return;
|
596
|
+
}
|
598
597
|
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
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
|
+
}
|
608
608
|
}
|
609
609
|
}
|
610
610
|
|