appwrite-utils-cli 0.9.998 → 0.10.0
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/interactiveCLI.js +269 -99
- package/package.json +1 -1
- package/src/interactiveCLI.ts +372 -132
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.0: Fixed `synchronize configurations` for functions, now you do not need to deploy the function first
|
151
|
+
- 0.9.999: Fixed Functions, looks for `./functions` in addition to `appwriteConfigFolder/functions`
|
150
152
|
- 0.9.998: Fixed transfer finally, added `--targetDbId` and `--sourceDbId` as aliases
|
151
153
|
- 0.9.994: Added function deployment management, in BETA, and fixed document transfer between databases
|
152
154
|
- 0.9.993: Fixed `updateFunctionSpecifications` resetting functions to default with undefined values (oops)
|
package/dist/interactiveCLI.js
CHANGED
@@ -10,7 +10,7 @@ import { AppwriteFunctionSchema, parseAttribute, PermissionToAppwritePermission,
|
|
10
10
|
import { ulid } from "ulidx";
|
11
11
|
import chalk from "chalk";
|
12
12
|
import { DateTime } from "luxon";
|
13
|
-
import { createFunctionTemplate, deleteFunction, downloadLatestFunctionDeployment, listFunctions, listSpecifications, } from "./functions/methods.js";
|
13
|
+
import { createFunctionTemplate, deleteFunction, downloadLatestFunctionDeployment, getFunction, listFunctions, listSpecifications, } from "./functions/methods.js";
|
14
14
|
import { deployLocalFunction } from "./functions/deployments.js";
|
15
15
|
import { join } from "node:path";
|
16
16
|
import fs from "node:fs";
|
@@ -292,27 +292,55 @@ export class InteractiveCLI {
|
|
292
292
|
console.log(chalk.green("✨ Function created successfully!"));
|
293
293
|
}
|
294
294
|
async findFunctionInSubdirectories(basePath, functionName) {
|
295
|
-
|
295
|
+
// Common locations to check first
|
296
|
+
const commonPaths = [
|
297
|
+
join(process.cwd(), "functions", functionName), // ./functions/functionName
|
298
|
+
join(process.cwd(), functionName), // ./functionName
|
299
|
+
join(basePath, "functions", functionName), // appwriteFolder/functions/functionName
|
300
|
+
join(basePath, functionName), // appwriteFolder/functionName
|
301
|
+
];
|
302
|
+
// Check common locations first
|
303
|
+
for (const path of commonPaths) {
|
304
|
+
try {
|
305
|
+
const stats = await fs.promises.stat(path);
|
306
|
+
if (stats.isDirectory()) {
|
307
|
+
console.log(chalk.green(`Found function at common location: ${path}`));
|
308
|
+
return path;
|
309
|
+
}
|
310
|
+
}
|
311
|
+
catch (error) {
|
312
|
+
// Path doesn't exist, continue to next
|
313
|
+
}
|
314
|
+
}
|
315
|
+
// If not found in common locations, do recursive search
|
316
|
+
console.log(chalk.yellow("Function not found in common locations, searching subdirectories..."));
|
317
|
+
const queue = [process.cwd(), basePath];
|
318
|
+
const searched = new Set();
|
296
319
|
while (queue.length > 0) {
|
297
320
|
const currentPath = queue.shift();
|
321
|
+
if (searched.has(currentPath))
|
322
|
+
continue;
|
323
|
+
searched.add(currentPath);
|
298
324
|
try {
|
299
325
|
const entries = await fs.promises.readdir(currentPath, {
|
300
326
|
withFileTypes: true,
|
301
327
|
});
|
302
|
-
// Check if function exists in current directory
|
303
|
-
const functionPath = join(currentPath, functionName);
|
304
|
-
if (fs.existsSync(functionPath)) {
|
305
|
-
return functionPath;
|
306
|
-
}
|
307
|
-
// Add subdirectories to queue
|
308
328
|
for (const entry of entries) {
|
309
|
-
|
310
|
-
|
329
|
+
const fullPath = join(currentPath, entry.name);
|
330
|
+
// Skip node_modules and hidden directories
|
331
|
+
if (entry.isDirectory() &&
|
332
|
+
!entry.name.startsWith(".") &&
|
333
|
+
entry.name !== "node_modules") {
|
334
|
+
if (entry.name === functionName) {
|
335
|
+
console.log(chalk.green(`Found function at: ${fullPath}`));
|
336
|
+
return fullPath;
|
337
|
+
}
|
338
|
+
queue.push(fullPath);
|
311
339
|
}
|
312
340
|
}
|
313
341
|
}
|
314
342
|
catch (error) {
|
315
|
-
console.log(chalk.yellow(`
|
343
|
+
console.log(chalk.yellow(`Error reading directory ${currentPath}:`, error));
|
316
344
|
}
|
317
345
|
}
|
318
346
|
return null;
|
@@ -333,83 +361,127 @@ export class InteractiveCLI {
|
|
333
361
|
console.log(chalk.red("Invalid function configuration"));
|
334
362
|
return;
|
335
363
|
}
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
364
|
+
const { shouldDownload } = await inquirer.prompt([
|
365
|
+
{
|
366
|
+
type: "confirm",
|
367
|
+
name: "shouldDownload",
|
368
|
+
message: "Would you like to download the latest deployment?",
|
369
|
+
default: false,
|
370
|
+
},
|
371
|
+
]);
|
372
|
+
if (shouldDownload) {
|
373
|
+
try {
|
374
|
+
console.log(chalk.blue("Downloading latest deployment..."));
|
375
|
+
const { path: downloadedPath, function: remoteFunction } = await downloadLatestFunctionDeployment(this.controller.appwriteServer, functionConfig.$id, join(this.controller.getAppwriteFolderPath(), "functions"));
|
376
|
+
console.log(chalk.green(`✨ Function downloaded to ${downloadedPath}`));
|
377
|
+
// Update the config and functions array safely
|
378
|
+
this.controller.config.functions =
|
379
|
+
this.controller.config.functions || [];
|
380
|
+
const newFunction = {
|
381
|
+
$id: remoteFunction.$id,
|
382
|
+
name: remoteFunction.name,
|
383
|
+
runtime: remoteFunction.runtime,
|
384
|
+
execute: remoteFunction.execute || [],
|
385
|
+
events: remoteFunction.events || [],
|
386
|
+
schedule: remoteFunction.schedule || "",
|
387
|
+
timeout: remoteFunction.timeout || 15,
|
388
|
+
enabled: remoteFunction.enabled !== false,
|
389
|
+
logging: remoteFunction.logging !== false,
|
390
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
391
|
+
commands: remoteFunction.commands || "npm install",
|
392
|
+
dirPath: downloadedPath,
|
393
|
+
scopes: (remoteFunction.scopes || []),
|
394
|
+
installationId: remoteFunction.installationId,
|
395
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
396
|
+
providerBranch: remoteFunction.providerBranch,
|
397
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
398
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
399
|
+
specification: remoteFunction.specification,
|
400
|
+
};
|
401
|
+
const existingIndex = this.controller.config.functions.findIndex((f) => f?.$id === remoteFunction.$id);
|
402
|
+
if (existingIndex >= 0) {
|
403
|
+
this.controller.config.functions[existingIndex] = newFunction;
|
404
|
+
}
|
405
|
+
else {
|
406
|
+
this.controller.config.functions.push(newFunction);
|
407
|
+
}
|
408
|
+
const schemaGenerator = new SchemaGenerator(this.controller.config, this.controller.getAppwriteFolderPath());
|
409
|
+
schemaGenerator.updateConfig(this.controller.config);
|
410
|
+
console.log(chalk.green("✨ Updated appwriteConfig.ts with new function"));
|
411
|
+
await this.controller.reloadConfig();
|
412
|
+
functionConfig.dirPath = downloadedPath;
|
344
413
|
}
|
345
|
-
|
346
|
-
console.
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
providerSilentMode: remoteFunction.providerSilentMode,
|
381
|
-
providerRootDirectory: remoteFunction.providerRootDirectory,
|
382
|
-
specification: remoteFunction.specification,
|
383
|
-
};
|
384
|
-
const existingIndex = this.controller.config.functions.findIndex((f) => f?.$id === remoteFunction.$id);
|
385
|
-
if (existingIndex >= 0) {
|
386
|
-
this.controller.config.functions[existingIndex] = newFunction;
|
387
|
-
}
|
388
|
-
else {
|
389
|
-
this.controller.config.functions.push(newFunction);
|
390
|
-
}
|
391
|
-
const schemaGenerator = new SchemaGenerator(this.controller.config, this.controller.getAppwriteFolderPath());
|
392
|
-
schemaGenerator.updateConfig(this.controller.config);
|
393
|
-
console.log(chalk.green("✨ Updated appwriteConfig.ts with new function"));
|
394
|
-
await this.controller.reloadConfig();
|
395
|
-
functionConfig.dirPath = downloadedPath;
|
396
|
-
}
|
397
|
-
catch (error) {
|
398
|
-
console.error(chalk.red("Failed to download function deployment:"), error);
|
399
|
-
return;
|
400
|
-
}
|
414
|
+
catch (error) {
|
415
|
+
console.error(chalk.red("Failed to download function deployment:"), error);
|
416
|
+
return;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
else {
|
420
|
+
console.log(chalk.yellow("Skipping download, updating config only..."));
|
421
|
+
try {
|
422
|
+
// Update the config with remote function info
|
423
|
+
this.controller.config.functions =
|
424
|
+
this.controller.config.functions || [];
|
425
|
+
const remoteFunction = await getFunction(this.controller.appwriteServer, functionConfig.$id);
|
426
|
+
const newFunction = {
|
427
|
+
$id: remoteFunction.$id,
|
428
|
+
name: remoteFunction.name,
|
429
|
+
runtime: remoteFunction.runtime,
|
430
|
+
execute: remoteFunction.execute || [],
|
431
|
+
events: remoteFunction.events || [],
|
432
|
+
schedule: remoteFunction.schedule || "",
|
433
|
+
timeout: remoteFunction.timeout || 15,
|
434
|
+
enabled: remoteFunction.enabled !== false,
|
435
|
+
logging: remoteFunction.logging !== false,
|
436
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
437
|
+
commands: remoteFunction.commands || "npm install",
|
438
|
+
scopes: (remoteFunction.scopes || []),
|
439
|
+
installationId: remoteFunction.installationId,
|
440
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
441
|
+
providerBranch: remoteFunction.providerBranch,
|
442
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
443
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
444
|
+
specification: remoteFunction.specification,
|
445
|
+
};
|
446
|
+
const existingIndex = this.controller.config.functions.findIndex((f) => f?.$id === remoteFunction.$id);
|
447
|
+
if (existingIndex >= 0) {
|
448
|
+
this.controller.config.functions[existingIndex] = newFunction;
|
401
449
|
}
|
402
450
|
else {
|
403
|
-
|
404
|
-
return;
|
451
|
+
this.controller.config.functions.push(newFunction);
|
405
452
|
}
|
453
|
+
const schemaGenerator = new SchemaGenerator(this.controller.config, this.controller.getAppwriteFolderPath());
|
454
|
+
schemaGenerator.updateConfig(this.controller.config);
|
455
|
+
console.log(chalk.green("✨ Updated appwriteConfig.ts with function info"));
|
456
|
+
await this.controller.reloadConfig();
|
457
|
+
}
|
458
|
+
catch (error) {
|
459
|
+
console.error(chalk.red("Failed to update function config:"), error);
|
460
|
+
return;
|
406
461
|
}
|
407
462
|
}
|
408
|
-
if
|
409
|
-
|
410
|
-
|
463
|
+
// Only try to deploy if we didn't just download
|
464
|
+
if (!shouldDownload) {
|
465
|
+
let functionPath = join(this.controller.getAppwriteFolderPath(), "functions", functionConfig.name);
|
466
|
+
if (!fs.existsSync(functionPath)) {
|
467
|
+
console.log(chalk.yellow(`Function not found in primary location, searching subdirectories...`));
|
468
|
+
const foundPath = await this.findFunctionInSubdirectories(this.controller.getAppwriteFolderPath(), functionConfig.name);
|
469
|
+
if (foundPath) {
|
470
|
+
console.log(chalk.green(`Found function at: ${foundPath}`));
|
471
|
+
functionPath = foundPath;
|
472
|
+
functionConfig.dirPath = foundPath;
|
473
|
+
}
|
474
|
+
else {
|
475
|
+
console.log(chalk.red(`Function ${functionConfig.name} not found locally in any subdirectory. Cannot deploy.`));
|
476
|
+
return;
|
477
|
+
}
|
478
|
+
}
|
479
|
+
if (!this.controller.appwriteServer) {
|
480
|
+
console.log(chalk.red("Appwrite server not initialized"));
|
481
|
+
return;
|
482
|
+
}
|
483
|
+
await deployLocalFunction(this.controller.appwriteServer, functionConfig.name, functionConfig);
|
411
484
|
}
|
412
|
-
await deployLocalFunction(this.controller.appwriteServer, functionConfig.name, functionConfig);
|
413
485
|
}
|
414
486
|
async deleteFunction() {
|
415
487
|
const functions = await this.selectFunctions("Select functions to delete:", true, false);
|
@@ -777,55 +849,153 @@ export class InteractiveCLI {
|
|
777
849
|
const hasLocal = localFunctions.some((lf) => lf.$id === func.$id);
|
778
850
|
const hasRemote = remoteFunctions.some((rf) => rf.$id === func.$id);
|
779
851
|
if (hasLocal && hasRemote) {
|
852
|
+
// First try to find the function locally
|
853
|
+
let functionPath = join(this.controller.getAppwriteFolderPath(), "functions", func.name);
|
854
|
+
if (!fs.existsSync(functionPath)) {
|
855
|
+
console.log(chalk.yellow(`Function not found in primary location, searching subdirectories...`));
|
856
|
+
const foundPath = await this.findFunctionInSubdirectories(this.controller.getAppwriteFolderPath(), func.name);
|
857
|
+
if (foundPath) {
|
858
|
+
console.log(chalk.green(`Found function at: ${foundPath}`));
|
859
|
+
functionPath = foundPath;
|
860
|
+
}
|
861
|
+
}
|
780
862
|
const { preference } = await inquirer.prompt([
|
781
863
|
{
|
782
864
|
type: "list",
|
783
865
|
name: "preference",
|
784
|
-
message: `Function "${func.name}"
|
866
|
+
message: `Function "${func.name}" ${functionPath ? "found at " + functionPath : "not found locally"}. What would you like to do?`,
|
785
867
|
choices: [
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
868
|
+
...(functionPath
|
869
|
+
? [
|
870
|
+
{
|
871
|
+
name: "Keep local version (deploy to remote)",
|
872
|
+
value: "local",
|
873
|
+
},
|
874
|
+
]
|
875
|
+
: []),
|
790
876
|
{ name: "Use remote version (download)", value: "remote" },
|
877
|
+
{ name: "Update config only", value: "config" },
|
791
878
|
{ name: "Skip this function", value: "skip" },
|
792
879
|
],
|
793
880
|
},
|
794
881
|
]);
|
795
|
-
if (preference === "local") {
|
882
|
+
if (preference === "local" && functionPath) {
|
796
883
|
await this.controller.deployFunction(func.name);
|
797
884
|
}
|
798
885
|
else if (preference === "remote") {
|
799
886
|
await downloadLatestFunctionDeployment(this.controller.appwriteServer, func.$id, join(this.controller.getAppwriteFolderPath(), "functions"));
|
800
887
|
}
|
888
|
+
else if (preference === "config") {
|
889
|
+
const remoteFunction = await getFunction(this.controller.appwriteServer, func.$id);
|
890
|
+
const newFunction = {
|
891
|
+
$id: remoteFunction.$id,
|
892
|
+
name: remoteFunction.name,
|
893
|
+
runtime: remoteFunction.runtime,
|
894
|
+
execute: remoteFunction.execute || [],
|
895
|
+
events: remoteFunction.events || [],
|
896
|
+
schedule: remoteFunction.schedule || "",
|
897
|
+
timeout: remoteFunction.timeout || 15,
|
898
|
+
enabled: remoteFunction.enabled !== false,
|
899
|
+
logging: remoteFunction.logging !== false,
|
900
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
901
|
+
commands: remoteFunction.commands || "npm install",
|
902
|
+
scopes: (remoteFunction.scopes || []),
|
903
|
+
installationId: remoteFunction.installationId,
|
904
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
905
|
+
providerBranch: remoteFunction.providerBranch,
|
906
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
907
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
908
|
+
specification: remoteFunction.specification,
|
909
|
+
};
|
910
|
+
const existingIndex = this.controller.config.functions.findIndex((f) => f.$id === remoteFunction.$id);
|
911
|
+
if (existingIndex >= 0) {
|
912
|
+
this.controller.config.functions[existingIndex] = newFunction;
|
913
|
+
}
|
914
|
+
else {
|
915
|
+
this.controller.config.functions.push(newFunction);
|
916
|
+
}
|
917
|
+
console.log(chalk.green(`Updated config for function: ${func.name}`));
|
918
|
+
}
|
801
919
|
}
|
802
920
|
else if (hasLocal) {
|
803
|
-
|
921
|
+
// Similar check for local-only functions
|
922
|
+
let functionPath = join(this.controller.getAppwriteFolderPath(), "functions", func.name);
|
923
|
+
if (!fs.existsSync(functionPath)) {
|
924
|
+
const foundPath = await this.findFunctionInSubdirectories(this.controller.getAppwriteFolderPath(), func.name);
|
925
|
+
if (foundPath) {
|
926
|
+
functionPath = foundPath;
|
927
|
+
}
|
928
|
+
}
|
929
|
+
const { action } = await inquirer.prompt([
|
804
930
|
{
|
805
|
-
type: "
|
806
|
-
name: "
|
807
|
-
message: `Function "${func.name}"
|
808
|
-
|
931
|
+
type: "list",
|
932
|
+
name: "action",
|
933
|
+
message: `Function "${func.name}" ${functionPath ? "found at " + functionPath : "not found locally"}. What would you like to do?`,
|
934
|
+
choices: [
|
935
|
+
...(functionPath
|
936
|
+
? [
|
937
|
+
{
|
938
|
+
name: "Deploy to remote",
|
939
|
+
value: "deploy",
|
940
|
+
},
|
941
|
+
]
|
942
|
+
: []),
|
943
|
+
{ name: "Skip this function", value: "skip" },
|
944
|
+
],
|
809
945
|
},
|
810
946
|
]);
|
811
|
-
if (deploy) {
|
947
|
+
if (action === "deploy" && functionPath) {
|
812
948
|
await this.controller.deployFunction(func.name);
|
813
949
|
}
|
814
950
|
}
|
815
951
|
else if (hasRemote) {
|
816
|
-
const {
|
952
|
+
const { action } = await inquirer.prompt([
|
817
953
|
{
|
818
|
-
type: "
|
819
|
-
name: "
|
820
|
-
message: `Function "${func.name}" exists only remotely.
|
821
|
-
|
954
|
+
type: "list",
|
955
|
+
name: "action",
|
956
|
+
message: `Function "${func.name}" exists only remotely. What would you like to do?`,
|
957
|
+
choices: [
|
958
|
+
{ name: "Update config only", value: "config" },
|
959
|
+
{ name: "Download locally", value: "download" },
|
960
|
+
{ name: "Skip this function", value: "skip" },
|
961
|
+
],
|
822
962
|
},
|
823
963
|
]);
|
824
|
-
if (download) {
|
964
|
+
if (action === "download") {
|
825
965
|
await downloadLatestFunctionDeployment(this.controller.appwriteServer, func.$id, join(this.controller.getAppwriteFolderPath(), "functions"));
|
826
966
|
}
|
967
|
+
else if (action === "config") {
|
968
|
+
const remoteFunction = await getFunction(this.controller.appwriteServer, func.$id);
|
969
|
+
const newFunction = {
|
970
|
+
$id: remoteFunction.$id,
|
971
|
+
name: remoteFunction.name,
|
972
|
+
runtime: remoteFunction.runtime,
|
973
|
+
execute: remoteFunction.execute || [],
|
974
|
+
events: remoteFunction.events || [],
|
975
|
+
schedule: remoteFunction.schedule || "",
|
976
|
+
timeout: remoteFunction.timeout || 15,
|
977
|
+
enabled: remoteFunction.enabled !== false,
|
978
|
+
logging: remoteFunction.logging !== false,
|
979
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
980
|
+
commands: remoteFunction.commands || "npm install",
|
981
|
+
scopes: (remoteFunction.scopes || []),
|
982
|
+
installationId: remoteFunction.installationId,
|
983
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
984
|
+
providerBranch: remoteFunction.providerBranch,
|
985
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
986
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
987
|
+
specification: remoteFunction.specification,
|
988
|
+
};
|
989
|
+
this.controller.config.functions =
|
990
|
+
this.controller.config.functions || [];
|
991
|
+
this.controller.config.functions.push(newFunction);
|
992
|
+
console.log(chalk.green(`Added config for remote function: ${func.name}`));
|
993
|
+
}
|
827
994
|
}
|
828
995
|
}
|
996
|
+
// Update schemas after all changes
|
997
|
+
const schemaGenerator = new SchemaGenerator(this.controller.config, this.controller.getAppwriteFolderPath());
|
998
|
+
schemaGenerator.updateConfig(this.controller.config);
|
829
999
|
}
|
830
1000
|
console.log(chalk.green("✨ Configurations synchronized successfully!"));
|
831
1001
|
}
|
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.
|
4
|
+
"version": "0.10.0",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
package/src/interactiveCLI.ts
CHANGED
@@ -35,6 +35,7 @@ import {
|
|
35
35
|
createFunctionTemplate,
|
36
36
|
deleteFunction,
|
37
37
|
downloadLatestFunctionDeployment,
|
38
|
+
getFunction,
|
38
39
|
listFunctions,
|
39
40
|
listSpecifications,
|
40
41
|
} from "./functions/methods.js";
|
@@ -391,31 +392,70 @@ export class InteractiveCLI {
|
|
391
392
|
basePath: string,
|
392
393
|
functionName: string
|
393
394
|
): Promise<string | null> {
|
394
|
-
|
395
|
+
// Common locations to check first
|
396
|
+
const commonPaths = [
|
397
|
+
join(process.cwd(), "functions", functionName), // ./functions/functionName
|
398
|
+
join(process.cwd(), functionName), // ./functionName
|
399
|
+
join(basePath, "functions", functionName), // appwriteFolder/functions/functionName
|
400
|
+
join(basePath, functionName), // appwriteFolder/functionName
|
401
|
+
];
|
402
|
+
|
403
|
+
// Check common locations first
|
404
|
+
for (const path of commonPaths) {
|
405
|
+
try {
|
406
|
+
const stats = await fs.promises.stat(path);
|
407
|
+
if (stats.isDirectory()) {
|
408
|
+
console.log(
|
409
|
+
chalk.green(`Found function at common location: ${path}`)
|
410
|
+
);
|
411
|
+
return path;
|
412
|
+
}
|
413
|
+
} catch (error) {
|
414
|
+
// Path doesn't exist, continue to next
|
415
|
+
}
|
416
|
+
}
|
417
|
+
|
418
|
+
// If not found in common locations, do recursive search
|
419
|
+
console.log(
|
420
|
+
chalk.yellow(
|
421
|
+
"Function not found in common locations, searching subdirectories..."
|
422
|
+
)
|
423
|
+
);
|
424
|
+
|
425
|
+
const queue = [process.cwd(), basePath];
|
426
|
+
const searched = new Set<string>();
|
395
427
|
|
396
428
|
while (queue.length > 0) {
|
397
429
|
const currentPath = queue.shift()!;
|
398
430
|
|
431
|
+
if (searched.has(currentPath)) continue;
|
432
|
+
searched.add(currentPath);
|
433
|
+
|
399
434
|
try {
|
400
435
|
const entries = await fs.promises.readdir(currentPath, {
|
401
436
|
withFileTypes: true,
|
402
437
|
});
|
403
438
|
|
404
|
-
// Check if function exists in current directory
|
405
|
-
const functionPath = join(currentPath, functionName);
|
406
|
-
if (fs.existsSync(functionPath)) {
|
407
|
-
return functionPath;
|
408
|
-
}
|
409
|
-
|
410
|
-
// Add subdirectories to queue
|
411
439
|
for (const entry of entries) {
|
412
|
-
|
413
|
-
|
440
|
+
const fullPath = join(currentPath, entry.name);
|
441
|
+
|
442
|
+
// Skip node_modules and hidden directories
|
443
|
+
if (
|
444
|
+
entry.isDirectory() &&
|
445
|
+
!entry.name.startsWith(".") &&
|
446
|
+
entry.name !== "node_modules"
|
447
|
+
) {
|
448
|
+
if (entry.name === functionName) {
|
449
|
+
console.log(chalk.green(`Found function at: ${fullPath}`));
|
450
|
+
return fullPath;
|
451
|
+
}
|
452
|
+
|
453
|
+
queue.push(fullPath);
|
414
454
|
}
|
415
455
|
}
|
416
456
|
} catch (error) {
|
417
457
|
console.log(
|
418
|
-
chalk.yellow(`
|
458
|
+
chalk.yellow(`Error reading directory ${currentPath}:`, error)
|
419
459
|
);
|
420
460
|
}
|
421
461
|
}
|
@@ -447,127 +487,183 @@ export class InteractiveCLI {
|
|
447
487
|
return;
|
448
488
|
}
|
449
489
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
490
|
+
const { shouldDownload } = await inquirer.prompt([
|
491
|
+
{
|
492
|
+
type: "confirm",
|
493
|
+
name: "shouldDownload",
|
494
|
+
message: "Would you like to download the latest deployment?",
|
495
|
+
default: false,
|
496
|
+
},
|
497
|
+
]);
|
455
498
|
|
456
|
-
if (
|
457
|
-
|
458
|
-
chalk.
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
499
|
+
if (shouldDownload) {
|
500
|
+
try {
|
501
|
+
console.log(chalk.blue("Downloading latest deployment..."));
|
502
|
+
const { path: downloadedPath, function: remoteFunction } =
|
503
|
+
await downloadLatestFunctionDeployment(
|
504
|
+
this.controller.appwriteServer!,
|
505
|
+
functionConfig.$id,
|
506
|
+
join(this.controller.getAppwriteFolderPath(), "functions")
|
507
|
+
);
|
508
|
+
console.log(chalk.green(`✨ Function downloaded to ${downloadedPath}`));
|
509
|
+
|
510
|
+
// Update the config and functions array safely
|
511
|
+
this.controller.config.functions =
|
512
|
+
this.controller.config.functions || [];
|
513
|
+
|
514
|
+
const newFunction = {
|
515
|
+
$id: remoteFunction.$id,
|
516
|
+
name: remoteFunction.name,
|
517
|
+
runtime: remoteFunction.runtime as Runtime,
|
518
|
+
execute: remoteFunction.execute || [],
|
519
|
+
events: remoteFunction.events || [],
|
520
|
+
schedule: remoteFunction.schedule || "",
|
521
|
+
timeout: remoteFunction.timeout || 15,
|
522
|
+
enabled: remoteFunction.enabled !== false,
|
523
|
+
logging: remoteFunction.logging !== false,
|
524
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
525
|
+
commands: remoteFunction.commands || "npm install",
|
526
|
+
dirPath: downloadedPath,
|
527
|
+
scopes: (remoteFunction.scopes || []) as FunctionScope[],
|
528
|
+
installationId: remoteFunction.installationId,
|
529
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
530
|
+
providerBranch: remoteFunction.providerBranch,
|
531
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
532
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
533
|
+
specification: remoteFunction.specification as Specification,
|
534
|
+
};
|
535
|
+
|
536
|
+
const existingIndex = this.controller.config.functions.findIndex(
|
537
|
+
(f) => f?.$id === remoteFunction.$id
|
538
|
+
);
|
466
539
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
540
|
+
if (existingIndex >= 0) {
|
541
|
+
this.controller.config.functions[existingIndex] = newFunction;
|
542
|
+
} else {
|
543
|
+
this.controller.config.functions.push(newFunction);
|
544
|
+
}
|
545
|
+
|
546
|
+
const schemaGenerator = new SchemaGenerator(
|
547
|
+
this.controller.config,
|
548
|
+
this.controller.getAppwriteFolderPath()
|
549
|
+
);
|
550
|
+
schemaGenerator.updateConfig(this.controller.config);
|
472
551
|
console.log(
|
473
|
-
chalk.
|
474
|
-
`Function ${functionConfig.name} not found locally in any subdirectory`
|
475
|
-
)
|
552
|
+
chalk.green("✨ Updated appwriteConfig.ts with new function")
|
476
553
|
);
|
477
554
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
555
|
+
await this.controller.reloadConfig();
|
556
|
+
functionConfig.dirPath = downloadedPath;
|
557
|
+
} catch (error) {
|
558
|
+
console.error(
|
559
|
+
chalk.red("Failed to download function deployment:"),
|
560
|
+
error
|
561
|
+
);
|
562
|
+
return;
|
563
|
+
}
|
564
|
+
} else {
|
565
|
+
console.log(chalk.yellow("Skipping download, updating config only..."));
|
566
|
+
try {
|
567
|
+
// Update the config with remote function info
|
568
|
+
this.controller.config.functions =
|
569
|
+
this.controller.config.functions || [];
|
486
570
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
await downloadLatestFunctionDeployment(
|
492
|
-
this.controller.appwriteServer!,
|
493
|
-
functionConfig.$id,
|
494
|
-
join(this.controller.getAppwriteFolderPath(), "functions")
|
495
|
-
);
|
496
|
-
console.log(
|
497
|
-
chalk.green(`✨ Function downloaded to ${downloadedPath}`)
|
498
|
-
);
|
571
|
+
const remoteFunction = await getFunction(
|
572
|
+
this.controller.appwriteServer!,
|
573
|
+
functionConfig.$id
|
574
|
+
);
|
499
575
|
|
500
|
-
|
501
|
-
|
502
|
-
|
576
|
+
const newFunction = {
|
577
|
+
$id: remoteFunction.$id,
|
578
|
+
name: remoteFunction.name,
|
579
|
+
runtime: remoteFunction.runtime as Runtime,
|
580
|
+
execute: remoteFunction.execute || [],
|
581
|
+
events: remoteFunction.events || [],
|
582
|
+
schedule: remoteFunction.schedule || "",
|
583
|
+
timeout: remoteFunction.timeout || 15,
|
584
|
+
enabled: remoteFunction.enabled !== false,
|
585
|
+
logging: remoteFunction.logging !== false,
|
586
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
587
|
+
commands: remoteFunction.commands || "npm install",
|
588
|
+
scopes: (remoteFunction.scopes || []) as FunctionScope[],
|
589
|
+
installationId: remoteFunction.installationId,
|
590
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
591
|
+
providerBranch: remoteFunction.providerBranch,
|
592
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
593
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
594
|
+
specification: remoteFunction.specification as Specification,
|
595
|
+
};
|
596
|
+
|
597
|
+
const existingIndex = this.controller.config.functions.findIndex(
|
598
|
+
(f) => f?.$id === remoteFunction.$id
|
599
|
+
);
|
503
600
|
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
events: remoteFunction.events || [],
|
510
|
-
schedule: remoteFunction.schedule || "",
|
511
|
-
timeout: remoteFunction.timeout || 15,
|
512
|
-
enabled: remoteFunction.enabled !== false,
|
513
|
-
logging: remoteFunction.logging !== false,
|
514
|
-
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
515
|
-
commands: remoteFunction.commands || "npm install",
|
516
|
-
dirPath: downloadedPath,
|
517
|
-
scopes: (remoteFunction.scopes || []) as FunctionScope[],
|
518
|
-
installationId: remoteFunction.installationId,
|
519
|
-
providerRepositoryId: remoteFunction.providerRepositoryId,
|
520
|
-
providerBranch: remoteFunction.providerBranch,
|
521
|
-
providerSilentMode: remoteFunction.providerSilentMode,
|
522
|
-
providerRootDirectory: remoteFunction.providerRootDirectory,
|
523
|
-
specification: remoteFunction.specification as Specification,
|
524
|
-
};
|
601
|
+
if (existingIndex >= 0) {
|
602
|
+
this.controller.config.functions[existingIndex] = newFunction;
|
603
|
+
} else {
|
604
|
+
this.controller.config.functions.push(newFunction);
|
605
|
+
}
|
525
606
|
|
526
|
-
|
527
|
-
|
528
|
-
|
607
|
+
const schemaGenerator = new SchemaGenerator(
|
608
|
+
this.controller.config,
|
609
|
+
this.controller.getAppwriteFolderPath()
|
610
|
+
);
|
611
|
+
schemaGenerator.updateConfig(this.controller.config);
|
612
|
+
console.log(
|
613
|
+
chalk.green("✨ Updated appwriteConfig.ts with function info")
|
614
|
+
);
|
529
615
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
616
|
+
await this.controller.reloadConfig();
|
617
|
+
} catch (error) {
|
618
|
+
console.error(chalk.red("Failed to update function config:"), error);
|
619
|
+
return;
|
620
|
+
}
|
621
|
+
}
|
535
622
|
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
);
|
623
|
+
// Only try to deploy if we didn't just download
|
624
|
+
if (!shouldDownload) {
|
625
|
+
let functionPath = join(
|
626
|
+
this.controller.getAppwriteFolderPath(),
|
627
|
+
"functions",
|
628
|
+
functionConfig.name
|
629
|
+
);
|
544
630
|
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
631
|
+
if (!fs.existsSync(functionPath)) {
|
632
|
+
console.log(
|
633
|
+
chalk.yellow(
|
634
|
+
`Function not found in primary location, searching subdirectories...`
|
635
|
+
)
|
636
|
+
);
|
637
|
+
const foundPath = await this.findFunctionInSubdirectories(
|
638
|
+
this.controller.getAppwriteFolderPath(),
|
639
|
+
functionConfig.name
|
640
|
+
);
|
641
|
+
|
642
|
+
if (foundPath) {
|
643
|
+
console.log(chalk.green(`Found function at: ${foundPath}`));
|
644
|
+
functionPath = foundPath;
|
645
|
+
functionConfig.dirPath = foundPath;
|
554
646
|
} else {
|
555
|
-
console.log(
|
647
|
+
console.log(
|
648
|
+
chalk.red(
|
649
|
+
`Function ${functionConfig.name} not found locally in any subdirectory. Cannot deploy.`
|
650
|
+
)
|
651
|
+
);
|
556
652
|
return;
|
557
653
|
}
|
558
654
|
}
|
559
|
-
}
|
560
655
|
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
656
|
+
if (!this.controller.appwriteServer) {
|
657
|
+
console.log(chalk.red("Appwrite server not initialized"));
|
658
|
+
return;
|
659
|
+
}
|
565
660
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
661
|
+
await deployLocalFunction(
|
662
|
+
this.controller.appwriteServer,
|
663
|
+
functionConfig.name,
|
664
|
+
functionConfig
|
665
|
+
);
|
666
|
+
}
|
571
667
|
}
|
572
668
|
|
573
669
|
private async deleteFunction(): Promise<void> {
|
@@ -1063,23 +1159,54 @@ export class InteractiveCLI {
|
|
1063
1159
|
const hasRemote = remoteFunctions.some((rf) => rf.$id === func.$id);
|
1064
1160
|
|
1065
1161
|
if (hasLocal && hasRemote) {
|
1162
|
+
// First try to find the function locally
|
1163
|
+
let functionPath = join(
|
1164
|
+
this.controller!.getAppwriteFolderPath(),
|
1165
|
+
"functions",
|
1166
|
+
func.name
|
1167
|
+
);
|
1168
|
+
|
1169
|
+
if (!fs.existsSync(functionPath)) {
|
1170
|
+
console.log(
|
1171
|
+
chalk.yellow(
|
1172
|
+
`Function not found in primary location, searching subdirectories...`
|
1173
|
+
)
|
1174
|
+
);
|
1175
|
+
const foundPath = await this.findFunctionInSubdirectories(
|
1176
|
+
this.controller!.getAppwriteFolderPath(),
|
1177
|
+
func.name
|
1178
|
+
);
|
1179
|
+
|
1180
|
+
if (foundPath) {
|
1181
|
+
console.log(chalk.green(`Found function at: ${foundPath}`));
|
1182
|
+
functionPath = foundPath;
|
1183
|
+
}
|
1184
|
+
}
|
1185
|
+
|
1066
1186
|
const { preference } = await inquirer.prompt([
|
1067
1187
|
{
|
1068
1188
|
type: "list",
|
1069
1189
|
name: "preference",
|
1070
|
-
message: `Function "${func.name}"
|
1190
|
+
message: `Function "${func.name}" ${
|
1191
|
+
functionPath ? "found at " + functionPath : "not found locally"
|
1192
|
+
}. What would you like to do?`,
|
1071
1193
|
choices: [
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1194
|
+
...(functionPath
|
1195
|
+
? [
|
1196
|
+
{
|
1197
|
+
name: "Keep local version (deploy to remote)",
|
1198
|
+
value: "local",
|
1199
|
+
},
|
1200
|
+
]
|
1201
|
+
: []),
|
1076
1202
|
{ name: "Use remote version (download)", value: "remote" },
|
1203
|
+
{ name: "Update config only", value: "config" },
|
1077
1204
|
{ name: "Skip this function", value: "skip" },
|
1078
1205
|
],
|
1079
1206
|
},
|
1080
1207
|
]);
|
1081
1208
|
|
1082
|
-
if (preference === "local") {
|
1209
|
+
if (preference === "local" && functionPath) {
|
1083
1210
|
await this.controller!.deployFunction(func.name);
|
1084
1211
|
} else if (preference === "remote") {
|
1085
1212
|
await downloadLatestFunctionDeployment(
|
@@ -1087,39 +1214,152 @@ export class InteractiveCLI {
|
|
1087
1214
|
func.$id,
|
1088
1215
|
join(this.controller!.getAppwriteFolderPath(), "functions")
|
1089
1216
|
);
|
1217
|
+
} else if (preference === "config") {
|
1218
|
+
const remoteFunction = await getFunction(
|
1219
|
+
this.controller!.appwriteServer!,
|
1220
|
+
func.$id
|
1221
|
+
);
|
1222
|
+
|
1223
|
+
const newFunction = {
|
1224
|
+
$id: remoteFunction.$id,
|
1225
|
+
name: remoteFunction.name,
|
1226
|
+
runtime: remoteFunction.runtime as Runtime,
|
1227
|
+
execute: remoteFunction.execute || [],
|
1228
|
+
events: remoteFunction.events || [],
|
1229
|
+
schedule: remoteFunction.schedule || "",
|
1230
|
+
timeout: remoteFunction.timeout || 15,
|
1231
|
+
enabled: remoteFunction.enabled !== false,
|
1232
|
+
logging: remoteFunction.logging !== false,
|
1233
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
1234
|
+
commands: remoteFunction.commands || "npm install",
|
1235
|
+
scopes: (remoteFunction.scopes || []) as FunctionScope[],
|
1236
|
+
installationId: remoteFunction.installationId,
|
1237
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
1238
|
+
providerBranch: remoteFunction.providerBranch,
|
1239
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
1240
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
1241
|
+
specification: remoteFunction.specification as Specification,
|
1242
|
+
};
|
1243
|
+
|
1244
|
+
const existingIndex = this.controller!.config!.functions!.findIndex(
|
1245
|
+
(f) => f.$id === remoteFunction.$id
|
1246
|
+
);
|
1247
|
+
|
1248
|
+
if (existingIndex >= 0) {
|
1249
|
+
this.controller!.config!.functions![existingIndex] = newFunction;
|
1250
|
+
} else {
|
1251
|
+
this.controller!.config!.functions!.push(newFunction);
|
1252
|
+
}
|
1253
|
+
console.log(
|
1254
|
+
chalk.green(`Updated config for function: ${func.name}`)
|
1255
|
+
);
|
1090
1256
|
}
|
1091
1257
|
} else if (hasLocal) {
|
1092
|
-
|
1258
|
+
// Similar check for local-only functions
|
1259
|
+
let functionPath = join(
|
1260
|
+
this.controller!.getAppwriteFolderPath(),
|
1261
|
+
"functions",
|
1262
|
+
func.name
|
1263
|
+
);
|
1264
|
+
|
1265
|
+
if (!fs.existsSync(functionPath)) {
|
1266
|
+
const foundPath = await this.findFunctionInSubdirectories(
|
1267
|
+
this.controller!.getAppwriteFolderPath(),
|
1268
|
+
func.name
|
1269
|
+
);
|
1270
|
+
|
1271
|
+
if (foundPath) {
|
1272
|
+
functionPath = foundPath;
|
1273
|
+
}
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
const { action } = await inquirer.prompt([
|
1093
1277
|
{
|
1094
|
-
type: "
|
1095
|
-
name: "
|
1096
|
-
message: `Function "${func.name}"
|
1097
|
-
|
1278
|
+
type: "list",
|
1279
|
+
name: "action",
|
1280
|
+
message: `Function "${func.name}" ${
|
1281
|
+
functionPath ? "found at " + functionPath : "not found locally"
|
1282
|
+
}. What would you like to do?`,
|
1283
|
+
choices: [
|
1284
|
+
...(functionPath
|
1285
|
+
? [
|
1286
|
+
{
|
1287
|
+
name: "Deploy to remote",
|
1288
|
+
value: "deploy",
|
1289
|
+
},
|
1290
|
+
]
|
1291
|
+
: []),
|
1292
|
+
{ name: "Skip this function", value: "skip" },
|
1293
|
+
],
|
1098
1294
|
},
|
1099
1295
|
]);
|
1100
1296
|
|
1101
|
-
if (deploy) {
|
1297
|
+
if (action === "deploy" && functionPath) {
|
1102
1298
|
await this.controller!.deployFunction(func.name);
|
1103
1299
|
}
|
1104
1300
|
} else if (hasRemote) {
|
1105
|
-
const {
|
1301
|
+
const { action } = await inquirer.prompt([
|
1106
1302
|
{
|
1107
|
-
type: "
|
1108
|
-
name: "
|
1109
|
-
message: `Function "${func.name}" exists only remotely.
|
1110
|
-
|
1303
|
+
type: "list",
|
1304
|
+
name: "action",
|
1305
|
+
message: `Function "${func.name}" exists only remotely. What would you like to do?`,
|
1306
|
+
choices: [
|
1307
|
+
{ name: "Update config only", value: "config" },
|
1308
|
+
{ name: "Download locally", value: "download" },
|
1309
|
+
{ name: "Skip this function", value: "skip" },
|
1310
|
+
],
|
1111
1311
|
},
|
1112
1312
|
]);
|
1113
1313
|
|
1114
|
-
if (download) {
|
1314
|
+
if (action === "download") {
|
1115
1315
|
await downloadLatestFunctionDeployment(
|
1116
1316
|
this.controller!.appwriteServer!,
|
1117
1317
|
func.$id,
|
1118
1318
|
join(this.controller!.getAppwriteFolderPath(), "functions")
|
1119
1319
|
);
|
1320
|
+
} else if (action === "config") {
|
1321
|
+
const remoteFunction = await getFunction(
|
1322
|
+
this.controller!.appwriteServer!,
|
1323
|
+
func.$id
|
1324
|
+
);
|
1325
|
+
|
1326
|
+
const newFunction = {
|
1327
|
+
$id: remoteFunction.$id,
|
1328
|
+
name: remoteFunction.name,
|
1329
|
+
runtime: remoteFunction.runtime as Runtime,
|
1330
|
+
execute: remoteFunction.execute || [],
|
1331
|
+
events: remoteFunction.events || [],
|
1332
|
+
schedule: remoteFunction.schedule || "",
|
1333
|
+
timeout: remoteFunction.timeout || 15,
|
1334
|
+
enabled: remoteFunction.enabled !== false,
|
1335
|
+
logging: remoteFunction.logging !== false,
|
1336
|
+
entrypoint: remoteFunction.entrypoint || "src/index.ts",
|
1337
|
+
commands: remoteFunction.commands || "npm install",
|
1338
|
+
scopes: (remoteFunction.scopes || []) as FunctionScope[],
|
1339
|
+
installationId: remoteFunction.installationId,
|
1340
|
+
providerRepositoryId: remoteFunction.providerRepositoryId,
|
1341
|
+
providerBranch: remoteFunction.providerBranch,
|
1342
|
+
providerSilentMode: remoteFunction.providerSilentMode,
|
1343
|
+
providerRootDirectory: remoteFunction.providerRootDirectory,
|
1344
|
+
specification: remoteFunction.specification as Specification,
|
1345
|
+
};
|
1346
|
+
|
1347
|
+
this.controller!.config!.functions =
|
1348
|
+
this.controller!.config!.functions || [];
|
1349
|
+
this.controller!.config!.functions.push(newFunction);
|
1350
|
+
console.log(
|
1351
|
+
chalk.green(`Added config for remote function: ${func.name}`)
|
1352
|
+
);
|
1120
1353
|
}
|
1121
1354
|
}
|
1122
1355
|
}
|
1356
|
+
|
1357
|
+
// Update schemas after all changes
|
1358
|
+
const schemaGenerator = new SchemaGenerator(
|
1359
|
+
this.controller!.config!,
|
1360
|
+
this.controller!.getAppwriteFolderPath()
|
1361
|
+
);
|
1362
|
+
schemaGenerator.updateConfig(this.controller!.config!);
|
1123
1363
|
}
|
1124
1364
|
|
1125
1365
|
console.log(chalk.green("✨ Configurations synchronized successfully!"));
|