@lensmcp/bridge 1.18.2 → 1.18.4
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/index.d.ts +1 -1
- package/index.js +1 -0
- package/lib/constants.d.ts +0 -1
- package/lib/env-sink.d.ts +0 -1
- package/lib/event-mappers.d.ts +18 -1
- package/lib/event-mappers.js +153 -23
- package/lib/redact.d.ts +89 -0
- package/lib/redact.js +215 -0
- package/lib/server.d.ts +0 -1
- package/lib/types.d.ts +38 -4
- package/main.d.ts +0 -1
- package/package.json +3 -3
- package/index.d.ts.map +0 -1
- package/lib/constants.d.ts.map +0 -1
- package/lib/env-sink.d.ts.map +0 -1
- package/lib/event-mappers.d.ts.map +0 -1
- package/lib/server.d.ts.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/main.d.ts.map +0 -1
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createBridgeServer, makePublisher, handleClientEnvelope, findFreePort, type BridgeServer, type BridgeServerOptions, type BridgeDeps, } from './lib/server.js';
|
|
2
2
|
export { envelopeToEvent } from './lib/event-mappers.js';
|
|
3
|
+
export { redactUrl, redactText, redactDeep, isSecretParam, clip, safeText, safeTitle, REDACTED, MAX_TITLE_CHARS, MAX_MESSAGE_CHARS, MAX_URL_CHARS, } from './lib/redact.js';
|
|
3
4
|
export { resolveEnvSink, resetEnvSinkCache, udsEnvSink } from './lib/env-sink.js';
|
|
4
5
|
export { DEFAULT_WS_HOST, DEFAULT_WS_PORT, ENV_WS_HOST, ENV_WS_PORT, ENV_SESSION_ID, } from './lib/constants.js';
|
|
5
6
|
export type { ClientEnvelope, EnvSink } from './lib/types.js';
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { createBridgeServer, makePublisher, handleClientEnvelope, findFreePort, } from './lib/server.js';
|
|
2
2
|
export { envelopeToEvent } from './lib/event-mappers.js';
|
|
3
|
+
export { redactUrl, redactText, redactDeep, isSecretParam, clip, safeText, safeTitle, REDACTED, MAX_TITLE_CHARS, MAX_MESSAGE_CHARS, MAX_URL_CHARS, } from './lib/redact.js';
|
|
3
4
|
export { resolveEnvSink, resetEnvSinkCache, udsEnvSink } from './lib/env-sink.js';
|
|
4
5
|
export { DEFAULT_WS_HOST, DEFAULT_WS_PORT, ENV_WS_HOST, ENV_WS_PORT, ENV_SESSION_ID, } from './lib/constants.js';
|
package/lib/constants.d.ts
CHANGED
|
@@ -22,4 +22,3 @@ export declare const ENV_WS_HOST = "LENSMCP_WS_HOST";
|
|
|
22
22
|
export declare const ENV_WS_PORT = "LENSMCP_WS_PORT";
|
|
23
23
|
/** Env var: session id stamped onto every event the bridge publishes. */
|
|
24
24
|
export declare const ENV_SESSION_ID = "LENSMCP_SESSION_ID";
|
|
25
|
-
//# sourceMappingURL=constants.d.ts.map
|
package/lib/env-sink.d.ts
CHANGED
|
@@ -4,4 +4,3 @@ export declare function resolveEnvSink(): EnvSink | null;
|
|
|
4
4
|
export declare function resetEnvSinkCache(): void;
|
|
5
5
|
/** Reconnecting NDJSON client over a Unix domain socket (see session/uds.ts). */
|
|
6
6
|
export declare function udsEnvSink(path: string): EnvSink;
|
|
7
|
-
//# sourceMappingURL=env-sink.d.ts.map
|
package/lib/event-mappers.d.ts
CHANGED
|
@@ -5,6 +5,23 @@ import type { ClientEnvelope } from './types.js';
|
|
|
5
5
|
* `BaseEvent` consumed by the LensMCP event bus. The bridge publishes
|
|
6
6
|
* these; reducers in `@lensmcp/<app>` materialise them into
|
|
7
7
|
* `runtime://browser/*` resources.
|
|
8
|
+
*
|
|
9
|
+
* ── Substance is the point ──────────────────────────────────────────────────
|
|
10
|
+
* This mapper decides what a reader of `runtime://browser/errors` can actually
|
|
11
|
+
* learn. Measured on foodguard (2026-07-30) an entry looked like:
|
|
12
|
+
*
|
|
13
|
+
* { id, timestamp, severity: 'error', source: 'client-runtime',
|
|
14
|
+
* fingerprint: 'runtime:52331dbd', tabId: 'tab-gal0r3bs',
|
|
15
|
+
* raw: { kind: 'error', at: 1785450203325, tabId: 'tab-gal0r3bs' } }
|
|
16
|
+
*
|
|
17
|
+
* — no message, no stack, no URL, no status. The resource could report that
|
|
18
|
+
* two errors happened and nothing whatsoever about what they were. A signal
|
|
19
|
+
* that is correct but undiagnosable is only half a signal, so every branch
|
|
20
|
+
* below now carries identity: a title that names the failure, a bounded
|
|
21
|
+
* message/stack, and for a request its method, URL and STATUS.
|
|
22
|
+
*
|
|
23
|
+
* Every string that reaches `title`/`message` is redacted and bounded first
|
|
24
|
+
* (`./redact.js`) — enrichment is exactly what creates the leak risk, so the
|
|
25
|
+
* two land together. See that module for what is and is not scrubbed.
|
|
8
26
|
*/
|
|
9
27
|
export declare function envelopeToEvent(env: ClientEnvelope, sessionId?: string): BaseEvent;
|
|
10
|
-
//# sourceMappingURL=event-mappers.d.ts.map
|
package/lib/event-mappers.js
CHANGED
|
@@ -1,16 +1,48 @@
|
|
|
1
1
|
import { fingerprint, ulid } from '@lensmcp/core';
|
|
2
|
+
import { redactDeep, redactText, redactUrl, safeText, safeTitle } from './redact.js';
|
|
2
3
|
const SESSION_ID_PLACEHOLDER = 'pending';
|
|
3
4
|
/**
|
|
4
5
|
* Translate a single client-runtime envelope into the normalised
|
|
5
6
|
* `BaseEvent` consumed by the LensMCP event bus. The bridge publishes
|
|
6
7
|
* these; reducers in `@lensmcp/<app>` materialise them into
|
|
7
8
|
* `runtime://browser/*` resources.
|
|
9
|
+
*
|
|
10
|
+
* ── Substance is the point ──────────────────────────────────────────────────
|
|
11
|
+
* This mapper decides what a reader of `runtime://browser/errors` can actually
|
|
12
|
+
* learn. Measured on foodguard (2026-07-30) an entry looked like:
|
|
13
|
+
*
|
|
14
|
+
* { id, timestamp, severity: 'error', source: 'client-runtime',
|
|
15
|
+
* fingerprint: 'runtime:52331dbd', tabId: 'tab-gal0r3bs',
|
|
16
|
+
* raw: { kind: 'error', at: 1785450203325, tabId: 'tab-gal0r3bs' } }
|
|
17
|
+
*
|
|
18
|
+
* — no message, no stack, no URL, no status. The resource could report that
|
|
19
|
+
* two errors happened and nothing whatsoever about what they were. A signal
|
|
20
|
+
* that is correct but undiagnosable is only half a signal, so every branch
|
|
21
|
+
* below now carries identity: a title that names the failure, a bounded
|
|
22
|
+
* message/stack, and for a request its method, URL and STATUS.
|
|
23
|
+
*
|
|
24
|
+
* Every string that reaches `title`/`message` is redacted and bounded first
|
|
25
|
+
* (`./redact.js`) — enrichment is exactly what creates the leak risk, so the
|
|
26
|
+
* two land together. See that module for what is and is not scrubbed.
|
|
8
27
|
*/
|
|
9
28
|
export function envelopeToEvent(env, sessionId = SESSION_ID_PLACEHOLDER) {
|
|
10
29
|
// Per-tab identity stamped by the client runtime — keys browser://tabs.
|
|
11
30
|
const tab = env.tabId ? { tabId: env.tabId } : {};
|
|
12
31
|
switch (env.kind) {
|
|
13
|
-
case 'error':
|
|
32
|
+
case 'error': {
|
|
33
|
+
// A cross-origin script yields the opaque "Script error." with no stack
|
|
34
|
+
// and no file. Saying so is more use than a bare message, because the
|
|
35
|
+
// fix is a `crossorigin` attribute rather than anything in the app.
|
|
36
|
+
const opaque = !env.stack && !env.source && (!env.message || env.message === 'Script error.');
|
|
37
|
+
const name = env.name && env.name !== 'Error' ? `${env.name}: ` : '';
|
|
38
|
+
// Opaque FIRST: the browser's own "Script error." is a message, but a
|
|
39
|
+
// useless one — naming the cause points at the actual fix (a
|
|
40
|
+
// `crossorigin` attribute on the script tag), which the raw string does not.
|
|
41
|
+
const title = opaque
|
|
42
|
+
? 'Uncaught cross-origin script error (no detail available — add crossorigin to the script tag)'
|
|
43
|
+
: env.message
|
|
44
|
+
? `${name}${env.message}`
|
|
45
|
+
: `Uncaught ${env.name ?? 'error'}`;
|
|
14
46
|
return {
|
|
15
47
|
id: ulid(),
|
|
16
48
|
sessionId,
|
|
@@ -23,16 +55,51 @@ export function envelopeToEvent(env, sessionId = SESSION_ID_PLACEHOLDER) {
|
|
|
23
55
|
kind: 'runtime',
|
|
24
56
|
identity: `error:${normaliseStackTopFrame(env.stack)}`,
|
|
25
57
|
file: env.source,
|
|
26
|
-
|
|
58
|
+
// The message is the discriminator between two errors thrown from
|
|
59
|
+
// the same frame. Without it every anonymous error collapsed into
|
|
60
|
+
// one fingerprint, so a count of them meant nothing.
|
|
61
|
+
detail: env.message ?? env.name,
|
|
27
62
|
}),
|
|
28
|
-
title:
|
|
29
|
-
message: env.stack ?? env.message,
|
|
63
|
+
title: safeTitle(title),
|
|
64
|
+
message: safeText(env.stack ?? env.message),
|
|
30
65
|
location: env.source
|
|
31
|
-
? { file: env.source, line: env.lineno, column: env.colno }
|
|
66
|
+
? { file: redactUrl(env.source), line: env.lineno, column: env.colno }
|
|
32
67
|
: undefined,
|
|
33
|
-
raw
|
|
68
|
+
// `raw` is read too — redact it as thoroughly as the rendered fields,
|
|
69
|
+
// or the credential just moves one key deeper.
|
|
70
|
+
raw: {
|
|
71
|
+
...env,
|
|
72
|
+
...(env.message ? { message: redactText(env.message) } : {}),
|
|
73
|
+
...(env.stack ? { stack: safeText(env.stack) } : {}),
|
|
74
|
+
...(env.source ? { source: redactUrl(env.source) } : {}),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
case 'resource-error': {
|
|
79
|
+
const url = env.url ? redactUrl(env.url) : undefined;
|
|
80
|
+
return {
|
|
81
|
+
id: ulid(),
|
|
82
|
+
sessionId,
|
|
83
|
+
timestamp: env.at,
|
|
84
|
+
source: 'client-runtime',
|
|
85
|
+
category: 'runtime',
|
|
86
|
+
severity: 'error',
|
|
87
|
+
context: { sessionId, ...tab },
|
|
88
|
+
fingerprint: fingerprint({
|
|
89
|
+
kind: 'runtime',
|
|
90
|
+
// Path-normalised so a cache-busted asset does not mint a new
|
|
91
|
+
// fingerprint on every reload, while two different failing assets
|
|
92
|
+
// stay distinct.
|
|
93
|
+
identity: `resource-error:${env.tagName}:${normaliseUrl(env.url ?? '')}`,
|
|
94
|
+
}),
|
|
95
|
+
title: safeTitle(`Failed to load <${env.tagName}>${url ? ` ${url}` : ''}`),
|
|
96
|
+
...(url ? { relatedUrls: [url] } : {}),
|
|
97
|
+
raw: { ...env, ...(url ? { url } : {}) },
|
|
34
98
|
};
|
|
35
|
-
|
|
99
|
+
}
|
|
100
|
+
case 'unhandledrejection': {
|
|
101
|
+
const name = env.name && env.name !== 'Error' ? `${env.name}: ` : '';
|
|
102
|
+
const summary = env.reason.split('\n')[0] ?? env.reason;
|
|
36
103
|
return {
|
|
37
104
|
id: ulid(),
|
|
38
105
|
sessionId,
|
|
@@ -45,13 +112,27 @@ export function envelopeToEvent(env, sessionId = SESSION_ID_PLACEHOLDER) {
|
|
|
45
112
|
kind: 'runtime',
|
|
46
113
|
identity: `unhandledrejection:${env.reason.slice(0, 80)}`,
|
|
47
114
|
}),
|
|
48
|
-
title
|
|
49
|
-
|
|
50
|
-
|
|
115
|
+
// The reason belongs in the title. "Unhandled promise rejection" on
|
|
116
|
+
// its own is a category, not a finding — a reader had to open `raw` to
|
|
117
|
+
// learn anything, and the status-line summary showed only the category.
|
|
118
|
+
title: safeTitle(`Unhandled promise rejection: ${name}${summary}`),
|
|
119
|
+
message: safeText(env.stack ?? env.reason),
|
|
120
|
+
raw: {
|
|
121
|
+
...env,
|
|
122
|
+
reason: redactText(env.reason),
|
|
123
|
+
...(env.stack ? { stack: safeText(env.stack) } : {}),
|
|
124
|
+
},
|
|
51
125
|
};
|
|
126
|
+
}
|
|
52
127
|
case 'console': {
|
|
53
128
|
const severity = env.level === 'error' ? 'error' : env.level === 'warn' ? 'warning' : 'info';
|
|
54
|
-
|
|
129
|
+
// Redact the args FIRST, then join. Joining first and scrubbing the
|
|
130
|
+
// result only catches credential SHAPES (a JWT, a `Bearer …`) — it
|
|
131
|
+
// cannot know that a key literally named `apiKey` holds one, so
|
|
132
|
+
// `console.log({ apiKey })` leaked into `message` while `raw.args` was
|
|
133
|
+
// correctly redacted. Redacting at the structured end catches both.
|
|
134
|
+
const args = redactDeep(env.args);
|
|
135
|
+
const text = args.map(stringify).join(' ');
|
|
55
136
|
return {
|
|
56
137
|
id: ulid(),
|
|
57
138
|
sessionId,
|
|
@@ -65,12 +146,18 @@ export function envelopeToEvent(env, sessionId = SESSION_ID_PLACEHOLDER) {
|
|
|
65
146
|
identity: `console:${env.level}:${text.slice(0, 80)}`,
|
|
66
147
|
}),
|
|
67
148
|
title: `console.${env.level}`,
|
|
68
|
-
message: text,
|
|
69
|
-
|
|
149
|
+
message: safeText(text),
|
|
150
|
+
// Console args are the one genuinely unstructured captured payload —
|
|
151
|
+
// `console.log('auth', { token })` is ordinary debugging code.
|
|
152
|
+
raw: { ...env, args },
|
|
70
153
|
};
|
|
71
154
|
}
|
|
72
155
|
case 'fetch': {
|
|
73
156
|
const failed = env.error !== undefined || (env.status !== undefined && env.status >= 400);
|
|
157
|
+
const url = redactUrl(env.url);
|
|
158
|
+
const status = env.status !== undefined
|
|
159
|
+
? ` → ${env.status}${env.statusText ? ` ${env.statusText}` : ''}`
|
|
160
|
+
: '';
|
|
74
161
|
return {
|
|
75
162
|
id: ulid(),
|
|
76
163
|
sessionId,
|
|
@@ -83,10 +170,10 @@ export function envelopeToEvent(env, sessionId = SESSION_ID_PLACEHOLDER) {
|
|
|
83
170
|
kind: 'network',
|
|
84
171
|
identity: `${env.method}:${normaliseUrl(env.url)}:${env.status ?? 'err'}`,
|
|
85
172
|
}),
|
|
86
|
-
title: `${env.method} ${
|
|
87
|
-
message: env.error,
|
|
88
|
-
relatedUrls: [
|
|
89
|
-
raw: env,
|
|
173
|
+
title: safeTitle(`${env.method} ${url}${status}`),
|
|
174
|
+
message: safeText(env.error),
|
|
175
|
+
relatedUrls: [url],
|
|
176
|
+
raw: { ...env, url },
|
|
90
177
|
};
|
|
91
178
|
}
|
|
92
179
|
case 'route':
|
|
@@ -116,27 +203,70 @@ export function envelopeToEvent(env, sessionId = SESSION_ID_PLACEHOLDER) {
|
|
|
116
203
|
message: env.userAgent,
|
|
117
204
|
raw: env,
|
|
118
205
|
};
|
|
119
|
-
case 'publish':
|
|
206
|
+
case 'publish': {
|
|
120
207
|
// Pre-formed publish envelope from in-page instrumentation. Trust
|
|
121
208
|
// its source/category (the producer is our own injected code); the
|
|
122
209
|
// reducers gate on those, and the context carries the flow id so
|
|
123
210
|
// React renders correlate with the originating user action.
|
|
211
|
+
const net = networkDetails(env.category, env.raw);
|
|
212
|
+
// A FAILED REQUEST IS AN ERROR, wherever it was published from.
|
|
213
|
+
//
|
|
214
|
+
// `flow-fetch` classified every non-ok response as `warning`, so a 4xx
|
|
215
|
+
// or 5xx never reached `runtime://browser/failed-requests` (the runtime
|
|
216
|
+
// reducer routes only `severity === 'error'` there). On foodguard that
|
|
217
|
+
// silently hid 116 real failures — 98×401, 10×503, 8×502. Normalising
|
|
218
|
+
// here rather than only at the publisher means the invariant holds for
|
|
219
|
+
// any producer, including an app pinned to an older instrumentation
|
|
220
|
+
// build.
|
|
221
|
+
const severity = net && net.status !== undefined && net.status >= 400
|
|
222
|
+
? 'error'
|
|
223
|
+
: (env.severity ?? 'info');
|
|
224
|
+
// The publisher embedded the un-redacted URL in its own title AND its
|
|
225
|
+
// own fingerprint (flow-fetch builds both from the raw URL); swap in the
|
|
226
|
+
// redacted form rather than dropping either. The substitution is
|
|
227
|
+
// deterministic, so the fingerprint stays a stable dedupe key.
|
|
228
|
+
const scrub = (s) => net && net.url !== net.redactedUrl ? s.split(net.url).join(net.redactedUrl) : s;
|
|
229
|
+
const title = scrub(env.title);
|
|
124
230
|
return {
|
|
125
231
|
id: ulid(),
|
|
126
232
|
sessionId,
|
|
127
233
|
timestamp: env.at,
|
|
128
234
|
source: env.source,
|
|
129
235
|
category: env.category,
|
|
130
|
-
severity
|
|
236
|
+
severity,
|
|
131
237
|
context: { sessionId, ...tab, ...(env.context ?? {}) },
|
|
132
|
-
fingerprint: env.fingerprint
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
238
|
+
fingerprint: env.fingerprint
|
|
239
|
+
? scrub(env.fingerprint)
|
|
240
|
+
: fingerprint({ kind: 'publish', identity: title }),
|
|
241
|
+
title: safeTitle(title),
|
|
242
|
+
message: safeText(env.message),
|
|
243
|
+
...(net ? { relatedUrls: [net.redactedUrl] } : {}),
|
|
244
|
+
raw: net
|
|
245
|
+
? { ...redactDeep(env.raw), url: net.redactedUrl }
|
|
246
|
+
: redactDeep(env.raw),
|
|
136
247
|
};
|
|
248
|
+
}
|
|
137
249
|
}
|
|
138
250
|
}
|
|
139
251
|
// --- helpers ---
|
|
252
|
+
/**
|
|
253
|
+
* Pull `{ url, status }` off a network `publish` envelope's `raw` (the shape
|
|
254
|
+
* `flow-fetch` emits: `fetch-start` / `fetch-done` / `fetch-error`). Returns
|
|
255
|
+
* undefined for anything that is not a network publish carrying a URL, so
|
|
256
|
+
* every other publish passes through untouched.
|
|
257
|
+
*/
|
|
258
|
+
function networkDetails(category, raw) {
|
|
259
|
+
if (category !== 'network' || !raw || typeof raw !== 'object')
|
|
260
|
+
return undefined;
|
|
261
|
+
const r = raw;
|
|
262
|
+
if (typeof r.url !== 'string' || r.url.length === 0)
|
|
263
|
+
return undefined;
|
|
264
|
+
return {
|
|
265
|
+
url: r.url,
|
|
266
|
+
redactedUrl: redactUrl(r.url),
|
|
267
|
+
...(typeof r.status === 'number' ? { status: r.status } : {}),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
140
270
|
function normaliseStackTopFrame(stack) {
|
|
141
271
|
if (!stack)
|
|
142
272
|
return 'unknown';
|
package/lib/redact.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redaction + bounding for browser-originated event text.
|
|
3
|
+
*
|
|
4
|
+
* ── Why this exists ─────────────────────────────────────────────────────────
|
|
5
|
+
* Until now the browser taps recorded almost nothing about an error, so there
|
|
6
|
+
* was nothing to leak. Enriching them (message, stack, method/URL/status)
|
|
7
|
+
* changes that: a request URL routinely carries a credential in its query
|
|
8
|
+
* string (`?access_token=…`, `?code=…` on an OAuth callback, `?key=…` on a
|
|
9
|
+
* Google API), and an error message can quote a JWT or an `Authorization`
|
|
10
|
+
* header. Those values then land in `runtime://browser/*`, which an agent
|
|
11
|
+
* reads and may quote into a transcript.
|
|
12
|
+
*
|
|
13
|
+
* So enrichment and redaction ship together, in the same place. This module is
|
|
14
|
+
* applied in `envelopeToEvent` — the ONE function every browser envelope
|
|
15
|
+
* crosses on its way to the bus — rather than at each tap, so a tap cannot
|
|
16
|
+
* forget it and a hand-rolled client cannot bypass it.
|
|
17
|
+
*
|
|
18
|
+
* `nx.json` has carried a `redaction: { headers, paths }` block since the init
|
|
19
|
+
* generator was written, with no reader anywhere in the repo. This is the
|
|
20
|
+
* first code to honour that intent; the lists below are a superset of it.
|
|
21
|
+
*
|
|
22
|
+
* ── Deliberately NOT done here ──────────────────────────────────────────────
|
|
23
|
+
* • Request/response HEADERS are never captured in the first place (the taps
|
|
24
|
+
* read none), which is the strongest possible defence — nothing to redact.
|
|
25
|
+
* Keep it that way; do not add header capture without extending this module.
|
|
26
|
+
* • Request/response BODIES are likewise never captured.
|
|
27
|
+
* • Free text is scrubbed for credential SHAPES (JWT, `Bearer …`), not parsed
|
|
28
|
+
* for arbitrary URLs. A URL embedded in a stack frame keeps its query
|
|
29
|
+
* string. Widening that means running the URL redactor over every message,
|
|
30
|
+
* which is a cost/false-positive trade not worth making blind.
|
|
31
|
+
*/
|
|
32
|
+
/** Replacement for a redacted value. Short, obvious, greppable. */
|
|
33
|
+
export declare const REDACTED = "REDACTED";
|
|
34
|
+
/**
|
|
35
|
+
* Bounds. `raw` is structurally clamped to 32KiB by the bus transform
|
|
36
|
+
* (`createEventClamp`, wired in `@lensmcp/session`), but `title`/`message` are
|
|
37
|
+
* NOT — they are plain strings on `BaseEvent` and reach every reader
|
|
38
|
+
* unclamped. A stack from a deep React tree is routinely tens of KB, so these
|
|
39
|
+
* are the bounds that actually keep an event small.
|
|
40
|
+
*/
|
|
41
|
+
export declare const MAX_TITLE_CHARS = 300;
|
|
42
|
+
export declare const MAX_MESSAGE_CHARS = 4096;
|
|
43
|
+
export declare const MAX_URL_CHARS = 1024;
|
|
44
|
+
/** Is this query-parameter name carrying a credential? */
|
|
45
|
+
export declare function isSecretParam(name: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Strip credentials from a URL, preserving every other byte.
|
|
48
|
+
*
|
|
49
|
+
* Implemented as a regex rewrite rather than `new URL(...)` on purpose:
|
|
50
|
+
* `URL` re-encodes as it round-trips (`+` vs `%20`, dropped default ports,
|
|
51
|
+
* sorted-looking output), which would mean the URL an agent reads is not the
|
|
52
|
+
* URL the app requested. It also throws on relative inputs, which is most of
|
|
53
|
+
* what a SPA fetches. This keeps the string byte-identical apart from the
|
|
54
|
+
* redacted values, and never throws.
|
|
55
|
+
*
|
|
56
|
+
* Redacts, in order: userinfo, then any query OR fragment parameter whose name
|
|
57
|
+
* looks like a credential. The fragment matters — an OAuth implicit-flow
|
|
58
|
+
* callback puts the access token there (`#access_token=…`).
|
|
59
|
+
*/
|
|
60
|
+
export declare function redactUrl(url: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Scrub credential SHAPES out of free text (an error message, a stack, a
|
|
63
|
+
* console line). Cheap, linear, and tuned for precision over recall — a false
|
|
64
|
+
* positive destroys the diagnostic value this whole change is adding.
|
|
65
|
+
*/
|
|
66
|
+
export declare function redactText(text: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Bound a string, marking what was removed. Marker text matches
|
|
69
|
+
* `@lensmcp/storage`'s `clampEventRaw` so the two truncations read the same in
|
|
70
|
+
* a transcript.
|
|
71
|
+
*/
|
|
72
|
+
export declare function clip(value: string, max: number): string;
|
|
73
|
+
/** Redact then bound — the standard treatment for any captured free text. */
|
|
74
|
+
export declare function safeText(value: string | undefined, max?: number): string | undefined;
|
|
75
|
+
/** Redact then bound — the standard treatment for a captured title. */
|
|
76
|
+
export declare function safeTitle(value: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Scrub credential shapes out of every string leaf of an arbitrary value.
|
|
79
|
+
*
|
|
80
|
+
* Needed for `console` arguments, which are the one captured payload that is
|
|
81
|
+
* genuinely unstructured — `console.log('auth', { token })` is ordinary
|
|
82
|
+
* debugging code, and the whole point of this change is that those payloads
|
|
83
|
+
* now reach a transcript. Bounded on depth and array length so a pathological
|
|
84
|
+
* object cannot make the bridge the slow part of a page's logging.
|
|
85
|
+
*
|
|
86
|
+
* Values are returned by reference when nothing changed, so the common case
|
|
87
|
+
* (no credential anywhere) allocates nothing.
|
|
88
|
+
*/
|
|
89
|
+
export declare function redactDeep(value: unknown, depth?: number): unknown;
|
package/lib/redact.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redaction + bounding for browser-originated event text.
|
|
3
|
+
*
|
|
4
|
+
* ── Why this exists ─────────────────────────────────────────────────────────
|
|
5
|
+
* Until now the browser taps recorded almost nothing about an error, so there
|
|
6
|
+
* was nothing to leak. Enriching them (message, stack, method/URL/status)
|
|
7
|
+
* changes that: a request URL routinely carries a credential in its query
|
|
8
|
+
* string (`?access_token=…`, `?code=…` on an OAuth callback, `?key=…` on a
|
|
9
|
+
* Google API), and an error message can quote a JWT or an `Authorization`
|
|
10
|
+
* header. Those values then land in `runtime://browser/*`, which an agent
|
|
11
|
+
* reads and may quote into a transcript.
|
|
12
|
+
*
|
|
13
|
+
* So enrichment and redaction ship together, in the same place. This module is
|
|
14
|
+
* applied in `envelopeToEvent` — the ONE function every browser envelope
|
|
15
|
+
* crosses on its way to the bus — rather than at each tap, so a tap cannot
|
|
16
|
+
* forget it and a hand-rolled client cannot bypass it.
|
|
17
|
+
*
|
|
18
|
+
* `nx.json` has carried a `redaction: { headers, paths }` block since the init
|
|
19
|
+
* generator was written, with no reader anywhere in the repo. This is the
|
|
20
|
+
* first code to honour that intent; the lists below are a superset of it.
|
|
21
|
+
*
|
|
22
|
+
* ── Deliberately NOT done here ──────────────────────────────────────────────
|
|
23
|
+
* • Request/response HEADERS are never captured in the first place (the taps
|
|
24
|
+
* read none), which is the strongest possible defence — nothing to redact.
|
|
25
|
+
* Keep it that way; do not add header capture without extending this module.
|
|
26
|
+
* • Request/response BODIES are likewise never captured.
|
|
27
|
+
* • Free text is scrubbed for credential SHAPES (JWT, `Bearer …`), not parsed
|
|
28
|
+
* for arbitrary URLs. A URL embedded in a stack frame keeps its query
|
|
29
|
+
* string. Widening that means running the URL redactor over every message,
|
|
30
|
+
* which is a cost/false-positive trade not worth making blind.
|
|
31
|
+
*/
|
|
32
|
+
/** Replacement for a redacted value. Short, obvious, greppable. */
|
|
33
|
+
export const REDACTED = 'REDACTED';
|
|
34
|
+
/**
|
|
35
|
+
* Bounds. `raw` is structurally clamped to 32KiB by the bus transform
|
|
36
|
+
* (`createEventClamp`, wired in `@lensmcp/session`), but `title`/`message` are
|
|
37
|
+
* NOT — they are plain strings on `BaseEvent` and reach every reader
|
|
38
|
+
* unclamped. A stack from a deep React tree is routinely tens of KB, so these
|
|
39
|
+
* are the bounds that actually keep an event small.
|
|
40
|
+
*/
|
|
41
|
+
export const MAX_TITLE_CHARS = 300;
|
|
42
|
+
export const MAX_MESSAGE_CHARS = 4096;
|
|
43
|
+
export const MAX_URL_CHARS = 1024;
|
|
44
|
+
/**
|
|
45
|
+
* Substrings that make a query-parameter name a credential regardless of how
|
|
46
|
+
* it is spelled or delimited. These are safe as substrings — no ordinary
|
|
47
|
+
* parameter name contains them innocently.
|
|
48
|
+
*/
|
|
49
|
+
const SECRET_SUBSTRINGS = [
|
|
50
|
+
'token',
|
|
51
|
+
'secret',
|
|
52
|
+
'password',
|
|
53
|
+
'passwd',
|
|
54
|
+
'apikey',
|
|
55
|
+
'credential',
|
|
56
|
+
'assertion',
|
|
57
|
+
'signature',
|
|
58
|
+
];
|
|
59
|
+
/**
|
|
60
|
+
* Whole delimiter-separated words that make a parameter name a credential.
|
|
61
|
+
* Matched per-word (splitting on `-`, `_`, `.`) rather than as substrings,
|
|
62
|
+
* because the short ones collide: `auth` is a substring of `author`, `key` of
|
|
63
|
+
* `keywords`, `sig` of `sign_up_date`. Word matching keeps `?author=jane` and
|
|
64
|
+
* `?keywords=x` intact while still catching `?api_key=`/`?x-auth=`.
|
|
65
|
+
*/
|
|
66
|
+
const SECRET_WORDS = new Set([
|
|
67
|
+
'key',
|
|
68
|
+
'auth',
|
|
69
|
+
'authorization',
|
|
70
|
+
'jwt',
|
|
71
|
+
'code',
|
|
72
|
+
'sig',
|
|
73
|
+
'pwd',
|
|
74
|
+
'pass',
|
|
75
|
+
'session',
|
|
76
|
+
'sid',
|
|
77
|
+
'bearer',
|
|
78
|
+
'otp',
|
|
79
|
+
// The `headers` half of the `nx.json` redaction contract. Relevant to
|
|
80
|
+
// `redactDeep` (a headers object logged to console) as much as to a query
|
|
81
|
+
// string.
|
|
82
|
+
'cookie',
|
|
83
|
+
'set-cookie',
|
|
84
|
+
]);
|
|
85
|
+
/** Is this query-parameter name carrying a credential? */
|
|
86
|
+
export function isSecretParam(name) {
|
|
87
|
+
const n = name.toLowerCase();
|
|
88
|
+
if (SECRET_SUBSTRINGS.some((s) => n.includes(s)))
|
|
89
|
+
return true;
|
|
90
|
+
for (const word of n.split(/[-_.]+/)) {
|
|
91
|
+
if (word && SECRET_WORDS.has(word))
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* `scheme://user:pass@host` — credentials in the authority component.
|
|
98
|
+
* Anchored at the scheme so it cannot match a `@` inside a path or query.
|
|
99
|
+
*/
|
|
100
|
+
const USERINFO_RE = /^([a-z][a-z0-9+.-]*:\/\/)[^/?#@\s]*@/i;
|
|
101
|
+
/**
|
|
102
|
+
* One `?name=value` / `&name=value` / `#name=value` pair. Values are matched
|
|
103
|
+
* lazily up to the next delimiter, so the walk is linear and cannot backtrack
|
|
104
|
+
* catastrophically on a long URL.
|
|
105
|
+
*/
|
|
106
|
+
const PARAM_RE = /([?&#])([^=&#\s]+)=([^&#\s]*)/g;
|
|
107
|
+
/**
|
|
108
|
+
* Strip credentials from a URL, preserving every other byte.
|
|
109
|
+
*
|
|
110
|
+
* Implemented as a regex rewrite rather than `new URL(...)` on purpose:
|
|
111
|
+
* `URL` re-encodes as it round-trips (`+` vs `%20`, dropped default ports,
|
|
112
|
+
* sorted-looking output), which would mean the URL an agent reads is not the
|
|
113
|
+
* URL the app requested. It also throws on relative inputs, which is most of
|
|
114
|
+
* what a SPA fetches. This keeps the string byte-identical apart from the
|
|
115
|
+
* redacted values, and never throws.
|
|
116
|
+
*
|
|
117
|
+
* Redacts, in order: userinfo, then any query OR fragment parameter whose name
|
|
118
|
+
* looks like a credential. The fragment matters — an OAuth implicit-flow
|
|
119
|
+
* callback puts the access token there (`#access_token=…`).
|
|
120
|
+
*/
|
|
121
|
+
export function redactUrl(url) {
|
|
122
|
+
if (!url)
|
|
123
|
+
return url;
|
|
124
|
+
const withoutUserinfo = url.replace(USERINFO_RE, `$1${REDACTED}@`);
|
|
125
|
+
const withoutSecrets = withoutUserinfo.replace(PARAM_RE, (match, delim, name) => isSecretParam(name) ? `${delim}${name}=${REDACTED}` : match);
|
|
126
|
+
return clip(withoutSecrets, MAX_URL_CHARS);
|
|
127
|
+
}
|
|
128
|
+
/** A JSON Web Token: three base64url segments, the first starting `eyJ` (`{"`). */
|
|
129
|
+
const JWT_RE = /\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]*/g;
|
|
130
|
+
/** `Bearer <token>` / `Basic <creds>`, however it was quoted or spaced. */
|
|
131
|
+
const SCHEME_CREDENTIAL_RE = /\b(bearer|basic)\s+[A-Za-z0-9._~+/=-]{8,}/gi;
|
|
132
|
+
/**
|
|
133
|
+
* A credential-bearing header quoted into free text — `authorization: xyz`,
|
|
134
|
+
* `"x-api-key": "xyz"`, `cookie=xyz`. Only the VALUE is replaced so the reader
|
|
135
|
+
* still learns which header was involved.
|
|
136
|
+
*/
|
|
137
|
+
const HEADER_CREDENTIAL_RE = /\b(authorization|x-api-key|api-key|cookie|set-cookie|proxy-authorization)\b(\s*[:=]\s*)(["']?)([^\s"',;]{4,})\3/gi;
|
|
138
|
+
/**
|
|
139
|
+
* Scrub credential SHAPES out of free text (an error message, a stack, a
|
|
140
|
+
* console line). Cheap, linear, and tuned for precision over recall — a false
|
|
141
|
+
* positive destroys the diagnostic value this whole change is adding.
|
|
142
|
+
*/
|
|
143
|
+
export function redactText(text) {
|
|
144
|
+
return text
|
|
145
|
+
.replace(HEADER_CREDENTIAL_RE, (_m, header, sep, quote) => `${header}${sep}${quote}${REDACTED}${quote}`)
|
|
146
|
+
.replace(JWT_RE, REDACTED)
|
|
147
|
+
.replace(SCHEME_CREDENTIAL_RE, (_m, scheme) => `${scheme} ${REDACTED}`);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Bound a string, marking what was removed. Marker text matches
|
|
151
|
+
* `@lensmcp/storage`'s `clampEventRaw` so the two truncations read the same in
|
|
152
|
+
* a transcript.
|
|
153
|
+
*/
|
|
154
|
+
export function clip(value, max) {
|
|
155
|
+
if (value.length <= max)
|
|
156
|
+
return value;
|
|
157
|
+
return `${value.slice(0, max)}…[lensmcp truncated: ${value.length - max} more chars]`;
|
|
158
|
+
}
|
|
159
|
+
/** Redact then bound — the standard treatment for any captured free text. */
|
|
160
|
+
export function safeText(value, max = MAX_MESSAGE_CHARS) {
|
|
161
|
+
if (value === undefined)
|
|
162
|
+
return undefined;
|
|
163
|
+
return clip(redactText(value), max);
|
|
164
|
+
}
|
|
165
|
+
/** Redact then bound — the standard treatment for a captured title. */
|
|
166
|
+
export function safeTitle(value) {
|
|
167
|
+
return clip(redactText(value), MAX_TITLE_CHARS);
|
|
168
|
+
}
|
|
169
|
+
/** Depth ceiling for {@link redactDeep}; doubles as an allocation-free cycle guard. */
|
|
170
|
+
const MAX_REDACT_DEPTH = 6;
|
|
171
|
+
/** Array ceiling for {@link redactDeep}. Beyond this the tail is left as-is for the raw clamp to shed. */
|
|
172
|
+
const MAX_REDACT_ITEMS = 64;
|
|
173
|
+
/**
|
|
174
|
+
* Scrub credential shapes out of every string leaf of an arbitrary value.
|
|
175
|
+
*
|
|
176
|
+
* Needed for `console` arguments, which are the one captured payload that is
|
|
177
|
+
* genuinely unstructured — `console.log('auth', { token })` is ordinary
|
|
178
|
+
* debugging code, and the whole point of this change is that those payloads
|
|
179
|
+
* now reach a transcript. Bounded on depth and array length so a pathological
|
|
180
|
+
* object cannot make the bridge the slow part of a page's logging.
|
|
181
|
+
*
|
|
182
|
+
* Values are returned by reference when nothing changed, so the common case
|
|
183
|
+
* (no credential anywhere) allocates nothing.
|
|
184
|
+
*/
|
|
185
|
+
export function redactDeep(value, depth = 0) {
|
|
186
|
+
if (typeof value === 'string') {
|
|
187
|
+
return redactText(value);
|
|
188
|
+
}
|
|
189
|
+
if (value === null || typeof value !== 'object' || depth >= MAX_REDACT_DEPTH) {
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
if (Array.isArray(value)) {
|
|
193
|
+
let changed = false;
|
|
194
|
+
const out = value.map((item, i) => {
|
|
195
|
+
if (i >= MAX_REDACT_ITEMS)
|
|
196
|
+
return item;
|
|
197
|
+
const next = redactDeep(item, depth + 1);
|
|
198
|
+
if (next !== item)
|
|
199
|
+
changed = true;
|
|
200
|
+
return next;
|
|
201
|
+
});
|
|
202
|
+
return changed ? out : value;
|
|
203
|
+
}
|
|
204
|
+
let changed = false;
|
|
205
|
+
const out = {};
|
|
206
|
+
for (const [key, item] of Object.entries(value)) {
|
|
207
|
+
// A key named like a credential is redacted whatever its value's shape —
|
|
208
|
+
// this is the `paths` half of the `nx.json` redaction contract.
|
|
209
|
+
const next = isSecretParam(key) && item !== undefined && item !== null ? REDACTED : redactDeep(item, depth + 1);
|
|
210
|
+
if (next !== item)
|
|
211
|
+
changed = true;
|
|
212
|
+
out[key] = next;
|
|
213
|
+
}
|
|
214
|
+
return changed ? out : value;
|
|
215
|
+
}
|
package/lib/server.d.ts
CHANGED
|
@@ -53,4 +53,3 @@ export declare function handleClientEnvelope(raw: string, publish: (event: BaseE
|
|
|
53
53
|
export declare function createBridgeServer(options?: BridgeServerOptions): Promise<BridgeServer>;
|
|
54
54
|
/** Allocate an ephemeral free port (used when `port: 0` is requested). */
|
|
55
55
|
export declare function findFreePort(): Promise<number>;
|
|
56
|
-
//# sourceMappingURL=server.d.ts.map
|
package/lib/types.d.ts
CHANGED
|
@@ -8,18 +8,52 @@
|
|
|
8
8
|
* no-build) shares one definition. The Vite plugin re-exports it for
|
|
9
9
|
* backwards compatibility.
|
|
10
10
|
*/
|
|
11
|
-
export type ClientEnvelope = (
|
|
11
|
+
export type ClientEnvelope = (
|
|
12
|
+
/**
|
|
13
|
+
* An uncaught JS error (`window.onerror`). `message` is OPTIONAL because it
|
|
14
|
+
* genuinely can be absent: a synthesised or cross-origin `ErrorEvent`
|
|
15
|
+
* carries none, and 3 of the 7 real browser errors captured on foodguard
|
|
16
|
+
* (2026-07-30) had no message at all. `name` is the constructor name of the
|
|
17
|
+
* thrown value, which survives when a cross-origin policy strips the rest.
|
|
18
|
+
*/
|
|
19
|
+
{
|
|
12
20
|
kind: 'error';
|
|
13
21
|
at: number;
|
|
14
|
-
message
|
|
22
|
+
message?: string;
|
|
23
|
+
name?: string;
|
|
15
24
|
stack?: string;
|
|
16
25
|
source?: string;
|
|
17
26
|
lineno?: number;
|
|
18
27
|
colno?: number;
|
|
19
|
-
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A SUBRESOURCE that failed to load — `<img>`, `<script>`, `<link>`,
|
|
31
|
+
* `<video>`. The browser delivers these through the SAME `error` listener as
|
|
32
|
+
* an uncaught exception, but as a plain `Event`, not an `ErrorEvent`: no
|
|
33
|
+
* message, no filename, no line. Its only identity is the target element and
|
|
34
|
+
* its `src`/`href`, which the tap previously never read — so every one of
|
|
35
|
+
* them serialised to a bare `{ kind: 'error', at, tabId }` and arrived
|
|
36
|
+
* completely anonymous. Splitting the kind is what makes that identity
|
|
37
|
+
* representable.
|
|
38
|
+
*/
|
|
39
|
+
| {
|
|
40
|
+
kind: 'resource-error';
|
|
41
|
+
at: number;
|
|
42
|
+
tagName: string;
|
|
43
|
+
url?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* An unhandled promise rejection. The reason is decomposed rather than
|
|
47
|
+
* pre-stringified: a rejected non-Error object (`{ status: 401 }`, a
|
|
48
|
+
* `Response`) used to be flattened by `String(reason)` into the useless
|
|
49
|
+
* `"[object Object]"`.
|
|
50
|
+
*/
|
|
51
|
+
| {
|
|
20
52
|
kind: 'unhandledrejection';
|
|
21
53
|
at: number;
|
|
22
54
|
reason: string;
|
|
55
|
+
name?: string;
|
|
56
|
+
stack?: string;
|
|
23
57
|
} | {
|
|
24
58
|
kind: 'console';
|
|
25
59
|
at: number;
|
|
@@ -31,6 +65,7 @@ export type ClientEnvelope = ({
|
|
|
31
65
|
method: string;
|
|
32
66
|
url: string;
|
|
33
67
|
status?: number;
|
|
68
|
+
statusText?: string;
|
|
34
69
|
durationMs?: number;
|
|
35
70
|
ok?: boolean;
|
|
36
71
|
error?: string;
|
|
@@ -61,4 +96,3 @@ export type ClientEnvelope = ({
|
|
|
61
96
|
};
|
|
62
97
|
/** A cross-process event sink: takes one normalised event and forwards it onward. */
|
|
63
98
|
export type EnvSink = (event: import('@lensmcp/protocol-types').BaseEvent) => void;
|
|
64
|
-
//# sourceMappingURL=types.d.ts.map
|
package/main.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lensmcp/bridge",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@lensmcp/core": "1.18.
|
|
23
|
-
"@lensmcp/protocol-types": "1.18.
|
|
22
|
+
"@lensmcp/core": "1.18.4",
|
|
23
|
+
"@lensmcp/protocol-types": "1.18.4",
|
|
24
24
|
"tslib": "^2.3.0",
|
|
25
25
|
"ws": "^8.21.0"
|
|
26
26
|
},
|
package/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EACL,eAAe,EACf,eAAe,EACf,WAAW,EACX,WAAW,EACX,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC"}
|
package/lib/constants.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C,4FAA4F;AAC5F,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,oDAAoD;AACpD,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAC7C,oFAAoF;AACpF,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAC7C,yEAAyE;AACzE,eAAO,MAAM,cAAc,uBAAuB,CAAC"}
|
package/lib/env-sink.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"env-sink.d.ts","sourceRoot":"","sources":["../../src/lib/env-sink.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAwF1C,wBAAgB,cAAc,IAAI,OAAO,GAAG,IAAI,CA6C/C;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgDhD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event-mappers.d.ts","sourceRoot":"","sources":["../../src/lib/event-mappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,SAAS,SAAyB,GAAG,SAAS,CAuIlG"}
|
package/lib/server.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/lib/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAI9C,OAAO,KAAK,EAAkB,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAsB1E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,EACnC,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CASN;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC,CAmCjG;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAgB9C"}
|
package/lib/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,CACzB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChH;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,GACpG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9H;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAK7D;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CACJ,GAAG;IACF,0GAA0G;IAC1G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,OAAO,yBAAyB,EAAE,SAAS,KAAK,IAAI,CAAC"}
|
package/main.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
|