@bomb.sh/router 0.0.1 → 0.7.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 +293 -0
- package/esm/_dnt.polyfills.d.ts +11 -0
- package/esm/_dnt.polyfills.js +15 -0
- package/esm/lib/argument.d.ts +7 -0
- package/esm/lib/argument.js +66 -0
- package/esm/lib/bind.d.ts +41 -0
- package/esm/lib/bind.js +285 -0
- package/esm/lib/checkpoint.d.ts +3 -0
- package/esm/lib/checkpoint.js +5 -0
- package/esm/lib/command.d.ts +6 -0
- package/esm/lib/command.js +16 -0
- package/esm/lib/dasherize.d.ts +1 -0
- package/esm/lib/dasherize.js +7 -0
- package/esm/lib/decode.d.ts +6 -0
- package/esm/lib/decode.js +46 -0
- package/esm/lib/definition.d.ts +4 -0
- package/esm/lib/definition.js +10 -0
- package/esm/lib/dynamic.d.ts +6 -0
- package/esm/lib/dynamic.js +21 -0
- package/esm/lib/env.d.ts +34 -0
- package/esm/lib/env.js +83 -0
- package/esm/lib/extend.d.ts +2 -0
- package/esm/lib/extend.js +4 -0
- package/esm/lib/maybe.d.ts +9 -0
- package/esm/lib/maybe.js +12 -0
- package/esm/lib/multiple.d.ts +8 -0
- package/esm/lib/multiple.js +9 -0
- package/esm/lib/option.d.ts +7 -0
- package/esm/lib/option.js +31 -0
- package/esm/lib/param.d.ts +26 -0
- package/esm/lib/param.js +37 -0
- package/esm/lib/parse.d.ts +2 -0
- package/esm/lib/parse.js +338 -0
- package/esm/lib/pipeline.d.ts +182 -0
- package/esm/lib/pipeline.js +6 -0
- package/esm/lib/print.d.ts +7 -0
- package/esm/lib/print.js +156 -0
- package/esm/lib/read.d.ts +27 -0
- package/esm/lib/read.js +95 -0
- package/esm/lib/rest.d.ts +9 -0
- package/esm/lib/rest.js +1 -0
- package/esm/lib/result.d.ts +9 -0
- package/esm/lib/result.js +1 -0
- package/esm/lib/route.d.ts +9 -0
- package/esm/lib/route.js +45 -0
- package/esm/lib/toggle.d.ts +7 -0
- package/esm/lib/toggle.js +91 -0
- package/esm/lib/tokenize.d.ts +20 -0
- package/esm/lib/tokenize.js +41 -0
- package/esm/lib/tokenizer.d.ts +34 -0
- package/esm/lib/tokenizer.js +130 -0
- package/esm/lib/transform.d.ts +8 -0
- package/esm/lib/transform.js +34 -0
- package/esm/lib/types.d.ts +196 -0
- package/esm/lib/types.js +1 -0
- package/esm/lib/values.d.ts +29 -0
- package/esm/lib/values.js +83 -0
- package/esm/mod.d.ts +29 -0
- package/esm/mod.js +18 -0
- package/esm/package.json +3 -0
- package/package.json +27 -9
- package/src/_dnt.polyfills.ts +27 -0
- package/src/lib/argument.ts +100 -0
- package/src/lib/bind.ts +421 -0
- package/src/lib/checkpoint.ts +10 -0
- package/src/lib/command.ts +36 -0
- package/src/lib/dasherize.ts +7 -0
- package/src/lib/decode.ts +55 -0
- package/src/lib/definition.ts +17 -0
- package/src/lib/dynamic.ts +39 -0
- package/src/lib/env.ts +142 -0
- package/src/lib/extend.ts +12 -0
- package/src/lib/maybe.ts +22 -0
- package/src/lib/multiple.ts +23 -0
- package/src/lib/option.ts +57 -0
- package/src/lib/param.ts +96 -0
- package/src/lib/parse.ts +478 -0
- package/src/lib/pipeline.ts +549 -0
- package/src/lib/print.ts +216 -0
- package/src/lib/read.ts +133 -0
- package/src/lib/rest.ts +10 -0
- package/src/lib/result.ts +10 -0
- package/src/lib/route.ts +77 -0
- package/src/lib/toggle.ts +132 -0
- package/src/lib/tokenize.ts +74 -0
- package/src/lib/tokenizer.ts +191 -0
- package/src/lib/transform.ts +49 -0
- package/src/lib/types.ts +460 -0
- package/src/lib/values.ts +131 -0
- package/src/mod.ts +74 -0
package/README.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# @bomb.sh/router
|
|
2
|
+
|
|
3
|
+
**A statically typed entry-point router for command-line applications.**
|
|
4
|
+
|
|
5
|
+
An argument parser tells you what the user typed. `@bomb.sh/router` tells you
|
|
6
|
+
where and how they intend to enter your program. For execution, it binds a
|
|
7
|
+
validated, statically typed model for that entry point.
|
|
8
|
+
|
|
9
|
+
`@bomb.sh/router` matches input to an intent: a method at an
|
|
10
|
+
application-relative route, such as:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
HELP /
|
|
14
|
+
VERSION /
|
|
15
|
+
EXECUTE /serve
|
|
16
|
+
HELP /database/clean
|
|
17
|
+
EXECUTE /database/clean
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Every reachable intent appears in the result type. Narrow `method` and `route`,
|
|
21
|
+
and TypeScript knows the exact model available at that entry point.
|
|
22
|
+
|
|
23
|
+
`@bomb.sh/router` is not a CLI framework. It does not own handlers, effects,
|
|
24
|
+
output, or process lifetime. It is not a CLI parser whose product is a bag of
|
|
25
|
+
flags. Its product is a typed intent; your application decides what that intent
|
|
26
|
+
does.
|
|
27
|
+
|
|
28
|
+
## Define every way into the program
|
|
29
|
+
|
|
30
|
+
`route()` declares an address, and every `command()` is just an address that
|
|
31
|
+
declares an intent to execute. Every route supports help, whereas version and
|
|
32
|
+
execution exist only where they are explicitly added.
|
|
33
|
+
|
|
34
|
+
Definitions are immutable composition pipelines, not handler registrations:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import {
|
|
38
|
+
command,
|
|
39
|
+
description,
|
|
40
|
+
name,
|
|
41
|
+
option,
|
|
42
|
+
route,
|
|
43
|
+
routes,
|
|
44
|
+
schema,
|
|
45
|
+
toggle,
|
|
46
|
+
version,
|
|
47
|
+
} from "@bomb.sh/router";
|
|
48
|
+
import * as z from "zod";
|
|
49
|
+
|
|
50
|
+
export const app = command(
|
|
51
|
+
name("simulacrum"),
|
|
52
|
+
description("Run and manage local service simulators."),
|
|
53
|
+
version("1.0.0"),
|
|
54
|
+
toggle(name("verbose")),
|
|
55
|
+
routes(
|
|
56
|
+
command(
|
|
57
|
+
name("serve"),
|
|
58
|
+
option(name("port"), schema(z.number().default(4000))),
|
|
59
|
+
),
|
|
60
|
+
route(
|
|
61
|
+
name("database"),
|
|
62
|
+
routes(
|
|
63
|
+
command(
|
|
64
|
+
name("clean"),
|
|
65
|
+
toggle(name("dryRun")),
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
That definition makes these entry points—and no others—reachable:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
HELP / VERSION / EXECUTE /
|
|
77
|
+
HELP /serve EXECUTE /serve
|
|
78
|
+
HELP /database
|
|
79
|
+
HELP /database/clean EXECUTE /database/clean
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The root name identifies the executable; it is not repeated in route IDs.
|
|
83
|
+
`simulacrum serve` therefore selects `/serve`, not `/simulacrum/serve`.
|
|
84
|
+
|
|
85
|
+
## Route an intent
|
|
86
|
+
|
|
87
|
+
`parse()` returns a discriminated union of the reachable entry points. Dispatch
|
|
88
|
+
can stay flat even when the route tree is deep:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import process from "node:process";
|
|
92
|
+
import { parse, printErrors, printHelp, printVersion } from "@bomb.sh/router";
|
|
93
|
+
import { app } from "./app.ts";
|
|
94
|
+
|
|
95
|
+
const result = parse(app, { argv: process.argv.slice(2) });
|
|
96
|
+
|
|
97
|
+
if (!result.ok) {
|
|
98
|
+
console.error(printErrors(result));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
switch (result.method) {
|
|
103
|
+
case "help":
|
|
104
|
+
console.log(printHelp(result));
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
case "version":
|
|
108
|
+
console.log(printVersion(result));
|
|
109
|
+
break;
|
|
110
|
+
|
|
111
|
+
case "execute":
|
|
112
|
+
switch (result.route) {
|
|
113
|
+
case "/":
|
|
114
|
+
result.model.verbose; // boolean
|
|
115
|
+
break;
|
|
116
|
+
|
|
117
|
+
case "/serve":
|
|
118
|
+
result.model.port; // number
|
|
119
|
+
result.models["/"].verbose; // boolean
|
|
120
|
+
break;
|
|
121
|
+
|
|
122
|
+
case "/database/clean":
|
|
123
|
+
result.model.dryRun; // boolean
|
|
124
|
+
result.models["/"]; // { verbose: boolean }
|
|
125
|
+
result.models["/database"]; // {}
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
An execute intent has two views of configuration:
|
|
132
|
+
|
|
133
|
+
- `model` is owned by the selected route.
|
|
134
|
+
- `models` contains the statically typed model for every route along the
|
|
135
|
+
selected path. Sibling routes are absent from both the value and its type.
|
|
136
|
+
|
|
137
|
+
| Invocation | Intent and model |
|
|
138
|
+
| ------------------------------------- | ------------------------------------------------------------------- |
|
|
139
|
+
| `simulacrum --verbose` | `EXECUTE /` with `{ verbose: true }` |
|
|
140
|
+
| `simulacrum serve --port 4100` | `EXECUTE /serve` with `{ port: 4100 }` |
|
|
141
|
+
| `simulacrum database clean --dry-run` | `EXECUTE /database/clean` with `{ dryRun: true }` |
|
|
142
|
+
| `simulacrum --help database clean` | `HELP /database/clean`; controls target the deepest selected route |
|
|
143
|
+
| `simulacrum database` | `method-not-allowed`; `/database` does not support execution |
|
|
144
|
+
| `simulacrum serve --port nope` | `unprocessable-content`; invalid data never reaches the application |
|
|
145
|
+
|
|
146
|
+
Command literals are routing tokens, not positional arguments. As route segments
|
|
147
|
+
become discoverable, `@bomb.sh/router` scopes parameter binding to the segment
|
|
148
|
+
that owns each token. This makes identical option names on parent and child
|
|
149
|
+
routes unambiguous.
|
|
150
|
+
|
|
151
|
+
## Bind route parameters from multiple sources
|
|
152
|
+
|
|
153
|
+
CLI arguments are only one source. `@bomb.sh/router` can bind JavaScript values
|
|
154
|
+
and flat environment records onto the same route-local models:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const result = parse(app, {
|
|
158
|
+
argv: process.argv.slice(2),
|
|
159
|
+
values: [{
|
|
160
|
+
name: "config.json",
|
|
161
|
+
value: { serve: { port: 4200 } },
|
|
162
|
+
}],
|
|
163
|
+
envs: [{
|
|
164
|
+
name: "process",
|
|
165
|
+
value: process.env,
|
|
166
|
+
}],
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
For `/serve`, `serve.port` and `SERVE_PORT` both address its `port` parameter.
|
|
171
|
+
CLI text and environment text are decoded; JavaScript values are used directly.
|
|
172
|
+
The resulting value is then validated by its
|
|
173
|
+
[Standard Schema](https://standardschema.dev/) schema. Zod, ArkType, Valibot,
|
|
174
|
+
and other conforming libraries work without adapters.
|
|
175
|
+
|
|
176
|
+
Source precedence is explicit:
|
|
177
|
+
|
|
178
|
+
```text
|
|
179
|
+
CLI → environment → JavaScript values → schema default
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Pause without surrendering the type system
|
|
183
|
+
|
|
184
|
+
Sometimes the route cannot be fully configured, or even fully discovered, until
|
|
185
|
+
the application performs I/O. `@bomb.sh/router` can pause at a typed checkpoint
|
|
186
|
+
and resume with the result.
|
|
187
|
+
|
|
188
|
+
Dynamic phases serve two common cases:
|
|
189
|
+
|
|
190
|
+
- Load a configuration file, then use its contents as value sources for later
|
|
191
|
+
parameters.
|
|
192
|
+
- Load plugins, then extend the route graph with their options and routes.
|
|
193
|
+
|
|
194
|
+
`checkpoint()` is the configuration-file convenience; `dynamic()` is the general
|
|
195
|
+
route-extension mechanism. Both keep I/O in the application while preserving the
|
|
196
|
+
exact type of what parsing can produce next.
|
|
197
|
+
|
|
198
|
+
### Help and version cross checkpoints
|
|
199
|
+
|
|
200
|
+
`--help` and `--version` request methods; they do not settle an intent or bypass
|
|
201
|
+
parsing. `@bomb.sh/router` cannot produce either intent until it knows the
|
|
202
|
+
deepest selected route. A dynamic phase may introduce that route, its options,
|
|
203
|
+
or its version.
|
|
204
|
+
|
|
205
|
+
The driver must therefore resume every increment until parsing returns an
|
|
206
|
+
intent—even when the arguments contain `--help` or `--version`. This applies
|
|
207
|
+
recursively when one continuation exposes another increment.
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
app --config app.json auth0 --help
|
|
211
|
+
→ bind the configuration phase
|
|
212
|
+
→ load configuration and resume
|
|
213
|
+
→ discover /auth0
|
|
214
|
+
→ HELP /auth0
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Help and version are not escape hatches around configuration loading. Do not
|
|
218
|
+
inspect `argv` to skip a checkpoint. A phase may be required by `HELP`,
|
|
219
|
+
`VERSION`, or `EXECUTE`, so its driver work must be safe for all three: return
|
|
220
|
+
loading and validation failures as `Result` issues, avoid command side effects,
|
|
221
|
+
and defer execution until an `EXECUTE` intent. If discovery fails, report that
|
|
222
|
+
failure rather than printing incomplete help for an unresolved route graph.
|
|
223
|
+
Routes without dynamic phases still resolve directly; the rule is to stop only
|
|
224
|
+
at an intent or failure, never merely because the arguments look informational.
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import process from "node:process";
|
|
228
|
+
import {
|
|
229
|
+
checkpoint,
|
|
230
|
+
command,
|
|
231
|
+
name,
|
|
232
|
+
option,
|
|
233
|
+
parse,
|
|
234
|
+
printErrors,
|
|
235
|
+
printHelp,
|
|
236
|
+
printVersion,
|
|
237
|
+
type Result,
|
|
238
|
+
schema,
|
|
239
|
+
type ValueSource,
|
|
240
|
+
version,
|
|
241
|
+
} from "@bomb.sh/router";
|
|
242
|
+
import * as z from "zod";
|
|
243
|
+
|
|
244
|
+
const app = command(
|
|
245
|
+
name("server"),
|
|
246
|
+
version("1.0.0"),
|
|
247
|
+
option(name("config"), schema(z.string())),
|
|
248
|
+
checkpoint(),
|
|
249
|
+
option(name("port"), schema(z.number())),
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const step = parse(app, { argv: process.argv.slice(2) });
|
|
253
|
+
|
|
254
|
+
if (!step.ok) {
|
|
255
|
+
console.error(printErrors(step));
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
step.model.config; // string—the model resolved before the checkpoint
|
|
260
|
+
|
|
261
|
+
const loaded = await load(step.model.config);
|
|
262
|
+
const result = step.resume(loaded);
|
|
263
|
+
|
|
264
|
+
if (!result.ok) {
|
|
265
|
+
console.error(printErrors(result));
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
switch (result.method) {
|
|
270
|
+
case "help":
|
|
271
|
+
console.log(printHelp(result));
|
|
272
|
+
break;
|
|
273
|
+
|
|
274
|
+
case "version":
|
|
275
|
+
console.log(printVersion(result));
|
|
276
|
+
break;
|
|
277
|
+
|
|
278
|
+
case "execute":
|
|
279
|
+
result.model; // { config: string; port: number }
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
declare function load(path: string): Promise<Result<ValueSource[]>>;
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The parser remains synchronous and performs no I/O. The caller loads the file
|
|
287
|
+
and resumes with a `Result`; loader failures enter the ordinary issue path.
|
|
288
|
+
Unconsumed CLI input survives the pause, so a later `--port 5000` can override
|
|
289
|
+
the value loaded from the file.
|
|
290
|
+
|
|
291
|
+
The same phase mechanism can add options or routes from runtime data. Parsing
|
|
292
|
+
then continues against the expanded route graph, and the continuation type
|
|
293
|
+
describes the entry points that can appear next.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// https://github.com/tc39/proposal-accessible-object-hasownproperty/blob/main/polyfill.js
|
|
2
|
+
if (!Object.hasOwn) {
|
|
3
|
+
Object.defineProperty(Object, "hasOwn", {
|
|
4
|
+
value: function (object, property) {
|
|
5
|
+
if (object == null) {
|
|
6
|
+
throw new TypeError("Cannot convert undefined or null to object");
|
|
7
|
+
}
|
|
8
|
+
return Object.prototype.hasOwnProperty.call(Object(object), property);
|
|
9
|
+
},
|
|
10
|
+
configurable: true,
|
|
11
|
+
enumerable: false,
|
|
12
|
+
writable: true,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Param, type ParamModel } from "./param.js";
|
|
2
|
+
import { type Check, type Fold, type ModelElement, type Unary } from "./pipeline.js";
|
|
3
|
+
import type { Definition } from "./types.js";
|
|
4
|
+
export declare function argument<const N extends string, const E extends readonly Unary[]>(named: Definition<N>, ...elements: E & Check<Zero<N>, E>): ElementOf<N, Fold<Zero<N>, E>>;
|
|
5
|
+
type Zero<N extends string> = Param<N, unknown, "one">;
|
|
6
|
+
type ElementOf<N extends string, P> = P extends Param<N, infer Model, infer _Cardinality> ? ModelElement<ParamModel<N, Model>> : never;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { param } from "./param.js";
|
|
2
|
+
import { brand, } from "./pipeline.js";
|
|
3
|
+
export function argument(named, ...elements) {
|
|
4
|
+
const added = elements.reduce((value, element) => element(value), param(named, positional));
|
|
5
|
+
return brand((route) => {
|
|
6
|
+
let phases = [...route.phases];
|
|
7
|
+
let phase = phases.pop();
|
|
8
|
+
phases.push({
|
|
9
|
+
...phase,
|
|
10
|
+
model: {
|
|
11
|
+
params: {
|
|
12
|
+
...phase.model.params,
|
|
13
|
+
[added.name]: added,
|
|
14
|
+
},
|
|
15
|
+
steps: phase.model.steps.concat((current, bindings) => ({
|
|
16
|
+
ok: true,
|
|
17
|
+
value: {
|
|
18
|
+
...current,
|
|
19
|
+
[added.name]: bindings[added.name],
|
|
20
|
+
},
|
|
21
|
+
})),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
...route,
|
|
26
|
+
phases,
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function positional(param) {
|
|
31
|
+
return {
|
|
32
|
+
...param,
|
|
33
|
+
cli: {
|
|
34
|
+
read,
|
|
35
|
+
syntax: {
|
|
36
|
+
type: "argument",
|
|
37
|
+
label: `<${param.name.toUpperCase()}>`,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const read = (tokens) => {
|
|
43
|
+
let claim = tokens.claimOne((token) => token.type === "word");
|
|
44
|
+
let [word] = claim.tokens;
|
|
45
|
+
return word
|
|
46
|
+
? {
|
|
47
|
+
claim,
|
|
48
|
+
result: {
|
|
49
|
+
ok: true,
|
|
50
|
+
value: { exists: true, value: word.text },
|
|
51
|
+
issues: [],
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
: nothing(tokens);
|
|
55
|
+
};
|
|
56
|
+
function nothing(tokens) {
|
|
57
|
+
let claim = tokens.claimAll(() => false);
|
|
58
|
+
return {
|
|
59
|
+
claim,
|
|
60
|
+
result: {
|
|
61
|
+
ok: true,
|
|
62
|
+
value: { exists: false },
|
|
63
|
+
issues: [],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Maybe } from "./maybe.js";
|
|
2
|
+
import type { AnyParam, Param } from "./param.js";
|
|
3
|
+
import type { Symbol } from "./read.js";
|
|
4
|
+
import type { Rest } from "./rest.js";
|
|
5
|
+
import type { Result } from "./result.js";
|
|
6
|
+
import type { TokenInput, TokenRange } from "./tokenizer.js";
|
|
7
|
+
import type { AnyPhase, Issue, OutputOf, Path } from "./types.js";
|
|
8
|
+
export interface Binding<T> {
|
|
9
|
+
readonly rest: Rest;
|
|
10
|
+
readonly result: Result<T>;
|
|
11
|
+
}
|
|
12
|
+
export interface PhaseBinding {
|
|
13
|
+
readonly rest: Rest;
|
|
14
|
+
readonly model: Record<string, unknown>;
|
|
15
|
+
readonly issues: Issue[];
|
|
16
|
+
readonly valid: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface PhaseSegment {
|
|
19
|
+
readonly range: TokenRange;
|
|
20
|
+
readonly path: Path;
|
|
21
|
+
}
|
|
22
|
+
export declare function fromCLI<P extends Param<string, unknown, "one">>(options: {
|
|
23
|
+
readonly param: P;
|
|
24
|
+
readonly view: TokenInput<Symbol>;
|
|
25
|
+
readonly rest: Rest;
|
|
26
|
+
}): Maybe<Binding<OutputOf<P["schema"]>>>;
|
|
27
|
+
export declare function fromValues<P extends AnyParam>(options: {
|
|
28
|
+
readonly param: P;
|
|
29
|
+
readonly route: Path;
|
|
30
|
+
readonly rest: Rest;
|
|
31
|
+
}): Maybe<Binding<OutputOf<P["schema"]>>>;
|
|
32
|
+
export declare function fromEnv<P extends AnyParam>(options: {
|
|
33
|
+
readonly param: P;
|
|
34
|
+
readonly route: Path;
|
|
35
|
+
readonly rest: Rest;
|
|
36
|
+
}): Maybe<Binding<OutputOf<P["schema"]>>>;
|
|
37
|
+
export declare function bindPhase(options: {
|
|
38
|
+
readonly phase: AnyPhase;
|
|
39
|
+
readonly segment: PhaseSegment;
|
|
40
|
+
readonly rest: Rest;
|
|
41
|
+
}): PhaseBinding;
|