@chrischall/mcp-utils 0.6.0 → 0.8.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 +148 -9
- package/dist/auth/index.d.ts +15 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +48 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/config/index.d.ts +66 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +97 -0
- package/dist/config/index.js.map +1 -1
- package/dist/errors/index.d.ts +12 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +45 -3
- package/dist/errors/index.js.map +1 -1
- package/dist/fetchproxy/index.d.ts +149 -2
- package/dist/fetchproxy/index.d.ts.map +1 -1
- package/dist/fetchproxy/index.js +179 -2
- package/dist/fetchproxy/index.js.map +1 -1
- package/dist/http/index.d.ts +179 -5
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +280 -21
- package/dist/http/index.js.map +1 -1
- package/dist/http/throttle.d.ts +28 -0
- package/dist/http/throttle.d.ts.map +1 -0
- package/dist/http/throttle.js +39 -0
- package/dist/http/throttle.js.map +1 -0
- package/dist/response/index.d.ts +5 -1
- package/dist/response/index.d.ts.map +1 -1
- package/dist/response/index.js +7 -2
- package/dist/response/index.js.map +1 -1
- package/dist/session/index.d.ts +139 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +215 -9
- package/dist/session/index.js.map +1 -1
- package/dist/zod/index.d.ts +19 -0
- package/dist/zod/index.d.ts.map +1 -1
- package/dist/zod/index.js +27 -0
- package/dist/zod/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ import light:
|
|
|
28
28
|
| Import | Contents |
|
|
29
29
|
| --- | --- |
|
|
30
30
|
| `@chrischall/mcp-utils` | core barrel: `server` + `response` + `errors` + `config` + `fs` + `http` + `zod` + `auth` |
|
|
31
|
-
| `@chrischall/mcp-utils/session` | session registry, session store, token manager |
|
|
31
|
+
| `@chrischall/mcp-utils/session` | session registry, session store, token manager, cookie-session manager |
|
|
32
32
|
| `@chrischall/mcp-utils/fetchproxy` | fetchproxy transport adapter, bot-wall / retry / concurrency helpers |
|
|
33
33
|
| `@chrischall/mcp-utils/html` | opt-in HTML scraping helpers (needs `node-html-parser`) |
|
|
34
34
|
| `@chrischall/mcp-utils/test` | in-memory test harness for tool registration |
|
|
@@ -82,8 +82,12 @@ deepMapStringField(payload, 'eventDate', dmyToIso);
|
|
|
82
82
|
|
|
83
83
|
`McpToolError` and its subclasses (`SessionNotAuthenticatedError`,
|
|
84
84
|
`BotWallError`, `RateLimitError`, `UnreachableError`, `ModeMismatchError`),
|
|
85
|
-
plus `createHelpfulError`, `wrapToolError`, `truncateErrorMessage`,
|
|
86
|
-
`messageOf`.
|
|
85
|
+
plus `createHelpfulError`, `wrapToolError`, `truncateErrorMessage`,
|
|
86
|
+
`redactSecrets`, and `messageOf`. `redactSecrets` scrubs `Bearer`/`Basic` auth
|
|
87
|
+
headers, `Cookie`/`Set-Cookie` values (cookie names stay visible), JWTs,
|
|
88
|
+
well-known API-key shapes (`sk-…`, `ghp_…`, `xox?-…`, `AIza…`, `AKIA…`,
|
|
89
|
+
`whsec_…`), and secret-bearing URL query params; `truncateErrorMessage` applies
|
|
90
|
+
it before truncating, and `errorResult` applies it (without truncating). This core module has **no runtime dependencies** — the fetchproxy
|
|
87
91
|
typed-error hierarchy (`Fetchproxy*Error`), the raw `classifyBridgeError` /
|
|
88
92
|
`classifyRowError` re-exports, and the `bridgeErrorInfo` envelope helper live in
|
|
89
93
|
the [`/fetchproxy`](#fetchproxy) subpath instead, so
|
|
@@ -105,19 +109,46 @@ tool surface can show the user.
|
|
|
105
109
|
|
|
106
110
|
### `config` — hardened env/config
|
|
107
111
|
|
|
108
|
-
`readEnvVar`, `requireEnvVar`, `parseBoolEnv`, `
|
|
112
|
+
`readEnvVar`, `requireEnvVar`, `parseBoolEnv`, `readPortEnv`, `expandPath`,
|
|
113
|
+
`loadDotenvSafely`, `createCachedJsonArrayLoader`.
|
|
109
114
|
|
|
110
115
|
```ts
|
|
111
|
-
import { requireEnvVar, parseBoolEnv, expandPath } from '@chrischall/mcp-utils';
|
|
116
|
+
import { requireEnvVar, parseBoolEnv, readPortEnv, expandPath } from '@chrischall/mcp-utils';
|
|
112
117
|
|
|
113
118
|
const apiKey = requireEnvVar('MY_API_KEY');
|
|
114
119
|
const debug = parseBoolEnv('MY_DEBUG', { default: false });
|
|
120
|
+
const port = readPortEnv('MY_WS_PORT', 37149); // placeholder/NaN/out-of-range → fallback
|
|
115
121
|
const home = expandPath('~/.config/my-mcp');
|
|
116
122
|
```
|
|
117
123
|
|
|
124
|
+
`readPortEnv` parses a TCP port with the same placeholder hardening as
|
|
125
|
+
`readEnvVar`, plus integer + `1..65535` range validation — so an unexpanded
|
|
126
|
+
`${MY_WS_PORT}` or junk falls back to the default instead of handing `NaN` to
|
|
127
|
+
the server.
|
|
128
|
+
|
|
118
129
|
`loadDotenvSafely` is a no-throw `.env` loader (returns `false` instead of
|
|
119
130
|
failing when the file is absent).
|
|
120
131
|
|
|
132
|
+
`createCachedJsonArrayLoader` builds a cached, negative-cached loader for an
|
|
133
|
+
env-named JSON string-array file — the `loadCommunities`/`DEFAULT_COMMUNITIES`
|
|
134
|
+
pattern shared across the realty servers:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import { createCachedJsonArrayLoader } from '@chrischall/mcp-utils';
|
|
138
|
+
|
|
139
|
+
const loadCommunities = createCachedJsonArrayLoader({
|
|
140
|
+
envVar: 'REDFIN_COMMUNITIES_FILE', // path to a JSON string-array file
|
|
141
|
+
defaults: DEFAULT_COMMUNITIES, // returned when unset/missing/invalid
|
|
142
|
+
label: 'redfin-mcp',
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const communities = loadCommunities(); // parses + caches; re-reads only on path change
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
A successful parse is cached; a missing/unreadable file, invalid JSON, or a
|
|
149
|
+
non-string-array logs one stderr warning and negative-caches (returns defaults
|
|
150
|
+
without re-reading). Pass `readFile` to inject a reader in tests.
|
|
151
|
+
|
|
121
152
|
### `fs` — streaming file helpers (uploads)
|
|
122
153
|
|
|
123
154
|
`fileBlob`, `readFileHead`.
|
|
@@ -141,10 +172,15 @@ constant memory instead of a 20 MB Buffer.
|
|
|
141
172
|
### `http` — bearer API-client kit
|
|
142
173
|
|
|
143
174
|
`createApiClient` plus building blocks: `buildQueryString`, `buildOptionalBody`,
|
|
144
|
-
`formatApiError`, `parseLinkHeader`, `parseCookieJar`,
|
|
145
|
-
(`decodeJwtExp`, `decodeJwtSessionId`,
|
|
175
|
+
`formatApiError`, `parseLinkHeader`, `parseCookieJar`, `parseCookieHeader`,
|
|
176
|
+
`runBoundedBatch`, JWT helpers (`decodeJwtExp`, `decodeJwtSessionId`,
|
|
177
|
+
`decodeJwtClaim`, `validateJwtExpiry`), and the `ApiError` / `UpstreamHttpError` /
|
|
146
178
|
`UnauthorizedError` / `RateLimitedError` / `RequestTimeoutError` classes.
|
|
147
179
|
|
|
180
|
+
`decodeJwtClaim(token, claim)` is the generic single-claim reader — returns the
|
|
181
|
+
raw claim value (`unknown`) or `undefined` for an undecodable token / absent
|
|
182
|
+
claim, so a repo doesn't hand-roll its own `extractXFromJwt`.
|
|
183
|
+
|
|
148
184
|
```ts
|
|
149
185
|
import { createApiClient } from '@chrischall/mcp-utils';
|
|
150
186
|
|
|
@@ -163,6 +199,37 @@ const data = await api.get('/v1/things', { query: { page: 2 } });
|
|
|
163
199
|
`RequestTimeoutError` instead of hanging the tool call. A 429 retry gets a fresh
|
|
164
200
|
timeout. Omit it to keep the previous unbounded behavior.
|
|
165
201
|
|
|
202
|
+
`parseCookieHeader(header)` parses an inbound *request* `Cookie:` header
|
|
203
|
+
(`name=value; name2=value2`) into a `Record<string, string>` (first `=` splits,
|
|
204
|
+
so values may contain `=`; last value wins on a duplicate name). It's the
|
|
205
|
+
counterpart to `parseCookieJar`, which parses *response* `Set-Cookie` headers
|
|
206
|
+
with their attributes and deletion semantics.
|
|
207
|
+
|
|
208
|
+
`UpstreamHttpError(status, message)` is a directly-`throw new`-able,
|
|
209
|
+
status-carrying HTTP error — the manual-throw parallel to `ApiError` (which
|
|
210
|
+
`createApiClient` throws internally). It `extends ApiError`, so both the
|
|
211
|
+
`err instanceof ApiError && err.status === 404` branch and a narrower
|
|
212
|
+
`instanceof UpstreamHttpError` check work. Use it from a transport/bridge code
|
|
213
|
+
path that doesn't route through `createApiClient` but still needs to branch on a
|
|
214
|
+
404.
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { runBoundedBatch } from '@chrischall/mcp-utils';
|
|
218
|
+
|
|
219
|
+
const rows = await runBoundedBatch(ids, (id, signal) => fetchRow(id, signal), {
|
|
220
|
+
deadlineMs: 45_000, // overall hard deadline for the whole batch
|
|
221
|
+
concurrency: 4, // optional fan-out cap
|
|
222
|
+
onTimeout: (id, i) => ({ id, pending: true }), // backfill any row the deadline cut off
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`runBoundedBatch(items, worker, opts)` races the whole batch against one overall
|
|
227
|
+
`deadlineMs`; any item still unsettled when it fires is filled by
|
|
228
|
+
`onTimeout(item, index)` (and its worker abandoned + `AbortSignal`-signalled) so
|
|
229
|
+
a single hung row can't wedge the call. It always returns a full-length,
|
|
230
|
+
input-ordered array. `setTimer`/`clearTimer` are injectable for tests. This
|
|
231
|
+
hoists zillow's bulk-tool deadline + `pending`-backfill primitive.
|
|
232
|
+
|
|
166
233
|
### `dates` — date-format converters
|
|
167
234
|
|
|
168
235
|
`isoToDmy`, `dmyToIso`, `isoToCompactTimestamp`. For upstreams that don't speak
|
|
@@ -180,7 +247,8 @@ deepMapStringField(payload, 'eventDate', dmyToIso); // '28-08-2025' → '202
|
|
|
180
247
|
### `zod` — schema atoms
|
|
181
248
|
|
|
182
249
|
Reusable schemas (`PositiveInt`, `NonNegInt`, `NonEmptyString`, `IsoDate`,
|
|
183
|
-
`IsoTime`, `
|
|
250
|
+
`IsoTime`, `NumericIdString`, `SafePathSegment`, `schemaOrigin`,
|
|
251
|
+
`schemaConfirm`), pagination helpers
|
|
184
252
|
(`paginationSchema`, `pageSchema`, `calculateOffset`), tool-annotation builders
|
|
185
253
|
(`toolAnnotations`), and time normalizers (`extractTime`, `normalizeTime`).
|
|
186
254
|
|
|
@@ -192,6 +260,11 @@ const offset = calculateOffset(page, size);
|
|
|
192
260
|
const annotations = toolAnnotations({ readOnly: true });
|
|
193
261
|
```
|
|
194
262
|
|
|
263
|
+
`NumericIdString` (`/^\d+$/`) and `SafePathSegment` (rejects `/`, `..`, `?`,
|
|
264
|
+
`#`, and whitespace) harden caller-supplied ids that get interpolated into
|
|
265
|
+
request paths — defense-in-depth against path traversal and query/fragment
|
|
266
|
+
injection.
|
|
267
|
+
|
|
195
268
|
### `auth` — auth resolver skeletons
|
|
196
269
|
|
|
197
270
|
`createAuthResolver`, `resolveAuthPattern`, `sessionLoginFlow`,
|
|
@@ -205,13 +278,14 @@ const resolver = createAuthResolver({ /* ... */ });
|
|
|
205
278
|
const refresh = createOAuth2Refresher({ /* ... */ });
|
|
206
279
|
```
|
|
207
280
|
|
|
208
|
-
### `session` — session registry &
|
|
281
|
+
### `session` — session registry, token manager & cookie-session manager *(subpath)*
|
|
209
282
|
|
|
210
283
|
```ts
|
|
211
284
|
import {
|
|
212
285
|
createSessionRegistry,
|
|
213
286
|
registerSessionTools,
|
|
214
287
|
TokenManager,
|
|
288
|
+
CookieSessionManager,
|
|
215
289
|
} from '@chrischall/mcp-utils/session';
|
|
216
290
|
|
|
217
291
|
const registry = createSessionRegistry();
|
|
@@ -221,12 +295,40 @@ registerSessionTools(server, { registry /* ... */ });
|
|
|
221
295
|
Includes `SessionStore`, `normalizeOrigin`, `AuthMode`, and `TokenManager`
|
|
222
296
|
(with `TOKEN_REFRESH_SKEW_MS` for proactive refresh).
|
|
223
297
|
|
|
298
|
+
`CookieSessionManager<S>` is the cookie-session analog of `TokenManager` for
|
|
299
|
+
sites authenticated by a browser-style cookie session rather than a bearer
|
|
300
|
+
token. It owns *when* to log in (single-flight, so concurrent callers coalesce
|
|
301
|
+
into ONE login), clears the in-flight promise on settle (a rejected login never
|
|
302
|
+
sticks — the next `ensure()` retries), and `withSession()` re-logs-in and
|
|
303
|
+
replays a request **exactly once** on a detected expiry (no infinite loop). The
|
|
304
|
+
injected `isExpired(res)` predicate is the hook for body/URL heuristics — so a
|
|
305
|
+
`200` serving an HTML login page or a redirect away from the target is treated
|
|
306
|
+
as expired, not just `401`/`403`. An optional `isPermanentError` caches genuine
|
|
307
|
+
missing-config errors while leaving transient login failures retryable.
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
const sessions = new CookieSessionManager<{ cookieHeader: string; csrfToken?: string }>({
|
|
311
|
+
login: () => loginWithPassword(), // mints a fresh cookie session
|
|
312
|
+
isExpired: async (res) =>
|
|
313
|
+
res.status === 401 || /<form[^>]*id="login"/i.test(await res.clone().text()),
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const res = await sessions.withSession((s) =>
|
|
317
|
+
fetch(url, { headers: { cookie: s.cookieHeader } }),
|
|
318
|
+
);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Replaces the hand-rolled re-login / single-flight / 401-replay code in
|
|
322
|
+
`artsonia-mcp`, `canvas-parent-mcp`, `evite-mcp`, `signupgenius-mcp`, and
|
|
323
|
+
`skylight-mcp`.
|
|
324
|
+
|
|
224
325
|
### `fetchproxy` — transport adapter *(subpath, optional peer)*
|
|
225
326
|
|
|
226
327
|
```ts
|
|
227
328
|
import {
|
|
228
329
|
createFetchproxyTransport,
|
|
229
330
|
createBootstrapOpts,
|
|
331
|
+
registerBridgeHealthcheckTool,
|
|
230
332
|
mapWithConcurrency,
|
|
231
333
|
TokenBucket,
|
|
232
334
|
classifyBotWall,
|
|
@@ -237,6 +339,43 @@ Wraps `@fetchproxy/server` with the fleet's transport, bot-wall classification,
|
|
|
237
339
|
deadline/retry, token-bucket rate limiting, and bounded-concurrency helpers, and
|
|
238
340
|
re-exports the fetchproxy typed-error hierarchy.
|
|
239
341
|
|
|
342
|
+
**Transport verb adapters.** Beyond the `start` / `close` / `status` lifecycle,
|
|
343
|
+
`createFetchproxyTransport` exposes the verb passthroughs redfin / homes /
|
|
344
|
+
compass / musescore had each hand-rolled over the server:
|
|
345
|
+
|
|
346
|
+
- `fetch(init)` → `{ status, body, url }` via `server.request(...)`;
|
|
347
|
+
- `requestJson(method, path, init?)` → `{ data, result }` via
|
|
348
|
+
`server.requestJson(...)` (serialization + header defaults + 204→null +
|
|
349
|
+
`JSON.parse`; the caller keeps its per-site `throwIfNotOk` over `result`);
|
|
350
|
+
- `runProbe(fetchFn, probePath)` → the healthcheck probe loop.
|
|
351
|
+
|
|
352
|
+
The one per-site bit is the subdomain: pass `defaultSubdomain: 'www'` for sites
|
|
353
|
+
served from `www` (redfin/homes/compass); omit it for apex-served sites
|
|
354
|
+
(musescore). A per-call `subdomain` always overrides the default, and absolute
|
|
355
|
+
`http(s)://` paths self-describe their host. Other per-site verbs (e.g.
|
|
356
|
+
musescore's `download` capability) stay caller-supplied — the factory covers the
|
|
357
|
+
common subset, not the long tail.
|
|
358
|
+
|
|
359
|
+
**Bridge-healthcheck tool factory.** `registerBridgeHealthcheckTool({ server,
|
|
360
|
+
prefix, probePath, hostLabel, transport, probeFn })` registers a
|
|
361
|
+
`<prefix>_healthcheck` tool that round-trips `probePath` through the bridge and
|
|
362
|
+
reports bridge role / port / timing plus an actionable hint ladder
|
|
363
|
+
(`bridge_down` → wake the SW, `role === null` → check startup, `timeout` →
|
|
364
|
+
extension not connected, …). The failure hint cites the **actual configured
|
|
365
|
+
bridge port** from `bridgeHealth()`, not a hardcoded `37149` — fixing the bug
|
|
366
|
+
the per-site compass + musescore copies shared.
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
registerBridgeHealthcheckTool({
|
|
370
|
+
server,
|
|
371
|
+
prefix: 'compass',
|
|
372
|
+
probePath: '/robots.txt',
|
|
373
|
+
hostLabel: 'compass.com',
|
|
374
|
+
transport,
|
|
375
|
+
probeFn: (path) => client.fetchHtml(path),
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
240
379
|
### `html` — scraping helpers *(subpath, optional peer)*
|
|
241
380
|
|
|
242
381
|
```ts
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -24,6 +24,18 @@
|
|
|
24
24
|
* (placeholder / `'null'` / `'undefined'` suppression); thrown errors never
|
|
25
25
|
* echo the offending secret value and run upstream bodies through
|
|
26
26
|
* {@link truncateErrorMessage} (redaction + truncation) before surfacing.
|
|
27
|
+
*
|
|
28
|
+
* fetchproxy bridge-down hints are preserved: when the injected bootstrap
|
|
29
|
+
* rejects with a `FetchproxyBridgeDownError` (duck-typed — this core module
|
|
30
|
+
* stays zero-runtime-dep and never imports `@fetchproxy/server` or the
|
|
31
|
+
* `/fetchproxy` subpath), {@link createAuthResolver} surfaces the error's
|
|
32
|
+
* actionable `.hint` verbatim ("make sure a signed-in tab is open… reload
|
|
33
|
+
* the extension…") instead of the generic truncated wrap. This absorbs the
|
|
34
|
+
* `classifyBridgeError(e) === 'bridge_down'` branch the fleet copies of this
|
|
35
|
+
* skeleton hand-rolled, and unblocks the zola / infinitecampus / ofw /
|
|
36
|
+
* creditkarma migrations onto this resolver in a later wave.
|
|
37
|
+
* ({@link resolveAuthPattern} never had the gap — it propagates a configured
|
|
38
|
+
* path's errors unwrapped, so an injected fetchproxy path's hint survives.)
|
|
27
39
|
*/
|
|
28
40
|
import { type EnvSource } from '../config/index.js';
|
|
29
41
|
/** A `@fetchproxy/bootstrap` session blob: declared cookies / storage, by key. */
|
|
@@ -117,7 +129,9 @@ export interface AuthPattern {
|
|
|
117
129
|
* fetchproxy**. Runs the first *provided* resolver in that order (a missing
|
|
118
130
|
* resolver = an unconfigured path). A resolver that throws propagates — a
|
|
119
131
|
* partial-config error (the user's mistake) must surface, not silently fall
|
|
120
|
-
* through.
|
|
132
|
+
* through. Errors propagate *unwrapped*, so an injected fetchproxy path's
|
|
133
|
+
* bridge-down `.hint` survives intact. Throws an actionable error when no
|
|
134
|
+
* path is configured at all.
|
|
121
135
|
*/
|
|
122
136
|
export declare function resolveAuthPattern(pattern: AuthPattern): Promise<PatternResult>;
|
|
123
137
|
/** Options for {@link sessionLoginFlow}. */
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/index.js
CHANGED
|
@@ -24,10 +24,43 @@
|
|
|
24
24
|
* (placeholder / `'null'` / `'undefined'` suppression); thrown errors never
|
|
25
25
|
* echo the offending secret value and run upstream bodies through
|
|
26
26
|
* {@link truncateErrorMessage} (redaction + truncation) before surfacing.
|
|
27
|
+
*
|
|
28
|
+
* fetchproxy bridge-down hints are preserved: when the injected bootstrap
|
|
29
|
+
* rejects with a `FetchproxyBridgeDownError` (duck-typed — this core module
|
|
30
|
+
* stays zero-runtime-dep and never imports `@fetchproxy/server` or the
|
|
31
|
+
* `/fetchproxy` subpath), {@link createAuthResolver} surfaces the error's
|
|
32
|
+
* actionable `.hint` verbatim ("make sure a signed-in tab is open… reload
|
|
33
|
+
* the extension…") instead of the generic truncated wrap. This absorbs the
|
|
34
|
+
* `classifyBridgeError(e) === 'bridge_down'` branch the fleet copies of this
|
|
35
|
+
* skeleton hand-rolled, and unblocks the zola / infinitecampus / ofw /
|
|
36
|
+
* creditkarma migrations onto this resolver in a later wave.
|
|
37
|
+
* ({@link resolveAuthPattern} never had the gap — it propagates a configured
|
|
38
|
+
* path's errors unwrapped, so an injected fetchproxy path's hint survives.)
|
|
27
39
|
*/
|
|
28
40
|
import { readEnvVar, parseBoolEnv } from '../config/index.js';
|
|
29
41
|
import { truncateErrorMessage, SessionNotAuthenticatedError, createHelpfulError, } from '../errors/index.js';
|
|
30
42
|
import { parseCookieJar } from '../http/index.js';
|
|
43
|
+
/**
|
|
44
|
+
* Duck-typed `bridge_down` detection — mirrors `classifyBridgeError(e) ===
|
|
45
|
+
* 'bridge_down'` from the `/fetchproxy` subpath WITHOUT importing
|
|
46
|
+
* `@fetchproxy/server` (this core module must stay zero-runtime-dep).
|
|
47
|
+
* `classifyBridgeError`'s `'bridge_down'` arm is exactly
|
|
48
|
+
* `err instanceof FetchproxyBridgeDownError`, and that class's constructor
|
|
49
|
+
* unconditionally sets `name = 'FetchproxyBridgeDownError'` and a non-empty
|
|
50
|
+
* string `hint` — so the (name, string-hint) pair is a faithful stand-in for
|
|
51
|
+
* the `instanceof`, and unlike `instanceof` it stays correct when the dep
|
|
52
|
+
* tree carries a duplicated copy of `@fetchproxy/server`.
|
|
53
|
+
*
|
|
54
|
+
* Returns the actionable `.hint` when `err` is bridge-down, else `undefined`.
|
|
55
|
+
*/
|
|
56
|
+
function bridgeDownHintOf(err) {
|
|
57
|
+
if (err instanceof Error && err.name === 'FetchproxyBridgeDownError') {
|
|
58
|
+
const hint = err.hint;
|
|
59
|
+
if (typeof hint === 'string' && hint.length > 0)
|
|
60
|
+
return hint;
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
31
64
|
/**
|
|
32
65
|
* Build the canonical **three-path** auth resolver:
|
|
33
66
|
*
|
|
@@ -60,6 +93,18 @@ export function createAuthResolver(opts) {
|
|
|
60
93
|
session = await bootstrap(bootstrapOptions);
|
|
61
94
|
}
|
|
62
95
|
catch (e) {
|
|
96
|
+
// Bridge-down gets first-class treatment. A `FetchproxyBridgeDownError`
|
|
97
|
+
// only escapes bootstrap() after the server's one-shot lazy-revive
|
|
98
|
+
// retry also failed — the extension's service worker is genuinely down
|
|
99
|
+
// and the user needs to wake it. Its `.hint` is the actionable copy
|
|
100
|
+
// the fleet (zola / IC / ofw / honeybook) hand-rolled this branch to
|
|
101
|
+
// preserve; surface it verbatim (library-authored, not an untrusted
|
|
102
|
+
// upstream body — so no truncation that could clip the guidance).
|
|
103
|
+
const bridgeHint = bridgeDownHintOf(e);
|
|
104
|
+
if (bridgeHint !== undefined) {
|
|
105
|
+
throw createHelpfulError(`Auth: no ${envVar} set, and the fetchproxy bridge is down ` +
|
|
106
|
+
`(extension service worker unreachable). ${bridgeHint}`, { hint: bridgeHint });
|
|
107
|
+
}
|
|
63
108
|
// Surface the fallback failure but point back at the env-var escape
|
|
64
109
|
// hatch. Redact + truncate the underlying message.
|
|
65
110
|
throw createHelpfulError(`Auth: no ${envVar} set, and fetchproxy fallback failed: ${truncateErrorMessage(messageOf(e))}`, { hint: `Set ${envVar}, or sign in in your browser and retry.` });
|
|
@@ -82,7 +127,9 @@ export function createAuthResolver(opts) {
|
|
|
82
127
|
* fetchproxy**. Runs the first *provided* resolver in that order (a missing
|
|
83
128
|
* resolver = an unconfigured path). A resolver that throws propagates — a
|
|
84
129
|
* partial-config error (the user's mistake) must surface, not silently fall
|
|
85
|
-
* through.
|
|
130
|
+
* through. Errors propagate *unwrapped*, so an injected fetchproxy path's
|
|
131
|
+
* bridge-down `.hint` survives intact. Throws an actionable error when no
|
|
132
|
+
* path is configured at all.
|
|
86
133
|
*/
|
|
87
134
|
export async function resolveAuthPattern(pattern) {
|
|
88
135
|
const ordered = [
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"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"}
|
package/dist/config/index.d.ts
CHANGED
|
@@ -62,6 +62,72 @@ export declare function parseBoolEnv(key: string, opts?: ParseBoolEnvOptions): b
|
|
|
62
62
|
* NOT expanded — only the current user's home is ever substituted.
|
|
63
63
|
*/
|
|
64
64
|
export declare function expandPath(p: string): string;
|
|
65
|
+
/** Options for {@link readPortEnv}. */
|
|
66
|
+
export interface ReadPortEnvOptions {
|
|
67
|
+
/** The source to read from. Defaults to {@link process.env}. */
|
|
68
|
+
env?: EnvSource;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Read a TCP port from an environment variable, hardened the way
|
|
72
|
+
* {@link readEnvVar} hardens any var (trim, treat blank / `'undefined'` /
|
|
73
|
+
* `'null'` / unsubstituted `${...}` placeholder as unset) PLUS numeric
|
|
74
|
+
* validation: the value must parse to an integer in the valid port range
|
|
75
|
+
* `1..65535`.
|
|
76
|
+
*
|
|
77
|
+
* Returns `fallback` when the variable is unset, a placeholder, non-numeric, or
|
|
78
|
+
* out of range. Consolidates the bare `Number(process.env.X_WS_PORT)` pattern
|
|
79
|
+
* across compass/redfin/homes/musescore, which yields `NaN` on an unexpanded
|
|
80
|
+
* `${...}` placeholder or junk and then hands `NaN` to the server.
|
|
81
|
+
*
|
|
82
|
+
* @example readPortEnv('REDFIN_WS_PORT', 37149)
|
|
83
|
+
*/
|
|
84
|
+
export declare function readPortEnv(key: string, fallback: number, opts?: ReadPortEnvOptions): number;
|
|
85
|
+
/** A minimal injectable file reader: returns the file's UTF-8 contents. */
|
|
86
|
+
export type ReadFileSyncFn = (path: string) => string;
|
|
87
|
+
/** Options for {@link createCachedJsonArrayLoader}. */
|
|
88
|
+
export interface CachedJsonArrayLoaderOptions {
|
|
89
|
+
/** Name of the env var holding the path to a JSON string-array file. */
|
|
90
|
+
envVar: string;
|
|
91
|
+
/** Returned when the var is unset, or the file is missing/unreadable/invalid. */
|
|
92
|
+
defaults: string[];
|
|
93
|
+
/** The source to read env from. Defaults to {@link process.env}. */
|
|
94
|
+
env?: EnvSource;
|
|
95
|
+
/**
|
|
96
|
+
* Injectable file reader (for tests). Defaults to a `node:fs` reader that
|
|
97
|
+
* throws when the file is missing — a missing file is caught and
|
|
98
|
+
* negative-cached like any other read failure.
|
|
99
|
+
*/
|
|
100
|
+
readFile?: ReadFileSyncFn;
|
|
101
|
+
/**
|
|
102
|
+
* Label woven into the stderr warning on a missing/invalid file (e.g.
|
|
103
|
+
* `'redfin-mcp'`). Defaults to the env-var name.
|
|
104
|
+
*/
|
|
105
|
+
label?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Build a cached, negative-cached loader for an env-named JSON string-array
|
|
109
|
+
* file — the `loadCommunities` + `DEFAULT_COMMUNITIES` pattern quadruplicated
|
|
110
|
+
* across redfin/zillow/homes/onehome (only the env var differs:
|
|
111
|
+
* `REDFIN_/ZILLOW_/HOMES_/ONEHOME_COMMUNITIES_FILE`).
|
|
112
|
+
*
|
|
113
|
+
* The returned function:
|
|
114
|
+
* - reads the file path from `envVar` via {@link readEnvVar} (placeholder
|
|
115
|
+
* hardening), returning `defaults` when unset (and clearing any cache),
|
|
116
|
+
* - parses the file as a JSON array of strings; on success caches and returns
|
|
117
|
+
* it (keyed by the env-var value, so a path change re-reads),
|
|
118
|
+
* - on a missing / unreadable file, invalid JSON, or non-string-array,
|
|
119
|
+
* logs a single stderr warning and **negative-caches** — it returns
|
|
120
|
+
* `defaults` without re-reading on subsequent calls for the same path,
|
|
121
|
+
* - never re-reads a successfully-cached file.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* const loadCommunities = createCachedJsonArrayLoader({
|
|
125
|
+
* envVar: 'REDFIN_COMMUNITIES_FILE',
|
|
126
|
+
* defaults: DEFAULT_COMMUNITIES,
|
|
127
|
+
* label: 'redfin-mcp',
|
|
128
|
+
* });
|
|
129
|
+
*/
|
|
130
|
+
export declare function createCachedJsonArrayLoader(opts: CachedJsonArrayLoaderOptions): () => string[];
|
|
65
131
|
/** Options for {@link loadDotenvSafely}. */
|
|
66
132
|
export interface LoadDotenvOptions {
|
|
67
133
|
/** Path to the `.env` file. Defaults to dotenv's own resolution (CWD). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAIA,+DAA+D;AAC/D,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE3D,iDAAiD;AACjD,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,MAAM,GAAG,SAAS,CAerF;AAED,yCAAyC;AACzC,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAO/E;AAED,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAKD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAQjF;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ5C;AAED,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,GAAG,CAAC,EAAE,SAAS,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,MAAM,CAShG;AAED,2EAA2E;AAC3E,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAEtD,uDAAuD;AACvD,MAAM,WAAW,4BAA4B;IAC3C,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM,MAAM,EAAE,CAoD9F;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBrF"}
|
package/dist/config/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
1
2
|
import { homedir } from 'node:os';
|
|
2
3
|
import { isAbsolute, join, resolve } from 'node:path';
|
|
3
4
|
/**
|
|
@@ -93,6 +94,102 @@ export function expandPath(p) {
|
|
|
93
94
|
}
|
|
94
95
|
return isAbsolute(expanded) ? expanded : resolve(expanded);
|
|
95
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Read a TCP port from an environment variable, hardened the way
|
|
99
|
+
* {@link readEnvVar} hardens any var (trim, treat blank / `'undefined'` /
|
|
100
|
+
* `'null'` / unsubstituted `${...}` placeholder as unset) PLUS numeric
|
|
101
|
+
* validation: the value must parse to an integer in the valid port range
|
|
102
|
+
* `1..65535`.
|
|
103
|
+
*
|
|
104
|
+
* Returns `fallback` when the variable is unset, a placeholder, non-numeric, or
|
|
105
|
+
* out of range. Consolidates the bare `Number(process.env.X_WS_PORT)` pattern
|
|
106
|
+
* across compass/redfin/homes/musescore, which yields `NaN` on an unexpanded
|
|
107
|
+
* `${...}` placeholder or junk and then hands `NaN` to the server.
|
|
108
|
+
*
|
|
109
|
+
* @example readPortEnv('REDFIN_WS_PORT', 37149)
|
|
110
|
+
*/
|
|
111
|
+
export function readPortEnv(key, fallback, opts = {}) {
|
|
112
|
+
const raw = readEnvVar(key, { env: opts.env });
|
|
113
|
+
if (raw === undefined)
|
|
114
|
+
return fallback;
|
|
115
|
+
// Strict integer parse: reject `12abc`, `1.5`, `0x10`, etc. that `Number`
|
|
116
|
+
// would otherwise coerce or accept.
|
|
117
|
+
if (!/^\d+$/.test(raw))
|
|
118
|
+
return fallback;
|
|
119
|
+
const port = Number(raw);
|
|
120
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
121
|
+
return fallback;
|
|
122
|
+
return port;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Build a cached, negative-cached loader for an env-named JSON string-array
|
|
126
|
+
* file — the `loadCommunities` + `DEFAULT_COMMUNITIES` pattern quadruplicated
|
|
127
|
+
* across redfin/zillow/homes/onehome (only the env var differs:
|
|
128
|
+
* `REDFIN_/ZILLOW_/HOMES_/ONEHOME_COMMUNITIES_FILE`).
|
|
129
|
+
*
|
|
130
|
+
* The returned function:
|
|
131
|
+
* - reads the file path from `envVar` via {@link readEnvVar} (placeholder
|
|
132
|
+
* hardening), returning `defaults` when unset (and clearing any cache),
|
|
133
|
+
* - parses the file as a JSON array of strings; on success caches and returns
|
|
134
|
+
* it (keyed by the env-var value, so a path change re-reads),
|
|
135
|
+
* - on a missing / unreadable file, invalid JSON, or non-string-array,
|
|
136
|
+
* logs a single stderr warning and **negative-caches** — it returns
|
|
137
|
+
* `defaults` without re-reading on subsequent calls for the same path,
|
|
138
|
+
* - never re-reads a successfully-cached file.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* const loadCommunities = createCachedJsonArrayLoader({
|
|
142
|
+
* envVar: 'REDFIN_COMMUNITIES_FILE',
|
|
143
|
+
* defaults: DEFAULT_COMMUNITIES,
|
|
144
|
+
* label: 'redfin-mcp',
|
|
145
|
+
* });
|
|
146
|
+
*/
|
|
147
|
+
export function createCachedJsonArrayLoader(opts) {
|
|
148
|
+
const env = opts.env ?? process.env;
|
|
149
|
+
const label = opts.label ?? opts.envVar;
|
|
150
|
+
// Default reader: `node:fs#readFileSync` (utf8). A missing file throws, which
|
|
151
|
+
// the catch below turns into a negative-cached fallback — mirroring redfin's
|
|
152
|
+
// original `existsSync` guard without the extra stat.
|
|
153
|
+
const readFile = opts.readFile ?? ((path) => readFileSync(path, 'utf8'));
|
|
154
|
+
let cached = null;
|
|
155
|
+
// Path the cache (positive OR negative) is keyed to. A negative cache is
|
|
156
|
+
// `cached === null && cachedPath === <path>`: we resolved that path to
|
|
157
|
+
// defaults and won't re-read it.
|
|
158
|
+
let cachedPath = null;
|
|
159
|
+
return function load() {
|
|
160
|
+
const path = readEnvVar(opts.envVar, { env });
|
|
161
|
+
if (!path) {
|
|
162
|
+
// Unset: never cache (the var may be set later) and return defaults.
|
|
163
|
+
cached = null;
|
|
164
|
+
cachedPath = null;
|
|
165
|
+
return opts.defaults;
|
|
166
|
+
}
|
|
167
|
+
if (cachedPath === path) {
|
|
168
|
+
// Same path as last time — positive cache (return it) or negative cache
|
|
169
|
+
// (cached === null → return defaults without re-reading).
|
|
170
|
+
return cached ?? opts.defaults;
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const raw = readFile(path);
|
|
174
|
+
const parsed = JSON.parse(raw);
|
|
175
|
+
if (!Array.isArray(parsed) || !parsed.every((s) => typeof s === 'string')) {
|
|
176
|
+
console.error(`[${label}] ${opts.envVar}="${path}" must be a JSON string array — falling back to defaults.`);
|
|
177
|
+
cached = null;
|
|
178
|
+
cachedPath = path; // negative-cache this path
|
|
179
|
+
return opts.defaults;
|
|
180
|
+
}
|
|
181
|
+
cached = parsed;
|
|
182
|
+
cachedPath = path;
|
|
183
|
+
return cached;
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
console.error(`[${label}] failed to load ${opts.envVar}="${path}": ${err instanceof Error ? err.message : String(err)} — falling back to defaults.`);
|
|
187
|
+
cached = null;
|
|
188
|
+
cachedPath = path; // negative-cache this path
|
|
189
|
+
return opts.defaults;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
96
193
|
/**
|
|
97
194
|
* Load a `.env` file for local development, swallowing any failure.
|
|
98
195
|
*
|
package/dist/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAatD;;;;;;;;GAQG;AACH,MAAM,cAAc,GAAG,eAAe,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,OAAuB,EAAE;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,IACE,OAAO,CAAC,MAAM,GAAG,CAAC;YAClB,OAAO,KAAK,WAAW;YACvB,OAAO,KAAK,MAAM;YAClB,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAC7B,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC;AACtB,CAAC;AAUD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,OAA0B,EAAE;IACrE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACjD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,yCAAyC,GAAG,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAUD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AACxD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,OAA4B,EAAE;IACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC;IACvC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/C,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACvC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAChC,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACd,QAAQ,GAAG,OAAO,EAAE,CAAC;IACvB,CAAC;SAAM,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAQD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,QAAgB,EAAE,OAA2B,EAAE;IACtF,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/C,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACvC,0EAA0E;IAC1E,oCAAoC;IACpC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK;QAAE,OAAO,QAAQ,CAAC;IACzE,OAAO,IAAI,CAAC;AACd,CAAC;AA0BD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAAkC;IAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;IACxC,8EAA8E;IAC9E,6EAA6E;IAC7E,sDAAsD;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAEzF,IAAI,MAAM,GAAoB,IAAI,CAAC;IACnC,yEAAyE;IACzE,uEAAuE;IACvE,iCAAiC;IACjC,IAAI,UAAU,GAAkB,IAAI,CAAC;IAErC,OAAO,SAAS,IAAI;QAClB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,qEAAqE;YACrE,MAAM,GAAG,IAAI,CAAC;YACd,UAAU,GAAG,IAAI,CAAC;YAClB,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QACD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,wEAAwE;YACxE,0DAA0D;YAC1D,OAAO,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC;QACjC,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;gBAC1E,OAAO,CAAC,KAAK,CACX,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,KAAK,IAAI,2DAA2D,CAC9F,CAAC;gBACF,MAAM,GAAG,IAAI,CAAC;gBACd,UAAU,GAAG,IAAI,CAAC,CAAC,2BAA2B;gBAC9C,OAAO,IAAI,CAAC,QAAQ,CAAC;YACvB,CAAC;YACD,MAAM,GAAG,MAAM,CAAC;YAChB,UAAU,GAAG,IAAI,CAAC;YAClB,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,IAAI,KAAK,oBAAoB,IAAI,CAAC,MAAM,KAAK,IAAI,MAC/C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,8BAA8B,CAC/B,CAAC;YACF,MAAM,GAAG,IAAI,CAAC;YACd,UAAU,GAAG,IAAI,CAAC,CAAC,2BAA2B;YAC9C,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAaD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAA0B,EAAE;IACjE,IAAI,CAAC;QAUH,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,QAAkB,CAAC,CAE/D,CAAC;QACF,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;YAChC,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -69,6 +69,18 @@ export declare class ModeMismatchError extends McpToolError {
|
|
|
69
69
|
export declare function createHelpfulError(message: string, opts?: {
|
|
70
70
|
hint?: string;
|
|
71
71
|
}): McpToolError;
|
|
72
|
+
/**
|
|
73
|
+
* Redact secrets that commonly leak into upstream error bodies before the text
|
|
74
|
+
* is surfaced to a client: `Bearer <token>` / `Authorization: Basic <…>` headers,
|
|
75
|
+
* `Cookie:` / `Set-Cookie:` header values (cookie names stay visible), standalone
|
|
76
|
+
* JWTs, well-known API-key shapes (OpenAI/Anthropic `sk-…`, GitHub `ghp_…`,
|
|
77
|
+
* Slack `xox?-…`, Google `AIza…`, AWS `AKIA…`, `whsec_…`), and secret-bearing
|
|
78
|
+
* URL query params (`access_token`, `api_key`, `token`, `key`, `sig`, …).
|
|
79
|
+
*
|
|
80
|
+
* Exported so fleet repos can redact custom strings (log lines, debug payloads)
|
|
81
|
+
* without taking on {@link truncateErrorMessage}'s length cap.
|
|
82
|
+
*/
|
|
83
|
+
export declare function redactSecrets(text: string): string;
|
|
72
84
|
/**
|
|
73
85
|
* Redact secrets, then cap an (upstream) error string at `max` characters,
|
|
74
86
|
* appending a `… [truncated]` marker when clipped.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,qFAAqF;AACrF,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,qDAAqD;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAOvE;AAED;;;GAGG;AACH,qBAAa,4BAA6B,SAAQ,YAAY;gBAChD,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAUlD;AAED;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAE,MAAuC;CASrF;AAED,uEAAuE;AACvE,qBAAa,cAAe,SAAQ,YAAY;IAC9C,8DAA8D;IAC9D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM;CAOxD;AAED,kFAAkF;AAClF,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,mDAAmD;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAQ7C;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IAE/C,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAFf,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM;CAS3B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAE1F;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,qFAAqF;AACrF,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,+EAA+E;AAC/E,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,qDAAqD;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAOvE;AAED;;;GAGG;AACH,qBAAa,4BAA6B,SAAQ,YAAY;gBAChD,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAUlD;AAED;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;gBAEvB,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAE,MAAuC;CASrF;AAED,uEAAuE;AACvE,qBAAa,cAAe,SAAQ,YAAY;IAC9C,8DAA8D;IAC9D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM;CAOxD;AAED,kFAAkF;AAClF,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,mDAAmD;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAQ7C;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,YAAY;IAE/C,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAFf,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM;CAS3B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAE1F;AAuCD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYlD;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAkC,GAAG,MAAM,CAKlG;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAG9C;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,YAAY,CAM1E"}
|