@epic-js/express-profiler 0.1.0

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/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # express-profiler
2
+
3
+ Lightweight Express API profiler with route, middleware, DB, and external API timing.
4
+
5
+ ## Installation
6
+ ```bash
7
+ npm install express-profiler
8
+ ```
9
+
10
+ ## Usage
11
+ ```js
12
+ const express = require('express');
13
+ const expressProfiler = require('express-profiler');
14
+ const { wrapAsync } = require('express-profiler/wrappers');
15
+
16
+ const app = express();
17
+ app.use(expressProfiler());
18
+
19
+ app.get('/users', async (req, res) => {
20
+ const users = await wrapAsync(async () => [{ id: 1, name: 'Alice' }], 'DB', req)();
21
+ res.send(users);
22
+ });
23
+
24
+ app.listen(3000);
25
+ ```
26
+
27
+ ## CLI Usage
28
+ ```
29
+ express-profiler-cli logs.json
30
+ ```
package/cli.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+
4
+ const logs = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
5
+ logs.forEach(log => {
6
+ console.log(`${log.route} ${log.status} ${log.total.toFixed(1)}ms`);
7
+ Object.entries(log.timings).forEach(([k, v]) => console.log(` ${k}: ${v.toFixed(1)}ms`));
8
+ });
@@ -0,0 +1,45 @@
1
+ const express = require('express');
2
+ const expressProfiler = require('../index');
3
+ const { wrapAsync } = require('../wrappers');
4
+
5
+ const app = express();
6
+
7
+ // ----- Middleware example -----
8
+ app.use((req, res, next) => {
9
+ const start = Date.now();
10
+ // Simulate middleware work
11
+ setTimeout(() => {
12
+ if (req._profiler) req._profiler.timings['customMiddleware'] = Date.now() - start;
13
+ next();
14
+ }, 50);
15
+ });
16
+
17
+ // Attach profiler
18
+ app.use(expressProfiler());
19
+
20
+ // ----- Fast route -----
21
+ app.get('/users', async (req, res) => {
22
+ const users = await wrapAsync(async () => [{ id: 1, name: 'Alice' }], 'DB', req)();
23
+ res.send(users);
24
+ });
25
+
26
+ // ----- Slow route with multiple async tasks -----
27
+ app.get('/slow', async (req, res) => {
28
+ const dbTask = wrapAsync(() => new Promise(r => setTimeout(r, 300)), 'DB', req);
29
+ const apiTask = wrapAsync(() => new Promise(r => setTimeout(r, 200)), 'External API', req);
30
+
31
+ await dbTask();
32
+ await apiTask();
33
+ res.send('Slow route done');
34
+ });
35
+
36
+ // ----- Route with nested async -----
37
+ app.get('/nested', async (req, res) => {
38
+ await wrapAsync(async () => {
39
+ await wrapAsync(() => new Promise(r => setTimeout(r, 100)), 'Inner DB', req)();
40
+ }, 'Outer wrapper', req)();
41
+ res.send('Nested async done');
42
+ });
43
+
44
+ // ----- Start server -----
45
+ app.listen(3000, () => console.log('Server running on http://localhost:3000'));
package/index.js ADDED
@@ -0,0 +1,21 @@
1
+ const profiler = require('./profiler');
2
+
3
+ module.exports = function expressProfiler(options = {}) {
4
+ return function (req, res, next) {
5
+ const start = process.hrtime.bigint();
6
+
7
+ req._profiler = { timings: {} };
8
+
9
+ res.on('finish', () => {
10
+ const end = process.hrtime.bigint();
11
+ const totalMs = Number(end - start) / 1e6;
12
+ req._profiler.totalMs = totalMs;
13
+
14
+ if (options.log !== false) {
15
+ console.log(profiler.format(req));
16
+ }
17
+ });
18
+
19
+ next();
20
+ };
21
+ };
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@epic-js/express-profiler",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight Express API profiler with route/middleware/async timing",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "express-profiler-cli": "./cli.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node examples/express-app.js"
11
+ },
12
+ "keywords": [
13
+ "express",
14
+ "profiler",
15
+ "api",
16
+ "middleware",
17
+ "performance",
18
+ "express-profiler",
19
+ "epicprofiler",
20
+ "epic profiler"
21
+ ],
22
+ "author": "Rajgowthaman Rajendran",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "express": "^5.2.1"
26
+ }
27
+ }
package/profiler.js ADDED
@@ -0,0 +1,11 @@
1
+ function format(req) {
2
+ const route = req.method + ' ' + req.originalUrl;
3
+ const total = req._profiler.totalMs.toFixed(1);
4
+ const details = Object.entries(req._profiler.timings)
5
+ .map(([k, v]) => ` ${k}: ${v.toFixed(1)}ms`)
6
+ .join('\n');
7
+
8
+ return `${route} ${req.res.statusCode || 200} ${total}ms\n${details}`;
9
+ }
10
+
11
+ module.exports = { format };
package/wrappers.js ADDED
@@ -0,0 +1,16 @@
1
+ function wrapAsync(fn, label, req) {
2
+ return async (...args) => {
3
+ const start = process.hrtime.bigint();
4
+ const result = await fn(...args);
5
+ const end = process.hrtime.bigint();
6
+
7
+ if (req && req._profiler) {
8
+ const ms = Number(end - start) / 1e6;
9
+ req._profiler.timings[label] = ms;
10
+ }
11
+
12
+ return result;
13
+ };
14
+ }
15
+
16
+ module.exports = { wrapAsync };