@expressots/studio-agent 4.0.0-preview.1 → 4.0.0-preview.3

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.
Files changed (40) hide show
  1. package/README.md +143 -143
  2. package/dist/agent.d.ts +75 -0
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +443 -14
  5. package/dist/agent.js.map +1 -1
  6. package/dist/discovery/route-scanner.d.ts +62 -1
  7. package/dist/discovery/route-scanner.d.ts.map +1 -1
  8. package/dist/discovery/route-scanner.js +923 -101
  9. package/dist/discovery/route-scanner.js.map +1 -1
  10. package/dist/identity/index.d.ts +2 -0
  11. package/dist/identity/index.d.ts.map +1 -0
  12. package/dist/identity/index.js +2 -0
  13. package/dist/identity/index.js.map +1 -0
  14. package/dist/identity/install-id.d.ts +22 -0
  15. package/dist/identity/install-id.d.ts.map +1 -0
  16. package/dist/identity/install-id.js +73 -0
  17. package/dist/identity/install-id.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/instrumentation/tracer.d.ts.map +1 -1
  23. package/dist/instrumentation/tracer.js +40 -4
  24. package/dist/instrumentation/tracer.js.map +1 -1
  25. package/dist/introspection/database-introspector.d.ts +58 -0
  26. package/dist/introspection/database-introspector.d.ts.map +1 -0
  27. package/dist/introspection/database-introspector.js +351 -0
  28. package/dist/introspection/database-introspector.js.map +1 -0
  29. package/dist/logging/log-capture.d.ts.map +1 -1
  30. package/dist/logging/log-capture.js +23 -1
  31. package/dist/logging/log-capture.js.map +1 -1
  32. package/dist/recording/request-recorder.js +73 -73
  33. package/dist/security/posture-analyzer.d.ts.map +1 -1
  34. package/dist/security/posture-analyzer.js +1 -1
  35. package/dist/security/posture-analyzer.js.map +1 -1
  36. package/dist/types/index.d.ts +261 -2
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/types/index.js +2 -0
  39. package/dist/types/index.js.map +1 -1
  40. package/package.json +18 -15
package/README.md CHANGED
@@ -1,143 +1,143 @@
1
- # @expressots/studio-agent
2
-
3
- Instrumentation agent for ExpressoTS Studio - provides route discovery, OpenTelemetry tracing, and request recording.
4
-
5
- ## Features
6
-
7
- - **Route Discovery**: Automatically scans your ExpressoTS application to discover all routes, controllers, and services
8
- - **OpenTelemetry Tracing**: Full distributed tracing with automatic instrumentation
9
- - **Request Recording**: Record and replay HTTP requests for debugging
10
- - **WebSocket Communication**: Real-time updates to Studio UI
11
- - **Metrics Collection**: P50/P95/P99 latency, error rates, and more
12
-
13
- ## Installation
14
-
15
- ```bash
16
- npm install @expressots/studio-agent
17
- ```
18
-
19
- ## Quick Start
20
-
21
- ```typescript
22
- import { StudioAgent } from '@expressots/studio-agent';
23
-
24
- const agent = new StudioAgent({
25
- port: 3334,
26
- serviceName: 'my-app',
27
- enableRecording: true,
28
- });
29
-
30
- // Start the agent
31
- await agent.start();
32
-
33
- // Use the middleware (optional, for request recording)
34
- app.use(agent.createMiddleware());
35
-
36
- // Get discovered routes
37
- const routes = agent.getRoutes();
38
-
39
- // Stop when done
40
- await agent.stop();
41
- ```
42
-
43
- ## Configuration
44
-
45
- ```typescript
46
- interface AgentConfig {
47
- /** Port for the agent WebSocket server (default: 3334) */
48
- port: number;
49
-
50
- /** Path to store SQLite database (default: '.studio/studio.db') */
51
- dbPath: string;
52
-
53
- /** Enable request/response recording (default: true) */
54
- enableRecording: boolean;
55
-
56
- /** Maximum number of recorded exchanges to keep (default: 1000) */
57
- maxRecordedExchanges: number;
58
-
59
- /** Enable performance profiling (default: true) */
60
- enableProfiling: boolean;
61
-
62
- /** Sample rate for tracing 0-1 (default: 1.0) */
63
- traceSampleRate: number;
64
-
65
- /** Custom service name (default: 'expressots-app') */
66
- serviceName: string;
67
-
68
- /** Express app instance for runtime route scanning */
69
- expressApp?: any;
70
- }
71
- ```
72
-
73
- ## Components
74
-
75
- ### StudioAgent
76
-
77
- Main orchestrator that coordinates all functionality.
78
-
79
- ### RouteScanner
80
-
81
- Scans TypeScript source files to discover routes and their metadata:
82
-
83
- ```typescript
84
- import { RouteScanner } from '@expressots/studio-agent';
85
-
86
- const scanner = new RouteScanner('./src');
87
- const structure = await scanner.scan();
88
-
89
- console.log(structure.controllers);
90
- console.log(structure.services);
91
- console.log(structure.dependencies);
92
- ```
93
-
94
- ### RequestRecorder
95
-
96
- Records HTTP requests/responses for later replay:
97
-
98
- ```typescript
99
- import { RequestRecorder } from '@expressots/studio-agent';
100
-
101
- const recorder = new RequestRecorder('.studio/studio.db');
102
- await recorder.initialize();
103
-
104
- // Get recent exchanges
105
- const exchanges = recorder.getRecentExchanges(100);
106
-
107
- // Search by path
108
- const results = recorder.searchExchanges('/api/users', 'GET');
109
- ```
110
-
111
- ### StudioTracer
112
-
113
- OpenTelemetry tracer with custom span processing:
114
-
115
- ```typescript
116
- import { StudioTracer } from '@expressots/studio-agent';
117
-
118
- const tracer = new StudioTracer('my-service');
119
- await tracer.start((trace) => {
120
- console.log('Trace completed:', trace.traceId);
121
- });
122
-
123
- // Create custom spans
124
- await tracer.createSpan('my-operation', async () => {
125
- // Your code here
126
- }, { attribute: 'value' });
127
- ```
128
-
129
- ## WebSocket Events
130
-
131
- The agent emits real-time events to connected clients:
132
-
133
- | Event | Description |
134
- |-------|-------------|
135
- | `routes` | Discovered routes |
136
- | `trace` | Completed trace |
137
- | `request` | New request recorded |
138
- | `metrics` | Updated metrics |
139
- | `structure` | Application structure |
140
-
141
- ## License
142
-
143
- MIT © ExpressoTS
1
+ # @expressots/studio-agent
2
+
3
+ Instrumentation agent for ExpressoTS Studio - provides route discovery, OpenTelemetry tracing, and request recording.
4
+
5
+ ## Features
6
+
7
+ - **Route Discovery**: Automatically scans your ExpressoTS application to discover all routes, controllers, and services
8
+ - **OpenTelemetry Tracing**: Full distributed tracing with automatic instrumentation
9
+ - **Request Recording**: Record and replay HTTP requests for debugging
10
+ - **WebSocket Communication**: Real-time updates to Studio UI
11
+ - **Metrics Collection**: P50/P95/P99 latency, error rates, and more
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @expressots/studio-agent
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { StudioAgent } from '@expressots/studio-agent';
23
+
24
+ const agent = new StudioAgent({
25
+ port: 3334,
26
+ serviceName: 'my-app',
27
+ enableRecording: true,
28
+ });
29
+
30
+ // Start the agent
31
+ await agent.start();
32
+
33
+ // Use the middleware (optional, for request recording)
34
+ app.use(agent.createMiddleware());
35
+
36
+ // Get discovered routes
37
+ const routes = agent.getRoutes();
38
+
39
+ // Stop when done
40
+ await agent.stop();
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ ```typescript
46
+ interface AgentConfig {
47
+ /** Port for the agent WebSocket server (default: 3334) */
48
+ port: number;
49
+
50
+ /** Path to store SQLite database (default: '.studio/studio.db') */
51
+ dbPath: string;
52
+
53
+ /** Enable request/response recording (default: true) */
54
+ enableRecording: boolean;
55
+
56
+ /** Maximum number of recorded exchanges to keep (default: 1000) */
57
+ maxRecordedExchanges: number;
58
+
59
+ /** Enable performance profiling (default: true) */
60
+ enableProfiling: boolean;
61
+
62
+ /** Sample rate for tracing 0-1 (default: 1.0) */
63
+ traceSampleRate: number;
64
+
65
+ /** Custom service name (default: 'expressots-app') */
66
+ serviceName: string;
67
+
68
+ /** Express app instance for runtime route scanning */
69
+ expressApp?: any;
70
+ }
71
+ ```
72
+
73
+ ## Components
74
+
75
+ ### StudioAgent
76
+
77
+ Main orchestrator that coordinates all functionality.
78
+
79
+ ### RouteScanner
80
+
81
+ Scans TypeScript source files to discover routes and their metadata:
82
+
83
+ ```typescript
84
+ import { RouteScanner } from '@expressots/studio-agent';
85
+
86
+ const scanner = new RouteScanner('./src');
87
+ const structure = await scanner.scan();
88
+
89
+ console.log(structure.controllers);
90
+ console.log(structure.services);
91
+ console.log(structure.dependencies);
92
+ ```
93
+
94
+ ### RequestRecorder
95
+
96
+ Records HTTP requests/responses for later replay:
97
+
98
+ ```typescript
99
+ import { RequestRecorder } from '@expressots/studio-agent';
100
+
101
+ const recorder = new RequestRecorder('.studio/studio.db');
102
+ await recorder.initialize();
103
+
104
+ // Get recent exchanges
105
+ const exchanges = recorder.getRecentExchanges(100);
106
+
107
+ // Search by path
108
+ const results = recorder.searchExchanges('/api/users', 'GET');
109
+ ```
110
+
111
+ ### StudioTracer
112
+
113
+ OpenTelemetry tracer with custom span processing:
114
+
115
+ ```typescript
116
+ import { StudioTracer } from '@expressots/studio-agent';
117
+
118
+ const tracer = new StudioTracer('my-service');
119
+ await tracer.start((trace) => {
120
+ console.log('Trace completed:', trace.traceId);
121
+ });
122
+
123
+ // Create custom spans
124
+ await tracer.createSpan('my-operation', async () => {
125
+ // Your code here
126
+ }, { attribute: 'value' });
127
+ ```
128
+
129
+ ## WebSocket Events
130
+
131
+ The agent emits real-time events to connected clients:
132
+
133
+ | Event | Description |
134
+ |-------|-------------|
135
+ | `routes` | Discovered routes |
136
+ | `trace` | Completed trace |
137
+ | `request` | New request recorded |
138
+ | `metrics` | Updated metrics |
139
+ | `structure` | Application structure |
140
+
141
+ ## License
142
+
143
+ MIT © ExpressoTS
package/dist/agent.d.ts CHANGED
@@ -17,6 +17,7 @@ export declare class StudioAgent {
17
17
  private recorder;
18
18
  private introspector;
19
19
  private containerSnapshot;
20
+ private databaseIntrospector;
20
21
  private logCapture;
21
22
  private securityEngine;
22
23
  private io;
@@ -28,9 +29,24 @@ export declare class StudioAgent {
28
29
  private responseTimes;
29
30
  private startTime;
30
31
  private isRunning;
32
+ private srcWatcher;
33
+ private rescanTimer;
34
+ /**
35
+ * Periodic metrics-broadcast timer. Captured so `stop()` can clear it
36
+ * cleanly; `.unref()`'d so it never keeps the Node event loop alive in
37
+ * tests / serverless environments.
38
+ */
39
+ private metricsTimer;
31
40
  constructor(config?: Partial<AgentConfig>);
32
41
  /** Start the Studio Agent */
33
42
  start(): Promise<void>;
43
+ /**
44
+ * Start a debounced filesystem watcher over `./src` (relative to the
45
+ * host's CWD) that triggers a route + structure rescan whenever a
46
+ * `*.ts` / `*.js` file changes. Uses `fs.watch({ recursive: true })`
47
+ * to avoid taking a chokidar dependency. Failures are non-fatal.
48
+ */
49
+ private startSrcWatcher;
34
50
  /**
35
51
  * Stand up the SecurityEngine and kick off the first scan. The
36
52
  * engine reuses the existing Socket.IO server — every transition in
@@ -40,6 +56,12 @@ export declare class StudioAgent {
40
56
  private startSecurityEngine;
41
57
  /** Get the captured container snapshot (or null if unavailable). */
42
58
  getContainerSnapshot(): ContainerSnapshot | null;
59
+ /**
60
+ * Capture a fresh in-memory database snapshot. Returns an "unavailable"
61
+ * snapshot when no `InMemoryDBProvider` is registered or no container was
62
+ * provided to the agent.
63
+ */
64
+ private captureDatabaseSnapshot;
43
65
  /** Stop the Studio Agent */
44
66
  stop(): Promise<void>;
45
67
  /**
@@ -56,6 +78,25 @@ export declare class StudioAgent {
56
78
  scanRoutes(): Promise<void>;
57
79
  /** Get discovered routes */
58
80
  getRoutes(): RouteInfo[];
81
+ /**
82
+ * Normalise the host-supplied global URL prefix into the form we
83
+ * actually want to splice into route paths.
84
+ *
85
+ * - Returns `''` for "no prefix" (so callers can fall through with a
86
+ * simple truthy check).
87
+ * - Strips trailing slashes (`/api/` → `/api`) so the join helper
88
+ * never produces `/api//foo`.
89
+ * - Defends against the host passing through a legitimate but
90
+ * no-op `'/'` prefix.
91
+ */
92
+ private normaliseGlobalPrefix;
93
+ /**
94
+ * Splice a normalised global prefix onto a controller-relative route
95
+ * path while preserving the leading slash and avoiding doubled
96
+ * separators. `/api` + `/` → `/api/`, `/api` + `users` → `/api/users`,
97
+ * `/api` + `/users` → `/api/users`.
98
+ */
99
+ private joinPrefixWithRoute;
59
100
  /** Get application structure */
60
101
  getAppStructure(): AppStructure | null;
61
102
  /** Get current metrics */
@@ -79,7 +120,41 @@ export declare class StudioAgent {
79
120
  providerCount?: number;
80
121
  middlewareCount?: number;
81
122
  runtimeItems?: import('./types/index.js').RuntimeItems;
123
+ middlewarePreset?: import('./types/index.js').MiddlewarePresetInfo;
82
124
  }): void;
125
+ /**
126
+ * Recompute every route's `path` from its captured `originalPath` plus
127
+ * the current `config.globalPrefix`. Idempotent and prefix-change-safe
128
+ * — calling it twice with different prefixes never produces the
129
+ * `/api/api/health` doubling we'd see if we appended in place.
130
+ *
131
+ * Routes pushed by older code paths that don't carry an `originalPath`
132
+ * (defensive — hot-reload scans always set it now) are left alone, so
133
+ * we never silently strip a prefix the source of truth set
134
+ * intentionally.
135
+ */
136
+ private applyGlobalPrefixToRoutes;
137
+ /**
138
+ * Merge global pipeline middleware and runtime middleware bindings
139
+ * into the static `appStructure` so the architecture map sees a
140
+ * single source of truth. Returns `true` when the structure changed.
141
+ *
142
+ * Rules:
143
+ * - Each `runtimeItems.middleware` entry whose `type === 'custom'`
144
+ * gets a `MiddlewareInfo` node with `scope: 'global'` (built-in
145
+ * pipeline entries like `helmet` / `jsonParser` aren't worth
146
+ * plotting — they would clutter every architecture map without
147
+ * adding signal). Names are deduplicated against the existing
148
+ * middleware list.
149
+ * - Each `runtimeItems.middlewareBindings` entry contributes a
150
+ * `middleware → controller` edge (deduplicated with the static
151
+ * bindings produced by `RouteScanner`). The middleware node's
152
+ * scope is upgraded to `controller` or `route`.
153
+ * - Global middleware also gets synthetic edges to every
154
+ * controller in the structure so the map shows the pipeline
155
+ * fanning out across the app.
156
+ */
157
+ private mergeRuntimeMiddlewareIntoStructure;
83
158
  /**
84
159
  * Build a snapshot of runtime information for the Status dashboard.
85
160
  *
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAKrE,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EAET,YAAY,EACZ,UAAU,EACV,aAAa,EAGb,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAgE1B,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,EAAE,CAA+B;IACzC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,SAAS,CAAkB;gBAEvB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IA2C7C,6BAA6B;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD5B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IA2B3B,oEAAoE;IACpE,oBAAoB,IAAI,iBAAiB,GAAG,IAAI;IAIhD,4BAA4B;IACtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA6B3B;;;;;;;;OAQG;YACW,uBAAuB;IAyCrC,kCAAkC;IAC5B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BjC,4BAA4B;IAC5B,SAAS,IAAI,SAAS,EAAE;IAIxB,gCAAgC;IAChC,eAAe,IAAI,YAAY,GAAG,IAAI;IAItC,0BAA0B;IAC1B,UAAU,IAAI,UAAU;IAQxB,iEAAiE;IACjE,gBAAgB,IAAI,aAAa,EAAE;IAInC;;;;;;;;OAQG;IACH,iBAAiB,CAAC,KAAK,EAAE;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,YAAY,CAAC,EAAE,OAAO,kBAAkB,EAAE,YAAY,CAAC;KACxD,GAAG,IAAI;IA0BR;;;;;;;;;;OAUG;IACH,cAAc,IAAI,WAAW;IAgE7B,6BAA6B;YACf,oBAAoB;IA+RlC;;;;;;;;;;OAUG;YACW,eAAe;IA2B7B,oEAAoE;IACpE,OAAO,CAAC,UAAU;IAgBlB,4BAA4B;IAC5B,OAAO,CAAC,WAAW;IAkCnB,iCAAiC;IACjC,OAAO,CAAC,mBAAmB;IA6D3B,gCAAgC;YAClB,aAAa;IAqF3B,iDAAiD;IACjD,OAAO,CAAC,SAAS;IAMjB,+BAA+B;IAC/B,OAAO,CAAC,aAAa;IAQrB,wCAAwC;IACxC,OAAO,CAAC,sBAAsB;IAwB9B,+DAA+D;IAC/D,gBAAgB,KACN,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG;CA+JxC;AAED,YAAY,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}