@searchspring/snap-url-manager 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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +228 -0
  3. package/dist/cjs/Translators/Noop/NoopTranslator.d.ts +10 -0
  4. package/dist/cjs/Translators/Noop/NoopTranslator.d.ts.map +1 -0
  5. package/dist/cjs/Translators/Noop/NoopTranslator.js +25 -0
  6. package/dist/cjs/Translators/QueryString/QueryStringTranslator.d.ts +35 -0
  7. package/dist/cjs/Translators/QueryString/QueryStringTranslator.d.ts.map +1 -0
  8. package/dist/cjs/Translators/QueryString/QueryStringTranslator.js +267 -0
  9. package/dist/cjs/Translators/Url/UrlTranslator.d.ts +67 -0
  10. package/dist/cjs/Translators/Url/UrlTranslator.d.ts.map +1 -0
  11. package/dist/cjs/Translators/Url/UrlTranslator.js +466 -0
  12. package/dist/cjs/Translators/index.d.ts +4 -0
  13. package/dist/cjs/Translators/index.d.ts.map +1 -0
  14. package/dist/cjs/Translators/index.js +15 -0
  15. package/dist/cjs/UrlManager/UrlManager.d.ts +50 -0
  16. package/dist/cjs/UrlManager/UrlManager.d.ts.map +1 -0
  17. package/dist/cjs/UrlManager/UrlManager.js +301 -0
  18. package/dist/cjs/UrlManager/typecheck.d.ts +5 -0
  19. package/dist/cjs/UrlManager/typecheck.d.ts.map +1 -0
  20. package/dist/cjs/UrlManager/typecheck.js +75 -0
  21. package/dist/cjs/index.d.ts +5 -0
  22. package/dist/cjs/index.d.ts.map +1 -0
  23. package/dist/cjs/index.js +15 -0
  24. package/dist/cjs/linkers/index.d.ts +2 -0
  25. package/dist/cjs/linkers/index.d.ts.map +1 -0
  26. package/dist/cjs/linkers/index.js +13 -0
  27. package/dist/cjs/linkers/react/react.d.ts +8 -0
  28. package/dist/cjs/linkers/react/react.d.ts.map +1 -0
  29. package/dist/cjs/linkers/react/react.js +15 -0
  30. package/dist/cjs/types.d.ts +47 -0
  31. package/dist/cjs/types.d.ts.map +1 -0
  32. package/dist/cjs/types.js +13 -0
  33. package/dist/esm/Translators/Noop/NoopTranslator.d.ts +10 -0
  34. package/dist/esm/Translators/Noop/NoopTranslator.d.ts.map +1 -0
  35. package/dist/esm/Translators/Noop/NoopTranslator.js +20 -0
  36. package/dist/esm/Translators/QueryString/QueryStringTranslator.d.ts +35 -0
  37. package/dist/esm/Translators/QueryString/QueryStringTranslator.d.ts.map +1 -0
  38. package/dist/esm/Translators/QueryString/QueryStringTranslator.js +260 -0
  39. package/dist/esm/Translators/Url/UrlTranslator.d.ts +67 -0
  40. package/dist/esm/Translators/Url/UrlTranslator.d.ts.map +1 -0
  41. package/dist/esm/Translators/Url/UrlTranslator.js +448 -0
  42. package/dist/esm/Translators/index.d.ts +4 -0
  43. package/dist/esm/Translators/index.d.ts.map +1 -0
  44. package/dist/esm/Translators/index.js +3 -0
  45. package/dist/esm/UrlManager/UrlManager.d.ts +50 -0
  46. package/dist/esm/UrlManager/UrlManager.d.ts.map +1 -0
  47. package/dist/esm/UrlManager/UrlManager.js +256 -0
  48. package/dist/esm/UrlManager/typecheck.d.ts +5 -0
  49. package/dist/esm/UrlManager/typecheck.d.ts.map +1 -0
  50. package/dist/esm/UrlManager/typecheck.js +66 -0
  51. package/dist/esm/index.d.ts +5 -0
  52. package/dist/esm/index.d.ts.map +1 -0
  53. package/dist/esm/index.js +3 -0
  54. package/dist/esm/linkers/index.d.ts +2 -0
  55. package/dist/esm/linkers/index.d.ts.map +1 -0
  56. package/dist/esm/linkers/index.js +1 -0
  57. package/dist/esm/linkers/react/react.d.ts +8 -0
  58. package/dist/esm/linkers/react/react.d.ts.map +1 -0
  59. package/dist/esm/linkers/react/react.js +11 -0
  60. package/dist/esm/types.d.ts +47 -0
  61. package/dist/esm/types.d.ts.map +1 -0
  62. package/dist/esm/types.js +10 -0
  63. package/package.json +31 -0
@@ -0,0 +1,260 @@
1
+ import { RangeValueProperties } from '../../types';
2
+ import Immutable from 'seamless-immutable';
3
+ export class QueryStringTranslator {
4
+ constructor(config = {}) {
5
+ this.config = Immutable({
6
+ urlRoot: typeof config.urlRoot == 'string' ? config.urlRoot.replace(/\/$/, '') : '',
7
+ queryParameter: typeof config.queryParameter == 'string' ? config.queryParameter : 'q',
8
+ ...config,
9
+ });
10
+ }
11
+ bindExternalEvents(update) {
12
+ window.addEventListener('popstate', update);
13
+ }
14
+ getCurrentUrl() {
15
+ return location.search || '';
16
+ }
17
+ getConfig() {
18
+ return this.config.asMutable();
19
+ }
20
+ parseQueryString(queryString) {
21
+ const justQueryString = queryString.split('?').pop() || '';
22
+ return justQueryString
23
+ .split('&')
24
+ .filter((v) => v)
25
+ .map((kvPair) => {
26
+ const [key, value] = kvPair.split('=').map((v) => decodeURIComponent(v.replace(/\+/g, ' ')));
27
+ return { key: key.split('.'), value };
28
+ });
29
+ }
30
+ generateQueryString(params) {
31
+ const paramString = params.length
32
+ ? '?' +
33
+ params
34
+ .map((param) => {
35
+ return encodeURIComponent(param.key.join('.')) + '=' + encodeURIComponent(param.value);
36
+ })
37
+ .join('&')
38
+ : this.config.urlRoot
39
+ ? ''
40
+ : location.pathname;
41
+ return `${this.config.urlRoot}${paramString}`;
42
+ }
43
+ parsePage(queryParams) {
44
+ const pageParam = queryParams.find((param) => param.key.length == 1 && param.key[0] == 'page');
45
+ if (!pageParam) {
46
+ return {};
47
+ }
48
+ const page = Number(pageParam.value);
49
+ return !isNaN(page) && page > 1 ? { page } : {};
50
+ }
51
+ parseSort(queryParams) {
52
+ const sortParams = queryParams.filter((param) => param.key.length == 2 && param.key[0] == 'sort');
53
+ if (!sortParams.length) {
54
+ return {};
55
+ }
56
+ return {
57
+ sort: sortParams.map((param) => ({
58
+ field: param.key[1],
59
+ direction: param.value,
60
+ })),
61
+ };
62
+ }
63
+ parseOther(queryParams, except = []) {
64
+ const state = {};
65
+ queryParams
66
+ .filter((param) => except.indexOf(param.key[0]) == -1)
67
+ .forEach((param) => {
68
+ const path = param.key;
69
+ const value = param.value;
70
+ // eslint-disable-next-line prefer-const
71
+ let node = state;
72
+ path.forEach((key, i) => {
73
+ const isLast = i == path.length - 1;
74
+ if (isLast) {
75
+ node[key] = node[key] || [];
76
+ node[key].push(value);
77
+ }
78
+ else {
79
+ node[key] = node[key] || {};
80
+ node = node[key];
81
+ }
82
+ });
83
+ });
84
+ return state;
85
+ }
86
+ parseQuery(queryParams) {
87
+ const qParamKey = this.getConfig().queryParameter;
88
+ const qParam = queryParams.find((param) => param.key.length == 1 && param.key[0] == qParamKey);
89
+ return qParam ? { query: qParam.value } : {};
90
+ }
91
+ parseFilter(queryParams) {
92
+ const valueFilterParams = queryParams.filter((p) => p.key.length == 2 && p.key[0] == 'filter');
93
+ const rangeFilterParams = queryParams.filter((p) => p.key.length == 3 && p.key[0] == 'filter');
94
+ const valueFilters = valueFilterParams.reduce((state, param) => {
95
+ const currentValue = (state.filter || {})[param.key[1]] || [];
96
+ return {
97
+ filter: {
98
+ ...state.filter,
99
+ [param.key[1]]: [...(Array.isArray(currentValue) ? currentValue : [currentValue]), param.value],
100
+ },
101
+ };
102
+ }, {});
103
+ const rangeFilters = rangeFilterParams.reduce((state, param, index) => {
104
+ // ranges should come in pairs!
105
+ // use index to build pairs, ignore non pairs
106
+ // build set as encountered - only return full sets (low + high)
107
+ let newState = state;
108
+ const nextRangeParam = rangeFilterParams[index + 1];
109
+ if (index % 2 == 0 &&
110
+ nextRangeParam &&
111
+ nextRangeParam.key[1] == param.key[1] &&
112
+ param.key[2] == RangeValueProperties.LOW &&
113
+ nextRangeParam.key[2] == RangeValueProperties.HIGH) {
114
+ const currentValue = (state.filter || {})[param.key[1]] || [];
115
+ newState = {
116
+ filter: {
117
+ ...state.filter,
118
+ [param.key[1]]: [
119
+ ...(Array.isArray(currentValue) ? currentValue : [currentValue]),
120
+ {
121
+ [RangeValueProperties.LOW]: +param.value || null,
122
+ [RangeValueProperties.HIGH]: +nextRangeParam.value || null,
123
+ },
124
+ ],
125
+ },
126
+ };
127
+ }
128
+ return newState;
129
+ }, {});
130
+ return {
131
+ ...(valueFilters.filter || rangeFilters.filter
132
+ ? {
133
+ filter: {
134
+ ...valueFilters.filter,
135
+ ...rangeFilters.filter,
136
+ },
137
+ }
138
+ : {}),
139
+ };
140
+ }
141
+ encodePage(state) {
142
+ if (!state.page || state.page === 1) {
143
+ return [];
144
+ }
145
+ return [{ key: ['page'], value: '' + state.page }];
146
+ }
147
+ encodeOther(state, except = []) {
148
+ let params = [];
149
+ const addRecursive = (obj, currentPath) => {
150
+ Object.keys(obj).forEach((key) => {
151
+ if (currentPath.length == 0 && except.indexOf(key) != -1) {
152
+ return;
153
+ }
154
+ const value = obj[key];
155
+ if (value instanceof Array) {
156
+ params = params.concat(value.map((v) => {
157
+ return { key: [...currentPath, key], value: v };
158
+ }));
159
+ }
160
+ else if (typeof value == 'object') {
161
+ addRecursive(value, [...currentPath, key]);
162
+ }
163
+ else {
164
+ params = params.concat([{ key: [...currentPath, key], value }]);
165
+ }
166
+ });
167
+ };
168
+ addRecursive(state, []);
169
+ return params;
170
+ }
171
+ encodeQuery(state) {
172
+ if (!state.query) {
173
+ return [];
174
+ }
175
+ return [
176
+ {
177
+ key: [this.getConfig().queryParameter],
178
+ value: state.query,
179
+ },
180
+ ];
181
+ }
182
+ encodeSort(state) {
183
+ if (!state.sort) {
184
+ return [];
185
+ }
186
+ return (state.sort instanceof Array ? state.sort : [state.sort]).map((sort) => {
187
+ return {
188
+ key: ['sort', sort.field],
189
+ value: sort.direction,
190
+ };
191
+ });
192
+ }
193
+ encodeFilter(state) {
194
+ if (!state.filter) {
195
+ return [];
196
+ }
197
+ return Object.keys(state.filter).flatMap((key) => {
198
+ if (!state.filter || !state.filter[key]) {
199
+ return [];
200
+ }
201
+ const filter = state.filter[key];
202
+ return (filter instanceof Array ? filter : [filter]).flatMap((value) => {
203
+ if (typeof value == 'string' || typeof value == 'number' || typeof value == 'boolean') {
204
+ return [
205
+ {
206
+ key: ['filter', key],
207
+ value: '' + value,
208
+ },
209
+ ];
210
+ }
211
+ else if (typeof value == 'object' &&
212
+ typeof value[RangeValueProperties.LOW] != 'undefined' &&
213
+ typeof value[RangeValueProperties.HIGH] != 'undefined') {
214
+ return [
215
+ {
216
+ key: ['filter', key, RangeValueProperties.LOW],
217
+ value: '' + (value[RangeValueProperties.LOW] ?? '*'),
218
+ },
219
+ {
220
+ key: ['filter', key, RangeValueProperties.HIGH],
221
+ value: '' + (value[RangeValueProperties.HIGH] ?? '*'),
222
+ },
223
+ ];
224
+ }
225
+ return [];
226
+ });
227
+ });
228
+ }
229
+ queryParamsToState(queryParams) {
230
+ // Todo: Special stage storage for sorts
231
+ return {
232
+ ...this.parseQuery(queryParams),
233
+ ...this.parsePage(queryParams),
234
+ ...this.parseFilter(queryParams),
235
+ ...this.parseSort(queryParams),
236
+ ...this.parseOther(queryParams, ['page', this.getConfig().queryParameter, 'filter', 'sort']),
237
+ };
238
+ }
239
+ stateToQueryParams(state = {}) {
240
+ return [
241
+ ...this.encodeQuery(state),
242
+ ...this.encodePage(state),
243
+ ...this.encodeFilter(state),
244
+ ...this.encodeSort(state),
245
+ ...this.encodeOther(state, ['page', 'query', 'filter', 'sort', this.getConfig().queryParameter]),
246
+ ];
247
+ }
248
+ serialize(state) {
249
+ const queryParams = this.stateToQueryParams(state);
250
+ return this.generateQueryString(queryParams);
251
+ }
252
+ deserialize(url) {
253
+ const queryString = url.includes('?') ? (url.split('?').pop() || '').split('#').shift() || '' : '';
254
+ const queryParams = this.parseQueryString(queryString);
255
+ return this.queryParamsToState(queryParams);
256
+ }
257
+ go(url) {
258
+ history.pushState(null, '', url);
259
+ }
260
+ }
@@ -0,0 +1,67 @@
1
+ import { UrlState, Translator, ParamLocationType } from '../../types';
2
+ declare type UrlParameter = {
3
+ key: Array<string>;
4
+ value: string;
5
+ type: ParamLocationType;
6
+ };
7
+ declare type MapOptions = {
8
+ name?: string;
9
+ type?: ParamLocationType;
10
+ };
11
+ declare type CoreMap = {
12
+ query?: MapOptions;
13
+ oq?: MapOptions;
14
+ rq?: MapOptions;
15
+ tag?: MapOptions;
16
+ page?: MapOptions;
17
+ pageSize?: MapOptions;
18
+ sort?: MapOptions;
19
+ filter?: MapOptions;
20
+ };
21
+ declare type CustomMap = {
22
+ [param: string]: {
23
+ type?: ParamLocationType;
24
+ };
25
+ };
26
+ export declare type UrlTranslatorParametersConfig = {
27
+ core?: CoreMap;
28
+ custom?: CustomMap;
29
+ };
30
+ export declare type UrlTranslatorConfig = {
31
+ urlRoot?: string;
32
+ settings?: {
33
+ corePrefix?: string;
34
+ coreType?: ParamLocationType;
35
+ customType?: ParamLocationType;
36
+ rootParams?: boolean;
37
+ };
38
+ parameters?: UrlTranslatorParametersConfig;
39
+ };
40
+ export declare class UrlTranslator implements Translator {
41
+ private config;
42
+ private reverseMapping;
43
+ constructor(config?: UrlTranslatorConfig);
44
+ bindExternalEvents(update: () => void): void;
45
+ getCurrentUrl(): string;
46
+ getConfig(): UrlTranslatorConfig;
47
+ deserialize(url: string): UrlState;
48
+ protected parseUrlParams(url: string): Array<UrlParameter>;
49
+ protected parseQueryString(queryString: string): Array<UrlParameter>;
50
+ protected parseHashString(hashString: string): Array<UrlParameter>;
51
+ protected paramsToState(params: Array<UrlParameter>): UrlState;
52
+ protected parseCoreOther(otherParams: Array<UrlParameter>): UrlState;
53
+ protected parseCoreFilter(filterParams: Array<UrlParameter>): UrlState;
54
+ protected parseCoreSort(sortParams: Array<UrlParameter>): UrlState;
55
+ protected parseOther(otherParams: Array<UrlParameter>): UrlState;
56
+ serialize(state: UrlState): string;
57
+ protected stateToParams(state: UrlState): Array<UrlParameter>;
58
+ protected encodeCoreFilters(state: UrlState): Array<UrlParameter>;
59
+ protected encodeCoreSorts(state: UrlState): Array<UrlParameter>;
60
+ protected encodeCoreOther(state: UrlState, except: string[]): Array<UrlParameter>;
61
+ protected encodeOther(state: UrlState): Array<UrlParameter>;
62
+ go(url: string, config?: {
63
+ history: string;
64
+ }): void;
65
+ }
66
+ export {};
67
+ //# sourceMappingURL=UrlTranslator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UrlTranslator.d.ts","sourceRoot":"","sources":["../../../../src/Translators/Url/UrlTranslator.ts"],"names":[],"mappings":"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"}