@spudlabs/guardis 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/README.md +901 -0
- package/esm/mod.d.ts +55 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +43 -0
- package/esm/package.json +3 -0
- package/esm/specs/standard-schema-spec.v1.d.ts +56 -0
- package/esm/specs/standard-schema-spec.v1.d.ts.map +1 -0
- package/esm/specs/standard-schema-spec.v1.js +1 -0
- package/esm/src/batch.d.ts +23 -0
- package/esm/src/batch.d.ts.map +1 -0
- package/esm/src/batch.js +23 -0
- package/esm/src/brand.d.ts +62 -0
- package/esm/src/brand.d.ts.map +1 -0
- package/esm/src/brand.js +9 -0
- package/esm/src/context.d.ts +19 -0
- package/esm/src/context.d.ts.map +1 -0
- package/esm/src/context.js +41 -0
- package/esm/src/extend.d.ts +23 -0
- package/esm/src/extend.d.ts.map +1 -0
- package/esm/src/extend.js +9 -0
- package/esm/src/guard.d.ts +288 -0
- package/esm/src/guard.d.ts.map +1 -0
- package/esm/src/guard.js +631 -0
- package/esm/src/helpers/http.helpers.d.ts +3 -0
- package/esm/src/helpers/http.helpers.d.ts.map +1 -0
- package/esm/src/helpers/http.helpers.js +2 -0
- package/esm/src/helpers/strings.helpers.d.ts +18 -0
- package/esm/src/helpers/strings.helpers.d.ts.map +1 -0
- package/esm/src/helpers/strings.helpers.js +47 -0
- package/esm/src/introspect.d.ts +36 -0
- package/esm/src/introspect.d.ts.map +1 -0
- package/esm/src/introspect.js +25 -0
- package/esm/src/modules/async.d.ts +27 -0
- package/esm/src/modules/async.d.ts.map +1 -0
- package/esm/src/modules/async.js +38 -0
- package/esm/src/modules/http.branded.d.ts +42 -0
- package/esm/src/modules/http.branded.d.ts.map +1 -0
- package/esm/src/modules/http.branded.js +24 -0
- package/esm/src/modules/http.d.ts +46 -0
- package/esm/src/modules/http.d.ts.map +1 -0
- package/esm/src/modules/http.js +59 -0
- package/esm/src/modules/strings.branded.d.ts +185 -0
- package/esm/src/modules/strings.branded.d.ts.map +1 -0
- package/esm/src/modules/strings.branded.js +123 -0
- package/esm/src/modules/strings.d.ts +109 -0
- package/esm/src/modules/strings.d.ts.map +1 -0
- package/esm/src/modules/strings.js +147 -0
- package/esm/src/types.d.ts +318 -0
- package/esm/src/types.d.ts.map +1 -0
- package/esm/src/types.js +1 -0
- package/esm/src/utilities.d.ts +95 -0
- package/esm/src/utilities.d.ts.map +1 -0
- package/esm/src/utilities.js +196 -0
- package/package.json +40 -0
- package/script/mod.d.ts +55 -0
- package/script/mod.d.ts.map +1 -0
- package/script/mod.js +83 -0
- package/script/package.json +3 -0
- package/script/specs/standard-schema-spec.v1.d.ts +56 -0
- package/script/specs/standard-schema-spec.v1.d.ts.map +1 -0
- package/script/specs/standard-schema-spec.v1.js +2 -0
- package/script/src/batch.d.ts +23 -0
- package/script/src/batch.d.ts.map +1 -0
- package/script/src/batch.js +26 -0
- package/script/src/brand.d.ts +62 -0
- package/script/src/brand.d.ts.map +1 -0
- package/script/src/brand.js +12 -0
- package/script/src/context.d.ts +19 -0
- package/script/src/context.d.ts.map +1 -0
- package/script/src/context.js +45 -0
- package/script/src/extend.d.ts +23 -0
- package/script/src/extend.d.ts.map +1 -0
- package/script/src/extend.js +12 -0
- package/script/src/guard.d.ts +288 -0
- package/script/src/guard.d.ts.map +1 -0
- package/script/src/guard.js +640 -0
- package/script/src/helpers/http.helpers.d.ts +3 -0
- package/script/src/helpers/http.helpers.d.ts.map +1 -0
- package/script/src/helpers/http.helpers.js +5 -0
- package/script/src/helpers/strings.helpers.d.ts +18 -0
- package/script/src/helpers/strings.helpers.d.ts.map +1 -0
- package/script/src/helpers/strings.helpers.js +52 -0
- package/script/src/introspect.d.ts +36 -0
- package/script/src/introspect.d.ts.map +1 -0
- package/script/src/introspect.js +31 -0
- package/script/src/modules/async.d.ts +27 -0
- package/script/src/modules/async.d.ts.map +1 -0
- package/script/src/modules/async.js +41 -0
- package/script/src/modules/http.branded.d.ts +42 -0
- package/script/src/modules/http.branded.d.ts.map +1 -0
- package/script/src/modules/http.branded.js +30 -0
- package/script/src/modules/http.d.ts +46 -0
- package/script/src/modules/http.d.ts.map +1 -0
- package/script/src/modules/http.js +62 -0
- package/script/src/modules/strings.branded.d.ts +185 -0
- package/script/src/modules/strings.branded.d.ts.map +1 -0
- package/script/src/modules/strings.branded.js +126 -0
- package/script/src/modules/strings.d.ts +109 -0
- package/script/src/modules/strings.d.ts.map +1 -0
- package/script/src/modules/strings.js +150 -0
- package/script/src/types.d.ts +318 -0
- package/script/src/types.d.ts.map +1 -0
- package/script/src/types.js +2 -0
- package/script/src/utilities.d.ts +95 -0
- package/script/src/utilities.d.ts.map +1 -0
- package/script/src/utilities.js +207 -0
package/esm/mod.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardis is a utility to help build type guard libraries while
|
|
3
|
+
* addressing one of the main potential sources of error in TypeScript's
|
|
4
|
+
* "type guard" behavior.
|
|
5
|
+
*
|
|
6
|
+
* @module Guardis
|
|
7
|
+
*/
|
|
8
|
+
export * from "./src/guard.js";
|
|
9
|
+
export * from "./src/extend.js";
|
|
10
|
+
export * from "./src/batch.js";
|
|
11
|
+
export * from "./src/brand.js";
|
|
12
|
+
export * from "./src/types.js";
|
|
13
|
+
export { unionOf } from "./src/utilities.js";
|
|
14
|
+
/**
|
|
15
|
+
* "Is" serves as the main libray object and contains
|
|
16
|
+
* keys corresponding to most of JavaScript's basic
|
|
17
|
+
* data types. The key values are callbacks that function as
|
|
18
|
+
* type guards for their respective types.
|
|
19
|
+
*/
|
|
20
|
+
export declare const Is: {
|
|
21
|
+
readonly Boolean: import("./mod.js").TypeGuard<boolean>;
|
|
22
|
+
readonly String: import("./mod.js").TypeGuard<string>;
|
|
23
|
+
readonly Number: import("./mod.js").TypeGuard<number>;
|
|
24
|
+
readonly Binary: import("./mod.js").TypeGuard<0 | 1>;
|
|
25
|
+
readonly Numeric: import("./mod.js").TypeGuard<number>;
|
|
26
|
+
readonly Symbol: import("./mod.js").TypeGuard<symbol>;
|
|
27
|
+
readonly Function: import("./mod.js").TypeGuard<(...args: unknown[]) => unknown>;
|
|
28
|
+
readonly Object: import("./mod.js").TypeGuard<object>;
|
|
29
|
+
readonly PropertyKey: import("./mod.js").TypeGuard<PropertyKey>;
|
|
30
|
+
readonly Undefined: import("./mod.js").TypeGuard<undefined>;
|
|
31
|
+
readonly Array: import("./mod.js").TypeGuard<unknown[]> & {
|
|
32
|
+
of: <T>(guard: import("./mod.js").TypeGuard<T>) => import("./mod.js").TypeGuard<T[]>;
|
|
33
|
+
};
|
|
34
|
+
readonly JsonPrimitive: import("./mod.js").TypeGuard<import("./mod.js").JsonPrimitive>;
|
|
35
|
+
readonly JsonArray: import("./mod.js").TypeGuard<import("./mod.js").JsonValue[] | readonly import("./mod.js").JsonValue[]>;
|
|
36
|
+
readonly JsonObject: import("./mod.js").TypeGuard<import("./mod.js").JsonObject>;
|
|
37
|
+
readonly JsonValue: import("./mod.js").TypeGuard<import("./mod.js").JsonValue>;
|
|
38
|
+
readonly Null: import("./mod.js").TypeGuard<null>;
|
|
39
|
+
readonly Nil: import("./mod.js").TypeGuard<null | undefined>;
|
|
40
|
+
readonly Empty: import("./mod.js").TypeGuard<"" | [] | Record<string, never> | null | undefined>;
|
|
41
|
+
readonly Iterable: import("./mod.js").TypeGuard<Iterable<unknown>>;
|
|
42
|
+
readonly Tuple: {
|
|
43
|
+
<N extends number>(t: unknown, length: N): t is import("./mod.js").TupleOfLength<N>;
|
|
44
|
+
strict<N extends number>(t: unknown, length: N, errorMsg?: string): t is import("./mod.js").TupleOfLength<N>;
|
|
45
|
+
assert: <N extends number>(t: unknown, length: N, errorMsg?: string) => asserts t is import("./mod.js").TupleOfLength<N>;
|
|
46
|
+
or<N extends number, T2>(length: N, guard: import("./mod.js").TypeGuard<T2>): import("./mod.js").TypeGuard<import("./mod.js").TupleOfLength<N> | T2>;
|
|
47
|
+
optional: {
|
|
48
|
+
<N extends number>(t: unknown, length: N): t is import("./mod.js").TupleOfLength<N> | undefined;
|
|
49
|
+
strict<N extends number>(t: unknown, length: N, errorMsg?: string): t is import("./mod.js").TupleOfLength<N> | undefined;
|
|
50
|
+
assert: <N extends number>(t: unknown, length: N, errorMsg?: string) => t is import("./mod.js").TupleOfLength<N> | undefined;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
readonly Date: import("./mod.js").TypeGuard<Date>;
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=mod.d.ts.map
|
package/esm/mod.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAI7C;;;;;GAKG;AACH,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsBL,CAAC"}
|
package/esm/mod.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardis is a utility to help build type guard libraries while
|
|
3
|
+
* addressing one of the main potential sources of error in TypeScript's
|
|
4
|
+
* "type guard" behavior.
|
|
5
|
+
*
|
|
6
|
+
* @module Guardis
|
|
7
|
+
*/
|
|
8
|
+
export * from "./src/guard.js";
|
|
9
|
+
export * from "./src/extend.js";
|
|
10
|
+
export * from "./src/batch.js";
|
|
11
|
+
export * from "./src/brand.js";
|
|
12
|
+
export * from "./src/types.js";
|
|
13
|
+
export { unionOf } from "./src/utilities.js";
|
|
14
|
+
import * as g from "./src/guard.js";
|
|
15
|
+
/**
|
|
16
|
+
* "Is" serves as the main libray object and contains
|
|
17
|
+
* keys corresponding to most of JavaScript's basic
|
|
18
|
+
* data types. The key values are callbacks that function as
|
|
19
|
+
* type guards for their respective types.
|
|
20
|
+
*/
|
|
21
|
+
export const Is = {
|
|
22
|
+
Boolean: g.isBoolean,
|
|
23
|
+
String: g.isString,
|
|
24
|
+
Number: g.isNumber,
|
|
25
|
+
Binary: g.isBinary,
|
|
26
|
+
Numeric: g.isNumeric,
|
|
27
|
+
Symbol: g.isSymbol,
|
|
28
|
+
Function: g.isFunction,
|
|
29
|
+
Object: g.isObject,
|
|
30
|
+
PropertyKey: g.isPropertyKey,
|
|
31
|
+
Undefined: g.isUndefined,
|
|
32
|
+
Array: g.isArray,
|
|
33
|
+
JsonPrimitive: g.isJsonPrimitive,
|
|
34
|
+
JsonArray: g.isJsonArray,
|
|
35
|
+
JsonObject: g.isJsonObject,
|
|
36
|
+
JsonValue: g.isJsonValue,
|
|
37
|
+
Null: g.isNull,
|
|
38
|
+
Nil: g.isNil,
|
|
39
|
+
Empty: g.isEmpty,
|
|
40
|
+
Iterable: g.isIterable,
|
|
41
|
+
Tuple: g.isTuple,
|
|
42
|
+
Date: g.isDate,
|
|
43
|
+
};
|
package/esm/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** The Standard Schema interface. */
|
|
2
|
+
export interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
3
|
+
/** The Standard Schema properties. */
|
|
4
|
+
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
|
5
|
+
}
|
|
6
|
+
export declare namespace StandardSchemaV1 {
|
|
7
|
+
/** The Standard Schema properties interface. */
|
|
8
|
+
interface Props<Input = unknown, Output = Input> {
|
|
9
|
+
/** The version number of the standard. */
|
|
10
|
+
readonly version: 1;
|
|
11
|
+
/** The vendor name of the schema library. */
|
|
12
|
+
readonly vendor: string;
|
|
13
|
+
/** Validates unknown input values. */
|
|
14
|
+
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
|
|
15
|
+
/** Inferred types associated with the schema. */
|
|
16
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** The result interface of the validate function. */
|
|
19
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
20
|
+
/** The result interface if validation succeeds. */
|
|
21
|
+
interface SuccessResult<Output> {
|
|
22
|
+
/** The typed output value. */
|
|
23
|
+
readonly value: Output;
|
|
24
|
+
/** The non-existent issues. */
|
|
25
|
+
readonly issues?: undefined;
|
|
26
|
+
}
|
|
27
|
+
/** The result interface if validation fails. */
|
|
28
|
+
interface FailureResult {
|
|
29
|
+
/** The issues of failed validation. */
|
|
30
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
31
|
+
}
|
|
32
|
+
/** The issue interface of the failure output. */
|
|
33
|
+
interface Issue {
|
|
34
|
+
/** The error message of the issue. */
|
|
35
|
+
readonly message: string;
|
|
36
|
+
/** The path of the issue, if any. */
|
|
37
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
38
|
+
}
|
|
39
|
+
/** The path segment interface of the issue. */
|
|
40
|
+
interface PathSegment {
|
|
41
|
+
/** The key representing a path segment. */
|
|
42
|
+
readonly key: PropertyKey;
|
|
43
|
+
}
|
|
44
|
+
/** The Standard Schema types interface. */
|
|
45
|
+
interface Types<Input = unknown, Output = Input> {
|
|
46
|
+
/** The input type of the schema. */
|
|
47
|
+
readonly input: Input;
|
|
48
|
+
/** The output type of the schema. */
|
|
49
|
+
readonly output: Output;
|
|
50
|
+
}
|
|
51
|
+
/** Infers the input type of a Standard Schema. */
|
|
52
|
+
type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
|
53
|
+
/** Infers the output type of a Standard Schema. */
|
|
54
|
+
type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=standard-schema-spec.v1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standard-schema-spec.v1.d.ts","sourceRoot":"","sources":["../../src/specs/standard-schema-spec.v1.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,WAAW,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;IAC/D,sCAAsC;IACtC,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CAC7D;AAED,MAAM,CAAC,OAAO,WAAW,gBAAgB,CAAC;IACxC,gDAAgD;IAChD,UAAiB,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;QACpD,0CAA0C;QAC1C,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACpB,6CAA6C;QAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,sCAAsC;QACtC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAChF,iDAAiD;QACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;KACnD;IAED,qDAAqD;IACrD,KAAY,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC;IAEnE,mDAAmD;IACnD,UAAiB,aAAa,CAAC,MAAM;QACnC,8BAA8B;QAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,+BAA+B;QAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;KAC7B;IAED,gDAAgD;IAChD,UAAiB,aAAa;QAC5B,uCAAuC;QACvC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;KACvC;IAED,iDAAiD;IACjD,UAAiB,KAAK;QACpB,sCAAsC;QACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,qCAAqC;QACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,SAAS,CAAC;KACtE;IAED,+CAA+C;IAC/C,UAAiB,WAAW;QAC1B,2CAA2C;QAC3C,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;KAC3B;IAED,2CAA2C;IAC3C,UAAiB,KAAK,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;QACpD,oCAAoC;QACpC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QACtB,qCAAqC;QACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB;IAED,kDAAkD;IAClD,KAAY,UAAU,CAAC,MAAM,SAAS,gBAAgB,IAAI,WAAW,CACnE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAC7B,CAAC,OAAO,CAAC,CAAC;IAEX,mDAAmD;IACnD,KAAY,WAAW,CAAC,MAAM,SAAS,gBAAgB,IAAI,WAAW,CACpE,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAC7B,CAAC,QAAQ,CAAC,CAAC;CACb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { InferEntry, ParserRecords, TypeGuard } from "./types.js";
|
|
2
|
+
type GuardRecords<E extends ParserRecords, K extends keyof E = keyof E> = {
|
|
3
|
+
[key in K as `is${Capitalize<key & string>}`]: TypeGuard<InferEntry<E[key]>>;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Batch generate a set of type guard functions. The returned record
|
|
7
|
+
* will contain keys for each type, prefixed by `is`. These can be destructured
|
|
8
|
+
* to the corresponding type guards.
|
|
9
|
+
*
|
|
10
|
+
* @param config
|
|
11
|
+
* @returns
|
|
12
|
+
*
|
|
13
|
+
* Keys will be automatically capitalized in the returned object.
|
|
14
|
+
* _e.g._
|
|
15
|
+
* * `Meatball => isMeatball`
|
|
16
|
+
* * `sausage => isSausage`
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const { isMeatball } = batch({ Meatball: (v) => v === "meatball" ? v : null });
|
|
20
|
+
*/
|
|
21
|
+
export declare function batch<B extends ParserRecords>(config: B): GuardRecords<B>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIvE,KAAK,YAAY,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI;KACvE,GAAG,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,GAAG,GAAG,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7E,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAKzE"}
|
package/esm/src/batch.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { entryToGuard } from "./guard.js";
|
|
2
|
+
import { toPascalCase } from "./helpers/strings.helpers.js";
|
|
3
|
+
/**
|
|
4
|
+
* Batch generate a set of type guard functions. The returned record
|
|
5
|
+
* will contain keys for each type, prefixed by `is`. These can be destructured
|
|
6
|
+
* to the corresponding type guards.
|
|
7
|
+
*
|
|
8
|
+
* @param config
|
|
9
|
+
* @returns
|
|
10
|
+
*
|
|
11
|
+
* Keys will be automatically capitalized in the returned object.
|
|
12
|
+
* _e.g._
|
|
13
|
+
* * `Meatball => isMeatball`
|
|
14
|
+
* * `sausage => isSausage`
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const { isMeatball } = batch({ Meatball: (v) => v === "meatball" ? v : null });
|
|
18
|
+
*/
|
|
19
|
+
export function batch(config) {
|
|
20
|
+
const entries = Object.entries(config)
|
|
21
|
+
.map(([name, entry]) => [`is${toPascalCase(name)}`, entryToGuard(entry)]);
|
|
22
|
+
return Object.fromEntries(entries);
|
|
23
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { InferShape, Parser, TypeGuard, TypeGuardShape } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a nominal type by intersecting a base type `T` with a unique brand `B`.
|
|
4
|
+
* This helps distinguish between types that are structurally identical but conceptually different.
|
|
5
|
+
*/
|
|
6
|
+
export type Brand<T, B extends string> = T & {
|
|
7
|
+
readonly __brand: B;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Removes the property with the key `brand` from the given type `T`.
|
|
11
|
+
*/
|
|
12
|
+
export type RemoveBrand<T> = T extends string ? string : T extends number ? number : T extends Record<infer K, infer V> ? Record<Exclude<K, "__brand">, V> : T extends (infer U)[] ? U[] : T extends object ? {
|
|
13
|
+
[P in Exclude<keyof T, "__brand">]: T[P];
|
|
14
|
+
} : T[Exclude<keyof T, "__brand">];
|
|
15
|
+
/**
|
|
16
|
+
* Creates a type guard for branded types, allowing runtime validation of nominal types.
|
|
17
|
+
*
|
|
18
|
+
* Branded types (also known as nominal types) are a TypeScript pattern that allows
|
|
19
|
+
* distinguishing between types that are structurally identical but conceptually different.
|
|
20
|
+
* This function creates a type guard that validates the underlying type while preserving
|
|
21
|
+
* the brand in the type system.
|
|
22
|
+
*
|
|
23
|
+
* @template T1 - The base type or a branded type
|
|
24
|
+
* @template B - The brand string (when using the first overload)
|
|
25
|
+
*
|
|
26
|
+
* @param parse - A parser function that validates the underlying type (without the brand)
|
|
27
|
+
* @returns A TypeGuard that validates the value and narrows it to the branded type
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Define branded types
|
|
32
|
+
* type UserId = Brand<string, "UserId">;
|
|
33
|
+
* type ProductId = Brand<string, "ProductId">;
|
|
34
|
+
*
|
|
35
|
+
* // Create parsers for the underlying type
|
|
36
|
+
* const parseUserId = (val: unknown): string | null =>
|
|
37
|
+
* typeof val === "string" && val.startsWith("user_") ? val : null;
|
|
38
|
+
*
|
|
39
|
+
* // Create branded type guards
|
|
40
|
+
* const isUserId = createBrandedTypeGuard<string, "UserId">(parseUserId);
|
|
41
|
+
* const isProductId = createBrandedTypeGuard<ProductId>(isString._parser);
|
|
42
|
+
*
|
|
43
|
+
* // Create a named branded type guard (name infers the brand and appears in error messages)
|
|
44
|
+
* const isNamedUserId = createBrandedTypeGuard("UserId", parseUserId);
|
|
45
|
+
*
|
|
46
|
+
* // Create a branded type guard from a shape
|
|
47
|
+
* const isBrandedUser = createBrandedTypeGuard("User", { name: isString, age: isNumber });
|
|
48
|
+
*
|
|
49
|
+
* // Use the type guards
|
|
50
|
+
* const id: unknown = "user_123";
|
|
51
|
+
* if (isUserId(id)) {
|
|
52
|
+
* // id is now typed as UserId
|
|
53
|
+
* const userId: UserId = id;
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function createBrandedTypeGuard<S extends TypeGuardShape, B extends string>(name: B, shape: S): TypeGuard<Brand<InferShape<S>, B>>;
|
|
58
|
+
export declare function createBrandedTypeGuard<S extends TypeGuardShape, B extends string>(shape: S): TypeGuard<Brand<InferShape<S>, B>>;
|
|
59
|
+
export declare function createBrandedTypeGuard<T1, B extends string>(name: B, parse: Parser<T1>): TypeGuard<Brand<T1, B>>;
|
|
60
|
+
export declare function createBrandedTypeGuard<T1, B extends string>(parse: Parser<T1>): TypeGuard<Brand<T1, B>>;
|
|
61
|
+
export declare function createBrandedTypeGuard<T1 extends Brand<unknown, string>>(parse: Parser<RemoveBrand<T1>>): TypeGuard<T1>;
|
|
62
|
+
//# sourceMappingURL=brand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../../src/src/brand.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhF;;;GAGG;AACH,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC;AAErE;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,MAAM,GAClD,CAAC,SAAS,MAAM,GAAG,MAAM,GACzB,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,GACrE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAC3B,CAAC,SAAS,MAAM,GAAG;KAAG,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,GAC/D,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,cAAc,EAAE,CAAC,SAAS,MAAM,EAC/E,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,CAAC,GACP,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtC,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,cAAc,EAAE,CAAC,SAAS,MAAM,EAC/E,KAAK,EAAE,CAAC,GACP,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtC,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,CAAC,SAAS,MAAM,EACzD,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,GAChB,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3B,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,CAAC,SAAS,MAAM,EACzD,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,GAChB,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3B,wBAAgB,sBAAsB,CAAC,EAAE,SAAS,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,EACtE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,GAC7B,SAAS,CAAC,EAAE,CAAC,CAAC"}
|
package/esm/src/brand.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createTypeGuard } from "./guard.js";
|
|
2
|
+
export function createBrandedTypeGuard(...args) {
|
|
3
|
+
const parserOrShape = args.length === 2 ? args[1] : args[0];
|
|
4
|
+
const name = args.length === 2 ? args[0] : undefined;
|
|
5
|
+
if (name !== undefined) {
|
|
6
|
+
return createTypeGuard(name, parserOrShape);
|
|
7
|
+
}
|
|
8
|
+
return createTypeGuard(parserOrShape);
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "../specs/standard-schema-spec.v1.js";
|
|
2
|
+
import type { Context } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a validation context for tracking paths and collecting issues during validation.
|
|
5
|
+
*
|
|
6
|
+
* @param path The current path segments (defaults to empty array for root)
|
|
7
|
+
* @param rootIssues Optional shared issues array (for propagating issues to parent context)
|
|
8
|
+
* @returns A new Context instance
|
|
9
|
+
*/
|
|
10
|
+
export declare function createContext(path?: PropertyKey[], rootIssues?: StandardSchemaV1.Issue[]): Context;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a strict validation context that throws TypeError immediately on first issue.
|
|
13
|
+
* Used by strict type guards to provide detailed error messages with path information.
|
|
14
|
+
*
|
|
15
|
+
* @param path The current path segments (defaults to empty array for root)
|
|
16
|
+
* @returns A Context that throws on addIssue instead of collecting issues
|
|
17
|
+
*/
|
|
18
|
+
export declare function createStrictContext(path?: PropertyKey[]): Context;
|
|
19
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,GAAE,WAAW,EAAO,EACxB,UAAU,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,GACpC,OAAO,CAcT;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,WAAW,EAAO,GAAG,OAAO,CAYrE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a validation context for tracking paths and collecting issues during validation.
|
|
3
|
+
*
|
|
4
|
+
* @param path The current path segments (defaults to empty array for root)
|
|
5
|
+
* @param rootIssues Optional shared issues array (for propagating issues to parent context)
|
|
6
|
+
* @returns A new Context instance
|
|
7
|
+
*/
|
|
8
|
+
export function createContext(path = [], rootIssues) {
|
|
9
|
+
const issues = rootIssues ?? [];
|
|
10
|
+
return {
|
|
11
|
+
path,
|
|
12
|
+
issues,
|
|
13
|
+
pushPath(segment) {
|
|
14
|
+
return createContext([...path, segment], issues);
|
|
15
|
+
},
|
|
16
|
+
addIssue(message) {
|
|
17
|
+
// Only include path if it has segments (not at root level)
|
|
18
|
+
issues.push(path.length > 0 ? { message, path: [...path] } : { message });
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a strict validation context that throws TypeError immediately on first issue.
|
|
24
|
+
* Used by strict type guards to provide detailed error messages with path information.
|
|
25
|
+
*
|
|
26
|
+
* @param path The current path segments (defaults to empty array for root)
|
|
27
|
+
* @returns A Context that throws on addIssue instead of collecting issues
|
|
28
|
+
*/
|
|
29
|
+
export function createStrictContext(path = []) {
|
|
30
|
+
return {
|
|
31
|
+
path,
|
|
32
|
+
issues: [],
|
|
33
|
+
pushPath(segment) {
|
|
34
|
+
return createStrictContext([...path, segment]);
|
|
35
|
+
},
|
|
36
|
+
addIssue(message) {
|
|
37
|
+
const pathStr = path.length > 0 ? ` at path: ${path.join(".")}` : "";
|
|
38
|
+
throw new TypeError(`${message}${pathStr}`);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { InferEntry, ParserRecords, TypeGuard } from "./types.js";
|
|
2
|
+
import { Is } from "../mod.js";
|
|
3
|
+
/** The return Is dictionary, merging both the definitions from the standard library
|
|
4
|
+
* and the custom type guards generated from the GuardExtension record. */
|
|
5
|
+
export type ExtendedIs<E extends ParserRecords, I extends typeof Is> = {
|
|
6
|
+
[K in keyof I | keyof E]: K extends keyof I ? I[K] : K extends keyof E ? TypeGuard<InferEntry<E[K]>> : never;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Generate a custom Is dictionary using an object with the names of your types
|
|
10
|
+
* and the parsers to use to create type guards.
|
|
11
|
+
* @param config
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
export declare function extend<P extends ParserRecords>(config: P): ExtendedIs<P, typeof Is>;
|
|
15
|
+
/**
|
|
16
|
+
* Clones the provided Is library and extends it by adding in your
|
|
17
|
+
* new parsers.
|
|
18
|
+
* @param Is The Is library to extend.
|
|
19
|
+
* @param config The catalog of parsers to include in your library.
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export declare function extend<P extends ParserRecords, I extends typeof Is>(is: I, config: P): ExtendedIs<P, I>;
|
|
23
|
+
//# sourceMappingURL=extend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extend.d.ts","sourceRoot":"","sources":["../../src/src/extend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvE,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAE/B;0EAC0E;AAC1E,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,SAAS,OAAO,EAAE,IAAI;KACpE,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAClG,KAAK;CACR,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,aAAa,EAC5C,MAAM,EAAE,CAAC,GACR,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5B;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,aAAa,EAAE,CAAC,SAAS,OAAO,EAAE,EACjE,EAAE,EAAE,CAAC,EACL,MAAM,EAAE,CAAC,GACR,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { entryToGuard } from "./guard.js";
|
|
2
|
+
import { Is } from "../mod.js";
|
|
3
|
+
export function extend(...args) {
|
|
4
|
+
const config = (1 in args ? args[1] : args[0]);
|
|
5
|
+
const is = 1 in args ? args[0] : Is;
|
|
6
|
+
const entries = Object.entries(config)
|
|
7
|
+
.map(([name, entry]) => [name, entryToGuard(entry)]);
|
|
8
|
+
return { ...Object.fromEntries(entries), ...(is ?? Is) };
|
|
9
|
+
}
|