UNPKG

@v4fire/client

Version:

V4Fire client core library

181 lines (149 loc) 3.98 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ import { canParseStr, systemRouteParams, transitionOptions } from 'core/router/const'; import type { TransitionOptions, AnyRoute, PurifiedRoute, RouteParamsFilter, PlainRoute, WatchableRoute } from 'core/router/interface'; /** * Normalizes the specified transitions options and returns a new object * * @param data * * @example * ```js * // {query: {bla: 1}, params: {id: null}} * normalizeTransitionOpts({query: {bla: '1'}, params: {id: 'null'}}); * ``` */ export function normalizeTransitionOpts(data: Nullable<TransitionOptions>): CanUndef<TransitionOptions> { if (!data) { return; } let isEmptyData = true; for (let keys = Object.keys(data), i = 0; i < keys.length; i++) { if (Object.size(data[keys[i]]) > 0) { isEmptyData = false; break; } } if (isEmptyData) { return; } const normalizedData = Object.mixin<Dictionary>(true, {}, Object.select(data, transitionOptions)); const normalizer = (data, key?, parent?) => { if (data == null) { return; } if (Object.isArray(data)) { for (let i = 0; i < data.length; i++) { normalizer(data[i], i, data); } return; } if (Object.isDictionary(data)) { for (let keys = Object.keys(data), i = 0; i < keys.length; i++) { const key = keys[i]; normalizer(data[key], key, data); } return; } if (parent != null) { const strVal = String(data); if (canParseStr.test(strVal)) { parent[key] = Object.isString(data) ? Object.parse(data) : data; } else { const numVal = Number(data); parent[key] = isNaN(data) || strVal !== String(numVal) ? strVal : numVal; } } }; normalizer(normalizedData.params); normalizer(normalizedData.query); return normalizedData; } /** * Returns a common representation of the specified route * @param params */ export function purifyRoute<T extends AnyRoute>(params: Nullable<T>): PurifiedRoute<T> { if (params) { return convertRouteToPlainObject(params, (el, key) => !key.startsWith('_') && systemRouteParams[key] !== true); } return {}; } /** * Returns a blank route object from the specified * @param route */ export function getBlankRouteFrom(route: Nullable<AnyRoute | TransitionOptions>): PurifiedRoute<AnyRoute> { return Object.mixin(true, route ? purifyRoute(<AnyRoute>route) : undefined, { query: {}, params: {}, meta: {} }); } /** * Converts the specified route object to a plain object and returns it * * @param route * @param [filter] - filter predicate */ export function convertRouteToPlainObject<T extends AnyRoute, FILTER extends string>( route: Nullable<T>, filter?: RouteParamsFilter ): PlainRoute<T, FILTER> { const res = {}; if (!route) { return res; } // eslint-disable-next-line guard-for-in for (const key in route) { const el = route[key]; if (filter && !filter(el, key)) { continue; } if (!Object.isFunction(el)) { (<Dictionary>res)[key] = el; } } return res; } /** * Converts the specified route object to a plain object and returns it. * All properties from the prototype are skipped. * * @param route */ export function convertRouteToPlainObjectWithoutProto<T extends AnyRoute>(route: Nullable<T>): PlainRoute<T> { const res = {}; if (route) { for (let keys = Object.keys(route).sort(), i = 0; i < keys.length; i++) { const key = keys[i], el = route[key]; if (key.startsWith('_')) { continue; } if (!Object.isFunction(el)) { res[key] = el; } } } return res; } /** * Returns a plain object based on the specified route without non-comparing parameters * @param route */ export function getComparableRouteParams<T extends AnyRoute>(route: Nullable<T>): WatchableRoute<T> { return convertRouteToPlainObject<T, 'meta'>(route, (el, key) => key !== 'meta' && !key.startsWith('_')); }