@thi.ng/router 3.4.0 → 4.0.1

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/basic.js CHANGED
@@ -15,41 +15,37 @@ import { equiv } from "@thi.ng/equiv";
15
15
  import { assert } from "@thi.ng/errors/assert";
16
16
  import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
17
17
  import { illegalArity } from "@thi.ng/errors/illegal-arity";
18
+ import { illegalState } from "@thi.ng/errors/illegal-state";
18
19
  import {
19
20
  EVENT_ROUTE_CHANGED,
20
21
  EVENT_ROUTE_FAILED
21
22
  } from "./api.js";
23
+ import { Trie } from "./trie.js";
22
24
  let BasicRouter = class {
23
- config;
25
+ opts;
24
26
  current;
25
- routeIndex;
27
+ index = {};
28
+ routes = new Trie();
26
29
  constructor(config) {
27
- this.config = {
28
- authenticator: (route, _, params) => ({
29
- id: route.id,
30
- title: route.title,
31
- params
32
- }),
30
+ this.opts = {
31
+ authenticator: (match) => match,
33
32
  prefix: "/",
34
33
  separator: "/",
35
- removeTrailingSlash: true,
34
+ trim: true,
36
35
  ...config
37
36
  };
38
- this.updateRoutes();
37
+ this.addRoutes(this.opts.routes);
39
38
  assert(
40
- this.routeForID(this.config.defaultRouteID) !== void 0,
41
- `missing config for default route: '${this.config.defaultRouteID}'`
39
+ this.routeForID(this.opts.default) !== void 0,
40
+ `missing config for default route: '${this.opts.default}'`
42
41
  );
43
- if (config.initialRouteID) {
44
- const route = this.routeForID(config.initialRouteID);
42
+ if (config.initial) {
43
+ const route = this.routeForID(config.initial);
45
44
  assert(
46
45
  route !== void 0,
47
- `missing config for initial route: ${this.config.initialRouteID}`
48
- );
49
- assert(
50
- !isParametricRoute(route),
51
- "initial route MUST not be parametric"
46
+ `missing config for initial route: ${this.opts.initial}`
52
47
  );
48
+ assert(!route.params, "initial route MUST not be parametric");
53
49
  }
54
50
  }
55
51
  // @ts-ignore: arguments
@@ -64,15 +60,24 @@ let BasicRouter = class {
64
60
  notify(event) {
65
61
  }
66
62
  start() {
67
- if (this.config.initialRouteID) {
68
- const route = this.routeForID(this.config.initialRouteID);
69
- this.current = { id: route.id, title: route.title, params: {} };
63
+ if (this.opts.initial) {
64
+ const route = this.routeForID(this.opts.initial);
65
+ this.current = { id: route.id, params: {} };
70
66
  this.notify({ id: EVENT_ROUTE_CHANGED, value: this.current });
71
67
  }
72
68
  }
73
- addRoutes(route) {
74
- this.config.routes.push(...route);
75
- this.updateRoutes();
69
+ addRoutes(routes) {
70
+ for (let r of routes) {
71
+ try {
72
+ const route = this.augmentRoute(r);
73
+ this.routes.set(route.match, route);
74
+ this.index[route.id] = route;
75
+ } catch (e) {
76
+ illegalArgs(
77
+ `error in route "${r.id}": ${e.origMessage}`
78
+ );
79
+ }
80
+ }
76
81
  }
77
82
  /**
78
83
  * Main router function. Attempts to match given input string against all
@@ -81,21 +86,25 @@ let BasicRouter = class {
81
86
  * {@link EVENT_ROUTE_FAILED} and then falls back to configured default
82
87
  * route.
83
88
  *
89
+ * @remarks
90
+ * See {@link RouteAuthenticator} for details about `ctx` handling.
91
+ *
84
92
  * @param src - route path to match
93
+ * @param ctx - arbitrary user context
85
94
  */
86
- route(src) {
87
- if (this.config.removeTrailingSlash && src.charAt(src.length - 1) === this.config.separator) {
95
+ route(src, ctx) {
96
+ if (this.opts.trim && src.charAt(src.length - 1) === this.opts.separator) {
88
97
  src = src.substring(0, src.length - 1);
89
98
  }
90
- src = src.substring(this.config.prefix.length);
91
- let match = this.matchRoutes(src);
99
+ src = src.substring(this.opts.prefix.length);
100
+ let match = this.matchRoutes(src, ctx);
92
101
  if (!match) {
93
102
  this.notify({ id: EVENT_ROUTE_FAILED, value: src });
94
103
  if (!this.handleRouteFailure()) {
95
104
  return;
96
105
  }
97
- const route = this.routeForID(this.config.defaultRouteID);
98
- match = { id: route.id, title: route.title, params: {} };
106
+ const route = this.routeForID(this.opts.default);
107
+ match = { id: route.id, redirect: true };
99
108
  }
100
109
  if (!equiv(match, this.current)) {
101
110
  this.current = match;
@@ -104,9 +113,12 @@ let BasicRouter = class {
104
113
  return match;
105
114
  }
106
115
  format(...args) {
107
- let [id, params] = args;
116
+ let [id, params, rest] = args;
108
117
  let match;
109
118
  switch (args.length) {
119
+ case 3:
120
+ match = { id, params, rest };
121
+ break;
110
122
  case 2:
111
123
  match = { id, params };
112
124
  break;
@@ -118,67 +130,81 @@ let BasicRouter = class {
118
130
  }
119
131
  const route = this.routeForID(match.id);
120
132
  if (route) {
121
- const params2 = match.params || {};
122
- return this.config.prefix + route.match.map((x) => {
133
+ const params2 = match.params;
134
+ let parts = route.match.map((x) => {
123
135
  if (isRouteParam(x)) {
124
136
  const id2 = x.substring(1);
125
- const p = params2[id2];
126
- if (p != null)
127
- return p;
128
- illegalArgs(`missing value for param '${id2}'`);
137
+ const p = params2?.[id2];
138
+ if (p == null) {
139
+ illegalArgs(`missing value for param '${id2}'`);
140
+ }
141
+ return p;
129
142
  }
130
143
  return x;
131
- }).join(this.config.separator);
144
+ });
145
+ if (route.rest >= 0)
146
+ parts = parts.slice(0, route.rest).concat(match.rest || []);
147
+ return this.opts.prefix + parts.join(this.opts.separator);
132
148
  } else {
133
149
  illegalArgs(`invalid route ID: ${match.id}`);
134
150
  }
135
151
  }
136
152
  routeForID(id) {
137
- return this.routeIndex[id];
153
+ return this.index[id];
138
154
  }
139
- updateRoutes() {
140
- this.config.routes.sort((a, b) => b.length - a.length);
141
- this.config.routes.reduce((acc, x) => {
142
- const fmt = x.match.map((y) => isRouteParam(y) ? "*" : y).join("/");
143
- if (acc[fmt]) {
144
- illegalArgs(`duplicate route: ${x.match} (id: ${x.id})`);
155
+ augmentRoute(route) {
156
+ const match = isString(route.match) ? route.match.split(this.opts.separator).filter((x) => !!x) : route.match;
157
+ const existing = this.routes.get(match);
158
+ if (existing) {
159
+ illegalArgs(
160
+ `duplicate route: ${match} (id: ${route.id}, conflicts with: ${existing.id})`
161
+ );
162
+ }
163
+ let hasParams = false;
164
+ const params = match.reduce((acc, x, i) => {
165
+ if (isRouteParam(x)) {
166
+ hasParams = true;
167
+ acc[i] = x.substring(1);
145
168
  }
146
- acc[fmt] = true;
147
169
  return acc;
148
170
  }, {});
149
- this.routeIndex = this.config.routes.reduce(
150
- (acc, r) => (acc[r.id] = r, acc),
151
- {}
152
- );
171
+ return {
172
+ ...route,
173
+ match,
174
+ params: hasParams ? params : void 0,
175
+ rest: match.indexOf("+")
176
+ };
153
177
  }
154
- matchRoutes(src) {
155
- const routes = this.config.routes;
156
- const curr = src.split(this.config.separator);
157
- for (let i = 0, n = routes.length; i < n; i++) {
158
- const match = this.matchRoute(curr, routes[i]);
159
- if (match) {
160
- return match;
161
- }
178
+ matchRoutes(src, ctx) {
179
+ const curr = src.split(this.opts.separator);
180
+ const route = this.routes.get(curr);
181
+ if (!route)
182
+ return;
183
+ let params;
184
+ if (route.params) {
185
+ params = Object.entries(route.params).reduce(
186
+ (acc, [i, k]) => (acc[k] = curr[+i], acc),
187
+ {}
188
+ );
162
189
  }
163
- }
164
- matchRoute(curr, route) {
165
- const match = route.match;
166
- const n = match.length;
167
- if (curr.length === n) {
168
- const params = {};
169
- for (let i = 0; i < n; i++) {
170
- const m = match[i];
171
- if (isRouteParam(m)) {
172
- params[m.substring(1)] = curr[i];
173
- } else if (curr[i] !== m) {
174
- return;
175
- }
176
- }
177
- if (route.validate && !this.validateRouteParams(params, route.validate)) {
178
- return;
190
+ if (route.validate && !this.validateRouteParams(params, route.validate)) {
191
+ return;
192
+ }
193
+ const rest = route.rest >= 0 ? curr.slice(route.rest) : void 0;
194
+ let match = {
195
+ id: route.id,
196
+ params,
197
+ rest
198
+ };
199
+ if (route.auth) {
200
+ match = this.opts.authenticator(match, route, ctx);
201
+ if (match && !this.index[match.id]) {
202
+ illegalState(
203
+ "auth handler returned invalid route ID: " + match.id
204
+ );
179
205
  }
180
- return route.auth ? this.config.authenticator(route, curr, params) : { id: route.id, title: route.title, params };
181
206
  }
207
+ return match;
182
208
  }
183
209
  validateRouteParams(params, validators) {
184
210
  for (let id in validators) {
@@ -201,10 +227,7 @@ let BasicRouter = class {
201
227
  BasicRouter = __decorateClass([
202
228
  INotifyMixin
203
229
  ], BasicRouter);
204
- const isParametricRoute = (route) => route.match.some(isRouteParam);
205
230
  const isRouteParam = (x) => x[0] === "?";
206
- const defMatch = (pattern, sep = "/") => pattern.split(sep).filter((x) => !!x);
207
231
  export {
208
- BasicRouter,
209
- defMatch
232
+ BasicRouter
210
233
  };
package/history.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Fn } from "@thi.ng/api";
2
2
  import type { HTMLRouterConfig } from "./api.js";
3
3
  import { BasicRouter } from "./basic.js";
4
- export declare class HTMLRouter extends BasicRouter {
4
+ export declare class HTMLRouter<T = any> extends BasicRouter<T> {
5
5
  protected currentPath: string;
6
6
  protected popHandler: Fn<PopStateEvent, void>;
7
7
  protected hashHandler: EventListener;
@@ -11,16 +11,19 @@ export declare class HTMLRouter extends BasicRouter {
11
11
  start(): void;
12
12
  release(): void;
13
13
  /**
14
- * Like `BasicRouter.route()`, but takes additional arg to control
15
- * if this routing operation should manipulate the browser's `history`.
16
- * If called from userland, this normally is true. However, we want
17
- * to avoid this if called from this router's own event handlers.
14
+ * Like {@link BasicRouter.route}, but takes additional arg to control if
15
+ * this routing operation should manipulate the browser's `history`.
16
+ *
17
+ * @remarks
18
+ * If called from userland, this normally is true (also default). However,
19
+ * we want to avoid this if called from this router's own event handlers.
18
20
  *
19
21
  * @param src -
22
+ * @param ctx -
20
23
  * @param pushState -
21
24
  */
22
- route(src: string, pushState?: boolean): import("./api.js").RouteMatch | undefined;
23
- routeTo(route: string): void;
25
+ route(src: string, ctx?: T, pushState?: boolean): import("./api.js").RouteMatch | undefined;
26
+ routeTo(route: string, ctx?: T): void;
24
27
  protected handlePopChange(): Fn<PopStateEvent, void>;
25
28
  protected handleHashChange(): EventListener;
26
29
  protected handleRouteFailure(): boolean;
package/history.js CHANGED
@@ -16,14 +16,9 @@ class HTMLRouter extends BasicRouter {
16
16
  if (this.useFragment) {
17
17
  window.addEventListener("hashchange", this.handleHashChange());
18
18
  }
19
- if (this.config.initialRouteID) {
20
- const route = this.routeForID(this.config.initialRouteID);
21
- this.route(
22
- this.format({
23
- id: route.id,
24
- title: route.title
25
- })
26
- );
19
+ if (this.opts.initial) {
20
+ const route = this.routeForID(this.opts.initial);
21
+ this.route(this.format({ id: route.id }));
27
22
  } else {
28
23
  this.route(this.useFragment ? location.hash : location.pathname);
29
24
  }
@@ -35,39 +30,39 @@ class HTMLRouter extends BasicRouter {
35
30
  }
36
31
  }
37
32
  /**
38
- * Like `BasicRouter.route()`, but takes additional arg to control
39
- * if this routing operation should manipulate the browser's `history`.
40
- * If called from userland, this normally is true. However, we want
41
- * to avoid this if called from this router's own event handlers.
33
+ * Like {@link BasicRouter.route}, but takes additional arg to control if
34
+ * this routing operation should manipulate the browser's `history`.
35
+ *
36
+ * @remarks
37
+ * If called from userland, this normally is true (also default). However,
38
+ * we want to avoid this if called from this router's own event handlers.
42
39
  *
43
40
  * @param src -
41
+ * @param ctx -
44
42
  * @param pushState -
45
43
  */
46
- route(src, pushState = true) {
44
+ route(src, ctx, pushState = true) {
47
45
  const old = this.current;
48
- const route = super.route(src);
46
+ const route = super.route(src, ctx);
49
47
  if (route && !equiv(route, old)) {
50
48
  this.currentPath = this.format(route);
51
49
  if (pushState) {
52
- history.pushState(
53
- this.currentPath,
54
- route.title || window.document.title || "",
55
- this.currentPath
56
- );
50
+ history.pushState(this.currentPath, "", this.currentPath);
57
51
  }
58
52
  }
59
53
  return route;
60
54
  }
61
- routeTo(route) {
55
+ routeTo(route, ctx) {
62
56
  if (this.useFragment) {
63
57
  location.hash = route;
64
58
  }
65
- this.route(route);
59
+ this.route(route, ctx);
66
60
  }
67
61
  handlePopChange() {
68
62
  return this.popHandler = this.popHandler || ((e) => {
69
63
  this.route(
70
64
  e.state || (this.useFragment ? location.hash : location.pathname),
65
+ void 0,
71
66
  false
72
67
  );
73
68
  }).bind(this);
@@ -77,7 +72,7 @@ class HTMLRouter extends BasicRouter {
77
72
  if (!this.ignoreHashChange) {
78
73
  const hash = e.newURL.substring(e.newURL.indexOf("#"));
79
74
  if (hash !== this.currentPath) {
80
- this.route(hash, false);
75
+ this.route(hash, void 0, false);
81
76
  }
82
77
  }
83
78
  }).bind(this);
@@ -85,7 +80,7 @@ class HTMLRouter extends BasicRouter {
85
80
  handleRouteFailure() {
86
81
  this.ignoreHashChange = true;
87
82
  location.hash = this.format({
88
- id: this.routeForID(this.config.defaultRouteID).id
83
+ id: this.routeForID(this.opts.default).id
89
84
  });
90
85
  this.ignoreHashChange = false;
91
86
  return true;
package/html.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import type { Fn } from "@thi.ng/api";
2
+ import type { HTMLRouterOpts } from "./api.js";
3
+ import { Router } from "./router.js";
4
+ export declare class HTMLRouter<T = any> extends Router<T> {
5
+ protected currentPath: string;
6
+ protected popHandler: Fn<PopStateEvent, void>;
7
+ protected hashHandler: EventListener;
8
+ protected useFragment: boolean;
9
+ protected ignoreHashChange: boolean;
10
+ constructor(config: HTMLRouterOpts);
11
+ start(): void;
12
+ release(): void;
13
+ /**
14
+ * Like {@link Router.route}, but takes additional arg to control if
15
+ * this routing operation should manipulate the browser's `history`.
16
+ *
17
+ * @remarks
18
+ * If called from userland, this normally is true (also default). However,
19
+ * we want to avoid this if called from this router's own event handlers.
20
+ *
21
+ * @param src -
22
+ * @param ctx -
23
+ * @param pushState -
24
+ */
25
+ route(src: string, ctx?: T, pushState?: boolean): import("./api.js").RouteMatch | undefined;
26
+ routeTo(route: string, ctx?: T): void;
27
+ protected handlePopChange(): Fn<PopStateEvent, void>;
28
+ protected handleHashChange(): EventListener;
29
+ protected handleRouteFailure(): boolean;
30
+ }
31
+ //# sourceMappingURL=html.d.ts.map
package/html.js ADDED
@@ -0,0 +1,91 @@
1
+ import { equiv } from "@thi.ng/equiv";
2
+ import { Router } from "./router.js";
3
+ class HTMLRouter extends Router {
4
+ currentPath;
5
+ popHandler;
6
+ hashHandler;
7
+ useFragment;
8
+ ignoreHashChange;
9
+ constructor(config) {
10
+ super({ prefix: config.useFragment ? "#/" : "/", ...config });
11
+ this.useFragment = config.useFragment !== false;
12
+ this.ignoreHashChange = false;
13
+ }
14
+ start() {
15
+ window.addEventListener("popstate", this.handlePopChange());
16
+ if (this.useFragment) {
17
+ window.addEventListener("hashchange", this.handleHashChange());
18
+ }
19
+ if (this.opts.initial) {
20
+ const route = this.routeForID(this.opts.initial);
21
+ this.route(this.format({ id: route.spec.id }));
22
+ } else {
23
+ this.route(this.useFragment ? location.hash : location.pathname);
24
+ }
25
+ }
26
+ release() {
27
+ window.removeEventListener("popstate", this.popHandler);
28
+ if (this.useFragment) {
29
+ window.removeEventListener("hashchange", this.hashHandler);
30
+ }
31
+ }
32
+ /**
33
+ * Like {@link Router.route}, but takes additional arg to control if
34
+ * this routing operation should manipulate the browser's `history`.
35
+ *
36
+ * @remarks
37
+ * If called from userland, this normally is true (also default). However,
38
+ * we want to avoid this if called from this router's own event handlers.
39
+ *
40
+ * @param src -
41
+ * @param ctx -
42
+ * @param pushState -
43
+ */
44
+ route(src, ctx, pushState = true) {
45
+ const old = this.current;
46
+ const route = super.route(src, ctx);
47
+ if (route && !equiv(route, old)) {
48
+ this.currentPath = this.format(route);
49
+ if (pushState) {
50
+ history.pushState(this.currentPath, "", this.currentPath);
51
+ }
52
+ }
53
+ return route;
54
+ }
55
+ routeTo(route, ctx) {
56
+ if (this.useFragment) {
57
+ location.hash = route;
58
+ }
59
+ this.route(route, ctx);
60
+ }
61
+ handlePopChange() {
62
+ return this.popHandler = this.popHandler || ((e) => {
63
+ this.route(
64
+ e.state || (this.useFragment ? location.hash : location.pathname),
65
+ void 0,
66
+ false
67
+ );
68
+ }).bind(this);
69
+ }
70
+ handleHashChange() {
71
+ return this.hashHandler = this.hashHandler || ((e) => {
72
+ if (!this.ignoreHashChange) {
73
+ const hash = e.newURL.substring(e.newURL.indexOf("#"));
74
+ if (hash !== this.currentPath) {
75
+ this.route(hash, void 0, false);
76
+ }
77
+ }
78
+ }).bind(this);
79
+ }
80
+ handleRouteFailure() {
81
+ this.ignoreHashChange = true;
82
+ location.hash = this.format({
83
+ id: this.routeForID(this.opts.default).spec.id
84
+ });
85
+ this.ignoreHashChange = false;
86
+ return true;
87
+ }
88
+ }
89
+ export {
90
+ HTMLRouter
91
+ };
package/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./api.js";
2
- export * from "./basic.js";
3
- export * from "./history.js";
2
+ export * from "./html.js";
3
+ export * from "./router.js";
4
+ export * from "./trie.js";
4
5
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./api.js";
2
- export * from "./basic.js";
3
- export * from "./history.js";
2
+ export * from "./html.js";
3
+ export * from "./router.js";
4
+ export * from "./trie.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@thi.ng/router",
3
- "version": "3.4.0",
4
- "description": "Generic router for browser & non-browser based applications",
3
+ "version": "4.0.1",
4
+ "description": "Generic trie-based router with support for wildcards, route param validation/coercion, auth",
5
5
  "type": "module",
6
6
  "module": "./index.js",
7
7
  "typings": "./index.d.ts",
@@ -36,18 +36,18 @@
36
36
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
37
37
  },
38
38
  "dependencies": {
39
- "@thi.ng/api": "^8.9.29",
40
- "@thi.ng/checks": "^3.5.2",
41
- "@thi.ng/equiv": "^2.1.51",
42
- "@thi.ng/errors": "^2.4.20",
39
+ "@thi.ng/api": "^8.9.30",
40
+ "@thi.ng/checks": "^3.5.3",
41
+ "@thi.ng/equiv": "^2.1.52",
42
+ "@thi.ng/errors": "^2.5.0",
43
43
  "tslib": "^2.6.2"
44
44
  },
45
45
  "devDependencies": {
46
- "@microsoft/api-extractor": "^7.40.1",
47
- "esbuild": "^0.20.0",
46
+ "@microsoft/api-extractor": "^7.42.3",
47
+ "esbuild": "^0.20.1",
48
48
  "rimraf": "^5.0.5",
49
- "typedoc": "^0.25.7",
50
- "typescript": "^5.3.3"
49
+ "typedoc": "^0.25.12",
50
+ "typescript": "^5.4.2"
51
51
  },
52
52
  "keywords": [
53
53
  "browser",
@@ -56,10 +56,13 @@
56
56
  "history",
57
57
  "html",
58
58
  "parametric",
59
+ "pattern",
59
60
  "router",
61
+ "trie",
60
62
  "typescript",
61
63
  "ui",
62
- "validate"
64
+ "validate",
65
+ "wildcards"
63
66
  ],
64
67
  "publishConfig": {
65
68
  "access": "public"
@@ -78,11 +81,14 @@
78
81
  "./api": {
79
82
  "default": "./api.js"
80
83
  },
81
- "./basic": {
82
- "default": "./basic.js"
84
+ "./html": {
85
+ "default": "./html.js"
83
86
  },
84
- "./history": {
85
- "default": "./history.js"
87
+ "./router": {
88
+ "default": "./router.js"
89
+ },
90
+ "./trie": {
91
+ "default": "./trie.js"
86
92
  }
87
93
  },
88
94
  "thi.ng": {
@@ -92,5 +98,5 @@
92
98
  ],
93
99
  "year": 2014
94
100
  },
95
- "gitHead": "c93ab989dd2013dce1a7f7434f42ef3a270b950f\n"
101
+ "gitHead": "23838381932bb72b7538b612c5ae6f0d8f24a517\n"
96
102
  }
package/router.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ import type { Event, INotify, IObjectOf, Listener, SomeRequired } from "@thi.ng/api";
2
+ import { type AugmentedRoute, type Route, type RouteMatch, type RouteParamValidator, type RouterEventType, type RouterOpts } from "./api.js";
3
+ import { Trie } from "./trie.js";
4
+ export declare class Router<T = any> implements INotify<RouterEventType> {
5
+ opts: RouterOpts<T>;
6
+ current: RouteMatch | undefined;
7
+ protected index: Record<string, AugmentedRoute>;
8
+ protected routes: Trie<AugmentedRoute>;
9
+ constructor(config: RouterOpts<T>);
10
+ addListener(id: RouterEventType, fn: Listener<RouterEventType>, scope?: any): boolean;
11
+ removeListener(id: RouterEventType, fn: Listener<RouterEventType>, scope?: any): boolean;
12
+ notify(event: Event<RouterEventType>): boolean;
13
+ start(): void;
14
+ addRoutes(routes: Route[]): void;
15
+ /**
16
+ * Main router function. Attempts to match given input string against all
17
+ * configured routes. Before returning, triggers {@link EVENT_ROUTE_CHANGED}
18
+ * with return value as well. If none of the routes matches, emits
19
+ * {@link EVENT_ROUTE_FAILED} and then falls back to configured default
20
+ * route.
21
+ *
22
+ * @remarks
23
+ * See {@link RouteAuthenticator} for details about `ctx` handling.
24
+ *
25
+ * @param src - route path to match
26
+ * @param ctx - arbitrary user context
27
+ */
28
+ route(src: string, ctx?: T): RouteMatch | undefined;
29
+ /**
30
+ * Returns a formatted version of given {@link RouteMatch}, incl. any
31
+ * params, or alternatively a registered route ID (and optional route
32
+ * params). Throws an error if an invalid route `id` is provided.
33
+ *
34
+ * @param id -
35
+ * @param params -
36
+ * @param rest -
37
+ */
38
+ format(id: string, params?: any, rest?: string[]): string;
39
+ format(match: SomeRequired<RouteMatch, "id">): string;
40
+ routeForID(id: string): AugmentedRoute | undefined;
41
+ protected augmentRoute(route: Route): AugmentedRoute;
42
+ protected matchRoutes(src: string, ctx?: T): RouteMatch | undefined;
43
+ protected validateRouteParams(params: any, validators: IObjectOf<Partial<RouteParamValidator>>): boolean;
44
+ protected handleRouteFailure(): boolean;
45
+ }
46
+ //# sourceMappingURL=router.d.ts.map