boring-router
Advanced tools
Comparing version 0.3.2 to 0.3.3
@@ -1,6 +0,4 @@ | ||
import { Dict } from 'tslang'; | ||
import { GeneralParamDict, GeneralQueryDict, GeneralSegmentDict } from './route-match'; | ||
export declare function hasOwnProperty(object: object, name: string): boolean; | ||
import { GeneralParamDict, GeneralSegmentDict } from './route-match'; | ||
export declare function buildPath(segmentDict: GeneralSegmentDict, paramDict?: GeneralParamDict): string; | ||
export declare function buildRef(pathMap: Map<string | undefined, string>, queryDict: Dict<string | undefined>): string; | ||
export declare function buildRef(pathMap: Map<string | undefined, string>, queryMap: Map<string, string | undefined> | undefined): string; | ||
export interface ParseRefResult { | ||
@@ -12,5 +10,5 @@ pathname: string; | ||
export declare function parseRef(ref: string): ParseRefResult; | ||
export declare function parseSearch(search: string): GeneralQueryDict; | ||
export declare function parseSearch(search: string): Map<string, string>; | ||
export declare function testPathPrefix(path: string, prefix: string): boolean; | ||
export declare type ToleratedReturnType<TOriginalReturnType> = TOriginalReturnType extends Promise<infer T> ? Promise<T | undefined> | undefined : TOriginalReturnType | undefined; | ||
export declare function tolerate<T extends (...args: any[]) => any>(fn: T, ...args: Parameters<T>): ToleratedReturnType<ReturnType<T>>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.tolerate = exports.testPathPrefix = exports.parseSearch = exports.parseRef = exports.buildRef = exports.buildPath = exports.hasOwnProperty = void 0; | ||
const _hasOwnProperty = Object.prototype.hasOwnProperty; | ||
function hasOwnProperty(object, name) { | ||
return _hasOwnProperty.call(object, name); | ||
} | ||
exports.hasOwnProperty = hasOwnProperty; | ||
exports.tolerate = exports.testPathPrefix = exports.parseSearch = exports.parseRef = exports.buildRef = exports.buildPath = void 0; | ||
function buildPath(segmentDict, paramDict = {}) { | ||
@@ -22,3 +17,3 @@ return (Object.entries(segmentDict) | ||
exports.buildPath = buildPath; | ||
function buildRef(pathMap, queryDict) { | ||
function buildRef(pathMap, queryMap) { | ||
var _a; | ||
@@ -30,3 +25,4 @@ let primaryPath = (_a = pathMap.get(undefined)) !== null && _a !== void 0 ? _a : ''; | ||
.join('&')); | ||
let normalQuery = new URLSearchParams(Object.entries(queryDict).filter((entry) => entry[1] !== undefined)).toString(); | ||
let normalQuery = queryMap && | ||
new URLSearchParams(Array.from(queryMap).filter((entry) => entry[1] !== undefined)).toString(); | ||
let query = pathQuery | ||
@@ -58,6 +54,3 @@ ? normalQuery | ||
let searchParams = new URLSearchParams(search); | ||
return Array.from(searchParams).reduce((dict, [key, value]) => { | ||
dict[key] = value; | ||
return dict; | ||
}, {}); | ||
return new Map(searchParams); | ||
} | ||
@@ -64,0 +57,0 @@ exports.parseSearch = parseSearch; |
import { EmptyObjectPatch } from 'tslang'; | ||
import { GeneralParamDict, GeneralQueryDict, RouteMatchShared, RouteMatchSharedToParamDict } from './route-match'; | ||
import { GeneralParamDict, RouteMatchShared, RouteMatchSharedToParamDict, RouteSourceQuery } from './route-match'; | ||
import { Router, RouterNavigateOptions } from './router'; | ||
@@ -10,7 +10,7 @@ export interface RouteBuilderBuildingPart { | ||
private sourcePathMap; | ||
private sourceQueryDict; | ||
private sourceQueryMap; | ||
private router; | ||
private buildingParts; | ||
private leavingGroupSet; | ||
constructor(sourcePathMap: Map<string | undefined, string>, sourceQueryDict: GeneralQueryDict, router: Router<TGroupName>, buildingParts?: (RouteBuilderBuildingPart | string)[], leavingGroupSet?: Set<string>); | ||
constructor(sourcePathMap: Map<string | undefined, string>, sourceQueryMap: Map<string, RouteSourceQuery>, router: Router<TGroupName>, buildingParts?: (RouteBuilderBuildingPart | string)[], leavingGroupSet?: Set<string>); | ||
/** | ||
@@ -17,0 +17,0 @@ * Route of the first building part if available. |
@@ -6,5 +6,5 @@ "use strict"; | ||
class RouteBuilder { | ||
constructor(sourcePathMap, sourceQueryDict, router, buildingParts = [], leavingGroupSet = new Set()) { | ||
constructor(sourcePathMap, sourceQueryMap, router, buildingParts = [], leavingGroupSet = new Set()) { | ||
this.sourcePathMap = sourcePathMap; | ||
this.sourceQueryDict = sourceQueryDict; | ||
this.sourceQueryMap = sourceQueryMap; | ||
this.router = router; | ||
@@ -28,3 +28,3 @@ this.buildingParts = buildingParts; | ||
}; | ||
return new RouteBuilder(this.sourcePathMap, this.sourceQueryDict, this.router, [...this.buildingParts, buildingPart]); | ||
return new RouteBuilder(this.sourcePathMap, this.sourceQueryMap, this.router, [...this.buildingParts, buildingPart]); | ||
} | ||
@@ -36,18 +36,15 @@ $leave(groups) { | ||
let leavingGroupSet = new Set([...this.leavingGroupSet, ...groups]); | ||
return new RouteBuilder(this.sourcePathMap, this.sourceQueryDict, this.router, this.buildingParts, leavingGroupSet); | ||
return new RouteBuilder(this.sourcePathMap, this.sourceQueryMap, this.router, this.buildingParts, leavingGroupSet); | ||
} | ||
$ref() { | ||
let pathMap = new Map(this.sourcePathMap); | ||
let queryDict = this.sourceQueryDict; | ||
let queryMap; | ||
for (let buildingPart of this.buildingParts) { | ||
if (typeof buildingPart === 'string') { | ||
let { groups, query: buildingPartQueryDict } = parseStringBuildingPart(buildingPart, this.router.$groups); | ||
let { groups, query: buildingPartQueryMap } = parseStringBuildingPart(buildingPart, this.router.$groups); | ||
for (let { name, path } of groups) { | ||
pathMap.set(name, path); | ||
} | ||
if (buildingPartQueryDict) { | ||
queryDict = { | ||
...queryDict, | ||
...buildingPartQueryDict, | ||
}; | ||
if (buildingPartQueryMap) { | ||
queryMap = buildingPartQueryMap; | ||
} | ||
@@ -67,15 +64,15 @@ } | ||
if (primary) { | ||
let { queryDict: sourceQueryDict } = route._source; | ||
let queryKeySet = route._queryKeySet; | ||
queryDict = {}; | ||
for (let [key, value] of Object.entries(sourceQueryDict)) { | ||
if (queryKeySet.has(key)) { | ||
queryDict[key] = value; | ||
let { queryMap: sourceQueryMap } = route._source; | ||
let queryKeyToIdMap = route._queryKeyToIdMap; | ||
queryMap = new Map(); | ||
for (let [key, { id, value }] of sourceQueryMap) { | ||
if (queryKeyToIdMap.get(key) === id) { | ||
queryMap.set(key, value); | ||
} | ||
} | ||
for (let key of restParamKeySet) { | ||
if (!queryKeySet.has(key)) { | ||
if (!queryKeyToIdMap.has(key)) { | ||
throw new Error(`Parameter "${key}" is defined as neither segment nor query`); | ||
} | ||
queryDict[key] = paramDict[key]; | ||
queryMap.set(key, paramDict[key]); | ||
} | ||
@@ -88,3 +85,6 @@ } | ||
} | ||
return _utils_1.buildRef(pathMap, pathMap.get(undefined) ? queryDict : {}); | ||
if (pathMap.get(undefined) && !queryMap) { | ||
queryMap = new Map(Array.from(this.sourceQueryMap).map(([key, { value }]) => [key, value])); | ||
} | ||
return _utils_1.buildRef(pathMap, queryMap); | ||
} | ||
@@ -114,10 +114,10 @@ $href() { | ||
let primaryPath; | ||
let queryDict; | ||
let queryMap; | ||
if (searchIndex >= 0) { | ||
primaryPath = part.slice(0, searchIndex); | ||
queryDict = _utils_1.parseSearch(part.slice(searchIndex)); | ||
queryMap = _utils_1.parseSearch(part.slice(searchIndex)); | ||
} | ||
else { | ||
primaryPath = part; | ||
queryDict = undefined; | ||
queryMap = undefined; | ||
} | ||
@@ -131,22 +131,26 @@ let buildingPartGroups = []; | ||
} | ||
if (queryDict) { | ||
if (queryMap) { | ||
for (let group of groups) { | ||
let key = `_${group}`; | ||
if (_utils_1.hasOwnProperty(queryDict, key)) { | ||
if (queryMap.has(key)) { | ||
buildingPartGroups.push({ | ||
name: group, | ||
path: queryDict[key], | ||
path: queryMap.get(key), | ||
}); | ||
delete queryDict[key]; | ||
queryMap.delete(key); | ||
} | ||
} | ||
if (Object.keys(queryDict).length === 0) { | ||
queryDict = undefined; | ||
if (queryMap.size === 0) { | ||
queryMap = undefined; | ||
} | ||
if (queryMap && !primaryPath) { | ||
console.error(`Unexpected query in string building part without primary route path: "${part}"`); | ||
queryMap = undefined; | ||
} | ||
} | ||
return { | ||
groups: buildingPartGroups, | ||
query: queryDict, | ||
query: queryMap, | ||
}; | ||
} | ||
//# sourceMappingURL=route-builder.js.map |
@@ -25,3 +25,3 @@ import { Dict, EmptyObjectPatch } from 'tslang'; | ||
match: string | symbol | RegExp; | ||
query: Dict<boolean> | undefined; | ||
query: Map<string, string | symbol>; | ||
group: string | undefined; | ||
@@ -28,0 +28,0 @@ } |
@@ -10,2 +10,3 @@ "use strict"; | ||
constructor(name, router, source, parent, history, { match, query, group }) { | ||
var _a; | ||
this.$name = name; | ||
@@ -21,5 +22,6 @@ this.$group = group; | ||
this._matchPattern = match; | ||
this._queryKeySet = new Set([ | ||
...(query ? Object.keys(query) : []), | ||
...(parent ? parent._queryKeySet : []), | ||
this._queryKeyToIdMap = new Map([ | ||
...query, | ||
...Object.entries(query !== null && query !== void 0 ? query : {}), | ||
...((_a = parent === null || parent === void 0 ? void 0 : parent._queryKeyToIdMap) !== null && _a !== void 0 ? _a : []), | ||
]); | ||
@@ -109,8 +111,9 @@ } | ||
get _query() { | ||
let sourceQueryDict = this._source.queryDict; | ||
return Array.from(this._queryKeySet).reduce((dict, key) => { | ||
let value = sourceQueryDict[key]; | ||
if (value !== undefined) { | ||
dict[key] = sourceQueryDict[key]; | ||
let sourceQueryMap = this._source.queryMap; | ||
return Array.from(this._queryKeyToIdMap).reduce((dict, [key, id]) => { | ||
let sourceQuery = sourceQueryMap.get(key); | ||
if (!sourceQuery || sourceQuery.id !== id) { | ||
return dict; | ||
} | ||
dict[key] = sourceQuery.value; | ||
return dict; | ||
@@ -120,3 +123,3 @@ }, {}); | ||
$(params) { | ||
return new route_builder_1.RouteBuilder(new Map(), this._source.queryDict, this.$router, [{ route: this, params }]); | ||
return new route_builder_1.RouteBuilder(new Map(), this._source.queryMap, this.$router, [{ route: this, params }]); | ||
} | ||
@@ -123,0 +126,0 @@ $ref(params) { |
@@ -6,3 +6,3 @@ import { IAutorunOptions, IReactionDisposer, IReactionPublic } from 'mobx'; | ||
import { NextRouteMatch } from './next-route-match'; | ||
import { GeneralParamDict, GeneralQueryDict, RouteMatchShared, RouteMatchSharedOptions } from './route-match-shared'; | ||
import { GeneralParamDict, RouteMatchShared, RouteMatchSharedOptions } from './route-match-shared'; | ||
export interface RouteUpdateCallbackData { | ||
@@ -93,5 +93,9 @@ descendants: boolean; | ||
} | ||
export interface RouteSourceQuery { | ||
id: string | symbol; | ||
value: string; | ||
} | ||
export interface RouteSource { | ||
groupToMatchToMatchEntryMapMap: Map<string | undefined, Map<RouteMatch, RouteMatchEntry>>; | ||
queryDict: GeneralQueryDict; | ||
queryMap: Map<string, RouteSourceQuery>; | ||
pathMap: Map<string | undefined, string>; | ||
@@ -123,4 +127,4 @@ } | ||
$parallel(options: RouteMatchParallelOptions<TGroupName>): void; | ||
static segment: RegExp; | ||
static rest: RegExp; | ||
static SEGMENT: RegExp; | ||
static REST: RegExp; | ||
} |
@@ -37,5 +37,3 @@ "use strict"; | ||
get() { | ||
let service = this.$matched | ||
? this._service | ||
: undefined; | ||
let service = this.$matched ? this._service : undefined; | ||
return service && key in service | ||
@@ -439,4 +437,4 @@ ? service[key] | ||
} | ||
RouteMatch.segment = /[^/]+/; | ||
RouteMatch.rest = /.+/; | ||
RouteMatch.SEGMENT = /[^/]+/; | ||
RouteMatch.REST = /.*/; | ||
tslib_1.__decorate([ | ||
@@ -443,0 +441,0 @@ mobx_1.observable |
@@ -18,3 +18,3 @@ "use strict"; | ||
groupToMatchToMatchEntryMapMap: new Map(), | ||
queryDict: {}, | ||
queryMap: new Map(), | ||
pathMap: new Map(), | ||
@@ -25,3 +25,3 @@ }); | ||
groupToMatchToMatchEntryMapMap: new Map(), | ||
queryDict: {}, | ||
queryMap: new Map(), | ||
pathMap: new Map(), | ||
@@ -67,3 +67,3 @@ }); | ||
} | ||
let queryDict = _utils_1.parseSearch(search); | ||
let queryMap = _utils_1.parseSearch(search); | ||
let pathMap = new Map(); | ||
@@ -75,10 +75,10 @@ pathMap.set(undefined, pathname || '/'); | ||
let key = `_${group}`; | ||
if (!_utils_1.hasOwnProperty(queryDict, key)) { | ||
if (!queryMap.has(key)) { | ||
continue; | ||
} | ||
let path = queryDict[key]; | ||
let path = queryMap.get(key); | ||
if (path) { | ||
pathMap.set(group, path); | ||
} | ||
delete queryDict[key]; | ||
queryMap.delete(key); | ||
} | ||
@@ -119,8 +119,11 @@ // Match parallel routes | ||
} | ||
let matchingSource = this._matchingSource; | ||
mobx_1.runInAction(() => { | ||
Object.assign(this._matchingSource, { | ||
groupToMatchToMatchEntryMapMap, | ||
queryDict, | ||
pathMap, | ||
}); | ||
matchingSource.groupToMatchToMatchEntryMapMap = groupToMatchToMatchEntryMapMap; | ||
matchingSource.pathMap = pathMap; | ||
let matchingQueryKeyToIdMap = groupToRouteMatchMap.get(undefined).$next | ||
.$rest._queryKeyToIdMap; | ||
matchingSource.queryMap = new Map(lodash_1.default.compact(Array.from(queryMap).map(([key, value]) => matchingQueryKeyToIdMap.has(key) | ||
? [key, { id: matchingQueryKeyToIdMap.get(key), value }] | ||
: undefined))); | ||
}); | ||
@@ -145,4 +148,4 @@ let generalGroups = [undefined, ...groups]; | ||
get $current() { | ||
let { pathMap, queryDict } = this._source; | ||
return new route_builder_1.RouteBuilder(pathMap, queryDict, this); | ||
let { pathMap, queryMap } = this._source; | ||
return new route_builder_1.RouteBuilder(pathMap, queryMap, this); | ||
} | ||
@@ -153,4 +156,4 @@ get $routing() { | ||
get $next() { | ||
let { pathMap, queryDict } = this._matchingSource; | ||
return new route_builder_1.RouteBuilder(pathMap, queryDict, this); | ||
let { pathMap, queryMap } = this._matchingSource; | ||
return new route_builder_1.RouteBuilder(pathMap, queryMap, this); | ||
} | ||
@@ -189,3 +192,3 @@ get $groups() { | ||
$(route, params) { | ||
let { pathMap, queryDict } = this._source; | ||
let { pathMap, queryMap } = this._source; | ||
let buildingPart = typeof route === 'string' | ||
@@ -197,6 +200,6 @@ ? route | ||
}; | ||
return new route_builder_1.RouteBuilder(pathMap, queryDict, this, [buildingPart]); | ||
return new route_builder_1.RouteBuilder(pathMap, queryMap, this, [buildingPart]); | ||
} | ||
$scratch() { | ||
return new route_builder_1.RouteBuilder(new Map(), {}, this); | ||
return new route_builder_1.RouteBuilder(new Map(), new Map(), this); | ||
} | ||
@@ -312,3 +315,3 @@ $push(ref, options) { | ||
let matchingSource = this._matchingSource; | ||
source.queryDict = matchingSource.queryDict; | ||
source.queryMap = matchingSource.queryMap; | ||
for (let group of generalGroups) { | ||
@@ -412,6 +415,10 @@ let path = matchingSource.pathMap.get(group); | ||
/** @internal */ | ||
_buildRouteMatch(group, routeName, parent, matchingParent, { match, exact, query, children, extension, metadata, }) { | ||
_buildRouteMatch(group, routeName, parent, matchingParent, { match, exact, query: queryDict, children, extension, metadata, }) { | ||
let source = this._source; | ||
let matchingSource = this._matchingSource; | ||
let history = this._history; | ||
let query = new Map(Object.entries(queryDict !== null && queryDict !== void 0 ? queryDict : {}).map(([key, id]) => [ | ||
key, | ||
typeof id === 'boolean' ? Symbol(`query:${routeName}.${key}`) : id, | ||
])); | ||
let options = { | ||
@@ -418,0 +425,0 @@ match, |
import { Dict } from 'tslang'; | ||
export interface RouteSchema { | ||
$match?: string | RegExp; | ||
$query?: Dict<boolean>; | ||
$query?: Dict<string | symbol | true>; | ||
/** | ||
@@ -6,0 +6,0 @@ * Whether to allow exact match while if this route has children. Only |
{ | ||
"name": "boring-router", | ||
"version": "0.3.2", | ||
"version": "0.3.3", | ||
"description": "A type-safe MobX router with parallel routing support.", | ||
@@ -36,3 +36,3 @@ "repository": { | ||
}, | ||
"gitHead": "ab23a3ea9bb70a67b79920f3a71287cc0a93c259" | ||
"gitHead": "ca1048def542e1f8eb46bfaac8205a3f403cb16a" | ||
} |
# Boring Router | ||
The core of boring router. | ||
The core of Boring Router. | ||
Checkout https://github.com/makeflow/boring-router for documentation. | ||
Checkout https://makeflow.github.io/boring-router/ for documentation. |
@@ -1,15 +0,3 @@ | ||
import {Dict} from 'tslang'; | ||
import {GeneralParamDict, GeneralSegmentDict} from './route-match'; | ||
import { | ||
GeneralParamDict, | ||
GeneralQueryDict, | ||
GeneralSegmentDict, | ||
} from './route-match'; | ||
const _hasOwnProperty = Object.prototype.hasOwnProperty; | ||
export function hasOwnProperty(object: object, name: string): boolean { | ||
return _hasOwnProperty.call(object, name); | ||
} | ||
export function buildPath( | ||
@@ -37,3 +25,3 @@ segmentDict: GeneralSegmentDict, | ||
pathMap: Map<string | undefined, string>, | ||
queryDict: Dict<string | undefined>, | ||
queryMap: Map<string, string | undefined> | undefined, | ||
): string { | ||
@@ -49,7 +37,9 @@ let primaryPath = pathMap.get(undefined) ?? ''; | ||
let normalQuery = new URLSearchParams( | ||
Object.entries(queryDict).filter( | ||
(entry): entry is [string, string] => entry[1] !== undefined, | ||
), | ||
).toString(); | ||
let normalQuery = | ||
queryMap && | ||
new URLSearchParams( | ||
Array.from(queryMap).filter( | ||
(entry): entry is [string, string] => entry[1] !== undefined, | ||
), | ||
).toString(); | ||
@@ -90,9 +80,6 @@ let query = pathQuery | ||
export function parseSearch(search: string): GeneralQueryDict { | ||
export function parseSearch(search: string): Map<string, string> { | ||
let searchParams = new URLSearchParams(search); | ||
return Array.from(searchParams).reduce((dict, [key, value]) => { | ||
dict[key] = value; | ||
return dict; | ||
}, {} as GeneralQueryDict); | ||
return new Map(searchParams); | ||
} | ||
@@ -99,0 +86,0 @@ |
import {EmptyObjectPatch} from 'tslang'; | ||
import {buildPath, buildRef, hasOwnProperty, parseSearch} from './@utils'; | ||
import {buildPath, buildRef, parseSearch} from './@utils'; | ||
import { | ||
GeneralParamDict, | ||
GeneralQueryDict, | ||
RouteMatchShared, | ||
RouteMatchSharedToParamDict, | ||
RouteSourceQuery, | ||
} from './route-match'; | ||
@@ -20,3 +20,3 @@ import {Router, RouterNavigateOptions} from './router'; | ||
private sourcePathMap: Map<string | undefined, string>, | ||
private sourceQueryDict: GeneralQueryDict, | ||
private sourceQueryMap: Map<string, RouteSourceQuery>, | ||
private router: Router<TGroupName>, | ||
@@ -53,3 +53,3 @@ private buildingParts: (RouteBuilderBuildingPart | string)[] = [], | ||
this.sourcePathMap, | ||
this.sourceQueryDict, | ||
this.sourceQueryMap, | ||
this.router, | ||
@@ -69,3 +69,3 @@ [...this.buildingParts, buildingPart], | ||
this.sourcePathMap, | ||
this.sourceQueryDict, | ||
this.sourceQueryMap, | ||
this.router, | ||
@@ -79,7 +79,8 @@ this.buildingParts, | ||
let pathMap = new Map(this.sourcePathMap); | ||
let queryDict = this.sourceQueryDict; | ||
let queryMap: Map<string, string | undefined> | undefined; | ||
for (let buildingPart of this.buildingParts) { | ||
if (typeof buildingPart === 'string') { | ||
let {groups, query: buildingPartQueryDict} = parseStringBuildingPart( | ||
let {groups, query: buildingPartQueryMap} = parseStringBuildingPart( | ||
buildingPart, | ||
@@ -93,7 +94,4 @@ this.router.$groups, | ||
if (buildingPartQueryDict) { | ||
queryDict = { | ||
...queryDict, | ||
...buildingPartQueryDict, | ||
}; | ||
if (buildingPartQueryMap) { | ||
queryMap = buildingPartQueryMap; | ||
} | ||
@@ -119,11 +117,11 @@ } else { | ||
if (primary) { | ||
let {queryDict: sourceQueryDict} = route._source; | ||
let {queryMap: sourceQueryMap} = route._source; | ||
let queryKeySet = route._queryKeySet; | ||
let queryKeyToIdMap = route._queryKeyToIdMap; | ||
queryDict = {}; | ||
queryMap = new Map(); | ||
for (let [key, value] of Object.entries(sourceQueryDict)) { | ||
if (queryKeySet.has(key)) { | ||
queryDict[key] = value; | ||
for (let [key, {id, value}] of sourceQueryMap) { | ||
if (queryKeyToIdMap.get(key) === id) { | ||
queryMap.set(key, value); | ||
} | ||
@@ -133,3 +131,3 @@ } | ||
for (let key of restParamKeySet) { | ||
if (!queryKeySet.has(key)) { | ||
if (!queryKeyToIdMap.has(key)) { | ||
throw new Error( | ||
@@ -140,3 +138,3 @@ `Parameter "${key}" is defined as neither segment nor query`, | ||
queryDict[key] = paramDict[key]; | ||
queryMap.set(key, paramDict[key]); | ||
} | ||
@@ -151,3 +149,9 @@ } | ||
return buildRef(pathMap, pathMap.get(undefined) ? queryDict : {}); | ||
if (pathMap.get(undefined) && !queryMap) { | ||
queryMap = new Map( | ||
Array.from(this.sourceQueryMap).map(([key, {value}]) => [key, value]), | ||
); | ||
} | ||
return buildRef(pathMap, queryMap); | ||
} | ||
@@ -184,3 +188,3 @@ | ||
groups: ParsedStringBuildingPartGroup[]; | ||
query: GeneralQueryDict | undefined; | ||
query: Map<string, string> | undefined; | ||
} | ||
@@ -195,10 +199,10 @@ | ||
let primaryPath: string | undefined; | ||
let queryDict: GeneralQueryDict | undefined; | ||
let queryMap: Map<string, string> | undefined; | ||
if (searchIndex >= 0) { | ||
primaryPath = part.slice(0, searchIndex); | ||
queryDict = parseSearch(part.slice(searchIndex)); | ||
queryMap = parseSearch(part.slice(searchIndex)); | ||
} else { | ||
primaryPath = part; | ||
queryDict = undefined; | ||
queryMap = undefined; | ||
} | ||
@@ -215,19 +219,27 @@ | ||
if (queryDict) { | ||
if (queryMap) { | ||
for (let group of groups) { | ||
let key = `_${group}`; | ||
if (hasOwnProperty(queryDict, key)) { | ||
if (queryMap.has(key)) { | ||
buildingPartGroups.push({ | ||
name: group, | ||
path: queryDict[key]!, | ||
path: queryMap.get(key)!, | ||
}); | ||
delete queryDict[key]; | ||
queryMap.delete(key); | ||
} | ||
} | ||
if (Object.keys(queryDict).length === 0) { | ||
queryDict = undefined; | ||
if (queryMap.size === 0) { | ||
queryMap = undefined; | ||
} | ||
if (queryMap && !primaryPath) { | ||
console.error( | ||
`Unexpected query in string building part without primary route path: "${part}"`, | ||
); | ||
queryMap = undefined; | ||
} | ||
} | ||
@@ -237,4 +249,4 @@ | ||
groups: buildingPartGroups, | ||
query: queryDict, | ||
query: queryMap, | ||
}; | ||
} |
@@ -39,3 +39,3 @@ import {computed} from 'mobx'; | ||
match: string | symbol | RegExp; | ||
query: Dict<boolean> | undefined; | ||
query: Map<string, string | symbol>; | ||
group: string | undefined; | ||
@@ -71,3 +71,3 @@ } | ||
/** @internal */ | ||
readonly _queryKeySet: Set<string>; | ||
readonly _queryKeyToIdMap: Map<string, string | symbol>; | ||
@@ -106,5 +106,6 @@ /** @internal */ | ||
this._queryKeySet = new Set([ | ||
...(query ? Object.keys(query) : []), | ||
...(parent ? parent._queryKeySet : []), | ||
this._queryKeyToIdMap = new Map([ | ||
...query, | ||
...Object.entries(query ?? {}), | ||
...(parent?._queryKeyToIdMap ?? []), | ||
]); | ||
@@ -223,11 +224,13 @@ } | ||
protected get _query(): GeneralQueryDict | undefined { | ||
let sourceQueryDict = this._source.queryDict; | ||
let sourceQueryMap = this._source.queryMap; | ||
return Array.from(this._queryKeySet).reduce((dict, key) => { | ||
let value = sourceQueryDict[key]; | ||
return Array.from(this._queryKeyToIdMap).reduce((dict, [key, id]) => { | ||
let sourceQuery = sourceQueryMap.get(key); | ||
if (value !== undefined) { | ||
dict[key] = sourceQueryDict[key]; | ||
if (!sourceQuery || sourceQuery.id !== id) { | ||
return dict; | ||
} | ||
dict[key] = sourceQuery.value; | ||
return dict; | ||
@@ -240,3 +243,3 @@ }, {} as GeneralQueryDict); | ||
new Map(), | ||
this._source.queryDict, | ||
this._source.queryMap, | ||
this.$router, | ||
@@ -243,0 +246,0 @@ [{route: this, params}], |
@@ -18,3 +18,2 @@ import { | ||
GeneralParamDict, | ||
GeneralQueryDict, | ||
GeneralSegmentDict, | ||
@@ -206,2 +205,7 @@ ROUTE_MATCH_START_ANCHOR_PATTERN, | ||
export interface RouteSourceQuery { | ||
id: string | symbol; | ||
value: string; | ||
} | ||
export interface RouteSource { | ||
@@ -212,3 +216,3 @@ groupToMatchToMatchEntryMapMap: Map< | ||
>; | ||
queryDict: GeneralQueryDict; | ||
queryMap: Map<string, RouteSourceQuery>; | ||
pathMap: Map<string | undefined, string>; | ||
@@ -300,6 +304,4 @@ } | ||
Object.defineProperty(this, key, { | ||
get() { | ||
let service = (this as RouteMatch).$matched | ||
? (this as RouteMatch)._service | ||
: undefined; | ||
get(this: RouteMatch) { | ||
let service = this.$matched ? this._service : undefined; | ||
@@ -870,4 +872,4 @@ return service && key in (service as any) | ||
static segment = /[^/]+/; | ||
static rest = /.+/; | ||
static SEGMENT = /[^/]+/; | ||
static REST = /.*/; | ||
} |
@@ -6,3 +6,3 @@ import hyphenate from 'hyphenate'; | ||
import {hasOwnProperty, parseRef, parseSearch} from './@utils'; | ||
import {parseRef, parseSearch} from './@utils'; | ||
import {HistorySnapshot, IHistory, getActiveHistoryEntry} from './history'; | ||
@@ -20,2 +20,3 @@ import {RouteBuilder} from './route-builder'; | ||
RouteSource, | ||
RouteSourceQuery, | ||
} from './route-match'; | ||
@@ -225,3 +226,3 @@ import {RouteSchemaDict} from './schema'; | ||
exact: boolean | string; | ||
query: Dict<boolean> | undefined; | ||
query: Dict<string | symbol | true> | undefined; | ||
children: RouteSchemaDict | undefined; | ||
@@ -266,3 +267,3 @@ extension: object | undefined; | ||
groupToMatchToMatchEntryMapMap: new Map(), | ||
queryDict: {}, | ||
queryMap: new Map(), | ||
pathMap: new Map(), | ||
@@ -275,3 +276,3 @@ }); | ||
groupToMatchToMatchEntryMapMap: new Map(), | ||
queryDict: {}, | ||
queryMap: new Map(), | ||
pathMap: new Map(), | ||
@@ -302,5 +303,5 @@ }); | ||
get $current(): RouteBuilder<TGroupName> { | ||
let {pathMap, queryDict} = this._source; | ||
let {pathMap, queryMap} = this._source; | ||
return new RouteBuilder(pathMap, queryDict, this); | ||
return new RouteBuilder(pathMap, queryMap, this); | ||
} | ||
@@ -313,5 +314,5 @@ | ||
get $next(): RouteBuilder<TGroupName> { | ||
let {pathMap, queryDict} = this._matchingSource; | ||
let {pathMap, queryMap} = this._matchingSource; | ||
return new RouteBuilder(pathMap, queryDict, this); | ||
return new RouteBuilder(pathMap, queryMap, this); | ||
} | ||
@@ -379,3 +380,3 @@ | ||
$(route: RouteMatchShared | string, params?: GeneralParamDict): RouteBuilder { | ||
let {pathMap, queryDict} = this._source; | ||
let {pathMap, queryMap} = this._source; | ||
@@ -390,7 +391,7 @@ let buildingPart = | ||
return new RouteBuilder(pathMap, queryDict, this, [buildingPart]); | ||
return new RouteBuilder(pathMap, queryMap, this, [buildingPart]); | ||
} | ||
$scratch(): RouteBuilder<TGroupName> { | ||
return new RouteBuilder(new Map(), {}, this); | ||
return new RouteBuilder(new Map(), new Map(), this); | ||
} | ||
@@ -462,3 +463,3 @@ | ||
let queryDict = parseSearch(search); | ||
let queryMap = parseSearch(search); | ||
@@ -475,7 +476,7 @@ let pathMap = new Map<string | undefined, string>(); | ||
if (!hasOwnProperty(queryDict, key)) { | ||
if (!queryMap.has(key)) { | ||
continue; | ||
} | ||
let path = queryDict[key]; | ||
let path = queryMap.get(key); | ||
@@ -486,3 +487,3 @@ if (path) { | ||
delete queryDict[key]; | ||
queryMap.delete(key); | ||
} | ||
@@ -553,8 +554,22 @@ | ||
let matchingSource = this._matchingSource; | ||
runInAction(() => { | ||
Object.assign(this._matchingSource, { | ||
groupToMatchToMatchEntryMapMap, | ||
queryDict, | ||
pathMap, | ||
}); | ||
matchingSource.groupToMatchToMatchEntryMapMap = groupToMatchToMatchEntryMapMap; | ||
matchingSource.pathMap = pathMap; | ||
let matchingQueryKeyToIdMap = groupToRouteMatchMap.get(undefined)!.$next | ||
.$rest._queryKeyToIdMap; | ||
matchingSource.queryMap = new Map( | ||
_.compact( | ||
Array.from(queryMap).map(([key, value]): | ||
| [string, RouteSourceQuery] | ||
| undefined => | ||
matchingQueryKeyToIdMap.has(key) | ||
? [key, {id: matchingQueryKeyToIdMap.get(key)!, value}] | ||
: undefined, | ||
), | ||
), | ||
); | ||
}); | ||
@@ -730,3 +745,3 @@ | ||
source.queryDict = matchingSource.queryDict; | ||
source.queryMap = matchingSource.queryMap; | ||
@@ -891,3 +906,3 @@ for (let group of generalGroups) { | ||
exact, | ||
query, | ||
query: queryDict, | ||
children, | ||
@@ -902,2 +917,12 @@ extension, | ||
let query = new Map( | ||
Object.entries(queryDict ?? {}).map(([key, id]): [ | ||
string, | ||
string | symbol, | ||
] => [ | ||
key, | ||
typeof id === 'boolean' ? Symbol(`query:${routeName}.${key}`) : id, | ||
]), | ||
); | ||
let options: RouteMatchOptions = { | ||
@@ -904,0 +929,0 @@ match, |
@@ -5,3 +5,3 @@ import {Dict} from 'tslang'; | ||
$match?: string | RegExp; | ||
$query?: Dict<boolean>; | ||
$query?: Dict<string | symbol | true>; | ||
/** | ||
@@ -8,0 +8,0 @@ * Whether to allow exact match while if this route has children. Only |
@@ -10,2 +10,6 @@ declare class URLSearchParams { | ||
interface Console { | ||
debug(message?: any, ...optionalParams: any[]): void; | ||
log(message?: any, ...optionalParams: any[]): void; | ||
info(message?: any, ...optionalParams: any[]): void; | ||
warn(message?: any, ...optionalParams: any[]): void; | ||
error(message?: any, ...optionalParams: any[]): void; | ||
@@ -12,0 +16,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
196649
4250