@dbx-tools/shared-core 0.3.44 → 0.4.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/lib/index.d.ts +36 -0
- package/lib/index.js +30 -0
- package/lib/src/async.d.ts +152 -0
- package/lib/src/async.js +163 -0
- package/lib/src/brand.d.ts +94 -0
- package/lib/src/brand.js +123 -0
- package/lib/src/error.d.ts +76 -0
- package/lib/src/error.js +168 -0
- package/lib/src/function.d.ts +38 -0
- package/lib/src/function.js +44 -0
- package/lib/src/hash.d.ts +102 -0
- package/lib/src/hash.js +274 -0
- package/lib/src/http.d.ts +79 -0
- package/lib/src/http.js +189 -0
- package/lib/src/json.d.ts +48 -0
- package/lib/src/json.js +49 -0
- package/lib/src/log.d.ts +86 -0
- package/lib/src/log.js +352 -0
- package/lib/src/net.d.ts +246 -0
- package/lib/src/net.js +465 -0
- package/lib/src/object.d.ts +382 -0
- package/lib/src/object.js +749 -0
- package/lib/src/predicate.d.ts +81 -0
- package/lib/src/predicate.js +43 -0
- package/lib/src/string.d.ts +221 -0
- package/lib/src/string.js +509 -0
- package/lib/src/token.d.ts +30 -0
- package/lib/src/token.js +126 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +9 -5
package/lib/src/net.d.ts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe networking helpers built around {@link urlBuilder}: a
|
|
3
|
+
* tolerant `URL` coercion + chainable builder that gracefully handles
|
|
4
|
+
* partial inputs (bare hosts, path-only strings, `{ url }` wrappers),
|
|
5
|
+
* a small IPv4 / IPv6 address + CIDR toolkit (parsing and membership
|
|
6
|
+
* lookups), and email-address parsing ({@link parseEmails} /
|
|
7
|
+
* {@link isEmail}) that normalizes the CSV / single-string / array
|
|
8
|
+
* inputs email recipient and allow-list fields accept into a clean
|
|
9
|
+
* `string[]`. No node-only imports, so this module is the canonical
|
|
10
|
+
* home for anything URL-, IP-, or email-shaped that also has to run in
|
|
11
|
+
* a Vite / Webpack / esbuild client bundle. Node-only network helpers
|
|
12
|
+
* (e.g. DNS resolution) belong in a node-tagged package, not here.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import type { NonFunctionKeys } from "./object.js";
|
|
17
|
+
/**
|
|
18
|
+
* Anything {@link urlBuilder} (and {@link pathMatch}) know how to coerce
|
|
19
|
+
* into a URL:
|
|
20
|
+
*
|
|
21
|
+
* - A string: a host, a full URL, or a path / query / hash fragment.
|
|
22
|
+
* - A WHATWG `URL` instance.
|
|
23
|
+
* - Any object with a `url` field (e.g. a fetch `Request`, a Databricks
|
|
24
|
+
* `WorkspaceClient` config).
|
|
25
|
+
*/
|
|
26
|
+
export type UrlLike = string | URL | {
|
|
27
|
+
url: string;
|
|
28
|
+
};
|
|
29
|
+
/** IP protocol family: `4` for IPv4, `6` for IPv6. */
|
|
30
|
+
export type IpVersion = 4 | 6;
|
|
31
|
+
/**
|
|
32
|
+
* A parsed IP address. `value` is the address as an unsigned integer
|
|
33
|
+
* (a 32-bit range for v4, 128-bit for v6) held in a `bigint` so both
|
|
34
|
+
* families share one comparison / masking path. Produce one with
|
|
35
|
+
* {@link parseIp}.
|
|
36
|
+
*/
|
|
37
|
+
export interface ParsedIp {
|
|
38
|
+
version: IpVersion;
|
|
39
|
+
/** The address as an unsigned integer (`bigint` for uniform v4/v6 math). */
|
|
40
|
+
value: bigint;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A parsed CIDR block (`10.0.0.0/8`, `2001:db8::/32`). `base` is the
|
|
44
|
+
* network address with all host bits cleared, so membership is a
|
|
45
|
+
* single masked compare (see {@link ipInCidr}). Produce one with
|
|
46
|
+
* {@link parseCidr}. Carries the normalized `cidr` string for logging
|
|
47
|
+
* and to key back to caller-side metadata.
|
|
48
|
+
*/
|
|
49
|
+
export interface Cidr {
|
|
50
|
+
version: IpVersion;
|
|
51
|
+
/** Network address (host bits zeroed) as an unsigned `bigint`. */
|
|
52
|
+
base: bigint;
|
|
53
|
+
/** Prefix length in bits (the number after the `/`). */
|
|
54
|
+
prefix: number;
|
|
55
|
+
/** Normalized `<address>/<prefix>` string. */
|
|
56
|
+
cidr: string;
|
|
57
|
+
}
|
|
58
|
+
/** Settable, non-method `URL` properties - the keys {@link UrlBuilder.with} accepts. */
|
|
59
|
+
type UrlPropertyKey = NonFunctionKeys<UrlBuilderImpl>;
|
|
60
|
+
/**
|
|
61
|
+
* A `URL` subclass with chainable, copy-on-write helpers. Every mutating
|
|
62
|
+
* method returns a fresh builder rather than editing in place, so a base
|
|
63
|
+
* builder can be safely reused. Construct one via {@link urlBuilder}.
|
|
64
|
+
*/
|
|
65
|
+
declare class UrlBuilderImpl extends URL {
|
|
66
|
+
constructor(url: URL);
|
|
67
|
+
/** The scheme without the trailing colon (`https`, not `https:`). */
|
|
68
|
+
get scheme(): string;
|
|
69
|
+
set scheme(value: string);
|
|
70
|
+
/**
|
|
71
|
+
* Return a copy with a single `URL` property (`pathname`, `search`,
|
|
72
|
+
* `hostname`, `scheme`, ...) set to `value`, leaving this builder
|
|
73
|
+
* untouched.
|
|
74
|
+
*/
|
|
75
|
+
with<K extends UrlPropertyKey>(key: K, value: UrlBuilderImpl[K]): UrlBuilder;
|
|
76
|
+
/**
|
|
77
|
+
* Return a copy with `pathSegments` appended to the current pathname.
|
|
78
|
+
* Segments may be strings or string arrays; each is trimmed of
|
|
79
|
+
* boundary slashes and blanks are dropped before joining with `/`.
|
|
80
|
+
*/
|
|
81
|
+
withPathAppend(...pathSegments: (string | string[])[]): UrlBuilder;
|
|
82
|
+
/**
|
|
83
|
+
* Return a copy whose pathname is `pathSegments` joined with `/`,
|
|
84
|
+
* replacing any existing path. Segments may be strings or string
|
|
85
|
+
* arrays; each is trimmed of boundary slashes and blanks are dropped.
|
|
86
|
+
*/
|
|
87
|
+
withPathReplace(...pathSegments: (string | string[])[]): UrlBuilder;
|
|
88
|
+
/**
|
|
89
|
+
* Test whether this URL's pathname is `path` or lives beneath it,
|
|
90
|
+
* matching on segment boundaries so `/api` matches `/api` and
|
|
91
|
+
* `/api/cool` but not `/apicool`. A missing leading slash on `path`
|
|
92
|
+
* is tolerated; query and hash are ignored (they aren't part of
|
|
93
|
+
* `pathname`). Matching is exact otherwise - trailing slashes are
|
|
94
|
+
* not normalized and `/` matches only the root.
|
|
95
|
+
*/
|
|
96
|
+
pathMatches(path: string): boolean;
|
|
97
|
+
}
|
|
98
|
+
/** Public type for the {@link urlBuilder} return value. */
|
|
99
|
+
export type UrlBuilder = UrlBuilderImpl;
|
|
100
|
+
/** With no argument, resolves to the base origin (never `null`). */
|
|
101
|
+
export declare function urlBuilder(): UrlBuilder;
|
|
102
|
+
/**
|
|
103
|
+
* Coerce a {@link UrlLike} into a chainable {@link UrlBuilder}, or `null`
|
|
104
|
+
* when the input cannot be parsed into a URL. Never throws.
|
|
105
|
+
*
|
|
106
|
+
* - A `URL` instance or `{ url }` wrapper is adopted as-is.
|
|
107
|
+
* - A bare hostname (`"example.com"`) is upgraded to `https://`; an
|
|
108
|
+
* explicit scheme is preserved.
|
|
109
|
+
* - A path / query / hash fragment (`"/api"`, `"?q=1"`, `"#x"`) is
|
|
110
|
+
* resolved against {@link defaultUrl} (the browser origin, else
|
|
111
|
+
* `http://localhost`).
|
|
112
|
+
* - An empty / blank string or omitted input resolves to the base
|
|
113
|
+
* origin.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* urlBuilder("example.com"); // https://example.com/
|
|
117
|
+
* urlBuilder("http://x/path"); // http://x/path
|
|
118
|
+
* urlBuilder("/api/v2"); // http://localhost/api/v2
|
|
119
|
+
* urlBuilder({ url: "http://y" }); // http://y/
|
|
120
|
+
* urlBuilder(); // http://localhost/
|
|
121
|
+
*/
|
|
122
|
+
export declare function urlBuilder(input?: UrlLike): UrlBuilder | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* Convenience wrapper over {@link UrlBuilder.pathMatches}: coerce
|
|
125
|
+
* `input` via {@link urlBuilder} and test its pathname against `path`.
|
|
126
|
+
* Returns `false` for input that can't be parsed into a URL.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* pathMatch("/api/cool?q=1", "/api"); // true
|
|
130
|
+
* pathMatch("/apicool", "/api"); // false
|
|
131
|
+
* pathMatch("https://host/api", "/api"); // true
|
|
132
|
+
* pathMatch(request, "/api/v2"); // fetch Request
|
|
133
|
+
*/
|
|
134
|
+
export declare function pathMatch(input: UrlLike, path: string): boolean;
|
|
135
|
+
/** Options for {@link parseEmails}. */
|
|
136
|
+
export interface ParseEmailsOptions {
|
|
137
|
+
/** Lower-case every address (useful for allow-lists / matching). Off by default. */
|
|
138
|
+
lowercase?: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Drop later case-insensitive duplicates, keeping first-seen casing.
|
|
141
|
+
* On by default - a recipient or pattern list rarely wants repeats.
|
|
142
|
+
*/
|
|
143
|
+
dedupe?: boolean;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Normalize the shapes an email address field accepts - a single string,
|
|
147
|
+
* a comma / semicolon / whitespace separated list, an array of either,
|
|
148
|
+
* or nothing - into a clean `string[]`. Each entry is split on the list
|
|
149
|
+
* separators, trimmed, and de-emptied; blanks and non-string array
|
|
150
|
+
* members are dropped. By default duplicates are removed
|
|
151
|
+
* case-insensitively (first-seen casing wins) and casing is otherwise
|
|
152
|
+
* preserved; pass `lowercase` to fold everything to lower case (e.g. for
|
|
153
|
+
* an allow-list). This is the one place recipient lists, CC/BCC inputs,
|
|
154
|
+
* and sender allow-lists across the repo agree on how free-text email
|
|
155
|
+
* input is read. Never throws; does not validate - pair with
|
|
156
|
+
* {@link isEmail} when you need to reject malformed addresses.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* parseEmails("a@x.com, b@y.com; a@x.com"); // ["a@x.com", "b@y.com"]
|
|
160
|
+
* parseEmails(["A@x.com", " b@y.com "]); // ["A@x.com", "b@y.com"]
|
|
161
|
+
* parseEmails("*@corp.com", { lowercase: true }); // ["*@corp.com"]
|
|
162
|
+
* parseEmails(undefined); // []
|
|
163
|
+
*/
|
|
164
|
+
export declare function parseEmails(input: string | readonly string[] | null | undefined, options?: ParseEmailsOptions): string[];
|
|
165
|
+
/**
|
|
166
|
+
* Pragmatic `local@domain.tld` shape check: non-empty local and domain
|
|
167
|
+
* parts around a single `@`, with a dotted domain and no whitespace.
|
|
168
|
+
* Deliberately loose (not full RFC 5322) - enough to catch obvious typos
|
|
169
|
+
* and give CLI / form feedback, not to gate delivery. Trims first. This
|
|
170
|
+
* is a purely syntactic test, so a wildcard allow-list pattern like
|
|
171
|
+
* `*@example.com` passes; distinguishing a pattern from a real address
|
|
172
|
+
* is the sender policy's job, not this validator's.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* isEmail("alice@example.com"); // true
|
|
176
|
+
* isEmail("nope"); // false (no @)
|
|
177
|
+
* isEmail("no@domain"); // false (no dotted domain)
|
|
178
|
+
*/
|
|
179
|
+
export declare function isEmail(value: string): boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Parse an IPv4 (`"1.2.3.4"`) or IPv6 (`"2001:db8::1"`,
|
|
182
|
+
* `"::ffff:1.2.3.4"`, `"::1"`) address into a {@link ParsedIp}, or
|
|
183
|
+
* `null` when the input isn't a valid literal. Never throws. Surrounding
|
|
184
|
+
* whitespace, `[...]` brackets around an IPv6 literal, and an IPv6 zone
|
|
185
|
+
* id (`fe80::1%eth0`) are all tolerated. The `value` is returned as a
|
|
186
|
+
* `bigint` so v4 and v6 share one comparison path.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* parseIp("10.0.0.1"); // { version: 4, value: 167772161n }
|
|
190
|
+
* parseIp("2001:db8::1"); // { version: 6, value: ... }
|
|
191
|
+
* parseIp("not-an-ip"); // null
|
|
192
|
+
*/
|
|
193
|
+
export declare function parseIp(input: string): ParsedIp | null;
|
|
194
|
+
/**
|
|
195
|
+
* Parse a CIDR block (`"10.0.0.0/8"`, `"2001:db8::/32"`) into a
|
|
196
|
+
* {@link Cidr} with host bits cleared from `base`, or `null` when the
|
|
197
|
+
* input isn't a valid block (bad address, missing / out-of-range
|
|
198
|
+
* prefix). Never throws.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* parseCidr("10.0.0.0/8")?.base; // 167772160n (10.0.0.0)
|
|
202
|
+
* parseCidr("10.1.2.3/8")?.base; // 167772160n (host bits dropped)
|
|
203
|
+
* parseCidr("10.0.0.0/40"); // null (prefix > 32 for v4)
|
|
204
|
+
*/
|
|
205
|
+
export declare function parseCidr(input: string): Cidr | null;
|
|
206
|
+
/**
|
|
207
|
+
* Test whether `ip` falls inside `cidr`. Both arguments accept either
|
|
208
|
+
* a string (parsed on the fly via {@link parseIp} / {@link parseCidr})
|
|
209
|
+
* or an already-parsed value - pass parsed values in hot loops to skip
|
|
210
|
+
* re-parsing. Returns `false` for unparseable input or a version
|
|
211
|
+
* mismatch (an IPv4 address is never inside an IPv6 block).
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ipInCidr("10.1.2.3", "10.0.0.0/8"); // true
|
|
215
|
+
* ipInCidr("11.0.0.1", "10.0.0.0/8"); // false
|
|
216
|
+
*/
|
|
217
|
+
export declare function ipInCidr(ip: string | ParsedIp, cidr: string | Cidr): boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Return the first CIDR in `cidrs` that contains `ip`, or `null` when
|
|
220
|
+
* none match. `cidrs` holds pre-parsed {@link Cidr} values (or any
|
|
221
|
+
* object extending it), so callers can carry side metadata on each
|
|
222
|
+
* entry (e.g. a region tag) and read it straight off the returned
|
|
223
|
+
* match. Linear scan; parse the address once by passing a
|
|
224
|
+
* {@link ParsedIp}.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* const ranges = ["10.0.0.0/8", "192.168.0.0/16"]
|
|
228
|
+
* .map(parseCidr)
|
|
229
|
+
* .filter((c): c is Cidr => c !== null);
|
|
230
|
+
* findContainingCidr("10.1.2.3", ranges)?.cidr; // "10.0.0.0/8"
|
|
231
|
+
*/
|
|
232
|
+
export declare function findContainingCidr<T extends Cidr>(ip: string | ParsedIp, cidrs: Iterable<T>): T | null;
|
|
233
|
+
/**
|
|
234
|
+
* Whether `input`'s host is a loopback address - `localhost`, an IPv4
|
|
235
|
+
* `127.0.0.0/8` address, or IPv6 `::1` - i.e. a service running on this
|
|
236
|
+
* machine (e.g. a local registry). Accepts anything {@link urlBuilder}
|
|
237
|
+
* coerces (a URL string, `URL`, or `{ url }`); returns `false` when the
|
|
238
|
+
* input has no resolvable host.
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* isLoopbackHost("http://localhost:4873"); // true
|
|
242
|
+
* isLoopbackHost("http://127.0.0.1"); // true
|
|
243
|
+
* isLoopbackHost("https://registry.npmjs.org"); // false
|
|
244
|
+
*/
|
|
245
|
+
export declare function isLoopbackHost(input: UrlLike): boolean;
|
|
246
|
+
export {};
|