@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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fluent, callable predicate combinators that preserve TypeScript type guards.
|
|
3
|
+
*
|
|
4
|
+
* A Predicate<T, U> is:
|
|
5
|
+
* - Callable as `(value: T) => value is U`
|
|
6
|
+
* - Composable through `.and()`, `.or()`, and `.negate()`
|
|
7
|
+
*
|
|
8
|
+
* Ordinary boolean predicates are treated as narrowing to `T`, meaning they
|
|
9
|
+
* do not narrow the input type by themselves. Composed predicates passed to
|
|
10
|
+
* `.and()` / `.or()` may return any value; they are tested for truthiness.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
/** An ordinary boolean predicate. */
|
|
15
|
+
export type PredicateFunction<T> = (value: T) => boolean;
|
|
16
|
+
/** A predicate that narrows T to U. */
|
|
17
|
+
export type TypePredicateFunction<T, U extends T> = (value: T) => value is U;
|
|
18
|
+
/** A predicate tested for truthiness when composed with `.and()` / `.or()`. */
|
|
19
|
+
export type PredicateInput<T> = (value: T) => unknown;
|
|
20
|
+
/**
|
|
21
|
+
* Extracts the narrowed type from a type predicate.
|
|
22
|
+
*
|
|
23
|
+
* Ordinary boolean predicates do not narrow, so they produce T. A guard whose
|
|
24
|
+
* narrowed type is disjoint from T (`Extract<U, T>` is `never`) is treated as a
|
|
25
|
+
* non-narrowing filter and keeps T, rather than collapsing the chain to `never` -
|
|
26
|
+
* this is what a negated narrowing guard looks like (e.g. `hasName(...).negate()`,
|
|
27
|
+
* which widens back to a supertype of T).
|
|
28
|
+
*/
|
|
29
|
+
type NarrowedBy<T, P> = P extends (value: any) => value is infer U ? [Extract<U, T>] extends [never] ? T : Extract<U, T> : T;
|
|
30
|
+
/** Intersects the narrowed types produced by a tuple of predicates. */
|
|
31
|
+
type AndNarrowed<T, P extends readonly PredicateInput<T>[], Result = T> = P extends readonly [
|
|
32
|
+
infer First,
|
|
33
|
+
...infer Rest extends readonly PredicateInput<T>[]
|
|
34
|
+
] ? AndNarrowed<T, Rest, Result & NarrowedBy<T, First>> : Result;
|
|
35
|
+
/** Unions the narrowed types produced by a tuple of predicates. */
|
|
36
|
+
type OrNarrowed<T, P extends readonly PredicateInput<T>[], Result = never> = P extends readonly [
|
|
37
|
+
infer First,
|
|
38
|
+
...infer Rest extends readonly PredicateInput<T>[]
|
|
39
|
+
] ? OrNarrowed<T, Rest, Result | NarrowedBy<T, First>> : Result;
|
|
40
|
+
/**
|
|
41
|
+
* A callable predicate with fluent composition methods.
|
|
42
|
+
*
|
|
43
|
+
* T is the accepted input type.
|
|
44
|
+
* U is the type established when the predicate returns true.
|
|
45
|
+
*/
|
|
46
|
+
export interface Predicate<T, U extends T = T> {
|
|
47
|
+
(value: T): value is U;
|
|
48
|
+
/**
|
|
49
|
+
* Returns a predicate requiring this predicate and every supplied predicate
|
|
50
|
+
* to match.
|
|
51
|
+
*
|
|
52
|
+
* Type guards are intersected. Additional predicates are checked against the
|
|
53
|
+
* type already established by this predicate.
|
|
54
|
+
*/
|
|
55
|
+
and<const P extends readonly PredicateInput<U>[]>(...predicates: P): Predicate<T, Extract<U & AndNarrowed<U, P>, T>>;
|
|
56
|
+
/**
|
|
57
|
+
* Returns a predicate requiring this predicate or any supplied predicate
|
|
58
|
+
* to match.
|
|
59
|
+
*
|
|
60
|
+
* Type guards are unioned. Because an ordinary boolean predicate could
|
|
61
|
+
* accept any value of `U`, including one causes the resulting predicate to
|
|
62
|
+
* narrow only to `U`.
|
|
63
|
+
*/
|
|
64
|
+
or<const P extends readonly PredicateInput<U>[]>(...predicates: P): Predicate<T, Extract<U | OrNarrowed<U, P>, T>>;
|
|
65
|
+
/**
|
|
66
|
+
* Returns the logical inverse of this predicate.
|
|
67
|
+
*
|
|
68
|
+
* For a type predicate narrowing T to U, the result narrows to
|
|
69
|
+
* Exclude<T, U>.
|
|
70
|
+
*/
|
|
71
|
+
negate(): Predicate<T, Exclude<T, U>>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Wraps a type predicate while preserving its narrowed type.
|
|
75
|
+
*/
|
|
76
|
+
export declare function create<T, U extends T>(predicate: TypePredicateFunction<T, U>): Predicate<T, U>;
|
|
77
|
+
/**
|
|
78
|
+
* Wraps an ordinary boolean or truthy predicate.
|
|
79
|
+
*/
|
|
80
|
+
export declare function create<T>(predicate: PredicateInput<T>): Predicate<T, T>;
|
|
81
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fluent, callable predicate combinators that preserve TypeScript type guards.
|
|
3
|
+
*
|
|
4
|
+
* A Predicate<T, U> is:
|
|
5
|
+
* - Callable as `(value: T) => value is U`
|
|
6
|
+
* - Composable through `.and()`, `.or()`, and `.negate()`
|
|
7
|
+
*
|
|
8
|
+
* Ordinary boolean predicates are treated as narrowing to `T`, meaning they
|
|
9
|
+
* do not narrow the input type by themselves. Composed predicates passed to
|
|
10
|
+
* `.and()` / `.or()` may return any value; they are tested for truthiness.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
/** Coerce a predicate result to boolean the way `if (...)` does. */
|
|
15
|
+
function isTruthy(test) {
|
|
16
|
+
return (value) => Boolean(test(value));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates the callable predicate object.
|
|
20
|
+
*
|
|
21
|
+
* The public generic behavior is provided by Predicate<T, U>. Runtime
|
|
22
|
+
* composition coerces predicate results to boolean; type predicates are
|
|
23
|
+
* ordinary boolean functions at runtime.
|
|
24
|
+
*/
|
|
25
|
+
function buildPredicate(test) {
|
|
26
|
+
const check = isTruthy(test);
|
|
27
|
+
const callable = ((value) => check(value));
|
|
28
|
+
return Object.assign(callable, {
|
|
29
|
+
and(...predicates) {
|
|
30
|
+
return buildPredicate((value) => check(value) && predicates.every((predicate) => isTruthy(predicate)(value)));
|
|
31
|
+
},
|
|
32
|
+
or(...predicates) {
|
|
33
|
+
return buildPredicate((value) => check(value) || predicates.some((predicate) => isTruthy(predicate)(value)));
|
|
34
|
+
},
|
|
35
|
+
negate() {
|
|
36
|
+
return buildPredicate((value) => !check(value));
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export function create(predicate) {
|
|
41
|
+
return buildPredicate(predicate);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlZGljYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ByZWRpY2F0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7O0dBWUc7QUFtRkgsb0VBQW9FO0FBQ3BFLFNBQVMsUUFBUSxDQUFJLElBQTJCO0lBQzlDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxjQUFjLENBQWlCLElBQTJCO0lBQ2pFLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3QixNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsS0FBUSxFQUFjLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQTZCLENBQUM7SUFFdEYsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtRQUM3QixHQUFHLENBQ0QsR0FBRyxVQUFhO1lBR2hCLE9BQU8sY0FBYyxDQUNuQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFVLENBQUMsQ0FBQyxDQUM1RixDQUFDO1FBQ0osQ0FBQztRQUVELEVBQUUsQ0FDQSxHQUFHLFVBQWE7WUFHaEIsT0FBTyxjQUFjLENBQ25CLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQVUsQ0FBQyxDQUFDLENBQzNGLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTTtZQUNKLE9BQU8sY0FBYyxDQUFtQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNwRSxDQUFDO0tBQ0YsQ0FBb0IsQ0FBQztBQUN4QixDQUFDO0FBWUQsTUFBTSxVQUFVLE1BQU0sQ0FDcEIsU0FBMEQ7SUFFMUQsT0FBTyxjQUFjLENBQU8sU0FBUyxDQUFDLENBQUM7QUFDekMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRmx1ZW50LCBjYWxsYWJsZSBwcmVkaWNhdGUgY29tYmluYXRvcnMgdGhhdCBwcmVzZXJ2ZSBUeXBlU2NyaXB0IHR5cGUgZ3VhcmRzLlxuICpcbiAqIEEgUHJlZGljYXRlPFQsIFU+IGlzOlxuICogLSBDYWxsYWJsZSBhcyBgKHZhbHVlOiBUKSA9PiB2YWx1ZSBpcyBVYFxuICogLSBDb21wb3NhYmxlIHRocm91Z2ggYC5hbmQoKWAsIGAub3IoKWAsIGFuZCBgLm5lZ2F0ZSgpYFxuICpcbiAqIE9yZGluYXJ5IGJvb2xlYW4gcHJlZGljYXRlcyBhcmUgdHJlYXRlZCBhcyBuYXJyb3dpbmcgdG8gYFRgLCBtZWFuaW5nIHRoZXlcbiAqIGRvIG5vdCBuYXJyb3cgdGhlIGlucHV0IHR5cGUgYnkgdGhlbXNlbHZlcy4gQ29tcG9zZWQgcHJlZGljYXRlcyBwYXNzZWQgdG9cbiAqIGAuYW5kKClgIC8gYC5vcigpYCBtYXkgcmV0dXJuIGFueSB2YWx1ZTsgdGhleSBhcmUgdGVzdGVkIGZvciB0cnV0aGluZXNzLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG4vKiogQW4gb3JkaW5hcnkgYm9vbGVhbiBwcmVkaWNhdGUuICovXG5leHBvcnQgdHlwZSBQcmVkaWNhdGVGdW5jdGlvbjxUPiA9ICh2YWx1ZTogVCkgPT4gYm9vbGVhbjtcblxuLyoqIEEgcHJlZGljYXRlIHRoYXQgbmFycm93cyBUIHRvIFUuICovXG5leHBvcnQgdHlwZSBUeXBlUHJlZGljYXRlRnVuY3Rpb248VCwgVSBleHRlbmRzIFQ+ID0gKHZhbHVlOiBUKSA9PiB2YWx1ZSBpcyBVO1xuXG4vKiogQSBwcmVkaWNhdGUgdGVzdGVkIGZvciB0cnV0aGluZXNzIHdoZW4gY29tcG9zZWQgd2l0aCBgLmFuZCgpYCAvIGAub3IoKWAuICovXG5leHBvcnQgdHlwZSBQcmVkaWNhdGVJbnB1dDxUPiA9ICh2YWx1ZTogVCkgPT4gdW5rbm93bjtcblxuLyoqXG4gKiBFeHRyYWN0cyB0aGUgbmFycm93ZWQgdHlwZSBmcm9tIGEgdHlwZSBwcmVkaWNhdGUuXG4gKlxuICogT3JkaW5hcnkgYm9vbGVhbiBwcmVkaWNhdGVzIGRvIG5vdCBuYXJyb3csIHNvIHRoZXkgcHJvZHVjZSBULiBBIGd1YXJkIHdob3NlXG4gKiBuYXJyb3dlZCB0eXBlIGlzIGRpc2pvaW50IGZyb20gVCAoYEV4dHJhY3Q8VSwgVD5gIGlzIGBuZXZlcmApIGlzIHRyZWF0ZWQgYXMgYVxuICogbm9uLW5hcnJvd2luZyBmaWx0ZXIgYW5kIGtlZXBzIFQsIHJhdGhlciB0aGFuIGNvbGxhcHNpbmcgdGhlIGNoYWluIHRvIGBuZXZlcmAgLVxuICogdGhpcyBpcyB3aGF0IGEgbmVnYXRlZCBuYXJyb3dpbmcgZ3VhcmQgbG9va3MgbGlrZSAoZS5nLiBgaGFzTmFtZSguLi4pLm5lZ2F0ZSgpYCxcbiAqIHdoaWNoIHdpZGVucyBiYWNrIHRvIGEgc3VwZXJ0eXBlIG9mIFQpLlxuICovXG50eXBlIE5hcnJvd2VkQnk8VCwgUD4gPSBQIGV4dGVuZHMgKHZhbHVlOiBhbnkpID0+IHZhbHVlIGlzIGluZmVyIFVcbiAgPyBbRXh0cmFjdDxVLCBUPl0gZXh0ZW5kcyBbbmV2ZXJdXG4gICAgPyBUXG4gICAgOiBFeHRyYWN0PFUsIFQ+XG4gIDogVDtcblxuLyoqIEludGVyc2VjdHMgdGhlIG5hcnJvd2VkIHR5cGVzIHByb2R1Y2VkIGJ5IGEgdHVwbGUgb2YgcHJlZGljYXRlcy4gKi9cbnR5cGUgQW5kTmFycm93ZWQ8VCwgUCBleHRlbmRzIHJlYWRvbmx5IFByZWRpY2F0ZUlucHV0PFQ+W10sIFJlc3VsdCA9IFQ+ID0gUCBleHRlbmRzIHJlYWRvbmx5IFtcbiAgaW5mZXIgRmlyc3QsXG4gIC4uLmluZmVyIFJlc3QgZXh0ZW5kcyByZWFkb25seSBQcmVkaWNhdGVJbnB1dDxUPltdLFxuXVxuICA/IEFuZE5hcnJvd2VkPFQsIFJlc3QsIFJlc3VsdCAmIE5hcnJvd2VkQnk8VCwgRmlyc3Q+PlxuICA6IFJlc3VsdDtcblxuLyoqIFVuaW9ucyB0aGUgbmFycm93ZWQgdHlwZXMgcHJvZHVjZWQgYnkgYSB0dXBsZSBvZiBwcmVkaWNhdGVzLiAqL1xudHlwZSBPck5hcnJvd2VkPFQsIFAgZXh0ZW5kcyByZWFkb25seSBQcmVkaWNhdGVJbnB1dDxUPltdLCBSZXN1bHQgPSBuZXZlcj4gPSBQIGV4dGVuZHMgcmVhZG9ubHkgW1xuICBpbmZlciBGaXJzdCxcbiAgLi4uaW5mZXIgUmVzdCBleHRlbmRzIHJlYWRvbmx5IFByZWRpY2F0ZUlucHV0PFQ+W10sXG5dXG4gID8gT3JOYXJyb3dlZDxULCBSZXN0LCBSZXN1bHQgfCBOYXJyb3dlZEJ5PFQsIEZpcnN0Pj5cbiAgOiBSZXN1bHQ7XG5cbi8qKlxuICogQSBjYWxsYWJsZSBwcmVkaWNhdGUgd2l0aCBmbHVlbnQgY29tcG9zaXRpb24gbWV0aG9kcy5cbiAqXG4gKiBUIGlzIHRoZSBhY2NlcHRlZCBpbnB1dCB0eXBlLlxuICogVSBpcyB0aGUgdHlwZSBlc3RhYmxpc2hlZCB3aGVuIHRoZSBwcmVkaWNhdGUgcmV0dXJucyB0cnVlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByZWRpY2F0ZTxULCBVIGV4dGVuZHMgVCA9IFQ+IHtcbiAgKHZhbHVlOiBUKTogdmFsdWUgaXMgVTtcblxuICAvKipcbiAgICogUmV0dXJucyBhIHByZWRpY2F0ZSByZXF1aXJpbmcgdGhpcyBwcmVkaWNhdGUgYW5kIGV2ZXJ5IHN1cHBsaWVkIHByZWRpY2F0ZVxuICAgKiB0byBtYXRjaC5cbiAgICpcbiAgICogVHlwZSBndWFyZHMgYXJlIGludGVyc2VjdGVkLiBBZGRpdGlvbmFsIHByZWRpY2F0ZXMgYXJlIGNoZWNrZWQgYWdhaW5zdCB0aGVcbiAgICogdHlwZSBhbHJlYWR5IGVzdGFibGlzaGVkIGJ5IHRoaXMgcHJlZGljYXRlLlxuICAgKi9cbiAgYW5kPGNvbnN0IFAgZXh0ZW5kcyByZWFkb25seSBQcmVkaWNhdGVJbnB1dDxVPltdPihcbiAgICAuLi5wcmVkaWNhdGVzOiBQXG4gICk6IFByZWRpY2F0ZTxULCBFeHRyYWN0PFUgJiBBbmROYXJyb3dlZDxVLCBQPiwgVD4+O1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgcHJlZGljYXRlIHJlcXVpcmluZyB0aGlzIHByZWRpY2F0ZSBvciBhbnkgc3VwcGxpZWQgcHJlZGljYXRlXG4gICAqIHRvIG1hdGNoLlxuICAgKlxuICAgKiBUeXBlIGd1YXJkcyBhcmUgdW5pb25lZC4gQmVjYXVzZSBhbiBvcmRpbmFyeSBib29sZWFuIHByZWRpY2F0ZSBjb3VsZFxuICAgKiBhY2NlcHQgYW55IHZhbHVlIG9mIGBVYCwgaW5jbHVkaW5nIG9uZSBjYXVzZXMgdGhlIHJlc3VsdGluZyBwcmVkaWNhdGUgdG9cbiAgICogbmFycm93IG9ubHkgdG8gYFVgLlxuICAgKi9cbiAgb3I8Y29uc3QgUCBleHRlbmRzIHJlYWRvbmx5IFByZWRpY2F0ZUlucHV0PFU+W10+KFxuICAgIC4uLnByZWRpY2F0ZXM6IFBcbiAgKTogUHJlZGljYXRlPFQsIEV4dHJhY3Q8VSB8IE9yTmFycm93ZWQ8VSwgUD4sIFQ+PjtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbG9naWNhbCBpbnZlcnNlIG9mIHRoaXMgcHJlZGljYXRlLlxuICAgKlxuICAgKiBGb3IgYSB0eXBlIHByZWRpY2F0ZSBuYXJyb3dpbmcgVCB0byBVLCB0aGUgcmVzdWx0IG5hcnJvd3MgdG9cbiAgICogRXhjbHVkZTxULCBVPi5cbiAgICovXG4gIG5lZ2F0ZSgpOiBQcmVkaWNhdGU8VCwgRXhjbHVkZTxULCBVPj47XG59XG5cbi8qKiBDb2VyY2UgYSBwcmVkaWNhdGUgcmVzdWx0IHRvIGJvb2xlYW4gdGhlIHdheSBgaWYgKC4uLilgIGRvZXMuICovXG5mdW5jdGlvbiBpc1RydXRoeTxUPih0ZXN0OiAodmFsdWU6IFQpID0+IHVua25vd24pOiBQcmVkaWNhdGVGdW5jdGlvbjxUPiB7XG4gIHJldHVybiAodmFsdWUpID0+IEJvb2xlYW4odGVzdCh2YWx1ZSkpO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIGNhbGxhYmxlIHByZWRpY2F0ZSBvYmplY3QuXG4gKlxuICogVGhlIHB1YmxpYyBnZW5lcmljIGJlaGF2aW9yIGlzIHByb3ZpZGVkIGJ5IFByZWRpY2F0ZTxULCBVPi4gUnVudGltZVxuICogY29tcG9zaXRpb24gY29lcmNlcyBwcmVkaWNhdGUgcmVzdWx0cyB0byBib29sZWFuOyB0eXBlIHByZWRpY2F0ZXMgYXJlXG4gKiBvcmRpbmFyeSBib29sZWFuIGZ1bmN0aW9ucyBhdCBydW50aW1lLlxuICovXG5mdW5jdGlvbiBidWlsZFByZWRpY2F0ZTxULCBVIGV4dGVuZHMgVD4odGVzdDogKHZhbHVlOiBUKSA9PiB1bmtub3duKTogUHJlZGljYXRlPFQsIFU+IHtcbiAgY29uc3QgY2hlY2sgPSBpc1RydXRoeSh0ZXN0KTtcbiAgY29uc3QgY2FsbGFibGUgPSAoKHZhbHVlOiBUKTogdmFsdWUgaXMgVSA9PiBjaGVjayh2YWx1ZSkpIGFzICh2YWx1ZTogVCkgPT4gdmFsdWUgaXMgVTtcblxuICByZXR1cm4gT2JqZWN0LmFzc2lnbihjYWxsYWJsZSwge1xuICAgIGFuZDxjb25zdCBQIGV4dGVuZHMgcmVhZG9ubHkgUHJlZGljYXRlSW5wdXQ8VT5bXT4oXG4gICAgICAuLi5wcmVkaWNhdGVzOiBQXG4gICAgKTogUHJlZGljYXRlPFQsIEV4dHJhY3Q8VSAmIEFuZE5hcnJvd2VkPFUsIFA+LCBUPj4ge1xuICAgICAgdHlwZSBSZXN1bHQgPSBFeHRyYWN0PFUgJiBBbmROYXJyb3dlZDxVLCBQPiwgVD47XG4gICAgICByZXR1cm4gYnVpbGRQcmVkaWNhdGU8VCwgUmVzdWx0PihcbiAgICAgICAgKHZhbHVlKSA9PiBjaGVjayh2YWx1ZSkgJiYgcHJlZGljYXRlcy5ldmVyeSgocHJlZGljYXRlKSA9PiBpc1RydXRoeShwcmVkaWNhdGUpKHZhbHVlIGFzIFUpKSxcbiAgICAgICk7XG4gICAgfSxcblxuICAgIG9yPGNvbnN0IFAgZXh0ZW5kcyByZWFkb25seSBQcmVkaWNhdGVJbnB1dDxVPltdPihcbiAgICAgIC4uLnByZWRpY2F0ZXM6IFBcbiAgICApOiBQcmVkaWNhdGU8VCwgRXh0cmFjdDxVIHwgT3JOYXJyb3dlZDxVLCBQPiwgVD4+IHtcbiAgICAgIHR5cGUgUmVzdWx0ID0gRXh0cmFjdDxVIHwgT3JOYXJyb3dlZDxVLCBQPiwgVD47XG4gICAgICByZXR1cm4gYnVpbGRQcmVkaWNhdGU8VCwgUmVzdWx0PihcbiAgICAgICAgKHZhbHVlKSA9PiBjaGVjayh2YWx1ZSkgfHwgcHJlZGljYXRlcy5zb21lKChwcmVkaWNhdGUpID0+IGlzVHJ1dGh5KHByZWRpY2F0ZSkodmFsdWUgYXMgVSkpLFxuICAgICAgKTtcbiAgICB9LFxuXG4gICAgbmVnYXRlKCk6IFByZWRpY2F0ZTxULCBFeGNsdWRlPFQsIFU+PiB7XG4gICAgICByZXR1cm4gYnVpbGRQcmVkaWNhdGU8VCwgRXhjbHVkZTxULCBVPj4oKHZhbHVlKSA9PiAhY2hlY2sodmFsdWUpKTtcbiAgICB9LFxuICB9KSBhcyBQcmVkaWNhdGU8VCwgVT47XG59XG5cbi8qKlxuICogV3JhcHMgYSB0eXBlIHByZWRpY2F0ZSB3aGlsZSBwcmVzZXJ2aW5nIGl0cyBuYXJyb3dlZCB0eXBlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlPFQsIFUgZXh0ZW5kcyBUPihwcmVkaWNhdGU6IFR5cGVQcmVkaWNhdGVGdW5jdGlvbjxULCBVPik6IFByZWRpY2F0ZTxULCBVPjtcblxuLyoqXG4gKiBXcmFwcyBhbiBvcmRpbmFyeSBib29sZWFuIG9yIHRydXRoeSBwcmVkaWNhdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGU8VD4ocHJlZGljYXRlOiBQcmVkaWNhdGVJbnB1dDxUPik6IFByZWRpY2F0ZTxULCBUPjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZTxULCBVIGV4dGVuZHMgVCA9IFQ+KFxuICBwcmVkaWNhdGU6IFR5cGVQcmVkaWNhdGVGdW5jdGlvbjxULCBVPiB8IFByZWRpY2F0ZUlucHV0PFQ+LFxuKTogUHJlZGljYXRlPFQsIFU+IHtcbiAgcmV0dXJuIGJ1aWxkUHJlZGljYXRlPFQsIFU+KHByZWRpY2F0ZSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options controlling {@link tokenizeWithOptions}. All default off except
|
|
3
|
+
* `camelCase`.
|
|
4
|
+
*
|
|
5
|
+
* - `distinct` - drop duplicate tokens (first occurrence wins).
|
|
6
|
+
* - `lowerCase` - lowercase every token.
|
|
7
|
+
* - `capitalize` - upper-case each token's first letter (then
|
|
8
|
+
* {@link TOKENIZE_OVERRIDES} fix up `ai` -> `AI` and `v2` -> `V2`).
|
|
9
|
+
* - `omitUriScheme` - strip a leading `scheme://` before tokenizing.
|
|
10
|
+
* - `omitEmailDomain` - keep only the local part of an email.
|
|
11
|
+
* - `camelCase` - split on camelCase boundaries / digit runs / acronyms
|
|
12
|
+
* (default `true`); when `false`, split only on non-alphanumerics.
|
|
13
|
+
*/
|
|
14
|
+
export type TokenizeOptions = {
|
|
15
|
+
distinct?: boolean;
|
|
16
|
+
lowerCase?: boolean;
|
|
17
|
+
capitalize?: boolean;
|
|
18
|
+
omitUriScheme?: boolean;
|
|
19
|
+
omitEmailDomain?: boolean;
|
|
20
|
+
camelCase?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type KeyOptions = Omit<TokenizeOptions, "lowerCase" | "capitalize"> & {
|
|
23
|
+
maxLength?: number;
|
|
24
|
+
truncateStrategy?: "hash" | "trim" | "empty";
|
|
25
|
+
truncateHashLength?: number;
|
|
26
|
+
};
|
|
27
|
+
export type IdentifierOptions = KeyOptions & {
|
|
28
|
+
delimiter?: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function tokenizeWithOptions(options: TokenizeOptions, ...values: unknown[]): Generator<string>;
|
|
31
|
+
export declare function tokenize(...values: unknown[]): Generator<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Join tokenized values with `delimiter`. When the next token would push the
|
|
34
|
+
* result over `maxLength`: `trim` stops adding; `empty` returns `""`; `hash`
|
|
35
|
+
* appends a digest of accepted tokens plus the overflow token if the result
|
|
36
|
+
* still fits, otherwise `""`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function toIdentifierWithOptions(options: IdentifierOptions, ...values: unknown[]): string;
|
|
39
|
+
export declare function toIdentifier(...values: unknown[]): string;
|
|
40
|
+
/**
|
|
41
|
+
* Slugified identifier: same rules as {@link toIdentifierWithOptions} with the
|
|
42
|
+
* delimiter forced to `-`. Accepts {@link KeyOptions} so callers cannot
|
|
43
|
+
* override the delimiter.
|
|
44
|
+
*/
|
|
45
|
+
export declare function toSlugWithOptions(options: KeyOptions, ...values: unknown[]): string;
|
|
46
|
+
export declare function toSlug(...values: unknown[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* Trim `value` and return `null` for non-strings, `undefined`, or
|
|
49
|
+
* strings that are empty after trimming. Lets call sites collapse the
|
|
50
|
+
* common
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* typeof v === "string" && v.trim() ? v.trim() : null
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* dance into a single helper. Useful for HTTP header / query / form
|
|
57
|
+
* extractors where downstream code wants `string | null` to drive a
|
|
58
|
+
* cheap `??` / `if (x)` cascade.
|
|
59
|
+
*/
|
|
60
|
+
export declare function trimToNull(value: unknown): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Normalize a config list that may arrive as an array or as a single
|
|
63
|
+
* comma/whitespace-separated string: split, apply `transform`, drop empties,
|
|
64
|
+
* and de-duplicate (first occurrence wins).
|
|
65
|
+
*
|
|
66
|
+
* This is the shape every allow-list / fallback-order setting in this repo
|
|
67
|
+
* takes, because the same value can come from typed config (`string[]`) or from
|
|
68
|
+
* an environment variable (`"a, b c"`). Pass `transform` to normalize entries
|
|
69
|
+
* as they are read; it defaults to trimming.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* parseList("docs.example.com, *.databricks.com");
|
|
73
|
+
* parseList(process.env.MODEL_FALLBACKS);
|
|
74
|
+
* parseList(raw, normalizeUrlPattern);
|
|
75
|
+
*/
|
|
76
|
+
export declare function parseList(raw: string | readonly string[] | undefined | null, transform?: (entry: string) => string): string[];
|
|
77
|
+
/**
|
|
78
|
+
* {@link trimToNull} with an empty-string miss instead of `null`, for callers
|
|
79
|
+
* that build a string unconditionally and treat "absent" as "".
|
|
80
|
+
*
|
|
81
|
+
* Reading loosely-typed JSON is the motivating case: a field that should be a
|
|
82
|
+
* string may be missing or the wrong type, and the caller wants `""` rather
|
|
83
|
+
* than a null check at every access.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* const title = trimToEmpty(record.title); // always a string
|
|
87
|
+
*/
|
|
88
|
+
export declare function trimToEmpty(value: unknown): string;
|
|
89
|
+
/**
|
|
90
|
+
* Trim the first usable string out of `value`. Returns `null` when
|
|
91
|
+
* `value` is `undefined`, `null`, an empty string, or an array whose
|
|
92
|
+
* first string member is empty. Mirrors how Express / Node header
|
|
93
|
+
* accessors expose single vs. repeated headers - the first
|
|
94
|
+
* non-empty entry wins, everything else is ignored.
|
|
95
|
+
*/
|
|
96
|
+
export declare function firstNonEmpty(value: unknown): string | null;
|
|
97
|
+
/**
|
|
98
|
+
* Escape the five characters significant in HTML text and
|
|
99
|
+
* double-quoted attribute values (`&`, `<`, `>`, `"`, `'`) so an
|
|
100
|
+
* untrusted string can be interpolated into markup without breaking
|
|
101
|
+
* out of its context. `&` is replaced first so ampersands introduced
|
|
102
|
+
* by the later replacements aren't double-escaped.
|
|
103
|
+
*/
|
|
104
|
+
export declare function escapeHtml(value: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* Slugify `value` (using the standard {@link toIdentifierWithOptions}
|
|
107
|
+
* tokenizer + delimiter rules) and **always** suffix a short
|
|
108
|
+
* deterministic hash. Use when you need a stable, slugified id that
|
|
109
|
+
* is guaranteed to be unique across descriptions sharing the same
|
|
110
|
+
* leading tokens (tool ids, cache keys, etc.).
|
|
111
|
+
*
|
|
112
|
+
* Behaviour differs from `toIdentifierWithOptions({ maxLength,
|
|
113
|
+
* truncateStrategy: "hash" })`: that helper only appends a hash when
|
|
114
|
+
* the slug *overflows* `maxLength`. This helper appends a hash
|
|
115
|
+
* unconditionally so the result is collision-resistant even for
|
|
116
|
+
* short inputs. The hash is computed over the raw `value` so two
|
|
117
|
+
* descriptions producing the same slug still get different ids.
|
|
118
|
+
*
|
|
119
|
+
* @param value - Source string (typically a tool/agent description).
|
|
120
|
+
* @param options.delimiter - Token separator (default `"_"`).
|
|
121
|
+
* @param options.slugMaxLength - Cap on the slug portion (the part
|
|
122
|
+
* before the hash). Default 32.
|
|
123
|
+
* @param options.hashLength - Length of the suffix produced by
|
|
124
|
+
* {@link fnvHashWithOptions} (Crockford-style base-32 alphabet, max 7
|
|
125
|
+
* chars). Default 6.
|
|
126
|
+
* @param options.fallbackPrefix - Prefix used when the slug is empty
|
|
127
|
+
* (e.g. punctuation-only input). Default `"id"`.
|
|
128
|
+
*/
|
|
129
|
+
export declare function toUniqueSlug(value: string, options?: {
|
|
130
|
+
delimiter?: string;
|
|
131
|
+
slugMaxLength?: number;
|
|
132
|
+
hashLength?: number;
|
|
133
|
+
fallbackPrefix?: string;
|
|
134
|
+
}): string;
|
|
135
|
+
/**
|
|
136
|
+
* A node in the description tree consumed by {@link toDescription}.
|
|
137
|
+
*
|
|
138
|
+
* - `string` - a text paragraph.
|
|
139
|
+
* - `Description[]` - a sequence of stacked blocks at the same level
|
|
140
|
+
* (no list markers). Plain text adjacent to a list (either direction)
|
|
141
|
+
* flushes together so the prose reads as a lead-in or trailing
|
|
142
|
+
* summary. Two text paragraphs, two adjacent lists, and anything
|
|
143
|
+
* touching a map get a blank-line break.
|
|
144
|
+
* - `{ bullets: [...] }` / `{ numbered: [...] }` - explicit list. A
|
|
145
|
+
* list of one bare string drops its marker (`-` / `1.`); a list of
|
|
146
|
+
* one item with nested children keeps its marker as the visual anchor
|
|
147
|
+
* for the indented children.
|
|
148
|
+
* - any other object - headers map: each key becomes a `Header:` line
|
|
149
|
+
* followed by a blank line and the rendered value.
|
|
150
|
+
*/
|
|
151
|
+
export type Description = string | readonly Description[] | {
|
|
152
|
+
readonly [key: string]: Description;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Format a nested description tree as a Markdown-ish string suitable
|
|
156
|
+
* for an LLM system prompt, Zod `.describe()` block, Mastra tool
|
|
157
|
+
* description, or any other long-form text destination.
|
|
158
|
+
*
|
|
159
|
+
* Every string section is dedented (common leading whitespace stripped),
|
|
160
|
+
* right-trimmed line by line, and freed of leading / trailing blank
|
|
161
|
+
* lines, so callers can write multi-line template literals indented
|
|
162
|
+
* naturally in source without leaking that indentation into the
|
|
163
|
+
* consumer-facing output. Plain-string inputs flow through unchanged
|
|
164
|
+
* apart from the same normalization pass, so a single multi-line
|
|
165
|
+
* template literal works directly:
|
|
166
|
+
*
|
|
167
|
+
* ```ts
|
|
168
|
+
* toDescription(`
|
|
169
|
+
* Ask the Genie space "${alias}" a question.
|
|
170
|
+
* Pass the answer through as-is.
|
|
171
|
+
* `);
|
|
172
|
+
* // Ask the Genie space "default" a question.
|
|
173
|
+
* // Pass the answer through as-is.
|
|
174
|
+
*
|
|
175
|
+
* toDescription([
|
|
176
|
+
* `
|
|
177
|
+
* Ask the Genie space a question.
|
|
178
|
+
* Phrase it from the user's perspective.
|
|
179
|
+
* `,
|
|
180
|
+
* { bullets: [
|
|
181
|
+
* ["Pass the answer through as-is", { numbered: ["item", "item"] }],
|
|
182
|
+
* ]},
|
|
183
|
+
* { Instructions: "Reply with the SQL only." },
|
|
184
|
+
* ]);
|
|
185
|
+
* // Ask the Genie space a question.
|
|
186
|
+
* // Phrase it from the user's perspective.
|
|
187
|
+
* // - Pass the answer through as-is
|
|
188
|
+
* // 1. item
|
|
189
|
+
* // 2. item
|
|
190
|
+
* //
|
|
191
|
+
* // Instructions:
|
|
192
|
+
* //
|
|
193
|
+
* // Reply with the SQL only.
|
|
194
|
+
* ```
|
|
195
|
+
*
|
|
196
|
+
* See {@link Description} for the node grammar.
|
|
197
|
+
*/
|
|
198
|
+
export declare function toDescription(node: Description): string;
|
|
199
|
+
/**
|
|
200
|
+
* Format a count with its noun, pluralizing (naive `+s`) unless the count is 1:
|
|
201
|
+
* `pluralize(1, "barrel")` -> `"1 barrel"`, `pluralize(3, "barrel")` ->
|
|
202
|
+
* `"3 barrels"`. Collapses the `${n} noun${n === 1 ? "" : "s"}` idiom.
|
|
203
|
+
*/
|
|
204
|
+
export declare function pluralize(count: number, noun: string): string;
|
|
205
|
+
/**
|
|
206
|
+
* Title-case a snake / kebab / camel identifier into a human-readable label:
|
|
207
|
+
* tokenize (lowercased, capitalized), then join with spaces. Falls back to
|
|
208
|
+
* the raw `value` when it yields no tokens (e.g. punctuation-only input).
|
|
209
|
+
* `bge_large_en` -> `"Bge Large En"`, `promptId` -> `"Prompt Id"`.
|
|
210
|
+
*
|
|
211
|
+
* The single source of truth for the "humanize a column / field name" idiom -
|
|
212
|
+
* reused by the chat data-grid headers and the export renderer. Extra
|
|
213
|
+
* {@link TokenizeOptions} (e.g. `camelCase: false`) merge over the defaults.
|
|
214
|
+
*/
|
|
215
|
+
export declare function toLabel(value: string, options?: TokenizeOptions): string;
|
|
216
|
+
/**
|
|
217
|
+
* Upper-case the first character of `value`, leaving the rest untouched.
|
|
218
|
+
* `"working"` -> `"Working"`. Collapses the
|
|
219
|
+
* `s.charAt(0).toUpperCase() + s.slice(1)` idiom.
|
|
220
|
+
*/
|
|
221
|
+
export declare function capitalize(value: string): string;
|