@bronti/wooter 0.0.0-stage → 6.0.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/DOC.md +289 -0
- package/LICENSE +7 -0
- package/README.md +23 -2
- package/package.json +13 -4
- package/src/Graph.ts +231 -0
- package/src/MiddlewareContext.ts +216 -0
- package/src/RouteContext.ts +312 -0
- package/src/Wooter.ts +318 -0
- package/src/WooterError.ts +26 -0
- package/src/export/error.ts +17 -0
- package/src/export/mod.ts +10 -0
- package/src/export/option.ts +8 -0
- package/src/export/path.ts +13 -0
- package/src/export/response.ts +39 -0
- package/src/export/result.ts +14 -0
- package/src/export/types.ts +1 -0
- package/src/export/use.ts +68 -0
- package/src/path/index.ts +84 -0
- package/src/path/match.ts +82 -0
- package/src/path/matcher.ts +29 -0
- package/src/path/types.ts +39 -0
- package/src/types/internal.ts +41 -0
- package/src/types/types.ts +39 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Matcher } from "./types.ts";
|
|
2
|
+
|
|
3
|
+
/** Creates a named matcher while preserving matcher typing. */
|
|
4
|
+
export const matcher = <T, Options = undefined>(
|
|
5
|
+
matcher: Matcher<T, Options>,
|
|
6
|
+
): Matcher<T, Options> => matcher;
|
|
7
|
+
|
|
8
|
+
/** Creates a one-segment matcher from a segment parser function. */
|
|
9
|
+
export function single<T, Options = undefined>(
|
|
10
|
+
fn: (seg: string, options: Options) => { ok: false } | { ok: true; value: T },
|
|
11
|
+
): Matcher<T, Options> {
|
|
12
|
+
return wrap((path, i, opt) => {
|
|
13
|
+
if (i >= path.length) return { ok: false };
|
|
14
|
+
const result = fn(path[i], opt);
|
|
15
|
+
return result.ok ? { ok: true, value: result.value, consume: 1 } : result;
|
|
16
|
+
}, fn.name);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Wraps a matcher and optionally rewrites its display name. */
|
|
20
|
+
export function wrap<T, Options = undefined>(
|
|
21
|
+
fn: Matcher<T, Options>,
|
|
22
|
+
name: string,
|
|
23
|
+
transform?: (name: string) => string,
|
|
24
|
+
): Matcher<T, Options> {
|
|
25
|
+
return Object.defineProperty(fn, "name", {
|
|
26
|
+
value: name ? (transform ? transform(name) : name) : "",
|
|
27
|
+
configurable: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Merge } from "../types/internal.ts";
|
|
2
|
+
|
|
3
|
+
/** Matches path segments and returns a parsed value and consumed count. */
|
|
4
|
+
export type Matcher<T, Options = undefined> = (
|
|
5
|
+
path: string[],
|
|
6
|
+
current_index: number,
|
|
7
|
+
options: Options,
|
|
8
|
+
) => { ok: false } | { ok: true; value: T; consume: number };
|
|
9
|
+
/** Extracts the parsed value type from a matcher-bearing parameter. */
|
|
10
|
+
export type MatcherValue<P> = P extends { matcher: Matcher<infer T, any> }
|
|
11
|
+
? T
|
|
12
|
+
: never;
|
|
13
|
+
|
|
14
|
+
/** Describes a named route parameter with an optional matcher. */
|
|
15
|
+
export type Param<
|
|
16
|
+
Name extends string = string,
|
|
17
|
+
T = unknown,
|
|
18
|
+
Options = undefined,
|
|
19
|
+
> =
|
|
20
|
+
| {
|
|
21
|
+
name: Name;
|
|
22
|
+
}
|
|
23
|
+
| { name: Name; matcher: Matcher<T, Options>; options: Options };
|
|
24
|
+
/** Resolves the value type produced by a route parameter. */
|
|
25
|
+
export type ParamValue<P> = [MatcherValue<P>] extends [never]
|
|
26
|
+
? string
|
|
27
|
+
: MatcherValue<P>;
|
|
28
|
+
|
|
29
|
+
/** A typed sequence of literal and parameter path segments. */
|
|
30
|
+
export type Path = (Param | string)[];
|
|
31
|
+
/** Infers a parameter object from a typed path. */
|
|
32
|
+
export type ParamsOfPath<P extends readonly unknown[]> = P extends readonly [
|
|
33
|
+
infer Head,
|
|
34
|
+
...infer Tail,
|
|
35
|
+
]
|
|
36
|
+
? [Head] extends [Param<infer Name, any>]
|
|
37
|
+
? Merge<{ [K in Name]: ParamValue<Head> }, ParamsOfPath<Tail>>
|
|
38
|
+
: ParamsOfPath<Tail>
|
|
39
|
+
: Record<never, never>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes optional property names from a type.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
* https://stackoverflow.com/a/49683575/15910952
|
|
6
|
+
*/
|
|
7
|
+
type OptionalPropertyNames<T> = {
|
|
8
|
+
// deno-lint-ignore ban-types
|
|
9
|
+
[K in keyof T]-?: {} extends { [P in K]: T[K] } ? K : never;
|
|
10
|
+
}[keyof T];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Merges overlapping properties while preserving requiredness rules.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
* https://stackoverflow.com/a/49683575/15910952
|
|
17
|
+
*/
|
|
18
|
+
type SpreadProperties<L, R, K extends keyof L & keyof R> = {
|
|
19
|
+
[P in K]: L[P] | Exclude<R[P], undefined>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Flattens intersections for cleaner public-facing type output.
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
* https://stackoverflow.com/a/49683575/15910952
|
|
27
|
+
*/
|
|
28
|
+
type Id<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Utility type that merges two object types with optional-property awareness.
|
|
32
|
+
*
|
|
33
|
+
* @internal
|
|
34
|
+
* https://stackoverflow.com/a/49683575/15910952
|
|
35
|
+
*/
|
|
36
|
+
export type Merge<L, R> = Id<
|
|
37
|
+
Pick<L, Exclude<keyof L, keyof R>> &
|
|
38
|
+
Pick<R, Exclude<keyof R, OptionalPropertyNames<R>>> &
|
|
39
|
+
Pick<R, Exclude<OptionalPropertyNames<R>, keyof L>> &
|
|
40
|
+
SpreadProperties<L, R, OptionalPropertyNames<R> & keyof L>
|
|
41
|
+
>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Merge } from "./internal.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generic route-parameter object shape.
|
|
5
|
+
*/
|
|
6
|
+
export type Params = Record<string, unknown>;
|
|
7
|
+
|
|
8
|
+
/** Empty object shape used when no state or parameters are defined. */
|
|
9
|
+
export type EmptyObject = Record<never, never>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generic context state object shape.
|
|
13
|
+
*/
|
|
14
|
+
export type State = Record<string, unknown>;
|
|
15
|
+
|
|
16
|
+
export type {
|
|
17
|
+
default as MiddlewareContext,
|
|
18
|
+
MiddlewareHandler,
|
|
19
|
+
} from "../MiddlewareContext.ts";
|
|
20
|
+
export type { default as RouteContext, RouteHandler } from "../RouteContext.ts";
|
|
21
|
+
export type { MethodDefinitionInput, MethodDefinitions } from "../Graph.ts";
|
|
22
|
+
|
|
23
|
+
export type { TypedMap } from "@bronti/robust/TypedMap";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Conditionally merges two state/params types when either side may be undefined.
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export type OptionalMerge<
|
|
31
|
+
A extends Record<keyof any, unknown> | undefined,
|
|
32
|
+
B extends Record<keyof any, unknown> | undefined,
|
|
33
|
+
> = A extends undefined ? B : B extends undefined ? A : Merge<A, B>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* HTTP methods for typed route declarations.
|
|
37
|
+
*/
|
|
38
|
+
export type Methods =
|
|
39
|
+
"GET" | "PUT" | "POST" | "PATCH" | "DELETE" | "OPTIONS" | "QUERY";
|