@pulse-labs/server-pulse 0.0.1 → 0.0.2
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 +6 -0
- package/README.md +119 -12
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.0.2] - 2026-10-15
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- README: step-by-step guide for using the package in a project (install, Express CommonJS/ESM/TypeScript, NestJS, dashboard credentials via environment variables, opening the dashboard, mounting rules, updating).
|
|
14
|
+
|
|
9
15
|
## [0.0.1] - 2026-10-14
|
|
10
16
|
|
|
11
17
|
First public preview on npm as `@pulse-labs/server-pulse`. Scaffold only: the middleware is a pass-through. (Briefly published as `@mukesh-singh9862/server-pulse`, which was unpublished.)
|
package/README.md
CHANGED
|
@@ -4,42 +4,149 @@ Live server monitoring dashboard for Node.js apps, served from your own base URL
|
|
|
4
4
|
|
|
5
5
|
> **Status:** early preview (`0.0.x`, milestone M0 — project scaffold). The middleware is currently a pass-through and does not collect anything yet. Do not use it in production before `1.0.0`. Sections marked _TODO_ are completed in later milestones.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Use it in your project (step by step)
|
|
8
|
+
|
|
9
|
+
> In `0.0.x` the setup below already installs and runs, but the dashboard at `/monitor` is not served yet. Your setup code stays the same when the full version is released.
|
|
10
|
+
|
|
11
|
+
### Step 1: Check your Node.js version
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node -v
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
You need Node.js **18.15 or newer**.
|
|
18
|
+
|
|
19
|
+
### Step 2: Install the package
|
|
20
|
+
|
|
21
|
+
Run this in your project folder (the one that contains your project's `package.json`):
|
|
8
22
|
|
|
9
23
|
```bash
|
|
10
24
|
npm install @pulse-labs/server-pulse
|
|
11
25
|
```
|
|
12
26
|
|
|
13
|
-
|
|
27
|
+
The package has **no runtime dependencies** and ships its own TypeScript types, so you don't need a separate `@types` package.
|
|
28
|
+
|
|
29
|
+
### Step 3: Add it to your app
|
|
14
30
|
|
|
15
|
-
|
|
31
|
+
Works with **Express 4 and Express 5** (the two current major versions of Express). The code is the same for both.
|
|
32
|
+
|
|
33
|
+
**Express (CommonJS, `require`)**
|
|
16
34
|
|
|
17
35
|
```js
|
|
18
36
|
const express = require('express');
|
|
19
37
|
const { serverPulse } = require('@pulse-labs/server-pulse');
|
|
20
38
|
|
|
21
39
|
const app = express();
|
|
40
|
+
|
|
22
41
|
const pulse = serverPulse({
|
|
23
42
|
auth: { username: process.env.PULSE_USER, password: process.env.PULSE_PASS },
|
|
24
43
|
});
|
|
25
|
-
app.use(pulse); // must be the FIRST middleware
|
|
44
|
+
app.use(pulse); // 1. must be the FIRST middleware
|
|
45
|
+
|
|
46
|
+
app.use(express.json()); // 2. your other middleware comes after it
|
|
47
|
+
app.get('/api/products', (req, res) => res.json([]));
|
|
26
48
|
// ... your routes ...
|
|
27
|
-
|
|
49
|
+
|
|
50
|
+
app.use(pulse.errorHandler()); // 3. optional, AFTER your routes: shows error messages in "Recent errors"
|
|
51
|
+
|
|
28
52
|
app.listen(3000);
|
|
29
53
|
```
|
|
30
54
|
|
|
31
|
-
|
|
55
|
+
**Express with ESM or TypeScript (`import`)**
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import express from 'express';
|
|
59
|
+
import { serverPulse } from '@pulse-labs/server-pulse';
|
|
32
60
|
|
|
33
|
-
|
|
61
|
+
const app = express();
|
|
62
|
+
const pulse = serverPulse({
|
|
63
|
+
auth: { username: process.env.PULSE_USER!, password: process.env.PULSE_PASS! },
|
|
64
|
+
});
|
|
65
|
+
app.use(pulse);
|
|
66
|
+
// ... your routes ...
|
|
67
|
+
app.use(pulse.errorHandler());
|
|
68
|
+
app.listen(3000);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**NestJS** (in `main.ts`; NestJS uses Express by default)
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { NestFactory } from '@nestjs/core';
|
|
75
|
+
import { serverPulse } from '@pulse-labs/server-pulse';
|
|
76
|
+
import { AppModule } from './app.module';
|
|
77
|
+
|
|
78
|
+
async function bootstrap() {
|
|
79
|
+
const app = await NestFactory.create(AppModule);
|
|
80
|
+
const pulse = serverPulse({
|
|
81
|
+
auth: { username: process.env.PULSE_USER!, password: process.env.PULSE_PASS! },
|
|
82
|
+
});
|
|
83
|
+
app.use(pulse);
|
|
84
|
+
// optional: call pulse.captureError(err, req) inside your global exception filter
|
|
85
|
+
await app.listen(3000);
|
|
86
|
+
}
|
|
87
|
+
bootstrap();
|
|
88
|
+
```
|
|
34
89
|
|
|
35
|
-
###
|
|
90
|
+
### Step 4: Set the dashboard login
|
|
36
91
|
|
|
37
|
-
|
|
38
|
-
- Do not mount it under a sub-path (`app.use('/x', pulse)` is unsupported). Use the `basePath` option instead.
|
|
92
|
+
Never write the username and password in your code. Use environment variables:
|
|
39
93
|
|
|
40
|
-
|
|
94
|
+
| Variable | Purpose |
|
|
95
|
+
| -------------- | -------------------------------------------------------------------------------------------------------- |
|
|
96
|
+
| `PULSE_USER` | Dashboard username |
|
|
97
|
+
| `PULSE_PASS` | Dashboard password (use a strong one) |
|
|
98
|
+
| `PULSE_SECRET` | Long random string that signs login sessions. If it is not set, everyone is logged out on every restart. |
|
|
41
99
|
|
|
42
|
-
|
|
100
|
+
PowerShell (Windows):
|
|
101
|
+
|
|
102
|
+
```powershell
|
|
103
|
+
$env:PULSE_USER="admin"
|
|
104
|
+
$env:PULSE_PASS="a-strong-password"
|
|
105
|
+
$env:PULSE_SECRET="a-long-random-string"
|
|
106
|
+
node server.js
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
macOS / Linux:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
PULSE_USER=admin PULSE_PASS=a-strong-password PULSE_SECRET=a-long-random-string node server.js
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Or in a `.env` file, if your project uses [dotenv](https://www.npmjs.com/package/dotenv). Do not commit the `.env` file to git.
|
|
116
|
+
|
|
117
|
+
```dotenv
|
|
118
|
+
PULSE_USER=admin
|
|
119
|
+
PULSE_PASS=a-strong-password
|
|
120
|
+
PULSE_SECRET=a-long-random-string
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
To create a random secret: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`
|
|
124
|
+
|
|
125
|
+
### Step 5: Open the dashboard
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
http://localhost:3000/monitor
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Sign in with `PULSE_USER` / `PULSE_PASS`. In production this is your API's own URL, for example `https://api.example.com/monitor`. Serve it over HTTPS.
|
|
132
|
+
|
|
133
|
+
### Rules to follow
|
|
134
|
+
|
|
135
|
+
1. Register `app.use(pulse)` **first**, at the application root, before any other middleware, especially before `compression()` (compression buffers the live updates).
|
|
136
|
+
2. Do **not** mount it under a sub-path: `app.use('/admin', pulse)` is not supported. To change the URL, use the `basePath` option instead:
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
serverPulse({ basePath: '/admin/monitor', auth: { username: '...', password: '...' } });
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
3. Call `serverPulse()` only once per process and reuse the returned `pulse` object.
|
|
143
|
+
|
|
144
|
+
### Update to a newer version
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm install @pulse-labs/server-pulse@latest # update
|
|
148
|
+
npm ls @pulse-labs/server-pulse # show the installed version
|
|
149
|
+
```
|
|
43
150
|
|
|
44
151
|
## PM2 cluster
|
|
45
152
|
|
package/dist/cli.cjs
CHANGED
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.2\",\n \"license\": \"MIT\",\n \"description\": \"Live server monitoring dashboard for Node.js apps, served from your own base URL.\",\n \"engines\": {\n \"node\": \">=18.15\"\n },\n \"type\": \"commonjs\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"bin\": {\n \"server-pulse\": \"dist/cli.cjs\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup && node scripts/copy-ui.mjs\",\n \"prepare\": \"npm run build\",\n \"prepublishOnly\": \"npm run lint && npm run typecheck && npm test\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint .\",\n \"format\": \"prettier --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"smoke\": \"node scripts/smoke-dist.mjs\",\n \"test:pm2\": \"vitest run test/integration/pm2.test.ts\",\n \"test:ui\": \"node test/ui/run.mjs\",\n \"bench\": \"node bench/overhead.mjs\"\n },\n \"peerDependencies\": {\n \"pm2\": \">=5\"\n },\n \"peerDependenciesMeta\": {\n \"pm2\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.5\",\n \"@types/express\": \"^5.0.6\",\n \"@types/node\": \"^20.19.43\",\n \"@types/supertest\": \"^7.2.1\",\n \"@vitest/coverage-v8\": \"^4.1.11\",\n \"eslint\": \"^9.39.5\",\n \"express4\": \"npm:express@^4.22.3\",\n \"express5\": \"npm:express@^5.3.0\",\n \"globals\": \"^17.13.0\",\n \"prettier\": \"^3.9.10\",\n \"supertest\": \"^7.3.1\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"~5.9.3\",\n \"typescript-eslint\": \"^8.71.2\",\n \"vite\": \"^6.4.4\",\n \"vitest\": \"^4.1.11\"\n },\n \"overrides\": {\n \"tsup\": {\n \"esbuild\": \"^0.28.2\",\n \"bundle-require\": {\n \"esbuild\": \"^0.28.2\"\n }\n }\n },\n \"keywords\": [\n \"monitoring\",\n \"dashboard\",\n \"express\",\n \"nestjs\",\n \"pm2\",\n \"metrics\",\n \"sse\"\n ]\n}\n","#!/usr/bin/env node\n// `server-pulse monitor [--port 9100] [--host 127.0.0.1]` — the PM2 monitor process (spec 11.4).\n// M0 scaffold: argument handling only; the monitor itself is implemented in M9.\nimport { version } from '../package.json';\n\nconst USAGE = `server-pulse ${version}\n\nUsage:\n server-pulse monitor [--port 9100] [--host 127.0.0.1]\n`;\n\nfunction main(argv: string[]): number {\n const [command] = argv;\n if (command === '--version' || command === '-v') {\n process.stdout.write(version + '\\n');\n return 0;\n }\n if (command === 'monitor') {\n process.stderr.write('server-pulse: the monitor command is not implemented yet.\\n');\n return 1;\n }\n process.stdout.write(USAGE);\n return command === undefined || command === '--help' || command === '-h' ? 0 : 1;\n}\n\nprocess.exitCode = main(process.argv.slice(2));\n"],"mappings":";;;;AAEE,cAAW;;;ACGb,IAAM,QAAQ,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAAA;AAMrC,SAAS,KAAK,MAAwB;AACpC,QAAM,CAAC,OAAO,IAAI;AAClB,MAAI,YAAY,eAAe,YAAY,MAAM;AAC/C,YAAQ,OAAO,MAAM,UAAU,IAAI;AACnC,WAAO;AAAA,EACT;AACA,MAAI,YAAY,WAAW;AACzB,YAAQ,OAAO,MAAM,6DAA6D;AAClF,WAAO;AAAA,EACT;AACA,UAAQ,OAAO,MAAM,KAAK;AAC1B,SAAO,YAAY,UAAa,YAAY,YAAY,YAAY,OAAO,IAAI;AACjF;AAEA,QAAQ,WAAW,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC;","names":[]}
|
package/dist/cli.mjs
CHANGED
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../package.json","../src/cli.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../package.json","../src/cli.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.2\",\n \"license\": \"MIT\",\n \"description\": \"Live server monitoring dashboard for Node.js apps, served from your own base URL.\",\n \"engines\": {\n \"node\": \">=18.15\"\n },\n \"type\": \"commonjs\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"bin\": {\n \"server-pulse\": \"dist/cli.cjs\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup && node scripts/copy-ui.mjs\",\n \"prepare\": \"npm run build\",\n \"prepublishOnly\": \"npm run lint && npm run typecheck && npm test\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint .\",\n \"format\": \"prettier --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"smoke\": \"node scripts/smoke-dist.mjs\",\n \"test:pm2\": \"vitest run test/integration/pm2.test.ts\",\n \"test:ui\": \"node test/ui/run.mjs\",\n \"bench\": \"node bench/overhead.mjs\"\n },\n \"peerDependencies\": {\n \"pm2\": \">=5\"\n },\n \"peerDependenciesMeta\": {\n \"pm2\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.5\",\n \"@types/express\": \"^5.0.6\",\n \"@types/node\": \"^20.19.43\",\n \"@types/supertest\": \"^7.2.1\",\n \"@vitest/coverage-v8\": \"^4.1.11\",\n \"eslint\": \"^9.39.5\",\n \"express4\": \"npm:express@^4.22.3\",\n \"express5\": \"npm:express@^5.3.0\",\n \"globals\": \"^17.13.0\",\n \"prettier\": \"^3.9.10\",\n \"supertest\": \"^7.3.1\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"~5.9.3\",\n \"typescript-eslint\": \"^8.71.2\",\n \"vite\": \"^6.4.4\",\n \"vitest\": \"^4.1.11\"\n },\n \"overrides\": {\n \"tsup\": {\n \"esbuild\": \"^0.28.2\",\n \"bundle-require\": {\n \"esbuild\": \"^0.28.2\"\n }\n }\n },\n \"keywords\": [\n \"monitoring\",\n \"dashboard\",\n \"express\",\n \"nestjs\",\n \"pm2\",\n \"metrics\",\n \"sse\"\n ]\n}\n","#!/usr/bin/env node\n// `server-pulse monitor [--port 9100] [--host 127.0.0.1]` — the PM2 monitor process (spec 11.4).\n// M0 scaffold: argument handling only; the monitor itself is implemented in M9.\nimport { version } from '../package.json';\n\nconst USAGE = `server-pulse ${version}\n\nUsage:\n server-pulse monitor [--port 9100] [--host 127.0.0.1]\n`;\n\nfunction main(argv: string[]): number {\n const [command] = argv;\n if (command === '--version' || command === '-v') {\n process.stdout.write(version + '\\n');\n return 0;\n }\n if (command === 'monitor') {\n process.stderr.write('server-pulse: the monitor command is not implemented yet.\\n');\n return 1;\n }\n process.stdout.write(USAGE);\n return command === undefined || command === '--help' || command === '-h' ? 0 : 1;\n}\n\nprocess.exitCode = main(process.argv.slice(2));\n"],"mappings":";;;;;;;;;;;;;;;;;;;AACA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAF9B;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAEE;AAFF;AAAA;AAEE,cAAW;AAAA;AAAA;;;ACFb;AAAA;AAAA;AAGA;AAEA,QAAM,QAAQ,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAAA;AAMrC,aAAS,KAAK,MAAwB;AACpC,YAAM,CAAC,OAAO,IAAI;AAClB,UAAI,YAAY,eAAe,YAAY,MAAM;AAC/C,gBAAQ,OAAO,MAAM,UAAU,IAAI;AACnC,eAAO;AAAA,MACT;AACA,UAAI,YAAY,WAAW;AACzB,gBAAQ,OAAO,MAAM,6DAA6D;AAClF,eAAO;AAAA,MACT;AACA,cAAQ,OAAO,MAAM,KAAK;AAC1B,aAAO,YAAY,UAAa,YAAY,YAAY,YAAY,OAAO,IAAI;AAAA,IACjF;AAEA,YAAQ,WAAW,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC;AAAA;AAAA;","names":[]}
|
package/dist/index.cjs
CHANGED
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../package.json"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport type { ServerPulseOptions, Thresholds } from './options';\nimport type { InitPayload, TickPayload } from './engine/payloads';\nimport { version } from '../package.json';\n\nexport interface ServerPulseMiddleware {\n (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void): void;\n /** Express error middleware that records the error, then calls next(err). */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n errorHandler(): (err: unknown, req: any, res: any, next: (err?: unknown) => void) => void;\n /** Record an error manually (e.g. from a NestJS exception filter). */\n captureError(err: unknown, req?: IncomingMessage): void;\n /** Current snapshot (same shape as the SSE init payload). For tests and scripts. */\n snapshot(): InitPayload;\n /** Stop timers, close SSE connections, disable event loop monitoring. */\n stop(): Promise<void>;\n /** Resolved mode: 'memory' | 'pm2' | 'disabled'. */\n readonly mode: 'memory' | 'pm2' | 'disabled';\n}\n\n// M0 scaffold: pass-through middleware. Collection, dashboard and PM2 mode arrive in later milestones.\nconst DEFAULT_THRESHOLDS: Thresholds = {\n cpuPercent: [70, 85],\n memoryPercent: [75, 90],\n diskPercent: [80, 90],\n heapPercent: [70, 85],\n eventLoopLagMs: [50, 100],\n errorRatePercent: [1, 3],\n};\n\nconst BUCKETS_WIRE = [5, 10, 25, 50, 75, 100, 150, 250, 350, 500, 750, 1000, 1500, 2500, 5000, 10000, 30000, null];\n\nexport function serverPulse(_options?: ServerPulseOptions): ServerPulseMiddleware {\n const startedAt = Date.now();\n\n const middleware = ((_req: IncomingMessage, _res: ServerResponse, next: (err?: unknown) => void) => {\n next();\n }) as ServerPulseMiddleware;\n\n middleware.errorHandler = () => (err, _req, _res, next) => next(err);\n middleware.captureError = () => {};\n middleware.snapshot = () => ({\n meta: {\n version,\n title: os.hostname(),\n host: os.hostname(),\n node: process.version,\n platform: process.platform,\n mode: 'memory',\n workers: 1,\n appStartedAt: Math.round(Date.now() - process.uptime() * 1000),\n monitorStartedAt: startedAt,\n cores: os.availableParallelism?.() ?? os.cpus().length,\n },\n config: {\n buckets: [...BUCKETS_WIRE],\n defaultTargetMs: 500,\n apdexThresholdMs: 300,\n thresholds: structuredClone(DEFAULT_THRESHOLDS),\n windowSeconds: 900,\n user: '',\n },\n totals: { requests: 0, since: startedAt },\n history: [],\n routes: [],\n workers: [],\n errors: [],\n });\n middleware.stop = async () => {};\n Object.defineProperty(middleware, 'mode', { value: 'disabled', enumerable: true });\n\n return middleware;\n}\n\nexport type { ServerPulseOptions, InitPayload, TickPayload };\n","{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../package.json"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport type { ServerPulseOptions, Thresholds } from './options';\nimport type { InitPayload, TickPayload } from './engine/payloads';\nimport { version } from '../package.json';\n\nexport interface ServerPulseMiddleware {\n (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void): void;\n /** Express error middleware that records the error, then calls next(err). */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n errorHandler(): (err: unknown, req: any, res: any, next: (err?: unknown) => void) => void;\n /** Record an error manually (e.g. from a NestJS exception filter). */\n captureError(err: unknown, req?: IncomingMessage): void;\n /** Current snapshot (same shape as the SSE init payload). For tests and scripts. */\n snapshot(): InitPayload;\n /** Stop timers, close SSE connections, disable event loop monitoring. */\n stop(): Promise<void>;\n /** Resolved mode: 'memory' | 'pm2' | 'disabled'. */\n readonly mode: 'memory' | 'pm2' | 'disabled';\n}\n\n// M0 scaffold: pass-through middleware. Collection, dashboard and PM2 mode arrive in later milestones.\nconst DEFAULT_THRESHOLDS: Thresholds = {\n cpuPercent: [70, 85],\n memoryPercent: [75, 90],\n diskPercent: [80, 90],\n heapPercent: [70, 85],\n eventLoopLagMs: [50, 100],\n errorRatePercent: [1, 3],\n};\n\nconst BUCKETS_WIRE = [5, 10, 25, 50, 75, 100, 150, 250, 350, 500, 750, 1000, 1500, 2500, 5000, 10000, 30000, null];\n\nexport function serverPulse(_options?: ServerPulseOptions): ServerPulseMiddleware {\n const startedAt = Date.now();\n\n const middleware = ((_req: IncomingMessage, _res: ServerResponse, next: (err?: unknown) => void) => {\n next();\n }) as ServerPulseMiddleware;\n\n middleware.errorHandler = () => (err, _req, _res, next) => next(err);\n middleware.captureError = () => {};\n middleware.snapshot = () => ({\n meta: {\n version,\n title: os.hostname(),\n host: os.hostname(),\n node: process.version,\n platform: process.platform,\n mode: 'memory',\n workers: 1,\n appStartedAt: Math.round(Date.now() - process.uptime() * 1000),\n monitorStartedAt: startedAt,\n cores: os.availableParallelism?.() ?? os.cpus().length,\n },\n config: {\n buckets: [...BUCKETS_WIRE],\n defaultTargetMs: 500,\n apdexThresholdMs: 300,\n thresholds: structuredClone(DEFAULT_THRESHOLDS),\n windowSeconds: 900,\n user: '',\n },\n totals: { requests: 0, since: startedAt },\n history: [],\n routes: [],\n workers: [],\n errors: [],\n });\n middleware.stop = async () => {};\n Object.defineProperty(middleware, 'mode', { value: 'disabled', enumerable: true });\n\n return middleware;\n}\n\nexport type { ServerPulseOptions, InitPayload, TickPayload };\n","{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.2\",\n \"license\": \"MIT\",\n \"description\": \"Live server monitoring dashboard for Node.js apps, served from your own base URL.\",\n \"engines\": {\n \"node\": \">=18.15\"\n },\n \"type\": \"commonjs\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"bin\": {\n \"server-pulse\": \"dist/cli.cjs\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup && node scripts/copy-ui.mjs\",\n \"prepare\": \"npm run build\",\n \"prepublishOnly\": \"npm run lint && npm run typecheck && npm test\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint .\",\n \"format\": \"prettier --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"smoke\": \"node scripts/smoke-dist.mjs\",\n \"test:pm2\": \"vitest run test/integration/pm2.test.ts\",\n \"test:ui\": \"node test/ui/run.mjs\",\n \"bench\": \"node bench/overhead.mjs\"\n },\n \"peerDependencies\": {\n \"pm2\": \">=5\"\n },\n \"peerDependenciesMeta\": {\n \"pm2\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.5\",\n \"@types/express\": \"^5.0.6\",\n \"@types/node\": \"^20.19.43\",\n \"@types/supertest\": \"^7.2.1\",\n \"@vitest/coverage-v8\": \"^4.1.11\",\n \"eslint\": \"^9.39.5\",\n \"express4\": \"npm:express@^4.22.3\",\n \"express5\": \"npm:express@^5.3.0\",\n \"globals\": \"^17.13.0\",\n \"prettier\": \"^3.9.10\",\n \"supertest\": \"^7.3.1\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"~5.9.3\",\n \"typescript-eslint\": \"^8.71.2\",\n \"vite\": \"^6.4.4\",\n \"vitest\": \"^4.1.11\"\n },\n \"overrides\": {\n \"tsup\": {\n \"esbuild\": \"^0.28.2\",\n \"bundle-require\": {\n \"esbuild\": \"^0.28.2\"\n }\n }\n },\n \"keywords\": [\n \"monitoring\",\n \"dashboard\",\n \"express\",\n \"nestjs\",\n \"pm2\",\n \"metrics\",\n \"sse\"\n ]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAAe;;;ACCb,cAAW;;;ADoBb,IAAM,qBAAiC;AAAA,EACrC,YAAY,CAAC,IAAI,EAAE;AAAA,EACnB,eAAe,CAAC,IAAI,EAAE;AAAA,EACtB,aAAa,CAAC,IAAI,EAAE;AAAA,EACpB,aAAa,CAAC,IAAI,EAAE;AAAA,EACpB,gBAAgB,CAAC,IAAI,GAAG;AAAA,EACxB,kBAAkB,CAAC,GAAG,CAAC;AACzB;AAEA,IAAM,eAAe,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAM,MAAM,MAAM,KAAM,KAAO,KAAO,IAAI;AAE1G,SAAS,YAAY,UAAsD;AAChF,QAAM,YAAY,KAAK,IAAI;AAE3B,QAAM,cAAc,CAAC,MAAuB,MAAsB,SAAkC;AAClG,SAAK;AAAA,EACP;AAEA,aAAW,eAAe,MAAM,CAAC,KAAK,MAAM,MAAM,SAAS,KAAK,GAAG;AACnE,aAAW,eAAe,MAAM;AAAA,EAAC;AACjC,aAAW,WAAW,OAAO;AAAA,IAC3B,MAAM;AAAA,MACJ;AAAA,MACA,OAAO,eAAAA,QAAG,SAAS;AAAA,MACnB,MAAM,eAAAA,QAAG,SAAS;AAAA,MAClB,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ;AAAA,MAClB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,QAAQ,OAAO,IAAI,GAAI;AAAA,MAC7D,kBAAkB;AAAA,MAClB,OAAO,eAAAA,QAAG,uBAAuB,KAAK,eAAAA,QAAG,KAAK,EAAE;AAAA,IAClD;AAAA,IACA,QAAQ;AAAA,MACN,SAAS,CAAC,GAAG,YAAY;AAAA,MACzB,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,MAClB,YAAY,gBAAgB,kBAAkB;AAAA,MAC9C,eAAe;AAAA,MACf,MAAM;AAAA,IACR;AAAA,IACA,QAAQ,EAAE,UAAU,GAAG,OAAO,UAAU;AAAA,IACxC,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,IACT,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACA,aAAW,OAAO,YAAY;AAAA,EAAC;AAC/B,SAAO,eAAe,YAAY,QAAQ,EAAE,OAAO,YAAY,YAAY,KAAK,CAAC;AAEjF,SAAO;AACT;","names":["os"]}
|
package/dist/index.mjs
CHANGED
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../package.json"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport type { ServerPulseOptions, Thresholds } from './options';\nimport type { InitPayload, TickPayload } from './engine/payloads';\nimport { version } from '../package.json';\n\nexport interface ServerPulseMiddleware {\n (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void): void;\n /** Express error middleware that records the error, then calls next(err). */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n errorHandler(): (err: unknown, req: any, res: any, next: (err?: unknown) => void) => void;\n /** Record an error manually (e.g. from a NestJS exception filter). */\n captureError(err: unknown, req?: IncomingMessage): void;\n /** Current snapshot (same shape as the SSE init payload). For tests and scripts. */\n snapshot(): InitPayload;\n /** Stop timers, close SSE connections, disable event loop monitoring. */\n stop(): Promise<void>;\n /** Resolved mode: 'memory' | 'pm2' | 'disabled'. */\n readonly mode: 'memory' | 'pm2' | 'disabled';\n}\n\n// M0 scaffold: pass-through middleware. Collection, dashboard and PM2 mode arrive in later milestones.\nconst DEFAULT_THRESHOLDS: Thresholds = {\n cpuPercent: [70, 85],\n memoryPercent: [75, 90],\n diskPercent: [80, 90],\n heapPercent: [70, 85],\n eventLoopLagMs: [50, 100],\n errorRatePercent: [1, 3],\n};\n\nconst BUCKETS_WIRE = [5, 10, 25, 50, 75, 100, 150, 250, 350, 500, 750, 1000, 1500, 2500, 5000, 10000, 30000, null];\n\nexport function serverPulse(_options?: ServerPulseOptions): ServerPulseMiddleware {\n const startedAt = Date.now();\n\n const middleware = ((_req: IncomingMessage, _res: ServerResponse, next: (err?: unknown) => void) => {\n next();\n }) as ServerPulseMiddleware;\n\n middleware.errorHandler = () => (err, _req, _res, next) => next(err);\n middleware.captureError = () => {};\n middleware.snapshot = () => ({\n meta: {\n version,\n title: os.hostname(),\n host: os.hostname(),\n node: process.version,\n platform: process.platform,\n mode: 'memory',\n workers: 1,\n appStartedAt: Math.round(Date.now() - process.uptime() * 1000),\n monitorStartedAt: startedAt,\n cores: os.availableParallelism?.() ?? os.cpus().length,\n },\n config: {\n buckets: [...BUCKETS_WIRE],\n defaultTargetMs: 500,\n apdexThresholdMs: 300,\n thresholds: structuredClone(DEFAULT_THRESHOLDS),\n windowSeconds: 900,\n user: '',\n },\n totals: { requests: 0, since: startedAt },\n history: [],\n routes: [],\n workers: [],\n errors: [],\n });\n middleware.stop = async () => {};\n Object.defineProperty(middleware, 'mode', { value: 'disabled', enumerable: true });\n\n return middleware;\n}\n\nexport type { ServerPulseOptions, InitPayload, TickPayload };\n","{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../package.json"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport os from 'node:os';\nimport type { ServerPulseOptions, Thresholds } from './options';\nimport type { InitPayload, TickPayload } from './engine/payloads';\nimport { version } from '../package.json';\n\nexport interface ServerPulseMiddleware {\n (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void): void;\n /** Express error middleware that records the error, then calls next(err). */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n errorHandler(): (err: unknown, req: any, res: any, next: (err?: unknown) => void) => void;\n /** Record an error manually (e.g. from a NestJS exception filter). */\n captureError(err: unknown, req?: IncomingMessage): void;\n /** Current snapshot (same shape as the SSE init payload). For tests and scripts. */\n snapshot(): InitPayload;\n /** Stop timers, close SSE connections, disable event loop monitoring. */\n stop(): Promise<void>;\n /** Resolved mode: 'memory' | 'pm2' | 'disabled'. */\n readonly mode: 'memory' | 'pm2' | 'disabled';\n}\n\n// M0 scaffold: pass-through middleware. Collection, dashboard and PM2 mode arrive in later milestones.\nconst DEFAULT_THRESHOLDS: Thresholds = {\n cpuPercent: [70, 85],\n memoryPercent: [75, 90],\n diskPercent: [80, 90],\n heapPercent: [70, 85],\n eventLoopLagMs: [50, 100],\n errorRatePercent: [1, 3],\n};\n\nconst BUCKETS_WIRE = [5, 10, 25, 50, 75, 100, 150, 250, 350, 500, 750, 1000, 1500, 2500, 5000, 10000, 30000, null];\n\nexport function serverPulse(_options?: ServerPulseOptions): ServerPulseMiddleware {\n const startedAt = Date.now();\n\n const middleware = ((_req: IncomingMessage, _res: ServerResponse, next: (err?: unknown) => void) => {\n next();\n }) as ServerPulseMiddleware;\n\n middleware.errorHandler = () => (err, _req, _res, next) => next(err);\n middleware.captureError = () => {};\n middleware.snapshot = () => ({\n meta: {\n version,\n title: os.hostname(),\n host: os.hostname(),\n node: process.version,\n platform: process.platform,\n mode: 'memory',\n workers: 1,\n appStartedAt: Math.round(Date.now() - process.uptime() * 1000),\n monitorStartedAt: startedAt,\n cores: os.availableParallelism?.() ?? os.cpus().length,\n },\n config: {\n buckets: [...BUCKETS_WIRE],\n defaultTargetMs: 500,\n apdexThresholdMs: 300,\n thresholds: structuredClone(DEFAULT_THRESHOLDS),\n windowSeconds: 900,\n user: '',\n },\n totals: { requests: 0, since: startedAt },\n history: [],\n routes: [],\n workers: [],\n errors: [],\n });\n middleware.stop = async () => {};\n Object.defineProperty(middleware, 'mode', { value: 'disabled', enumerable: true });\n\n return middleware;\n}\n\nexport type { ServerPulseOptions, InitPayload, TickPayload };\n","{\n \"name\": \"@pulse-labs/server-pulse\",\n \"version\": \"0.0.2\",\n \"license\": \"MIT\",\n \"description\": \"Live server monitoring dashboard for Node.js apps, served from your own base URL.\",\n \"engines\": {\n \"node\": \">=18.15\"\n },\n \"type\": \"commonjs\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.mts\",\n \"default\": \"./dist/index.mjs\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"bin\": {\n \"server-pulse\": \"dist/cli.cjs\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"CHANGELOG.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup && node scripts/copy-ui.mjs\",\n \"prepare\": \"npm run build\",\n \"prepublishOnly\": \"npm run lint && npm run typecheck && npm test\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint .\",\n \"format\": \"prettier --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"smoke\": \"node scripts/smoke-dist.mjs\",\n \"test:pm2\": \"vitest run test/integration/pm2.test.ts\",\n \"test:ui\": \"node test/ui/run.mjs\",\n \"bench\": \"node bench/overhead.mjs\"\n },\n \"peerDependencies\": {\n \"pm2\": \">=5\"\n },\n \"peerDependenciesMeta\": {\n \"pm2\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.5\",\n \"@types/express\": \"^5.0.6\",\n \"@types/node\": \"^20.19.43\",\n \"@types/supertest\": \"^7.2.1\",\n \"@vitest/coverage-v8\": \"^4.1.11\",\n \"eslint\": \"^9.39.5\",\n \"express4\": \"npm:express@^4.22.3\",\n \"express5\": \"npm:express@^5.3.0\",\n \"globals\": \"^17.13.0\",\n \"prettier\": \"^3.9.10\",\n \"supertest\": \"^7.3.1\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"~5.9.3\",\n \"typescript-eslint\": \"^8.71.2\",\n \"vite\": \"^6.4.4\",\n \"vitest\": \"^4.1.11\"\n },\n \"overrides\": {\n \"tsup\": {\n \"esbuild\": \"^0.28.2\",\n \"bundle-require\": {\n \"esbuild\": \"^0.28.2\"\n }\n }\n },\n \"keywords\": [\n \"monitoring\",\n \"dashboard\",\n \"express\",\n \"nestjs\",\n \"pm2\",\n \"metrics\",\n \"sse\"\n ]\n}\n"],"mappings":";AACA,OAAO,QAAQ;;;ACCb,cAAW;;;ADoBb,IAAM,qBAAiC;AAAA,EACrC,YAAY,CAAC,IAAI,EAAE;AAAA,EACnB,eAAe,CAAC,IAAI,EAAE;AAAA,EACtB,aAAa,CAAC,IAAI,EAAE;AAAA,EACpB,aAAa,CAAC,IAAI,EAAE;AAAA,EACpB,gBAAgB,CAAC,IAAI,GAAG;AAAA,EACxB,kBAAkB,CAAC,GAAG,CAAC;AACzB;AAEA,IAAM,eAAe,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAM,MAAM,MAAM,KAAM,KAAO,KAAO,IAAI;AAE1G,SAAS,YAAY,UAAsD;AAChF,QAAM,YAAY,KAAK,IAAI;AAE3B,QAAM,cAAc,CAAC,MAAuB,MAAsB,SAAkC;AAClG,SAAK;AAAA,EACP;AAEA,aAAW,eAAe,MAAM,CAAC,KAAK,MAAM,MAAM,SAAS,KAAK,GAAG;AACnE,aAAW,eAAe,MAAM;AAAA,EAAC;AACjC,aAAW,WAAW,OAAO;AAAA,IAC3B,MAAM;AAAA,MACJ;AAAA,MACA,OAAO,GAAG,SAAS;AAAA,MACnB,MAAM,GAAG,SAAS;AAAA,MAClB,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ;AAAA,MAClB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,QAAQ,OAAO,IAAI,GAAI;AAAA,MAC7D,kBAAkB;AAAA,MAClB,OAAO,GAAG,uBAAuB,KAAK,GAAG,KAAK,EAAE;AAAA,IAClD;AAAA,IACA,QAAQ;AAAA,MACN,SAAS,CAAC,GAAG,YAAY;AAAA,MACzB,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,MAClB,YAAY,gBAAgB,kBAAkB;AAAA,MAC9C,eAAe;AAAA,MACf,MAAM;AAAA,IACR;AAAA,IACA,QAAQ,EAAE,UAAU,GAAG,OAAO,UAAU;AAAA,IACxC,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,IACT,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AACA,aAAW,OAAO,YAAY;AAAA,EAAC;AAC/B,SAAO,eAAe,YAAY,QAAQ,EAAE,OAAO,YAAY,YAAY,KAAK,CAAC;AAEjF,SAAO;AACT;","names":[]}
|