query-params-store
Version:
[](https://travis-ci.org/IliaIdakiev/query-param-store)
1 lines • 62.7 kB
Source Map (JSON)
{"version":3,"file":"query-params-store.mjs","sources":["../../../projects/query-params-store/src/lib/tokens.ts","../../../projects/query-params-store/src/lib/utils.ts","../../../projects/query-params-store/src/lib/query-params-store.service.ts","../../../projects/query-params-store/src/lib/query-params-store.module.ts","../../../projects/query-params-store/src/public-api.ts","../../../projects/query-params-store/src/query-params-store.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport const QPS_CONFIG = new InjectionToken('QPS_CONFIG');\n","import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string';\n\nexport function binaryToNumber(...args: any[]) {\n if (args.length === 1 && Array.isArray(args[0])) { args = args[0]; }\n return args.reduce((acc, curr, index) => {\n if (!curr) { return acc; }\n return acc + Math.pow(2, index);\n }, 0);\n}\n\nexport function compress(queryParams: object) {\n return compressToEncodedURIComponent(JSON.stringify(queryParams));\n}\n\nexport function decompress(compression: string) {\n try {\n return JSON.parse(decompressFromEncodedURIComponent(compression)!);\n } catch {\n return null;\n }\n}\n","import { Injectable, OnDestroy, Inject } from '@angular/core';\nimport {\n Router,\n NavigationStart,\n ActivationEnd,\n ActivatedRouteSnapshot,\n RoutesRecognized,\n RouterStateSnapshot,\n NavigationCancel,\n NavigationEnd,\n ResolveStart\n} from '@angular/router';\nimport { ReplaySubject, Subscription, Observable, of as observableOf, of, ConnectableObservable, defer } from 'rxjs';\nimport {\n map,\n filter,\n tap,\n distinctUntilChanged,\n withLatestFrom,\n first,\n pairwise,\n publishReplay,\n switchMap,\n mapTo\n} from 'rxjs/operators';\nimport {\n IAllowedValuesConfig,\n IQueryParamsStoreConfig,\n IStateConfig,\n QueryParamsStoreDefaultValue,\n IQueryParamsStoreModuleConfig\n} from './interfaces-and-types';\nimport { decompressFromEncodedURIComponent } from 'lz-string';\nimport { QPS_CONFIG } from './tokens';\nimport { compress } from './utils';\n\ntype SelectorFn<T> = (a: any) => T;\nconst NOT_PRESENT = Symbol('NOT_PRESENT');\n\nfunction booleanTypeConverter(val: any) {\n if (['true', 1, '1', true].includes(val)) { return true; }\n if (['false', 0, '0', false].includes(val)) { return false; }\n return Boolean(val);\n}\n\n@Injectable()\nexport class QueryParamsStore<T = any> implements OnDestroy {\n\n private snapshot = new ReplaySubject<ActivatedRouteSnapshot | null>(2);\n private subscription!: Subscription;\n private url!: string;\n private fullUrl!: string;\n private prevFullUrl!: string;\n private redirectUrl!: string | null;\n\n private isInDebugMode = false;\n private useCompression = false;\n private compressionKey: string | null = null;\n\n store!: Observable<T>;\n\n private getConvertBinaryBooleanResult(value: any, stateConfigLength: number) {\n value = +value;\n if (isNaN(value)) { return { isConvertedCorrectly: false }; }\n\n const binaryBooleanStringArray = value.toString(2).split('');\n const isOverflowing = binaryBooleanStringArray.length > stateConfigLength;\n let binaryBooleanResult: ('true' | 'false')[] = binaryBooleanStringArray.slice(0, stateConfigLength).map((val: string) => `${val === '1'}`).reverse();\n\n if (binaryBooleanResult.length < stateConfigLength) {\n binaryBooleanResult = binaryBooleanResult.concat(new Array(stateConfigLength - binaryBooleanResult.length).fill('false'));\n }\n\n const booleanResult = binaryBooleanResult.map(v => this.getConvertValueResult(v, Boolean));\n\n return { binaryBooleanResult: booleanResult, isConvertedCorrectly: true, isOverflowing };\n }\n\n private getConvertValueResult(value: any, typeConvertor: typeof Boolean | typeof Number | typeof String | typeof booleanTypeConverter) {\n const isTypeConverterBoolean = typeConvertor === Boolean || typeConvertor === booleanTypeConverter;\n const isBoolean = ['true', 'false'].includes(value) && isTypeConverterBoolean;\n const convertedValue = typeConvertor === String && typeof value === 'string' ? value :\n typeConvertor(value === 'true' ? 1 : value === 'false' ? 0 : value);\n const isValidNumber = typeConvertor === Number && !Number.isNaN(convertedValue);\n const isValidString = typeConvertor === String && typeof convertedValue === 'string';\n const isValidBoolean = isTypeConverterBoolean && typeof convertedValue === 'boolean';\n\n const hasValidConversion = isValidNumber || isValidString || isValidBoolean;\n return {\n hasValidConversion,\n convertedValue,\n invalidRawConversion: (isTypeConverterBoolean && !isBoolean || typeConvertor === Number && isNaN(typeConvertor(value)))\n };\n }\n\n private getTypeConverter(stateConfig: any) {\n if (stateConfig.typeConvertor) {\n return stateConfig.typeConvertor === Boolean ? booleanTypeConverter : stateConfig.typeConvertor;\n }\n const stateConfigValueType = typeof (stateConfig.value ? stateConfig.value : stateConfig);\n if (stateConfigValueType === 'number') { return Number; }\n if (stateConfigValueType === 'boolean') { return booleanTypeConverter; }\n return String;\n }\n\n private parseStateConfig<A = any>(config: IStateConfig<A>) {\n return Object.entries(config).reduce((acc, [key, configForKey]: [string, unknown]) => {\n\n if (configForKey === null || Array.isArray(configForKey)) {\n // remove invalid configuration\n if (this.isInDebugMode) {\n console.warn(`Query Params Store: Invalid configuration for parameter key: ${key}! (nulls or arrays are not supported)`);\n }\n return acc;\n }\n\n const typeConvertor = this.getTypeConverter(configForKey);\n const isObjectConfig = typeof configForKey === 'object';\n\n if (!isObjectConfig) {\n // the case when the property is just a value (page: 1 or filter: 'something')\n acc[key] = { value: configForKey, originalValue: configForKey, typeConvertor, multi: false };\n return acc;\n }\n\n if (!configForKey.hasOwnProperty('value')) {\n // missing the value property => remove invalid configuration\n if (this.isInDebugMode) { console.warn(`Query Params Store: Invalid configuration for parameter key ${key}! (value is missing)`); }\n return acc;\n }\n\n let value = (configForKey as any).value;\n const originalValue = value;\n\n if (!['number', 'string', 'boolean'].includes(typeof value) && value !== null) {\n // value is not in the supported type => remove invalid configuration\n if (this.isInDebugMode) {\n // tslint:disable-next-line:max-line-length\n console.warn(`Query Params Store: Invalid value configuration for parameter key ${key}! (value can be number, string, boolean or null)`);\n }\n return acc;\n }\n\n const useCompression = (configForKey as any).useCompression || false;\n const isMultiValueConfig = (configForKey as any).multi || false;\n const multiCount = isMultiValueConfig ? (configForKey as any).count : null;\n const isBinaryBoolean = this.isBinaryBoolean({ value, typeConvertor, multi: isMultiValueConfig });\n\n if (isBinaryBoolean) {\n const configForKeyLength = !configForKey.hasOwnProperty('length') ? undefined : +(configForKey as any).length;\n value = value.toString(2).split('').slice(0, configForKeyLength).map((val: string) => `${val === '1'}`).reverse();\n\n if (value.length < (configForKeyLength || 0)) {\n value = value.concat(new Array(configForKeyLength! - value.length).fill('false'));\n }\n } else if (isMultiValueConfig && value !== null) {\n if (typeof value !== 'string' && !isBinaryBoolean) {\n // value should be a string and if we need multiple values we should use the given separator\n // tslint:disable-next-line:max-line-length\n if (this.isInDebugMode) { console.warn(`Query Params Store: Invalid configuration for parameter key ${key}! (value should be a string)`); }\n return acc;\n }\n\n value = isBinaryBoolean ?\n value : value === '' ?\n [] : (value as string).split((configForKey as any).separator || ';');\n\n const difference = (!multiCount || isBinaryBoolean) ? 0 : +multiCount - value.length;\n if (difference > 0) {\n for (let i = 0; i < difference; i++) {\n value.push(typeConvertor === String ? '' : typeConvertor === Number ? 0 : false);\n }\n }\n }\n\n if (Array.isArray(value)) { value = value.map(typeConvertor); }\n\n acc[key] = {\n ...(configForKey as any),\n typeConvertor,\n originalValue,\n value,\n multi: isMultiValueConfig,\n multiCount,\n useCompression,\n separator: (configForKey as any).separator || ';'\n };\n\n return acc;\n }, {} as any);\n }\n\n private isBinaryBoolean(cfg: any) {\n return cfg.multi && typeof cfg.value === 'number' &&\n (cfg.typeConvertor === Boolean || cfg.typeConvertor === booleanTypeConverter);\n }\n\n private getSnapshotData(snapshot: ActivatedRouteSnapshot) {\n const defaultStoreConfig = { stateConfig: {}, noQueryParams: false, removeUnknown: false };\n let storeConfig: IQueryParamsStoreConfig = snapshot.data && snapshot.data['storeConfig'] || defaultStoreConfig;\n const inherit = storeConfig.inherit || false;\n\n if (inherit) {\n // iterate over all route data configs and merge the store configs (priority is from the bottom up)\n storeConfig = snapshot.pathFromRoot.slice(0, -1).reduceRight((acc, curr) => {\n const currentData = curr.data;\n if (!currentData || !currentData['storeConfig']) { return acc; }\n const { stateConfig: accumulatedStateConfig, ...accumulatedStoreConfigOptions } = acc;\n const { stateConfig: currentStateConfig, ...currentStoreConfigOptions } = currentData['storeConfig'];\n\n if (this.isInDebugMode) {\n const accumulatedStateKeys = Object.keys(accumulatedStateConfig || {});\n const currentStateKeys = Object.keys(currentStateConfig || {});\n\n const accumulatedStoreKeys = Object.keys(accumulatedStoreConfigOptions);\n const currentStoreKeys = Object.keys(currentStoreConfigOptions);\n\n const storeKeysIntersection = accumulatedStoreKeys.filter(x => currentStoreKeys.includes(x));\n const stateKeysIntersection = accumulatedStateKeys.filter(x => currentStateKeys.includes(x));\n\n // tslint:disable-next-line:max-line-length\n if (storeKeysIntersection.length > 0) { console.warn(`Query Params Store: parameter keys ${storeKeysIntersection} were overridden`); }\n // tslint:disable-next-line:max-line-length\n if (stateKeysIntersection.length > 0) { console.warn(`Query Params Store: parameter keys ${stateKeysIntersection} were overridden`); }\n }\n\n return {\n ...currentStoreConfigOptions,\n ...accumulatedStoreConfigOptions,\n stateConfig: { ...currentStateConfig, ...accumulatedStateConfig }\n };\n }, storeConfig);\n }\n\n const noQueryParams = storeConfig.noQueryParams || false;\n let snapshotQueryParams = snapshot.queryParams;\n if (this.useCompression) {\n const key: string = this.compressionKey || 'q';\n const compressedString = key === '#' ? snapshot.fragment : snapshotQueryParams[key];\n if (compressedString) {\n const decompressedString = decompressFromEncodedURIComponent(compressedString);\n try {\n snapshotQueryParams = JSON.parse(decompressedString!);\n } catch {\n if (this.isInDebugMode) { console.warn(`Query Params Store: Can't decompress provided value!`); }\n snapshotQueryParams = {};\n }\n }\n }\n\n const stateConfig = this.parseStateConfig(storeConfig.stateConfig || {});\n const removeUnknown = storeConfig.removeUnknown || false;\n const caseSensitive = storeConfig.hasOwnProperty('caseSensitive') ? storeConfig.caseSensitive : true;\n\n const allQueryParamsNames = Array.from(new Set(Object.keys(snapshotQueryParams).concat(Object.keys(stateConfig))));\n const allQueryParams = allQueryParamsNames.reduce((acc, queryParamName) => {\n acc[queryParamName] = snapshotQueryParams[queryParamName] || NOT_PRESENT;\n return acc;\n }, {} as any);\n\n\n return { noQueryParams, storeConfig, removeUnknown, caseSensitive, allQueryParams, stateConfig };\n }\n\n private constructStore(snpsht?: ActivatedRouteSnapshot): Observable<T> {\n const stream$ = (snpsht ? of(null, snpsht) : this.snapshot).pipe(\n pairwise(),\n filter(val => !this.redirectUrl || !!val[1]),\n switchMap(s => snpsht ? [s] : this.router.events.pipe(\n // emit the store if we are in the resolve phase (the guard checks passed) or catch the case\n // if we are just changing a query paramter in an already resolved route (watch for the NavigationEnd)\n first(e => e instanceof ResolveStart || e instanceof NavigationEnd), mapTo(s)),\n\n ),\n map(([prevSnapshot, snapshot]) => {\n if (!snapshot?.data) { return {}; }\n const {\n stateConfig,\n noQueryParams,\n caseSensitive,\n removeUnknown,\n allQueryParams\n } = this.getSnapshotData(snapshot);\n\n if (noQueryParams && Object.keys(snapshot.queryParams).length !== 0) { this.router.navigateByUrl(this.url); return null; }\n\n const queryParamsResult = Object.entries(allQueryParams).reduce((queryParams: Record<string, any>, [paramKey, paramValue]: [string, any]) => {\n // if we have caseSensitive: false we have to skip the NOT_PRESENT set when allQueryParams is generated\n if (paramValue === NOT_PRESENT && queryParams[paramKey]) { return queryParams; }\n\n let stateConfigForParam = stateConfig[paramKey] as any;\n paramValue = paramValue === NOT_PRESENT ? NOT_PRESENT : decodeURIComponent(paramValue);\n\n if (!stateConfigForParam && caseSensitive === false) {\n const stateConfigKeys = Object.keys(stateConfig);\n paramKey = stateConfigKeys.find(objKey => paramKey.toLowerCase() === objKey.toLowerCase())!;\n stateConfigForParam = stateConfig[paramKey];\n }\n\n if (removeUnknown && !stateConfigForParam) {\n if (this.isInDebugMode) { console.warn(`Query Params Store: removing parameter key: ${paramKey} because it's unknown!`); }\n return { ...queryParams, [paramKey]: { storeValue: null, urlValue: null } };\n } else if (!stateConfigForParam) { return { ...queryParams, [paramKey]: { urlValue: paramValue, storeValue: paramValue } }; }\n\n const hasAllowedValuesProperty = stateConfigForParam.hasOwnProperty('allowedValues');\n const isAllowedValuesAnArray = Array.isArray(stateConfigForParam.allowedValues);\n\n const allowedValues = hasAllowedValuesProperty && isAllowedValuesAnArray ?\n stateConfigForParam.allowedValues : null;\n\n if (hasAllowedValuesProperty && !isAllowedValuesAnArray && this.isInDebugMode) {\n console.warn(`Query Params Store: ignoring allowed values for parameter key: ${paramKey} since it's not an array!`);\n }\n\n const typeConvertor = stateConfigForParam.typeConvertor;\n // const value = paramValue !== NOT_PRESENT ? +paramValue : NaN;\n const isBinaryBoolean = this.isBinaryBoolean({\n value: stateConfigForParam.originalValue,\n multi: stateConfigForParam.multi,\n typeConvertor\n });\n const stateConfigLength = stateConfigForParam.length;\n const paramConfigValue = stateConfigForParam.hasOwnProperty('value') ? stateConfigForParam.value : stateConfigForParam;\n\n if (paramValue === NOT_PRESENT) {\n return { ...queryParams, [paramKey]: { urlValue: NOT_PRESENT, storeValue: paramConfigValue } };\n }\n\n // Binary Boolean Configuration Case\n if (isBinaryBoolean) {\n if (this.isInDebugMode && allowedValues) {\n console.warn(`Query Params Store: Allowed values can't be used with binary boolean values!`);\n }\n const removeInvalid = stateConfigForParam.removeInvalid;\n const isFalseAsString = paramValue === 'false';\n const isTrueAsString = paramValue === 'true';\n const isBooleanAsString = isFalseAsString || isTrueAsString;\n paramValue = isFalseAsString ? 0 : isTrueAsString ? 1 : paramValue;\n const binaryBooleanConversionResult = this.getConvertBinaryBooleanResult(paramValue, stateConfigLength);\n const { binaryBooleanResult, isConvertedCorrectly, isOverflowing } = binaryBooleanConversionResult;\n\n if (!isConvertedCorrectly || (isOverflowing && removeInvalid)) {\n if (this.isInDebugMode) {\n if (isOverflowing) {\n // tslint:disable-next-line:max-line-length\n console.warn(`Query Params Store: removing parameter key: ${paramKey} since ${paramValue} converted to boolean ${binaryBooleanResult.map(r => r.convertedValue).join(',')} is longer than the configured length of ${stateConfigLength} and the property removeInvalid is set to true!`);\n } else {\n // tslint:disable-next-line:max-line-length\n console.warn(`Query Params Store: Config value ${paramValue} for parameter key ${paramKey} can't be converted correctly so its replaced with the one from the configuration!`);\n }\n }\n const defaultValue = { storeValue: paramConfigValue, urlValue: null };\n return { ...queryParams, [paramKey]: defaultValue };\n }\n\n\n return {\n ...queryParams,\n [paramKey]: {\n storeValue: binaryBooleanResult?.map(r => r.convertedValue),\n urlValue: paramValue,\n isNewUrlValue: isBooleanAsString\n }\n };\n }\n\n // const isMultiToMultiParamTransition = !!(stateConfigForParam.multi && prevSnapshot && prevSnapshot.data\n // && prevSnapshot.data.storeConfig && prevSnapshot.data.storeConfig.stateConfig &&\n // prevSnapshot.data.storeConfig.stateConfig[paramKey] && prevSnapshot.data.storeConfig.stateConfig[paramKey].multi);\n\n // Multi Value Configuration Case\n if (stateConfigForParam.multi) {\n\n // const isSingleToMultiParamTransition = !!(prevSnapshot && prevSnapshot.data\n // && prevSnapshot.data.storeConfig && prevSnapshot.data.storeConfig.stateConfig &&\n // prevSnapshot.data.storeConfig.stateConfig[paramKey] && !prevSnapshot.data.storeConfig.stateConfig[paramKey].multi);\n\n let conversionResults: {\n hasValidConversion: boolean;\n convertedValue: string | number | boolean;\n invalidRawConversion: boolean;\n }[] = paramValue.split(stateConfigForParam.separator)\n .map((v: string) => this.getConvertValueResult(v, typeConvertor));\n\n const multiCount = typeof stateConfigForParam.multiCount === 'number' ?\n stateConfigForParam.multiCount : paramConfigValue && typeof paramConfigValue.length === 'number' ?\n paramConfigValue.length : conversionResults.length || 0;\n\n const difference = isBinaryBoolean ? 0 : +multiCount - conversionResults.length;\n if (difference > 0) {\n for (let i = 0; i < difference; i++) {\n // if we have difference in the lengths of the value of the parameter then we either use the default value\n // provided in the config for the selected index or just use a default one\n const conversionResultsIndex = conversionResults.length + i;\n const hasDefaultValueArrayIndex = paramConfigValue.length > conversionResultsIndex;\n\n conversionResults.push({\n hasValidConversion: true, convertedValue: hasDefaultValueArrayIndex ? paramConfigValue[conversionResultsIndex] :\n typeConvertor === String ? '' : typeConvertor === Number ? 0 : false,\n invalidRawConversion: false\n });\n }\n } else if (difference < 0) { conversionResults = conversionResults.slice(0, difference); }\n\n const checkResult = conversionResults.map(v => {\n if (!v.hasValidConversion) { return 'invalid'; }\n if (allowedValues && !allowedValues.includes(v.convertedValue)) { return 'not-allowed'; }\n return null;\n });\n const hasInvalidValue = checkResult.includes('invalid');\n const hasNotAllowedValue = checkResult.includes('not-allowed');\n\n if (hasInvalidValue || hasNotAllowedValue) {\n if (this.isInDebugMode) {\n if (hasInvalidValue) {\n // tslint:disable-next-line:max-line-length\n console.warn(`Query Params Store: parameter key ${paramKey} with value: ${paramValue} can't be converted correctly!`);\n } else {\n // tslint:disable-next-line:max-line-length\n console.warn(`Query Params Store: parameter key ${paramKey} with value: ${paramValue} is not found in the allowed values ${allowedValues}!`);\n }\n }\n const defaultValue = { storeValue: paramConfigValue, urlValue: null };\n return { ...queryParams, [paramKey]: defaultValue };\n }\n\n const invalidURLValue = !!conversionResults.find(r => r.invalidRawConversion);\n const storeValue = conversionResults.map(r => r.convertedValue);\n // here we also provide the difference so if it's > 0 we can correctly redirect bellow\n return { ...queryParams, [paramKey]: { urlValue: paramValue, storeValue, difference, invalidURLValue } };\n }\n\n // Default (string, number, boolean) Value Configuration Case\n {\n // when using strings hasValidConversion can be true because '10;10' is a valid string so we need to know if we are having\n // a multi to single transition in order to be able to redirect the the correct url\n const isMultiToSingleParamTransition = !!(!stateConfigForParam.multi && prevSnapshot && prevSnapshot.data\n && prevSnapshot.data['storeConfig'] && prevSnapshot.data['storeConfig'].stateConfig &&\n prevSnapshot.data['storeConfig'].stateConfig[paramKey] && prevSnapshot.data['storeConfig'].stateConfig[paramKey].multi);\n\n let isValidMultiToSingle = false;\n let invalidURLValue = false;\n let conversionResult = this.getConvertValueResult(paramValue, typeConvertor);\n if ((!conversionResult.hasValidConversion && prevSnapshot && prevSnapshot.data) || isMultiToSingleParamTransition) {\n const { stateConfig: prevStateConfig, allQueryParams: allPrevQueryParams } = this.getSnapshotData(prevSnapshot);\n const prevStateConfigForKey = prevStateConfig[paramKey];\n if (prevStateConfigForKey && prevStateConfigForKey.multi) {\n paramValue = allPrevQueryParams[paramKey] ?\n allPrevQueryParams[paramKey].split(prevStateConfig[paramKey].separator)[0] :\n prevStateConfig[paramKey].value[0];\n\n conversionResult = this.getConvertValueResult(paramValue, typeConvertor);\n isValidMultiToSingle = conversionResult.hasValidConversion;\n invalidURLValue = conversionResult.invalidRawConversion;\n }\n }\n\n const isAllowed = allowedValues ? allowedValues.includes(conversionResult.convertedValue) : true;\n if (!conversionResult.hasValidConversion || !isAllowed) {\n if (this.isInDebugMode) {\n if (!isAllowed) {\n // tslint:disable-next-line:max-line-length\n console.warn(`Query Params Store: parameter key: ${paramKey} with value: ${paramValue} is not found in the allowed values ${allowedValues}!`);\n } else {\n console.warn(`Query Params Store: parameter key: ${paramKey} with value: ${paramValue} can't be converted correctly!`);\n }\n }\n const defaultValue = { storeValue: paramConfigValue, urlValue: null };\n return { ...queryParams, [paramKey]: defaultValue };\n }\n const storeValue = conversionResult.convertedValue;\n // if isValidMultiToSingle is true then we need to set isNewUrlValue to true so we can change the URL bellow\n return {\n ...queryParams, [paramKey]: {\n urlValue: paramValue,\n storeValue,\n isNewUrlValue: isValidMultiToSingle,\n invalidURLValue\n }\n };\n }\n\n }, {});\n\n // Redirect if needed and send the new store\n {\n const mustChangeUrl = !!Object.values(queryParamsResult).find(\n (v: any) => v.urlValue === null || v.isNewUrlValue || v.difference || v.invalidURLValue\n );\n\n if (mustChangeUrl) {\n const queryParamsTupleArray = Object.entries(queryParamsResult).reduce(\n (acc, [key, { urlValue, difference, storeValue, isNewUrlValue, invalidURLValue }]: [string, any]) => {\n if (isNewUrlValue || invalidURLValue || ![null, NOT_PRESENT].includes(urlValue)) {\n const currentConfig = stateConfig[key];\n if (!currentConfig) { return acc; }\n const separator = currentConfig.separator;\n if (invalidURLValue) {\n urlValue = currentConfig.multi ? storeValue.join(separator) : storeValue;\n difference = 0;\n }\n if (typeof difference === 'number' && difference !== 0) {\n const currentUrlValueArray = urlValue.split(separator);\n if (difference > 0) {\n for (let i = 0; i < difference; i++) {\n urlValue = `${urlValue}${separator}${storeValue[currentUrlValueArray.length + i]}`;\n }\n } else {\n urlValue = `${currentUrlValueArray.slice(0, difference).join(separator)}`;\n }\n }\n return acc.concat([[key, urlValue]]);\n }\n return acc;\n }, [] as any\n );\n\n let redirectUrl = null;\n\n if (this.useCompression) {\n const queryParamsObject = queryParamsTupleArray.reduce((acc: Record<string, any>, [key, value]: [string, any]) => {\n acc[key] = value;\n return acc;\n }, {} as Record<string, any>);\n const compressedQueryParams = compress(queryParamsObject);\n const compressionKey: string = this.compressionKey || 'q';\n const anchorCompressionKey = compressionKey === '#';\n redirectUrl = `${anchorCompressionKey ? this.url.split('#')[0] : this.url}${queryParamsTupleArray.length > 0 ?\n anchorCompressionKey ? `#${compressedQueryParams}` : `?${compressionKey}=${compressedQueryParams}` : ''}`;\n } else {\n const queryParamsArray = queryParamsTupleArray.reduce((acc: string[], [key, value]: [string, any]) => acc.concat(`${key}=${value}`), [] as string[]);\n redirectUrl = `${this.url}${queryParamsTupleArray.length > 0 ? '?' + queryParamsArray.join('&') : ''}`;\n }\n this.router.navigateByUrl(redirectUrl);\n this.redirectUrl = redirectUrl;\n return undefined;\n }\n\n const store = Object.entries(queryParamsResult).reduce((acc, [key, data]: [string, any]) => {\n acc[key] = data.storeValue;\n return acc;\n }, {} as Record<string, any>);\n return store;\n }\n\n }),\n ).pipe(filter(val => !!val));\n\n return stream$ as any;\n }\n\n constructor(public router: Router, @Inject(QPS_CONFIG) config: IQueryParamsStoreModuleConfig) {\n this.snapshot.next(null);\n this.isInDebugMode = !!config && !!config.debug;\n this.useCompression = !!config && !!config.useCompression;\n this.compressionKey = !!config && config.compressionKey || null;\n }\n\n public _constructHandler() {\n if (this.subscription) { return; }\n this.subscription = this.router.events.pipe(\n filter(event => !(event instanceof ActivationEnd)),\n tap(event => {\n if (event instanceof NavigationStart) {\n this.prevFullUrl = this.fullUrl || '';\n this.fullUrl = event.url;\n this.url = decodeURIComponent(/[^?]+/.exec(event.url)![0]);\n } else if (event instanceof RoutesRecognized) {\n this.url = decodeURIComponent(/[^?]+/.exec(event.urlAfterRedirects)![0]);\n } else if (event instanceof NavigationCancel) {\n this.fullUrl = this.prevFullUrl;\n } else if (event instanceof NavigationEnd) {\n this.redirectUrl = null;\n }\n }),\n filter(event => !!(event as any).snapshot),\n map(event => {\n let currSnapshot = (event as any).snapshot;\n while (currSnapshot && currSnapshot.children.length !== 0) {\n currSnapshot = currSnapshot.children.find((childSnapshot: any) => {\n return this.url === '/' && childSnapshot.url.length === 0\n || !!childSnapshot.url.find((segment: any) => this.url.includes(segment.path));\n });\n }\n return currSnapshot;\n }),\n filter(val => !!val),\n distinctUntilChanged()\n ).subscribe(this.snapshot);\n\n this.store = this.constructStore().pipe(publishReplay(1));\n (this.store as ConnectableObservable<T>).connect();\n }\n\n select<R = any>(\n selector: string | SelectorFn<R>,\n disableDistinctUntilChanged: boolean = false,\n compare?: (x: any, y: any) => boolean,\n ): Observable<R> {\n return defer(() => {\n const fn = typeof selector === 'function' ? selector : (state: any) => state[selector];\n let select = this.store.pipe(map(fn));\n if (!disableDistinctUntilChanged) {\n select = select.pipe(distinctUntilChanged(compare));\n }\n return select;\n })\n }\n\n first<R>(selector?: string | SelectorFn<R>, predicate?: null, defaultValue?: R) {\n selector = selector || (s => s);\n return this.select(selector).pipe(first(predicate, defaultValue));\n }\n\n private _match(\n snapshot: ActivatedRouteSnapshot,\n allowedValues: IAllowedValuesConfig | Observable<IAllowedValuesConfig>,\n navigateTo?: string,\n isDeactivate = false\n ): Observable<boolean> {\n if (!(allowedValues instanceof Observable)) { allowedValues = observableOf(allowedValues); }\n if (navigateTo === this.fullUrl) {\n throw new Error('Navigating to the same route will result into infinite loop!');\n }\n return this.constructStore(snapshot).pipe(\n withLatestFrom(allowedValues),\n map(([queryParams, allowedValuesObj]) => {\n let successfulMatch = true;\n let redirectQueryParams = {};\n for (const [name, value] of Object.entries(queryParams as any)) {\n const config = allowedValuesObj[name];\n if (!config) { continue; }\n const { match, default: defaultValue } = config;\n const isCurrentMatch = (Array.isArray(match) ? match.includes(value as any) : value === match);\n if (!isCurrentMatch && defaultValue) {\n redirectQueryParams = { ...redirectQueryParams, [name]: defaultValue };\n }\n successfulMatch = successfulMatch && isCurrentMatch;\n }\n if (!successfulMatch && typeof navigateTo === 'string') {\n if (navigateTo !== this.prevFullUrl) { this.router.navigateByUrl(navigateTo); }\n }\n return successfulMatch;\n }),\n );\n }\n\n canActivate(allowedValues: IAllowedValuesConfig | Observable<IAllowedValuesConfig>, currentSnapshot: ActivatedRouteSnapshot) {\n return this._match(currentSnapshot, allowedValues, this.prevFullUrl).pipe(first());\n }\n\n canDeactivate(\n allowedValues: IAllowedValuesConfig | Observable<IAllowedValuesConfig>,\n currentSnapshot: ActivatedRouteSnapshot,\n routerSnapshot: RouterStateSnapshot,\n ) {\n return this._match(currentSnapshot, allowedValues, routerSnapshot.url, true).pipe(first());\n }\n\n ngOnDestroy() {\n this.subscription.unsubscribe();\n }\n}\n","import { NgModule, ModuleWithProviders, Provider } from '@angular/core';\nimport { QueryParamsStore } from './query-params-store.service';\nimport { Router } from '@angular/router';\nimport { IQueryParamsStoreModuleConfig } from './interfaces-and-types';\nimport { QPS_CONFIG } from './tokens';\n\nexport function qpsFactory(router: Router, config: IQueryParamsStoreModuleConfig) {\n const instance = new QueryParamsStore(router, config);\n return instance;\n}\n\nexport const serviceProvider: Provider = {\n provide: QueryParamsStore,\n useFactory: qpsFactory,\n deps: [Router, QPS_CONFIG],\n};\n\n@NgModule({\n declarations: [],\n providers: [\n { provide: QPS_CONFIG, useValue: null },\n serviceProvider\n ],\n imports: [],\n exports: []\n})\nexport class QueryParamsStoreModule {\n static withConfig(config: IQueryParamsStoreModuleConfig): ModuleWithProviders<QueryParamsStoreModule> {\n return {\n ngModule: QueryParamsStoreModule,\n providers: [\n { provide: QPS_CONFIG, useValue: config },\n serviceProvider\n ]\n };\n }\n\n constructor(qps: QueryParamsStore) {\n qps._constructHandler();\n }\n}\n","/*\n * Public API Surface of query-params-store\n */\n\nexport * from './lib/query-params-store.service';\nexport * from './lib/query-params-store.module';\nexport * from './lib/interfaces-and-types';\nexport * from './lib/utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["observableOf","i1.QueryParamsStore"],"mappings":"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