mobx-route 0.19.0 → 0.20.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 +2 -2
- package/index.cjs +86 -57
- package/index.cjs.map +1 -1
- package/index.d.ts +16 -13
- package/index.js +87 -58
- package/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,9 +22,9 @@ _Uses [`path-to-regexp` power](https://www.npmjs.com/package/path-to-regexp)_
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
|
-
import {
|
|
25
|
+
import { createRoute } from "mobx-route";
|
|
26
26
|
|
|
27
|
-
const userDetails =
|
|
27
|
+
const userDetails = createRoute("/users/:id");
|
|
28
28
|
|
|
29
29
|
await userDetails.open({ id: 1 }); // path params are required
|
|
30
30
|
|
package/index.cjs
CHANGED
|
@@ -34,7 +34,8 @@ const routeConfig = complex.createGlobalDynamicConfig(
|
|
|
34
34
|
location,
|
|
35
35
|
queryParams
|
|
36
36
|
};
|
|
37
|
-
}
|
|
37
|
+
},
|
|
38
|
+
Symbol.for("MOBX_ROUTE_CONFIG")
|
|
38
39
|
);
|
|
39
40
|
class Route {
|
|
40
41
|
constructor(path, config = {}) {
|
|
@@ -46,35 +47,27 @@ class Route {
|
|
|
46
47
|
this.isIndex = !!this.config.index;
|
|
47
48
|
this.isHash = !!this.config.hash;
|
|
48
49
|
this.meta = this.config.meta;
|
|
50
|
+
this.status = "unknown";
|
|
49
51
|
this.parent = config.parent ?? null;
|
|
50
|
-
mobx.computed
|
|
52
|
+
mobx.computed(this, "isPathMatched");
|
|
53
|
+
mobx.computed(this, "isOpened");
|
|
51
54
|
mobx.computed.struct(this, "data");
|
|
52
55
|
mobx.computed.struct(this, "params");
|
|
53
|
-
mobx.computed
|
|
54
|
-
mobx.computed
|
|
55
|
-
mobx.computed
|
|
56
|
+
mobx.computed(this, "currentPath");
|
|
57
|
+
mobx.computed(this, "hasOpenedChildren");
|
|
58
|
+
mobx.computed(this, "isAbleToMergeQuery");
|
|
56
59
|
mobx.computed(this, "baseUrl");
|
|
57
60
|
mobx.observable(this, "children");
|
|
58
61
|
mobx.observable.ref(this, "parent");
|
|
62
|
+
mobx.observable.ref(this, "status");
|
|
59
63
|
mobx.action(this, "addChildren");
|
|
64
|
+
mobx.action(this, "confirmOpening");
|
|
65
|
+
mobx.action(this, "confirmClosing");
|
|
60
66
|
mobx.action(this, "removeChildren");
|
|
61
67
|
mobx.makeObservable(this);
|
|
62
|
-
mobx.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
this.reactionDisposer = mobx.reaction(
|
|
67
|
-
() => this.isOpened,
|
|
68
|
-
this.processOpenedState,
|
|
69
|
-
{
|
|
70
|
-
signal: this.abortController.signal,
|
|
71
|
-
fireImmediately: true
|
|
72
|
-
}
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
mobx.onBecomeUnobserved(this, "isOpened", () => {
|
|
76
|
-
this.reactionDisposer?.();
|
|
77
|
-
this.reactionDisposer = void 0;
|
|
68
|
+
mobx.reaction(() => this.isPathMatched, this.checkPathMatch, {
|
|
69
|
+
signal: this.abortController.signal,
|
|
70
|
+
fireImmediately: true
|
|
78
71
|
});
|
|
79
72
|
}
|
|
80
73
|
abortController;
|
|
@@ -84,7 +77,8 @@ class Route {
|
|
|
84
77
|
_tokenData;
|
|
85
78
|
_matcher;
|
|
86
79
|
_compiler;
|
|
87
|
-
|
|
80
|
+
skipPathMatchCheck = false;
|
|
81
|
+
status;
|
|
88
82
|
meta;
|
|
89
83
|
/**
|
|
90
84
|
* Indicates if this route is an index route. Index routes activate when parent route path matches exactly.
|
|
@@ -120,7 +114,7 @@ class Route {
|
|
|
120
114
|
return { params: {}, path: pathnameToCheck };
|
|
121
115
|
}
|
|
122
116
|
this._matcher ??= pathToRegexp.match(this.tokenData, {
|
|
123
|
-
end: false,
|
|
117
|
+
end: this.config.exact ?? false,
|
|
124
118
|
...this.config.matchOptions
|
|
125
119
|
});
|
|
126
120
|
const parsed = this._matcher(pathnameToCheck);
|
|
@@ -160,13 +154,16 @@ class Route {
|
|
|
160
154
|
}
|
|
161
155
|
return params;
|
|
162
156
|
}
|
|
157
|
+
get isPathMatched() {
|
|
158
|
+
return this.parsedPathData !== null;
|
|
159
|
+
}
|
|
163
160
|
/**
|
|
164
161
|
* Defines the "open" state for this route.
|
|
165
162
|
*
|
|
166
163
|
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)
|
|
167
164
|
*/
|
|
168
165
|
get isOpened() {
|
|
169
|
-
if (this.params === null || this.
|
|
166
|
+
if (!this.isPathMatched || this.params === null || this.status !== "open-confirmed") {
|
|
170
167
|
return false;
|
|
171
168
|
}
|
|
172
169
|
return !this.config.checkOpened || this.config.checkOpened(this.parsedPathData);
|
|
@@ -223,9 +220,7 @@ class Route {
|
|
|
223
220
|
};
|
|
224
221
|
const urlCreateParams = this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ?? routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ?? defaultUrlCreateParams;
|
|
225
222
|
const path = this._compiler(this.processParams(urlCreateParams.params));
|
|
226
|
-
const url =
|
|
227
|
-
""
|
|
228
|
-
);
|
|
223
|
+
const url = `${urlCreateParams.baseUrl || ""}${this.isHash ? "#" : ""}${path}`;
|
|
229
224
|
if (outputParams?.omitQuery) {
|
|
230
225
|
return url;
|
|
231
226
|
}
|
|
@@ -254,59 +249,93 @@ class Route {
|
|
|
254
249
|
url = this.createUrl(args[0], query);
|
|
255
250
|
}
|
|
256
251
|
const state = rawState ?? null;
|
|
257
|
-
const
|
|
252
|
+
const trx = {
|
|
258
253
|
url,
|
|
259
254
|
params,
|
|
260
255
|
replace,
|
|
261
256
|
state,
|
|
262
257
|
query
|
|
263
258
|
};
|
|
264
|
-
const
|
|
265
|
-
if (
|
|
259
|
+
const isConfirmed = await this.confirmOpening(trx);
|
|
260
|
+
if (!isConfirmed) {
|
|
266
261
|
return;
|
|
267
262
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if (replace) {
|
|
272
|
-
this.history.replace(url, state);
|
|
263
|
+
this.skipPathMatchCheck = true;
|
|
264
|
+
if (trx.replace) {
|
|
265
|
+
this.history.replace(trx.url, trx.state);
|
|
273
266
|
} else {
|
|
274
|
-
this.history.push(url, state);
|
|
267
|
+
this.history.push(trx.url, trx.state);
|
|
275
268
|
}
|
|
276
|
-
|
|
277
|
-
|
|
269
|
+
}
|
|
270
|
+
get tokenData() {
|
|
271
|
+
if (!this._tokenData) {
|
|
272
|
+
this._tokenData = pathToRegexp.parse(this.path, this.config.parseOptions);
|
|
278
273
|
}
|
|
274
|
+
return this._tokenData;
|
|
279
275
|
}
|
|
280
|
-
|
|
276
|
+
async confirmOpening(trx) {
|
|
277
|
+
this.status = "opening";
|
|
281
278
|
if (this.config.beforeOpen) {
|
|
282
|
-
|
|
279
|
+
const feedback = await this.config.beforeOpen(trx);
|
|
280
|
+
if (feedback === false) {
|
|
281
|
+
mobx.runInAction(() => {
|
|
282
|
+
this.status = "open-rejected";
|
|
283
|
+
});
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
if (typeof feedback === "object") {
|
|
287
|
+
return Object.assign(trx, feedback);
|
|
288
|
+
}
|
|
283
289
|
}
|
|
290
|
+
mobx.runInAction(() => {
|
|
291
|
+
this.status = "open-confirmed";
|
|
292
|
+
});
|
|
284
293
|
return true;
|
|
285
294
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
return this.config.afterClose();
|
|
289
|
-
}
|
|
295
|
+
confirmClosing() {
|
|
296
|
+
this.status = "closed";
|
|
290
297
|
return true;
|
|
291
298
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
firstOpenedStateCheck = true;
|
|
299
|
-
processOpenedState = (isOpened) => {
|
|
300
|
-
if (this.firstOpenedStateCheck) {
|
|
301
|
-
this.firstOpenedStateCheck = false;
|
|
302
|
-
if (!isOpened) {
|
|
299
|
+
firstPathMatchingRun = true;
|
|
300
|
+
checkPathMatch = async (isPathMathched) => {
|
|
301
|
+
if (this.firstPathMatchingRun) {
|
|
302
|
+
this.firstPathMatchingRun = false;
|
|
303
|
+
if (!isPathMathched) {
|
|
303
304
|
return;
|
|
304
305
|
}
|
|
305
306
|
}
|
|
306
|
-
if (
|
|
307
|
+
if (this.skipPathMatchCheck) {
|
|
308
|
+
this.skipPathMatchCheck = false;
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (isPathMathched) {
|
|
312
|
+
const trx = {
|
|
313
|
+
url: this.parsedPathData.path,
|
|
314
|
+
params: this.parsedPathData.params,
|
|
315
|
+
state: this.history.location.state,
|
|
316
|
+
query: this.query.data
|
|
317
|
+
};
|
|
318
|
+
const nextTrxOrConfirmed = await this.confirmOpening(trx);
|
|
319
|
+
if (!nextTrxOrConfirmed) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
307
322
|
this.config.afterOpen?.(this.parsedPathData, this);
|
|
323
|
+
if (typeof nextTrxOrConfirmed === "object") {
|
|
324
|
+
if (nextTrxOrConfirmed.replace) {
|
|
325
|
+
this.history.replace(
|
|
326
|
+
nextTrxOrConfirmed.url,
|
|
327
|
+
nextTrxOrConfirmed.state
|
|
328
|
+
);
|
|
329
|
+
} else {
|
|
330
|
+
this.history.push(nextTrxOrConfirmed.url, nextTrxOrConfirmed.state);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return;
|
|
308
334
|
} else {
|
|
309
|
-
this.
|
|
335
|
+
const isConfirmed = this.confirmClosing();
|
|
336
|
+
if (isConfirmed) {
|
|
337
|
+
this.config.afterClose?.();
|
|
338
|
+
}
|
|
310
339
|
}
|
|
311
340
|
};
|
|
312
341
|
get isAbleToMergeQuery() {
|
package/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/core/config/config.ts","../src/core/route/route.ts","../src/core/route-group/route-group.ts","../src/core/router/router.ts","../src/core/utils/is-route-entity.ts","../src/core/virtual-route/virtual-route.ts"],"sourcesContent":["import {\n createBrowserHistory,\n type History,\n type IQueryParams,\n isObservableHistory,\n QueryParams,\n} from 'mobx-location-history';\nimport { createGlobalDynamicConfig } from 'yummies/complex';\n\nimport type { RouteGlobalConfig } from './config.types.js';\n\nlet localHistory: History | undefined;\n\nexport const routeConfig = createGlobalDynamicConfig<RouteGlobalConfig>(\n (update) => {\n if (localHistory && update?.history && isObservableHistory(localHistory)) {\n localHistory.destroy();\n }\n\n let history: History;\n\n if (update?.history) {\n history = update.history;\n } else {\n history = localHistory = createBrowserHistory();\n }\n\n let queryParams: IQueryParams;\n\n if (update?.history && !update.queryParams) {\n queryParams = new QueryParams({ history });\n } else {\n if (update?.queryParams) {\n queryParams = update.queryParams;\n } else {\n queryParams = new QueryParams({ history });\n }\n }\n\n return {\n ...update,\n history,\n location,\n queryParams,\n };\n },\n);\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n} from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\nimport {\n compile,\n match,\n type ParamData,\n parse,\n type TokenData,\n} from 'path-to-regexp';\nimport type { AnyObject, IsPartial, Maybe, MaybePromise } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AnyRoute,\n BeforeOpenFeedback,\n CreatedUrlOutputParams,\n InputPathParams,\n IRoute,\n ParsedPathData,\n ParsedPathParams,\n PreparedNavigationData,\n RouteConfiguration,\n RouteNavigateParams,\n UrlCreateParams,\n} from './route.types.js';\n\n/**\n * Class for creating path based route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html)\n */\nexport class Route<\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n> implements IRoute<TPath, TInputParams, TOutputParams>\n{\n protected abortController: AbortController;\n protected history: History;\n parent: TParentRoute;\n\n query: IQueryParams;\n\n private _tokenData: TokenData | undefined;\n private _matcher?: ReturnType<typeof match>;\n private _compiler?: ReturnType<typeof compile>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n meta?: AnyObject;\n\n /**\n * Indicates if this route is an index route. Index routes activate when parent route path matches exactly.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isindex-boolean)\n */\n isIndex: boolean;\n\n /**\n * Indicates if this route is an hash route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ishash-boolean)\n */\n isHash: boolean;\n\n children: AnyRoute[] = [];\n\n constructor(\n public path: TPath,\n protected config: RouteConfiguration<\n TPath,\n TInputParams,\n TOutputParams,\n TParentRoute\n > = {},\n ) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.isIndex = !!this.config.index;\n this.isHash = !!this.config.hash;\n this.meta = this.config.meta;\n this.parent = config.parent ?? (null as unknown as TParentRoute);\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'data');\n computed.struct(this, 'params');\n computed.struct(this, 'currentPath');\n computed.struct(this, 'hasOpenedChildren');\n computed.struct(this, 'isAbleToMergeQuery');\n computed(this, 'baseUrl');\n\n observable(this, 'children');\n observable.ref(this, 'parent');\n action(this, 'addChildren');\n action(this, 'removeChildren');\n\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n protected get baseUrl() {\n const baseUrl = this.config.baseUrl ?? routeConfig.get().baseUrl;\n return baseUrl?.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n }\n\n protected get parsedPathData(): ParsedPathData<TPath> | null {\n let pathnameToCheck: string;\n\n if (this.isHash) {\n pathnameToCheck = this.history.location.hash.slice(1);\n } else {\n pathnameToCheck = this.history.location.pathname;\n }\n\n if (this.baseUrl) {\n if (!this.history.location.pathname.startsWith(this.baseUrl)) {\n return null;\n }\n\n pathnameToCheck = pathnameToCheck.replace(this.baseUrl, '');\n }\n\n if (\n (this.path === '' || this.path === '/') &&\n (pathnameToCheck === '/' || pathnameToCheck === '')\n ) {\n return { params: {} as any, path: pathnameToCheck };\n }\n\n this._matcher ??= match(this.tokenData, {\n end: false,\n ...this.config.matchOptions,\n });\n const parsed = this._matcher(pathnameToCheck);\n\n if (parsed === false) {\n return null;\n }\n\n return parsed as ParsedPathData<TPath>;\n }\n\n /**\n * Matched path segment for current URL.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#currentpath-parsedpathname-null)\n */\n get currentPath(): string | null {\n return this.parsedPathData?.path ?? null;\n }\n\n /**\n * Current parsed path parameters.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params-parsedpathparams-null)\n */\n get params(): TOutputParams | null {\n if (!this.parsedPathData?.params) {\n return null;\n }\n\n let params: TOutputParams | null =\n (this.parsedPathData?.params as unknown as Maybe<TOutputParams>) ?? null;\n\n if (this.config.params) {\n const result = this.config.params(\n this.parsedPathData.params,\n this.config.meta,\n );\n if (result) {\n params = result;\n } else {\n return null;\n }\n }\n\n return params;\n }\n\n /**\n * Defines the \"open\" state for this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)\n */\n get isOpened() {\n if (this.params === null || this.parsedPathData === null) {\n return false;\n }\n\n return (\n !this.config.checkOpened || this.config.checkOpened(this.parsedPathData)\n );\n }\n\n /**\n * Allows to create child route based on this route with merging this route path and extending path.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend-path-config-route)\n */\n extend<\n TExtendedPath extends string,\n TExtendedInputParams extends\n InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>,\n TExtendedOutputParams extends AnyObject = TInputParams &\n ParsedPathParams<`${TPath}${TExtendedPath}`>,\n >(\n path: TExtendedPath,\n config?: Omit<\n RouteConfiguration<\n `${TPath}${TExtendedPath}`,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n any\n >,\n 'parent'\n >,\n ) {\n type ExtendedRoutePath = `${TPath}${TExtendedPath}`;\n type ParentRoute = this;\n // biome-ignore lint/correctness/noUnusedVariables: this is need to extract unused fields\n const { index, params, ...configFromCurrentRoute } = this.config;\n\n const extendedChild = new Route<\n ExtendedRoutePath,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n ParentRoute\n >(`${this.path}${path}`, {\n ...configFromCurrentRoute,\n ...config,\n parent: this,\n } as any);\n\n this.addChildren(extendedChild as any);\n\n return extendedChild;\n }\n\n addChildren(...routes: AnyRoute[]) {\n this.children.push(...routes);\n }\n\n removeChildren(...routes: AnyRoute[]) {\n this.children = this.children.filter((child) => !routes.includes(child));\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#hasopenedchildren-boolean)\n */\n get hasOpenedChildren(): boolean {\n return this.children.some(\n (child) => child.isOpened || child.hasOpenedChildren,\n );\n }\n\n protected processParams(\n params?: TInputParams | null | undefined,\n ): ParamData | undefined {\n if (params == null) return undefined;\n\n return Object.entries(params).reduce((acc, [key, value]) => {\n if (value != null) {\n acc[key] = Array.isArray(value) ? value.map(String) : String(value);\n }\n return acc;\n }, {} as ParamData);\n }\n\n createUrl(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: Maybe<TInputParams>,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n : [\n params: TInputParams,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n ) {\n const params = args[0];\n const rawQuery = args[1];\n const mergeQueryOrOutputParams = args[2] ?? this.isAbleToMergeQuery;\n const outputParams: Maybe<CreatedUrlOutputParams> =\n typeof mergeQueryOrOutputParams === 'boolean'\n ? { mergeQuery: mergeQueryOrOutputParams }\n : mergeQueryOrOutputParams;\n\n const query = outputParams?.mergeQuery\n ? { ...this.query.data, ...rawQuery }\n : (rawQuery ?? {});\n\n this._compiler ??= compile(this.tokenData);\n\n const defaultUrlCreateParams: UrlCreateParams<TInputParams> = {\n baseUrl: this.baseUrl,\n params: params as TInputParams,\n query,\n };\n const urlCreateParams: UrlCreateParams<TInputParams> =\n this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ??\n routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ??\n defaultUrlCreateParams;\n\n const path = this._compiler(this.processParams(urlCreateParams.params));\n\n const url = [urlCreateParams.baseUrl, this.isHash ? '#' : '', path].join(\n '',\n );\n\n if (outputParams?.omitQuery) {\n return url;\n }\n\n return `${url}${buildSearchString(urlCreateParams.query)}`;\n }\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n navigateParams?: RouteNavigateParams,\n ]\n : [params: TInputParams, navigateParams?: RouteNavigateParams]\n ): Promise<void>;\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n : [\n params: TInputParams,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n ): Promise<void>;\n open(url: string, navigateParams?: RouteNavigateParams): Promise<void>;\n open(\n url: string,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ): Promise<void>;\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n async open(...args: any[]) {\n const {\n replace,\n state: rawState,\n query: rawQuery,\n mergeQuery: rawMergeQuery,\n } = typeof args[1] === 'boolean' || args.length > 2\n ? ({ replace: args[1], query: args[2] } as RouteNavigateParams)\n : ((args[1] ?? {}) as RouteNavigateParams);\n let url: string;\n let params: Maybe<InputPathParams<TPath>>;\n\n const mergeQuery = rawMergeQuery ?? this.isAbleToMergeQuery;\n const query = mergeQuery ? { ...this.query.data, ...rawQuery } : rawQuery;\n\n if (typeof args[0] === 'string') {\n url = args[0];\n } else {\n params = args[0] as InputPathParams<TPath>;\n url = this.createUrl(args[0], query);\n }\n\n const state = rawState ?? null;\n\n const navigationData: PreparedNavigationData<TInputParams> = {\n url,\n params: params as TInputParams,\n replace,\n state,\n query,\n };\n\n const feedback = await this.beforeOpen(navigationData);\n\n if (feedback === false) {\n return;\n }\n\n if (typeof feedback === 'object') {\n Object.assign(navigationData, feedback);\n }\n\n if (replace) {\n this.history.replace(url, state);\n } else {\n this.history.push(url, state);\n }\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.parsedPathData!, this);\n }\n }\n\n protected beforeOpen(\n openData: PreparedNavigationData<TInputParams>,\n ): MaybePromise<BeforeOpenFeedback> {\n if (this.config.beforeOpen) {\n return this.config.beforeOpen(openData);\n }\n\n return true;\n }\n\n protected afterClose() {\n if (this.config.afterClose) {\n return this.config.afterClose();\n }\n\n return true;\n }\n\n protected get tokenData() {\n if (!this._tokenData) {\n this._tokenData = parse(this.path, this.config.parseOptions);\n }\n return this._tokenData;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.parsedPathData!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n private get isAbleToMergeQuery() {\n return this.config.mergeQuery ?? routeConfig.get().mergeQuery;\n }\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createRoute = <\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n>(\n path: TPath,\n config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute>,\n) => new Route<TPath, TInputParams, TOutputParams, TParentRoute>(path, config);\n","import { computed, makeObservable, observable } from 'mobx';\n\nimport type {\n AbstractRouteGroup,\n AnyRouteEntity,\n RoutesCollection,\n} from './route-group.types.js';\n\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Class for grouping related routes and managing their state.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html)\n */\nexport class RouteGroup<TRoutesCollection extends RoutesCollection>\n implements AbstractRouteGroup<TRoutesCollection>\n{\n routes: TRoutesCollection;\n\n constructor(\n routes: TRoutesCollection,\n private _indexRoute?: AnyRouteEntity,\n ) {\n this.routes = routes;\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'indexRoute');\n observable.shallow(this, 'routes');\n makeObservable(this);\n }\n\n /**\n * Returns true if at least one route in the group is open.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#isopened-boolean)\n */\n get isOpened(): boolean {\n const routes = Object.values(this.routes);\n return routes.some(\n (route) =>\n route.isOpened ||\n ('hasOpenedChildren' in route && route.hasOpenedChildren),\n );\n }\n\n /**\n * First found index route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#indexroute-route-undefined)\n */\n get indexRoute(): AnyRouteEntity | undefined {\n return (this._indexRoute ??\n Object.values(this.routes).find(\n (route) => 'isIndex' in route && route.isIndex,\n )) as unknown as AnyRouteEntity;\n }\n\n /**\n * Main navigation method for the group.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#open-args-any-void)\n */\n open(...args: any[]) {\n let lastGroupRoute: RouteGroup<any> | undefined;\n\n if (this.indexRoute && 'open' in this.indexRoute) {\n this.indexRoute.open(...args);\n return;\n }\n\n for (const routeName in this.routes) {\n const route = this.routes[routeName];\n if (route instanceof RouteGroup) {\n lastGroupRoute = route;\n }\n }\n\n if (lastGroupRoute) {\n lastGroupRoute.open(...args);\n } else if (process.env.NODE_ENV !== 'production') {\n console.warn(\n \"RouteGroup doesn't have index route. open() method doesn't work.\",\n );\n }\n }\n}\n\nexport const createRouteGroup = <TRoutesCollection extends RoutesCollection>(\n routes: TRoutesCollection,\n indexRoute?: AnyRouteEntity,\n) => new RouteGroup<TRoutesCollection>(routes, indexRoute);\n","import { computed, makeObservable } from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\n\nimport { routeConfig } from '../config/index.js';\nimport type { RoutesCollection } from '../route-group/index.js';\n\nimport type {\n RouterConfiguration,\n RouterNavigateOptions,\n} from './router.types.js';\n\n/**\n * Class for centralized routing management.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Router.html)\n */\nexport class Router<TRoutesCollection extends RoutesCollection> {\n routes: TRoutesCollection;\n history: History;\n query: IQueryParams;\n\n constructor(config: RouterConfiguration<TRoutesCollection>) {\n this.routes = config.routes;\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n\n computed.struct(this, 'location');\n\n makeObservable(this);\n }\n\n get location() {\n return this.history.location;\n }\n\n navigate(url: string, options?: RouterNavigateOptions) {\n const query =\n (options?.mergeQuery ?? routeConfig.get().mergeQuery)\n ? { ...this.query.data, ...options?.query }\n : { ...options?.query };\n\n const searchString = buildSearchString(query);\n const navigationUrl = `${url}${searchString}`;\n\n if (options?.replace) {\n this.history.replace(navigationUrl, options?.state);\n } else {\n this.history.push(navigationUrl, options?.state);\n }\n }\n}\n\nexport const createRouter = <TRoutesCollection extends RoutesCollection>(\n config: RouterConfiguration<TRoutesCollection>,\n) => new Router(config);\n","import type { AnyRouteEntity } from '../route-group/index.js';\n\nexport const isRouteEntity = (route: any): route is AnyRouteEntity =>\n route && 'isOpened' in route;\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n runInAction,\n} from 'mobx';\nimport type { IQueryParams } from 'mobx-location-history';\nimport { callFunction } from 'yummies/common';\nimport type { AnyObject, EmptyObject, IsPartial, Maybe } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AbstractVirtualRoute,\n VirtualOpenExtraParams,\n VirtualRouteConfiguration,\n} from './virtual-route.types.js';\n\n/**\n * Class for creating routes with custom activation logic\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html)\n */\nexport class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject>\n implements AbstractVirtualRoute<TParams>\n{\n protected abortController: AbortController;\n query: IQueryParams;\n params: TParams | null;\n\n private isLocalOpened: boolean;\n\n private openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n constructor(protected config: VirtualRouteConfiguration<TParams> = {}) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.params = callFunction(config.initialParams, this) ?? null;\n this.openChecker = config.checkOpened;\n this.isLocalOpened = this.openChecker?.(this) ?? false;\n\n observable(this, 'params');\n observable.ref(this, 'isLocalOpened');\n observable.ref(this, '_isOpened');\n computed.struct(this, 'isOpened');\n action(this, 'setOpenChecker');\n action(this, 'open');\n action(this, 'close');\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isopened-boolean)\n */\n get isOpened() {\n const isOuterOpened = this.openChecker == null || this.openChecker(this);\n return this.isLocalOpened && isOuterOpened;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#setopenchecker-openchecker-void)\n */\n setOpenChecker(\n openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>,\n ) {\n this.openChecker = openChecker;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#open-params-extraparams-query-replace-promise-void)\n */\n open(\n ...args: IsPartial<TParams> extends true\n ? [params?: Maybe<TParams>, extraParams?: VirtualOpenExtraParams]\n : [params: TParams, extraParams?: VirtualOpenExtraParams]\n ): Promise<void>;\n async open(...args: any[]) {\n const params = (args[0] ?? {}) as unknown as TParams;\n const extraParams: Maybe<VirtualOpenExtraParams> = args[1];\n\n if (this.config.beforeOpen) {\n const beforeOpenResult = await this.config.beforeOpen(params, this);\n if (beforeOpenResult === false) {\n return;\n }\n }\n\n if (this.config.open == null) {\n runInAction(() => {\n this.isLocalOpened = true;\n });\n } else {\n const result = await this.config.open(params, this);\n // because result can return void so this is truthy for opening state\n runInAction(() => {\n this.isLocalOpened = result !== false;\n });\n }\n\n if (!this.isLocalOpened) {\n return;\n }\n\n if (extraParams?.query) {\n this.query.update(extraParams.query, extraParams.replace);\n }\n\n runInAction(() => {\n this.params = params;\n });\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.params!, this);\n }\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#close-void)\n */\n close() {\n if (this.config.close == null) {\n this.isLocalOpened = false;\n } else {\n const result = this.config.close(this);\n // because result can return void so this is truthy for opening state\n this.isLocalOpened = result !== false;\n }\n\n this.params = null;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.params!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createVirtualRoute = <\n TParams extends AnyObject | EmptyObject = EmptyObject,\n>(\n config?: VirtualRouteConfiguration<TParams>,\n) => new VirtualRoute<TParams>(config);\n"],"names":["createGlobalDynamicConfig","isObservableHistory","createBrowserHistory","QueryParams","LinkedAbortController","computed","observable","action","makeObservable","onBecomeObserved","reaction","onBecomeUnobserved","match","compile","buildSearchString","parse","callFunction","runInAction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/core/config/config.ts","../src/core/route/route.ts","../src/core/route-group/route-group.ts","../src/core/router/router.ts","../src/core/utils/is-route-entity.ts","../src/core/virtual-route/virtual-route.ts"],"sourcesContent":["import {\n createBrowserHistory,\n type History,\n type IQueryParams,\n isObservableHistory,\n QueryParams,\n} from 'mobx-location-history';\nimport { createGlobalDynamicConfig } from 'yummies/complex';\n\nimport type { RouteGlobalConfig } from './config.types.js';\n\nlet localHistory: History | undefined;\n\nexport const routeConfig = createGlobalDynamicConfig<RouteGlobalConfig>(\n (update) => {\n if (localHistory && update?.history && isObservableHistory(localHistory)) {\n localHistory.destroy();\n }\n\n let history: History;\n\n if (update?.history) {\n history = update.history;\n } else {\n history = localHistory = createBrowserHistory();\n }\n\n let queryParams: IQueryParams;\n\n if (update?.history && !update.queryParams) {\n queryParams = new QueryParams({ history });\n } else {\n if (update?.queryParams) {\n queryParams = update.queryParams;\n } else {\n queryParams = new QueryParams({ history });\n }\n }\n\n return {\n ...update,\n history,\n location,\n queryParams,\n };\n },\n Symbol.for('MOBX_ROUTE_CONFIG'),\n);\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n reaction,\n runInAction,\n} from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\nimport {\n compile,\n match,\n type ParamData,\n parse,\n type TokenData,\n} from 'path-to-regexp';\nimport type { AnyObject, IsPartial, Maybe } from 'yummies/types';\nimport { routeConfig } from '../config/index.js';\nimport type {\n AnyRoute,\n CreatedUrlOutputParams,\n InputPathParams,\n IRoute,\n NavigationTrx,\n ParsedPathData,\n ParsedPathParams,\n RouteConfiguration,\n RouteNavigateParams,\n UrlCreateParams,\n} from './route.types.js';\n\n/**\n * Class for creating path based route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html)\n */\nexport class Route<\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n> implements IRoute<TPath, TInputParams, TOutputParams>\n{\n protected abortController: AbortController;\n protected history: History;\n parent: TParentRoute;\n\n query: IQueryParams;\n\n private _tokenData: TokenData | undefined;\n private _matcher?: ReturnType<typeof match>;\n private _compiler?: ReturnType<typeof compile>;\n private skipPathMatchCheck = false;\n\n protected status:\n | 'opening'\n | 'closed'\n | 'open-rejected'\n | 'open-confirmed'\n | 'unknown';\n\n meta?: AnyObject;\n\n /**\n * Indicates if this route is an index route. Index routes activate when parent route path matches exactly.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isindex-boolean)\n */\n isIndex: boolean;\n\n /**\n * Indicates if this route is an hash route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ishash-boolean)\n */\n isHash: boolean;\n\n children: AnyRoute[] = [];\n\n constructor(\n public path: TPath,\n protected config: RouteConfiguration<\n TPath,\n TInputParams,\n TOutputParams,\n TParentRoute\n > = {},\n ) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.isIndex = !!this.config.index;\n this.isHash = !!this.config.hash;\n this.meta = this.config.meta;\n this.status = 'unknown';\n this.parent = config.parent ?? (null as unknown as TParentRoute);\n\n computed(this, 'isPathMatched');\n computed(this, 'isOpened');\n computed.struct(this, 'data');\n computed.struct(this, 'params');\n computed(this, 'currentPath');\n computed(this, 'hasOpenedChildren');\n computed(this, 'isAbleToMergeQuery');\n computed(this, 'baseUrl');\n\n observable(this, 'children');\n observable.ref(this, 'parent');\n observable.ref(this, 'status');\n action(this, 'addChildren');\n action(this, 'confirmOpening');\n action(this, 'confirmClosing');\n action(this, 'removeChildren');\n\n makeObservable(this);\n\n reaction(() => this.isPathMatched, this.checkPathMatch, {\n signal: this.abortController.signal,\n fireImmediately: true,\n });\n }\n\n protected get baseUrl() {\n const baseUrl = this.config.baseUrl ?? routeConfig.get().baseUrl;\n return baseUrl?.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n }\n\n protected get parsedPathData(): ParsedPathData<TPath> | null {\n let pathnameToCheck: string;\n\n if (this.isHash) {\n pathnameToCheck = this.history.location.hash.slice(1);\n } else {\n pathnameToCheck = this.history.location.pathname;\n }\n\n if (this.baseUrl) {\n if (!this.history.location.pathname.startsWith(this.baseUrl)) {\n return null;\n }\n\n pathnameToCheck = pathnameToCheck.replace(this.baseUrl, '');\n }\n\n if (\n (this.path === '' || this.path === '/') &&\n (pathnameToCheck === '/' || pathnameToCheck === '')\n ) {\n return { params: {} as any, path: pathnameToCheck };\n }\n\n this._matcher ??= match(this.tokenData, {\n end: this.config.exact ?? false,\n ...this.config.matchOptions,\n });\n const parsed = this._matcher(pathnameToCheck);\n\n if (parsed === false) {\n return null;\n }\n\n return parsed as ParsedPathData<TPath>;\n }\n\n /**\n * Matched path segment for current URL.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#currentpath-parsedpathname-null)\n */\n get currentPath(): string | null {\n return this.parsedPathData?.path ?? null;\n }\n\n /**\n * Current parsed path parameters.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params-parsedpathparams-null)\n */\n get params(): TOutputParams | null {\n if (!this.parsedPathData?.params) {\n return null;\n }\n\n let params: TOutputParams | null =\n (this.parsedPathData?.params as unknown as Maybe<TOutputParams>) ?? null;\n\n if (this.config.params) {\n const result = this.config.params(\n this.parsedPathData.params,\n this.config.meta,\n );\n if (result) {\n params = result;\n } else {\n return null;\n }\n }\n\n return params;\n }\n\n protected get isPathMatched() {\n return this.parsedPathData !== null;\n }\n\n /**\n * Defines the \"open\" state for this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)\n */\n get isOpened() {\n if (\n !this.isPathMatched ||\n this.params === null ||\n this.status !== 'open-confirmed'\n ) {\n return false;\n }\n\n return (\n !this.config.checkOpened || this.config.checkOpened(this.parsedPathData!)\n );\n }\n\n /**\n * Allows to create child route based on this route with merging this route path and extending path.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend-path-config-route)\n */\n extend<\n TExtendedPath extends string,\n TExtendedInputParams extends\n InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>,\n TExtendedOutputParams extends AnyObject = TInputParams &\n ParsedPathParams<`${TPath}${TExtendedPath}`>,\n >(\n path: TExtendedPath,\n config?: Omit<\n RouteConfiguration<\n `${TPath}${TExtendedPath}`,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n any\n >,\n 'parent'\n >,\n ) {\n type ExtendedRoutePath = `${TPath}${TExtendedPath}`;\n type ParentRoute = this;\n // biome-ignore lint/correctness/noUnusedVariables: this is need to extract unused fields\n const { index, params, ...configFromCurrentRoute } = this.config;\n\n const extendedChild = new Route<\n ExtendedRoutePath,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n ParentRoute\n >(`${this.path}${path}`, {\n ...configFromCurrentRoute,\n ...config,\n parent: this,\n } as any);\n\n this.addChildren(extendedChild as any);\n\n return extendedChild;\n }\n\n addChildren(...routes: AnyRoute[]) {\n this.children.push(...routes);\n }\n\n removeChildren(...routes: AnyRoute[]) {\n this.children = this.children.filter((child) => !routes.includes(child));\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#hasopenedchildren-boolean)\n */\n get hasOpenedChildren(): boolean {\n return this.children.some(\n (child) => child.isOpened || child.hasOpenedChildren,\n );\n }\n\n protected processParams(\n params?: TInputParams | null | undefined,\n ): ParamData | undefined {\n if (params == null) return undefined;\n\n return Object.entries(params).reduce((acc, [key, value]) => {\n if (value != null) {\n acc[key] = Array.isArray(value) ? value.map(String) : String(value);\n }\n return acc;\n }, {} as ParamData);\n }\n\n createUrl(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: Maybe<TInputParams>,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n : [\n params: TInputParams,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n ) {\n const params = args[0];\n const rawQuery = args[1];\n const mergeQueryOrOutputParams = args[2] ?? this.isAbleToMergeQuery;\n const outputParams: Maybe<CreatedUrlOutputParams> =\n typeof mergeQueryOrOutputParams === 'boolean'\n ? { mergeQuery: mergeQueryOrOutputParams }\n : mergeQueryOrOutputParams;\n\n const query = outputParams?.mergeQuery\n ? { ...this.query.data, ...rawQuery }\n : (rawQuery ?? {});\n\n this._compiler ??= compile(this.tokenData);\n\n const defaultUrlCreateParams: UrlCreateParams<TInputParams> = {\n baseUrl: this.baseUrl,\n params: params as TInputParams,\n query,\n };\n const urlCreateParams: UrlCreateParams<TInputParams> =\n this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ??\n routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ??\n defaultUrlCreateParams;\n\n const path = this._compiler(this.processParams(urlCreateParams.params));\n\n const url = `${urlCreateParams.baseUrl || ''}${this.isHash ? '#' : ''}${path}`;\n\n if (outputParams?.omitQuery) {\n return url;\n }\n\n return `${url}${buildSearchString(urlCreateParams.query)}`;\n }\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n navigateParams?: RouteNavigateParams,\n ]\n : [params: TInputParams, navigateParams?: RouteNavigateParams]\n ): Promise<void>;\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n : [\n params: TInputParams,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n ): Promise<void>;\n open(url: string, navigateParams?: RouteNavigateParams): Promise<void>;\n open(\n url: string,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ): Promise<void>;\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n async open(...args: any[]) {\n const {\n replace,\n state: rawState,\n query: rawQuery,\n mergeQuery: rawMergeQuery,\n } = typeof args[1] === 'boolean' || args.length > 2\n ? ({ replace: args[1], query: args[2] } as RouteNavigateParams)\n : ((args[1] ?? {}) as RouteNavigateParams);\n let url: string;\n let params: Maybe<InputPathParams<TPath>>;\n\n const mergeQuery = rawMergeQuery ?? this.isAbleToMergeQuery;\n const query = mergeQuery ? { ...this.query.data, ...rawQuery } : rawQuery;\n\n if (typeof args[0] === 'string') {\n url = args[0];\n } else {\n params = args[0] as InputPathParams<TPath>;\n url = this.createUrl(args[0], query);\n }\n\n const state = rawState ?? null;\n\n const trx: NavigationTrx<TInputParams> = {\n url,\n params: params as TInputParams,\n replace,\n state,\n query,\n };\n\n const isConfirmed = await this.confirmOpening(trx);\n\n if (!isConfirmed) {\n return;\n }\n\n this.skipPathMatchCheck = true;\n\n if (trx.replace) {\n this.history.replace(trx.url, trx.state);\n } else {\n this.history.push(trx.url, trx.state);\n }\n }\n\n protected get tokenData() {\n if (!this._tokenData) {\n this._tokenData = parse(this.path, this.config.parseOptions);\n }\n return this._tokenData;\n }\n\n protected async confirmOpening(trx: NavigationTrx<TInputParams>) {\n this.status = 'opening';\n\n if (this.config.beforeOpen) {\n const feedback = await this.config.beforeOpen(trx);\n\n if (feedback === false) {\n runInAction(() => {\n this.status = 'open-rejected';\n });\n return false;\n }\n\n if (typeof feedback === 'object') {\n return Object.assign(trx, feedback);\n }\n }\n\n runInAction(() => {\n this.status = 'open-confirmed';\n });\n\n return true;\n }\n\n protected confirmClosing() {\n this.status = 'closed';\n return true;\n }\n\n private firstPathMatchingRun = true;\n\n private checkPathMatch = async (isPathMathched: boolean) => {\n if (this.firstPathMatchingRun) {\n this.firstPathMatchingRun = false;\n // ignore first 'afterClose' callback call\n if (!isPathMathched) {\n return;\n }\n }\n\n if (this.skipPathMatchCheck) {\n // after open\n this.skipPathMatchCheck = false;\n return;\n }\n\n if (isPathMathched) {\n const trx: NavigationTrx<TInputParams> = {\n url: this.parsedPathData!.path,\n params: this.parsedPathData!.params as TInputParams,\n state: this.history.location.state,\n query: this.query.data,\n };\n\n const nextTrxOrConfirmed = await this.confirmOpening(trx);\n\n if (!nextTrxOrConfirmed) {\n return;\n }\n\n this.config.afterOpen?.(this.parsedPathData!, this);\n\n if (typeof nextTrxOrConfirmed === 'object') {\n if (nextTrxOrConfirmed.replace) {\n this.history.replace(\n nextTrxOrConfirmed.url,\n nextTrxOrConfirmed.state,\n );\n } else {\n this.history.push(nextTrxOrConfirmed.url, nextTrxOrConfirmed.state);\n }\n }\n\n return;\n } else {\n const isConfirmed = this.confirmClosing();\n\n if (isConfirmed) {\n this.config.afterClose?.();\n }\n }\n };\n\n private get isAbleToMergeQuery() {\n return this.config.mergeQuery ?? routeConfig.get().mergeQuery;\n }\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createRoute = <\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n>(\n path: TPath,\n config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute>,\n) => new Route<TPath, TInputParams, TOutputParams, TParentRoute>(path, config);\n","import { computed, makeObservable, observable } from 'mobx';\n\nimport type {\n AbstractRouteGroup,\n AnyRouteEntity,\n RoutesCollection,\n} from './route-group.types.js';\n\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Class for grouping related routes and managing their state.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html)\n */\nexport class RouteGroup<TRoutesCollection extends RoutesCollection>\n implements AbstractRouteGroup<TRoutesCollection>\n{\n routes: TRoutesCollection;\n\n constructor(\n routes: TRoutesCollection,\n private _indexRoute?: AnyRouteEntity,\n ) {\n this.routes = routes;\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'indexRoute');\n observable.shallow(this, 'routes');\n makeObservable(this);\n }\n\n /**\n * Returns true if at least one route in the group is open.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#isopened-boolean)\n */\n get isOpened(): boolean {\n const routes = Object.values(this.routes);\n return routes.some(\n (route) =>\n route.isOpened ||\n ('hasOpenedChildren' in route && route.hasOpenedChildren),\n );\n }\n\n /**\n * First found index route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#indexroute-route-undefined)\n */\n get indexRoute(): AnyRouteEntity | undefined {\n return (this._indexRoute ??\n Object.values(this.routes).find(\n (route) => 'isIndex' in route && route.isIndex,\n )) as unknown as AnyRouteEntity;\n }\n\n /**\n * Main navigation method for the group.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#open-args-any-void)\n */\n open(...args: any[]) {\n let lastGroupRoute: RouteGroup<any> | undefined;\n\n if (this.indexRoute && 'open' in this.indexRoute) {\n this.indexRoute.open(...args);\n return;\n }\n\n for (const routeName in this.routes) {\n const route = this.routes[routeName];\n if (route instanceof RouteGroup) {\n lastGroupRoute = route;\n }\n }\n\n if (lastGroupRoute) {\n lastGroupRoute.open(...args);\n } else if (process.env.NODE_ENV !== 'production') {\n console.warn(\n \"RouteGroup doesn't have index route. open() method doesn't work.\",\n );\n }\n }\n}\n\nexport const createRouteGroup = <TRoutesCollection extends RoutesCollection>(\n routes: TRoutesCollection,\n indexRoute?: AnyRouteEntity,\n) => new RouteGroup<TRoutesCollection>(routes, indexRoute);\n","import { computed, makeObservable } from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\n\nimport { routeConfig } from '../config/index.js';\nimport type { RoutesCollection } from '../route-group/index.js';\n\nimport type {\n RouterConfiguration,\n RouterNavigateOptions,\n} from './router.types.js';\n\n/**\n * Class for centralized routing management.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Router.html)\n */\nexport class Router<TRoutesCollection extends RoutesCollection> {\n routes: TRoutesCollection;\n history: History;\n query: IQueryParams;\n\n constructor(config: RouterConfiguration<TRoutesCollection>) {\n this.routes = config.routes;\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n\n computed.struct(this, 'location');\n\n makeObservable(this);\n }\n\n get location() {\n return this.history.location;\n }\n\n navigate(url: string, options?: RouterNavigateOptions) {\n const query =\n (options?.mergeQuery ?? routeConfig.get().mergeQuery)\n ? { ...this.query.data, ...options?.query }\n : { ...options?.query };\n\n const searchString = buildSearchString(query);\n const navigationUrl = `${url}${searchString}`;\n\n if (options?.replace) {\n this.history.replace(navigationUrl, options?.state);\n } else {\n this.history.push(navigationUrl, options?.state);\n }\n }\n}\n\nexport const createRouter = <TRoutesCollection extends RoutesCollection>(\n config: RouterConfiguration<TRoutesCollection>,\n) => new Router(config);\n","import type { AnyRouteEntity } from '../route-group/index.js';\n\nexport const isRouteEntity = (route: any): route is AnyRouteEntity =>\n route && 'isOpened' in route;\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n runInAction,\n} from 'mobx';\nimport type { IQueryParams } from 'mobx-location-history';\nimport { callFunction } from 'yummies/common';\nimport type { AnyObject, EmptyObject, IsPartial, Maybe } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AbstractVirtualRoute,\n VirtualOpenExtraParams,\n VirtualRouteConfiguration,\n} from './virtual-route.types.js';\n\n/**\n * Class for creating routes with custom activation logic\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html)\n */\nexport class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject>\n implements AbstractVirtualRoute<TParams>\n{\n protected abortController: AbortController;\n query: IQueryParams;\n params: TParams | null;\n\n private isLocalOpened: boolean;\n\n private openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n constructor(protected config: VirtualRouteConfiguration<TParams> = {}) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.params = callFunction(config.initialParams, this) ?? null;\n this.openChecker = config.checkOpened;\n this.isLocalOpened = this.openChecker?.(this) ?? false;\n\n observable(this, 'params');\n observable.ref(this, 'isLocalOpened');\n observable.ref(this, '_isOpened');\n computed.struct(this, 'isOpened');\n action(this, 'setOpenChecker');\n action(this, 'open');\n action(this, 'close');\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isopened-boolean)\n */\n get isOpened() {\n const isOuterOpened = this.openChecker == null || this.openChecker(this);\n return this.isLocalOpened && isOuterOpened;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#setopenchecker-openchecker-void)\n */\n setOpenChecker(\n openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>,\n ) {\n this.openChecker = openChecker;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#open-params-extraparams-query-replace-promise-void)\n */\n open(\n ...args: IsPartial<TParams> extends true\n ? [params?: Maybe<TParams>, extraParams?: VirtualOpenExtraParams]\n : [params: TParams, extraParams?: VirtualOpenExtraParams]\n ): Promise<void>;\n async open(...args: any[]) {\n const params = (args[0] ?? {}) as unknown as TParams;\n const extraParams: Maybe<VirtualOpenExtraParams> = args[1];\n\n if (this.config.beforeOpen) {\n const beforeOpenResult = await this.config.beforeOpen(params, this);\n if (beforeOpenResult === false) {\n return;\n }\n }\n\n if (this.config.open == null) {\n runInAction(() => {\n this.isLocalOpened = true;\n });\n } else {\n const result = await this.config.open(params, this);\n // because result can return void so this is truthy for opening state\n runInAction(() => {\n this.isLocalOpened = result !== false;\n });\n }\n\n if (!this.isLocalOpened) {\n return;\n }\n\n if (extraParams?.query) {\n this.query.update(extraParams.query, extraParams.replace);\n }\n\n runInAction(() => {\n this.params = params;\n });\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.params!, this);\n }\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#close-void)\n */\n close() {\n if (this.config.close == null) {\n this.isLocalOpened = false;\n } else {\n const result = this.config.close(this);\n // because result can return void so this is truthy for opening state\n this.isLocalOpened = result !== false;\n }\n\n this.params = null;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.params!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createVirtualRoute = <\n TParams extends AnyObject | EmptyObject = EmptyObject,\n>(\n config?: VirtualRouteConfiguration<TParams>,\n) => new VirtualRoute<TParams>(config);\n"],"names":["createGlobalDynamicConfig","isObservableHistory","createBrowserHistory","QueryParams","LinkedAbortController","computed","observable","action","makeObservable","reaction","match","compile","buildSearchString","parse","runInAction","callFunction","onBecomeObserved","onBecomeUnobserved"],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -138,7 +138,7 @@ declare class RouteGroup<TRoutesCollection extends RoutesCollection> implements
|
|
|
138
138
|
}
|
|
139
139
|
declare const createRouteGroup: <TRoutesCollection extends RoutesCollection>(routes: TRoutesCollection, indexRoute?: AnyRouteEntity) => RouteGroup<TRoutesCollection>;
|
|
140
140
|
|
|
141
|
-
type
|
|
141
|
+
type NavigationTrx<TParams extends AnyObject = AnyObject> = {
|
|
142
142
|
state?: any;
|
|
143
143
|
/**
|
|
144
144
|
* path parameters
|
|
@@ -153,11 +153,7 @@ type PreparedNavigationData<TParams extends AnyObject = AnyObject> = {
|
|
|
153
153
|
/**
|
|
154
154
|
* Returning `false` means ignore navigation
|
|
155
155
|
*/
|
|
156
|
-
type BeforeOpenFeedback = void | boolean |
|
|
157
|
-
url: string;
|
|
158
|
-
state?: any;
|
|
159
|
-
replace?: boolean;
|
|
160
|
-
};
|
|
156
|
+
type BeforeOpenFeedback = void | boolean | Pick<NavigationTrx, 'url' | 'state' | 'replace'>;
|
|
161
157
|
interface UrlCreateParams<TInputParams> {
|
|
162
158
|
baseUrl?: string | undefined;
|
|
163
159
|
params: TInputParams;
|
|
@@ -175,6 +171,11 @@ interface RouteConfiguration<TPath extends string, TInputParams extends InputPat
|
|
|
175
171
|
abortSignal?: AbortSignal;
|
|
176
172
|
index?: boolean;
|
|
177
173
|
hash?: boolean;
|
|
174
|
+
/**
|
|
175
|
+
* Exact match for the path
|
|
176
|
+
* @default false
|
|
177
|
+
*/
|
|
178
|
+
exact?: boolean;
|
|
178
179
|
/**
|
|
179
180
|
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#meta)
|
|
180
181
|
*/
|
|
@@ -194,7 +195,7 @@ interface RouteConfiguration<TPath extends string, TInputParams extends InputPat
|
|
|
194
195
|
/**
|
|
195
196
|
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#beforeopen)
|
|
196
197
|
*/
|
|
197
|
-
beforeOpen?: (
|
|
198
|
+
beforeOpen?: (navigationTransaction: NavigationTrx<NoInfer<TInputParams>>) => MaybePromise<BeforeOpenFeedback>;
|
|
198
199
|
/**
|
|
199
200
|
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#afterclose)
|
|
200
201
|
*/
|
|
@@ -288,7 +289,8 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
|
|
|
288
289
|
private _tokenData;
|
|
289
290
|
private _matcher?;
|
|
290
291
|
private _compiler?;
|
|
291
|
-
private
|
|
292
|
+
private skipPathMatchCheck;
|
|
293
|
+
protected status: 'opening' | 'closed' | 'open-rejected' | 'open-confirmed' | 'unknown';
|
|
292
294
|
meta?: AnyObject;
|
|
293
295
|
/**
|
|
294
296
|
* Indicates if this route is an index route. Index routes activate when parent route path matches exactly.
|
|
@@ -318,6 +320,7 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
|
|
|
318
320
|
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params-parsedpathparams-null)
|
|
319
321
|
*/
|
|
320
322
|
get params(): TOutputParams | null;
|
|
323
|
+
protected get isPathMatched(): boolean;
|
|
321
324
|
/**
|
|
322
325
|
* Defines the "open" state for this route.
|
|
323
326
|
*
|
|
@@ -366,11 +369,11 @@ declare class Route<TPath extends string, TInputParams extends InputPathParams<T
|
|
|
366
369
|
]): Promise<void>;
|
|
367
370
|
open(url: string, navigateParams?: RouteNavigateParams): Promise<void>;
|
|
368
371
|
open(url: string, replace?: RouteNavigateParams['replace'], query?: RouteNavigateParams['query']): Promise<void>;
|
|
369
|
-
protected beforeOpen(openData: PreparedNavigationData<TInputParams>): MaybePromise<BeforeOpenFeedback>;
|
|
370
|
-
protected afterClose(): true | void;
|
|
371
372
|
protected get tokenData(): TokenData;
|
|
372
|
-
|
|
373
|
-
|
|
373
|
+
protected confirmOpening(trx: NavigationTrx<TInputParams>): Promise<boolean | (NavigationTrx<TInputParams> & Pick<NavigationTrx<AnyObject>, "url" | "state" | "replace">)>;
|
|
374
|
+
protected confirmClosing(): boolean;
|
|
375
|
+
private firstPathMatchingRun;
|
|
376
|
+
private checkPathMatch;
|
|
374
377
|
private get isAbleToMergeQuery();
|
|
375
378
|
destroy(): void;
|
|
376
379
|
}
|
|
@@ -418,4 +421,4 @@ declare const createRouter: <TRoutesCollection extends RoutesCollection>(config:
|
|
|
418
421
|
declare const isRouteEntity: (route: any) => route is AnyRouteEntity;
|
|
419
422
|
|
|
420
423
|
export { Route, RouteGroup, Router, VirtualRoute, createRoute, createRouteGroup, createRouter, createVirtualRoute, isRouteEntity, routeConfig };
|
|
421
|
-
export type { AbstractRouteGroup, AbstractVirtualRoute, AnyAbstractRoute, AnyAbstractRouteEntity, AnyRoute, AnyRouteEntity, AnyRouteGroup, AnyRouter, AnyVirtualRoute, BeforeOpenFeedback, CreatedUrlOutputParams, IRoute, InferInputParams, InferParams, InferPath, InputPathParam, InputPathParams, ParsedPathData, ParsedPathParam, ParsedPathParams, PathToObject,
|
|
424
|
+
export type { AbstractRouteGroup, AbstractVirtualRoute, AnyAbstractRoute, AnyAbstractRouteEntity, AnyRoute, AnyRouteEntity, AnyRouteGroup, AnyRouter, AnyVirtualRoute, BeforeOpenFeedback, CreatedUrlOutputParams, IRoute, InferInputParams, InferParams, InferPath, InputPathParam, InputPathParams, NavigationTrx, ParsedPathData, ParsedPathParam, ParsedPathParams, PathToObject, RouteConfiguration, RouteGlobalConfig, RouteNavigateParams, RouteParams, RouterConfiguration, RouterNavigateOptions, RoutesArrayCollection, RoutesCollection, RoutesObjectCollection, UrlCreateParams, UrlCreateParamsFn, VirtualOpenExtraParams, VirtualRouteConfiguration };
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createBrowserHistory, QueryParams, isObservableHistory, buildSearchStri
|
|
|
2
2
|
export * from "mobx-location-history";
|
|
3
3
|
import { createGlobalDynamicConfig } from "yummies/complex";
|
|
4
4
|
import { LinkedAbortController } from "linked-abort-controller";
|
|
5
|
-
import { computed, observable, action, makeObservable,
|
|
5
|
+
import { computed, observable, action, makeObservable, reaction, runInAction, onBecomeObserved, onBecomeUnobserved } from "mobx";
|
|
6
6
|
import { match, compile, parse } from "path-to-regexp";
|
|
7
7
|
import { callFunction } from "yummies/common";
|
|
8
8
|
let localHistory;
|
|
@@ -33,7 +33,8 @@ const routeConfig = createGlobalDynamicConfig(
|
|
|
33
33
|
location,
|
|
34
34
|
queryParams
|
|
35
35
|
};
|
|
36
|
-
}
|
|
36
|
+
},
|
|
37
|
+
Symbol.for("MOBX_ROUTE_CONFIG")
|
|
37
38
|
);
|
|
38
39
|
class Route {
|
|
39
40
|
constructor(path, config = {}) {
|
|
@@ -45,35 +46,27 @@ class Route {
|
|
|
45
46
|
this.isIndex = !!this.config.index;
|
|
46
47
|
this.isHash = !!this.config.hash;
|
|
47
48
|
this.meta = this.config.meta;
|
|
49
|
+
this.status = "unknown";
|
|
48
50
|
this.parent = config.parent ?? null;
|
|
49
|
-
computed
|
|
51
|
+
computed(this, "isPathMatched");
|
|
52
|
+
computed(this, "isOpened");
|
|
50
53
|
computed.struct(this, "data");
|
|
51
54
|
computed.struct(this, "params");
|
|
52
|
-
computed
|
|
53
|
-
computed
|
|
54
|
-
computed
|
|
55
|
+
computed(this, "currentPath");
|
|
56
|
+
computed(this, "hasOpenedChildren");
|
|
57
|
+
computed(this, "isAbleToMergeQuery");
|
|
55
58
|
computed(this, "baseUrl");
|
|
56
59
|
observable(this, "children");
|
|
57
60
|
observable.ref(this, "parent");
|
|
61
|
+
observable.ref(this, "status");
|
|
58
62
|
action(this, "addChildren");
|
|
63
|
+
action(this, "confirmOpening");
|
|
64
|
+
action(this, "confirmClosing");
|
|
59
65
|
action(this, "removeChildren");
|
|
60
66
|
makeObservable(this);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
this.reactionDisposer = reaction(
|
|
66
|
-
() => this.isOpened,
|
|
67
|
-
this.processOpenedState,
|
|
68
|
-
{
|
|
69
|
-
signal: this.abortController.signal,
|
|
70
|
-
fireImmediately: true
|
|
71
|
-
}
|
|
72
|
-
);
|
|
73
|
-
});
|
|
74
|
-
onBecomeUnobserved(this, "isOpened", () => {
|
|
75
|
-
this.reactionDisposer?.();
|
|
76
|
-
this.reactionDisposer = void 0;
|
|
67
|
+
reaction(() => this.isPathMatched, this.checkPathMatch, {
|
|
68
|
+
signal: this.abortController.signal,
|
|
69
|
+
fireImmediately: true
|
|
77
70
|
});
|
|
78
71
|
}
|
|
79
72
|
abortController;
|
|
@@ -83,7 +76,8 @@ class Route {
|
|
|
83
76
|
_tokenData;
|
|
84
77
|
_matcher;
|
|
85
78
|
_compiler;
|
|
86
|
-
|
|
79
|
+
skipPathMatchCheck = false;
|
|
80
|
+
status;
|
|
87
81
|
meta;
|
|
88
82
|
/**
|
|
89
83
|
* Indicates if this route is an index route. Index routes activate when parent route path matches exactly.
|
|
@@ -119,7 +113,7 @@ class Route {
|
|
|
119
113
|
return { params: {}, path: pathnameToCheck };
|
|
120
114
|
}
|
|
121
115
|
this._matcher ??= match(this.tokenData, {
|
|
122
|
-
end: false,
|
|
116
|
+
end: this.config.exact ?? false,
|
|
123
117
|
...this.config.matchOptions
|
|
124
118
|
});
|
|
125
119
|
const parsed = this._matcher(pathnameToCheck);
|
|
@@ -159,13 +153,16 @@ class Route {
|
|
|
159
153
|
}
|
|
160
154
|
return params;
|
|
161
155
|
}
|
|
156
|
+
get isPathMatched() {
|
|
157
|
+
return this.parsedPathData !== null;
|
|
158
|
+
}
|
|
162
159
|
/**
|
|
163
160
|
* Defines the "open" state for this route.
|
|
164
161
|
*
|
|
165
162
|
* [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)
|
|
166
163
|
*/
|
|
167
164
|
get isOpened() {
|
|
168
|
-
if (this.params === null || this.
|
|
165
|
+
if (!this.isPathMatched || this.params === null || this.status !== "open-confirmed") {
|
|
169
166
|
return false;
|
|
170
167
|
}
|
|
171
168
|
return !this.config.checkOpened || this.config.checkOpened(this.parsedPathData);
|
|
@@ -222,9 +219,7 @@ class Route {
|
|
|
222
219
|
};
|
|
223
220
|
const urlCreateParams = this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ?? routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ?? defaultUrlCreateParams;
|
|
224
221
|
const path = this._compiler(this.processParams(urlCreateParams.params));
|
|
225
|
-
const url =
|
|
226
|
-
""
|
|
227
|
-
);
|
|
222
|
+
const url = `${urlCreateParams.baseUrl || ""}${this.isHash ? "#" : ""}${path}`;
|
|
228
223
|
if (outputParams?.omitQuery) {
|
|
229
224
|
return url;
|
|
230
225
|
}
|
|
@@ -253,59 +248,93 @@ class Route {
|
|
|
253
248
|
url = this.createUrl(args[0], query);
|
|
254
249
|
}
|
|
255
250
|
const state = rawState ?? null;
|
|
256
|
-
const
|
|
251
|
+
const trx = {
|
|
257
252
|
url,
|
|
258
253
|
params,
|
|
259
254
|
replace,
|
|
260
255
|
state,
|
|
261
256
|
query
|
|
262
257
|
};
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
258
|
+
const isConfirmed = await this.confirmOpening(trx);
|
|
259
|
+
if (!isConfirmed) {
|
|
265
260
|
return;
|
|
266
261
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (replace) {
|
|
271
|
-
this.history.replace(url, state);
|
|
262
|
+
this.skipPathMatchCheck = true;
|
|
263
|
+
if (trx.replace) {
|
|
264
|
+
this.history.replace(trx.url, trx.state);
|
|
272
265
|
} else {
|
|
273
|
-
this.history.push(url, state);
|
|
266
|
+
this.history.push(trx.url, trx.state);
|
|
274
267
|
}
|
|
275
|
-
|
|
276
|
-
|
|
268
|
+
}
|
|
269
|
+
get tokenData() {
|
|
270
|
+
if (!this._tokenData) {
|
|
271
|
+
this._tokenData = parse(this.path, this.config.parseOptions);
|
|
277
272
|
}
|
|
273
|
+
return this._tokenData;
|
|
278
274
|
}
|
|
279
|
-
|
|
275
|
+
async confirmOpening(trx) {
|
|
276
|
+
this.status = "opening";
|
|
280
277
|
if (this.config.beforeOpen) {
|
|
281
|
-
|
|
278
|
+
const feedback = await this.config.beforeOpen(trx);
|
|
279
|
+
if (feedback === false) {
|
|
280
|
+
runInAction(() => {
|
|
281
|
+
this.status = "open-rejected";
|
|
282
|
+
});
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
if (typeof feedback === "object") {
|
|
286
|
+
return Object.assign(trx, feedback);
|
|
287
|
+
}
|
|
282
288
|
}
|
|
289
|
+
runInAction(() => {
|
|
290
|
+
this.status = "open-confirmed";
|
|
291
|
+
});
|
|
283
292
|
return true;
|
|
284
293
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return this.config.afterClose();
|
|
288
|
-
}
|
|
294
|
+
confirmClosing() {
|
|
295
|
+
this.status = "closed";
|
|
289
296
|
return true;
|
|
290
297
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
firstOpenedStateCheck = true;
|
|
298
|
-
processOpenedState = (isOpened) => {
|
|
299
|
-
if (this.firstOpenedStateCheck) {
|
|
300
|
-
this.firstOpenedStateCheck = false;
|
|
301
|
-
if (!isOpened) {
|
|
298
|
+
firstPathMatchingRun = true;
|
|
299
|
+
checkPathMatch = async (isPathMathched) => {
|
|
300
|
+
if (this.firstPathMatchingRun) {
|
|
301
|
+
this.firstPathMatchingRun = false;
|
|
302
|
+
if (!isPathMathched) {
|
|
302
303
|
return;
|
|
303
304
|
}
|
|
304
305
|
}
|
|
305
|
-
if (
|
|
306
|
+
if (this.skipPathMatchCheck) {
|
|
307
|
+
this.skipPathMatchCheck = false;
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (isPathMathched) {
|
|
311
|
+
const trx = {
|
|
312
|
+
url: this.parsedPathData.path,
|
|
313
|
+
params: this.parsedPathData.params,
|
|
314
|
+
state: this.history.location.state,
|
|
315
|
+
query: this.query.data
|
|
316
|
+
};
|
|
317
|
+
const nextTrxOrConfirmed = await this.confirmOpening(trx);
|
|
318
|
+
if (!nextTrxOrConfirmed) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
306
321
|
this.config.afterOpen?.(this.parsedPathData, this);
|
|
322
|
+
if (typeof nextTrxOrConfirmed === "object") {
|
|
323
|
+
if (nextTrxOrConfirmed.replace) {
|
|
324
|
+
this.history.replace(
|
|
325
|
+
nextTrxOrConfirmed.url,
|
|
326
|
+
nextTrxOrConfirmed.state
|
|
327
|
+
);
|
|
328
|
+
} else {
|
|
329
|
+
this.history.push(nextTrxOrConfirmed.url, nextTrxOrConfirmed.state);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
307
333
|
} else {
|
|
308
|
-
this.
|
|
334
|
+
const isConfirmed = this.confirmClosing();
|
|
335
|
+
if (isConfirmed) {
|
|
336
|
+
this.config.afterClose?.();
|
|
337
|
+
}
|
|
309
338
|
}
|
|
310
339
|
};
|
|
311
340
|
get isAbleToMergeQuery() {
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/core/config/config.ts","../src/core/route/route.ts","../src/core/route-group/route-group.ts","../src/core/router/router.ts","../src/core/utils/is-route-entity.ts","../src/core/virtual-route/virtual-route.ts"],"sourcesContent":["import {\n createBrowserHistory,\n type History,\n type IQueryParams,\n isObservableHistory,\n QueryParams,\n} from 'mobx-location-history';\nimport { createGlobalDynamicConfig } from 'yummies/complex';\n\nimport type { RouteGlobalConfig } from './config.types.js';\n\nlet localHistory: History | undefined;\n\nexport const routeConfig = createGlobalDynamicConfig<RouteGlobalConfig>(\n (update) => {\n if (localHistory && update?.history && isObservableHistory(localHistory)) {\n localHistory.destroy();\n }\n\n let history: History;\n\n if (update?.history) {\n history = update.history;\n } else {\n history = localHistory = createBrowserHistory();\n }\n\n let queryParams: IQueryParams;\n\n if (update?.history && !update.queryParams) {\n queryParams = new QueryParams({ history });\n } else {\n if (update?.queryParams) {\n queryParams = update.queryParams;\n } else {\n queryParams = new QueryParams({ history });\n }\n }\n\n return {\n ...update,\n history,\n location,\n queryParams,\n };\n },\n);\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n} from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\nimport {\n compile,\n match,\n type ParamData,\n parse,\n type TokenData,\n} from 'path-to-regexp';\nimport type { AnyObject, IsPartial, Maybe, MaybePromise } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AnyRoute,\n BeforeOpenFeedback,\n CreatedUrlOutputParams,\n InputPathParams,\n IRoute,\n ParsedPathData,\n ParsedPathParams,\n PreparedNavigationData,\n RouteConfiguration,\n RouteNavigateParams,\n UrlCreateParams,\n} from './route.types.js';\n\n/**\n * Class for creating path based route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html)\n */\nexport class Route<\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n> implements IRoute<TPath, TInputParams, TOutputParams>\n{\n protected abortController: AbortController;\n protected history: History;\n parent: TParentRoute;\n\n query: IQueryParams;\n\n private _tokenData: TokenData | undefined;\n private _matcher?: ReturnType<typeof match>;\n private _compiler?: ReturnType<typeof compile>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n meta?: AnyObject;\n\n /**\n * Indicates if this route is an index route. Index routes activate when parent route path matches exactly.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isindex-boolean)\n */\n isIndex: boolean;\n\n /**\n * Indicates if this route is an hash route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ishash-boolean)\n */\n isHash: boolean;\n\n children: AnyRoute[] = [];\n\n constructor(\n public path: TPath,\n protected config: RouteConfiguration<\n TPath,\n TInputParams,\n TOutputParams,\n TParentRoute\n > = {},\n ) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.isIndex = !!this.config.index;\n this.isHash = !!this.config.hash;\n this.meta = this.config.meta;\n this.parent = config.parent ?? (null as unknown as TParentRoute);\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'data');\n computed.struct(this, 'params');\n computed.struct(this, 'currentPath');\n computed.struct(this, 'hasOpenedChildren');\n computed.struct(this, 'isAbleToMergeQuery');\n computed(this, 'baseUrl');\n\n observable(this, 'children');\n observable.ref(this, 'parent');\n action(this, 'addChildren');\n action(this, 'removeChildren');\n\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n protected get baseUrl() {\n const baseUrl = this.config.baseUrl ?? routeConfig.get().baseUrl;\n return baseUrl?.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n }\n\n protected get parsedPathData(): ParsedPathData<TPath> | null {\n let pathnameToCheck: string;\n\n if (this.isHash) {\n pathnameToCheck = this.history.location.hash.slice(1);\n } else {\n pathnameToCheck = this.history.location.pathname;\n }\n\n if (this.baseUrl) {\n if (!this.history.location.pathname.startsWith(this.baseUrl)) {\n return null;\n }\n\n pathnameToCheck = pathnameToCheck.replace(this.baseUrl, '');\n }\n\n if (\n (this.path === '' || this.path === '/') &&\n (pathnameToCheck === '/' || pathnameToCheck === '')\n ) {\n return { params: {} as any, path: pathnameToCheck };\n }\n\n this._matcher ??= match(this.tokenData, {\n end: false,\n ...this.config.matchOptions,\n });\n const parsed = this._matcher(pathnameToCheck);\n\n if (parsed === false) {\n return null;\n }\n\n return parsed as ParsedPathData<TPath>;\n }\n\n /**\n * Matched path segment for current URL.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#currentpath-parsedpathname-null)\n */\n get currentPath(): string | null {\n return this.parsedPathData?.path ?? null;\n }\n\n /**\n * Current parsed path parameters.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params-parsedpathparams-null)\n */\n get params(): TOutputParams | null {\n if (!this.parsedPathData?.params) {\n return null;\n }\n\n let params: TOutputParams | null =\n (this.parsedPathData?.params as unknown as Maybe<TOutputParams>) ?? null;\n\n if (this.config.params) {\n const result = this.config.params(\n this.parsedPathData.params,\n this.config.meta,\n );\n if (result) {\n params = result;\n } else {\n return null;\n }\n }\n\n return params;\n }\n\n /**\n * Defines the \"open\" state for this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)\n */\n get isOpened() {\n if (this.params === null || this.parsedPathData === null) {\n return false;\n }\n\n return (\n !this.config.checkOpened || this.config.checkOpened(this.parsedPathData)\n );\n }\n\n /**\n * Allows to create child route based on this route with merging this route path and extending path.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend-path-config-route)\n */\n extend<\n TExtendedPath extends string,\n TExtendedInputParams extends\n InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>,\n TExtendedOutputParams extends AnyObject = TInputParams &\n ParsedPathParams<`${TPath}${TExtendedPath}`>,\n >(\n path: TExtendedPath,\n config?: Omit<\n RouteConfiguration<\n `${TPath}${TExtendedPath}`,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n any\n >,\n 'parent'\n >,\n ) {\n type ExtendedRoutePath = `${TPath}${TExtendedPath}`;\n type ParentRoute = this;\n // biome-ignore lint/correctness/noUnusedVariables: this is need to extract unused fields\n const { index, params, ...configFromCurrentRoute } = this.config;\n\n const extendedChild = new Route<\n ExtendedRoutePath,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n ParentRoute\n >(`${this.path}${path}`, {\n ...configFromCurrentRoute,\n ...config,\n parent: this,\n } as any);\n\n this.addChildren(extendedChild as any);\n\n return extendedChild;\n }\n\n addChildren(...routes: AnyRoute[]) {\n this.children.push(...routes);\n }\n\n removeChildren(...routes: AnyRoute[]) {\n this.children = this.children.filter((child) => !routes.includes(child));\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#hasopenedchildren-boolean)\n */\n get hasOpenedChildren(): boolean {\n return this.children.some(\n (child) => child.isOpened || child.hasOpenedChildren,\n );\n }\n\n protected processParams(\n params?: TInputParams | null | undefined,\n ): ParamData | undefined {\n if (params == null) return undefined;\n\n return Object.entries(params).reduce((acc, [key, value]) => {\n if (value != null) {\n acc[key] = Array.isArray(value) ? value.map(String) : String(value);\n }\n return acc;\n }, {} as ParamData);\n }\n\n createUrl(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: Maybe<TInputParams>,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n : [\n params: TInputParams,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n ) {\n const params = args[0];\n const rawQuery = args[1];\n const mergeQueryOrOutputParams = args[2] ?? this.isAbleToMergeQuery;\n const outputParams: Maybe<CreatedUrlOutputParams> =\n typeof mergeQueryOrOutputParams === 'boolean'\n ? { mergeQuery: mergeQueryOrOutputParams }\n : mergeQueryOrOutputParams;\n\n const query = outputParams?.mergeQuery\n ? { ...this.query.data, ...rawQuery }\n : (rawQuery ?? {});\n\n this._compiler ??= compile(this.tokenData);\n\n const defaultUrlCreateParams: UrlCreateParams<TInputParams> = {\n baseUrl: this.baseUrl,\n params: params as TInputParams,\n query,\n };\n const urlCreateParams: UrlCreateParams<TInputParams> =\n this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ??\n routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ??\n defaultUrlCreateParams;\n\n const path = this._compiler(this.processParams(urlCreateParams.params));\n\n const url = [urlCreateParams.baseUrl, this.isHash ? '#' : '', path].join(\n '',\n );\n\n if (outputParams?.omitQuery) {\n return url;\n }\n\n return `${url}${buildSearchString(urlCreateParams.query)}`;\n }\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n navigateParams?: RouteNavigateParams,\n ]\n : [params: TInputParams, navigateParams?: RouteNavigateParams]\n ): Promise<void>;\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n : [\n params: TInputParams,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n ): Promise<void>;\n open(url: string, navigateParams?: RouteNavigateParams): Promise<void>;\n open(\n url: string,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ): Promise<void>;\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n async open(...args: any[]) {\n const {\n replace,\n state: rawState,\n query: rawQuery,\n mergeQuery: rawMergeQuery,\n } = typeof args[1] === 'boolean' || args.length > 2\n ? ({ replace: args[1], query: args[2] } as RouteNavigateParams)\n : ((args[1] ?? {}) as RouteNavigateParams);\n let url: string;\n let params: Maybe<InputPathParams<TPath>>;\n\n const mergeQuery = rawMergeQuery ?? this.isAbleToMergeQuery;\n const query = mergeQuery ? { ...this.query.data, ...rawQuery } : rawQuery;\n\n if (typeof args[0] === 'string') {\n url = args[0];\n } else {\n params = args[0] as InputPathParams<TPath>;\n url = this.createUrl(args[0], query);\n }\n\n const state = rawState ?? null;\n\n const navigationData: PreparedNavigationData<TInputParams> = {\n url,\n params: params as TInputParams,\n replace,\n state,\n query,\n };\n\n const feedback = await this.beforeOpen(navigationData);\n\n if (feedback === false) {\n return;\n }\n\n if (typeof feedback === 'object') {\n Object.assign(navigationData, feedback);\n }\n\n if (replace) {\n this.history.replace(url, state);\n } else {\n this.history.push(url, state);\n }\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.parsedPathData!, this);\n }\n }\n\n protected beforeOpen(\n openData: PreparedNavigationData<TInputParams>,\n ): MaybePromise<BeforeOpenFeedback> {\n if (this.config.beforeOpen) {\n return this.config.beforeOpen(openData);\n }\n\n return true;\n }\n\n protected afterClose() {\n if (this.config.afterClose) {\n return this.config.afterClose();\n }\n\n return true;\n }\n\n protected get tokenData() {\n if (!this._tokenData) {\n this._tokenData = parse(this.path, this.config.parseOptions);\n }\n return this._tokenData;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.parsedPathData!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n private get isAbleToMergeQuery() {\n return this.config.mergeQuery ?? routeConfig.get().mergeQuery;\n }\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createRoute = <\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n>(\n path: TPath,\n config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute>,\n) => new Route<TPath, TInputParams, TOutputParams, TParentRoute>(path, config);\n","import { computed, makeObservable, observable } from 'mobx';\n\nimport type {\n AbstractRouteGroup,\n AnyRouteEntity,\n RoutesCollection,\n} from './route-group.types.js';\n\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Class for grouping related routes and managing their state.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html)\n */\nexport class RouteGroup<TRoutesCollection extends RoutesCollection>\n implements AbstractRouteGroup<TRoutesCollection>\n{\n routes: TRoutesCollection;\n\n constructor(\n routes: TRoutesCollection,\n private _indexRoute?: AnyRouteEntity,\n ) {\n this.routes = routes;\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'indexRoute');\n observable.shallow(this, 'routes');\n makeObservable(this);\n }\n\n /**\n * Returns true if at least one route in the group is open.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#isopened-boolean)\n */\n get isOpened(): boolean {\n const routes = Object.values(this.routes);\n return routes.some(\n (route) =>\n route.isOpened ||\n ('hasOpenedChildren' in route && route.hasOpenedChildren),\n );\n }\n\n /**\n * First found index route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#indexroute-route-undefined)\n */\n get indexRoute(): AnyRouteEntity | undefined {\n return (this._indexRoute ??\n Object.values(this.routes).find(\n (route) => 'isIndex' in route && route.isIndex,\n )) as unknown as AnyRouteEntity;\n }\n\n /**\n * Main navigation method for the group.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#open-args-any-void)\n */\n open(...args: any[]) {\n let lastGroupRoute: RouteGroup<any> | undefined;\n\n if (this.indexRoute && 'open' in this.indexRoute) {\n this.indexRoute.open(...args);\n return;\n }\n\n for (const routeName in this.routes) {\n const route = this.routes[routeName];\n if (route instanceof RouteGroup) {\n lastGroupRoute = route;\n }\n }\n\n if (lastGroupRoute) {\n lastGroupRoute.open(...args);\n } else if (process.env.NODE_ENV !== 'production') {\n console.warn(\n \"RouteGroup doesn't have index route. open() method doesn't work.\",\n );\n }\n }\n}\n\nexport const createRouteGroup = <TRoutesCollection extends RoutesCollection>(\n routes: TRoutesCollection,\n indexRoute?: AnyRouteEntity,\n) => new RouteGroup<TRoutesCollection>(routes, indexRoute);\n","import { computed, makeObservable } from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\n\nimport { routeConfig } from '../config/index.js';\nimport type { RoutesCollection } from '../route-group/index.js';\n\nimport type {\n RouterConfiguration,\n RouterNavigateOptions,\n} from './router.types.js';\n\n/**\n * Class for centralized routing management.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Router.html)\n */\nexport class Router<TRoutesCollection extends RoutesCollection> {\n routes: TRoutesCollection;\n history: History;\n query: IQueryParams;\n\n constructor(config: RouterConfiguration<TRoutesCollection>) {\n this.routes = config.routes;\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n\n computed.struct(this, 'location');\n\n makeObservable(this);\n }\n\n get location() {\n return this.history.location;\n }\n\n navigate(url: string, options?: RouterNavigateOptions) {\n const query =\n (options?.mergeQuery ?? routeConfig.get().mergeQuery)\n ? { ...this.query.data, ...options?.query }\n : { ...options?.query };\n\n const searchString = buildSearchString(query);\n const navigationUrl = `${url}${searchString}`;\n\n if (options?.replace) {\n this.history.replace(navigationUrl, options?.state);\n } else {\n this.history.push(navigationUrl, options?.state);\n }\n }\n}\n\nexport const createRouter = <TRoutesCollection extends RoutesCollection>(\n config: RouterConfiguration<TRoutesCollection>,\n) => new Router(config);\n","import type { AnyRouteEntity } from '../route-group/index.js';\n\nexport const isRouteEntity = (route: any): route is AnyRouteEntity =>\n route && 'isOpened' in route;\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n runInAction,\n} from 'mobx';\nimport type { IQueryParams } from 'mobx-location-history';\nimport { callFunction } from 'yummies/common';\nimport type { AnyObject, EmptyObject, IsPartial, Maybe } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AbstractVirtualRoute,\n VirtualOpenExtraParams,\n VirtualRouteConfiguration,\n} from './virtual-route.types.js';\n\n/**\n * Class for creating routes with custom activation logic\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html)\n */\nexport class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject>\n implements AbstractVirtualRoute<TParams>\n{\n protected abortController: AbortController;\n query: IQueryParams;\n params: TParams | null;\n\n private isLocalOpened: boolean;\n\n private openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n constructor(protected config: VirtualRouteConfiguration<TParams> = {}) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.params = callFunction(config.initialParams, this) ?? null;\n this.openChecker = config.checkOpened;\n this.isLocalOpened = this.openChecker?.(this) ?? false;\n\n observable(this, 'params');\n observable.ref(this, 'isLocalOpened');\n observable.ref(this, '_isOpened');\n computed.struct(this, 'isOpened');\n action(this, 'setOpenChecker');\n action(this, 'open');\n action(this, 'close');\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isopened-boolean)\n */\n get isOpened() {\n const isOuterOpened = this.openChecker == null || this.openChecker(this);\n return this.isLocalOpened && isOuterOpened;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#setopenchecker-openchecker-void)\n */\n setOpenChecker(\n openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>,\n ) {\n this.openChecker = openChecker;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#open-params-extraparams-query-replace-promise-void)\n */\n open(\n ...args: IsPartial<TParams> extends true\n ? [params?: Maybe<TParams>, extraParams?: VirtualOpenExtraParams]\n : [params: TParams, extraParams?: VirtualOpenExtraParams]\n ): Promise<void>;\n async open(...args: any[]) {\n const params = (args[0] ?? {}) as unknown as TParams;\n const extraParams: Maybe<VirtualOpenExtraParams> = args[1];\n\n if (this.config.beforeOpen) {\n const beforeOpenResult = await this.config.beforeOpen(params, this);\n if (beforeOpenResult === false) {\n return;\n }\n }\n\n if (this.config.open == null) {\n runInAction(() => {\n this.isLocalOpened = true;\n });\n } else {\n const result = await this.config.open(params, this);\n // because result can return void so this is truthy for opening state\n runInAction(() => {\n this.isLocalOpened = result !== false;\n });\n }\n\n if (!this.isLocalOpened) {\n return;\n }\n\n if (extraParams?.query) {\n this.query.update(extraParams.query, extraParams.replace);\n }\n\n runInAction(() => {\n this.params = params;\n });\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.params!, this);\n }\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#close-void)\n */\n close() {\n if (this.config.close == null) {\n this.isLocalOpened = false;\n } else {\n const result = this.config.close(this);\n // because result can return void so this is truthy for opening state\n this.isLocalOpened = result !== false;\n }\n\n this.params = null;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.params!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createVirtualRoute = <\n TParams extends AnyObject | EmptyObject = EmptyObject,\n>(\n config?: VirtualRouteConfiguration<TParams>,\n) => new VirtualRoute<TParams>(config);\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/core/config/config.ts","../src/core/route/route.ts","../src/core/route-group/route-group.ts","../src/core/router/router.ts","../src/core/utils/is-route-entity.ts","../src/core/virtual-route/virtual-route.ts"],"sourcesContent":["import {\n createBrowserHistory,\n type History,\n type IQueryParams,\n isObservableHistory,\n QueryParams,\n} from 'mobx-location-history';\nimport { createGlobalDynamicConfig } from 'yummies/complex';\n\nimport type { RouteGlobalConfig } from './config.types.js';\n\nlet localHistory: History | undefined;\n\nexport const routeConfig = createGlobalDynamicConfig<RouteGlobalConfig>(\n (update) => {\n if (localHistory && update?.history && isObservableHistory(localHistory)) {\n localHistory.destroy();\n }\n\n let history: History;\n\n if (update?.history) {\n history = update.history;\n } else {\n history = localHistory = createBrowserHistory();\n }\n\n let queryParams: IQueryParams;\n\n if (update?.history && !update.queryParams) {\n queryParams = new QueryParams({ history });\n } else {\n if (update?.queryParams) {\n queryParams = update.queryParams;\n } else {\n queryParams = new QueryParams({ history });\n }\n }\n\n return {\n ...update,\n history,\n location,\n queryParams,\n };\n },\n Symbol.for('MOBX_ROUTE_CONFIG'),\n);\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n reaction,\n runInAction,\n} from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\nimport {\n compile,\n match,\n type ParamData,\n parse,\n type TokenData,\n} from 'path-to-regexp';\nimport type { AnyObject, IsPartial, Maybe } from 'yummies/types';\nimport { routeConfig } from '../config/index.js';\nimport type {\n AnyRoute,\n CreatedUrlOutputParams,\n InputPathParams,\n IRoute,\n NavigationTrx,\n ParsedPathData,\n ParsedPathParams,\n RouteConfiguration,\n RouteNavigateParams,\n UrlCreateParams,\n} from './route.types.js';\n\n/**\n * Class for creating path based route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html)\n */\nexport class Route<\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n> implements IRoute<TPath, TInputParams, TOutputParams>\n{\n protected abortController: AbortController;\n protected history: History;\n parent: TParentRoute;\n\n query: IQueryParams;\n\n private _tokenData: TokenData | undefined;\n private _matcher?: ReturnType<typeof match>;\n private _compiler?: ReturnType<typeof compile>;\n private skipPathMatchCheck = false;\n\n protected status:\n | 'opening'\n | 'closed'\n | 'open-rejected'\n | 'open-confirmed'\n | 'unknown';\n\n meta?: AnyObject;\n\n /**\n * Indicates if this route is an index route. Index routes activate when parent route path matches exactly.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isindex-boolean)\n */\n isIndex: boolean;\n\n /**\n * Indicates if this route is an hash route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#ishash-boolean)\n */\n isHash: boolean;\n\n children: AnyRoute[] = [];\n\n constructor(\n public path: TPath,\n protected config: RouteConfiguration<\n TPath,\n TInputParams,\n TOutputParams,\n TParentRoute\n > = {},\n ) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.isIndex = !!this.config.index;\n this.isHash = !!this.config.hash;\n this.meta = this.config.meta;\n this.status = 'unknown';\n this.parent = config.parent ?? (null as unknown as TParentRoute);\n\n computed(this, 'isPathMatched');\n computed(this, 'isOpened');\n computed.struct(this, 'data');\n computed.struct(this, 'params');\n computed(this, 'currentPath');\n computed(this, 'hasOpenedChildren');\n computed(this, 'isAbleToMergeQuery');\n computed(this, 'baseUrl');\n\n observable(this, 'children');\n observable.ref(this, 'parent');\n observable.ref(this, 'status');\n action(this, 'addChildren');\n action(this, 'confirmOpening');\n action(this, 'confirmClosing');\n action(this, 'removeChildren');\n\n makeObservable(this);\n\n reaction(() => this.isPathMatched, this.checkPathMatch, {\n signal: this.abortController.signal,\n fireImmediately: true,\n });\n }\n\n protected get baseUrl() {\n const baseUrl = this.config.baseUrl ?? routeConfig.get().baseUrl;\n return baseUrl?.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n }\n\n protected get parsedPathData(): ParsedPathData<TPath> | null {\n let pathnameToCheck: string;\n\n if (this.isHash) {\n pathnameToCheck = this.history.location.hash.slice(1);\n } else {\n pathnameToCheck = this.history.location.pathname;\n }\n\n if (this.baseUrl) {\n if (!this.history.location.pathname.startsWith(this.baseUrl)) {\n return null;\n }\n\n pathnameToCheck = pathnameToCheck.replace(this.baseUrl, '');\n }\n\n if (\n (this.path === '' || this.path === '/') &&\n (pathnameToCheck === '/' || pathnameToCheck === '')\n ) {\n return { params: {} as any, path: pathnameToCheck };\n }\n\n this._matcher ??= match(this.tokenData, {\n end: this.config.exact ?? false,\n ...this.config.matchOptions,\n });\n const parsed = this._matcher(pathnameToCheck);\n\n if (parsed === false) {\n return null;\n }\n\n return parsed as ParsedPathData<TPath>;\n }\n\n /**\n * Matched path segment for current URL.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#currentpath-parsedpathname-null)\n */\n get currentPath(): string | null {\n return this.parsedPathData?.path ?? null;\n }\n\n /**\n * Current parsed path parameters.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#params-parsedpathparams-null)\n */\n get params(): TOutputParams | null {\n if (!this.parsedPathData?.params) {\n return null;\n }\n\n let params: TOutputParams | null =\n (this.parsedPathData?.params as unknown as Maybe<TOutputParams>) ?? null;\n\n if (this.config.params) {\n const result = this.config.params(\n this.parsedPathData.params,\n this.config.meta,\n );\n if (result) {\n params = result;\n } else {\n return null;\n }\n }\n\n return params;\n }\n\n protected get isPathMatched() {\n return this.parsedPathData !== null;\n }\n\n /**\n * Defines the \"open\" state for this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#isopened-boolean)\n */\n get isOpened() {\n if (\n !this.isPathMatched ||\n this.params === null ||\n this.status !== 'open-confirmed'\n ) {\n return false;\n }\n\n return (\n !this.config.checkOpened || this.config.checkOpened(this.parsedPathData!)\n );\n }\n\n /**\n * Allows to create child route based on this route with merging this route path and extending path.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#extend-path-config-route)\n */\n extend<\n TExtendedPath extends string,\n TExtendedInputParams extends\n InputPathParams<`${TPath}${TExtendedPath}`> = InputPathParams<`${TPath}${TExtendedPath}`>,\n TExtendedOutputParams extends AnyObject = TInputParams &\n ParsedPathParams<`${TPath}${TExtendedPath}`>,\n >(\n path: TExtendedPath,\n config?: Omit<\n RouteConfiguration<\n `${TPath}${TExtendedPath}`,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n any\n >,\n 'parent'\n >,\n ) {\n type ExtendedRoutePath = `${TPath}${TExtendedPath}`;\n type ParentRoute = this;\n // biome-ignore lint/correctness/noUnusedVariables: this is need to extract unused fields\n const { index, params, ...configFromCurrentRoute } = this.config;\n\n const extendedChild = new Route<\n ExtendedRoutePath,\n TInputParams & TExtendedInputParams,\n TExtendedOutputParams,\n ParentRoute\n >(`${this.path}${path}`, {\n ...configFromCurrentRoute,\n ...config,\n parent: this,\n } as any);\n\n this.addChildren(extendedChild as any);\n\n return extendedChild;\n }\n\n addChildren(...routes: AnyRoute[]) {\n this.children.push(...routes);\n }\n\n removeChildren(...routes: AnyRoute[]) {\n this.children = this.children.filter((child) => !routes.includes(child));\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#hasopenedchildren-boolean)\n */\n get hasOpenedChildren(): boolean {\n return this.children.some(\n (child) => child.isOpened || child.hasOpenedChildren,\n );\n }\n\n protected processParams(\n params?: TInputParams | null | undefined,\n ): ParamData | undefined {\n if (params == null) return undefined;\n\n return Object.entries(params).reduce((acc, [key, value]) => {\n if (value != null) {\n acc[key] = Array.isArray(value) ? value.map(String) : String(value);\n }\n return acc;\n }, {} as ParamData);\n }\n\n createUrl(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: Maybe<TInputParams>,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n : [\n params: TInputParams,\n query?: Maybe<AnyObject>,\n mergeQueryOrParams?: boolean | CreatedUrlOutputParams,\n ]\n ) {\n const params = args[0];\n const rawQuery = args[1];\n const mergeQueryOrOutputParams = args[2] ?? this.isAbleToMergeQuery;\n const outputParams: Maybe<CreatedUrlOutputParams> =\n typeof mergeQueryOrOutputParams === 'boolean'\n ? { mergeQuery: mergeQueryOrOutputParams }\n : mergeQueryOrOutputParams;\n\n const query = outputParams?.mergeQuery\n ? { ...this.query.data, ...rawQuery }\n : (rawQuery ?? {});\n\n this._compiler ??= compile(this.tokenData);\n\n const defaultUrlCreateParams: UrlCreateParams<TInputParams> = {\n baseUrl: this.baseUrl,\n params: params as TInputParams,\n query,\n };\n const urlCreateParams: UrlCreateParams<TInputParams> =\n this.config.createUrl?.(defaultUrlCreateParams, this.query.data) ??\n routeConfig.get().createUrl?.(defaultUrlCreateParams, this.query.data) ??\n defaultUrlCreateParams;\n\n const path = this._compiler(this.processParams(urlCreateParams.params));\n\n const url = `${urlCreateParams.baseUrl || ''}${this.isHash ? '#' : ''}${path}`;\n\n if (outputParams?.omitQuery) {\n return url;\n }\n\n return `${url}${buildSearchString(urlCreateParams.query)}`;\n }\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n navigateParams?: RouteNavigateParams,\n ]\n : [params: TInputParams, navigateParams?: RouteNavigateParams]\n ): Promise<void>;\n open(\n ...args: IsPartial<TInputParams> extends true\n ? [\n params?: TInputParams | null | undefined,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n : [\n params: TInputParams,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ]\n ): Promise<void>;\n open(url: string, navigateParams?: RouteNavigateParams): Promise<void>;\n open(\n url: string,\n replace?: RouteNavigateParams['replace'],\n query?: RouteNavigateParams['query'],\n ): Promise<void>;\n\n /**\n * Navigates to this route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Route.html#open-args)\n */\n async open(...args: any[]) {\n const {\n replace,\n state: rawState,\n query: rawQuery,\n mergeQuery: rawMergeQuery,\n } = typeof args[1] === 'boolean' || args.length > 2\n ? ({ replace: args[1], query: args[2] } as RouteNavigateParams)\n : ((args[1] ?? {}) as RouteNavigateParams);\n let url: string;\n let params: Maybe<InputPathParams<TPath>>;\n\n const mergeQuery = rawMergeQuery ?? this.isAbleToMergeQuery;\n const query = mergeQuery ? { ...this.query.data, ...rawQuery } : rawQuery;\n\n if (typeof args[0] === 'string') {\n url = args[0];\n } else {\n params = args[0] as InputPathParams<TPath>;\n url = this.createUrl(args[0], query);\n }\n\n const state = rawState ?? null;\n\n const trx: NavigationTrx<TInputParams> = {\n url,\n params: params as TInputParams,\n replace,\n state,\n query,\n };\n\n const isConfirmed = await this.confirmOpening(trx);\n\n if (!isConfirmed) {\n return;\n }\n\n this.skipPathMatchCheck = true;\n\n if (trx.replace) {\n this.history.replace(trx.url, trx.state);\n } else {\n this.history.push(trx.url, trx.state);\n }\n }\n\n protected get tokenData() {\n if (!this._tokenData) {\n this._tokenData = parse(this.path, this.config.parseOptions);\n }\n return this._tokenData;\n }\n\n protected async confirmOpening(trx: NavigationTrx<TInputParams>) {\n this.status = 'opening';\n\n if (this.config.beforeOpen) {\n const feedback = await this.config.beforeOpen(trx);\n\n if (feedback === false) {\n runInAction(() => {\n this.status = 'open-rejected';\n });\n return false;\n }\n\n if (typeof feedback === 'object') {\n return Object.assign(trx, feedback);\n }\n }\n\n runInAction(() => {\n this.status = 'open-confirmed';\n });\n\n return true;\n }\n\n protected confirmClosing() {\n this.status = 'closed';\n return true;\n }\n\n private firstPathMatchingRun = true;\n\n private checkPathMatch = async (isPathMathched: boolean) => {\n if (this.firstPathMatchingRun) {\n this.firstPathMatchingRun = false;\n // ignore first 'afterClose' callback call\n if (!isPathMathched) {\n return;\n }\n }\n\n if (this.skipPathMatchCheck) {\n // after open\n this.skipPathMatchCheck = false;\n return;\n }\n\n if (isPathMathched) {\n const trx: NavigationTrx<TInputParams> = {\n url: this.parsedPathData!.path,\n params: this.parsedPathData!.params as TInputParams,\n state: this.history.location.state,\n query: this.query.data,\n };\n\n const nextTrxOrConfirmed = await this.confirmOpening(trx);\n\n if (!nextTrxOrConfirmed) {\n return;\n }\n\n this.config.afterOpen?.(this.parsedPathData!, this);\n\n if (typeof nextTrxOrConfirmed === 'object') {\n if (nextTrxOrConfirmed.replace) {\n this.history.replace(\n nextTrxOrConfirmed.url,\n nextTrxOrConfirmed.state,\n );\n } else {\n this.history.push(nextTrxOrConfirmed.url, nextTrxOrConfirmed.state);\n }\n }\n\n return;\n } else {\n const isConfirmed = this.confirmClosing();\n\n if (isConfirmed) {\n this.config.afterClose?.();\n }\n }\n };\n\n private get isAbleToMergeQuery() {\n return this.config.mergeQuery ?? routeConfig.get().mergeQuery;\n }\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createRoute = <\n TPath extends string,\n TInputParams extends InputPathParams<TPath> = InputPathParams<TPath>,\n TOutputParams extends AnyObject = ParsedPathParams<TPath>,\n TParentRoute extends Route<any, any, any, any> | null = null,\n>(\n path: TPath,\n config?: RouteConfiguration<TPath, TInputParams, TOutputParams, TParentRoute>,\n) => new Route<TPath, TInputParams, TOutputParams, TParentRoute>(path, config);\n","import { computed, makeObservable, observable } from 'mobx';\n\nimport type {\n AbstractRouteGroup,\n AnyRouteEntity,\n RoutesCollection,\n} from './route-group.types.js';\n\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Class for grouping related routes and managing their state.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html)\n */\nexport class RouteGroup<TRoutesCollection extends RoutesCollection>\n implements AbstractRouteGroup<TRoutesCollection>\n{\n routes: TRoutesCollection;\n\n constructor(\n routes: TRoutesCollection,\n private _indexRoute?: AnyRouteEntity,\n ) {\n this.routes = routes;\n\n computed.struct(this, 'isOpened');\n computed.struct(this, 'indexRoute');\n observable.shallow(this, 'routes');\n makeObservable(this);\n }\n\n /**\n * Returns true if at least one route in the group is open.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#isopened-boolean)\n */\n get isOpened(): boolean {\n const routes = Object.values(this.routes);\n return routes.some(\n (route) =>\n route.isOpened ||\n ('hasOpenedChildren' in route && route.hasOpenedChildren),\n );\n }\n\n /**\n * First found index route.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#indexroute-route-undefined)\n */\n get indexRoute(): AnyRouteEntity | undefined {\n return (this._indexRoute ??\n Object.values(this.routes).find(\n (route) => 'isIndex' in route && route.isIndex,\n )) as unknown as AnyRouteEntity;\n }\n\n /**\n * Main navigation method for the group.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/RouteGroup.html#open-args-any-void)\n */\n open(...args: any[]) {\n let lastGroupRoute: RouteGroup<any> | undefined;\n\n if (this.indexRoute && 'open' in this.indexRoute) {\n this.indexRoute.open(...args);\n return;\n }\n\n for (const routeName in this.routes) {\n const route = this.routes[routeName];\n if (route instanceof RouteGroup) {\n lastGroupRoute = route;\n }\n }\n\n if (lastGroupRoute) {\n lastGroupRoute.open(...args);\n } else if (process.env.NODE_ENV !== 'production') {\n console.warn(\n \"RouteGroup doesn't have index route. open() method doesn't work.\",\n );\n }\n }\n}\n\nexport const createRouteGroup = <TRoutesCollection extends RoutesCollection>(\n routes: TRoutesCollection,\n indexRoute?: AnyRouteEntity,\n) => new RouteGroup<TRoutesCollection>(routes, indexRoute);\n","import { computed, makeObservable } from 'mobx';\nimport {\n buildSearchString,\n type History,\n type IQueryParams,\n} from 'mobx-location-history';\n\nimport { routeConfig } from '../config/index.js';\nimport type { RoutesCollection } from '../route-group/index.js';\n\nimport type {\n RouterConfiguration,\n RouterNavigateOptions,\n} from './router.types.js';\n\n/**\n * Class for centralized routing management.\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/Router.html)\n */\nexport class Router<TRoutesCollection extends RoutesCollection> {\n routes: TRoutesCollection;\n history: History;\n query: IQueryParams;\n\n constructor(config: RouterConfiguration<TRoutesCollection>) {\n this.routes = config.routes;\n this.history = config.history ?? routeConfig.get().history;\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n\n computed.struct(this, 'location');\n\n makeObservable(this);\n }\n\n get location() {\n return this.history.location;\n }\n\n navigate(url: string, options?: RouterNavigateOptions) {\n const query =\n (options?.mergeQuery ?? routeConfig.get().mergeQuery)\n ? { ...this.query.data, ...options?.query }\n : { ...options?.query };\n\n const searchString = buildSearchString(query);\n const navigationUrl = `${url}${searchString}`;\n\n if (options?.replace) {\n this.history.replace(navigationUrl, options?.state);\n } else {\n this.history.push(navigationUrl, options?.state);\n }\n }\n}\n\nexport const createRouter = <TRoutesCollection extends RoutesCollection>(\n config: RouterConfiguration<TRoutesCollection>,\n) => new Router(config);\n","import type { AnyRouteEntity } from '../route-group/index.js';\n\nexport const isRouteEntity = (route: any): route is AnyRouteEntity =>\n route && 'isOpened' in route;\n","import { LinkedAbortController } from 'linked-abort-controller';\nimport {\n action,\n computed,\n makeObservable,\n observable,\n onBecomeObserved,\n onBecomeUnobserved,\n reaction,\n runInAction,\n} from 'mobx';\nimport type { IQueryParams } from 'mobx-location-history';\nimport { callFunction } from 'yummies/common';\nimport type { AnyObject, EmptyObject, IsPartial, Maybe } from 'yummies/types';\n\nimport { routeConfig } from '../config/index.js';\n\nimport type {\n AbstractVirtualRoute,\n VirtualOpenExtraParams,\n VirtualRouteConfiguration,\n} from './virtual-route.types.js';\n\n/**\n * Class for creating routes with custom activation logic\n *\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html)\n */\nexport class VirtualRoute<TParams extends AnyObject | EmptyObject = EmptyObject>\n implements AbstractVirtualRoute<TParams>\n{\n protected abortController: AbortController;\n query: IQueryParams;\n params: TParams | null;\n\n private isLocalOpened: boolean;\n\n private openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>;\n private reactionDisposer: Maybe<VoidFunction>;\n\n constructor(protected config: VirtualRouteConfiguration<TParams> = {}) {\n this.abortController = new LinkedAbortController(config.abortSignal);\n this.query = config.queryParams ?? routeConfig.get().queryParams;\n this.params = callFunction(config.initialParams, this) ?? null;\n this.openChecker = config.checkOpened;\n this.isLocalOpened = this.openChecker?.(this) ?? false;\n\n observable(this, 'params');\n observable.ref(this, 'isLocalOpened');\n observable.ref(this, '_isOpened');\n computed.struct(this, 'isOpened');\n action(this, 'setOpenChecker');\n action(this, 'open');\n action(this, 'close');\n makeObservable(this);\n\n onBecomeObserved(this, 'isOpened', () => {\n if (!config.afterOpen && !config.afterClose) {\n return;\n }\n\n this.reactionDisposer = reaction(\n () => this.isOpened,\n this.processOpenedState,\n {\n signal: this.abortController.signal,\n fireImmediately: true,\n },\n );\n });\n onBecomeUnobserved(this, 'isOpened', () => {\n this.reactionDisposer?.();\n this.reactionDisposer = undefined;\n });\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#isopened-boolean)\n */\n get isOpened() {\n const isOuterOpened = this.openChecker == null || this.openChecker(this);\n return this.isLocalOpened && isOuterOpened;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#setopenchecker-openchecker-void)\n */\n setOpenChecker(\n openChecker: Maybe<VirtualRouteConfiguration<TParams>['checkOpened']>,\n ) {\n this.openChecker = openChecker;\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#open-params-extraparams-query-replace-promise-void)\n */\n open(\n ...args: IsPartial<TParams> extends true\n ? [params?: Maybe<TParams>, extraParams?: VirtualOpenExtraParams]\n : [params: TParams, extraParams?: VirtualOpenExtraParams]\n ): Promise<void>;\n async open(...args: any[]) {\n const params = (args[0] ?? {}) as unknown as TParams;\n const extraParams: Maybe<VirtualOpenExtraParams> = args[1];\n\n if (this.config.beforeOpen) {\n const beforeOpenResult = await this.config.beforeOpen(params, this);\n if (beforeOpenResult === false) {\n return;\n }\n }\n\n if (this.config.open == null) {\n runInAction(() => {\n this.isLocalOpened = true;\n });\n } else {\n const result = await this.config.open(params, this);\n // because result can return void so this is truthy for opening state\n runInAction(() => {\n this.isLocalOpened = result !== false;\n });\n }\n\n if (!this.isLocalOpened) {\n return;\n }\n\n if (extraParams?.query) {\n this.query.update(extraParams.query, extraParams.replace);\n }\n\n runInAction(() => {\n this.params = params;\n });\n\n if (!this.reactionDisposer && this.isOpened) {\n this.config.afterOpen?.(this.params!, this);\n }\n }\n\n /**\n * [**Documentation**](https://js2me.github.io/mobx-route/core/VirtualRoute.html#close-void)\n */\n close() {\n if (this.config.close == null) {\n this.isLocalOpened = false;\n } else {\n const result = this.config.close(this);\n // because result can return void so this is truthy for opening state\n this.isLocalOpened = result !== false;\n }\n\n this.params = null;\n }\n\n private firstOpenedStateCheck = true;\n private processOpenedState = (isOpened: boolean) => {\n if (this.firstOpenedStateCheck) {\n this.firstOpenedStateCheck = false;\n // ignore first 'afterClose' callback call\n if (!isOpened) {\n return;\n }\n }\n\n if (isOpened) {\n this.config.afterOpen?.(this.params!, this);\n } else {\n this.config.afterClose?.();\n }\n };\n\n destroy() {\n this.abortController.abort();\n }\n}\n\nexport const createVirtualRoute = <\n TParams extends AnyObject | EmptyObject = EmptyObject,\n>(\n config?: VirtualRouteConfiguration<TParams>,\n) => new VirtualRoute<TParams>(config);\n"],"names":[],"mappings":"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"}
|