@typed/router 0.27.7 → 0.28.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.
Files changed (46) hide show
  1. package/MatchInput/package.json +6 -0
  2. package/RouteGuard/package.json +6 -0
  3. package/RouteMatch/package.json +6 -0
  4. package/dist/cjs/CurrentRoute.js +48 -31
  5. package/dist/cjs/CurrentRoute.js.map +1 -1
  6. package/dist/cjs/MatchInput.js +96 -0
  7. package/dist/cjs/MatchInput.js.map +1 -0
  8. package/dist/cjs/Matcher.js +97 -73
  9. package/dist/cjs/Matcher.js.map +1 -1
  10. package/dist/cjs/RouteGuard.js +78 -0
  11. package/dist/cjs/RouteGuard.js.map +1 -0
  12. package/dist/cjs/RouteMatch.js +49 -0
  13. package/dist/cjs/RouteMatch.js.map +1 -0
  14. package/dist/cjs/index.js +25 -0
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/dts/CurrentRoute.d.ts +19 -14
  17. package/dist/dts/CurrentRoute.d.ts.map +1 -1
  18. package/dist/dts/MatchInput.d.ts +135 -0
  19. package/dist/dts/MatchInput.d.ts.map +1 -0
  20. package/dist/dts/Matcher.d.ts +94 -33
  21. package/dist/dts/Matcher.d.ts.map +1 -1
  22. package/dist/dts/RouteGuard.d.ts +94 -0
  23. package/dist/dts/RouteGuard.d.ts.map +1 -0
  24. package/dist/dts/RouteMatch.d.ts +50 -0
  25. package/dist/dts/RouteMatch.d.ts.map +1 -0
  26. package/dist/dts/index.d.ts +12 -0
  27. package/dist/dts/index.d.ts.map +1 -1
  28. package/dist/esm/CurrentRoute.js +46 -29
  29. package/dist/esm/CurrentRoute.js.map +1 -1
  30. package/dist/esm/MatchInput.js +79 -0
  31. package/dist/esm/MatchInput.js.map +1 -0
  32. package/dist/esm/Matcher.js +95 -67
  33. package/dist/esm/Matcher.js.map +1 -1
  34. package/dist/esm/RouteGuard.js +57 -0
  35. package/dist/esm/RouteGuard.js.map +1 -0
  36. package/dist/esm/RouteMatch.js +29 -0
  37. package/dist/esm/RouteMatch.js.map +1 -0
  38. package/dist/esm/index.js +12 -0
  39. package/dist/esm/index.js.map +1 -1
  40. package/package.json +35 -10
  41. package/src/CurrentRoute.ts +113 -63
  42. package/src/MatchInput.ts +282 -0
  43. package/src/Matcher.ts +325 -143
  44. package/src/RouteGuard.ts +217 -0
  45. package/src/RouteMatch.ts +104 -0
  46. package/src/index.ts +15 -0
@@ -4,23 +4,21 @@
4
4
 
5
5
  import * as Context from "@typed/context"
6
6
  import * as Document from "@typed/dom/Document"
7
+ import type * as Fx from "@typed/fx"
7
8
  import * as RefSubject from "@typed/fx/RefSubject"
8
- import type { Destination, Navigation } from "@typed/navigation"
9
- import { CurrentEntry, CurrentPath } from "@typed/navigation"
10
- import type { Layer } from "effect"
11
- import * as Option from "effect/Option"
12
-
9
+ import type { Destination } from "@typed/navigation"
10
+ import { CurrentEntry, CurrentPath, getCurrentPathFromUrl, Navigation } from "@typed/navigation"
11
+ import * as Route from "@typed/route"
13
12
  import * as Effect from "effect/Effect"
14
13
  import { dual, pipe } from "effect/Function"
15
-
16
- import type { ParamsOf } from "@typed/path"
17
- import * as Route from "@typed/route"
14
+ import type * as Layer from "effect/Layer"
15
+ import * as Option from "effect/Option"
18
16
 
19
17
  /**
20
18
  * @since 1.0.0
21
19
  */
22
- export interface CurrentRoute<P extends string = string> {
23
- readonly route: Route.Route<P>
20
+ export interface CurrentRoute {
21
+ readonly route: Route.Route.Any
24
22
  readonly parent: Option.Option<CurrentRoute>
25
23
  }
26
24
 
@@ -32,12 +30,12 @@ export const CurrentRoute: Context.Tagged<CurrentRoute> = Context.Tagged<Current
32
30
  /**
33
31
  * @since 1.0.0
34
32
  */
35
- export function make<const P extends string>(
36
- route: P | Route.Route<P>,
33
+ export function makeCurrentRoute<R extends Route.Route.Any>(
34
+ route: R,
37
35
  parent: Option.Option<CurrentRoute> = Option.none()
38
- ): CurrentRoute<P> {
36
+ ): CurrentRoute {
39
37
  return {
40
- route: getRoute(route),
38
+ route,
41
39
  parent
42
40
  }
43
41
  }
@@ -45,15 +43,11 @@ export function make<const P extends string>(
45
43
  /**
46
44
  * @since 1.0.0
47
45
  */
48
- export function layer<const P extends string>(
49
- route: P | Route.Route<P>,
46
+ export function layer<R extends Route.Route.Any>(
47
+ route: R,
50
48
  parent: Option.Option<CurrentRoute> = Option.none()
51
49
  ): Layer.Layer<CurrentRoute> {
52
- return CurrentRoute.layer(make(route, parent) as any as CurrentRoute)
53
- }
54
-
55
- function getRoute<P extends string>(route: P | Route.Route<P>): Route.Route<P> {
56
- return typeof route === "string" ? Route.fromPath(route) : route
50
+ return CurrentRoute.layer(makeCurrentRoute(route, parent))
57
51
  }
58
52
 
59
53
  /**
@@ -64,95 +58,139 @@ export const CurrentParams: RefSubject.Filtered<
64
58
  never,
65
59
  Navigation | CurrentRoute
66
60
  > = RefSubject
67
- .filterMapEffect(CurrentPath, (path) => CurrentRoute.with(({ route }) => route.match(path)))
61
+ .filteredFromTag(
62
+ Navigation,
63
+ (nav) =>
64
+ RefSubject.filterMapEffect(
65
+ nav.currentEntry,
66
+ (e) => CurrentRoute.with(({ route }) => route.match(getCurrentPathFromUrl(e.url)))
67
+ )
68
+ )
68
69
 
69
70
  /**
70
71
  * @since 1.0.0
71
72
  */
72
73
  export const withCurrentRoute: {
73
- <P extends string>(
74
- route: Route.Route<P>
74
+ <R extends Route.Route.Any>(
75
+ route: R
75
76
  ): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, CurrentRoute>>
76
77
 
77
- <A, E, R, P extends string>(
78
+ <A, E, R, R_ extends Route.Route.Any>(
78
79
  effect: Effect.Effect<A, E, R>,
79
- route: Route.Route<P>
80
+ route: R_
80
81
  ): Effect.Effect<A, E, Exclude<R, CurrentRoute>>
81
- } = dual(2, <A, E, R, P extends string>(
82
+ } = dual(2, <A, E, R, R_ extends Route.Route.Any>(
82
83
  effect: Effect.Effect<A, E, R>,
83
- route: Route.Route<P>
84
+ route: R_
84
85
  ): Effect.Effect<A, E, Exclude<R, CurrentRoute>> =>
85
86
  Effect.contextWithEffect((ctx) => {
86
87
  const parent = Context.getOption(ctx, CurrentRoute)
87
88
 
88
- if (Option.isNone(parent)) return pipe(effect, CurrentRoute.provide(make(route) as any as CurrentRoute))
89
+ if (Option.isNone(parent)) return pipe(effect, CurrentRoute.provide(makeCurrentRoute(route)))
89
90
 
90
91
  return pipe(
91
92
  effect,
92
- CurrentRoute.provide(make(parent.value.route.concat(route), parent) as CurrentRoute)
93
+ CurrentRoute.provide(makeCurrentRoute(parent.value.route.concat(route), parent))
93
94
  )
94
95
  }))
95
96
 
96
- const makeHref_ = <P extends string, P2 extends string>(
97
+ const makeHref_ = (
97
98
  currentPath: string,
98
- currentRoute: Route.Route<P>,
99
- route: Route.Route<P2>,
100
- ...[params]: [keyof ParamsOf<P2>] extends [never] ? [{}?] : [ParamsOf<P2>]
101
- ) => {
99
+ currentRoute: Route.Route.Any,
100
+ route: Route.Route.Any,
101
+ params: {} = {}
102
+ ): Option.Option<string> => {
102
103
  const currentMatch = currentRoute.match(currentPath)
103
104
  if (Option.isNone(currentMatch)) return Option.none()
104
105
 
105
106
  const fullRoute = currentRoute.concat(route)
106
107
  const fullParams = { ...currentMatch.value, ...params }
107
108
 
108
- return Option.some(fullRoute.make(fullParams as any))
109
+ return Option.some(fullRoute.interpolate(fullParams as any))
109
110
  }
110
111
 
111
112
  /**
112
113
  * @since 1.0.0
113
114
  */
114
- export function makeHref<const P extends string>(
115
- pathOrRoute: Route.Route<P> | P,
116
- ...params: [keyof ParamsOf<P>] extends [never] ? [{}?] : [ParamsOf<P>]
115
+ export function makeHref<const R extends Route.Route.Any>(
116
+ route: R,
117
+ ...[params]: Route.Route.ParamsList<R>
117
118
  ): RefSubject.Filtered<string, never, Navigation | CurrentRoute> {
118
- const route = typeof pathOrRoute === "string" ? Route.fromPath(pathOrRoute) : pathOrRoute
119
-
120
119
  return RefSubject.filterMapEffect(
121
120
  CurrentPath,
122
121
  (currentPath) =>
123
- Effect.map(CurrentRoute, (currentRoute) => makeHref_(currentPath, currentRoute.route, route, ...params))
122
+ Effect.map(
123
+ CurrentRoute,
124
+ (currentRoute): Option.Option<string> => makeHref_(currentPath, currentRoute.route, route, params)
125
+ )
124
126
  )
125
127
  }
126
128
 
127
- const isActive_ = <P extends string, P2 extends string>(
129
+ const isActive_ = (
128
130
  currentPath: string,
129
- currentRoute: Route.Route<P>,
130
- route: Route.Route<P2>,
131
- ...params: [keyof ParamsOf<P2>] extends [never] ? [{}?] : [ParamsOf<P2>]
132
- ) => {
131
+ currentRoute: Route.Route.Any,
132
+ route: Route.Route.Any,
133
+ params: any = {}
134
+ ): boolean => {
133
135
  const currentMatch = currentRoute.match(currentPath)
134
-
135
136
  if (Option.isNone(currentMatch)) return false
136
137
 
137
138
  const fullRoute = currentRoute.concat(route)
138
139
  const fullParams = { ...currentMatch.value, ...params }
139
- const fullPath = fullRoute.make(fullParams as any)
140
-
141
- return fullPath === currentPath || currentPath.startsWith(fullPath)
140
+ const fullPath: string = fullRoute.interpolate(fullParams as any)
141
+ const currentPathWithoutSearch = currentPath.split("?")[0] || "/"
142
+ const fullPathWithoutSearch = fullPath.split("?")[0] || "/"
143
+
144
+ if (fullPathWithoutSearch === currentPathWithoutSearch) {
145
+ return true
146
+ } else if (route.routeOptions.end) {
147
+ return false
148
+ } else {
149
+ return currentPathWithoutSearch.startsWith(fullPathWithoutSearch)
150
+ }
142
151
  }
152
+
143
153
  /**
144
154
  * @since 1.0.0
145
155
  */
146
- export function isActive<const P extends string>(
147
- pathOrRoute: Route.Route<P> | P,
148
- ...params: [keyof ParamsOf<P>] extends [never] ? [{}?] : [ParamsOf<P>]
156
+ export function isActive<R extends Route.Route.Any>(
157
+ route: R,
158
+ ...[params]: Route.Route.ParamsList<R>
159
+ ): RefSubject.Computed<boolean, never, Navigation | CurrentRoute>
160
+ export function isActive<R extends Route.Route.Any>(
161
+ route: R,
162
+ params: Route.Route.Params<R>
163
+ ): RefSubject.Computed<boolean, never, Navigation | CurrentRoute>
164
+ export function isActive<R extends Route.Route.Any>(
165
+ route: R,
166
+ ...[params]: Route.Route.ParamsList<R>
149
167
  ): RefSubject.Computed<boolean, never, Navigation | CurrentRoute> {
150
- const route = typeof pathOrRoute === "string" ? Route.fromPath(pathOrRoute) : pathOrRoute
151
-
152
168
  return RefSubject.mapEffect(
153
169
  CurrentPath,
154
170
  (currentPath) =>
155
- Effect.map(CurrentRoute, (currentRoute) => isActive_(currentPath, currentRoute.route, route, ...params))
171
+ CurrentRoute.with((currentRoute): boolean => isActive_(currentPath, currentRoute.route, route, params))
172
+ )
173
+ }
174
+
175
+ /**
176
+ * @since 1.0.0
177
+ */
178
+ export function decode<R extends Route.Route.Any>(
179
+ route: R
180
+ ): Fx.RefSubject.Filtered<
181
+ Route.Route.Type<R>,
182
+ Route.RouteDecodeError<R>,
183
+ Navigation | CurrentRoute | Route.Route.Context<R>
184
+ > {
185
+ return RefSubject.filteredFromTag(
186
+ Navigation,
187
+ (nav) =>
188
+ RefSubject.filterMapEffect(
189
+ nav.currentEntry,
190
+ (e) =>
191
+ Effect.flatMap(CurrentRoute, ({ route: parent }) =>
192
+ Effect.optionFromOptional(Route.decode(parent.concat(route) as R, getCurrentPathFromUrl(e.url))))
193
+ )
156
194
  )
157
195
  }
158
196
 
@@ -160,23 +198,32 @@ export function isActive<const P extends string>(
160
198
  * @since 1.0.0
161
199
  */
162
200
  export const browser: Layer.Layer<CurrentRoute, never, Document.Document> = CurrentRoute.layer(
163
- Effect.gen(function*(_) {
164
- const document = yield* _(Document.Document)
201
+ Effect.gen(function*() {
202
+ const document = yield* Document.Document
165
203
  const base = document.querySelector("base")
166
- const baseHref = base ? base.href : "/"
204
+ const baseHref = base ? getBasePathname(base.href) : "/"
167
205
 
168
206
  return {
169
- route: Route.fromPath(baseHref),
207
+ route: Route.parse(baseHref),
170
208
  parent: Option.none()
171
209
  }
172
210
  })
173
211
  )
174
212
 
213
+ function getBasePathname(base: string): string {
214
+ try {
215
+ const url = new URL(base)
216
+ return url.pathname
217
+ } catch {
218
+ return base
219
+ }
220
+ }
221
+
175
222
  /**
176
223
  * @since 1.0.0
177
224
  */
178
225
  export const server = (base: string = "/"): Layer.Layer<CurrentRoute> =>
179
- CurrentRoute.layer({ route: Route.fromPath(base), parent: Option.none() })
226
+ CurrentRoute.layer({ route: Route.parse(base), parent: Option.none() })
180
227
 
181
228
  const getSearchParams = (destination: Destination): Readonly<Record<string, string>> =>
182
229
  Object.fromEntries(destination.url.searchParams)
@@ -190,4 +237,7 @@ export const CurrentSearchParams: RefSubject.Computed<Readonly<Record<string, st
190
237
  /**
191
238
  * @since 1.0.0
192
239
  */
193
- export const CurrentState = RefSubject.map(CurrentEntry, (d) => d.state)
240
+ export const CurrentState = RefSubject.computedFromTag(
241
+ Navigation,
242
+ (n) => RefSubject.map(n.currentEntry, (e) => e.state)
243
+ )
@@ -0,0 +1,282 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+
5
+ import type * as Schema from "@effect/schema/Schema"
6
+ import type { Guard } from "@typed/guard"
7
+ import type * as _Path from "@typed/path"
8
+ import * as Route from "@typed/route"
9
+ import type * as Effect from "effect/Effect"
10
+ import { dual } from "effect/Function"
11
+ import type * as Option from "effect/Option"
12
+ import * as RouteGuard from "./RouteGuard.js"
13
+
14
+ /**
15
+ * @since 1.0.0
16
+ */
17
+ export type MatchInput<
18
+ P extends string,
19
+ S extends Schema.Schema.All,
20
+ A = never,
21
+ E = never,
22
+ R = never
23
+ > = Route.Route<P, S> | RouteGuard.RouteGuard<Route.Route<P, S>, A, E, R>
24
+
25
+ /**
26
+ * @since 1.0.0
27
+ */
28
+ export namespace MatchInput {
29
+ /**
30
+ * @since 1.0.0
31
+ */
32
+ export type Any = MatchInput<any, any, any, any, any> | MatchInput<any, never, any, any, any>
33
+
34
+ /**
35
+ * @since 1.0.0
36
+ */
37
+ export type Route<T> = T extends Route.Route<infer P, infer S> ? Route.Route<P, S>
38
+ : T extends RouteGuard.RouteGuard<Route.Route<infer P, infer S>, infer _A, infer _E, infer _R> ? Route.Route<P, S>
39
+ : never
40
+
41
+ /**
42
+ * @since 1.0.0
43
+ */
44
+ export type Path<T> = Route.Route.Path<Route<T>>
45
+
46
+ /**
47
+ * @since 1.0.0
48
+ */
49
+ export type ParamsOf<T> = Route.Route.Params<Route<T>>
50
+
51
+ /**
52
+ * @since 1.0.0
53
+ */
54
+ export type HasParams<T> = Route<T> extends Route.Route<infer P, infer _> ? _Path.HasParams<P> : false
55
+
56
+ /**
57
+ * @since 1.0.0
58
+ */
59
+ export type HasPathParams<T> = Route<T> extends Route.Route<infer P, infer _>
60
+ ? P extends `${infer P2}\\?${infer _}` ? _Path.HasParams<P2> : _Path.HasParams<P>
61
+ : false
62
+
63
+ /**
64
+ * @since 1.0.0
65
+ */
66
+ export type HasQueryParams<T> = Route<T> extends Route.Route<infer P, infer _>
67
+ ? P extends `${infer _}\\?${infer P2}` ? _Path.HasParams<`\\?${P2}`> : false
68
+ : false
69
+
70
+ /**
71
+ * @since 1.0.0
72
+ */
73
+ export type Success<T> = T extends Route.Route<infer _P, infer _S> ? Route.Route.Type<T>
74
+ : T extends RouteGuard.RouteGuard<Route.Route<infer _P, infer _S>, infer A, infer _E, infer _R> ? A
75
+ : never
76
+
77
+ /**
78
+ * @since 1.0.0
79
+ */
80
+ export type Error<T> = T extends Route.Route<infer _P, infer _S> ? Route.RouteDecodeError<T>
81
+ : T extends RouteGuard.RouteGuard<Route.Route<infer _P, infer _S>, infer _A, infer E, infer _R> ? E
82
+ : never
83
+
84
+ /**
85
+ * @since 1.0.0
86
+ */
87
+ export type Context<T> = T extends Route.Route<infer _P, infer _S> ? Route.Route.Context<T>
88
+ : T extends RouteGuard.RouteGuard<Route.Route<infer _P, infer _S>, infer _A, infer _E, infer R> ? R
89
+ : never
90
+
91
+ /**
92
+ * @since 1.0.0
93
+ */
94
+ export type Schema<T> = Route.Route.Schema<MatchInput.Route<T>>
95
+
96
+ /**
97
+ * @since 1.0.0
98
+ */
99
+ export type PathSchema<T> = Route.Route.PathSchema<MatchInput.Route<T>>
100
+
101
+ /**
102
+ * @since 1.0.0
103
+ */
104
+ export type QuerySchema<T> = Route.Route.QuerySchema<MatchInput.Route<T>>
105
+ }
106
+
107
+ /**
108
+ * @since 1.0.0
109
+ */
110
+ export function asRouteGuard<I extends MatchInput.Any>(
111
+ input: I
112
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>> {
113
+ return Route.isRoute(input) ? RouteGuard.fromRoute(input) as any : input
114
+ }
115
+
116
+ /**
117
+ * @since 1.0.0
118
+ */
119
+ export const map: {
120
+ <I extends MatchInput.Any, A>(
121
+ f: (a: MatchInput.Success<I>) => A
122
+ ): (input: I) => RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I>, MatchInput.Context<I>>
123
+
124
+ <I extends MatchInput.Any, A>(
125
+ input: I,
126
+ f: (a: MatchInput.Success<I>) => A
127
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I>, MatchInput.Context<I>>
128
+ } = dual(2, function map<I extends MatchInput.Any, A>(
129
+ input: I,
130
+ f: (a: MatchInput.Success<I>) => A
131
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I>, MatchInput.Context<I>> {
132
+ return RouteGuard.map<
133
+ RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>>,
134
+ A
135
+ >(asRouteGuard<I>(input), f)
136
+ })
137
+
138
+ /**
139
+ * @since 1.0.0
140
+ */
141
+ export const mapEffect: {
142
+ <I extends MatchInput.Any, A, E2, R2>(
143
+ f: (a: MatchInput.Success<I>) => Effect.Effect<A, E2, R2>
144
+ ): (input: I) => RouteGuard.RouteGuard<MatchInput.Route<I>, A, E2 | MatchInput.Error<I>, R2 | MatchInput.Context<I>>
145
+
146
+ <I extends MatchInput.Any, A, E2, R2>(
147
+ input: I,
148
+ f: (a: MatchInput.Success<I>) => Effect.Effect<A, E2, R2>
149
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, E2 | MatchInput.Error<I>, R2 | MatchInput.Context<I>>
150
+ } = dual(2, function mapEffect<I extends MatchInput.Any, A, E2, R2>(
151
+ input: I,
152
+ f: (a: MatchInput.Success<I>) => Effect.Effect<A, E2, R2>
153
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I> | E2, MatchInput.Context<I> | R2> {
154
+ return RouteGuard.mapEffect<
155
+ RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>>,
156
+ A,
157
+ E2,
158
+ R2
159
+ >(asRouteGuard<I>(input), f)
160
+ })
161
+
162
+ /**
163
+ * @since 1.0.0
164
+ */
165
+ export const filter: {
166
+ <I extends MatchInput.Any>(
167
+ f: (a: MatchInput.Success<I>) => boolean
168
+ ): (
169
+ input: I
170
+ ) => RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>>
171
+
172
+ <I extends MatchInput.Any>(
173
+ input: I,
174
+ f: (a: MatchInput.Success<I>) => boolean
175
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>>
176
+ } = dual(2, function filter<I extends MatchInput.Any>(
177
+ input: I,
178
+ f: (a: MatchInput.Success<I>) => boolean
179
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>> {
180
+ return RouteGuard.filter<
181
+ RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>>
182
+ >(asRouteGuard<I>(input), f)
183
+ })
184
+
185
+ /**
186
+ * @since 1.0.0
187
+ */
188
+ export const filterMap: {
189
+ <I extends MatchInput.Any, A>(
190
+ f: (a: MatchInput.Success<I>) => Option.Option<A>
191
+ ): (input: I) => RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I>, MatchInput.Context<I>>
192
+
193
+ <I extends MatchInput.Any, A>(
194
+ input: I,
195
+ f: (a: MatchInput.Success<I>) => Option.Option<A>
196
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I>, MatchInput.Context<I>>
197
+ } = dual(2, function filterMap<I extends MatchInput.Any, A>(
198
+ input: I,
199
+ f: (a: MatchInput.Success<I>) => Option.Option<A>
200
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I>, MatchInput.Context<I>> {
201
+ return RouteGuard.filterMap<
202
+ RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>>,
203
+ A
204
+ >(asRouteGuard<I>(input), f)
205
+ })
206
+
207
+ /**
208
+ * @since 1.0.0
209
+ */
210
+ export const flatMap: {
211
+ <I extends MatchInput.Any, A, E2, R2>(
212
+ guard: Guard<MatchInput.Success<I>, A, E2, R2>
213
+ ): (input: I) => RouteGuard.RouteGuard<MatchInput.Route<I>, A, E2 | MatchInput.Error<I>, R2 | MatchInput.Context<I>>
214
+
215
+ <I extends MatchInput.Any, A, E2, R2>(
216
+ input: I,
217
+ guard: Guard<MatchInput.Success<I>, A, E2, R2>
218
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, E2 | MatchInput.Error<I>, R2 | MatchInput.Context<I>>
219
+ } = dual(2, function flatMap<I extends MatchInput.Any, A, E2, R2>(
220
+ input: I,
221
+ guard: Guard<MatchInput.Success<I>, A, E2, R2>
222
+ ): RouteGuard.RouteGuard<MatchInput.Route<I>, A, MatchInput.Error<I> | E2, MatchInput.Context<I> | R2> {
223
+ return RouteGuard.flatMap<
224
+ RouteGuard.RouteGuard<MatchInput.Route<I>, MatchInput.Success<I>, MatchInput.Error<I>, MatchInput.Context<I>>,
225
+ A,
226
+ E2,
227
+ R2
228
+ >(asRouteGuard<I>(input), guard)
229
+ })
230
+
231
+ /**
232
+ * @since 1.0.0
233
+ */
234
+ export function concat<L extends MatchInput.Any, R extends MatchInput.Any>(
235
+ left: L,
236
+ right: R
237
+ ): RouteGuard.RouteGuard<
238
+ Route.Route.Concat<MatchInput.Route<L>, MatchInput.Route<R>>,
239
+ MatchInput.Success<L> & MatchInput.Success<R>,
240
+ MatchInput.Error<L> | MatchInput.Error<R>,
241
+ MatchInput.Context<L> | MatchInput.Context<R>
242
+ > {
243
+ return RouteGuard.concat<
244
+ RouteGuard.RouteGuard<MatchInput.Route<L>, MatchInput.Success<L>, MatchInput.Error<L>, MatchInput.Context<L>>,
245
+ RouteGuard.RouteGuard<MatchInput.Route<R>, MatchInput.Success<R>, MatchInput.Error<R>, MatchInput.Context<R>>
246
+ >(asRouteGuard<L>(left), asRouteGuard<R>(right))
247
+ }
248
+
249
+ /**
250
+ * @since 1.0.0
251
+ */
252
+ export function getRoute<I extends MatchInput.Any>(input: I): MatchInput.Route<I> {
253
+ return asRouteGuard<I>(input).route
254
+ }
255
+
256
+ /**
257
+ * @since 1.0.0
258
+ */
259
+ export function getSchema<I extends MatchInput.Any>(input: I): MatchInput.Schema<I> {
260
+ return asRouteGuard<I>(input).route.schema
261
+ }
262
+
263
+ /**
264
+ * @since 1.0.0
265
+ */
266
+ export function getPathSchema<I extends MatchInput.Any>(input: I): MatchInput.PathSchema<I> {
267
+ return asRouteGuard<I>(input).route.pathSchema as MatchInput.PathSchema<I>
268
+ }
269
+
270
+ /**
271
+ * @since 1.0.0
272
+ */
273
+ export function getQuerySchema<I extends MatchInput.Any>(input: I): MatchInput.QuerySchema<I> {
274
+ return asRouteGuard<I>(input).route.querySchema as MatchInput.QuerySchema<I>
275
+ }
276
+
277
+ /**
278
+ * @since 1.0.0
279
+ */
280
+ export function getPath<I extends MatchInput.Any>(input: I): MatchInput.Path<I> {
281
+ return asRouteGuard<I>(input).route.path
282
+ }