1+ const fs = require('fs');
2+ const path = require('path');
3+ const { parse: parseDotenv } = require('dotenv');
14const chalk = require('chalk');
25const inquirer = require("inquirer");
36const JSONbig = require("json-bigint")({ storeAsString: false });
@@ -12,7 +15,7 @@ const { proxyCreateFunctionRule, proxyCreateSiteRule, proxyListRules } = require
1215const { consoleVariables } = require('./console');
1316const { sdkForConsole } = require('../sdks')
1417const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsGetDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
15- const { sitesGet, sitesCreate, sitesUpdate, sitesCreateDeployment, sitesGetDeployment, sitesCreateVariable } = require('./sites');
18+ const { sitesGet, sitesCreate, sitesUpdate, sitesCreateDeployment, sitesGetDeployment, sitesCreateVariable, sitesListVariables, sitesDeleteVariable } = require('./sites');
1619const {
1720 databasesGet,
1821 databasesCreate,
@@ -149,37 +152,6 @@ const awaitPools = {
149152 iteration + 1
150153 );
151154 },
152- wipeVariables: async (functionId, iteration = 1) => {
153- if (iteration > pollMaxDebounces) {
154- return false;
155- }
156-
157- const { total } = await functionsListVariables({
158- functionId,
159- queries: ['limit(1)'],
160- parseOutput: false
161- });
162-
163- if (total === 0) {
164- return true;
165- }
166-
167- if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
168- let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
169- if (steps > 1 && iteration === 1) {
170- pollMaxDebounces *= steps;
171-
172- log('Found a large number of variables, increasing timeout to ' + (pollMaxDebounces * POLL_DEBOUNCE / 1000 / 60) + ' minutes')
173- }
174- }
175-
176- await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
177-
178- return await awaitPools.wipeVariables(
179- functionId,
180- iteration + 1
181- );
182- },
183155 deleteAttributes: async (databaseId, collectionId, attributeKeys, iteration = 1) => {
184156 if (iteration > pollMaxDebounces) {
185157 return false;
@@ -445,8 +417,17 @@ const getObjectChanges = (remote, local, index, what) => {
445417
446418 if (remote[index] && local[index]) {
447419 for (let [service, status] of Object.entries(remote[index])) {
448- if (status !== local[index][service]) {
449- changes.push({ group: what, setting: service, remote: chalk.red(status), local: chalk.green(local[index][service]) })
420+ const localValue = local[index][service];
421+ let valuesEqual = false;
422+
423+ if (Array.isArray(status) && Array.isArray(localValue)) {
424+ valuesEqual = JSON.stringify(status) === JSON.stringify(localValue);
425+ } else {
426+ valuesEqual = status === localValue;
427+ }
428+
429+ if (!valuesEqual) {
430+ changes.push({ group: what, setting: service, remote: chalk.red(status), local: chalk.green(localValue) })
450431 }
451432 }
452433 }
@@ -508,6 +489,7 @@ const createAttribute = (databaseId, collectionId, attribute) => {
508489 required: attribute.required,
509490 xdefault: attribute.default,
510491 array: attribute.array,
492+ encrypt: attribute.encrypt,
511493 parseOutput: false
512494 })
513495
@@ -844,10 +826,14 @@ const attributesToCreate = async (remoteAttributes, localAttributes, collection,
844826
845827 if (!cliConfig.force) {
846828 if (deleting.length > 0 && !isIndex) {
847- log(`Attribute deletion will cause ${chalk.red('loss of data')}`);
829+ console.log(`${chalk.red('-------------------------------------------------------')}`);
830+ console.log(`${chalk.red('| WARNING: Attribute deletion may cause loss of data |')}`);
831+ console.log(`${chalk.red('-------------------------------------------------------')}`);
848832 }
849833 if (conflicts.length > 0 && !isIndex) {
850- log(`Attribute recreation will cause ${chalk.red('loss of data')}`);
834+ console.log(`${chalk.red('---------------------------------------------------------')}`);
835+ console.log(`${chalk.red('| WARNING: Attribute recreation may cause loss of data |')}`);
836+ console.log(`${chalk.red('---------------------------------------------------------')}`);
851837 }
852838
853839 if ((await getConfirmation()) !== true) {
@@ -1042,7 +1028,7 @@ const pushSettings = async () => {
10421028 }
10431029}
10441030
1045- const pushSite = async({ siteId, async, code } = { returnOnZero: false }) => {
1031+ const pushSite = async({ siteId, async, code, withVariables } = { returnOnZero: false }) => {
10461032 process.chdir(localConfig.configDirectoryPath)
10471033
10481034 const siteIds = [];
@@ -1175,7 +1161,6 @@ const pushSite = async({ siteId, async, code } = { returnOnZero: false }) => {
11751161 timeout: site.timeout,
11761162 enabled: site.enabled,
11771163 logging: site.logging,
1178- vars: JSON.stringify(site.vars),
11791164 parseOutput: false
11801165 });
11811166
@@ -1208,16 +1193,43 @@ const pushSite = async({ siteId, async, code } = { returnOnZero: false }) => {
12081193 }
12091194 }
12101195
1211- updaterRow.update({ status: 'Creating variables' }).replaceSpinner(SPINNER_ARC);
1196+ if (withVariables) {
1197+ updaterRow.update({ status: 'Creating variables' }).replaceSpinner(SPINNER_ARC);
12121198
1213- await Promise.all((site['vars'] ?? []).map(async variable => {
1214- await sitesCreateVariable({
1199+ const { variables } = await paginate(sitesListVariables, {
12151200 siteId: site['$id'],
1216- key: variable['key'],
1217- value: variable['value'],
12181201 parseOutput: false
1219- });
1220- }));
1202+ }, 100, 'variables');
1203+
1204+ await Promise.all(variables.map(async variable => {
1205+ await sitesDeleteVariable({
1206+ siteId: site['$id'],
1207+ variableId: variable['$id'],
1208+ parseOutput: false
1209+ });
1210+ }));
1211+
1212+ const envFileLocation = `${site['path']}/.env`;
1213+ let envVariables = [];
1214+ try {
1215+ if (fs.existsSync(envFileLocation)) {
1216+ const envObject = parseDotenv(fs.readFileSync(envFileLocation, 'utf8'));
1217+ envVariables = Object.entries(envObject || {}).map(([key, value]) => ({ key, value }));
1218+ }
1219+ } catch (error) {
1220+ // Handle parsing errors gracefully
1221+ envVariables = [];
1222+ }
1223+ await Promise.all(envVariables.map(async variable => {
1224+ await sitesCreateVariable({
1225+ siteId: site['$id'],
1226+ key: variable.key,
1227+ value: variable.value,
1228+ parseOutput: false,
1229+ secret: false
1230+ });
1231+ }));
1232+ }
12211233
12221234 if (code === false) {
12231235 successfullyPushed++;
@@ -1470,7 +1482,6 @@ const pushFunction = async ({ functionId, async, code, withVariables } = { retur
14701482 entrypoint: func.entrypoint,
14711483 commands: func.commands,
14721484 scopes: func.scopes,
1473- vars: JSON.stringify(func.vars),
14741485 parseOutput: false
14751486 });
14761487
@@ -1519,19 +1530,25 @@ const pushFunction = async ({ functionId, async, code, withVariables } = { retur
15191530 });
15201531 }));
15211532
1522- let result = await awaitPools.wipeVariables(func['$id']);
1523- if (!result) {
1524- updaterRow.fail({ errorMessage: `Variable deletion timed out.` })
1525- return;
1533+ const envFileLocation = `${func['path']}/.env`;
1534+ let envVariables = [];
1535+ try {
1536+ if (fs.existsSync(envFileLocation)) {
1537+ const envObject = parseDotenv(fs.readFileSync(envFileLocation, 'utf8'));
1538+ envVariables = Object.entries(envObject || {}).map(([key, value]) => ({ key, value }));
1539+ }
1540+ } catch (error) {
1541+ // Handle parsing errors gracefully
1542+ envVariables = [];
15261543 }
1527-
1528- // Deploy local variables
1529- await Promise.all((func['vars'] ?? []).map(async variable => {
1544+ await Promise.all(envVariables.map(async variable => {
15301545 await functionsCreateVariable({
15311546 functionId: func['$id'],
1532- key: variable['key'],
1533- value: variable['value'],
1534- parseOutput: false
1547+ variableId: ID.unique(),
1548+ key: variable.key,
1549+ value: variable.value,
1550+ parseOutput: false,
1551+ secret: false
15351552 });
15361553 }));
15371554 }
@@ -2060,6 +2077,7 @@ push
20602077 .option(`-f, --site-id <site -id >`, `ID of site to run`)
20612078 .option(`-A, --async`, `Don't wait for sites deployments status`)
20622079 .option("--no-code", "Don't push the site's code")
2080+ .option("--with-variables", `Push site variables.`)
20632081 .action(actionRunner(pushSite));
20642082
20652083push
0 commit comments