appwrite-cli 6.0.0-rc.1 → 6.0.0-rc.3

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.
@@ -6,7 +6,7 @@ const { localConfig, globalConfig } = require("../config");
6
6
  const { Spinner, SPINNER_ARC, SPINNER_DOTS } = require('../spinner');
7
7
  const { paginate } = require('../paginate');
8
8
  const { questionsPushBuckets, questionsPushTeams, questionsPushFunctions, questionsGetEntrypoint, questionsPushCollections, questionsConfirmPushCollections, questionsPushMessagingTopics, questionsPushResources } = require("../questions");
9
- const { cliConfig, actionRunner, success, log, error, commandDescriptions, drawTable } = require("../parser");
9
+ const { cliConfig, actionRunner, success, warn, log, error, commandDescriptions, drawTable } = require("../parser");
10
10
  const { proxyListRules } = require('./proxy');
11
11
  const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsUpdateDeployment, functionsGetDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
12
12
  const {
@@ -67,7 +67,7 @@ const { checkDeployConditions } = require('../utils');
67
67
 
68
68
  const STEP_SIZE = 100; // Resources
69
69
  const POLL_DEBOUNCE = 2000; // Milliseconds
70
- const POLL_MAX_DEBOUNCE = 30; // Times
70
+ const POLL_MAX_DEBOUNCE = 1800; // Times of POLL_DEBOUNCE (1 hour)
71
71
 
72
72
  let pollMaxDebounces = 30;
73
73
 
@@ -354,8 +354,8 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
354
354
  collectionId,
355
355
  key: attribute.key,
356
356
  required: attribute.required,
357
- min: parseInt(attribute.min.toString()),
358
- max: parseInt(attribute.max.toString()),
357
+ min: attribute.min,
358
+ max: attribute.max,
359
359
  xdefault: attribute.default,
360
360
  array: attribute.array,
361
361
  parseOutput: false
@@ -366,8 +366,8 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
366
366
  collectionId,
367
367
  key: attribute.key,
368
368
  required: attribute.required,
369
- min: parseFloat(attribute.min.toString()),
370
- max: parseFloat(attribute.max.toString()),
369
+ min: attribute.min,
370
+ max: attribute.max,
371
371
  xdefault: attribute.default,
372
372
  array: attribute.array,
373
373
  parseOutput: false
@@ -471,8 +471,8 @@ const updateAttribute = async (databaseId, collectionId, attribute) => {
471
471
  collectionId,
472
472
  key: attribute.key,
473
473
  required: attribute.required,
474
- min: parseInt(attribute.min.toString()),
475
- max: parseInt(attribute.max.toString()),
474
+ min: attribute.min,
475
+ max: attribute.max,
476
476
  xdefault: attribute.default,
477
477
  array: attribute.array,
478
478
  parseOutput: false
@@ -483,8 +483,8 @@ const updateAttribute = async (databaseId, collectionId, attribute) => {
483
483
  collectionId,
484
484
  key: attribute.key,
485
485
  required: attribute.required,
486
- min: parseFloat(attribute.min.toString()),
487
- max: parseFloat(attribute.max.toString()),
486
+ min: attribute.min,
487
+ max: attribute.max,
488
488
  xdefault: attribute.default,
489
489
  array: attribute.array,
490
490
  parseOutput: false
@@ -714,7 +714,7 @@ const createAttributes = async (attributes, collection) => {
714
714
 
715
715
  const pushResources = async () => {
716
716
  const actions = {
717
- project: pushProject,
717
+ settings: pushSettings,
718
718
  functions: pushFunction,
719
719
  collections: pushCollection,
720
720
  buckets: pushBucket,
@@ -736,15 +736,16 @@ const pushResources = async () => {
736
736
  }
737
737
  };
738
738
 
739
- const pushProject = async () => {
739
+ const pushSettings = async () => {
740
740
  try {
741
+ log("Pushing project settings ...");
742
+
741
743
  const projectId = localConfig.getProject().projectId;
742
744
  const projectName = localConfig.getProject().projectName;
743
745
  const settings = localConfig.getProject().projectSettings ?? {};
744
746
 
745
- log(`Updating project ${projectId}`);
746
-
747
747
  if (projectName) {
748
+ log("Applying project name ...");
748
749
  await projectsUpdate({
749
750
  projectId,
750
751
  name: projectName,
@@ -753,7 +754,7 @@ const pushProject = async () => {
753
754
  }
754
755
 
755
756
  if (settings.services) {
756
- log('Updating service statuses');
757
+ log("Applying service statuses ...");
757
758
  for (let [service, status] of Object.entries(settings.services)) {
758
759
  await projectsUpdateServiceStatus({
759
760
  projectId,
@@ -766,7 +767,7 @@ const pushProject = async () => {
766
767
 
767
768
  if (settings.auth) {
768
769
  if (settings.auth.security) {
769
- log('Updating auth security settings');
770
+ log("Applying auth security settings ...");
770
771
  await projectsUpdateAuthDuration({ projectId, duration: settings.auth.security.duration, parseOutput: false });
771
772
  await projectsUpdateAuthLimit({ projectId, limit: settings.auth.security.limit, parseOutput: false });
772
773
  await projectsUpdateAuthSessionsLimit({ projectId, limit: settings.auth.security.sessionsLimit, parseOutput: false });
@@ -776,7 +777,7 @@ const pushProject = async () => {
776
777
  }
777
778
 
778
779
  if (settings.auth.methods) {
779
- log('Updating auth login methods');
780
+ log("Applying auth methods statuses ...");
780
781
 
781
782
  for (let [method, status] of Object.entries(settings.auth.methods)) {
782
783
  await projectsUpdateAuthStatus({
@@ -789,7 +790,7 @@ const pushProject = async () => {
789
790
  }
790
791
  }
791
792
 
792
- success("Project configuration updated.");
793
+ success(`Successfully pushed ${chalk.bold('all')} project settings.`);
793
794
  } catch (e) {
794
795
  throw e;
795
796
  }
@@ -806,11 +807,9 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
806
807
  checkDeployConditions(localConfig);
807
808
  const functions = localConfig.getFunctions();
808
809
  if (functions.length === 0) {
809
- if (returnOnZero) {
810
- log('No functions found, skipping');
811
- return;
812
- }
813
- throw new Error("No functions found in the current directory. Use 'appwrite pull functions' to synchronize existing one, or use 'appwrite init function' to create a new one.");
810
+ log("No functions found.");
811
+ hint("Use 'appwrite pull functions' to synchronize existing one, or use 'appwrite init function' to create a new one.");
812
+ return;
814
813
  }
815
814
  functionIds.push(...functions.map((func) => {
816
815
  return func.$id;
@@ -833,45 +832,19 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
833
832
  return func;
834
833
  });
835
834
 
836
- log('Validating functions');
835
+ log('Validating functions ...');
837
836
  // Validation is done BEFORE pushing so the deployment process can be run in async with progress update
838
837
  for (let func of functions) {
839
838
 
840
839
  if (!func.entrypoint) {
841
- log(`Function ${func.name} does not have an endpoint`);
840
+ log(`Function ${func.name} is missing an entrypoint.`);
842
841
  const answers = await inquirer.prompt(questionsGetEntrypoint)
843
842
  func.entrypoint = answers.entrypoint;
844
- localConfig.updateFunction(func['$id'], func);
845
- }
846
-
847
- if (func.variables) {
848
- func.pushVariables = cliConfig.force;
849
-
850
- try {
851
- const { total } = await functionsListVariables({
852
- functionId: func['$id'],
853
- queries: [JSON.stringify({ method: 'limit', values: [1] })],
854
- parseOutput: false
855
- });
856
-
857
- if (total === 0) {
858
- func.pushVariables = true;
859
- } else if (total > 0 && !func.pushVariables) {
860
- log(`The function ${func.name} has remote variables setup`);
861
- const variableAnswers = await inquirer.prompt(questionsPushFunctions[1])
862
- func.pushVariables = variableAnswers.override.toLowerCase() === "yes";
863
- }
864
- } catch (e) {
865
- if (e.code != 404) {
866
- throw e.message;
867
- }
868
- }
843
+ localConfig.addFunction(func);
869
844
  }
870
845
  }
871
846
 
872
-
873
- log('All functions are validated');
874
- log('Pushing functions\n');
847
+ log('Pushing functions ...');
875
848
 
876
849
  Spinner.start(false);
877
850
  let successfullyPushed = 0;
@@ -911,6 +884,7 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
911
884
  logging: func.logging,
912
885
  entrypoint: func.entrypoint,
913
886
  commands: func.commands,
887
+ scopes: func.scopes,
914
888
  providerRepositoryId: func.providerRepositoryId ?? "",
915
889
  installationId: func.installationId ?? '',
916
890
  providerBranch: func.providerBranch ?? '',
@@ -934,7 +908,7 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
934
908
 
935
909
  try {
936
910
  response = await functionsCreate({
937
- functionId: func.$id || 'unique()',
911
+ functionId: func.$id,
938
912
  name: func.name,
939
913
  runtime: func.runtime,
940
914
  execute: func.execute,
@@ -949,10 +923,6 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
949
923
  parseOutput: false
950
924
  });
951
925
 
952
- localConfig.updateFunction(func['$id'], {
953
- "$id": response['$id'],
954
- });
955
- func["$id"] = response['$id'];
956
926
  updaterRow.update({ status: 'Created' });
957
927
  } catch (e) {
958
928
  updaterRow.fail({ errorMessage: e.message ?? 'General error occurs please try again' });
@@ -960,43 +930,6 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
960
930
  }
961
931
  }
962
932
 
963
- if (func.variables) {
964
- if (!func.pushVariables) {
965
- updaterRow.update({ end: 'Skipping variables' });
966
- } else {
967
- updaterRow.update({ end: 'Pushing variables' });
968
-
969
- const { variables } = await paginate(functionsListVariables, {
970
- functionId: func['$id'],
971
- parseOutput: false
972
- }, 100, 'variables');
973
-
974
- await Promise.all(variables.map(async variable => {
975
- await functionsDeleteVariable({
976
- functionId: func['$id'],
977
- variableId: variable['$id'],
978
- parseOutput: false
979
- });
980
- }));
981
-
982
- let result = await awaitPools.wipeVariables(func['$id']);
983
- if (!result) {
984
- updaterRow.fail({ errorMessage: 'Variable deletion timed out' })
985
- return;
986
- }
987
-
988
- // Push local variables
989
- await Promise.all(Object.keys(func.variables).map(async localVariableKey => {
990
- await functionsCreateVariable({
991
- functionId: func['$id'],
992
- key: localVariableKey,
993
- value: func.variables[localVariableKey],
994
- parseOutput: false
995
- });
996
- }));
997
- }
998
- }
999
-
1000
933
  try {
1001
934
  updaterRow.update({ status: 'Pushing' }).replaceSpinner(SPINNER_ARC);
1002
935
  response = await functionsCreateDeployment({
@@ -1082,27 +1015,25 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
1082
1015
  }));
1083
1016
 
1084
1017
  Spinner.stop();
1085
- console.log('\n');
1086
1018
 
1087
1019
  failedDeployments.forEach((failed) => {
1088
1020
  const { name, deployment, $id } = failed;
1089
1021
  const failUrl = `${globalConfig.getEndpoint().replace('/v1', '')}/console/project-${localConfig.getProject().projectId}/functions/function-${$id}/deployment-${deployment}`;
1090
1022
 
1091
1023
  error(`Deployment of ${name} has failed. Check at ${failUrl} for more details\n`);
1092
- })
1093
-
1094
- let message = chalk.green(`Pushed and deployed ${successfullyPushed} functions`);
1024
+ });
1095
1025
 
1096
1026
  if (!async) {
1097
- if (successfullyDeployed < successfullyPushed) {
1098
- message = `${chalk.green(`Pushed and deployed ${successfullyPushed} functions.`)} ${chalk.red(`${successfullyPushed - successfullyDeployed} failed to deploy`)}`;
1027
+ if(successfullyPushed === 0) {
1028
+ error('No functions were pushed.');
1029
+ } else if(successfullyDeployed != successfullyPushed) {
1030
+ warn(`Successfully pushed ${successfullyDeployed} of ${successfullyPushed} functions`)
1099
1031
  } else {
1100
- if (successfullyPushed === 0) {
1101
- message = chalk.red(`Error pushing ${functions.length} functions`)
1102
- }
1032
+ success(`Successfully pushed ${successfullyPushed} functions.`);
1103
1033
  }
1034
+ } else {
1035
+ success(`Successfully pushed ${successfullyPushed} functions.`);
1104
1036
  }
1105
- log(message);
1106
1037
  }
1107
1038
 
1108
1039
  const pushCollection = async ({ returnOnZero } = { returnOnZero: false }) => {
@@ -1111,12 +1042,9 @@ const pushCollection = async ({ returnOnZero } = { returnOnZero: false }) => {
1111
1042
  if (cliConfig.all) {
1112
1043
  checkDeployConditions(localConfig);
1113
1044
  if (localConfig.getCollections().length === 0) {
1114
- if (returnOnZero) {
1115
- log('No collections found, skipping');
1116
- return;
1117
- }
1118
-
1119
- throw new Error("No collections found in the current directory. Use 'appwrite pull collections' to synchronize existing one, or use 'appwrite init collection' to create a new one.");
1045
+ log("No collections found.");
1046
+ hint("Use 'appwrite pull collections' to synchronize existing one, or use 'appwrite init collection' to create a new one.");
1047
+ return;
1120
1048
  }
1121
1049
  collections.push(...localConfig.getCollections());
1122
1050
  } else {
@@ -1131,7 +1059,8 @@ const pushCollection = async ({ returnOnZero } = { returnOnZero: false }) => {
1131
1059
  })
1132
1060
  }
1133
1061
  const databases = Array.from(new Set(collections.map(collection => collection['databaseId'])));
1134
- log('Checking for databases and collection changes');
1062
+
1063
+ log('Checking for changes ...');
1135
1064
 
1136
1065
  // Parallel db actions
1137
1066
  await Promise.all(databases.map(async (databaseId) => {
@@ -1153,7 +1082,7 @@ const pushCollection = async ({ returnOnZero } = { returnOnZero: false }) => {
1153
1082
  success(`Updated ${localDatabase.name} ( ${databaseId} ) name`);
1154
1083
  }
1155
1084
  } catch (err) {
1156
- log(`Database ${databaseId} not found. Creating it now...`);
1085
+ log(`Database ${databaseId} not found. Creating it now ...`);
1157
1086
 
1158
1087
  await databasesCreate({
1159
1088
  databaseId: databaseId,
@@ -1243,11 +1172,9 @@ const pushBucket = async ({ returnOnZero } = { returnOnZero: false }) => {
1243
1172
  if (cliConfig.all) {
1244
1173
  checkDeployConditions(localConfig);
1245
1174
  if (configBuckets.length === 0) {
1246
- if (returnOnZero) {
1247
- log('No buckets found, skipping');
1248
- return;
1249
- }
1250
- throw new Error("No buckets found in the current directory. Use 'appwrite pull buckets' to synchronize existing one, or use 'appwrite init bucket' to create a new one.");
1175
+ log("No buckets found.");
1176
+ hint("Use 'appwrite pull buckets' to synchronize existing one, or use 'appwrite init bucket' to create a new one.");
1177
+ return;
1251
1178
  }
1252
1179
  bucketIds.push(...configBuckets.map((b) => b.$id));
1253
1180
  }
@@ -1264,8 +1191,10 @@ const pushBucket = async ({ returnOnZero } = { returnOnZero: false }) => {
1264
1191
  buckets.push(...idBuckets);
1265
1192
  }
1266
1193
 
1194
+ log('Pushing buckets ...');
1195
+
1267
1196
  for (let bucket of buckets) {
1268
- log(`Pushing bucket ${bucket.name} ( ${bucket['$id']} )`)
1197
+ log(`Pushing bucket ${chalk.bold(bucket['name'])} ...`);
1269
1198
 
1270
1199
  try {
1271
1200
  response = await storageGetBucket({
@@ -1273,8 +1202,6 @@ const pushBucket = async ({ returnOnZero } = { returnOnZero: false }) => {
1273
1202
  parseOutput: false,
1274
1203
  })
1275
1204
 
1276
- log(`Updating bucket ...`)
1277
-
1278
1205
  await storageUpdateBucket({
1279
1206
  bucketId: bucket['$id'],
1280
1207
  name: bucket.name,
@@ -1288,8 +1215,6 @@ const pushBucket = async ({ returnOnZero } = { returnOnZero: false }) => {
1288
1215
  compression: bucket.compression,
1289
1216
  parseOutput: false
1290
1217
  });
1291
-
1292
- success(`Pushed ${bucket.name} ( ${bucket['$id']} )`);
1293
1218
  } catch (e) {
1294
1219
  if (Number(e.code) === 404) {
1295
1220
  log(`Bucket ${bucket.name} does not exist in the project. Creating ... `);
@@ -1307,13 +1232,13 @@ const pushBucket = async ({ returnOnZero } = { returnOnZero: false }) => {
1307
1232
  antivirus: bucket.antivirus,
1308
1233
  parseOutput: false
1309
1234
  })
1310
-
1311
- success(`Pushed ${bucket.name} ( ${bucket['$id']} )`);
1312
1235
  } else {
1313
1236
  throw e;
1314
1237
  }
1315
1238
  }
1316
1239
  }
1240
+
1241
+ success(`Successfully pushed ${buckets.length} buckets.`);
1317
1242
  }
1318
1243
 
1319
1244
  const pushTeam = async ({ returnOnZero } = { returnOnZero: false }) => {
@@ -1325,11 +1250,8 @@ const pushTeam = async ({ returnOnZero } = { returnOnZero: false }) => {
1325
1250
  if (cliConfig.all) {
1326
1251
  checkDeployConditions(localConfig);
1327
1252
  if (configTeams.length === 0) {
1328
- if (returnOnZero) {
1329
- log('No teams found, skipping');
1330
- return;
1331
- }
1332
- throw new Error("No teams found in the current directory. Use 'appwrite pull teams' to synchronize existing one, or use 'appwrite init team' to create a new one.");
1253
+ log("No teams found.");
1254
+ hint("Use 'appwrite pull teams' to synchronize existing one, or use 'appwrite init team' to create a new one.");
1333
1255
  }
1334
1256
  teamIds.push(...configTeams.map((t) => t.$id));
1335
1257
  }
@@ -1346,8 +1268,10 @@ const pushTeam = async ({ returnOnZero } = { returnOnZero: false }) => {
1346
1268
  teams.push(...idTeams);
1347
1269
  }
1348
1270
 
1271
+ log('Pushing teams ...');
1272
+
1349
1273
  for (let team of teams) {
1350
- log(`Pushing team ${team.name} ( ${team['$id']} )`)
1274
+ log(`Pushing team ${chalk.bold(team['name'])} ...`);
1351
1275
 
1352
1276
  try {
1353
1277
  response = await teamsGet({
@@ -1355,15 +1279,11 @@ const pushTeam = async ({ returnOnZero } = { returnOnZero: false }) => {
1355
1279
  parseOutput: false,
1356
1280
  })
1357
1281
 
1358
- log(`Updating team ...`)
1359
-
1360
1282
  await teamsUpdateName({
1361
1283
  teamId: team['$id'],
1362
1284
  name: team.name,
1363
1285
  parseOutput: false
1364
1286
  });
1365
-
1366
- success(`Pushed ${team.name} ( ${team['$id']} )`);
1367
1287
  } catch (e) {
1368
1288
  if (Number(e.code) === 404) {
1369
1289
  log(`Team ${team.name} does not exist in the project. Creating ... `);
@@ -1373,13 +1293,13 @@ const pushTeam = async ({ returnOnZero } = { returnOnZero: false }) => {
1373
1293
  name: team.name,
1374
1294
  parseOutput: false
1375
1295
  })
1376
-
1377
- success(`Pushed ${team.name} ( ${team['$id']} )`);
1378
1296
  } else {
1379
1297
  throw e;
1380
1298
  }
1381
1299
  }
1382
1300
  }
1301
+
1302
+ success(`Successfully pushed ${teams.length} teams.`);
1383
1303
  }
1384
1304
 
1385
1305
  const pushMessagingTopic = async ({ returnOnZero } = { returnOnZero: false }) => {
@@ -1392,11 +1312,8 @@ const pushMessagingTopic = async ({ returnOnZero } = { returnOnZero: false }) =>
1392
1312
  if (cliConfig.all) {
1393
1313
  checkDeployConditions(localConfig);
1394
1314
  if (configTopics.length === 0) {
1395
- if (returnOnZero) {
1396
- log('No topics found, skipping');
1397
- return;
1398
- }
1399
- throw new Error("No topics found in the current directory. Use 'appwrite pull topics' to synchronize existing one, or use 'appwrite init topic' to create a new one.");
1315
+ log("No topics found.");
1316
+ hint("Use 'appwrite pull topics' to synchronize existing one, or use 'appwrite init topic' to create a new one.");
1400
1317
  }
1401
1318
  topicsIds.push(...configTopics.map((b) => b.$id));
1402
1319
  }
@@ -1420,8 +1337,10 @@ const pushMessagingTopic = async ({ returnOnZero } = { returnOnZero: false }) =>
1420
1337
  }
1421
1338
  }
1422
1339
 
1340
+ log('Pushing topics ...');
1341
+
1423
1342
  for (let topic of topics) {
1424
- log(`Pushing topic ${topic.name} ( ${topic['$id']} )`)
1343
+ log(`Pushing topic ${chalk.bold(topic['name'])} ...`);
1425
1344
 
1426
1345
  try {
1427
1346
  response = await messagingGetTopic({
@@ -1435,16 +1354,12 @@ const pushMessagingTopic = async ({ returnOnZero } = { returnOnZero: false }) =>
1435
1354
  continue;
1436
1355
  }
1437
1356
 
1438
- log(`Updating Topic ...`)
1439
-
1440
1357
  await messagingUpdateTopic({
1441
1358
  topicId: topic['$id'],
1442
1359
  name: topic.name,
1443
1360
  subscribe: topic.subscribe,
1444
1361
  parseOutput: false
1445
1362
  });
1446
-
1447
- success(`Pushed ${topic.name} ( ${topic['$id']} )`);
1448
1363
  } catch (e) {
1449
1364
  if (Number(e.code) === 404) {
1450
1365
  log(`Topic ${topic.name} does not exist in the project. Creating ... `);
@@ -1462,6 +1377,8 @@ const pushMessagingTopic = async ({ returnOnZero } = { returnOnZero: false }) =>
1462
1377
  }
1463
1378
  }
1464
1379
  }
1380
+
1381
+ success(`Successfully pushed ${topics.length} topics.`);
1465
1382
  }
1466
1383
 
1467
1384
  const push = new Command("push")
@@ -1477,9 +1394,9 @@ push
1477
1394
  }));
1478
1395
 
1479
1396
  push
1480
- .command("project")
1397
+ .command("settings")
1481
1398
  .description("Push project name, services and auth settings")
1482
- .action(actionRunner(pushProject));
1399
+ .action(actionRunner(pushSettings));
1483
1400
 
1484
1401
  push
1485
1402
  .command("function")
@@ -1513,6 +1430,13 @@ push
1513
1430
  .description("Push messaging topics in the current project.")
1514
1431
  .action(actionRunner(pushMessagingTopic));
1515
1432
 
1433
+ const deploy = new Command("deploy")
1434
+ .description(commandDescriptions['push'])
1435
+ .action(actionRunner(async () => {
1436
+ warn("Did you mean to run 'appwrite push' command?");
1437
+ }));
1438
+
1516
1439
  module.exports = {
1517
- push
1440
+ push,
1441
+ deploy
1518
1442
  }