backend-manager 2.5.13 → 2.5.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-manager",
3
- "version": "2.5.13",
3
+ "version": "2.5.15",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -65,75 +65,5 @@
65
65
  "bin/",
66
66
  "src/",
67
67
  "templates/"
68
- ],
69
- "allDependencies": {
70
- "@firebase/rules-unit-testing": "^2.0.4",
71
- "@google-cloud/storage": "^5.20.5",
72
- "@sendgrid/mail": "^7.7.0",
73
- "@sentry/node": "^6.19.7",
74
- "backend-assistant": "^0.0.74",
75
- "busboy": "^1.6.0",
76
- "chalk": "^4.1.2",
77
- "cors": "^2.8.5",
78
- "dotenv": "^16.0.2",
79
- "firebase-admin": "^9.12.0",
80
- "firebase-functions": "^3.24.0",
81
- "fs-jetpack": "^4.3.1",
82
- "hcaptcha": "^0.1.1",
83
- "inquirer": "^8.2.4",
84
- "json5": "^2.2.1",
85
- "jwt-decode": "^3.1.2",
86
- "lodash": "^4.17.21",
87
- "lowdb": "^1.0.0",
88
- "mailchimp-api-v3": "^1.15.0",
89
- "moment": "^2.29.4",
90
- "node-fetch": "^2.6.7",
91
- "node-powertools": "^0.0.21",
92
- "npm-api": "^1.0.1",
93
- "paypal-server-api": "^0.0.8",
94
- "pushid": "^1.0.0",
95
- "semver": "^7.3.7",
96
- "shortid": "^2.2.16",
97
- "uid-generator": "^2.0.0",
98
- "ultimate-jekyll-poster": "^0.0.15",
99
- "universal-analytics": "^0.5.3",
100
- "uuid": "^8.3.2",
101
- "wonderful-fetch": "^0.0.14",
102
- "yargs": "^17.5.1"
103
- },
104
- "allDependenciesKeys": [
105
- "@firebase/rules-unit-testing",
106
- "@google-cloud/storage",
107
- "@sendgrid/mail",
108
- "@sentry/node",
109
- "backend-assistant",
110
- "busboy",
111
- "chalk",
112
- "cors",
113
- "dotenv",
114
- "firebase-admin",
115
- "firebase-functions",
116
- "fs-jetpack",
117
- "hcaptcha",
118
- "inquirer",
119
- "json5",
120
- "jwt-decode",
121
- "lodash",
122
- "lowdb",
123
- "mailchimp-api-v3",
124
- "moment",
125
- "node-fetch",
126
- "node-powertools",
127
- "npm-api",
128
- "paypal-server-api",
129
- "pushid",
130
- "semver",
131
- "shortid",
132
- "uid-generator",
133
- "ultimate-jekyll-poster",
134
- "universal-analytics",
135
- "uuid",
136
- "wonderful-fetch",
137
- "yargs"
138
68
  ]
139
- }
69
+ }
package/src/cli/cli.js CHANGED
@@ -1322,16 +1322,26 @@ async function cmd_iamImportExport(self) {
1322
1322
  async function cmd_setStorageLifecycle(self) {
1323
1323
  return new Promise(function(resolve, reject) {
1324
1324
  const command = `gsutil lifecycle set {config} gs://{bucket}`
1325
- .replace(/{config}/ig, path.resolve(`${__dirname}/../../templates/storage-lifecycle-config.json`))
1325
+ .replace(/{config}/ig, path.resolve(`${__dirname}/../../templates/storage-lifecycle-config-1-day.json`))
1326
1326
  .replace(/{bucket}/ig, `us.artifacts.${self.projectName}.appspot.com`)
1327
+ const command2 = `gsutil lifecycle set {config} gs://{bucket}`
1328
+ .replace(/{config}/ig, path.resolve(`${__dirname}/../../templates/storage-lifecycle-config-30-days.json`))
1329
+ .replace(/{bucket}/ig, `bm-backup-firestore-${self.projectName}`)
1327
1330
 
1328
- let cmd = exec(command, function (error, stdout, stderr) {
1331
+ exec(command, function (error, stdout, stderr) {
1329
1332
  if (error) {
1330
1333
  console.log(chalk.red(`Failed to run command`, error));
1331
1334
  reject(error);
1332
1335
  } else {
1333
- // console.log(chalk.green(`Added lifecycle`));
1334
- resolve(stdout);
1336
+ exec(command2, function (error, stdout, stderr) {
1337
+ if (error) {
1338
+ console.log(chalk.red(`Failed to run command`, error));
1339
+ reject(error);
1340
+ } else {
1341
+ // console.log(chalk.green(`Added lifecycle`));
1342
+ resolve(stdout);
1343
+ }
1344
+ })
1335
1345
  }
1336
1346
  });
1337
1347
  });
@@ -36,7 +36,7 @@ Module.prototype.main = function () {
36
36
  const bucketAddress = `gs://${bucketName}`;
37
37
 
38
38
  await self.createBucket(bucketName, resourceZone);
39
- await self.deleteOldFiles(bucketName, resourceZone);
39
+ // await self.deleteOldFiles(bucketName, resourceZone);
40
40
 
41
41
  client.exportDocuments({
42
42
  name: databaseName,
@@ -127,7 +127,86 @@ Module.prototype.createBucket = function (bucketName, resourceZone) {
127
127
  };
128
128
 
129
129
  // https://github.com/zsolt-dev/auto-delete-gcp-storage-backups/blob/master/index.js
130
- Module.prototype.deleteOldFiles = function (bucketName, resourceZone) {
130
+ Module.prototype.__RETRY_deleteOldFiles = function (bucketName, resourceZone) {
131
+ const self = this;
132
+ const Manager = self.Manager;
133
+ const Api = self.Api;
134
+ const assistant = self.assistant;
135
+ const payload = self.payload;
136
+
137
+ return new Promise(async function(resolve, reject) {
138
+ const now = moment();
139
+ const deletionRegex = payload.data.payload.deletionRegex;
140
+
141
+ // Helpers
142
+ const getFileObjectWithMetaData = async (bucketName, fileName) => {
143
+ const [metaData] = await storage.bucket(bucketName).file(fileName).getMetadata();
144
+ return ({ fileName, created: metaData.timeCreated });
145
+ };
146
+
147
+ const deleteFileFromBucket = async (bucketName, fileName) => {
148
+ assistant.log(`Deleting item: ${fileName}...`, );
149
+ return await storage.bucket(bucketName).file(fileName).delete();
150
+ };
151
+
152
+ // Main
153
+ // get the file names as an array
154
+ let [allFiles] = await storage.bucket(bucketName).getFiles();
155
+ let deletePromises = [];
156
+ let foldersToDelete = [];
157
+ allFiles = allFiles.map(file => file.name);
158
+ // console.log(`all files: ${allFiles.join(', ')}`);
159
+
160
+ allFiles.forEach((filePath, i) => {
161
+ const fileName = filePath.split('/')[0];
162
+ const date = moment(fileName.split('T')[0]);
163
+ const day = date.date();
164
+ const month = date.month();
165
+ const age = now.diff(date, 'days', false);
166
+
167
+ if (age >= 30) {
168
+ if (day === 1) { return }
169
+ deletePromises.push(deleteFileFromBucket(bucketName, backup.fileName))
170
+ assistant.log(`Preparing to delete ${filePath}: date=${date.format('MMM Do, YYYY')}, day=${day}, month=${month}, age=${age}`, );
171
+ // if (!foldersToDelete.includes(fileName)) {
172
+ // assistant.log(`Preparing to delete ${fileName}: date=${date.format('MMM Do, YYYY')}, day=${day}, month=${month}, age=${age}`, );
173
+ // foldersToDelete = foldersToDelete.concat(fileName);
174
+ // deletePromises.push(deleteFileFromBucket(bucketName, fileName))
175
+ // }
176
+ }
177
+ })
178
+
179
+ console.log('---deletePromises.length', deletePromises.length);
180
+
181
+ return
182
+
183
+ // transform to array of objects with creation timestamp { fileName: abc, created: xyz }
184
+ allFiles = allFiles.map(fileName => getFileObjectWithMetaData(bucketName, fileName));
185
+ allFiles = await Promise.all(allFiles);
186
+
187
+ allFiles.forEach((backup, i) => {
188
+ const date = moment(backup.created);
189
+ const day = date.date();
190
+ const month = date.month();
191
+ const age = now.diff(date, 'days', false);
192
+
193
+ assistant.log(`Sorting item ${i}: date=${date.format('MMM Do, YYYY')}, day=${day}, month=${month}, age=${age}`, );
194
+
195
+ if (age >= 31) {
196
+ if (day === 1) { return }
197
+ deletePromises.push(deleteFileFromBucket(bucketName, backup.fileName))
198
+ } else if ((deletionRegex && backup.fileName.match(deletionRegex))) {
199
+ deletePromises.push(deleteFileFromBucket(bucketName, backup.fileName))
200
+ }
201
+ })
202
+
203
+ await Promise.all(deletePromises);
204
+
205
+ return resolve();
206
+ });
207
+ };
208
+
209
+ Module.prototype.__deleteOldFiles = function (bucketName, resourceZone) {
131
210
  const self = this;
132
211
  const Manager = self.Manager;
133
212
  const Api = self.Api;
@@ -24,6 +24,7 @@ Module.prototype.main = function() {
24
24
  return new Promise(async function(resolve, reject) {
25
25
  fetch(`${Manager.project.functionsUrl}/bm_api`, {
26
26
  method: 'post',
27
+ response: 'json',
27
28
  body: {
28
29
  backendManagerKey: Manager.config.backend_manager.key,
29
30
  command: 'admin:backup',
@@ -48,6 +48,7 @@ Manager.prototype.init = function (exporter, options) {
48
48
  options.serviceAccountPath = typeof options.serviceAccountPath === 'undefined' ? 'service-account.json' : options.serviceAccountPath;
49
49
  options.backendManagerConfigPath = typeof options.backendManagerConfigPath === 'undefined' ? 'backend-manager-config.json' : options.backendManagerConfigPath;
50
50
  options.fetchStats = typeof options.fetchStats === 'undefined' ? true : options.fetchStats;
51
+ options.checkNodeVersion = typeof options.checkNodeVersion === 'undefined' ? true : options.checkNodeVersion;
51
52
  options.uniqueAppName = options.uniqueAppName || undefined;
52
53
  options.assistant = options.assistant || {};
53
54
  // options.assistant.optionsLogString = options.assistant.optionsLogString || undefined;
@@ -75,7 +76,7 @@ Manager.prototype.init = function (exporter, options) {
75
76
  self.project.resourceZone = options.resourceZone;
76
77
  self.project.serviceAccountPath = path.resolve(self.cwd, options.serviceAccountPath)
77
78
  self.project.backendManagerConfigPath = path.resolve(self.cwd, options.backendManagerConfigPath)
78
-
79
+
79
80
  self.package = resolveProjectPackage();
80
81
  self.config = merge(
81
82
  requireJSON5(self.project.backendManagerConfigPath),
@@ -117,7 +118,9 @@ Manager.prototype.init = function (exporter, options) {
117
118
  // Reject if package.json does not exist
118
119
  if (semverUsing !== semverRequired) {
119
120
  self.assistant.error(new Error(`Node.js version mismatch: using ${semverUsing} but asked for ${semverRequired}`), {environment: 'production'});
120
- return process.exit(1);
121
+ if (options.checkNodeVersion) {
122
+ return process.exit(1);
123
+ }
121
124
  }
122
125
  }
123
126
 
@@ -386,7 +389,7 @@ Manager.prototype.init = function (exporter, options) {
386
389
  // Cron
387
390
  exporter.bm_cronDaily =
388
391
  self.libraries.functions
389
- .runWith({ memory: '256MB', timeoutSeconds: 60 })
392
+ .runWith({ memory: '256MB', timeoutSeconds: 120 })
390
393
  .pubsub.schedule('every 24 hours')
391
394
  .onRun(async (context) => {
392
395
  return self._process((new (require(`${core}/cron/daily.js`))()).init(self, { context: context, }))
@@ -0,0 +1,9 @@
1
+ {
2
+ "rule":
3
+ [
4
+ {
5
+ "action": {"type": "Delete"},
6
+ "condition": {"age": 30}
7
+ }
8
+ ]
9
+ }