backend-manager 5.0.132 → 5.0.134
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/CLAUDE.md +6 -6
- package/package.json +6 -6
- package/src/cli/commands/emulator.js +1 -1
- package/src/cli/commands/logs.js +2 -2
- package/src/cli/commands/serve.js +42 -2
- package/src/cli/commands/setup-tests/remoteconfig-template-in-json.js +13 -2
- package/src/cli/commands/test.js +1 -1
- package/src/manager/routes/admin/post/post.js +0 -3
package/CLAUDE.md
CHANGED
|
@@ -467,16 +467,16 @@ npx bm test
|
|
|
467
467
|
```
|
|
468
468
|
|
|
469
469
|
### Log Files
|
|
470
|
-
|
|
471
|
-
- **`
|
|
472
|
-
- **`
|
|
470
|
+
BEM CLI commands automatically save all output to log files in `functions/` while still streaming to the console:
|
|
471
|
+
- **`functions/serve.log`** — Output from `npx bm serve` (Firebase serve)
|
|
472
|
+
- **`functions/emulator.log`** — Full emulator output (Firebase emulator + Cloud Functions logs)
|
|
473
|
+
- **`functions/test.log`** — Test runner output (when running against an existing emulator)
|
|
474
|
+
- **`functions/logs.log`** — Cloud Function logs from `npx bm logs:read` or `npx bm logs:tail` (raw JSON for `read`, streaming text for `tail`)
|
|
473
475
|
|
|
474
476
|
When `npx bm test` starts its own emulator, logs go to `emulator.log` (since it delegates to the emulator command). When running against an already-running emulator, logs go to `test.log`.
|
|
475
477
|
|
|
476
478
|
These files are overwritten on each run and are gitignored (`*.log`). Use them to search for errors, debug webhook pipelines, or review full function output after a test run.
|
|
477
479
|
|
|
478
|
-
- **`logs.log`** — Cloud Function logs from `npx bm logs:read` or `npx bm logs:tail` (raw JSON for `read`, streaming text for `tail`)
|
|
479
|
-
|
|
480
480
|
### Filtering Tests
|
|
481
481
|
```bash
|
|
482
482
|
npx bm test rules/ # Run rules tests (both BEM and project)
|
|
@@ -630,7 +630,7 @@ npx bm logs:tail # Stream live logs
|
|
|
630
630
|
npx bm logs:tail --fn bm_paymentsWebhookOnWrite # Stream filtered live logs
|
|
631
631
|
```
|
|
632
632
|
|
|
633
|
-
Both commands save output to `logs.log`
|
|
633
|
+
Both commands save output to `functions/logs.log` (overwritten on each run). `logs:read` saves raw JSON; `logs:tail` streams text.
|
|
634
634
|
|
|
635
635
|
| Flag | Description | Default | Commands |
|
|
636
636
|
|------|-------------|---------|----------|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.134",
|
|
4
4
|
"description": "Quick tools for developing Firebase functions",
|
|
5
5
|
"main": "src/manager/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"node": "22"
|
|
19
19
|
},
|
|
20
20
|
"projectScripts": {
|
|
21
|
-
"start": "npx
|
|
22
|
-
"deploy": "npx
|
|
23
|
-
"emulator": "npx
|
|
24
|
-
"test": "npx
|
|
25
|
-
"setup": "npx
|
|
21
|
+
"start": "npx mgr setup && npx mgr serve",
|
|
22
|
+
"deploy": "npx mgr setup && npx mgr deploy",
|
|
23
|
+
"emulator": "npx mgr setup && npx mgr emulator",
|
|
24
|
+
"test": "npx mgr setup && npx mgr test",
|
|
25
|
+
"setup": "npx mgr setup"
|
|
26
26
|
},
|
|
27
27
|
"repository": {
|
|
28
28
|
"type": "git",
|
|
@@ -62,7 +62,7 @@ class EmulatorCommand extends BaseCommand {
|
|
|
62
62
|
const emulatorCommand = `BEM_TESTING=true firebase emulators:exec --only functions,firestore,auth,database,hosting,pubsub --ui "${command}"`;
|
|
63
63
|
|
|
64
64
|
// Set up log file in the project directory
|
|
65
|
-
const logPath = path.join(projectDir, 'emulator.log');
|
|
65
|
+
const logPath = path.join(projectDir, 'functions', 'emulator.log');
|
|
66
66
|
const logStream = fs.createWriteStream(logPath, { flags: 'w' });
|
|
67
67
|
const stripAnsi = (str) => str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
|
|
68
68
|
|
package/src/cli/commands/logs.js
CHANGED
|
@@ -73,7 +73,7 @@ class LogsCommand extends BaseCommand {
|
|
|
73
73
|
|
|
74
74
|
// Set up log file in the project directory
|
|
75
75
|
const projectDir = this.main.firebaseProjectPath;
|
|
76
|
-
const logPath = path.join(projectDir, 'logs.log');
|
|
76
|
+
const logPath = path.join(projectDir, 'functions', 'logs.log');
|
|
77
77
|
|
|
78
78
|
this.log(chalk.gray(` Filter: ${filter || '(none)'}`));
|
|
79
79
|
this.log(chalk.gray(` Limit: ${limit}`));
|
|
@@ -127,7 +127,7 @@ class LogsCommand extends BaseCommand {
|
|
|
127
127
|
|
|
128
128
|
// Set up log file in the project directory
|
|
129
129
|
const projectDir = this.main.firebaseProjectPath;
|
|
130
|
-
const logPath = path.join(projectDir, 'logs.log');
|
|
130
|
+
const logPath = path.join(projectDir, 'functions', 'logs.log');
|
|
131
131
|
const logStream = fs.createWriteStream(logPath, { flags: 'w' });
|
|
132
132
|
|
|
133
133
|
const filter = this.buildFilter(argv, { excludeTimestamp: true });
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const BaseCommand = require('./base-command');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const chalk = require('chalk');
|
|
2
5
|
const powertools = require('node-powertools');
|
|
3
6
|
const WatchCommand = require('./watch');
|
|
4
7
|
|
|
@@ -6,6 +9,7 @@ class ServeCommand extends BaseCommand {
|
|
|
6
9
|
async execute() {
|
|
7
10
|
const self = this.main;
|
|
8
11
|
const port = self.argv.port || self.argv?._?.[1] || '5000';
|
|
12
|
+
const projectDir = self.firebaseProjectPath;
|
|
9
13
|
|
|
10
14
|
// Start BEM watcher in background
|
|
11
15
|
const watcher = new WatchCommand(self);
|
|
@@ -14,8 +18,44 @@ class ServeCommand extends BaseCommand {
|
|
|
14
18
|
// Start Stripe webhook forwarding in background
|
|
15
19
|
this.startStripeWebhookForwarding();
|
|
16
20
|
|
|
17
|
-
//
|
|
18
|
-
|
|
21
|
+
// Set up log file in the project directory
|
|
22
|
+
const logPath = path.join(projectDir, 'functions', 'serve.log');
|
|
23
|
+
const logStream = fs.createWriteStream(logPath, { flags: 'w' });
|
|
24
|
+
const stripAnsi = (str) => str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
|
|
25
|
+
|
|
26
|
+
this.log(chalk.gray(` Logs saving to: ${logPath}\n`));
|
|
27
|
+
|
|
28
|
+
// Execute with tee to log file
|
|
29
|
+
try {
|
|
30
|
+
await powertools.execute(`firebase serve --port ${port}`, {
|
|
31
|
+
log: false,
|
|
32
|
+
cwd: projectDir,
|
|
33
|
+
config: {
|
|
34
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
35
|
+
env: { ...process.env, FORCE_COLOR: '1' },
|
|
36
|
+
},
|
|
37
|
+
}, (child) => {
|
|
38
|
+
// Tee stdout to both console and log file (strip ANSI codes for clean log)
|
|
39
|
+
child.stdout.on('data', (data) => {
|
|
40
|
+
process.stdout.write(data);
|
|
41
|
+
logStream.write(stripAnsi(data.toString()));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Tee stderr to both console and log file (strip ANSI codes for clean log)
|
|
45
|
+
child.stderr.on('data', (data) => {
|
|
46
|
+
process.stderr.write(data);
|
|
47
|
+
logStream.write(stripAnsi(data.toString()));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Clean up log stream when child exits
|
|
51
|
+
child.on('close', () => {
|
|
52
|
+
logStream.end();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
} catch (error) {
|
|
56
|
+
// User pressed Ctrl+C - this is expected
|
|
57
|
+
this.log(chalk.gray('\n Server stopped.\n'));
|
|
58
|
+
}
|
|
19
59
|
}
|
|
20
60
|
}
|
|
21
61
|
|
|
@@ -2,17 +2,28 @@ const BaseTest = require('./base-test');
|
|
|
2
2
|
const jetpack = require('fs-jetpack');
|
|
3
3
|
const _ = require('lodash');
|
|
4
4
|
|
|
5
|
+
const ENABLED = false;
|
|
6
|
+
|
|
5
7
|
class RemoteconfigTemplateInJsonTest extends BaseTest {
|
|
6
8
|
getName() {
|
|
7
9
|
return 'remoteconfig template in JSON';
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
async run() {
|
|
11
|
-
|
|
13
|
+
if (ENABLED) {
|
|
14
|
+
return this.self.firebaseJSON?.remoteconfig?.template === 'remoteconfig.template.json';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return !this.self.firebaseJSON?.remoteconfig;
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
async fix() {
|
|
15
|
-
|
|
21
|
+
if (ENABLED) {
|
|
22
|
+
_.set(this.self.firebaseJSON, 'remoteconfig.template', 'remoteconfig.template.json');
|
|
23
|
+
} else {
|
|
24
|
+
delete this.self.firebaseJSON.remoteconfig;
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
jetpack.write(`${this.self.firebaseProjectPath}/firebase.json`, JSON.stringify(this.self.firebaseJSON, null, 2));
|
|
17
28
|
}
|
|
18
29
|
}
|
package/src/cli/commands/test.js
CHANGED
|
@@ -185,7 +185,7 @@ class TestCommand extends BaseCommand {
|
|
|
185
185
|
this.log(chalk.gray(` UI: http://127.0.0.1:${emulatorPorts.ui}`));
|
|
186
186
|
|
|
187
187
|
// Set up log file in the project directory
|
|
188
|
-
const logPath = path.join(projectDir, 'test.log');
|
|
188
|
+
const logPath = path.join(projectDir, 'functions', 'test.log');
|
|
189
189
|
const logStream = fs.createWriteStream(logPath, { flags: 'w' });
|
|
190
190
|
const stripAnsi = (str) => str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
|
|
191
191
|
|
|
@@ -271,9 +271,6 @@ async function uploadPost(assistant, octokit, settings, content) {
|
|
|
271
271
|
throw existing;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
-
// Wait for GitHub to process images
|
|
275
|
-
await powertools.wait(30000);
|
|
276
|
-
|
|
277
274
|
// Upload post
|
|
278
275
|
const result = await octokit.rest.repos.createOrUpdateFileContents({
|
|
279
276
|
owner: owner,
|