reflexive 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/CLAUDE.md +77 -0
- package/FAILURES.md +245 -0
- package/README.md +264 -0
- package/Screenshot 2026-01-22 at 6.31.27/342/200/257AM.png +0 -0
- package/dashboard.html +620 -0
- package/demo-ai-features.js +571 -0
- package/demo-app.js +210 -0
- package/demo-inject.js +212 -0
- package/demo-instrumented.js +272 -0
- package/docs/BREAKPOINT-AUDIT.md +293 -0
- package/docs/GENESIS.md +110 -0
- package/docs/HN-LAUNCH-PLAN-V2.md +631 -0
- package/docs/HN-LAUNCH-PLAN.md +492 -0
- package/docs/TODO.md +69 -0
- package/docs/V8-INSPECTOR-RESEARCH.md +1231 -0
- package/logo-carbon.png +0 -0
- package/logo0.jpg +0 -0
- package/logo1.jpg +0 -0
- package/logo2.jpg +0 -0
- package/new-ui-template.html +435 -0
- package/one-shot.js +1109 -0
- package/package.json +47 -0
- package/play-story.sh +10 -0
- package/src/demo-inject.js +3 -0
- package/src/inject.cjs +474 -0
- package/src/reflexive.js +6214 -0
- package/story-game-reflexive.js +1246 -0
- package/story-game-web.js +1030 -0
- package/story-mystery-1769171430377.js +162 -0
package/demo-app.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import http from 'http';
|
|
2
|
+
|
|
3
|
+
const PORT = 8080;
|
|
4
|
+
let requestCount = 0;
|
|
5
|
+
const visitors = new Map();
|
|
6
|
+
let dbConnected = true;
|
|
7
|
+
let authFailures = 0;
|
|
8
|
+
|
|
9
|
+
const server = http.createServer((req, res) => {
|
|
10
|
+
requestCount++;
|
|
11
|
+
const timestamp = new Date().toISOString();
|
|
12
|
+
|
|
13
|
+
console.log(`[${timestamp}] ${req.method} ${req.url}`);
|
|
14
|
+
|
|
15
|
+
// Track visitors by IP
|
|
16
|
+
const ip = req.socket.remoteAddress;
|
|
17
|
+
visitors.set(ip, (visitors.get(ip) || 0) + 1);
|
|
18
|
+
|
|
19
|
+
if (req.url === '/') {
|
|
20
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
21
|
+
res.end(`
|
|
22
|
+
<h1>Demo App</h1>
|
|
23
|
+
<p>Request #${requestCount}</p>
|
|
24
|
+
<h3>Basic Endpoints</h3>
|
|
25
|
+
<ul>
|
|
26
|
+
<li><a href="/status">/status</a> - Server stats</li>
|
|
27
|
+
<li><a href="/slow">/slow</a> - Slow endpoint (2s delay)</li>
|
|
28
|
+
<li><a href="/error">/error</a> - Throws an error</li>
|
|
29
|
+
<li><a href="/memory">/memory</a> - Memory usage</li>
|
|
30
|
+
</ul>
|
|
31
|
+
<h3>Watch Trigger Demos</h3>
|
|
32
|
+
<ul>
|
|
33
|
+
<li><a href="/login?user=admin&pass=wrong">/login</a> - Auth failure (try wrong password)</li>
|
|
34
|
+
<li><a href="/login?user=admin&pass=secret">/login</a> - Auth success</li>
|
|
35
|
+
<li><a href="/db-query">/db-query</a> - Simulated DB query (may fail randomly)</li>
|
|
36
|
+
<li><a href="/api/users">/api/users</a> - API endpoint with rate limiting</li>
|
|
37
|
+
<li><a href="/webhook">/webhook</a> - Incoming webhook simulation</li>
|
|
38
|
+
<li><a href="/toggle-db">/toggle-db</a> - Toggle DB connection state</li>
|
|
39
|
+
</ul>
|
|
40
|
+
`);
|
|
41
|
+
}
|
|
42
|
+
else if (req.url === '/status') {
|
|
43
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
44
|
+
res.end(JSON.stringify({
|
|
45
|
+
uptime: process.uptime(),
|
|
46
|
+
requests: requestCount,
|
|
47
|
+
visitors: visitors.size,
|
|
48
|
+
pid: process.pid
|
|
49
|
+
}, null, 2));
|
|
50
|
+
}
|
|
51
|
+
else if (req.url === '/slow') {
|
|
52
|
+
console.log('Starting slow operation...');
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
console.log('Slow operation complete');
|
|
55
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
56
|
+
res.end('Done after 2 seconds');
|
|
57
|
+
}, 2000);
|
|
58
|
+
}
|
|
59
|
+
else if (req.url === '/error') {
|
|
60
|
+
console.error('About to throw an error!');
|
|
61
|
+
throw new Error('Intentional error for testing');
|
|
62
|
+
}
|
|
63
|
+
else if (req.url === '/memory') {
|
|
64
|
+
const mem = process.memoryUsage();
|
|
65
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
66
|
+
res.end(JSON.stringify({
|
|
67
|
+
heapUsed: `${Math.round(mem.heapUsed / 1024 / 1024)}MB`,
|
|
68
|
+
heapTotal: `${Math.round(mem.heapTotal / 1024 / 1024)}MB`,
|
|
69
|
+
rss: `${Math.round(mem.rss / 1024 / 1024)}MB`
|
|
70
|
+
}, null, 2));
|
|
71
|
+
}
|
|
72
|
+
// ============ Watch Trigger Demo Endpoints ============
|
|
73
|
+
else if (req.url.startsWith('/login')) {
|
|
74
|
+
const params = new URL(req.url, `http://localhost:${PORT}`).searchParams;
|
|
75
|
+
const user = params.get('user') || 'unknown';
|
|
76
|
+
const pass = params.get('pass') || '';
|
|
77
|
+
|
|
78
|
+
if (pass === 'secret') {
|
|
79
|
+
console.log(`[AUTH] ✓ Login successful for user: ${user}`);
|
|
80
|
+
authFailures = 0;
|
|
81
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
82
|
+
res.end(JSON.stringify({ success: true, user, message: 'Welcome!' }));
|
|
83
|
+
} else {
|
|
84
|
+
authFailures++;
|
|
85
|
+
console.error(`[AUTH] ✗ Login FAILED for user: ${user} (attempt #${authFailures})`);
|
|
86
|
+
if (authFailures >= 3) {
|
|
87
|
+
console.error(`[AUTH] ⚠️ SECURITY WARNING: Multiple failed login attempts for user: ${user}`);
|
|
88
|
+
}
|
|
89
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
90
|
+
res.end(JSON.stringify({ success: false, error: 'Invalid credentials' }));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (req.url === '/db-query') {
|
|
94
|
+
if (!dbConnected) {
|
|
95
|
+
console.error('[DATABASE] ✗ Connection failed: Database is not connected');
|
|
96
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
97
|
+
res.end(JSON.stringify({ error: 'Database unavailable' }));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Simulate random query performance
|
|
101
|
+
const queryTime = Math.random() * 500;
|
|
102
|
+
if (queryTime > 400) {
|
|
103
|
+
console.warn(`[DATABASE] ⚠️ Slow query detected: ${queryTime.toFixed(0)}ms`);
|
|
104
|
+
}
|
|
105
|
+
if (Math.random() < 0.2) {
|
|
106
|
+
console.error('[DATABASE] ✗ Query failed: Deadlock detected');
|
|
107
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
108
|
+
res.end(JSON.stringify({ error: 'Query failed - deadlock' }));
|
|
109
|
+
} else {
|
|
110
|
+
console.log(`[DATABASE] ✓ Query completed in ${queryTime.toFixed(0)}ms`);
|
|
111
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
112
|
+
res.end(JSON.stringify({ success: true, rows: Math.floor(Math.random() * 100), queryTime: queryTime.toFixed(0) + 'ms' }));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (req.url.startsWith('/api/')) {
|
|
116
|
+
const visitorCount = visitors.get(ip) || 0;
|
|
117
|
+
if (visitorCount > 10) {
|
|
118
|
+
console.warn(`[RATE_LIMIT] ⚠️ Rate limit exceeded for IP: ${ip} (${visitorCount} requests)`);
|
|
119
|
+
res.writeHead(429, { 'Content-Type': 'application/json' });
|
|
120
|
+
res.end(JSON.stringify({ error: 'Too many requests', retryAfter: 60 }));
|
|
121
|
+
} else {
|
|
122
|
+
console.log(`[API] Request from ${ip} to ${req.url}`);
|
|
123
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
124
|
+
res.end(JSON.stringify({ users: ['alice', 'bob', 'charlie'] }));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else if (req.url === '/webhook') {
|
|
128
|
+
const eventType = ['payment.success', 'payment.failed', 'user.created', 'subscription.hacked'][Math.floor(Math.random() * 4)];
|
|
129
|
+
console.log(`[WEBHOOK] Received event: ${eventType}`);
|
|
130
|
+
if (eventType === 'payment.failed') {
|
|
131
|
+
console.error(`[WEBHOOK] ⚠️ Payment failure webhook received - needs attention!`);
|
|
132
|
+
}
|
|
133
|
+
if (eventType === 'subscription.hacked') {
|
|
134
|
+
console.warn(`[WEBHOOK] Security alert: subscription hacked`);
|
|
135
|
+
}
|
|
136
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
137
|
+
res.end(JSON.stringify({ received: true, event: eventType }));
|
|
138
|
+
}
|
|
139
|
+
else if (req.url === '/toggle-db') {
|
|
140
|
+
dbConnected = !dbConnected;
|
|
141
|
+
if (dbConnected) {
|
|
142
|
+
console.log('[DATABASE] ✓ Connection restored');
|
|
143
|
+
} else {
|
|
144
|
+
console.error('[DATABASE] ✗ Connection lost!');
|
|
145
|
+
}
|
|
146
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
147
|
+
res.end(JSON.stringify({ dbConnected }));
|
|
148
|
+
}
|
|
149
|
+
// ============ End Watch Trigger Demo Endpoints ============
|
|
150
|
+
else if (req.url.startsWith('/foo/')) {
|
|
151
|
+
const bar = req.url.slice(5); // Extract everything after '/foo/'
|
|
152
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
153
|
+
res.end(JSON.stringify({
|
|
154
|
+
path: req.url,
|
|
155
|
+
bar: bar
|
|
156
|
+
}, null, 2));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
160
|
+
res.end('Not Found');
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
server.listen(PORT, () => {
|
|
165
|
+
console.log(`
|
|
166
|
+
╔═══════════════════════════════════════════════════════════════════════════════╗
|
|
167
|
+
║ REFLEXIVE DEMO APP ║
|
|
168
|
+
╠═══════════════════════════════════════════════════════════════════════════════╣
|
|
169
|
+
║ Server running at http://localhost:${PORT} ║
|
|
170
|
+
║ PID: ${process.pid} ║
|
|
171
|
+
╠═══════════════════════════════════════════════════════════════════════════════╣
|
|
172
|
+
║ HOW TO USE THIS DEMO: ║
|
|
173
|
+
║ ║
|
|
174
|
+
║ 1. Run with Reflexive: npm run demo:app ║
|
|
175
|
+
║ 2. Open dashboard: http://localhost:3100 ║
|
|
176
|
+
║ 3. Try the Watch Triggers feature: ║
|
|
177
|
+
║ - Click 👁 on any log entry to create a watch ║
|
|
178
|
+
║ - Set a pattern like "Login FAILED" or "Deadlock" ║
|
|
179
|
+
║ - Add a prompt like "Investigate this error" ║
|
|
180
|
+
║ - The agent auto-responds when matching logs appear! ║
|
|
181
|
+
║ ║
|
|
182
|
+
║ DEMO ENDPOINTS (visit in browser or curl): ║
|
|
183
|
+
║ ║
|
|
184
|
+
║ Auth Demo: ║
|
|
185
|
+
║ /login?user=admin&pass=wrong → Triggers auth failure logs ║
|
|
186
|
+
║ /login?user=admin&pass=secret → Successful login ║
|
|
187
|
+
║ (3+ failures triggers SECURITY WARNING) ║
|
|
188
|
+
║ ║
|
|
189
|
+
║ Database Demo: ║
|
|
190
|
+
║ /db-query → Random success/slow/deadlock ║
|
|
191
|
+
║ /toggle-db → Simulate DB connection loss ║
|
|
192
|
+
║ ║
|
|
193
|
+
║ Other: ║
|
|
194
|
+
║ /api/users → Rate limiting (10+ requests = warning) ║
|
|
195
|
+
║ /webhook → Random webhook events (payment failures, churn) ║
|
|
196
|
+
║ ║
|
|
197
|
+
║ SUGGESTED WATCH PATTERNS: ║
|
|
198
|
+
║ "Login FAILED" → "Investigate why authentication is failing" ║
|
|
199
|
+
║ "Slow query" → "Check what's causing database slowness" ║
|
|
200
|
+
║ "Deadlock" → "Analyze the deadlock and suggest a fix" ║
|
|
201
|
+
║ "payment.failed" → "Alert! Check the payment processing system" ║
|
|
202
|
+
║ "SECURITY WARNING" → "Potential brute force - suggest mitigations" ║
|
|
203
|
+
╚═══════════════════════════════════════════════════════════════════════════════╝
|
|
204
|
+
`);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Log something periodically
|
|
208
|
+
setInterval(() => {
|
|
209
|
+
console.log(`[heartbeat] ${requestCount} requests served, ${visitors.size} unique visitors`);
|
|
210
|
+
}, 10000);
|
package/demo-inject.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo app to test --inject and --eval features
|
|
3
|
+
*
|
|
4
|
+
* Run with injection only:
|
|
5
|
+
* reflexive --inject demo-inject.js
|
|
6
|
+
*
|
|
7
|
+
* Run with eval enabled:
|
|
8
|
+
* reflexive --eval demo-inject.js
|
|
9
|
+
*
|
|
10
|
+
* Then try in the dashboard:
|
|
11
|
+
* - "What's in the config object?"
|
|
12
|
+
* - "How many users are there?"
|
|
13
|
+
* - "Call addUser with name 'Alice'"
|
|
14
|
+
* - "Clear the cache"
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import http from 'http';
|
|
18
|
+
import https from 'https';
|
|
19
|
+
|
|
20
|
+
// === Expose some globals for eval testing ===
|
|
21
|
+
global.config = {
|
|
22
|
+
port: 4567,
|
|
23
|
+
env: 'development',
|
|
24
|
+
debug: true,
|
|
25
|
+
maxConnections: 100
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
global.users = new Map([
|
|
29
|
+
[1, { id: 1, name: 'Demo User', role: 'admin' }],
|
|
30
|
+
[2, { id: 2, name: 'Test User', role: 'user' }]
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
global.cache = {
|
|
34
|
+
data: new Map(),
|
|
35
|
+
set(key, value) { this.data.set(key, value); },
|
|
36
|
+
get(key) { return this.data.get(key); },
|
|
37
|
+
clear() { this.data.clear(); console.log('Cache cleared'); },
|
|
38
|
+
size() { return this.data.size; }
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
global.addUser = (name, role = 'user') => {
|
|
42
|
+
const id = global.users.size + 1;
|
|
43
|
+
const user = { id, name, role };
|
|
44
|
+
global.users.set(id, user);
|
|
45
|
+
console.log(`Added user: ${JSON.stringify(user)}`);
|
|
46
|
+
return user;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
global.getStats = () => ({
|
|
50
|
+
users: global.users.size,
|
|
51
|
+
cacheSize: global.cache.size(),
|
|
52
|
+
uptime: process.uptime(),
|
|
53
|
+
memory: Math.round(process.memoryUsage().heapUsed / 1024 / 1024) + 'MB'
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// === Console interception (automatic) ===
|
|
57
|
+
console.log('App starting up...');
|
|
58
|
+
console.info('This is an info message');
|
|
59
|
+
console.warn('This is a warning');
|
|
60
|
+
console.error('This is an error (not a real error, just testing)');
|
|
61
|
+
console.debug('Debug info here');
|
|
62
|
+
|
|
63
|
+
// === HTTP Server (automatic tracking via diagnostics_channel) ===
|
|
64
|
+
const server = http.createServer((req, res) => {
|
|
65
|
+
console.log(`Incoming request: ${req.method} ${req.url}`);
|
|
66
|
+
|
|
67
|
+
// Simulate some work
|
|
68
|
+
const start = Date.now();
|
|
69
|
+
let sum = 0;
|
|
70
|
+
for (let i = 0; i < 1000000; i++) sum += i;
|
|
71
|
+
|
|
72
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
73
|
+
res.end(JSON.stringify({
|
|
74
|
+
status: 'ok',
|
|
75
|
+
path: req.url,
|
|
76
|
+
processingTime: Date.now() - start
|
|
77
|
+
}));
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
server.listen(4567, () => {
|
|
81
|
+
console.log(`
|
|
82
|
+
╔═══════════════════════════════════════════════════════════════════════════════╗
|
|
83
|
+
║ REFLEXIVE INJECTION MODE DEMO ║
|
|
84
|
+
║ (Deep Instrumentation via --inject) ║
|
|
85
|
+
╠═══════════════════════════════════════════════════════════════════════════════╣
|
|
86
|
+
║ Server: http://localhost:4567 ║
|
|
87
|
+
║ PID: ${String(process.pid).padEnd(73)}║
|
|
88
|
+
╠═══════════════════════════════════════════════════════════════════════════════╣
|
|
89
|
+
║ HOW TO RUN THIS DEMO: ║
|
|
90
|
+
║ ║
|
|
91
|
+
║ Injection only (console capture, diagnostics): ║
|
|
92
|
+
║ npm run demo:inject ║
|
|
93
|
+
║ (or: node src/reflexive.js --inject demo-inject.js) ║
|
|
94
|
+
║ ║
|
|
95
|
+
║ With eval enabled (run code in app context): ║
|
|
96
|
+
║ npm run demo:eval ║
|
|
97
|
+
║ (or: node src/reflexive.js --eval demo-inject.js) ║
|
|
98
|
+
║ ║
|
|
99
|
+
║ KEY FEATURES DEMONSTRATED: ║
|
|
100
|
+
║ • Console interception (all log levels captured) ║
|
|
101
|
+
║ • HTTP diagnostics via diagnostics_channel ║
|
|
102
|
+
║ • GC and event loop metrics via perf_hooks ║
|
|
103
|
+
║ • process.reflexive API for custom state ║
|
|
104
|
+
║ • Breakpoints (pause/resume execution) ║
|
|
105
|
+
║ • Remote eval (with --eval flag) ║
|
|
106
|
+
║ ║
|
|
107
|
+
║ GLOBAL VARIABLES (for --eval testing): ║
|
|
108
|
+
║ config → App configuration object ║
|
|
109
|
+
║ users → Map of user data ║
|
|
110
|
+
║ cache → Simple cache with get/set/clear ║
|
|
111
|
+
║ addUser() → Function to add new users ║
|
|
112
|
+
║ getStats()→ Function to get app statistics ║
|
|
113
|
+
║ ║
|
|
114
|
+
║ TRY WITH --inject: ║
|
|
115
|
+
║ "Show me the injection logs" ║
|
|
116
|
+
║ "What HTTP requests have been made?" ║
|
|
117
|
+
║ "Are there any GC events?" ║
|
|
118
|
+
║ ║
|
|
119
|
+
║ TRY WITH --eval: ║
|
|
120
|
+
║ "What's in the config object?" ║
|
|
121
|
+
║ "How many users are there?" ║
|
|
122
|
+
║ "Call addUser with name 'Alice'" ║
|
|
123
|
+
║ "Clear the cache" ║
|
|
124
|
+
║ "What are the current stats?" ║
|
|
125
|
+
║ ║
|
|
126
|
+
║ WATCH TRIGGER IDEAS: ║
|
|
127
|
+
║ "External request failed" → "Investigate the HTTP error" ║
|
|
128
|
+
║ "memory pressure" → "Analyze memory usage patterns" ║
|
|
129
|
+
║ "event loop" → "Check for performance issues" ║
|
|
130
|
+
╚═══════════════════════════════════════════════════════════════════════════════╝
|
|
131
|
+
`);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// === HTTP Client requests (automatic tracking) ===
|
|
135
|
+
function makeExternalRequest() {
|
|
136
|
+
console.log('Making external HTTP request...');
|
|
137
|
+
|
|
138
|
+
https.get('https://httpbin.org/get', (res) => {
|
|
139
|
+
console.log(`External request status: ${res.statusCode}`);
|
|
140
|
+
res.on('data', () => {}); // consume the data
|
|
141
|
+
}).on('error', (err) => {
|
|
142
|
+
console.error(`External request failed: ${err.message}`);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Make a request every 30 seconds
|
|
147
|
+
setTimeout(makeExternalRequest, 2000);
|
|
148
|
+
setInterval(makeExternalRequest, 30000);
|
|
149
|
+
|
|
150
|
+
// === Memory pressure (triggers GC) ===
|
|
151
|
+
function createMemoryPressure() {
|
|
152
|
+
console.log('Creating memory pressure to trigger GC...');
|
|
153
|
+
let arrays = [];
|
|
154
|
+
for (let i = 0; i < 100; i++) {
|
|
155
|
+
arrays.push(new Array(100000).fill(Math.random()));
|
|
156
|
+
}
|
|
157
|
+
// Let it get collected
|
|
158
|
+
arrays = null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Trigger GC periodically
|
|
162
|
+
setTimeout(createMemoryPressure, 5000);
|
|
163
|
+
setInterval(createMemoryPressure, 20000);
|
|
164
|
+
|
|
165
|
+
// === Event loop blocking (shows in event loop metrics) ===
|
|
166
|
+
function blockEventLoop() {
|
|
167
|
+
console.log('Blocking event loop briefly...');
|
|
168
|
+
const start = Date.now();
|
|
169
|
+
while (Date.now() - start < 100) {
|
|
170
|
+
// Busy wait for 100ms
|
|
171
|
+
}
|
|
172
|
+
console.log('Event loop unblocked');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
setTimeout(blockEventLoop, 8000);
|
|
176
|
+
|
|
177
|
+
// === Simulate an uncaught exception (after 60 seconds) ===
|
|
178
|
+
// Uncomment to test error capture:
|
|
179
|
+
// setTimeout(() => {
|
|
180
|
+
// throw new Error('Intentional uncaught exception for testing');
|
|
181
|
+
// }, 60000);
|
|
182
|
+
|
|
183
|
+
// === Bonus: Use process.reflexive if available ===
|
|
184
|
+
if (process.reflexive) {
|
|
185
|
+
console.log('Reflexive injection detected! Setting custom state...');
|
|
186
|
+
|
|
187
|
+
process.reflexive.setState('app.name', 'demo-inject');
|
|
188
|
+
process.reflexive.setState('app.version', '1.0.0');
|
|
189
|
+
process.reflexive.setState('user', { name: 'Alice', age: 30, email: 'alice@example.com' });
|
|
190
|
+
|
|
191
|
+
// Update request count
|
|
192
|
+
let requestCount = 0;
|
|
193
|
+
const originalEmit = server.emit.bind(server);
|
|
194
|
+
server.emit = function(event, ...args) {
|
|
195
|
+
if (event === 'request') {
|
|
196
|
+
requestCount++;
|
|
197
|
+
process.reflexive.setState('requests.total', requestCount);
|
|
198
|
+
}
|
|
199
|
+
return originalEmit(event, ...args);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Periodic state updates
|
|
203
|
+
setInterval(() => {
|
|
204
|
+
const mem = process.memoryUsage();
|
|
205
|
+
process.reflexive.setState('memory', {
|
|
206
|
+
heapUsed: Math.round(mem.heapUsed / 1024 / 1024),
|
|
207
|
+
heapTotal: Math.round(mem.heapTotal / 1024 / 1024)
|
|
208
|
+
});
|
|
209
|
+
}, 5000);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
console.log('Demo app ready! Make HTTP requests: curl http://localhost:4567/test');
|