@dbx-tools/shared-core 0.6.48 → 0.6.50
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 +32 -0
- package/index.ts +3 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -1
- package/lib/src/pattern.d.ts +67 -0
- package/lib/src/pattern.js +129 -0
- package/lib/src/token.d.ts +14 -0
- package/lib/src/token.js +16 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/pattern.ts +148 -0
- package/src/token.ts +18 -1
package/README.md
CHANGED
|
@@ -261,6 +261,36 @@ const internal = cidr ? net.ipInCidr("10.1.2.3", cidr) : false;
|
|
|
261
261
|
`net.pathMatch()` compares path prefixes on segment boundaries. IP/CIDR helpers
|
|
262
262
|
parse IPv4 and IPv6 into a shared bigint comparison model.
|
|
263
263
|
|
|
264
|
+
## Allow-List Patterns
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
// One matcher from a config array OR a delimited env string.
|
|
268
|
+
const forwardable = pattern.toPatternMatcher(["x-mastra-*", "/^x-trace-/", "x-tenant"]);
|
|
269
|
+
|
|
270
|
+
forwardable("x-mastra-model"); // true (glob)
|
|
271
|
+
forwardable("x-trace-parent"); // true (regex literal)
|
|
272
|
+
forwardable("x-tenant"); // true (literal, whole-string)
|
|
273
|
+
forwardable("x-forwarded-user"); // false
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Every configurable allow-list in this repo takes the same three shapes, so the
|
|
277
|
+
compilation lives here once: a `/regex/` literal (with optional flags), a
|
|
278
|
+
shell-style glob (`*`, `?`, anchored at both ends, all other characters escaped),
|
|
279
|
+
or a literal compared whole-string. Matching is case-insensitive by default -
|
|
280
|
+
what HTTP header names and email addresses both want - and `caseSensitive` opts
|
|
281
|
+
out.
|
|
282
|
+
|
|
283
|
+
An invalid regex is skipped with a warning instead of throwing, so one bad
|
|
284
|
+
config entry cannot stop a process from starting. No usable patterns yields a
|
|
285
|
+
matcher that always returns `false`; a caller that reads "no patterns" as "permit
|
|
286
|
+
everything" must say so itself. The result is a `predicate`, so it composes with
|
|
287
|
+
`.and()` / `.or()` / `.negate()`.
|
|
288
|
+
|
|
289
|
+
Reach for [`@dbx-tools/path`](../../node/path)'s `toPathMatcher` instead when
|
|
290
|
+
matching a filesystem path or URL path, where `/` is a segment boundary and `**`
|
|
291
|
+
is meaningful - that one is `minimatch`-backed. This module is deliberately
|
|
292
|
+
dependency-free so it stays usable in a browser bundle.
|
|
293
|
+
|
|
264
294
|
## Token Claims
|
|
265
295
|
|
|
266
296
|
```ts
|
|
@@ -312,6 +342,8 @@ without paying formatting cost when disabled.
|
|
|
312
342
|
- `env` - config-over-environment resolution: strings, booleans, positive
|
|
313
343
|
numbers/integers, and lists, with env-name fallback chains.
|
|
314
344
|
- `predicate` - composable boolean/type predicates.
|
|
345
|
+
- `pattern` - literal / glob / `/regex/` allow-list matching compiled to a
|
|
346
|
+
predicate.
|
|
315
347
|
- `http` - header iteration, cookie parsing, and fetch error creation.
|
|
316
348
|
- `execution` - direct executor fallback, cancellation merging, and result unwrapping.
|
|
317
349
|
- `net` - URL building, email parsing, path matching, IP/CIDR helpers.
|
package/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * as json from "./src/json.ts";
|
|
|
14
14
|
export * as log from "./src/log.ts";
|
|
15
15
|
export * as net from "./src/net.ts";
|
|
16
16
|
export * as object from "./src/object.ts";
|
|
17
|
+
export * as pattern from "./src/pattern.ts";
|
|
17
18
|
export * as predicate from "./src/predicate.ts";
|
|
18
19
|
export * as string from "./src/string.ts";
|
|
19
20
|
export * as token from "./src/token.ts";
|
|
@@ -28,5 +29,7 @@ export type { HeaderLike } from "./src/http.ts";
|
|
|
28
29
|
export type { LogLevel, Logger } from "./src/log.ts";
|
|
29
30
|
export type { UrlLike, IpVersion, ParsedIp, Cidr, UrlBuilder, ParseEmailsOptions } from "./src/net.ts";
|
|
30
31
|
export type { Sequence, Container, Collection, OneOrMany, NameLike, NonFunctionKeys, DeepEqualComparator } from "./src/object.ts";
|
|
32
|
+
export type { PatternOptions } from "./src/pattern.ts";
|
|
31
33
|
export type { PredicateFunction, TypePredicateFunction, PredicateInput, Predicate } from "./src/predicate.ts";
|
|
32
34
|
export type { TokenizeOptions, KeyOptions, IdentifierOptions, Description } from "./src/string.ts";
|
|
35
|
+
export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER } from "./src/token.ts";
|
package/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * as json from "./src/json.ts";
|
|
|
10
10
|
export * as log from "./src/log.ts";
|
|
11
11
|
export * as net from "./src/net.ts";
|
|
12
12
|
export * as object from "./src/object.ts";
|
|
13
|
+
export * as pattern from "./src/pattern.ts";
|
|
13
14
|
export * as predicate from "./src/predicate.ts";
|
|
14
15
|
export * as string from "./src/string.ts";
|
|
15
16
|
export * as token from "./src/token.ts";
|
|
@@ -24,5 +25,7 @@ export type { HeaderLike } from "./src/http.ts";
|
|
|
24
25
|
export type { LogLevel, Logger } from "./src/log.ts";
|
|
25
26
|
export type { UrlLike, IpVersion, ParsedIp, Cidr, UrlBuilder, ParseEmailsOptions } from "./src/net.ts";
|
|
26
27
|
export type { Sequence, Container, Collection, OneOrMany, NameLike, NonFunctionKeys, DeepEqualComparator } from "./src/object.ts";
|
|
28
|
+
export type { PatternOptions } from "./src/pattern.ts";
|
|
27
29
|
export type { PredicateFunction, TypePredicateFunction, PredicateInput, Predicate } from "./src/predicate.ts";
|
|
28
30
|
export type { TokenizeOptions, KeyOptions, IdentifierOptions, Description } from "./src/string.ts";
|
|
31
|
+
export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER } from "./src/token.ts";
|
package/lib/index.js
CHANGED
|
@@ -13,8 +13,10 @@ export * as json from "./src/json.js";
|
|
|
13
13
|
export * as log from "./src/log.js";
|
|
14
14
|
export * as net from "./src/net.js";
|
|
15
15
|
export * as object from "./src/object.js";
|
|
16
|
+
export * as pattern from "./src/pattern.js";
|
|
16
17
|
export * as predicate from "./src/predicate.js";
|
|
17
18
|
export * as string from "./src/string.js";
|
|
18
19
|
export * as token from "./src/token.js";
|
|
19
20
|
export { DEFAULT_BRAND_ASSETS, BrandAssetSetSchema, BrandColorsSchema, BrandVoiceSchema, BrandContextSchema, defaultBrandContext } from "./src/brand.js";
|
|
20
|
-
|
|
21
|
+
export { ACCESS_TOKEN_HEADER, USER_ID_HEADER, USER_EMAIL_HEADER } from "./src/token.js";
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxLQUFLLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUM7QUFDcEMsT0FBTyxLQUFLLEtBQUssTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QyxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxjQUFjLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUM7QUFDcEMsT0FBTyxLQUFLLEdBQUcsTUFBTSxjQUFjLENBQUM7QUFDcEMsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBRXhDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxtQkFBbUIsRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxrQkFBa0IsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBYXpKLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCAqIGFzIGFzeW5jIGZyb20gXCIuL3NyYy9hc3luYy50c1wiO1xuZXhwb3J0ICogYXMgYnJhbmQgZnJvbSBcIi4vc3JjL2JyYW5kLnRzXCI7XG5leHBvcnQgKiBhcyBlbnYgZnJvbSBcIi4vc3JjL2Vudi50c1wiO1xuZXhwb3J0ICogYXMgZXJyb3IgZnJvbSBcIi4vc3JjL2Vycm9yLnRzXCI7XG5leHBvcnQgKiBhcyBleGVjdXRpb24gZnJvbSBcIi4vc3JjL2V4ZWN1dGlvbi50c1wiO1xuZXhwb3J0ICogYXMgZnVuY3Rpb25Nb2R1bGUgZnJvbSBcIi4vc3JjL2Z1bmN0aW9uLnRzXCI7XG5leHBvcnQgKiBhcyBoYXNoIGZyb20gXCIuL3NyYy9oYXNoLnRzXCI7XG5leHBvcnQgKiBhcyBodHRwIGZyb20gXCIuL3NyYy9odHRwLnRzXCI7XG5leHBvcnQgKiBhcyBqc29uIGZyb20gXCIuL3NyYy9qc29uLnRzXCI7XG5leHBvcnQgKiBhcyBsb2cgZnJvbSBcIi4vc3JjL2xvZy50c1wiO1xuZXhwb3J0ICogYXMgbmV0IGZyb20gXCIuL3NyYy9uZXQudHNcIjtcbmV4cG9ydCAqIGFzIG9iamVjdCBmcm9tIFwiLi9zcmMvb2JqZWN0LnRzXCI7XG5leHBvcnQgKiBhcyBwYXR0ZXJuIGZyb20gXCIuL3NyYy9wYXR0ZXJuLnRzXCI7XG5leHBvcnQgKiBhcyBwcmVkaWNhdGUgZnJvbSBcIi4vc3JjL3ByZWRpY2F0ZS50c1wiO1xuZXhwb3J0ICogYXMgc3RyaW5nIGZyb20gXCIuL3NyYy9zdHJpbmcudHNcIjtcbmV4cG9ydCAqIGFzIHRva2VuIGZyb20gXCIuL3NyYy90b2tlbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBQb2xsQ29udGV4dCwgUG9sbFByb2R1Y2VyLCBQb2xsT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9hc3luYy50c1wiO1xuZXhwb3J0IHsgREVGQVVMVF9CUkFORF9BU1NFVFMsIEJyYW5kQXNzZXRTZXRTY2hlbWEsIEJyYW5kQ29sb3JzU2NoZW1hLCBCcmFuZFZvaWNlU2NoZW1hLCBCcmFuZENvbnRleHRTY2hlbWEsIGRlZmF1bHRCcmFuZENvbnRleHQgfSBmcm9tIFwiLi9zcmMvYnJhbmQudHNcIjtcbmV4cG9ydCB0eXBlIHsgQnJhbmRDb250ZXh0LCBCcmFuZENvbnRleHRJbnB1dCwgQnJhbmRBc3NldFNldCB9IGZyb20gXCIuL3NyYy9icmFuZC50c1wiO1xuZXhwb3J0IHR5cGUgeyBFbnZLZXkgfSBmcm9tIFwiLi9zcmMvZW52LnRzXCI7XG5leHBvcnQgdHlwZSB7IEVycm9yQ29udGV4dCB9IGZyb20gXCIuL3NyYy9lcnJvci50c1wiO1xuZXhwb3J0IHR5cGUgeyBFeGVjdXRpb25SZXN1bHQsIEV4ZWN1dG9yLCBFeGVjdXRpb25GYWlsdXJlLCBSdW5PcHRpb25zIH0gZnJvbSBcIi4vc3JjL2V4ZWN1dGlvbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBNZW1vaXplT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9mdW5jdGlvbi50c1wiO1xuZXhwb3J0IHR5cGUgeyBIZWFkZXJMaWtlIH0gZnJvbSBcIi4vc3JjL2h0dHAudHNcIjtcbmV4cG9ydCB0eXBlIHsgTG9nTGV2ZWwsIExvZ2dlciB9IGZyb20gXCIuL3NyYy9sb2cudHNcIjtcbmV4cG9ydCB0eXBlIHsgVXJsTGlrZSwgSXBWZXJzaW9uLCBQYXJzZWRJcCwgQ2lkciwgVXJsQnVpbGRlciwgUGFyc2VFbWFpbHNPcHRpb25zIH0gZnJvbSBcIi4vc3JjL25ldC50c1wiO1xuZXhwb3J0IHR5cGUgeyBTZXF1ZW5jZSwgQ29udGFpbmVyLCBDb2xsZWN0aW9uLCBPbmVPck1hbnksIE5hbWVMaWtlLCBOb25GdW5jdGlvbktleXMsIERlZXBFcXVhbENvbXBhcmF0b3IgfSBmcm9tIFwiLi9zcmMvb2JqZWN0LnRzXCI7XG5leHBvcnQgdHlwZSB7IFBhdHRlcm5PcHRpb25zIH0gZnJvbSBcIi4vc3JjL3BhdHRlcm4udHNcIjtcbmV4cG9ydCB0eXBlIHsgUHJlZGljYXRlRnVuY3Rpb24sIFR5cGVQcmVkaWNhdGVGdW5jdGlvbiwgUHJlZGljYXRlSW5wdXQsIFByZWRpY2F0ZSB9IGZyb20gXCIuL3NyYy9wcmVkaWNhdGUudHNcIjtcbmV4cG9ydCB0eXBlIHsgVG9rZW5pemVPcHRpb25zLCBLZXlPcHRpb25zLCBJZGVudGlmaWVyT3B0aW9ucywgRGVzY3JpcHRpb24gfSBmcm9tIFwiLi9zcmMvc3RyaW5nLnRzXCI7XG5leHBvcnQgeyBBQ0NFU1NfVE9LRU5fSEVBREVSLCBVU0VSX0lEX0hFQURFUiwgVVNFUl9FTUFJTF9IRUFERVIgfSBmcm9tIFwiLi9zcmMvdG9rZW4udHNcIjtcbiJdfQ==
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Literal / glob / regex string matching, compiled to a composable
|
|
3
|
+
* {@link Predicate}.
|
|
4
|
+
*
|
|
5
|
+
* A configurable allow-list is the same shape everywhere in this repo: a list of
|
|
6
|
+
* patterns from a config field or an env var, where an operator reasonably
|
|
7
|
+
* expects to write a plain value, a `*` wildcard, or - when neither is enough -
|
|
8
|
+
* a real regex. Each consumer used to grow its own `globToRegExp` +
|
|
9
|
+
* `/pattern/flags` parser; this is that parser, once.
|
|
10
|
+
*
|
|
11
|
+
* Three shapes are recognized per entry, tried in order:
|
|
12
|
+
*
|
|
13
|
+
* - **regex** - wrapped in slashes (`/^x-mastra-/`, with optional trailing
|
|
14
|
+
* flags). Compiled as written. An invalid regex never matches: it is skipped
|
|
15
|
+
* with a warning rather than throwing, so one bad entry cannot take a process
|
|
16
|
+
* down at startup.
|
|
17
|
+
* - **glob** - contains `*` or `?` (`x-mastra-*`). Shell-style, anchored at both
|
|
18
|
+
* ends: `*` matches any run of characters, `?` exactly one.
|
|
19
|
+
* - **literal** - anything else. Whole-string equality.
|
|
20
|
+
*
|
|
21
|
+
* Matching is case-INSENSITIVE by default, which is what the callers want (HTTP
|
|
22
|
+
* header names and email addresses are both case-insensitive); pass
|
|
23
|
+
* `caseSensitive` to opt out. An empty pattern list matches NOTHING, so a
|
|
24
|
+
* caller that treats "no patterns" as "permit everything" must special-case it
|
|
25
|
+
* rather than relying on the matcher.
|
|
26
|
+
*
|
|
27
|
+
* Browser-safe: hand-compiled to `RegExp` with no glob dependency, so this stays
|
|
28
|
+
* usable from a client bundle. Node code that needs path-aware globbing
|
|
29
|
+
* (`/` as a segment boundary, `**`) wants `@dbx-tools/path`'s `toPathMatcher`
|
|
30
|
+
* instead - that one is `minimatch`-backed and understands path semantics.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const allowed = toPatternMatcher(["x-mastra-*", "/^x-trace-/"]);
|
|
34
|
+
* allowed("x-mastra-thread-id"); // true
|
|
35
|
+
* allowed("x-forwarded-user"); // false
|
|
36
|
+
*
|
|
37
|
+
* @module
|
|
38
|
+
*/
|
|
39
|
+
import * as predicate from "./predicate.ts";
|
|
40
|
+
/** Options for {@link toPattern} / {@link toPatternMatcher}. */
|
|
41
|
+
export interface PatternOptions {
|
|
42
|
+
/** Match case-sensitively. Default `false` (case-insensitive). */
|
|
43
|
+
caseSensitive?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Escape a string for literal use inside a `RegExp`. */
|
|
46
|
+
export declare function escapeRegExp(value: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Compile ONE pattern into a predicate, or `undefined` when the entry is empty
|
|
49
|
+
* or an unparseable regex literal.
|
|
50
|
+
*
|
|
51
|
+
* Callers that want a whole list should use {@link toPatternMatcher}; this is
|
|
52
|
+
* exported for the case where a consumer applies its own semantics to some
|
|
53
|
+
* shapes and only wants the glob/regex handling (the email gate's bare-domain
|
|
54
|
+
* shortcut, for one).
|
|
55
|
+
*/
|
|
56
|
+
export declare function toPattern(pattern: string, options?: PatternOptions): predicate.Predicate<string> | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Compile patterns into a single OR'd {@link Predicate}. Accepts the raw config
|
|
59
|
+
* shapes {@link parseList} does - an array, or one comma/whitespace-separated
|
|
60
|
+
* string - so a field and its env var need no separate handling.
|
|
61
|
+
*
|
|
62
|
+
* With no usable patterns the result always returns `false`.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* const forwardable = toPatternMatcher(process.env.TUNNEL_FORWARD_HEADERS);
|
|
66
|
+
*/
|
|
67
|
+
export declare function toPatternMatcher(patterns: string | readonly string[] | undefined | null, options?: PatternOptions): predicate.Predicate<string>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Literal / glob / regex string matching, compiled to a composable
|
|
3
|
+
* {@link Predicate}.
|
|
4
|
+
*
|
|
5
|
+
* A configurable allow-list is the same shape everywhere in this repo: a list of
|
|
6
|
+
* patterns from a config field or an env var, where an operator reasonably
|
|
7
|
+
* expects to write a plain value, a `*` wildcard, or - when neither is enough -
|
|
8
|
+
* a real regex. Each consumer used to grow its own `globToRegExp` +
|
|
9
|
+
* `/pattern/flags` parser; this is that parser, once.
|
|
10
|
+
*
|
|
11
|
+
* Three shapes are recognized per entry, tried in order:
|
|
12
|
+
*
|
|
13
|
+
* - **regex** - wrapped in slashes (`/^x-mastra-/`, with optional trailing
|
|
14
|
+
* flags). Compiled as written. An invalid regex never matches: it is skipped
|
|
15
|
+
* with a warning rather than throwing, so one bad entry cannot take a process
|
|
16
|
+
* down at startup.
|
|
17
|
+
* - **glob** - contains `*` or `?` (`x-mastra-*`). Shell-style, anchored at both
|
|
18
|
+
* ends: `*` matches any run of characters, `?` exactly one.
|
|
19
|
+
* - **literal** - anything else. Whole-string equality.
|
|
20
|
+
*
|
|
21
|
+
* Matching is case-INSENSITIVE by default, which is what the callers want (HTTP
|
|
22
|
+
* header names and email addresses are both case-insensitive); pass
|
|
23
|
+
* `caseSensitive` to opt out. An empty pattern list matches NOTHING, so a
|
|
24
|
+
* caller that treats "no patterns" as "permit everything" must special-case it
|
|
25
|
+
* rather than relying on the matcher.
|
|
26
|
+
*
|
|
27
|
+
* Browser-safe: hand-compiled to `RegExp` with no glob dependency, so this stays
|
|
28
|
+
* usable from a client bundle. Node code that needs path-aware globbing
|
|
29
|
+
* (`/` as a segment boundary, `**`) wants `@dbx-tools/path`'s `toPathMatcher`
|
|
30
|
+
* instead - that one is `minimatch`-backed and understands path semantics.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const allowed = toPatternMatcher(["x-mastra-*", "/^x-trace-/"]);
|
|
34
|
+
* allowed("x-mastra-thread-id"); // true
|
|
35
|
+
* allowed("x-forwarded-user"); // false
|
|
36
|
+
*
|
|
37
|
+
* @module
|
|
38
|
+
*/
|
|
39
|
+
import { logger } from "./log.js";
|
|
40
|
+
import * as predicate from "./predicate.js";
|
|
41
|
+
import { parseList } from "./string.js";
|
|
42
|
+
const log = logger("shared/pattern");
|
|
43
|
+
/** Escape a string for literal use inside a `RegExp`. */
|
|
44
|
+
export function escapeRegExp(value) {
|
|
45
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
46
|
+
}
|
|
47
|
+
/** True when `pattern` is a `/.../flags` regex literal. */
|
|
48
|
+
function isRegexLiteral(pattern) {
|
|
49
|
+
return pattern.length > 1 && pattern.startsWith("/") && /\/[a-z]*$/i.test(pattern);
|
|
50
|
+
}
|
|
51
|
+
/** True when `pattern` contains a glob wildcard. */
|
|
52
|
+
function isGlob(pattern) {
|
|
53
|
+
return pattern.includes("*") || pattern.includes("?");
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Compile a `/pattern/flags` literal, or `undefined` when it is malformed or
|
|
57
|
+
* the body is not a valid regex.
|
|
58
|
+
*/
|
|
59
|
+
function compileRegexLiteral(pattern, caseSensitive) {
|
|
60
|
+
const parsed = /^\/(.+)\/([a-z]*)$/is.exec(pattern);
|
|
61
|
+
if (!parsed)
|
|
62
|
+
return undefined;
|
|
63
|
+
const body = parsed[1];
|
|
64
|
+
const flags = parsed[2];
|
|
65
|
+
try {
|
|
66
|
+
return new RegExp(body, caseSensitive || flags.includes("i") ? flags : `${flags}i`);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
log.warn("ignoring invalid regex pattern", { pattern, error });
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Compile a shell-style glob (`*`, `?`) into an anchored `RegExp`. Every other
|
|
75
|
+
* character is escaped, so a glob can safely contain regex metacharacters
|
|
76
|
+
* (`x-app.*` matches a literal dot followed by anything).
|
|
77
|
+
*/
|
|
78
|
+
function compileGlob(pattern, caseSensitive) {
|
|
79
|
+
const body = pattern
|
|
80
|
+
.split(/([*?])/)
|
|
81
|
+
.map((part) => (part === "*" ? ".*" : part === "?" ? "." : escapeRegExp(part)))
|
|
82
|
+
.join("");
|
|
83
|
+
return new RegExp(`^${body}$`, caseSensitive ? "" : "i");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Compile ONE pattern into a predicate, or `undefined` when the entry is empty
|
|
87
|
+
* or an unparseable regex literal.
|
|
88
|
+
*
|
|
89
|
+
* Callers that want a whole list should use {@link toPatternMatcher}; this is
|
|
90
|
+
* exported for the case where a consumer applies its own semantics to some
|
|
91
|
+
* shapes and only wants the glob/regex handling (the email gate's bare-domain
|
|
92
|
+
* shortcut, for one).
|
|
93
|
+
*/
|
|
94
|
+
export function toPattern(pattern, options = {}) {
|
|
95
|
+
const trimmed = pattern.trim();
|
|
96
|
+
if (!trimmed)
|
|
97
|
+
return undefined;
|
|
98
|
+
const caseSensitive = options.caseSensitive ?? false;
|
|
99
|
+
if (isRegexLiteral(trimmed)) {
|
|
100
|
+
const compiled = compileRegexLiteral(trimmed, caseSensitive);
|
|
101
|
+
return compiled && predicate.create((value) => compiled.test(value));
|
|
102
|
+
}
|
|
103
|
+
if (isGlob(trimmed)) {
|
|
104
|
+
const compiled = compileGlob(trimmed, caseSensitive);
|
|
105
|
+
return predicate.create((value) => compiled.test(value));
|
|
106
|
+
}
|
|
107
|
+
// Literal: whole-string equality.
|
|
108
|
+
const expected = caseSensitive ? trimmed : trimmed.toLowerCase();
|
|
109
|
+
return predicate.create((value) => caseSensitive ? value === expected : value.toLowerCase() === expected);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Compile patterns into a single OR'd {@link Predicate}. Accepts the raw config
|
|
113
|
+
* shapes {@link parseList} does - an array, or one comma/whitespace-separated
|
|
114
|
+
* string - so a field and its env var need no separate handling.
|
|
115
|
+
*
|
|
116
|
+
* With no usable patterns the result always returns `false`.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* const forwardable = toPatternMatcher(process.env.TUNNEL_FORWARD_HEADERS);
|
|
120
|
+
*/
|
|
121
|
+
export function toPatternMatcher(patterns, options = {}) {
|
|
122
|
+
const compiled = parseList(patterns)
|
|
123
|
+
.map((pattern) => toPattern(pattern, options))
|
|
124
|
+
.filter((value) => value !== undefined);
|
|
125
|
+
if (compiled.length === 0)
|
|
126
|
+
return predicate.create(() => false);
|
|
127
|
+
return compiled.slice(1).reduce((acc, next) => acc.or(next), compiled[0]);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0dGVybi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXR0ZXJuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUNHO0FBRUgsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNsQyxPQUFPLEtBQUssU0FBUyxNQUFNLGdCQUFnQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFeEMsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFRckMseURBQXlEO0FBQ3pELE1BQU0sVUFBVSxZQUFZLENBQUMsS0FBYTtJQUN4QyxPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDdEQsQ0FBQztBQUVELDJEQUEyRDtBQUMzRCxTQUFTLGNBQWMsQ0FBQyxPQUFlO0lBQ3JDLE9BQU8sT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3JGLENBQUM7QUFFRCxvREFBb0Q7QUFDcEQsU0FBUyxNQUFNLENBQUMsT0FBZTtJQUM3QixPQUFPLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN4RCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxPQUFlLEVBQUUsYUFBc0I7SUFDbEUsTUFBTSxNQUFNLEdBQUcsc0JBQXNCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3BELElBQUksQ0FBQyxNQUFNO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDOUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxD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RSxFQUFFLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztTQUM3QyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQXdDLEVBQUUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUM7SUFDaEYsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQyxNQUFNLENBQVMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDeEUsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUM7QUFDN0UsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGl0ZXJhbCAvIGdsb2IgLyByZWdleCBzdHJpbmcgbWF0Y2hpbmcsIGNvbXBpbGVkIHRvIGEgY29tcG9zYWJsZVxuICoge0BsaW5rIFByZWRpY2F0ZX0uXG4gKlxuICogQSBjb25maWd1cmFibGUgYWxsb3ctbGlzdCBpcyB0aGUgc2FtZSBzaGFwZSBldmVyeXdoZXJlIGluIHRoaXMgcmVwbzogYSBsaXN0IG9mXG4gKiBwYXR0ZXJucyBmcm9tIGEgY29uZmlnIGZpZWxkIG9yIGFuIGVudiB2YXIsIHdoZXJlIGFuIG9wZXJhdG9yIHJlYXNvbmFibHlcbiAqIGV4cGVjdHMgdG8gd3JpdGUgYSBwbGFpbiB2YWx1ZSwgYSBgKmAgd2lsZGNhcmQsIG9yIC0gd2hlbiBuZWl0aGVyIGlzIGVub3VnaCAtXG4gKiBhIHJlYWwgcmVnZXguIEVhY2ggY29uc3VtZXIgdXNlZCB0byBncm93IGl0cyBvd24gYGdsb2JUb1JlZ0V4cGAgK1xuICogYC9wYXR0ZXJuL2ZsYWdzYCBwYXJzZXI7IHRoaXMgaXMgdGhhdCBwYXJzZXIsIG9uY2UuXG4gKlxuICogVGhyZWUgc2hhcGVzIGFyZSByZWNvZ25pemVkIHBlciBlbnRyeSwgdHJpZWQgaW4gb3JkZXI6XG4gKlxuICogLSAqKnJlZ2V4KiogLSB3cmFwcGVkIGluIHNsYXNoZXMgKGAvXngtbWFzdHJhLS9gLCB3aXRoIG9wdGlvbmFsIHRyYWlsaW5nXG4gKiAgIGZsYWdzKS4gQ29tcGlsZWQgYXMgd3JpdHRlbi4gQW4gaW52YWxpZCByZWdleCBuZXZlciBtYXRjaGVzOiBpdCBpcyBza2lwcGVkXG4gKiAgIHdpdGggYSB3YXJuaW5nIHJhdGhlciB0aGFuIHRocm93aW5nLCBzbyBvbmUgYmFkIGVudHJ5IGNhbm5vdCB0YWtlIGEgcHJvY2Vzc1xuICogICBkb3duIGF0IHN0YXJ0dXAuXG4gKiAtICoqZ2xvYioqIC0gY29udGFpbnMgYCpgIG9yIGA/YCAoYHgtbWFzdHJhLSpgKS4gU2hlbGwtc3R5bGUsIGFuY2hvcmVkIGF0IGJvdGhcbiAqICAgZW5kczogYCpgIG1hdGNoZXMgYW55IHJ1biBvZiBjaGFyYWN0ZXJzLCBgP2AgZXhhY3RseSBvbmUuXG4gKiAtICoqbGl0ZXJhbCoqIC0gYW55dGhpbmcgZWxzZS4gV2hvbGUtc3RyaW5nIGVxdWFsaXR5LlxuICpcbiAqIE1hdGNoaW5nIGlzIGNhc2UtSU5TRU5TSVRJVkUgYnkgZGVmYXVsdCwgd2hpY2ggaXMgd2hhdCB0aGUgY2FsbGVycyB3YW50IChIVFRQXG4gKiBoZWFkZXIgbmFtZXMgYW5kIGVtYWlsIGFkZHJlc3NlcyBhcmUgYm90aCBjYXNlLWluc2Vuc2l0aXZlKTsgcGFzc1xuICogYGNhc2VTZW5zaXRpdmVgIHRvIG9wdCBvdXQuIEFuIGVtcHR5IHBhdHRlcm4gbGlzdCBtYXRjaGVzIE5PVEhJTkcsIHNvIGFcbiAqIGNhbGxlciB0aGF0IHRyZWF0cyBcIm5vIHBhdHRlcm5zXCIgYXMgXCJwZXJtaXQgZXZlcnl0aGluZ1wiIG11c3Qgc3BlY2lhbC1jYXNlIGl0XG4gKiByYXRoZXIgdGhhbiByZWx5aW5nIG9uIHRoZSBtYXRjaGVyLlxuICpcbiAqIEJyb3dzZXItc2FmZTogaGFuZC1jb21waWxlZCB0byBgUmVnRXhwYCB3aXRoIG5vIGdsb2IgZGVwZW5kZW5jeSwgc28gdGhpcyBzdGF5c1xuICogdXNhYmxlIGZyb20gYSBjbGllbnQgYnVuZGxlLiBOb2RlIGNvZGUgdGhhdCBuZWVkcyBwYXRoLWF3YXJlIGdsb2JiaW5nXG4gKiAoYC9gIGFzIGEgc2VnbWVudCBib3VuZGFyeSwgYCoqYCkgd2FudHMgYEBkYngtdG9vbHMvcGF0aGAncyBgdG9QYXRoTWF0Y2hlcmBcbiAqIGluc3RlYWQgLSB0aGF0IG9uZSBpcyBgbWluaW1hdGNoYC1iYWNrZWQgYW5kIHVuZGVyc3RhbmRzIHBhdGggc2VtYW50aWNzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBjb25zdCBhbGxvd2VkID0gdG9QYXR0ZXJuTWF0Y2hlcihbXCJ4LW1hc3RyYS0qXCIsIFwiL154LXRyYWNlLS9cIl0pO1xuICogYWxsb3dlZChcIngtbWFzdHJhLXRocmVhZC1pZFwiKTsgLy8gdHJ1ZVxuICogYWxsb3dlZChcIngtZm9yd2FyZGVkLXVzZXJcIik7ICAgLy8gZmFsc2VcbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nLnRzXCI7XG5pbXBvcnQgKiBhcyBwcmVkaWNhdGUgZnJvbSBcIi4vcHJlZGljYXRlLnRzXCI7XG5pbXBvcnQgeyBwYXJzZUxpc3QgfSBmcm9tIFwiLi9zdHJpbmcudHNcIjtcblxuY29uc3QgbG9nID0gbG9nZ2VyKFwic2hhcmVkL3BhdHRlcm5cIik7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgdG9QYXR0ZXJufSAvIHtAbGluayB0b1BhdHRlcm5NYXRjaGVyfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGF0dGVybk9wdGlvbnMge1xuICAvKiogTWF0Y2ggY2FzZS1zZW5zaXRpdmVseS4gRGVmYXVsdCBgZmFsc2VgIChjYXNlLWluc2Vuc2l0aXZlKS4gKi9cbiAgY2FzZVNlbnNpdGl2ZT86IGJvb2xlYW47XG59XG5cbi8qKiBFc2NhcGUgYSBzdHJpbmcgZm9yIGxpdGVyYWwgdXNlIGluc2lkZSBhIGBSZWdFeHBgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHZhbHVlLnJlcGxhY2UoL1suKis/XiR7fSgpfFtcXF1cXFxcXS9nLCBcIlxcXFwkJlwiKTtcbn1cblxuLyoqIFRydWUgd2hlbiBgcGF0dGVybmAgaXMgYSBgLy4uLi9mbGFnc2AgcmVnZXggbGl0ZXJhbC4gKi9cbmZ1bmN0aW9uIGlzUmVnZXhMaXRlcmFsKHBhdHRlcm46IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gcGF0dGVybi5sZW5ndGggPiAxICYmIHBhdHRlcm4uc3RhcnRzV2l0aChcIi9cIikgJiYgL1xcL1thLXpdKiQvaS50ZXN0KHBhdHRlcm4pO1xufVxuXG4vKiogVHJ1ZSB3aGVuIGBwYXR0ZXJuYCBjb250YWlucyBhIGdsb2Igd2lsZGNhcmQuICovXG5mdW5jdGlvbiBpc0dsb2IocGF0dGVybjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBwYXR0ZXJuLmluY2x1ZGVzKFwiKlwiKSB8fCBwYXR0ZXJuLmluY2x1ZGVzKFwiP1wiKTtcbn1cblxuLyoqXG4gKiBDb21waWxlIGEgYC9wYXR0ZXJuL2ZsYWdzYCBsaXRlcmFsLCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGlzIG1hbGZvcm1lZCBvclxuICogdGhlIGJvZHkgaXMgbm90IGEgdmFsaWQgcmVnZXguXG4gKi9cbmZ1bmN0aW9uIGNvbXBpbGVSZWdleExpdGVyYWwocGF0dGVybjogc3RyaW5nLCBjYXNlU2Vuc2l0aXZlOiBib29sZWFuKTogUmVnRXhwIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcGFyc2VkID0gL15cXC8oLispXFwvKFthLXpdKikkL2lzLmV4ZWMocGF0dGVybik7XG4gIGlmICghcGFyc2VkKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBib2R5ID0gcGFyc2VkWzFdITtcbiAgY29uc3QgZmxhZ3MgPSBwYXJzZWRbMl0hO1xuICB0cnkge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKGJvZHksIGNhc2VTZW5zaXRpdmUgfHwgZmxhZ3MuaW5jbHVkZXMoXCJpXCIpID8gZmxhZ3MgOiBgJHtmbGFnc31pYCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nLndhcm4oXCJpZ25vcmluZyBpbnZhbGlkIHJlZ2V4IHBhdHRlcm5cIiwgeyBwYXR0ZXJuLCBlcnJvciB9KTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogQ29tcGlsZSBhIHNoZWxsLXN0eWxlIGdsb2IgKGAqYCwgYD9gKSBpbnRvIGFuIGFuY2hvcmVkIGBSZWdFeHBgLiBFdmVyeSBvdGhlclxuICogY2hhcmFjdGVyIGlzIGVzY2FwZWQsIHNvIGEgZ2xvYiBjYW4gc2FmZWx5IGNvbnRhaW4gcmVnZXggbWV0YWNoYXJhY3RlcnNcbiAqIChgeC1hcHAuKmAgbWF0Y2hlcyBhIGxpdGVyYWwgZG90IGZvbGxvd2VkIGJ5IGFueXRoaW5nKS5cbiAqL1xuZnVuY3Rpb24gY29tcGlsZUdsb2IocGF0dGVybjogc3RyaW5nLCBjYXNlU2Vuc2l0aXZlOiBib29sZWFuKTogUmVnRXhwIHtcbiAgY29uc3QgYm9keSA9IHBhdHRlcm5cbiAgICAuc3BsaXQoLyhbKj9dKS8pXG4gICAgLm1hcCgocGFydCkgPT4gKHBhcnQgPT09IFwiKlwiID8gXCIuKlwiIDogcGFydCA9PT0gXCI/XCIgPyBcIi5cIiA6IGVzY2FwZVJlZ0V4cChwYXJ0KSkpXG4gICAgLmpvaW4oXCJcIik7XG4gIHJldHVybiBuZXcgUmVnRXhwKGBeJHtib2R5fSRgLCBjYXNlU2Vuc2l0aXZlID8gXCJcIiA6IFwiaVwiKTtcbn1cblxuLyoqXG4gKiBDb21waWxlIE9ORSBwYXR0ZXJuIGludG8gYSBwcmVkaWNhdGUsIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlIGVudHJ5IGlzIGVtcHR5XG4gKiBvciBhbiB1bnBhcnNlYWJsZSByZWdleCBsaXRlcmFsLlxuICpcbiAqIENhbGxlcnMgdGhhdCB3YW50IGEgd2hvbGUgbGlzdCBzaG91bGQgdXNlIHtAbGluayB0b1BhdHRlcm5NYXRjaGVyfTsgdGhpcyBpc1xuICogZXhwb3J0ZWQgZm9yIHRoZSBjYXNlIHdoZXJlIGEgY29uc3VtZXIgYXBwbGllcyBpdHMgb3duIHNlbWFudGljcyB0byBzb21lXG4gKiBzaGFwZXMgYW5kIG9ubHkgd2FudHMgdGhlIGdsb2IvcmVnZXggaGFuZGxpbmcgKHRoZSBlbWFpbCBnYXRlJ3MgYmFyZS1kb21haW5cbiAqIHNob3J0Y3V0LCBmb3Igb25lKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvUGF0dGVybihcbiAgcGF0dGVybjogc3RyaW5nLFxuICBvcHRpb25zOiBQYXR0ZXJuT3B0aW9ucyA9IHt9LFxuKTogcHJlZGljYXRlLlByZWRpY2F0ZTxzdHJpbmc+IHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgdHJpbW1lZCA9IHBhdHRlcm4udHJpbSgpO1xuICBpZiAoIXRyaW1tZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IGNhc2VTZW5zaXRpdmUgPSBvcHRpb25zLmNhc2VTZW5zaXRpdmUgPz8gZmFsc2U7XG5cbiAgaWYgKGlzUmVnZXhMaXRlcmFsKHRyaW1tZWQpKSB7XG4gICAgY29uc3QgY29tcGlsZWQgPSBjb21waWxlUmVnZXhMaXRlcmFsKHRyaW1tZWQsIGNhc2VTZW5zaXRpdmUpO1xuICAgIHJldHVybiBjb21waWxlZCAmJiBwcmVkaWNhdGUuY3JlYXRlPHN0cmluZz4oKHZhbHVlKSA9PiBjb21waWxlZC50ZXN0KHZhbHVlKSk7XG4gIH1cbiAgaWYgKGlzR2xvYih0cmltbWVkKSkge1xuICAgIGNvbnN0IGNvbXBpbGVkID0gY29tcGlsZUdsb2IodHJpbW1lZCwgY2FzZVNlbnNpdGl2ZSk7XG4gICAgcmV0dXJuIHByZWRpY2F0ZS5jcmVhdGU8c3RyaW5nPigodmFsdWUpID0+IGNvbXBpbGVkLnRlc3QodmFsdWUpKTtcbiAgfVxuICAvLyBMaXRlcmFsOiB3aG9sZS1zdHJpbmcgZXF1YWxpdHkuXG4gIGNvbnN0IGV4cGVjdGVkID0gY2FzZVNlbnNpdGl2ZSA/IHRyaW1tZWQgOiB0cmltbWVkLnRvTG93ZXJDYXNlKCk7XG4gIHJldHVybiBwcmVkaWNhdGUuY3JlYXRlPHN0cmluZz4oKHZhbHVlKSA9PlxuICAgIGNhc2VTZW5zaXRpdmUgPyB2YWx1ZSA9PT0gZXhwZWN0ZWQgOiB2YWx1ZS50b0xvd2VyQ2FzZSgpID09PSBleHBlY3RlZCxcbiAgKTtcbn1cblxuLyoqXG4gKiBDb21waWxlIHBhdHRlcm5zIGludG8gYSBzaW5nbGUgT1InZCB7QGxpbmsgUHJlZGljYXRlfS4gQWNjZXB0cyB0aGUgcmF3IGNvbmZpZ1xuICogc2hhcGVzIHtAbGluayBwYXJzZUxpc3R9IGRvZXMgLSBhbiBhcnJheSwgb3Igb25lIGNvbW1hL3doaXRlc3BhY2Utc2VwYXJhdGVkXG4gKiBzdHJpbmcgLSBzbyBhIGZpZWxkIGFuZCBpdHMgZW52IHZhciBuZWVkIG5vIHNlcGFyYXRlIGhhbmRsaW5nLlxuICpcbiAqIFdpdGggbm8gdXNhYmxlIHBhdHRlcm5zIHRoZSByZXN1bHQgYWx3YXlzIHJldHVybnMgYGZhbHNlYC5cbiAqXG4gKiBAZXhhbXBsZVxuICogY29uc3QgZm9yd2FyZGFibGUgPSB0b1BhdHRlcm5NYXRjaGVyKHByb2Nlc3MuZW52LlRVTk5FTF9GT1JXQVJEX0hFQURFUlMpO1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9QYXR0ZXJuTWF0Y2hlcihcbiAgcGF0dGVybnM6IHN0cmluZyB8IHJlYWRvbmx5IHN0cmluZ1tdIHwgdW5kZWZpbmVkIHwgbnVsbCxcbiAgb3B0aW9uczogUGF0dGVybk9wdGlvbnMgPSB7fSxcbik6IHByZWRpY2F0ZS5QcmVkaWNhdGU8c3RyaW5nPiB7XG4gIGNvbnN0IGNvbXBpbGVkID0gcGFyc2VMaXN0KHBhdHRlcm5zKVxuICAgIC5tYXAoKHBhdHRlcm4pID0+IHRvUGF0dGVybihwYXR0ZXJuLCBvcHRpb25zKSlcbiAgICAuZmlsdGVyKCh2YWx1ZSk6IHZhbHVlIGlzIHByZWRpY2F0ZS5QcmVkaWNhdGU8c3RyaW5nPiA9PiB2YWx1ZSAhPT0gdW5kZWZpbmVkKTtcbiAgaWYgKGNvbXBpbGVkLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHByZWRpY2F0ZS5jcmVhdGU8c3RyaW5nPigoKSA9PiBmYWxzZSk7XG4gIHJldHVybiBjb21waWxlZC5zbGljZSgxKS5yZWR1Y2UoKGFjYywgbmV4dCkgPT4gYWNjLm9yKG5leHQpLCBjb21waWxlZFswXSEpO1xufVxuIl19
|
package/lib/src/token.d.ts
CHANGED
|
@@ -7,6 +7,20 @@
|
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
9
|
import { type HeaderLike } from "./http.ts";
|
|
10
|
+
/**
|
|
11
|
+
* Header the Databricks Apps front door forwards the caller's OAuth (OBO) token
|
|
12
|
+
* on - the default source for every helper here.
|
|
13
|
+
*
|
|
14
|
+
* Exported because it is a wire contract several packages branch on, not just a
|
|
15
|
+
* default argument: `@dbx-tools/appkit`'s `identity` module decides whether a
|
|
16
|
+
* request can use OBO auth at all by its presence, and `@dbx-tools/cli-tunnel`
|
|
17
|
+
* must know the name to strip inbound copies of it. One spelling, one place.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ACCESS_TOKEN_HEADER = "x-forwarded-access-token";
|
|
20
|
+
/** Header the front door forwards the caller's user id on. */
|
|
21
|
+
export declare const USER_ID_HEADER = "x-forwarded-user";
|
|
22
|
+
/** Header the front door forwards the caller's email on. */
|
|
23
|
+
export declare const USER_EMAIL_HEADER = "x-forwarded-email";
|
|
10
24
|
/**
|
|
11
25
|
* Decode the JWT payload from a bearer token string or request headers.
|
|
12
26
|
*
|
package/lib/src/token.js
CHANGED
|
@@ -12,6 +12,20 @@ import { isLevelEnabled, logger } from "./log.js";
|
|
|
12
12
|
const BEARER_PREFIX_REGEX = /^bearer\s+/i;
|
|
13
13
|
const SPLIT_REGEX = /\s+|\s*,\s*/;
|
|
14
14
|
const log = logger("shared/token");
|
|
15
|
+
/**
|
|
16
|
+
* Header the Databricks Apps front door forwards the caller's OAuth (OBO) token
|
|
17
|
+
* on - the default source for every helper here.
|
|
18
|
+
*
|
|
19
|
+
* Exported because it is a wire contract several packages branch on, not just a
|
|
20
|
+
* default argument: `@dbx-tools/appkit`'s `identity` module decides whether a
|
|
21
|
+
* request can use OBO auth at all by its presence, and `@dbx-tools/cli-tunnel`
|
|
22
|
+
* must know the name to strip inbound copies of it. One spelling, one place.
|
|
23
|
+
*/
|
|
24
|
+
export const ACCESS_TOKEN_HEADER = "x-forwarded-access-token";
|
|
25
|
+
/** Header the front door forwards the caller's user id on. */
|
|
26
|
+
export const USER_ID_HEADER = "x-forwarded-user";
|
|
27
|
+
/** Header the front door forwards the caller's email on. */
|
|
28
|
+
export const USER_EMAIL_HEADER = "x-forwarded-email";
|
|
15
29
|
/**
|
|
16
30
|
* Decode a JWT segment (base64url with standard base64 padding), or
|
|
17
31
|
* `undefined` when the segment is not valid base64.
|
|
@@ -34,7 +48,7 @@ function decodeJwtSegment(segment) {
|
|
|
34
48
|
* When `input` is header-like, walks every value for `headerName` (default
|
|
35
49
|
* `x-forwarded-access-token`) and merges claim keys left-to-right.
|
|
36
50
|
*/
|
|
37
|
-
export function getAccessTokenPayload(input, headerName =
|
|
51
|
+
export function getAccessTokenPayload(input, headerName = ACCESS_TOKEN_HEADER) {
|
|
38
52
|
let accessTokenPayload;
|
|
39
53
|
if (!(typeof input === "string")) {
|
|
40
54
|
if (headerName) {
|
|
@@ -123,4 +137,4 @@ function* iterateClaims(input, distinct = true) {
|
|
|
123
137
|
}
|
|
124
138
|
yield* visit(input);
|
|
125
139
|
}
|
|
126
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUVILE9BQU8sRUFBRSxrQkFBa0IsRUFBbUIsTUFBTSxXQUFXLENBQUM7QUFDaEUsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFbEQsTUFBTSxtQkFBbUIsR0FBRyxhQUFhLENBQUM7QUFDMUMsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDO0FBQ2xDLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUVuQzs7O0dBR0c7QUFDSCxTQUFTLGdCQUFnQixDQUFDLE9BQWU7SUFDdkMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNqRSxNQUFNLE1BQU0sR0FBRyxVQUFVLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMxRSxJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUIsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoRSxPQUFPLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLFNBQVMs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LENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBKV1QgYWNjZXNzLXRva2VuIGhlbHBlcnMgZm9yIERhdGFicmlja3MgQXBwcy5cbiAqXG4gKiBQYXJzZXMgYmVhcmVyIHRva2VucyBhbmQgYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmAgcGF5bG9hZHMgdG8gcmVhZFxuICogT0F1dGggc2NvcGVzIGFuZCBvdGhlciBjbGFpbXMgZnJvbSBpbmNvbWluZyBIVFRQIHJlcXVlc3RzLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBmb3JFYWNoSGVhZGVyVmFsdWUsIHR5cGUgSGVhZGVyTGlrZSB9IGZyb20gXCIuL2h0dHAudHNcIjtcbmltcG9ydCAqIGFzIGpzb24gZnJvbSBcIi4vanNvbi50c1wiO1xuaW1wb3J0IHsgaXNMZXZlbEVuYWJsZWQsIGxvZ2dlciB9IGZyb20gXCIuL2xvZy50c1wiO1xuXG5jb25zdCBCRUFSRVJfUFJFRklYX1JFR0VYID0gL15iZWFyZXJcXHMrL2k7XG5jb25zdCBTUExJVF9SRUdFWCA9IC9cXHMrfFxccyosXFxzKi87XG5jb25zdCBsb2cgPSBsb2dnZXIoXCJzaGFyZWQvdG9rZW5cIik7XG5cbi8qKlxuICogRGVjb2RlIGEgSldUIHNlZ21lbnQgKGJhc2U2NHVybCB3aXRoIHN0YW5kYXJkIGJhc2U2NCBwYWRkaW5nKSwgb3JcbiAqIGB1bmRlZmluZWRgIHdoZW4gdGhlIHNlZ21lbnQgaXMgbm90IHZhbGlkIGJhc2U2NC5cbiAqL1xuZnVuY3Rpb24gZGVjb2RlSnd0U2VnbWVudChzZWdtZW50OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBub3JtYWxpemVkID0gc2VnbWVudC5yZXBsYWNlKC8tL2csIFwiK1wiKS5yZXBsYWNlKC9fL2csIFwiL1wiKTtcbiAgY29uc3QgcGFkZGVkID0gbm9ybWFsaXplZCArIFwiPVwiLnJlcGVhdCgoNCAtIChub3JtYWxpemVkLmxlbmd0aCAlIDQpKSAlIDQpO1xuICB0cnkge1xuICAgIGNvbnN0IGJpbmFyeSA9IGF0b2IocGFkZGVkKTtcbiAgICBjb25zdCBieXRlcyA9IFVpbnQ4QXJyYXkuZnJvbShiaW5hcnksIChjaCkgPT4gY2guY2hhckNvZGVBdCgwKSk7XG4gICAgcmV0dXJuIG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShieXRlcyk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBEZWNvZGUgdGhlIEpXVCBwYXlsb2FkIGZyb20gYSBiZWFyZXIgdG9rZW4gc3RyaW5nIG9yIHJlcXVlc3QgaGVhZGVycy5cbiAqXG4gKiBXaGVuIGBpbnB1dGAgaXMgaGVhZGVyLWxpa2UsIHdhbGtzIGV2ZXJ5IHZhbHVlIGZvciBgaGVhZGVyTmFtZWAgKGRlZmF1bHRcbiAqIGB4LWZvcndhcmRlZC1hY2Nlc3MtdG9rZW5gKSBhbmQgbWVyZ2VzIGNsYWltIGtleXMgbGVmdC10by1yaWdodC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFjY2Vzc1Rva2VuUGF5bG9hZChcbiAgaW5wdXQ6IEhlYWRlckxpa2UgfCBzdHJpbmcsXG4gIGhlYWRlck5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZCA9IFwieC1mb3J3YXJkZWQtYWNjZXNzLXRva2VuXCIsXG4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGxldCBhY2Nlc3NUb2tlblBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkO1xuICBpZiAoISh0eXBlb2YgaW5wdXQgPT09IFwic3RyaW5nXCIpKSB7XG4gICAgaWYgKGhlYWRlck5hbWUpIHtcbiAgICAgIGZvckVhY2hIZWFkZXJWYWx1ZShpbnB1dCwgaGVhZGVyTmFtZSwgKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgZm9yIChjb25zdCBbcGF5bG9hZEtleSwgcGF5bG9hZFZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhnZXRBY2Nlc3NUb2tlblBheWxvYWQodmFsdWUpKSkge1xuICAgICAgICAgIGlmICghYWNjZXNzVG9rZW5QYXlsb2FkIHx8ICEocGF5bG9hZEtleSBpbiBhY2Nlc3NUb2tlblBheWxvYWQpKSB7XG4gICAgICAgICAgICBpZiAoIWFjY2Vzc1Rva2VuUGF5bG9hZCkgYWNjZXNzVG9rZW5QYXlsb2FkID0ge307XG4gICAgICAgICAgICBhY2Nlc3NUb2tlblBheWxvYWRbcGF5bG9hZEtleV0gPSBwYXlsb2FkVmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaW5wdXQgPSBpbnB1dC50cmltKCk7XG4gICAgaWYgKGlucHV0KSB7XG4gICAgICBjb25zdCBtYXRjaCA9IEJFQVJFUl9QUkVGSVhfUkVHRVguZXhlYyhpbnB1dCk7XG4gICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgY29uc3QgZW5kSW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgaW5wdXQgPSBpbnB1dC5zbGljZShlbmRJbmRleCk7XG4gICAgICB9XG4gICAgICBjb25zdCBwYXJ0cyA9IGlucHV0LnNwbGl0KFwiLlwiLCA0KTtcbiAgICAgIGlmIChwYXJ0cy5sZW5ndGggPT09IDIgfHwgcGFydHMubGVuZ3RoID09PSAzKSB7XG4gICAgICAgIC8vIEEgbWFsZm9ybWVkIHNlZ21lbnQgeWllbGRzIHVuZGVmaW5lZDsgZmFsbCB0aHJvdWdoIHRvIGVtcHR5IG9iamVjdC5cbiAgICAgICAgYWNjZXNzVG9rZW5QYXlsb2FkID0ganNvbi5wYXJzZVJlY29yZChkZWNvZGVKd3RTZWdtZW50KHBhcnRzWzFdISkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAoIWFjY2Vzc1Rva2VuUGF5bG9hZCkgYWNjZXNzVG9rZW5QYXlsb2FkID0ge307XG4gIGxvZy5kZWJ1ZyhcImdldEFjY2Vzc1Rva2VuUGF5bG9hZFwiLCB7IGFjY2Vzc1Rva2VuUGF5bG9hZCB9KTtcbiAgcmV0dXJuIGFjY2Vzc1Rva2VuUGF5bG9hZDtcbn1cblxuLyoqXG4gKiBPQXV0aCBzY29wZXMgZnJvbSB0aGUgYWNjZXNzLXRva2VuIEpXVCBvbiBgaW5wdXRgLlxuICpcbiAqIERlZmF1bHRzIHRvIHRoZSBgeC1mb3J3YXJkZWQtYWNjZXNzLXRva2VuYCBoZWFkZXIsIHdoaWNoIERhdGFicmlja3MgQXBwc1xuICogZm9yd2FyZCBmcm9tIHRoZSBicm93c2VyIHNlc3Npb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBY2Nlc3NUb2tlblNjb3BlcyhcbiAgaW5wdXQ6IEhlYWRlckxpa2UgfCBzdHJpbmcsXG4gIGhlYWRlck5hbWU/OiBzdHJpbmcsXG4pOiBJdGVyYWJsZTxzdHJpbmc+IHtcbiAgY29uc3QgcGF5bG9hZCA9IGdldEFjY2Vzc1Rva2VuUGF5bG9hZChpbnB1dCwgaGVhZGVyTmFtZSk7XG4gIGxldCBhY2Nlc3NUb2tlblNjb3BlczogSXRlcmFibGU8c3RyaW5nPiA9IGl0ZXJhdGVDbGFpbXMocGF5bG9hZC5zY29wZSk7XG4gIGlmIChpc0xldmVsRW5hYmxlZChcImRlYnVnXCIpKSB7XG4gICAgYWNjZXNzVG9rZW5TY29wZXMgPSBBcnJheS5mcm9tKGFjY2Vzc1Rva2VuU2NvcGVzKTtcbiAgICBsb2cuZGVidWcoXCJnZXRBY2Nlc3NUb2tlblNjb3Blc1wiLCB7IGFjY2Vzc1Rva2VuU2NvcGVzIH0pO1xuICB9XG4gIHJldHVybiBhY2Nlc3NUb2tlblNjb3Blcztcbn1cblxuLyoqXG4gKiBSZXR1cm4gdHJ1ZSB3aGVuIGBzY29wZXNgIGNvbnRhaW5zIGFueSB2YWx1ZSBmcm9tIGBhbGxvd2VkYC5cbiAqXG4gKiBBY2NlcHRzIHRoZSByYXcge0BsaW5rIE1BU1RSQV9TQ09QRVNfS0VZfSBhcnJheSBzdGFtcGVkIG9uXG4gKiBgUmVxdWVzdENvbnRleHRgIGFzIHdlbGwgYXMgaXRlcmFibGVzIGZyb20ge0BsaW5rIGdldEFjY2Vzc1Rva2VuU2NvcGVzfS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluY2x1ZGVzQWNjZXNzVG9rZW5TY29wZShzY29wZXM6IHVua25vd24sIGFsbG93ZWQ6IHJlYWRvbmx5IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gIGlmIChhbGxvd2VkLmxlbmd0aCkge1xuICAgIGZvciAoY29uc3Qgc2NvcGUgb2YgaXRlcmF0ZUNsYWltcyhzY29wZXMpKSB7XG4gICAgICBpZiAoYWxsb3dlZC5pbmNsdWRlcyhzY29wZSkpIHtcbiAgICAgICAgbG9nLmRlYnVnKFwiaW5jbHVkZXNBY2Nlc3NUb2tlblNjb3BlXCIsIHsgc2NvcGUsIGFsbG93ZWQgfSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKiBTcGxpdCBhIEpXVCBgc2NvcGVgIGNsYWltIHN0cmluZyBvciBhcnJheSBpbnRvIGluZGl2aWR1YWwgc2NvcGUgdG9rZW5zLiAqL1xuZnVuY3Rpb24qIGl0ZXJhdGVDbGFpbXMoaW5wdXQ6IHVua25vd24sIGRpc3RpbmN0ID0gdHJ1ZSk6IEl0ZXJhYmxlPHN0cmluZz4ge1xuICBjb25zdCBzZWVuID0gZGlzdGluY3QgPyBuZXcgU2V0PHN0cmluZz4oKSA6IHVuZGVmaW5lZDtcblxuICBmdW5jdGlvbiogdmlzaXQodmFsdWU6IHVua25vd24pOiBJdGVyYWJsZTxzdHJpbmc+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBmb3IgKGNvbnN0IGNsYWltIG9mIHZhbHVlLnNwbGl0KFNQTElUX1JFR0VYKSkge1xuICAgICAgICBjb25zdCB0b2tlbiA9IGNsYWltLnRyaW0oKTtcbiAgICAgICAgaWYgKCF0b2tlbiB8fCBzZWVuPy5oYXModG9rZW4pKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgc2Vlbj8uYWRkKHRva2VuKTtcbiAgICAgICAgeWllbGQgdG9rZW47XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbHVlKSB7XG4gICAgICAgIHlpZWxkKiB2aXNpdChpdGVtKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB5aWVsZCogdmlzaXQoaW5wdXQpO1xufVxuIl19
|
|
140
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUVILE9BQU8sRUFBRSxrQkFBa0IsRUFBbUIsTUFBTSxXQUFXLENBQUM7QUFDaEUsT0FBTyxLQUFLLElBQUksTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFbEQsTUFBTSxtQkFBbUIsR0FBRyxhQUFhLENBQUM7QUFDMUMsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDO0FBQ2xDLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUVuQzs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLDBCQUEwQixDQUFDO0FBRTlELDhEQUE4RDtBQUM5RCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsa0JBQWtCLENBQUM7QUFFakQsNERBQTREO0FBQzVELE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLG1CQUFtQixDQUFDO0FBRXJEOzs7R0FHRztBQUNILFNBQVMsZ0JBQWdCLENBQUMsT0FBZTtJQUN2QyxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2pFLE1BQU0sTUFBTSxHQUFHLFVBQVUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzFFLElBQUksQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM1QixNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsSUFBSSxD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QU0sS0FBSyxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUN6QixLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3RCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEpXVCBhY2Nlc3MtdG9rZW4gaGVscGVycyBmb3IgRGF0YWJyaWNrcyBBcHBzLlxuICpcbiAqIFBhcnNlcyBiZWFyZXIgdG9rZW5zIGFuZCBgeC1mb3J3YXJkZWQtYWNjZXNzLXRva2VuYCBwYXlsb2FkcyB0byByZWFkXG4gKiBPQXV0aCBzY29wZXMgYW5kIG90aGVyIGNsYWltcyBmcm9tIGluY29taW5nIEhUVFAgcmVxdWVzdHMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGZvckVhY2hIZWFkZXJWYWx1ZSwgdHlwZSBIZWFkZXJMaWtlIH0gZnJvbSBcIi4vaHR0cC50c1wiO1xuaW1wb3J0ICogYXMganNvbiBmcm9tIFwiLi9qc29uLnRzXCI7XG5pbXBvcnQgeyBpc0xldmVsRW5hYmxlZCwgbG9nZ2VyIH0gZnJvbSBcIi4vbG9nLnRzXCI7XG5cbmNvbnN0IEJFQVJFUl9QUkVGSVhfUkVHRVggPSAvXmJlYXJlclxccysvaTtcbmNvbnN0IFNQTElUX1JFR0VYID0gL1xccyt8XFxzKixcXHMqLztcbmNvbnN0IGxvZyA9IGxvZ2dlcihcInNoYXJlZC90b2tlblwiKTtcblxuLyoqXG4gKiBIZWFkZXIgdGhlIERhdGFicmlja3MgQXBwcyBmcm9udCBkb29yIGZvcndhcmRzIHRoZSBjYWxsZXIncyBPQXV0aCAoT0JPKSB0b2tlblxuICogb24gLSB0aGUgZGVmYXVsdCBzb3VyY2UgZm9yIGV2ZXJ5IGhlbHBlciBoZXJlLlxuICpcbiAqIEV4cG9ydGVkIGJlY2F1c2UgaXQgaXMgYSB3aXJlIGNvbnRyYWN0IHNldmVyYWwgcGFja2FnZXMgYnJhbmNoIG9uLCBub3QganVzdCBhXG4gKiBkZWZhdWx0IGFyZ3VtZW50OiBgQGRieC10b29scy9hcHBraXRgJ3MgYGlkZW50aXR5YCBtb2R1bGUgZGVjaWRlcyB3aGV0aGVyIGFcbiAqIHJlcXVlc3QgY2FuIHVzZSBPQk8gYXV0aCBhdCBhbGwgYnkgaXRzIHByZXNlbmNlLCBhbmQgYEBkYngtdG9vbHMvY2xpLXR1bm5lbGBcbiAqIG11c3Qga25vdyB0aGUgbmFtZSB0byBzdHJpcCBpbmJvdW5kIGNvcGllcyBvZiBpdC4gT25lIHNwZWxsaW5nLCBvbmUgcGxhY2UuXG4gKi9cbmV4cG9ydCBjb25zdCBBQ0NFU1NfVE9LRU5fSEVBREVSID0gXCJ4LWZvcndhcmRlZC1hY2Nlc3MtdG9rZW5cIjtcblxuLyoqIEhlYWRlciB0aGUgZnJvbnQgZG9vciBmb3J3YXJkcyB0aGUgY2FsbGVyJ3MgdXNlciBpZCBvbi4gKi9cbmV4cG9ydCBjb25zdCBVU0VSX0lEX0hFQURFUiA9IFwieC1mb3J3YXJkZWQtdXNlclwiO1xuXG4vKiogSGVhZGVyIHRoZSBmcm9udCBkb29yIGZvcndhcmRzIHRoZSBjYWxsZXIncyBlbWFpbCBvbi4gKi9cbmV4cG9ydCBjb25zdCBVU0VSX0VNQUlMX0hFQURFUiA9IFwieC1mb3J3YXJkZWQtZW1haWxcIjtcblxuLyoqXG4gKiBEZWNvZGUgYSBKV1Qgc2VnbWVudCAoYmFzZTY0dXJsIHdpdGggc3RhbmRhcmQgYmFzZTY0IHBhZGRpbmcpLCBvclxuICogYHVuZGVmaW5lZGAgd2hlbiB0aGUgc2VnbWVudCBpcyBub3QgdmFsaWQgYmFzZTY0LlxuICovXG5mdW5jdGlvbiBkZWNvZGVKd3RTZWdtZW50KHNlZ21lbnQ6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSBzZWdtZW50LnJlcGxhY2UoLy0vZywgXCIrXCIpLnJlcGxhY2UoL18vZywgXCIvXCIpO1xuICBjb25zdCBwYWRkZWQgPSBub3JtYWxpemVkICsgXCI9XCIucmVwZWF0KCg0IC0gKG5vcm1hbGl6ZWQubGVuZ3RoICUgNCkpICUgNCk7XG4gIHRyeSB7XG4gICAgY29uc3QgYmluYXJ5ID0gYXRvYihwYWRkZWQpO1xuICAgIGNvbnN0IGJ5dGVzID0gVWludDhBcnJheS5mcm9tKGJpbmFyeSwgKGNoKSA9PiBjaC5jaGFyQ29kZUF0KDApKTtcbiAgICByZXR1cm4gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGJ5dGVzKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIERlY29kZSB0aGUgSldUIHBheWxvYWQgZnJvbSBhIGJlYXJlciB0b2tlbiBzdHJpbmcgb3IgcmVxdWVzdCBoZWFkZXJzLlxuICpcbiAqIFdoZW4gYGlucHV0YCBpcyBoZWFkZXItbGlrZSwgd2Fsa3MgZXZlcnkgdmFsdWUgZm9yIGBoZWFkZXJOYW1lYCAoZGVmYXVsdFxuICogYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmApIGFuZCBtZXJnZXMgY2xhaW0ga2V5cyBsZWZ0LXRvLXJpZ2h0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWNjZXNzVG9rZW5QYXlsb2FkKFxuICBpbnB1dDogSGVhZGVyTGlrZSB8IHN0cmluZyxcbiAgaGVhZGVyTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkID0gQUNDRVNTX1RPS0VOX0hFQURFUixcbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgbGV0IGFjY2Vzc1Rva2VuUGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ7XG4gIGlmICghKHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIikpIHtcbiAgICBpZiAoaGVhZGVyTmFtZSkge1xuICAgICAgZm9yRWFjaEhlYWRlclZhbHVlKGlucHV0LCBoZWFkZXJOYW1lLCAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IFtwYXlsb2FkS2V5LCBwYXlsb2FkVmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGdldEFjY2Vzc1Rva2VuUGF5bG9hZCh2YWx1ZSkpKSB7XG4gICAgICAgICAgaWYgKCFhY2Nlc3NUb2tlblBheWxvYWQgfHwgIShwYXlsb2FkS2V5IGluIGFjY2Vzc1Rva2VuUGF5bG9hZCkpIHtcbiAgICAgICAgICAgIGlmICghYWNjZXNzVG9rZW5QYXlsb2FkKSBhY2Nlc3NUb2tlblBheWxvYWQgPSB7fTtcbiAgICAgICAgICAgIGFjY2Vzc1Rva2VuUGF5bG9hZFtwYXlsb2FkS2V5XSA9IHBheWxvYWRWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpbnB1dCA9IGlucHV0LnRyaW0oKTtcbiAgICBpZiAoaW5wdXQpIHtcbiAgICAgIGNvbnN0IG1hdGNoID0gQkVBUkVSX1BSRUZJWF9SRUdFWC5leGVjKGlucHV0KTtcbiAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICBjb25zdCBlbmRJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICBpbnB1dCA9IGlucHV0LnNsaWNlKGVuZEluZGV4KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHBhcnRzID0gaW5wdXQuc3BsaXQoXCIuXCIsIDQpO1xuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMiB8fCBwYXJ0cy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgLy8gQSBtYWxmb3JtZWQgc2VnbWVudCB5aWVsZHMgdW5kZWZpbmVkOyBmYWxsIHRocm91Z2ggdG8gZW1wdHkgb2JqZWN0LlxuICAgICAgICBhY2Nlc3NUb2tlblBheWxvYWQgPSBqc29uLnBhcnNlUmVjb3JkKGRlY29kZUp3dFNlZ21lbnQocGFydHNbMV0hKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGlmICghYWNjZXNzVG9rZW5QYXlsb2FkKSBhY2Nlc3NUb2tlblBheWxvYWQgPSB7fTtcbiAgbG9nLmRlYnVnKFwiZ2V0QWNjZXNzVG9rZW5QYXlsb2FkXCIsIHsgYWNjZXNzVG9rZW5QYXlsb2FkIH0pO1xuICByZXR1cm4gYWNjZXNzVG9rZW5QYXlsb2FkO1xufVxuXG4vKipcbiAqIE9BdXRoIHNjb3BlcyBmcm9tIHRoZSBhY2Nlc3MtdG9rZW4gSldUIG9uIGBpbnB1dGAuXG4gKlxuICogRGVmYXVsdHMgdG8gdGhlIGB4LWZvcndhcmRlZC1hY2Nlc3MtdG9rZW5gIGhlYWRlciwgd2hpY2ggRGF0YWJyaWNrcyBBcHBzXG4gKiBmb3J3YXJkIGZyb20gdGhlIGJyb3dzZXIgc2Vzc2lvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFjY2Vzc1Rva2VuU2NvcGVzKFxuICBpbnB1dDogSGVhZGVyTGlrZSB8IHN0cmluZyxcbiAgaGVhZGVyTmFtZT86IHN0cmluZyxcbik6IEl0ZXJhYmxlPHN0cmluZz4ge1xuICBjb25zdCBwYXlsb2FkID0gZ2V0QWNjZXNzVG9rZW5QYXlsb2FkKGlucHV0LCBoZWFkZXJOYW1lKTtcbiAgbGV0IGFjY2Vzc1Rva2VuU2NvcGVzOiBJdGVyYWJsZTxzdHJpbmc+ID0gaXRlcmF0ZUNsYWltcyhwYXlsb2FkLnNjb3BlKTtcbiAgaWYgKGlzTGV2ZWxFbmFibGVkKFwiZGVidWdcIikpIHtcbiAgICBhY2Nlc3NUb2tlblNjb3BlcyA9IEFycmF5LmZyb20oYWNjZXNzVG9rZW5TY29wZXMpO1xuICAgIGxvZy5kZWJ1ZyhcImdldEFjY2Vzc1Rva2VuU2NvcGVzXCIsIHsgYWNjZXNzVG9rZW5TY29wZXMgfSk7XG4gIH1cbiAgcmV0dXJuIGFjY2Vzc1Rva2VuU2NvcGVzO1xufVxuXG4vKipcbiAqIFJldHVybiB0cnVlIHdoZW4gYHNjb3Blc2AgY29udGFpbnMgYW55IHZhbHVlIGZyb20gYGFsbG93ZWRgLlxuICpcbiAqIEFjY2VwdHMgdGhlIHJhdyB7QGxpbmsgTUFTVFJBX1NDT1BFU19LRVl9IGFycmF5IHN0YW1wZWQgb25cbiAqIGBSZXF1ZXN0Q29udGV4dGAgYXMgd2VsbCBhcyBpdGVyYWJsZXMgZnJvbSB7QGxpbmsgZ2V0QWNjZXNzVG9rZW5TY29wZXN9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5jbHVkZXNBY2Nlc3NUb2tlblNjb3BlKHNjb3BlczogdW5rbm93biwgYWxsb3dlZDogcmVhZG9ubHkgc3RyaW5nW10pOiBib29sZWFuIHtcbiAgaWYgKGFsbG93ZWQubGVuZ3RoKSB7XG4gICAgZm9yIChjb25zdCBzY29wZSBvZiBpdGVyYXRlQ2xhaW1zKHNjb3BlcykpIHtcbiAgICAgIGlmIChhbGxvd2VkLmluY2x1ZGVzKHNjb3BlKSkge1xuICAgICAgICBsb2cuZGVidWcoXCJpbmNsdWRlc0FjY2Vzc1Rva2VuU2NvcGVcIiwgeyBzY29wZSwgYWxsb3dlZCB9KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqIFNwbGl0IGEgSldUIGBzY29wZWAgY2xhaW0gc3RyaW5nIG9yIGFycmF5IGludG8gaW5kaXZpZHVhbCBzY29wZSB0b2tlbnMuICovXG5mdW5jdGlvbiogaXRlcmF0ZUNsYWltcyhpbnB1dDogdW5rbm93biwgZGlzdGluY3QgPSB0cnVlKTogSXRlcmFibGU8c3RyaW5nPiB7XG4gIGNvbnN0IHNlZW4gPSBkaXN0aW5jdCA/IG5ldyBTZXQ8c3RyaW5nPigpIDogdW5kZWZpbmVkO1xuXG4gIGZ1bmN0aW9uKiB2aXNpdCh2YWx1ZTogdW5rbm93bik6IEl0ZXJhYmxlPHN0cmluZz4ge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIGZvciAoY29uc3QgY2xhaW0gb2YgdmFsdWUuc3BsaXQoU1BMSVRfUkVHRVgpKSB7XG4gICAgICAgIGNvbnN0IHRva2VuID0gY2xhaW0udHJpbSgpO1xuICAgICAgICBpZiAoIXRva2VuIHx8IHNlZW4/Lmhhcyh0b2tlbikpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBzZWVuPy5hZGQodG9rZW4pO1xuICAgICAgICB5aWVsZCB0b2tlbjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdmFsdWUpIHtcbiAgICAgICAgeWllbGQqIHZpc2l0KGl0ZW0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHlpZWxkKiB2aXNpdChpbnB1dCk7XG59XG4iXX0=
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/async.ts","../src/brand.ts","../src/env.ts","../src/error.ts","../src/execution.ts","../src/function.ts","../src/hash.ts","../src/http.ts","../src/json.ts","../src/log.ts","../src/net.ts","../src/object.ts","../src/predicate.ts","../src/string.ts","../src/token.ts","../index.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/async.ts","../src/brand.ts","../src/env.ts","../src/error.ts","../src/execution.ts","../src/function.ts","../src/hash.ts","../src/http.ts","../src/json.ts","../src/log.ts","../src/net.ts","../src/object.ts","../src/pattern.ts","../src/predicate.ts","../src/string.ts","../src/token.ts","../index.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
package/src/pattern.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Literal / glob / regex string matching, compiled to a composable
|
|
3
|
+
* {@link Predicate}.
|
|
4
|
+
*
|
|
5
|
+
* A configurable allow-list is the same shape everywhere in this repo: a list of
|
|
6
|
+
* patterns from a config field or an env var, where an operator reasonably
|
|
7
|
+
* expects to write a plain value, a `*` wildcard, or - when neither is enough -
|
|
8
|
+
* a real regex. Each consumer used to grow its own `globToRegExp` +
|
|
9
|
+
* `/pattern/flags` parser; this is that parser, once.
|
|
10
|
+
*
|
|
11
|
+
* Three shapes are recognized per entry, tried in order:
|
|
12
|
+
*
|
|
13
|
+
* - **regex** - wrapped in slashes (`/^x-mastra-/`, with optional trailing
|
|
14
|
+
* flags). Compiled as written. An invalid regex never matches: it is skipped
|
|
15
|
+
* with a warning rather than throwing, so one bad entry cannot take a process
|
|
16
|
+
* down at startup.
|
|
17
|
+
* - **glob** - contains `*` or `?` (`x-mastra-*`). Shell-style, anchored at both
|
|
18
|
+
* ends: `*` matches any run of characters, `?` exactly one.
|
|
19
|
+
* - **literal** - anything else. Whole-string equality.
|
|
20
|
+
*
|
|
21
|
+
* Matching is case-INSENSITIVE by default, which is what the callers want (HTTP
|
|
22
|
+
* header names and email addresses are both case-insensitive); pass
|
|
23
|
+
* `caseSensitive` to opt out. An empty pattern list matches NOTHING, so a
|
|
24
|
+
* caller that treats "no patterns" as "permit everything" must special-case it
|
|
25
|
+
* rather than relying on the matcher.
|
|
26
|
+
*
|
|
27
|
+
* Browser-safe: hand-compiled to `RegExp` with no glob dependency, so this stays
|
|
28
|
+
* usable from a client bundle. Node code that needs path-aware globbing
|
|
29
|
+
* (`/` as a segment boundary, `**`) wants `@dbx-tools/path`'s `toPathMatcher`
|
|
30
|
+
* instead - that one is `minimatch`-backed and understands path semantics.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const allowed = toPatternMatcher(["x-mastra-*", "/^x-trace-/"]);
|
|
34
|
+
* allowed("x-mastra-thread-id"); // true
|
|
35
|
+
* allowed("x-forwarded-user"); // false
|
|
36
|
+
*
|
|
37
|
+
* @module
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import { logger } from "./log.ts";
|
|
41
|
+
import * as predicate from "./predicate.ts";
|
|
42
|
+
import { parseList } from "./string.ts";
|
|
43
|
+
|
|
44
|
+
const log = logger("shared/pattern");
|
|
45
|
+
|
|
46
|
+
/** Options for {@link toPattern} / {@link toPatternMatcher}. */
|
|
47
|
+
export interface PatternOptions {
|
|
48
|
+
/** Match case-sensitively. Default `false` (case-insensitive). */
|
|
49
|
+
caseSensitive?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Escape a string for literal use inside a `RegExp`. */
|
|
53
|
+
export function escapeRegExp(value: string): string {
|
|
54
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** True when `pattern` is a `/.../flags` regex literal. */
|
|
58
|
+
function isRegexLiteral(pattern: string): boolean {
|
|
59
|
+
return pattern.length > 1 && pattern.startsWith("/") && /\/[a-z]*$/i.test(pattern);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** True when `pattern` contains a glob wildcard. */
|
|
63
|
+
function isGlob(pattern: string): boolean {
|
|
64
|
+
return pattern.includes("*") || pattern.includes("?");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Compile a `/pattern/flags` literal, or `undefined` when it is malformed or
|
|
69
|
+
* the body is not a valid regex.
|
|
70
|
+
*/
|
|
71
|
+
function compileRegexLiteral(pattern: string, caseSensitive: boolean): RegExp | undefined {
|
|
72
|
+
const parsed = /^\/(.+)\/([a-z]*)$/is.exec(pattern);
|
|
73
|
+
if (!parsed) return undefined;
|
|
74
|
+
const body = parsed[1]!;
|
|
75
|
+
const flags = parsed[2]!;
|
|
76
|
+
try {
|
|
77
|
+
return new RegExp(body, caseSensitive || flags.includes("i") ? flags : `${flags}i`);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
log.warn("ignoring invalid regex pattern", { pattern, error });
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Compile a shell-style glob (`*`, `?`) into an anchored `RegExp`. Every other
|
|
86
|
+
* character is escaped, so a glob can safely contain regex metacharacters
|
|
87
|
+
* (`x-app.*` matches a literal dot followed by anything).
|
|
88
|
+
*/
|
|
89
|
+
function compileGlob(pattern: string, caseSensitive: boolean): RegExp {
|
|
90
|
+
const body = pattern
|
|
91
|
+
.split(/([*?])/)
|
|
92
|
+
.map((part) => (part === "*" ? ".*" : part === "?" ? "." : escapeRegExp(part)))
|
|
93
|
+
.join("");
|
|
94
|
+
return new RegExp(`^${body}$`, caseSensitive ? "" : "i");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Compile ONE pattern into a predicate, or `undefined` when the entry is empty
|
|
99
|
+
* or an unparseable regex literal.
|
|
100
|
+
*
|
|
101
|
+
* Callers that want a whole list should use {@link toPatternMatcher}; this is
|
|
102
|
+
* exported for the case where a consumer applies its own semantics to some
|
|
103
|
+
* shapes and only wants the glob/regex handling (the email gate's bare-domain
|
|
104
|
+
* shortcut, for one).
|
|
105
|
+
*/
|
|
106
|
+
export function toPattern(
|
|
107
|
+
pattern: string,
|
|
108
|
+
options: PatternOptions = {},
|
|
109
|
+
): predicate.Predicate<string> | undefined {
|
|
110
|
+
const trimmed = pattern.trim();
|
|
111
|
+
if (!trimmed) return undefined;
|
|
112
|
+
const caseSensitive = options.caseSensitive ?? false;
|
|
113
|
+
|
|
114
|
+
if (isRegexLiteral(trimmed)) {
|
|
115
|
+
const compiled = compileRegexLiteral(trimmed, caseSensitive);
|
|
116
|
+
return compiled && predicate.create<string>((value) => compiled.test(value));
|
|
117
|
+
}
|
|
118
|
+
if (isGlob(trimmed)) {
|
|
119
|
+
const compiled = compileGlob(trimmed, caseSensitive);
|
|
120
|
+
return predicate.create<string>((value) => compiled.test(value));
|
|
121
|
+
}
|
|
122
|
+
// Literal: whole-string equality.
|
|
123
|
+
const expected = caseSensitive ? trimmed : trimmed.toLowerCase();
|
|
124
|
+
return predicate.create<string>((value) =>
|
|
125
|
+
caseSensitive ? value === expected : value.toLowerCase() === expected,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Compile patterns into a single OR'd {@link Predicate}. Accepts the raw config
|
|
131
|
+
* shapes {@link parseList} does - an array, or one comma/whitespace-separated
|
|
132
|
+
* string - so a field and its env var need no separate handling.
|
|
133
|
+
*
|
|
134
|
+
* With no usable patterns the result always returns `false`.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* const forwardable = toPatternMatcher(process.env.TUNNEL_FORWARD_HEADERS);
|
|
138
|
+
*/
|
|
139
|
+
export function toPatternMatcher(
|
|
140
|
+
patterns: string | readonly string[] | undefined | null,
|
|
141
|
+
options: PatternOptions = {},
|
|
142
|
+
): predicate.Predicate<string> {
|
|
143
|
+
const compiled = parseList(patterns)
|
|
144
|
+
.map((pattern) => toPattern(pattern, options))
|
|
145
|
+
.filter((value): value is predicate.Predicate<string> => value !== undefined);
|
|
146
|
+
if (compiled.length === 0) return predicate.create<string>(() => false);
|
|
147
|
+
return compiled.slice(1).reduce((acc, next) => acc.or(next), compiled[0]!);
|
|
148
|
+
}
|
package/src/token.ts
CHANGED
|
@@ -15,6 +15,23 @@ const BEARER_PREFIX_REGEX = /^bearer\s+/i;
|
|
|
15
15
|
const SPLIT_REGEX = /\s+|\s*,\s*/;
|
|
16
16
|
const log = logger("shared/token");
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Header the Databricks Apps front door forwards the caller's OAuth (OBO) token
|
|
20
|
+
* on - the default source for every helper here.
|
|
21
|
+
*
|
|
22
|
+
* Exported because it is a wire contract several packages branch on, not just a
|
|
23
|
+
* default argument: `@dbx-tools/appkit`'s `identity` module decides whether a
|
|
24
|
+
* request can use OBO auth at all by its presence, and `@dbx-tools/cli-tunnel`
|
|
25
|
+
* must know the name to strip inbound copies of it. One spelling, one place.
|
|
26
|
+
*/
|
|
27
|
+
export const ACCESS_TOKEN_HEADER = "x-forwarded-access-token";
|
|
28
|
+
|
|
29
|
+
/** Header the front door forwards the caller's user id on. */
|
|
30
|
+
export const USER_ID_HEADER = "x-forwarded-user";
|
|
31
|
+
|
|
32
|
+
/** Header the front door forwards the caller's email on. */
|
|
33
|
+
export const USER_EMAIL_HEADER = "x-forwarded-email";
|
|
34
|
+
|
|
18
35
|
/**
|
|
19
36
|
* Decode a JWT segment (base64url with standard base64 padding), or
|
|
20
37
|
* `undefined` when the segment is not valid base64.
|
|
@@ -39,7 +56,7 @@ function decodeJwtSegment(segment: string): string | undefined {
|
|
|
39
56
|
*/
|
|
40
57
|
export function getAccessTokenPayload(
|
|
41
58
|
input: HeaderLike | string,
|
|
42
|
-
headerName: string | undefined =
|
|
59
|
+
headerName: string | undefined = ACCESS_TOKEN_HEADER,
|
|
43
60
|
): Record<string, unknown> {
|
|
44
61
|
let accessTokenPayload: Record<string, unknown> | undefined;
|
|
45
62
|
if (!(typeof input === "string")) {
|