@dbx-tools/shared-core 0.3.21 → 0.3.22
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 +1 -11
- package/package.json +1 -1
- package/src/async.ts +6 -3
- package/src/hash.ts +3 -2
- package/src/log.ts +6 -7
- package/src/net.ts +4 -6
- package/src/object.ts +19 -34
- package/src/predicate.ts +1 -3
- package/src/string.ts +1 -3
- package/src/token.ts +2 -7
package/README.md
CHANGED
|
@@ -7,17 +7,7 @@ browsers, workers, CLIs, and shared schema packages. Modules are exported as
|
|
|
7
7
|
namespaces so call sites stay explicit:
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import {
|
|
11
|
-
async,
|
|
12
|
-
error,
|
|
13
|
-
hash,
|
|
14
|
-
http,
|
|
15
|
-
log,
|
|
16
|
-
net,
|
|
17
|
-
object,
|
|
18
|
-
brand,
|
|
19
|
-
string,
|
|
20
|
-
} from "@dbx-tools/shared-core";
|
|
10
|
+
import { async, error, hash, http, log, net, object, brand, string } from "@dbx-tools/shared-core";
|
|
21
11
|
```
|
|
22
12
|
|
|
23
13
|
Node-only helpers live in [`@dbx-tools/core`](../../node/core). AppKit and
|
package/package.json
CHANGED
package/src/async.ts
CHANGED
|
@@ -152,7 +152,9 @@ export async function* poll<T, A = Record<string, unknown>>(
|
|
|
152
152
|
if (options.filter) {
|
|
153
153
|
if (options.filter === "distinct") {
|
|
154
154
|
if (deepEqual(previous, value)) continue;
|
|
155
|
-
} else if (!(await options.filter(value, ctx)))
|
|
155
|
+
} else if (!(await options.filter(value, ctx))) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
156
158
|
}
|
|
157
159
|
yield value;
|
|
158
160
|
if (predicate && !(await predicate(value, ctx))) return;
|
|
@@ -170,8 +172,9 @@ export async function* poll<T, A = Record<string, unknown>>(
|
|
|
170
172
|
* parent (so a fetch-level cancel doesn't tear down the main poll loop).
|
|
171
173
|
*/
|
|
172
174
|
export function tieAbortSignal(child: AbortController, parent?: AbortSignal): void {
|
|
173
|
-
if (!parent)
|
|
174
|
-
|
|
175
|
+
if (!parent) {
|
|
176
|
+
return;
|
|
177
|
+
} else if (parent.aborted) {
|
|
175
178
|
child.abort(parent.reason);
|
|
176
179
|
return;
|
|
177
180
|
}
|
package/src/hash.ts
CHANGED
|
@@ -215,8 +215,9 @@ const BASE32_ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
|
215
215
|
* fail fast instead of producing silently-degraded encodings.
|
|
216
216
|
*/
|
|
217
217
|
function base32Alphabet(alphabet?: string): string {
|
|
218
|
-
if (alphabet === undefined)
|
|
219
|
-
|
|
218
|
+
if (alphabet === undefined) {
|
|
219
|
+
return BASE32_ALPHABET;
|
|
220
|
+
} else if (new Set(alphabet).size !== 32) {
|
|
220
221
|
throw new Error("Base32 alphabet must contain 32 unique characters");
|
|
221
222
|
}
|
|
222
223
|
return alphabet;
|
package/src/log.ts
CHANGED
|
@@ -126,9 +126,8 @@ type LoggerFactory = (name?: string) => Logger;
|
|
|
126
126
|
* resolved factory (or the one resolved `undefined`). A rejection is evicted
|
|
127
127
|
* by {@link memoize} so a later call retries.
|
|
128
128
|
*/
|
|
129
|
-
const createConsolaLoggerFactory = memoize(
|
|
130
|
-
|
|
131
|
-
const consolaDisabled = toBoolean(globalProcess?.env?.LOG_CONSOLA_DISABLED);
|
|
129
|
+
const createConsolaLoggerFactory = memoize(async (): Promise<LoggerFactory | undefined> => {
|
|
130
|
+
const consolaDisabled = toBoolean(globalProcess?.env?.LOG_CONSOLA_DISABLED);
|
|
132
131
|
if (!consolaDisabled) {
|
|
133
132
|
try {
|
|
134
133
|
const { consola, createConsola, LogLevels } = await import(/* @vite-ignore */ "consola");
|
|
@@ -264,8 +263,7 @@ async function createConsoleLoggerFactory(globalProcessStdErr: any): Promise<Log
|
|
|
264
263
|
*/
|
|
265
264
|
const createLogger: LoggerFactory = await (async () => {
|
|
266
265
|
return (
|
|
267
|
-
(await createConsolaLoggerFactory()) ??
|
|
268
|
-
(await createConsoleLoggerFactory(globalProcessStdErr))
|
|
266
|
+
(await createConsolaLoggerFactory()) ?? (await createConsoleLoggerFactory(globalProcessStdErr))
|
|
269
267
|
);
|
|
270
268
|
})();
|
|
271
269
|
|
|
@@ -320,8 +318,9 @@ function parseLogLevel(raw: unknown): LogLevel | undefined {
|
|
|
320
318
|
if (text === normalized) break;
|
|
321
319
|
text = normalized;
|
|
322
320
|
}
|
|
323
|
-
if (!text)
|
|
324
|
-
|
|
321
|
+
if (!text) {
|
|
322
|
+
break;
|
|
323
|
+
} else if (text in LOG_LEVEL_RANK) {
|
|
325
324
|
return text as LogLevel;
|
|
326
325
|
}
|
|
327
326
|
}
|
package/src/net.ts
CHANGED
|
@@ -127,9 +127,7 @@ class UrlBuilderImpl extends URL {
|
|
|
127
127
|
* arrays; each is trimmed of boundary slashes and blanks are dropped.
|
|
128
128
|
*/
|
|
129
129
|
withPathReplace(...pathSegments: (string | string[])[]): UrlBuilder {
|
|
130
|
-
const pathnameParts: string[] = [...pathSegments].flatMap((p) =>
|
|
131
|
-
Array.isArray(p) ? p : [p],
|
|
132
|
-
);
|
|
130
|
+
const pathnameParts: string[] = [...pathSegments].flatMap((p) => (Array.isArray(p) ? p : [p]));
|
|
133
131
|
const pathname = pathnameParts
|
|
134
132
|
.map((p) => p.replace(URL_PATH_SEGMENT_TRIM, ""))
|
|
135
133
|
.filter(Boolean)
|
|
@@ -242,8 +240,8 @@ export function pathMatch(input: UrlLike, path: string): boolean {
|
|
|
242
240
|
function defaultUrl(): URL {
|
|
243
241
|
// Reach `window` via `globalThis` so this compiles without the DOM
|
|
244
242
|
// lib (it's `undefined` on the server / in workers without one).
|
|
245
|
-
const origin = (globalThis as { window?: { location?: { origin?: string } } }).window
|
|
246
|
-
?.
|
|
243
|
+
const origin = (globalThis as { window?: { location?: { origin?: string } } }).window?.location
|
|
244
|
+
?.origin;
|
|
247
245
|
if (origin && origin !== "null") {
|
|
248
246
|
const originUrl = parseUrl(origin);
|
|
249
247
|
if (originUrl) {
|
|
@@ -257,7 +255,7 @@ function parseUrl(input: string): URL | null {
|
|
|
257
255
|
if (input && input.includes(URL_SCHEME_SEPARATOR)) {
|
|
258
256
|
try {
|
|
259
257
|
return new URL(input);
|
|
260
|
-
} catch {
|
|
258
|
+
} catch {}
|
|
261
259
|
}
|
|
262
260
|
return null;
|
|
263
261
|
}
|
package/src/object.ts
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
/** Lazy sequence over iterable source(s). See {@link sequence}. */
|
|
20
20
|
export type Sequence<T> = SequenceImpl<T>;
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
type SequenceSource<T> = Iterable<T> | ReadonlyMap<unknown, T> | OneOrMany<T> | null | undefined;
|
|
24
23
|
|
|
25
24
|
/**
|
|
@@ -58,9 +57,6 @@ type GroupValue<T, P> = P extends (value: any, ...rest: any[]) => value is infer
|
|
|
58
57
|
/** A map of group name -> predicate, as accepted by {@link group}. */
|
|
59
58
|
type GroupPredicates<T> = Record<string, (value: T, index: number) => boolean>;
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
60
|
/**
|
|
65
61
|
* Type guard for a {@link Collection}: an {@link Array}, {@link Set}, or
|
|
66
62
|
* {@link Map}. Narrows `value` so its element/value type is treated as `T`.
|
|
@@ -84,19 +80,17 @@ export function isEmpty(
|
|
|
84
80
|
collection: Collection<unknown> | Record<string, unknown>,
|
|
85
81
|
options?: { recursive?: boolean },
|
|
86
82
|
): boolean {
|
|
87
|
-
|
|
88
83
|
function visit(value: unknown, seen?: Set<unknown>): boolean {
|
|
89
|
-
if (value == null)
|
|
90
|
-
|
|
84
|
+
if (value == null) {
|
|
85
|
+
return true;
|
|
86
|
+
} else if (typeof value === "object") {
|
|
91
87
|
if (seen?.has(value)) return true;
|
|
92
88
|
seen?.add(value);
|
|
93
89
|
if (Array.isArray(value)) {
|
|
94
90
|
return value.length === 0 || (seen ? value.every((item) => visit(item, seen)) : false);
|
|
95
91
|
}
|
|
96
92
|
if (value instanceof Set) {
|
|
97
|
-
return (
|
|
98
|
-
value.size === 0 || (seen ? [...value].every((item) => visit(item, seen)) : false)
|
|
99
|
-
);
|
|
93
|
+
return value.size === 0 || (seen ? [...value].every((item) => visit(item, seen)) : false);
|
|
100
94
|
}
|
|
101
95
|
if (value instanceof Map) {
|
|
102
96
|
return (
|
|
@@ -105,11 +99,12 @@ export function isEmpty(
|
|
|
105
99
|
);
|
|
106
100
|
}
|
|
107
101
|
const keys = Object.keys(value);
|
|
108
|
-
if (keys.length === 0)
|
|
109
|
-
|
|
102
|
+
if (keys.length === 0) {
|
|
103
|
+
return true;
|
|
104
|
+
} else if (seen) {
|
|
110
105
|
return keys.every((key) => visit((value as Record<string, unknown>)[key], seen));
|
|
111
106
|
} else {
|
|
112
|
-
return false
|
|
107
|
+
return false;
|
|
113
108
|
}
|
|
114
109
|
} else {
|
|
115
110
|
return false;
|
|
@@ -118,7 +113,6 @@ export function isEmpty(
|
|
|
118
113
|
return visit(collection, options?.recursive ? new Set() : undefined);
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
|
|
122
116
|
/**
|
|
123
117
|
* Normalizes a source to an iterable of its `T` values, so Maps are treated
|
|
124
118
|
* uniformly with arrays/sets: a {@link Map} yields its *values* (matching
|
|
@@ -154,7 +148,6 @@ export function isContainer<T = unknown>(value: unknown): value is Container<T>
|
|
|
154
148
|
);
|
|
155
149
|
}
|
|
156
150
|
|
|
157
|
-
|
|
158
151
|
function sequenceSources<T>(...sources: SequenceSource<T>[]): Iterable<T>[] {
|
|
159
152
|
const sourceIterables: Iterable<T>[] = [];
|
|
160
153
|
for (const source of sources) {
|
|
@@ -526,7 +519,7 @@ export function at<T>(index: number, ...sources: readonly Source<T>[]): T | unde
|
|
|
526
519
|
return undefined;
|
|
527
520
|
}
|
|
528
521
|
|
|
529
|
-
export function toOneOrMany<T>(input:
|
|
522
|
+
export function toOneOrMany<T>(input: T | OneOrMany<T>): OneOrMany<T> {
|
|
530
523
|
return Array.isArray(input) ? input : [input];
|
|
531
524
|
}
|
|
532
525
|
|
|
@@ -585,7 +578,7 @@ class SequenceImpl<T> {
|
|
|
585
578
|
// beginning.
|
|
586
579
|
const buffer = this.buffer!;
|
|
587
580
|
let index = 0;
|
|
588
|
-
for (
|
|
581
|
+
for (;;) {
|
|
589
582
|
if (index < buffer.length) {
|
|
590
583
|
yield buffer[index++]!;
|
|
591
584
|
continue;
|
|
@@ -648,9 +641,7 @@ class SequenceImpl<T> {
|
|
|
648
641
|
*
|
|
649
642
|
* @see {@link sequence}
|
|
650
643
|
*/
|
|
651
|
-
join(
|
|
652
|
-
...sources: readonly SequenceSource<T>[]
|
|
653
|
-
): Sequence<T> {
|
|
644
|
+
join(...sources: readonly SequenceSource<T>[]): Sequence<T> {
|
|
654
645
|
const sourceIterables = sequenceSources(this, ...sources);
|
|
655
646
|
return sequenceSources.length === 0 ? this : sequence(...sourceIterables);
|
|
656
647
|
}
|
|
@@ -751,9 +742,7 @@ const emptySequence: Sequence<never> = new SequenceImpl([], undefined, {
|
|
|
751
742
|
* @typeParam T - Element type of the sequence.
|
|
752
743
|
* @param sources - Iterables to concatenate, in order (`Map` sources use values).
|
|
753
744
|
*/
|
|
754
|
-
export function sequence<T>(
|
|
755
|
-
...sources: readonly SequenceSource<T>[]
|
|
756
|
-
): Sequence<T> {
|
|
745
|
+
export function sequence<T>(...sources: readonly SequenceSource<T>[]): Sequence<T> {
|
|
757
746
|
// Skip nullish sources and known-empty collections; normalize the rest to
|
|
758
747
|
// their values so a Map contributes values rather than [key, value] entries.
|
|
759
748
|
const sourceIterables = sequenceSources(...sources);
|
|
@@ -773,8 +762,6 @@ export function sequence<T>(
|
|
|
773
762
|
);
|
|
774
763
|
}
|
|
775
764
|
|
|
776
|
-
|
|
777
|
-
|
|
778
765
|
/**
|
|
779
766
|
* Flattens a mix of single items and iterables into one lazy {@link Generator}.
|
|
780
767
|
*
|
|
@@ -800,10 +787,6 @@ export function* generator<T>(
|
|
|
800
787
|
}
|
|
801
788
|
}
|
|
802
789
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
790
|
// ---------------------------------------------------------------------------
|
|
808
791
|
// Object value guards, coercions, and structural equality
|
|
809
792
|
// ---------------------------------------------------------------------------
|
|
@@ -836,8 +819,9 @@ export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
836
819
|
* well as the numbers `1` and `0`.
|
|
837
820
|
*/
|
|
838
821
|
export function toBoolean(value: unknown): boolean | undefined {
|
|
839
|
-
if (typeof value === "boolean")
|
|
840
|
-
|
|
822
|
+
if (typeof value === "boolean") {
|
|
823
|
+
return value;
|
|
824
|
+
} else if (typeof value === "string") {
|
|
841
825
|
value = value.trim().toLowerCase();
|
|
842
826
|
if (
|
|
843
827
|
value === "true" ||
|
|
@@ -846,17 +830,18 @@ export function toBoolean(value: unknown): boolean | undefined {
|
|
|
846
830
|
value === "1" ||
|
|
847
831
|
value === "yes" ||
|
|
848
832
|
value === "y"
|
|
849
|
-
)
|
|
833
|
+
) {
|
|
850
834
|
return true;
|
|
851
|
-
else if (
|
|
835
|
+
} else if (
|
|
852
836
|
value === "false" ||
|
|
853
837
|
value == "f" ||
|
|
854
838
|
value === "off" ||
|
|
855
839
|
value === "0" ||
|
|
856
840
|
value === "no" ||
|
|
857
841
|
value === "n"
|
|
858
|
-
)
|
|
842
|
+
) {
|
|
859
843
|
return false;
|
|
844
|
+
}
|
|
860
845
|
} else if (typeof value === "number") {
|
|
861
846
|
if (value === 1) return true;
|
|
862
847
|
else if (value === 0) return false;
|
package/src/predicate.ts
CHANGED
|
@@ -137,9 +137,7 @@ function buildPredicate<T, U extends T>(test: (value: T) => unknown): Predicate<
|
|
|
137
137
|
/**
|
|
138
138
|
* Wraps a type predicate while preserving its narrowed type.
|
|
139
139
|
*/
|
|
140
|
-
export function create<T, U extends T>(
|
|
141
|
-
predicate: TypePredicateFunction<T, U>,
|
|
142
|
-
): Predicate<T, U>;
|
|
140
|
+
export function create<T, U extends T>(predicate: TypePredicateFunction<T, U>): Predicate<T, U>;
|
|
143
141
|
|
|
144
142
|
/**
|
|
145
143
|
* Wraps an ordinary boolean or truthy predicate.
|
package/src/string.ts
CHANGED
|
@@ -520,9 +520,7 @@ export function pluralize(count: number, noun: string): string {
|
|
|
520
520
|
* {@link TokenizeOptions} (e.g. `camelCase: false`) merge over the defaults.
|
|
521
521
|
*/
|
|
522
522
|
export function toLabel(value: string, options?: TokenizeOptions): string {
|
|
523
|
-
const tokens = [
|
|
524
|
-
...tokenizeWithOptions({ lowerCase: true, capitalize: true, ...options }, value),
|
|
525
|
-
];
|
|
523
|
+
const tokens = [...tokenizeWithOptions({ lowerCase: true, capitalize: true, ...options }, value)];
|
|
526
524
|
return tokens.length > 0 ? tokens.join(" ") : value;
|
|
527
525
|
}
|
|
528
526
|
|
package/src/token.ts
CHANGED
|
@@ -37,9 +37,7 @@ export function getAccessTokenPayload(
|
|
|
37
37
|
if (!(typeof input === "string")) {
|
|
38
38
|
if (headerName) {
|
|
39
39
|
forEachHeaderValue(input, headerName, (value: string) => {
|
|
40
|
-
for (const [payloadKey, payloadValue] of Object.entries(
|
|
41
|
-
getAccessTokenPayload(value),
|
|
42
|
-
)) {
|
|
40
|
+
for (const [payloadKey, payloadValue] of Object.entries(getAccessTokenPayload(value))) {
|
|
43
41
|
if (!accessTokenPayload || !(payloadKey in accessTokenPayload)) {
|
|
44
42
|
if (!accessTokenPayload) accessTokenPayload = {};
|
|
45
43
|
accessTokenPayload[payloadKey] = payloadValue;
|
|
@@ -98,10 +96,7 @@ export function getAccessTokenScopes(
|
|
|
98
96
|
* Accepts the raw {@link MASTRA_SCOPES_KEY} array stamped on
|
|
99
97
|
* `RequestContext` as well as iterables from {@link getAccessTokenScopes}.
|
|
100
98
|
*/
|
|
101
|
-
export function includesAccessTokenScope(
|
|
102
|
-
scopes: unknown,
|
|
103
|
-
allowed: readonly string[],
|
|
104
|
-
): boolean {
|
|
99
|
+
export function includesAccessTokenScope(scopes: unknown, allowed: readonly string[]): boolean {
|
|
105
100
|
if (allowed.length) {
|
|
106
101
|
for (const scope of iterateClaims(scopes)) {
|
|
107
102
|
if (allowed.includes(scope)) {
|