appwrite-cli 6.2.2 → 7.0.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.
Files changed (111) hide show
  1. package/README.md +8 -7
  2. package/docs/examples/console/get-resource.md +3 -0
  3. package/docs/examples/databases/create-documents.md +4 -0
  4. package/docs/examples/databases/create-index.md +1 -0
  5. package/docs/examples/databases/delete-documents.md +4 -0
  6. package/docs/examples/databases/update-documents.md +5 -0
  7. package/docs/examples/databases/update-float-attribute.md +2 -2
  8. package/docs/examples/databases/update-integer-attribute.md +2 -2
  9. package/docs/examples/databases/upsert-document.md +6 -0
  10. package/docs/examples/databases/upsert-documents.md +4 -0
  11. package/docs/examples/functions/{create-build.md → create-duplicate-deployment.md} +1 -1
  12. package/docs/examples/functions/create-template-deployment.md +7 -0
  13. package/docs/examples/functions/create-variable.md +2 -1
  14. package/docs/examples/functions/create-vcs-deployment.md +5 -0
  15. package/docs/examples/functions/create.md +0 -4
  16. package/docs/examples/functions/get-deployment-download.md +2 -1
  17. package/docs/examples/functions/get-usage.md +1 -0
  18. package/docs/examples/functions/list-executions.md +0 -1
  19. package/docs/examples/functions/list-usage.md +2 -0
  20. package/docs/examples/functions/{update-deployment-build.md → update-deployment-status.md} +1 -1
  21. package/docs/examples/functions/{update-deployment.md → update-function-deployment.md} +1 -1
  22. package/docs/examples/functions/update-variable.md +1 -0
  23. package/docs/examples/health/get-queue-stats-resources.md +2 -0
  24. package/docs/examples/migrations/create-csv-migration.md +4 -0
  25. package/docs/examples/project/create-variable.md +2 -1
  26. package/docs/examples/project/update-variable.md +1 -0
  27. package/docs/examples/projects/create-dev-key.md +4 -0
  28. package/docs/examples/projects/delete-dev-key.md +3 -0
  29. package/docs/examples/projects/get-dev-key.md +3 -0
  30. package/docs/examples/projects/list-dev-keys.md +3 -0
  31. package/docs/examples/projects/update-dev-key.md +5 -0
  32. package/docs/examples/proxy/create-a-p-i-rule.md +2 -0
  33. package/docs/examples/proxy/create-function-rule.md +4 -0
  34. package/docs/examples/proxy/create-redirect-rule.md +4 -0
  35. package/docs/examples/proxy/create-site-rule.md +4 -0
  36. package/docs/examples/sites/create-deployment.md +7 -0
  37. package/docs/examples/sites/create-duplicate-deployment.md +3 -0
  38. package/docs/examples/sites/create-template-deployment.md +7 -0
  39. package/docs/examples/sites/create-variable.md +5 -0
  40. package/docs/examples/sites/create-vcs-deployment.md +5 -0
  41. package/docs/examples/sites/create.md +19 -0
  42. package/docs/examples/sites/delete-deployment.md +3 -0
  43. package/docs/examples/sites/delete-log.md +3 -0
  44. package/docs/examples/sites/delete-variable.md +3 -0
  45. package/docs/examples/sites/delete.md +2 -0
  46. package/docs/examples/sites/get-deployment-download.md +4 -0
  47. package/docs/examples/sites/get-deployment.md +3 -0
  48. package/docs/examples/sites/get-log.md +3 -0
  49. package/docs/examples/sites/get-template.md +2 -0
  50. package/docs/examples/sites/get-usage.md +3 -0
  51. package/docs/examples/sites/get-variable.md +3 -0
  52. package/docs/examples/sites/get.md +2 -0
  53. package/docs/examples/sites/list-deployments.md +4 -0
  54. package/docs/examples/sites/list-frameworks.md +1 -0
  55. package/docs/examples/sites/list-logs.md +3 -0
  56. package/docs/examples/sites/list-specifications.md +1 -0
  57. package/docs/examples/sites/list-templates.md +5 -0
  58. package/docs/examples/sites/list-usage.md +2 -0
  59. package/docs/examples/sites/list-variables.md +2 -0
  60. package/docs/examples/sites/list.md +3 -0
  61. package/docs/examples/sites/update-deployment-status.md +3 -0
  62. package/docs/examples/sites/update-site-deployment.md +3 -0
  63. package/docs/examples/sites/update-variable.md +6 -0
  64. package/docs/examples/sites/update.md +19 -0
  65. package/docs/examples/storage/get-file-download.md +2 -1
  66. package/docs/examples/storage/get-file-preview.md +1 -0
  67. package/docs/examples/storage/get-file-view.md +2 -1
  68. package/docs/examples/tokens/create-file-token.md +4 -0
  69. package/docs/examples/tokens/delete.md +2 -0
  70. package/docs/examples/tokens/get.md +2 -0
  71. package/docs/examples/tokens/list.md +4 -0
  72. package/docs/examples/tokens/update.md +3 -0
  73. package/docs/examples/users/list-memberships.md +3 -1
  74. package/docs/examples/vcs/create-repository-detection.md +1 -0
  75. package/docs/examples/vcs/list-repositories.md +1 -0
  76. package/index.js +4 -0
  77. package/install.ps1 +2 -2
  78. package/install.sh +1 -1
  79. package/lib/client.js +12 -5
  80. package/lib/commands/account.js +7 -17
  81. package/lib/commands/avatars.js +9 -16
  82. package/lib/commands/console.js +50 -1
  83. package/lib/commands/databases.js +294 -62
  84. package/lib/commands/functions.js +244 -146
  85. package/lib/commands/generic.js +1 -1
  86. package/lib/commands/health.js +15 -73
  87. package/lib/commands/init.js +191 -0
  88. package/lib/commands/locale.js +0 -8
  89. package/lib/commands/messaging.js +38 -51
  90. package/lib/commands/migrations.js +56 -11
  91. package/lib/commands/project.js +12 -5
  92. package/lib/commands/projects.js +246 -27
  93. package/lib/commands/proxy.js +160 -19
  94. package/lib/commands/pull.js +124 -1
  95. package/lib/commands/push.js +338 -5
  96. package/lib/commands/sites.js +1663 -0
  97. package/lib/commands/storage.js +28 -22
  98. package/lib/commands/teams.js +2 -8
  99. package/lib/commands/tokens.js +261 -0
  100. package/lib/commands/users.js +15 -17
  101. package/lib/commands/vcs.js +60 -53
  102. package/lib/config.js +50 -0
  103. package/lib/parser.js +2 -1
  104. package/lib/questions.js +110 -1
  105. package/lib/utils.js +7 -1
  106. package/package.json +1 -1
  107. package/scoop/appwrite.json +3 -3
  108. package/docs/examples/functions/get-function-usage.md +0 -3
  109. package/docs/examples/health/get-queue-usage-dump.md +0 -2
  110. package/docs/examples/health/get-queue.md +0 -1
  111. package/docs/examples/proxy/create-rule.md +0 -4
@@ -7,17 +7,19 @@ const { messagingListTopics } = require("./messaging");
7
7
  const { teamsList } = require("./teams");
8
8
  const { projectsGet } = require("./projects");
9
9
  const { functionsList, functionsGetDeploymentDownload, functionsListDeployments } = require("./functions");
10
+ const { sitesList, sitesGetDeploymentDownload, sitesListDeployments } = require("./sites");
10
11
  const { databasesGet, databasesListCollections, databasesList } = require("./databases");
11
12
  const { storageListBuckets } = require("./storage");
12
13
  const { localConfig } = require("../config");
13
14
  const { paginate } = require("../paginate");
14
- const { questionsPullCollection, questionsPullFunctions, questionsPullFunctionsCode, questionsPullResources } = require("../questions");
15
+ const { questionsPullCollection, questionsPullFunctions, questionsPullFunctionsCode, questionsPullSites, questionsPullSitesCode, questionsPullResources } = require("../questions");
15
16
  const { cliConfig, success, log, warn, actionRunner, commandDescriptions } = require("../parser");
16
17
 
17
18
  const pullResources = async () => {
18
19
  const actions = {
19
20
  settings: pullSettings,
20
21
  functions: pullFunctions,
22
+ sites: pullSites,
21
23
  collections: pullCollection,
22
24
  buckets: pullBucket,
23
25
  teams: pullTeam,
@@ -169,6 +171,119 @@ const pullFunctions = async ({ code, withVariables }) => {
169
171
  success(`Successfully pulled ${chalk.bold(total)} functions.`);
170
172
  }
171
173
 
174
+ const pullSites = async ({ code, withVariables }) => {
175
+ process.chdir(localConfig.configDirectoryPath)
176
+
177
+ log("Fetching sites ...");
178
+ let total = 0;
179
+
180
+ const fetchResponse = await sitesList({
181
+ queries: [JSON.stringify({ method: 'limit', values: [1] })],
182
+ parseOutput: false
183
+ });
184
+ if (fetchResponse["sites"].length <= 0) {
185
+ log("No sites found.");
186
+ success(`Successfully pulled ${chalk.bold(total)} sites.`);
187
+ return;
188
+ }
189
+
190
+ const sites = cliConfig.all
191
+ ? (await paginate(sitesList, { parseOutput: false }, 100, 'sites')).sites
192
+ : (await inquirer.prompt(questionsPullSites)).sites;
193
+
194
+ let allowCodePull = cliConfig.force === true ? true : null;
195
+
196
+ for (let site of sites) {
197
+ total++;
198
+ log(`Pulling site ${chalk.bold(site['name'])} ...`);
199
+
200
+ const localSite = localConfig.getSite(site.$id);
201
+
202
+ site['path'] = localSite['path'];
203
+ if (!localSite['path']) {
204
+ site['path'] = `sites/${site.name}`;
205
+ }
206
+ const holdingVars = site['vars'];
207
+ // We don't save var in to the config
208
+ delete site['vars'];
209
+ localConfig.addSite(site);
210
+
211
+ if (!fs.existsSync(site['path'])) {
212
+ fs.mkdirSync(site['path'], { recursive: true });
213
+ }
214
+
215
+ if (code === false) {
216
+ warn("Source code download skipped.");
217
+ continue;
218
+ }
219
+
220
+ if (allowCodePull === null) {
221
+ const codeAnswer = await inquirer.prompt(questionsPullSitesCode);
222
+ allowCodePull = codeAnswer.override;
223
+ }
224
+
225
+ if (!allowCodePull) {
226
+ continue;
227
+ }
228
+
229
+ let deploymentId = null;
230
+
231
+ try {
232
+ const fetchResponse = await sitesListDeployments({
233
+ siteId: site['$id'],
234
+ queries: [
235
+ JSON.stringify({ method: 'limit', values: [1] }),
236
+ JSON.stringify({ method: 'orderDesc', values: ['$id'] })
237
+ ],
238
+ parseOutput: false
239
+ });
240
+
241
+ if (fetchResponse['total'] > 0) {
242
+ deploymentId = fetchResponse['deployments'][0]['$id'];
243
+ }
244
+
245
+ } catch {
246
+ }
247
+
248
+ if (deploymentId === null) {
249
+ log("Source code download skipped because site doesn't have any available deployment");
250
+ continue;
251
+ }
252
+
253
+ log("Pulling latest deployment code ...");
254
+
255
+ const compressedFileName = `${site['$id']}-${+new Date()}.tar.gz`
256
+ await sitesGetDeploymentDownload({
257
+ siteId: site['$id'],
258
+ deploymentId,
259
+ destination: compressedFileName,
260
+ overrideForCli: true,
261
+ parseOutput: false
262
+ });
263
+
264
+ tar.extract({
265
+ sync: true,
266
+ cwd: site['path'],
267
+ file: compressedFileName,
268
+ strict: false,
269
+ });
270
+
271
+ fs.rmSync(compressedFileName);
272
+
273
+ if (withVariables) {
274
+ const envFileLocation = `${site['path']}/.env`
275
+ try {
276
+ fs.rmSync(envFileLocation);
277
+ } catch {
278
+ }
279
+
280
+ fs.writeFileSync(envFileLocation, holdingVars.map(r => `${r.key}=${r.value}\n`).join(''))
281
+ }
282
+ }
283
+
284
+ success(`Successfully pulled ${chalk.bold(total)} sites.`);
285
+ }
286
+
172
287
  const pullCollection = async () => {
173
288
  log("Fetching collections ...");
174
289
  let total = 0;
@@ -321,6 +436,14 @@ pull
321
436
  .option("--with-variables", `Pull function variables. ${chalk.red('recommend for testing purposes only')}`)
322
437
  .action(actionRunner(pullFunctions))
323
438
 
439
+ pull
440
+ .command("site")
441
+ .alias("sites")
442
+ .description("Pull your Appwrite site")
443
+ .option("--no-code", "Don't pull the site's code")
444
+ .option("--with-variables", `Pull site variables. ${chalk.red('recommend for testing purposes only')}`)
445
+ .action(actionRunner(pullSites))
446
+
324
447
  pull
325
448
  .command("collection")
326
449
  .alias("collections")
@@ -2,13 +2,17 @@ const chalk = require('chalk');
2
2
  const inquirer = require("inquirer");
3
3
  const JSONbig = require("json-bigint")({ storeAsString: false });
4
4
  const { Command } = require("commander");
5
- const { localConfig, globalConfig, KeysAttributes, KeysFunction, whitelistKeys, KeysTopics, KeysStorage, KeysTeams, KeysCollection } = require("../config");
5
+ const ID = require("../id");
6
+ const { localConfig, globalConfig, KeysAttributes, KeysFunction, KeysSite, whitelistKeys, KeysTopics, KeysStorage, KeysTeams, KeysCollection } = require("../config");
6
7
  const { Spinner, SPINNER_ARC, SPINNER_DOTS } = require('../spinner');
7
8
  const { paginate } = require('../paginate');
8
- const { questionsPushBuckets, questionsPushTeams, questionsPushFunctions, questionsGetEntrypoint, questionsPushCollections, questionPushChanges, questionPushChangesConfirmation, questionsPushMessagingTopics, questionsPushResources } = require("../questions");
9
+ const { questionsPushBuckets, questionsPushTeams, questionsPushFunctions, questionsPushSites, questionsGetEntrypoint, questionsPushCollections, questionPushChanges, questionPushChangesConfirmation, questionsPushMessagingTopics, questionsPushResources } = require("../questions");
9
10
  const { cliConfig, actionRunner, success, warn, log, hint, error, commandDescriptions, drawTable } = require("../parser");
10
- const { proxyListRules } = require('./proxy');
11
+ const { proxyCreateFunctionRule, proxyCreateSiteRule, proxyListRules } = require('./proxy');
12
+ const { consoleVariables } = require('./console');
13
+ const { sdkForConsole } = require('../sdks')
11
14
  const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsGetDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
15
+ const { sitesGet, sitesCreate, sitesUpdate, sitesCreateDeployment, sitesGetDeployment, sitesCreateVariable } = require('./sites');
12
16
  const {
13
17
  databasesGet,
14
18
  databasesCreate,
@@ -896,6 +900,7 @@ const pushResources = async () => {
896
900
  const actions = {
897
901
  settings: pushSettings,
898
902
  functions: pushFunction,
903
+ sites: pushSite,
899
904
  collections: pushCollection,
900
905
  buckets: pushBucket,
901
906
  teams: pushTeam,
@@ -1006,6 +1011,303 @@ const pushSettings = async () => {
1006
1011
  }
1007
1012
  }
1008
1013
 
1014
+ const pushSite = async({ siteId, async, code } = { returnOnZero: false }) => {
1015
+ process.chdir(localConfig.configDirectoryPath)
1016
+
1017
+ const siteIds = [];
1018
+
1019
+ if(siteId) {
1020
+ siteIds.push(siteId);
1021
+ } else if (cliConfig.all) {
1022
+ checkDeployConditions(localConfig);
1023
+ const sites = localConfig.getSites();
1024
+ siteIds.push(...sites.map((site) => {
1025
+ return site.$id;
1026
+ }));
1027
+ }
1028
+
1029
+ if (siteIds.length <= 0) {
1030
+ const answers = await inquirer.prompt(questionsPushSites[0]);
1031
+ if (answers.sites) {
1032
+ siteIds.push(...answers.sites);
1033
+ }
1034
+ }
1035
+
1036
+ if (siteIds.length === 0) {
1037
+ log("No sites found.");
1038
+ hint("Use 'appwrite pull sites' to synchronize existing one, or use 'appwrite init site' to create a new one.");
1039
+ return;
1040
+ }
1041
+
1042
+ let sites = siteIds.map((id) => {
1043
+ const sites = localConfig.getSites();
1044
+ const site = sites.find((s) => s.$id === id);
1045
+
1046
+ if (!site) {
1047
+ throw new Error("Site '" + id + "' not found.")
1048
+ }
1049
+
1050
+ return site;
1051
+ });
1052
+
1053
+ log('Validating sites ...');
1054
+ // Validation is done BEFORE pushing so the deployment process can be run in async with progress update
1055
+ for (let site of sites) {
1056
+
1057
+ if (!site.buildCommand) {
1058
+ log(`Site ${site.name} is missing build command.`);
1059
+ const answers = await inquirer.prompt(questionsGetBuildCommand)
1060
+ site.buildCommand = answers.buildCommand;
1061
+ localConfig.addSite(site);
1062
+ }
1063
+ }
1064
+
1065
+ if (!(await approveChanges(sites, sitesGet, KeysSite, 'siteId', 'sites', ['vars']))) {
1066
+ return;
1067
+ }
1068
+
1069
+ log('Pushing sites ...');
1070
+
1071
+ Spinner.start(false);
1072
+ let successfullyPushed = 0;
1073
+ let successfullyDeployed = 0;
1074
+ const failedDeployments = [];
1075
+ const errors = [];
1076
+
1077
+ await Promise.all(sites.map(async (site) => {
1078
+ let response = {};
1079
+
1080
+ const ignore = site.ignore ? 'appwrite.json' : '.gitignore';
1081
+ let siteExists = false;
1082
+ let deploymentCreated = false;
1083
+
1084
+ const updaterRow = new Spinner({ status: '', resource: site.name, id: site['$id'], end: `Ignoring using: ${ignore}` });
1085
+
1086
+ updaterRow.update({ status: 'Getting' }).startSpinner(SPINNER_DOTS);
1087
+
1088
+ try {
1089
+ response = await sitesGet({
1090
+ siteId: site['$id'],
1091
+ parseOutput: false,
1092
+ });
1093
+ siteExists = true;
1094
+ if (response.framework !== site.framework) {
1095
+ updaterRow.fail({ errorMessage: `Framework mismatch! (local=${site.framework},remote=${response.framework}) Please delete remote site or update your appwrite.json` })
1096
+ return;
1097
+ }
1098
+
1099
+ updaterRow.update({ status: 'Updating' }).replaceSpinner(SPINNER_ARC);
1100
+
1101
+ response = await sitesUpdate({
1102
+ siteId: site['$id'],
1103
+ name: site.name,
1104
+ framework: site.framework,
1105
+ buildRuntime: site.buildRuntime,
1106
+ specification: site.specification,
1107
+ timeout: site.timeout,
1108
+ enabled: site.enabled,
1109
+ logging: site.logging,
1110
+ adapter: site.adapter,
1111
+ buildCommand: site.buildCommand,
1112
+ installCommand: site.installCommand,
1113
+ outputDirectory: site.outputDirectory,
1114
+ fallbackFile: site.fallbackFile,
1115
+ vars: JSON.stringify(response.vars),
1116
+ parseOutput: false
1117
+ });
1118
+ } catch (e) {
1119
+
1120
+ if (Number(e.code) === 404) {
1121
+ siteExists = false;
1122
+ } else {
1123
+ errors.push(e);
1124
+ updaterRow.fail({ errorMessage: e.message ?? 'General error occurs please try again' });
1125
+ return;
1126
+ }
1127
+ }
1128
+
1129
+ if (!siteExists) {
1130
+ updaterRow.update({ status: 'Creating' }).replaceSpinner(SPINNER_DOTS);
1131
+
1132
+ try {
1133
+ response = await sitesCreate({
1134
+ siteId: site.$id,
1135
+ name: site.name,
1136
+ framework: site.framework,
1137
+ specification: site.specification,
1138
+ buildRuntime: site.buildRuntime,
1139
+ buildCommand: site.buildCommand,
1140
+ installCommand: site.installCommand,
1141
+ outputDirectory: site.outputDirectory,
1142
+ fallbackFile: site.fallbackFile,
1143
+ adapter: site.adapter,
1144
+ timeout: site.timeout,
1145
+ enabled: site.enabled,
1146
+ logging: site.logging,
1147
+ vars: JSON.stringify(site.vars),
1148
+ parseOutput: false
1149
+ });
1150
+
1151
+ let domain = '';
1152
+ try {
1153
+ const variables = await consoleVariables({ parseOutput: false, sdk: await sdkForConsole() });
1154
+ domain = ID.unique() + '.' + variables['_APP_DOMAIN_SITES'];
1155
+ } catch (error) {
1156
+ console.error('Error fetching console variables.');
1157
+ throw error;
1158
+ }
1159
+
1160
+ try {
1161
+ const rule = await proxyCreateSiteRule(
1162
+ {
1163
+ domain: domain,
1164
+ siteId: site.$id
1165
+ }
1166
+ );
1167
+ } catch (error) {
1168
+ console.error('Error creating site rule.');
1169
+ throw error;
1170
+ }
1171
+
1172
+ updaterRow.update({ status: 'Created' });
1173
+ } catch (e) {
1174
+ errors.push(e)
1175
+ updaterRow.fail({ errorMessage: e.message ?? 'General error occurs please try again' });
1176
+ return;
1177
+ }
1178
+ }
1179
+
1180
+ updaterRow.update({ status: 'Creating variables' }).replaceSpinner(SPINNER_ARC);
1181
+
1182
+ await Promise.all((site['vars'] ?? []).map(async variable => {
1183
+ await sitesCreateVariable({
1184
+ siteId: site['$id'],
1185
+ key: variable['key'],
1186
+ value: variable['value'],
1187
+ parseOutput: false
1188
+ });
1189
+ }));
1190
+
1191
+ if (code === false) {
1192
+ successfullyPushed++;
1193
+ successfullyDeployed++;
1194
+ updaterRow.update({ status: 'Pushed' });
1195
+ updaterRow.stopSpinner();
1196
+ return;
1197
+ }
1198
+
1199
+ try {
1200
+ updaterRow.update({ status: 'Pushing' }).replaceSpinner(SPINNER_ARC);
1201
+ response = await sitesCreateDeployment({
1202
+ siteId: site['$id'],
1203
+ buildCommand: site.buildCommand,
1204
+ installCommand: site.installCommand,
1205
+ outputDirectory: site.outputDirectory,
1206
+ fallbackFile: site.fallbackFile,
1207
+ code: site.path,
1208
+ activate: true,
1209
+ parseOutput: false
1210
+ })
1211
+
1212
+ updaterRow.update({ status: 'Pushed' });
1213
+ deploymentCreated = true;
1214
+ successfullyPushed++;
1215
+ } catch (e) {
1216
+ errors.push(e);
1217
+
1218
+ switch (e.code) {
1219
+ case 'ENOENT':
1220
+ updaterRow.fail({ errorMessage: 'Not found in the current directory. Skipping...' })
1221
+ break;
1222
+ default:
1223
+ updaterRow.fail({ errorMessage: e.message ?? 'An unknown error occurred. Please try again.' })
1224
+ }
1225
+ }
1226
+
1227
+ if (deploymentCreated && !async) {
1228
+ try {
1229
+ const deploymentId = response['$id'];
1230
+ updaterRow.update({ status: 'Deploying', end: 'Checking deployment status...' })
1231
+ let pollChecks = 0;
1232
+
1233
+ while (true) {
1234
+ response = await sitesGetDeployment({
1235
+ siteId: site['$id'],
1236
+ deploymentId: deploymentId,
1237
+ parseOutput: false
1238
+ });
1239
+
1240
+ const status = response['status'];
1241
+ if (status === 'ready') {
1242
+ successfullyDeployed++;
1243
+
1244
+ let url = '';
1245
+ const res = await proxyListRules({
1246
+ parseOutput: false,
1247
+ queries: [
1248
+ JSON.stringify({ method: 'limit', values: [1] }),
1249
+ JSON.stringify({ method: 'equal', "attribute": "deploymentResourceType", "values": ["site"] }),
1250
+ JSON.stringify({ method: 'equal', "attribute": "deploymentResourceId", "values": [site['$id']] }),
1251
+ JSON.stringify({ method: 'equal', "attribute": "trigger", "values": ["manual"] }),
1252
+ ],
1253
+ });
1254
+
1255
+ if (Number(res.total) === 1) {
1256
+ url = res.rules[0].domain;
1257
+ }
1258
+
1259
+ updaterRow.update({ status: 'Deployed', end: url });
1260
+
1261
+ break;
1262
+ } else if (status === 'failed') {
1263
+ failedDeployments.push({ name: site['name'], $id: site['$id'], deployment: response['$id'] });
1264
+ updaterRow.fail({ errorMessage: `Failed to deploy` });
1265
+
1266
+ break;
1267
+ } else {
1268
+ updaterRow.update({ status: 'Deploying', end: `Current status: ${status}` })
1269
+ }
1270
+
1271
+ pollChecks++;
1272
+ await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE * 1.5));
1273
+ }
1274
+ } catch (e) {
1275
+ errors.push(e);
1276
+ updaterRow.fail({ errorMessage: e.message ?? 'Unknown error occurred. Please try again' })
1277
+ }
1278
+ }
1279
+
1280
+ updaterRow.stopSpinner();
1281
+ }));
1282
+
1283
+ Spinner.stop();
1284
+
1285
+ failedDeployments.forEach((failed) => {
1286
+ const { name, deployment, $id } = failed;
1287
+ const failUrl = `${globalConfig.getEndpoint().slice(0, -3)}/console/project-${localConfig.getProject().projectId}/sites/site-${$id}/deployments/deployment-${deployment}`;
1288
+
1289
+ error(`Deployment of ${name} has failed. Check at ${failUrl} for more details\n`);
1290
+ });
1291
+
1292
+ if (!async) {
1293
+ if (successfullyPushed === 0) {
1294
+ error('No sites were pushed.');
1295
+ } else if (successfullyDeployed !== successfullyPushed) {
1296
+ warn(`Successfully pushed ${successfullyDeployed} of ${successfullyPushed} sites`)
1297
+ } else {
1298
+ success(`Successfully pushed ${successfullyPushed} sites.`);
1299
+ }
1300
+ } else {
1301
+ success(`Successfully pushed ${successfullyPushed} sites.`);
1302
+ }
1303
+
1304
+ if (cliConfig.verbose) {
1305
+ errors.forEach(e => {
1306
+ console.error(e);
1307
+ })
1308
+ }
1309
+ }
1310
+
1009
1311
  const pushFunction = async ({ functionId, async, code, withVariables } = { returnOnZero: false }) => {
1010
1312
  process.chdir(localConfig.configDirectoryPath)
1011
1313
 
@@ -1141,6 +1443,27 @@ const pushFunction = async ({ functionId, async, code, withVariables } = { retur
1141
1443
  parseOutput: false
1142
1444
  });
1143
1445
 
1446
+ let domain = '';
1447
+ try {
1448
+ const variables = await consoleVariables({ parseOutput: false, sdk: await sdkForConsole() });
1449
+ domain = ID.unique() + '.' + variables['_APP_DOMAIN_FUNCTIONS'];
1450
+ } catch (error) {
1451
+ console.error('Error fetching console variables.');
1452
+ throw error;
1453
+ }
1454
+
1455
+ try {
1456
+ const rule = await proxyCreateFunctionRule(
1457
+ {
1458
+ domain: domain,
1459
+ functionId: func.$id
1460
+ }
1461
+ );
1462
+ } catch (error) {
1463
+ console.error('Error creating function rule.');
1464
+ throw error;
1465
+ }
1466
+
1144
1467
  updaterRow.update({ status: 'Created' });
1145
1468
  } catch (e) {
1146
1469
  errors.push(e)
@@ -1239,8 +1562,9 @@ const pushFunction = async ({ functionId, async, code, withVariables } = { retur
1239
1562
  parseOutput: false,
1240
1563
  queries: [
1241
1564
  JSON.stringify({ method: 'limit', values: [1] }),
1242
- JSON.stringify({ method: 'equal', "attribute": "resourceType", "values": ["function"] }),
1243
- JSON.stringify({ method: 'equal', "attribute": "resourceId", "values": [func['$id']] })
1565
+ JSON.stringify({ method: 'equal', "attribute": "deploymentResourceType", "values": ["function"] }),
1566
+ JSON.stringify({ method: 'equal', "attribute": "deploymentResourceId", "values": [func['$id']] }),
1567
+ JSON.stringify({ method: 'equal', "attribute": "trigger", "values": ["manual"] }),
1244
1568
  ],
1245
1569
  });
1246
1570
 
@@ -1698,6 +2022,15 @@ push
1698
2022
  .option("--with-variables", `Push function variables.`)
1699
2023
  .action(actionRunner(pushFunction));
1700
2024
 
2025
+ push
2026
+ .command("site")
2027
+ .alias("sites")
2028
+ .description("Push sites in the current directory.")
2029
+ .option(`-f, --site-id <site-id>`, `ID of site to run`)
2030
+ .option(`-A, --async`, `Don't wait for sites deployments status`)
2031
+ .option("--no-code", "Don't push the site's code")
2032
+ .action(actionRunner(pushSite));
2033
+
1701
2034
  push
1702
2035
  .command("collection")
1703
2036
  .alias("collections")