backend-manager 3.2.108 → 3.2.110
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/CHANGELOG.md +10 -7
- package/package.json +4 -1
- package/src/cli/cli.js +21 -2
- package/src/manager/functions/core/actions/api/admin/create-post.js +0 -2
- package/src/manager/functions/core/actions/api/test/run-hook.js +1 -1
- package/src/manager/functions/core/actions/api.js +1 -1
- package/src/manager/helpers/assistant.js +18 -7
- package/src/manager/helpers/middleware.js +11 -4
- package/src/manager/helpers/settings.js +18 -14
- package/src/manager/helpers/usage.js +51 -22
- package/src/manager/index.js +394 -216
- package/src/manager/routes/restart/index.js +52 -0
- package/src/manager/routes/test/index.js +43 -0
- package/src/manager/schemas/restart.js +13 -0
- package/src/manager/schemas/test.js +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -15,18 +15,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
15
15
|
- `Security` in case of vulnerabilities.
|
|
16
16
|
|
|
17
17
|
---
|
|
18
|
-
## [3.2.
|
|
19
|
-
###
|
|
18
|
+
## [3.2.109] - 2024-05-08
|
|
19
|
+
### Changed
|
|
20
|
+
- Replaced all `methods` references with `routes`. This should be changed in your code as well.
|
|
21
|
+
|
|
22
|
+
## [3.2.32] - 2024-01-30
|
|
23
|
+
### Changed
|
|
20
24
|
- Modified `.assistant().errorify()` to have defaults of `log`, `sentry`, and `send` to `false` if not specified to prevent accidental logging and premature sending of errors.
|
|
21
25
|
|
|
22
|
-
## [3.2.30] -
|
|
23
|
-
###
|
|
26
|
+
## [3.2.30] - 2024-01-30
|
|
27
|
+
### Changed
|
|
24
28
|
- Modified `.assistant()` token/key check to use `options.apiKey || data.apiKey`
|
|
25
29
|
|
|
26
|
-
## [3.2.0] -
|
|
30
|
+
## [3.2.0] - 2024-01-19
|
|
27
31
|
### Added
|
|
28
|
-
- Added `.settings()` API. Put your settings in `./
|
|
29
|
-
|
|
32
|
+
- Added `.settings()` API. Put your settings in `./schemas/*.js` and access them with `assistant.settings.*`.
|
|
30
33
|
|
|
31
34
|
## [3.1.0] - 2023-12-19
|
|
32
35
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.110",
|
|
4
4
|
"description": "Quick tools for developing Firebase functions",
|
|
5
5
|
"main": "src/manager/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -39,13 +39,16 @@
|
|
|
39
39
|
"@octokit/rest": "^19.0.13",
|
|
40
40
|
"@sendgrid/mail": "^7.7.0",
|
|
41
41
|
"@sentry/node": "^6.19.7",
|
|
42
|
+
"body-parser": "^1.20.2",
|
|
42
43
|
"busboy": "^1.6.0",
|
|
43
44
|
"chalk": "^4.1.2",
|
|
44
45
|
"cors": "^2.8.5",
|
|
45
46
|
"dotenv": "^16.4.5",
|
|
47
|
+
"express": "^4.19.2",
|
|
46
48
|
"firebase-admin": "^11.11.1",
|
|
47
49
|
"firebase-functions": "^4.9.0",
|
|
48
50
|
"fs-jetpack": "^5.1.0",
|
|
51
|
+
"glob": "^10.3.12",
|
|
49
52
|
"hcaptcha": "^0.1.1",
|
|
50
53
|
"inquirer": "^8.2.5",
|
|
51
54
|
"json5": "^2.2.3",
|
package/src/cli/cli.js
CHANGED
|
@@ -82,9 +82,13 @@ Main.prototype.process = async function (args) {
|
|
|
82
82
|
console.clear();
|
|
83
83
|
process.stdout.write("\u001b[3J\u001b[2J\u001b[1J");
|
|
84
84
|
}
|
|
85
|
+
|
|
86
|
+
// Log CWD
|
|
85
87
|
if (self.options.cwd) {
|
|
86
88
|
console.log('cwd: ', self.firebaseProjectPath);
|
|
87
89
|
}
|
|
90
|
+
|
|
91
|
+
// Run setup
|
|
88
92
|
if (self.options.setup) {
|
|
89
93
|
// console.log(`Running Setup`);
|
|
90
94
|
// console.log(`node:`, process.versions.node);
|
|
@@ -95,14 +99,21 @@ Main.prototype.process = async function (args) {
|
|
|
95
99
|
await cmd_configGet(self).catch(e => log(chalk.red(`Failed to run config:get`)));
|
|
96
100
|
await self.setup();
|
|
97
101
|
}
|
|
102
|
+
|
|
103
|
+
// Install local BEM
|
|
98
104
|
if ((self.options.i || self.options.install) && (self.options.local || self.options.dev || self.options.development)) {
|
|
99
105
|
await uninstallPkg('backend-manager');
|
|
100
|
-
return await installPkg('file:../../../ITW-Creative-Works/backend-manager');
|
|
106
|
+
// return await installPkg('file:../../../ITW-Creative-Works/backend-manager');
|
|
107
|
+
return await installPkg('file:/Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager');
|
|
101
108
|
}
|
|
109
|
+
|
|
110
|
+
// Install live BEM
|
|
102
111
|
if ((self.options.i || self.options.install) && (self.options.live || self.options.prod || self.options.production)) {
|
|
103
112
|
await uninstallPkg('backend-manager');
|
|
104
113
|
return await installPkg('backend-manager');
|
|
105
114
|
}
|
|
115
|
+
|
|
116
|
+
// Serve firebase
|
|
106
117
|
if (self.options.serve) {
|
|
107
118
|
if (!self.options.quick && !self.options.q) {
|
|
108
119
|
}
|
|
@@ -121,30 +132,36 @@ Main.prototype.process = async function (args) {
|
|
|
121
132
|
});
|
|
122
133
|
}
|
|
123
134
|
|
|
135
|
+
// Get indexes
|
|
124
136
|
if (self.options['firestore:indexes:get'] || self.options['firestore:indexes'] || self.options['indexes:get']) {
|
|
125
137
|
return await cmd_indexesGet(self, undefined, true);
|
|
126
138
|
}
|
|
127
139
|
|
|
140
|
+
// Get config
|
|
128
141
|
if (self.options['functions:config:get'] || self.options['config:get']) {
|
|
129
142
|
return await cmd_configGet(self);
|
|
130
143
|
}
|
|
131
144
|
|
|
145
|
+
// Set config
|
|
132
146
|
if (self.options['functions:config:set'] || self.options['config:set']) {
|
|
133
147
|
await cmd_configSet(self);
|
|
134
148
|
return await cmd_configGet(self);
|
|
135
149
|
}
|
|
136
150
|
|
|
151
|
+
// Unset config
|
|
137
152
|
if (self.options['functions:config:unset'] || self.options['config:unset'] || self.options['config:delete'] || self.options['config:remove']) {
|
|
138
153
|
await cmd_configUnset(self);
|
|
139
154
|
return await cmd_configGet(self);
|
|
140
155
|
}
|
|
141
156
|
|
|
157
|
+
// Get rules
|
|
142
158
|
if (self.options['rules:default'] || self.options['rules:getdefault']) {
|
|
143
159
|
self.getRulesFile();
|
|
144
160
|
console.log(self.default.firestoreRulesWhole.match(bem_allRulesDefaultRegex)[0].replace(' ///', '///'));
|
|
145
161
|
return;
|
|
146
162
|
}
|
|
147
163
|
|
|
164
|
+
// Deploy
|
|
148
165
|
if (self.options.deploy) {
|
|
149
166
|
await self.setup();
|
|
150
167
|
|
|
@@ -166,8 +183,9 @@ Main.prototype.process = async function (args) {
|
|
|
166
183
|
console.error(chalk.red(`${cleanOutput(data)}`));
|
|
167
184
|
// ls = null;
|
|
168
185
|
});
|
|
169
|
-
|
|
170
186
|
}
|
|
187
|
+
|
|
188
|
+
// Test
|
|
171
189
|
if (self.options['test']) {
|
|
172
190
|
await self.setup();
|
|
173
191
|
// firebase emulators:exec --only firestore 'npm test'
|
|
@@ -182,6 +200,7 @@ Main.prototype.process = async function (args) {
|
|
|
182
200
|
});
|
|
183
201
|
}
|
|
184
202
|
|
|
203
|
+
// Clean
|
|
185
204
|
if (self.options['clean:npm']) {
|
|
186
205
|
// await self.setup();
|
|
187
206
|
// firebase emulators:exec --only firestore 'npm test'
|
|
@@ -28,7 +28,7 @@ Module.prototype.main = function () {
|
|
|
28
28
|
try {
|
|
29
29
|
hook = (new (require(pathify(`${Manager.cwd}/${payload.data.payload.path}.js`)))());
|
|
30
30
|
} catch (e) {
|
|
31
|
-
hook = (new (require(pathify(`${Manager.cwd}/
|
|
31
|
+
hook = (new (require(pathify(`${Manager.cwd}/routes/hooks/${payload.data.payload.path}.js`)))());
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Run the hook
|
|
@@ -326,7 +326,7 @@ function resolveBasePath(basePath, command) {
|
|
|
326
326
|
};
|
|
327
327
|
|
|
328
328
|
function resolveApiPath(command) {
|
|
329
|
-
const projectBasePath = path.join(process.cwd(), '
|
|
329
|
+
const projectBasePath = path.join(process.cwd(), 'routes/api');
|
|
330
330
|
const localBasePath = './api/';
|
|
331
331
|
|
|
332
332
|
const projectPath = resolveBasePath(projectBasePath, command);
|
|
@@ -140,17 +140,19 @@ BackendAssistant.prototype.init = function (ref, options) {
|
|
|
140
140
|
self.request.path = (self.ref.req.path || '');
|
|
141
141
|
self.request.user = self.resolveAccount({authenticated: false});
|
|
142
142
|
|
|
143
|
+
// Set body and query
|
|
143
144
|
if (options.accept === 'json') {
|
|
144
145
|
self.request.body = tryParse(self.ref.req.body || '{}');
|
|
145
146
|
self.request.query = tryParse(self.ref.req.query || '{}');
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
|
|
149
|
-
self.request.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
// Set headers
|
|
150
|
+
self.request.headers = self.ref.req.headers || {};
|
|
151
|
+
|
|
152
|
+
// Merge data
|
|
153
|
+
self.request.data = _.merge({}, self.request.body, self.request.query);
|
|
154
|
+
|
|
155
|
+
// Set multipart data
|
|
154
156
|
self.request.multipartData = {
|
|
155
157
|
fields: {},
|
|
156
158
|
files: {},
|
|
@@ -385,6 +387,11 @@ BackendAssistant.prototype.errorify = function (e, options) {
|
|
|
385
387
|
sendable = `${sendable} (${newError.tag})`;
|
|
386
388
|
}
|
|
387
389
|
|
|
390
|
+
// Log
|
|
391
|
+
if (options.log) {
|
|
392
|
+
self.log(`Sending response (${options.code}):`, JSON.stringify(sendable));
|
|
393
|
+
}
|
|
394
|
+
|
|
388
395
|
// Send response
|
|
389
396
|
res
|
|
390
397
|
.status(options.code)
|
|
@@ -463,7 +470,11 @@ BackendAssistant.prototype.respond = function(response, options) {
|
|
|
463
470
|
_log(`Sending response`);
|
|
464
471
|
|
|
465
472
|
// If it is an object, send as json
|
|
466
|
-
if (
|
|
473
|
+
if (
|
|
474
|
+
response
|
|
475
|
+
&& typeof response === 'object'
|
|
476
|
+
&& typeof res.json === 'function'
|
|
477
|
+
) {
|
|
467
478
|
return res.json(response);
|
|
468
479
|
} else {
|
|
469
480
|
return res.send(response);
|
|
@@ -39,15 +39,21 @@ Middleware.prototype.run = function (libPath, options) {
|
|
|
39
39
|
options.includeNonSchemaSettings = typeof options.includeNonSchemaSettings === 'undefined' ? false : options.includeNonSchemaSettings;
|
|
40
40
|
options.schema = typeof options.schema === 'undefined' ? undefined : options.schema;
|
|
41
41
|
|
|
42
|
+
// Set base path
|
|
43
|
+
options.routesDir = typeof options.routesDir === 'undefined' ? `${process.cwd()}/routes` : options.routesDir;
|
|
44
|
+
options.schemasDir = typeof options.schemasDir === 'undefined' ? `${process.cwd()}/schemas` : options.schemasDir;
|
|
45
|
+
|
|
42
46
|
// Log
|
|
43
47
|
assistant.log(`Middleware.process(): Request (${geolocation.ip} @ ${geolocation.country}, ${geolocation.region}, ${geolocation.city})`, JSON.stringify(data));
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
// Set paths
|
|
50
|
+
const routesDir = path.resolve(options.routesDir, libPath.replace('.js', ''));
|
|
51
|
+
const schemasDir = path.resolve(options.schemasDir);
|
|
47
52
|
|
|
48
53
|
// Load library
|
|
54
|
+
let library;
|
|
49
55
|
try {
|
|
50
|
-
libPath = path.resolve(
|
|
56
|
+
libPath = path.resolve(routesDir, `index.js`);
|
|
51
57
|
library = new (require(libPath))();
|
|
52
58
|
} catch (e) {
|
|
53
59
|
return assistant.respond(new Error(`Unable to load library @ (${libPath}): ${e.message}`), {code: 500, sentry: true});
|
|
@@ -85,7 +91,8 @@ Middleware.prototype.run = function (libPath, options) {
|
|
|
85
91
|
|
|
86
92
|
// Resolve settings
|
|
87
93
|
try {
|
|
88
|
-
assistant.settings = Manager.Settings().resolve(assistant, options.schema, data);
|
|
94
|
+
// assistant.settings = Manager.Settings().resolve(assistant, options.schema, data);
|
|
95
|
+
assistant.settings = Manager.Settings().resolve(assistant, undefined, data, {dir: schemasDir, schema: options.schema});
|
|
89
96
|
} catch (e) {
|
|
90
97
|
return assistant.respond(new Error(`Unable to resolve schema ${options.schema}: ${e.message}`), {code: 500, sentry: true});
|
|
91
98
|
}
|
|
@@ -16,25 +16,29 @@ function Settings(m) {
|
|
|
16
16
|
self.settings = null;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
Settings.prototype.resolve = function (assistant, schema, settings) {
|
|
19
|
+
Settings.prototype.resolve = function (assistant, schema, settings, options) {
|
|
20
20
|
const self = this;
|
|
21
21
|
const Manager = self.Manager;
|
|
22
22
|
|
|
23
23
|
// Set settings
|
|
24
|
-
schema = schema;
|
|
25
|
-
settings =
|
|
24
|
+
schema = schema || undefined;
|
|
25
|
+
settings = settings || {};
|
|
26
26
|
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
// Set options
|
|
28
|
+
options = options || {};
|
|
29
|
+
options.dir = typeof options.dir === 'undefined' ? `${process.cwd()}/schemas` : options.dir;
|
|
30
|
+
options.schema = typeof options.schema === 'undefined' ? undefined : options.schema;
|
|
31
|
+
|
|
32
|
+
// Load schema if not provided and schema is defined in options
|
|
33
|
+
// console.log('----schema:', schema);
|
|
34
|
+
// console.log('----settings:', settings);
|
|
35
|
+
// console.log('----options.dir:', options.dir);
|
|
36
|
+
// console.log('----options.schema:', options.schema);
|
|
37
|
+
if (
|
|
38
|
+
typeof schema === 'undefined'
|
|
39
|
+
&& typeof options.schema !== 'undefined'
|
|
40
|
+
) {
|
|
41
|
+
const schemaPath = path.resolve(options.dir, `${options.schema.replace('.js', '')}.js`);
|
|
38
42
|
|
|
39
43
|
schema = loadSchema(assistant, schemaPath, settings);
|
|
40
44
|
}
|
|
@@ -120,10 +120,12 @@ Usage.prototype.init = function (assistant, options) {
|
|
|
120
120
|
// Get app data
|
|
121
121
|
self.app = self.storage.get(`${self.paths.app}.data`, {}).value();
|
|
122
122
|
|
|
123
|
+
// Check for app data
|
|
123
124
|
if (!self.app) {
|
|
124
125
|
return reject(new Error('Usage.init(): No app data found'));
|
|
125
126
|
}
|
|
126
127
|
|
|
128
|
+
// Log
|
|
127
129
|
self.log(`Usage.init(): Got app data`, self.app);
|
|
128
130
|
self.log(`Usage.init(): Got user`, self.user);
|
|
129
131
|
|
|
@@ -135,26 +137,43 @@ Usage.prototype.init = function (assistant, options) {
|
|
|
135
137
|
});
|
|
136
138
|
};
|
|
137
139
|
|
|
138
|
-
Usage.prototype.validate = function (
|
|
140
|
+
Usage.prototype.validate = function (name, options) {
|
|
139
141
|
const self = this;
|
|
140
142
|
|
|
141
143
|
return new Promise(async function(resolve, reject) {
|
|
142
144
|
const Manager = self.Manager;
|
|
143
145
|
const assistant = self.assistant;
|
|
144
146
|
|
|
147
|
+
// Set options
|
|
145
148
|
options = options || {};
|
|
146
149
|
options.useCaptchaResponse = typeof options.useCaptchaResponse === 'undefined' ? true : options.useCaptchaResponse;
|
|
150
|
+
options.log = typeof options.log === 'undefined' ? true : options.log;
|
|
151
|
+
options.throw = typeof options.throw === 'undefined' ? false : options.throw;
|
|
147
152
|
|
|
148
153
|
// Check for required options
|
|
149
|
-
const period = self.getUsage(
|
|
150
|
-
const allowed = self.getLimit(
|
|
154
|
+
const period = self.getUsage(name);
|
|
155
|
+
const allowed = self.getLimit(name);
|
|
151
156
|
|
|
152
|
-
// Log
|
|
153
|
-
|
|
157
|
+
// Log (independent of options.log because this is important)
|
|
158
|
+
if (options.log) {
|
|
159
|
+
assistant.log(`Usage.validate(): Checking ${period}/${allowed} for ${name}...`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Reject function
|
|
163
|
+
function _reject() {
|
|
164
|
+
reject(
|
|
165
|
+
assistant.errorify(`You have exceeded your ${name} usage limit of ${period}/${allowed}.`, {code: 429})
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Dev mode throw
|
|
170
|
+
if (options.throw) {
|
|
171
|
+
return _reject();
|
|
172
|
+
}
|
|
154
173
|
|
|
155
174
|
// If they are under the limit, resolve
|
|
156
175
|
if (period < allowed) {
|
|
157
|
-
self.log(`Usage.validate(): Valid for ${
|
|
176
|
+
self.log(`Usage.validate(): Valid for ${name}`);
|
|
158
177
|
|
|
159
178
|
return resolve(true);
|
|
160
179
|
}
|
|
@@ -177,25 +196,28 @@ Usage.prototype.validate = function (path, options) {
|
|
|
177
196
|
}
|
|
178
197
|
|
|
179
198
|
// Otherwise, they are over the limit, reject
|
|
180
|
-
return
|
|
181
|
-
assistant.errorify(`You have exceeded your ${path} usage limit of ${period}/${allowed}.`, {code: 429})
|
|
182
|
-
);
|
|
199
|
+
return _reject();
|
|
183
200
|
});
|
|
184
201
|
};
|
|
185
202
|
|
|
186
|
-
Usage.prototype.increment = function (
|
|
203
|
+
Usage.prototype.increment = function (name, value, options) {
|
|
187
204
|
const self = this;
|
|
188
205
|
const Manager = self.Manager;
|
|
189
206
|
const assistant = self.assistant;
|
|
190
207
|
|
|
208
|
+
// Set name
|
|
209
|
+
name = name || 'requests';
|
|
210
|
+
|
|
211
|
+
// Set value
|
|
191
212
|
value = typeof value === 'undefined' ? 1 : value;
|
|
192
213
|
|
|
214
|
+
// Set options
|
|
193
215
|
options = options || {};
|
|
194
216
|
options.id = options.id || null;
|
|
195
217
|
|
|
196
218
|
// Update total and period
|
|
197
219
|
['total', 'period', 'last'].forEach((key) => {
|
|
198
|
-
const resolved = `usage.${
|
|
220
|
+
const resolved = `usage.${name}.${key}`;
|
|
199
221
|
const existing = _.get(self.user, resolved, 0);
|
|
200
222
|
|
|
201
223
|
if (key === 'last') {
|
|
@@ -214,51 +236,58 @@ Usage.prototype.increment = function (path, value, options) {
|
|
|
214
236
|
});
|
|
215
237
|
|
|
216
238
|
// Log the updated user
|
|
217
|
-
self.log(`Usage.init(): Incremented ${
|
|
239
|
+
self.log(`Usage.init(): Incremented ${name} for user`, self.user);
|
|
218
240
|
|
|
219
241
|
return self;
|
|
220
242
|
};
|
|
221
243
|
|
|
222
|
-
Usage.prototype.set = function (
|
|
244
|
+
Usage.prototype.set = function (name, value) {
|
|
223
245
|
const self = this;
|
|
224
246
|
const Manager = self.Manager;
|
|
225
247
|
const assistant = self.assistant;
|
|
226
248
|
|
|
227
|
-
//
|
|
228
|
-
|
|
249
|
+
// Set name
|
|
250
|
+
name = name || 'requests';
|
|
229
251
|
|
|
252
|
+
// Set value
|
|
230
253
|
value = typeof value === 'undefined' ? 0 : value;
|
|
231
254
|
|
|
255
|
+
// Update total and period
|
|
256
|
+
const resolved = `usage.${name}.period`;
|
|
257
|
+
|
|
232
258
|
// Set the value
|
|
233
259
|
_.set(self.user, resolved, value);
|
|
234
260
|
|
|
235
261
|
// Log the updated user
|
|
236
|
-
self.log(`Usage.init(): Set ${
|
|
262
|
+
self.log(`Usage.init(): Set ${name} for user`, self.user);
|
|
237
263
|
|
|
238
264
|
return self;
|
|
239
265
|
};
|
|
240
266
|
|
|
241
|
-
Usage.prototype.getUsage = function (
|
|
267
|
+
Usage.prototype.getUsage = function (name) {
|
|
242
268
|
const self = this;
|
|
243
269
|
const Manager = self.Manager;
|
|
244
270
|
const assistant = self.assistant;
|
|
245
271
|
|
|
246
|
-
|
|
247
|
-
|
|
272
|
+
// Get usage
|
|
273
|
+
if (name) {
|
|
274
|
+
return _.get(self.user, `usage.${name}.period`, 0);
|
|
248
275
|
} else {
|
|
249
276
|
return self.user.usage;
|
|
250
277
|
}
|
|
251
278
|
};
|
|
252
279
|
|
|
253
|
-
Usage.prototype.getLimit = function (
|
|
280
|
+
Usage.prototype.getLimit = function (name) {
|
|
254
281
|
const self = this;
|
|
255
282
|
const Manager = self.Manager;
|
|
256
283
|
const assistant = self.assistant;
|
|
257
284
|
|
|
285
|
+
// Get key
|
|
258
286
|
const key = `products.${self.options.app}-${self.user.plan.id}.limits`;
|
|
259
287
|
|
|
260
|
-
|
|
261
|
-
|
|
288
|
+
// Get limit
|
|
289
|
+
if (name) {
|
|
290
|
+
return _.get(self.app, `${key}.${name}`, 0);
|
|
262
291
|
} else {
|
|
263
292
|
return _.get(self.app, key, {});
|
|
264
293
|
}
|
package/src/manager/index.js
CHANGED
|
@@ -3,6 +3,9 @@ const path = require('path');
|
|
|
3
3
|
const { get, merge } = require('lodash');
|
|
4
4
|
const jetpack = require('fs-jetpack');
|
|
5
5
|
const JSON5 = require('json5');
|
|
6
|
+
const EventEmitter = require('events');
|
|
7
|
+
// const EventEmitter = require('events').EventEmitter;
|
|
8
|
+
const util = require('util');
|
|
6
9
|
|
|
7
10
|
// const { debug, log, error, warn } = require('firebase-functions/lib/logger');
|
|
8
11
|
// let User;
|
|
@@ -13,6 +16,7 @@ const wrappers = './functions/wrappers';
|
|
|
13
16
|
|
|
14
17
|
function Manager(exporter, options) {
|
|
15
18
|
const self = this;
|
|
19
|
+
|
|
16
20
|
// Constants
|
|
17
21
|
self.SERVER_UUID = '11111111-1111-1111-1111-111111111111';
|
|
18
22
|
|
|
@@ -24,11 +28,15 @@ function Manager(exporter, options) {
|
|
|
24
28
|
storage: {},
|
|
25
29
|
};
|
|
26
30
|
|
|
27
|
-
//
|
|
31
|
+
// Setup EventEmitter
|
|
32
|
+
EventEmitter.call(self);
|
|
28
33
|
|
|
29
34
|
return self;
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
// Inherit from EventEmitter
|
|
38
|
+
util.inherits(Manager, EventEmitter);
|
|
39
|
+
|
|
32
40
|
Manager.prototype.init = function (exporter, options) {
|
|
33
41
|
const self = this;
|
|
34
42
|
|
|
@@ -36,6 +44,9 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
36
44
|
options = options || {};
|
|
37
45
|
options.initialize = typeof options.initialize === 'undefined' ? true : options.initialize;
|
|
38
46
|
options.log = typeof options.log === 'undefined' ? false : options.log;
|
|
47
|
+
options.projectType = typeof options.projectType === 'undefined' ? 'firebase' : options.projectType; // firebase, custom
|
|
48
|
+
options.routes = typeof options.routes === 'undefined' ? '/routes' : options.routes;
|
|
49
|
+
options.schemas = typeof options.schemas === 'undefined' ? '/schemas' : options.schemas;
|
|
39
50
|
options.setupFunctions = typeof options.setupFunctions === 'undefined' ? true : options.setupFunctions;
|
|
40
51
|
options.setupFunctionsLegacy = typeof options.setupFunctionsLegacy === 'undefined' ? false : options.setupFunctionsLegacy;
|
|
41
52
|
options.setupFunctionsIdentity = typeof options.setupFunctionsIdentity === 'undefined' ? true : options.setupFunctionsIdentity;
|
|
@@ -71,6 +82,7 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
71
82
|
// Set properties
|
|
72
83
|
self.cwd = process.cwd();
|
|
73
84
|
|
|
85
|
+
// Set options
|
|
74
86
|
self.options = options;
|
|
75
87
|
self.project = options.firebaseConfig || JSON.parse(process.env.FIREBASE_CONFIG || '{}');
|
|
76
88
|
self.project.resourceZone = options.resourceZone;
|
|
@@ -206,222 +218,14 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
206
218
|
// admin.firestore().settings({/* your settings... */ timestampsInSnapshots: true})
|
|
207
219
|
}
|
|
208
220
|
|
|
209
|
-
//
|
|
210
|
-
if (options.setupFunctions) {
|
|
211
|
-
exporter
|
|
212
|
-
|
|
213
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
214
|
-
// TODO: Replace this with new API
|
|
215
|
-
.https.onRequest(async (req, res) => self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, })));
|
|
216
|
-
|
|
217
|
-
if (options.setupFunctionsLegacy) {
|
|
218
|
-
exporter.bm_signUpHandler =
|
|
219
|
-
self.libraries.functions
|
|
220
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
221
|
-
.https.onRequest(async (req, res) => {
|
|
222
|
-
const Module = require(`${core}/actions/sign-up-handler.js`);
|
|
223
|
-
Module.init(self, { req: req, res: res, });
|
|
224
|
-
|
|
225
|
-
return self._preProcess(Module)
|
|
226
|
-
.then(r => Module.main())
|
|
227
|
-
.catch(e => {
|
|
228
|
-
self.assistant.error(e);
|
|
229
|
-
return res.status(500).send(e.message);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// Admin
|
|
234
|
-
exporter.bm_createPost =
|
|
235
|
-
self.libraries.functions
|
|
236
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
237
|
-
.https.onRequest(async (req, res) => {
|
|
238
|
-
const Module = require(`${core}/admin/create-post.js`);
|
|
239
|
-
Module.init(self, { req: req, res: res, });
|
|
240
|
-
|
|
241
|
-
return self._preProcess(Module)
|
|
242
|
-
.then(r => Module.main())
|
|
243
|
-
.catch(e => {
|
|
244
|
-
self.assistant.error(e);
|
|
245
|
-
return res.status(500).send(e.message);
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
exporter.bm_firestoreWrite =
|
|
250
|
-
self.libraries.functions
|
|
251
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
252
|
-
.https.onRequest(async (req, res) => {
|
|
253
|
-
const Module = require(`${core}/admin/firestore-write.js`);
|
|
254
|
-
Module.init(self, { req: req, res: res, });
|
|
255
|
-
|
|
256
|
-
return self._preProcess(Module)
|
|
257
|
-
.then(r => Module.main())
|
|
258
|
-
.catch(e => {
|
|
259
|
-
self.assistant.error(e);
|
|
260
|
-
return res.status(500).send(e.message);
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
exporter.bm_getStats =
|
|
265
|
-
self.libraries.functions
|
|
266
|
-
.runWith({memory: '256MB', timeoutSeconds: 420})
|
|
267
|
-
.https.onRequest(async (req, res) => {
|
|
268
|
-
const Module = require(`${core}/admin/get-stats.js`);
|
|
269
|
-
Module.init(self, { req: req, res: res, });
|
|
270
|
-
|
|
271
|
-
return self._preProcess(Module)
|
|
272
|
-
.then(r => Module.main())
|
|
273
|
-
.catch(e => {
|
|
274
|
-
self.assistant.error(e);
|
|
275
|
-
return res.status(500).send(e.message);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
exporter.bm_sendNotification =
|
|
280
|
-
self.libraries.functions
|
|
281
|
-
.runWith({memory: '1GB', timeoutSeconds: 420})
|
|
282
|
-
.https.onRequest(async (req, res) => {
|
|
283
|
-
const Module = require(`${core}/admin/send-notification.js`);
|
|
284
|
-
Module.init(self, { req: req, res: res, });
|
|
285
|
-
|
|
286
|
-
return self._preProcess(Module)
|
|
287
|
-
.then(r => Module.main())
|
|
288
|
-
.catch(e => {
|
|
289
|
-
self.assistant.error(e);
|
|
290
|
-
return res.status(500).send(e.message);
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
exporter.bm_query =
|
|
295
|
-
self.libraries.functions
|
|
296
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
297
|
-
.https.onRequest(async (req, res) => {
|
|
298
|
-
const Module = require(`${core}/admin/query.js`);
|
|
299
|
-
Module.init(self, { req: req, res: res, });
|
|
300
|
-
|
|
301
|
-
return self._preProcess(Module)
|
|
302
|
-
.then(r => Module.main())
|
|
303
|
-
.catch(e => {
|
|
304
|
-
self.assistant.error(e);
|
|
305
|
-
return res.status(500).send(e.message);
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
exporter.bm_createPostHandler =
|
|
310
|
-
self.libraries.functions
|
|
311
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
312
|
-
.https.onRequest(async (req, res) => {
|
|
313
|
-
const Module = require(`${core}/actions/create-post-handler.js`);
|
|
314
|
-
Module.init(self, { req: req, res: res, });
|
|
315
|
-
|
|
316
|
-
return self._preProcess(Module)
|
|
317
|
-
.then(r => Module.main())
|
|
318
|
-
.catch(e => {
|
|
319
|
-
self.assistant.error(e);
|
|
320
|
-
return res.status(500).send(e.message);
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
exporter.bm_generateUuid =
|
|
325
|
-
self.libraries.functions
|
|
326
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
327
|
-
.https.onRequest(async (req, res) => {
|
|
328
|
-
const Module = require(`${core}/actions/generate-uuid.js`);
|
|
329
|
-
Module.init(self, { req: req, res: res, });
|
|
330
|
-
|
|
331
|
-
return self._preProcess(Module)
|
|
332
|
-
.then(r => Module.main())
|
|
333
|
-
.catch(e => {
|
|
334
|
-
self.assistant.error(e);
|
|
335
|
-
return res.status(500).send(e.message);
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
// Test
|
|
340
|
-
exporter.bm_test_authenticate =
|
|
341
|
-
self.libraries.functions
|
|
342
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
343
|
-
.https.onRequest(async (req, res) => {
|
|
344
|
-
const Module = require(`${test}/authenticate.js`);
|
|
345
|
-
Module.init(self, { req: req, res: res, });
|
|
346
|
-
|
|
347
|
-
return self._preProcess(Module)
|
|
348
|
-
.then(r => Module.main())
|
|
349
|
-
.catch(e => {
|
|
350
|
-
self.assistant.error(e);
|
|
351
|
-
return res.status(500).send(e.message);
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
exporter.bm_test_createTestAccounts =
|
|
356
|
-
self.libraries.functions
|
|
357
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
358
|
-
.https.onRequest(async (req, res) => {
|
|
359
|
-
const Module = require(`${test}/create-test-accounts.js`);
|
|
360
|
-
Module.init(self, { req: req, res: res, });
|
|
361
|
-
|
|
362
|
-
return self._preProcess(Module)
|
|
363
|
-
.then(r => Module.main())
|
|
364
|
-
.catch(e => {
|
|
365
|
-
self.assistant.error(e);
|
|
366
|
-
return res.status(500).send(e.message);
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
exporter.bm_test_webhook =
|
|
371
|
-
self.libraries.functions
|
|
372
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
373
|
-
.https.onRequest(async (req, res) => {
|
|
374
|
-
const Module = require(`${test}/webhook.js`);
|
|
375
|
-
Module.init(self, { req: req, res: res, });
|
|
376
|
-
|
|
377
|
-
return self._preProcess(Module)
|
|
378
|
-
.then(r => Module.main())
|
|
379
|
-
.catch(e => {
|
|
380
|
-
self.assistant.error(e);
|
|
381
|
-
return res.status(500).send(e.message);
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// Events
|
|
387
|
-
if (options.setupFunctionsIdentity) {
|
|
388
|
-
exporter.bm_authBeforeCreate =
|
|
389
|
-
self.libraries.functions
|
|
390
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
391
|
-
.auth.user()
|
|
392
|
-
.beforeCreate(async (user, context) => self._process((new (require(`${core}/events/auth/before-create.js`))()).init(self, { user: user, context: context})));
|
|
393
|
-
|
|
394
|
-
exporter.bm_authBeforeSignIn =
|
|
395
|
-
self.libraries.functions
|
|
396
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
397
|
-
.auth.user()
|
|
398
|
-
.beforeSignIn(async (user, context) => self._process((new (require(`${core}/events/auth/before-signin.js`))()).init(self, { user: user, context: context})));
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
exporter.bm_authOnCreate =
|
|
402
|
-
self.libraries.functions
|
|
403
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
404
|
-
.auth.user()
|
|
405
|
-
.onCreate(async (user, context) => self._process((new (require(`${core}/events/auth/on-create.js`))()).init(self, { user: user, context: context})));
|
|
406
|
-
|
|
407
|
-
exporter.bm_authOnDelete =
|
|
408
|
-
self.libraries.functions
|
|
409
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
410
|
-
.auth.user()
|
|
411
|
-
.onDelete(async (user, context) => self._process((new (require(`${core}/events/auth/on-delete.js`))()).init(self, { user: user, context: context})));
|
|
412
|
-
|
|
413
|
-
exporter.bm_subOnWrite =
|
|
414
|
-
self.libraries.functions
|
|
415
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
416
|
-
.firestore.document('notifications/subscriptions/all/{token}')
|
|
417
|
-
.onWrite(async (change, context) => self._process((new (require(`${core}/events/firestore/on-subscription.js`))()).init(self, { change: change, context: context, })));
|
|
221
|
+
// Setup main functions
|
|
222
|
+
if (options.projectType === 'firebase' && options.setupFunctions) {
|
|
223
|
+
self.setupFunctions(exporter, options);
|
|
224
|
+
}
|
|
418
225
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
self.
|
|
422
|
-
.runWith({ memory: '256MB', timeoutSeconds: 120 })
|
|
423
|
-
.pubsub.schedule('every 24 hours')
|
|
424
|
-
.onRun(async (context) => self._process((new (require(`${core}/cron/daily.js`))()).init(self, { context: context, })));
|
|
226
|
+
// Setup custom server
|
|
227
|
+
if (options.projectType === 'custom') {
|
|
228
|
+
self.setupCustomServer(exporter, options);
|
|
425
229
|
}
|
|
426
230
|
|
|
427
231
|
// Set dotenv
|
|
@@ -799,6 +603,380 @@ Manager.prototype.debug = function () {
|
|
|
799
603
|
}
|
|
800
604
|
}
|
|
801
605
|
|
|
606
|
+
// Setup functions
|
|
607
|
+
Manager.prototype.setupFunctions = function (exporter, options) {
|
|
608
|
+
const self = this;
|
|
609
|
+
|
|
610
|
+
// Log
|
|
611
|
+
if (options.log) {
|
|
612
|
+
self.assistant.log('Setting up Firebase functions...');
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Setup functions
|
|
616
|
+
exporter.bm_api =
|
|
617
|
+
self.libraries.functions
|
|
618
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
619
|
+
// TODO: Replace this with new API
|
|
620
|
+
.https.onRequest(async (req, res) => self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, })));
|
|
621
|
+
|
|
622
|
+
// Setup legacy functions
|
|
623
|
+
if (options.setupFunctionsLegacy) {
|
|
624
|
+
exporter.bm_signUpHandler =
|
|
625
|
+
self.libraries.functions
|
|
626
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
627
|
+
.https.onRequest(async (req, res) => {
|
|
628
|
+
const Module = require(`${core}/actions/sign-up-handler.js`);
|
|
629
|
+
Module.init(self, { req: req, res: res, });
|
|
630
|
+
|
|
631
|
+
return self._preProcess(Module)
|
|
632
|
+
.then(r => Module.main())
|
|
633
|
+
.catch(e => {
|
|
634
|
+
self.assistant.error(e);
|
|
635
|
+
return res.status(500).send(e.message);
|
|
636
|
+
});
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// Admin
|
|
640
|
+
exporter.bm_createPost =
|
|
641
|
+
self.libraries.functions
|
|
642
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
643
|
+
.https.onRequest(async (req, res) => {
|
|
644
|
+
const Module = require(`${core}/admin/create-post.js`);
|
|
645
|
+
Module.init(self, { req: req, res: res, });
|
|
646
|
+
|
|
647
|
+
return self._preProcess(Module)
|
|
648
|
+
.then(r => Module.main())
|
|
649
|
+
.catch(e => {
|
|
650
|
+
self.assistant.error(e);
|
|
651
|
+
return res.status(500).send(e.message);
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
exporter.bm_firestoreWrite =
|
|
656
|
+
self.libraries.functions
|
|
657
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
658
|
+
.https.onRequest(async (req, res) => {
|
|
659
|
+
const Module = require(`${core}/admin/firestore-write.js`);
|
|
660
|
+
Module.init(self, { req: req, res: res, });
|
|
661
|
+
|
|
662
|
+
return self._preProcess(Module)
|
|
663
|
+
.then(r => Module.main())
|
|
664
|
+
.catch(e => {
|
|
665
|
+
self.assistant.error(e);
|
|
666
|
+
return res.status(500).send(e.message);
|
|
667
|
+
});
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
exporter.bm_getStats =
|
|
671
|
+
self.libraries.functions
|
|
672
|
+
.runWith({memory: '256MB', timeoutSeconds: 420})
|
|
673
|
+
.https.onRequest(async (req, res) => {
|
|
674
|
+
const Module = require(`${core}/admin/get-stats.js`);
|
|
675
|
+
Module.init(self, { req: req, res: res, });
|
|
676
|
+
|
|
677
|
+
return self._preProcess(Module)
|
|
678
|
+
.then(r => Module.main())
|
|
679
|
+
.catch(e => {
|
|
680
|
+
self.assistant.error(e);
|
|
681
|
+
return res.status(500).send(e.message);
|
|
682
|
+
});
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
exporter.bm_sendNotification =
|
|
686
|
+
self.libraries.functions
|
|
687
|
+
.runWith({memory: '1GB', timeoutSeconds: 420})
|
|
688
|
+
.https.onRequest(async (req, res) => {
|
|
689
|
+
const Module = require(`${core}/admin/send-notification.js`);
|
|
690
|
+
Module.init(self, { req: req, res: res, });
|
|
691
|
+
|
|
692
|
+
return self._preProcess(Module)
|
|
693
|
+
.then(r => Module.main())
|
|
694
|
+
.catch(e => {
|
|
695
|
+
self.assistant.error(e);
|
|
696
|
+
return res.status(500).send(e.message);
|
|
697
|
+
});
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
exporter.bm_query =
|
|
701
|
+
self.libraries.functions
|
|
702
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
703
|
+
.https.onRequest(async (req, res) => {
|
|
704
|
+
const Module = require(`${core}/admin/query.js`);
|
|
705
|
+
Module.init(self, { req: req, res: res, });
|
|
706
|
+
|
|
707
|
+
return self._preProcess(Module)
|
|
708
|
+
.then(r => Module.main())
|
|
709
|
+
.catch(e => {
|
|
710
|
+
self.assistant.error(e);
|
|
711
|
+
return res.status(500).send(e.message);
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
exporter.bm_createPostHandler =
|
|
716
|
+
self.libraries.functions
|
|
717
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
718
|
+
.https.onRequest(async (req, res) => {
|
|
719
|
+
const Module = require(`${core}/actions/create-post-handler.js`);
|
|
720
|
+
Module.init(self, { req: req, res: res, });
|
|
721
|
+
|
|
722
|
+
return self._preProcess(Module)
|
|
723
|
+
.then(r => Module.main())
|
|
724
|
+
.catch(e => {
|
|
725
|
+
self.assistant.error(e);
|
|
726
|
+
return res.status(500).send(e.message);
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
exporter.bm_generateUuid =
|
|
731
|
+
self.libraries.functions
|
|
732
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
733
|
+
.https.onRequest(async (req, res) => {
|
|
734
|
+
const Module = require(`${core}/actions/generate-uuid.js`);
|
|
735
|
+
Module.init(self, { req: req, res: res, });
|
|
736
|
+
|
|
737
|
+
return self._preProcess(Module)
|
|
738
|
+
.then(r => Module.main())
|
|
739
|
+
.catch(e => {
|
|
740
|
+
self.assistant.error(e);
|
|
741
|
+
return res.status(500).send(e.message);
|
|
742
|
+
});
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
// Test
|
|
746
|
+
exporter.bm_test_authenticate =
|
|
747
|
+
self.libraries.functions
|
|
748
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
749
|
+
.https.onRequest(async (req, res) => {
|
|
750
|
+
const Module = require(`${test}/authenticate.js`);
|
|
751
|
+
Module.init(self, { req: req, res: res, });
|
|
752
|
+
|
|
753
|
+
return self._preProcess(Module)
|
|
754
|
+
.then(r => Module.main())
|
|
755
|
+
.catch(e => {
|
|
756
|
+
self.assistant.error(e);
|
|
757
|
+
return res.status(500).send(e.message);
|
|
758
|
+
});
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
exporter.bm_test_createTestAccounts =
|
|
762
|
+
self.libraries.functions
|
|
763
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
764
|
+
.https.onRequest(async (req, res) => {
|
|
765
|
+
const Module = require(`${test}/create-test-accounts.js`);
|
|
766
|
+
Module.init(self, { req: req, res: res, });
|
|
767
|
+
|
|
768
|
+
return self._preProcess(Module)
|
|
769
|
+
.then(r => Module.main())
|
|
770
|
+
.catch(e => {
|
|
771
|
+
self.assistant.error(e);
|
|
772
|
+
return res.status(500).send(e.message);
|
|
773
|
+
});
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
exporter.bm_test_webhook =
|
|
777
|
+
self.libraries.functions
|
|
778
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
779
|
+
.https.onRequest(async (req, res) => {
|
|
780
|
+
const Module = require(`${test}/webhook.js`);
|
|
781
|
+
Module.init(self, { req: req, res: res, });
|
|
782
|
+
|
|
783
|
+
return self._preProcess(Module)
|
|
784
|
+
.then(r => Module.main())
|
|
785
|
+
.catch(e => {
|
|
786
|
+
self.assistant.error(e);
|
|
787
|
+
return res.status(500).send(e.message);
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Setup identity functions
|
|
793
|
+
if (options.setupFunctionsIdentity) {
|
|
794
|
+
exporter.bm_authBeforeCreate =
|
|
795
|
+
self.libraries.functions
|
|
796
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
797
|
+
.auth.user()
|
|
798
|
+
.beforeCreate(async (user, context) => self._process((new (require(`${core}/events/auth/before-create.js`))()).init(self, { user: user, context: context})));
|
|
799
|
+
|
|
800
|
+
exporter.bm_authBeforeSignIn =
|
|
801
|
+
self.libraries.functions
|
|
802
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
803
|
+
.auth.user()
|
|
804
|
+
.beforeSignIn(async (user, context) => self._process((new (require(`${core}/events/auth/before-signin.js`))()).init(self, { user: user, context: context})));
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// Setup events
|
|
808
|
+
exporter.bm_authOnCreate =
|
|
809
|
+
self.libraries.functions
|
|
810
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
811
|
+
.auth.user()
|
|
812
|
+
.onCreate(async (user, context) => self._process((new (require(`${core}/events/auth/on-create.js`))()).init(self, { user: user, context: context})));
|
|
813
|
+
|
|
814
|
+
exporter.bm_authOnDelete =
|
|
815
|
+
self.libraries.functions
|
|
816
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
817
|
+
.auth.user()
|
|
818
|
+
.onDelete(async (user, context) => self._process((new (require(`${core}/events/auth/on-delete.js`))()).init(self, { user: user, context: context})));
|
|
819
|
+
|
|
820
|
+
exporter.bm_subOnWrite =
|
|
821
|
+
self.libraries.functions
|
|
822
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
823
|
+
.firestore.document('notifications/subscriptions/all/{token}')
|
|
824
|
+
.onWrite(async (change, context) => self._process((new (require(`${core}/events/firestore/on-subscription.js`))()).init(self, { change: change, context: context, })));
|
|
825
|
+
|
|
826
|
+
// Setup cron jobs
|
|
827
|
+
exporter.bm_cronDaily =
|
|
828
|
+
self.libraries.functions
|
|
829
|
+
.runWith({ memory: '256MB', timeoutSeconds: 120 })
|
|
830
|
+
.pubsub.schedule('every 24 hours')
|
|
831
|
+
.onRun(async (context) => self._process((new (require(`${core}/cron/daily.js`))()).init(self, { context: context, })));
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
// Setup Custom Server
|
|
835
|
+
Manager.prototype.setupCustomServer = function (_library, options) {
|
|
836
|
+
const self = this;
|
|
837
|
+
|
|
838
|
+
// Require
|
|
839
|
+
const glob = require('glob').globSync;
|
|
840
|
+
|
|
841
|
+
// Log
|
|
842
|
+
if (options.log) {
|
|
843
|
+
self.assistant.log('Setting up custom server...');
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// Setup fastify
|
|
847
|
+
// const app = library({
|
|
848
|
+
// logger: true,
|
|
849
|
+
// // querystringParser: str => querystring.parse(str.toLowerCase())
|
|
850
|
+
// });
|
|
851
|
+
|
|
852
|
+
//
|
|
853
|
+
const app = require('express')({
|
|
854
|
+
logger: true,
|
|
855
|
+
// querystringParser: str => querystring.parse(str.toLowerCase())
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
// Setup body parser
|
|
859
|
+
app.use(require('body-parser').json());
|
|
860
|
+
|
|
861
|
+
// Designate paths
|
|
862
|
+
const managerRoutesPath = path.normalize(`${__dirname}/routes`);
|
|
863
|
+
const managerSchemasPath = path.normalize(`${__dirname}/schemas`);
|
|
864
|
+
const customRoutesPath = path.normalize(`${self.cwd}${options.routes}`);
|
|
865
|
+
const customSchemasPath = path.normalize(`${self.cwd}${options.schemas}`);
|
|
866
|
+
|
|
867
|
+
// Create routes
|
|
868
|
+
const routes = [];
|
|
869
|
+
|
|
870
|
+
// Push function
|
|
871
|
+
function _push(dir, isManager) {
|
|
872
|
+
// Get all files
|
|
873
|
+
glob('**/index.js', { cwd: dir })
|
|
874
|
+
.forEach((file) => {
|
|
875
|
+
// Build the item
|
|
876
|
+
const item = {
|
|
877
|
+
name: file.replace('/index.js', ''),
|
|
878
|
+
namespace: file,
|
|
879
|
+
path: path.resolve(dir, file),
|
|
880
|
+
dir: dir,
|
|
881
|
+
isManager: isManager,
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// If it exists in routes, replace it
|
|
885
|
+
const existing = routes.findIndex(r => r.name === item.name);
|
|
886
|
+
if (existing > -1) {
|
|
887
|
+
routes[existing] = item;
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// Otherwise, push it
|
|
892
|
+
routes.push(item);
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// Push routes
|
|
897
|
+
// _push(`${__dirname}/routes`)
|
|
898
|
+
_push(managerRoutesPath, true)
|
|
899
|
+
_push(customRoutesPath, false)
|
|
900
|
+
|
|
901
|
+
// Log routes
|
|
902
|
+
// if (options.log) {
|
|
903
|
+
// self.assistant.log('Routes:', routes);
|
|
904
|
+
// }
|
|
905
|
+
|
|
906
|
+
// Install process
|
|
907
|
+
routes.forEach((file) => {
|
|
908
|
+
// console.log('---file', file);
|
|
909
|
+
// Require the file
|
|
910
|
+
const cors = self.libraries.cors;
|
|
911
|
+
|
|
912
|
+
// Log
|
|
913
|
+
if (options.log) {
|
|
914
|
+
self.assistant.log(`Initializing route: ${file.name} @ ${file.path}`);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// Register the route
|
|
918
|
+
app.all(`/${file.name}`, async (req, res) => {
|
|
919
|
+
return cors(req, res, async () => {
|
|
920
|
+
// self.Middleware(req, res).run(file.name, {schema: file.name})
|
|
921
|
+
self.Middleware(req, res).run(file.name, {
|
|
922
|
+
schema: file.name,
|
|
923
|
+
routesDir: file.isManager ? managerRoutesPath : customRoutesPath,
|
|
924
|
+
schemasDir: file.isManager ? managerSchemasPath : customSchemasPath,
|
|
925
|
+
})
|
|
926
|
+
});
|
|
927
|
+
})
|
|
928
|
+
|
|
929
|
+
// app.all(`/${name}`, async (req, res) => {
|
|
930
|
+
// return cors(req, res, async () => {
|
|
931
|
+
// // Fix req/res
|
|
932
|
+
// req.body = req.body || {};
|
|
933
|
+
// req.query = Object.assign({}, req.query || {});
|
|
934
|
+
|
|
935
|
+
// // Manager.Middleware(req, res).run('tools/screenshot', {schema: 'screenshot'})
|
|
936
|
+
// const handler = new (require(file.path))();
|
|
937
|
+
// const assistant = self.Assistant({req: req, res: res}, {functionName: name, functionType: 'http'});
|
|
938
|
+
// // const apiUser = await ApiManager.getUser(assistant);
|
|
939
|
+
|
|
940
|
+
// // Set handler properties
|
|
941
|
+
// handler.Manager = self;
|
|
942
|
+
// handler.assistant = assistant;
|
|
943
|
+
// handler.apiUser = null;
|
|
944
|
+
|
|
945
|
+
// // Log
|
|
946
|
+
// if (options.log) {
|
|
947
|
+
// self.assistant.log(`[Request] ${name} @ ${filepath}`, req.body, req.query);
|
|
948
|
+
// }
|
|
949
|
+
|
|
950
|
+
// // Execute the route
|
|
951
|
+
// try {
|
|
952
|
+
// await handler.process(req, res);
|
|
953
|
+
// } catch (e) {
|
|
954
|
+
// assistant.respond(e, {code: e.code});
|
|
955
|
+
// }
|
|
956
|
+
// });
|
|
957
|
+
// })
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
// Run the server!
|
|
961
|
+
const server = app.listen({ port: process.env.PORT || 3000, host: '0.0.0.0' }, () => {
|
|
962
|
+
const address = server.address();
|
|
963
|
+
|
|
964
|
+
// Check if there's an error
|
|
965
|
+
if (server.address() === null) {
|
|
966
|
+
self.assistant.error(e);
|
|
967
|
+
process.exit(1);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// Log
|
|
971
|
+
if (options.log) {
|
|
972
|
+
self.assistant.log(`Server listening on ${address.address}:${address.port}`);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
// Emit event
|
|
976
|
+
self.emit('online', new Event('online'), server, app);
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
|
|
802
980
|
function resolveProjectPackage() {
|
|
803
981
|
try {
|
|
804
982
|
return require(path.resolve(process.cwd(), 'functions', 'package.json'));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function Route() {
|
|
2
|
+
const self = this;
|
|
3
|
+
|
|
4
|
+
return self;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
Route.prototype.process = async function (assistant) {
|
|
8
|
+
const self = this;
|
|
9
|
+
|
|
10
|
+
// Set shortcuts
|
|
11
|
+
const Manager = assistant.Manager;
|
|
12
|
+
const usage = assistant.usage;
|
|
13
|
+
const user = assistant.usage.user;
|
|
14
|
+
const analytics = assistant.analytics;
|
|
15
|
+
const settings = assistant.settings;
|
|
16
|
+
|
|
17
|
+
// Load preloaded libraries
|
|
18
|
+
const jetpack = require('fs-jetpack');
|
|
19
|
+
|
|
20
|
+
// Send analytics event
|
|
21
|
+
analytics.event({
|
|
22
|
+
name: 'restart',
|
|
23
|
+
params: {},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Check for user authentication
|
|
27
|
+
// if (!user.roles.admin) {
|
|
28
|
+
// return assistant.respond(`Admin required`, {code: 401});;
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
// Log
|
|
32
|
+
assistant.log('Restarting...');
|
|
33
|
+
|
|
34
|
+
// Remove node_modules
|
|
35
|
+
jetpack.remove('node_modules');
|
|
36
|
+
|
|
37
|
+
// Perform delayed refresh to allow a successful response
|
|
38
|
+
setTimeout(function () {
|
|
39
|
+
require('child_process').exec('refresh', (error, stdout, stderr) => {
|
|
40
|
+
// Quit the process if there is an error
|
|
41
|
+
if (error || stderr) {
|
|
42
|
+
console.log(`error: ${error ? error.message : stderr}`);
|
|
43
|
+
return process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}, 1000);
|
|
47
|
+
|
|
48
|
+
// Return success
|
|
49
|
+
assistant.respond({success: true});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
module.exports = Route;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function Route() {
|
|
2
|
+
const self = this;
|
|
3
|
+
|
|
4
|
+
return self;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
Route.prototype.main = async function (assistant) {
|
|
8
|
+
const self = this;
|
|
9
|
+
|
|
10
|
+
// Set shortcuts
|
|
11
|
+
const Manager = assistant.Manager;
|
|
12
|
+
const usage = assistant.usage;
|
|
13
|
+
const user = assistant.usage.user;
|
|
14
|
+
const analytics = assistant.analytics;
|
|
15
|
+
const settings = assistant.settings;
|
|
16
|
+
|
|
17
|
+
// Load preloaded libraries
|
|
18
|
+
// ..
|
|
19
|
+
|
|
20
|
+
// Send analytics event
|
|
21
|
+
analytics.event({
|
|
22
|
+
name: 'test',
|
|
23
|
+
params: {},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Check for user authentication
|
|
27
|
+
// if (!user.roles.admin) {
|
|
28
|
+
// return assistant.respond(`Admin required`, {code: 401});;
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
// Log
|
|
32
|
+
assistant.log('Running test');
|
|
33
|
+
assistant.log('assistant.request.body', assistant.request.body);
|
|
34
|
+
assistant.log('assistant.request.query', assistant.request.query);
|
|
35
|
+
assistant.log('assistant.request.headers', assistant.request.headers);
|
|
36
|
+
assistant.log('assistant.request.data', assistant.request.data);
|
|
37
|
+
assistant.log('assistant.settings', assistant.settings);
|
|
38
|
+
|
|
39
|
+
// Return success
|
|
40
|
+
assistant.respond({timestamp: new Date().toISOString(), id: assistant.id});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
module.exports = Route;
|