ropegeo-common 1.10.1 → 1.10.3
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/dist/models/api/params/routesParams.d.ts +13 -10
- package/dist/models/api/params/routesParams.d.ts.map +1 -1
- package/dist/models/api/params/routesParams.js +126 -75
- package/dist/models/filters/routeFilter.d.ts +10 -6
- package/dist/models/filters/routeFilter.d.ts.map +1 -1
- package/dist/models/filters/routeFilter.js +54 -43
- package/package.json +1 -1
|
@@ -5,28 +5,29 @@ import './registerDifficultyParamsParsers';
|
|
|
5
5
|
import { DifficultyParams } from './difficultyParams';
|
|
6
6
|
/**
|
|
7
7
|
* Validated params for getRoutes (GET /routes).
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* Optional `route-types` query param is a pipe-list of {@link RouteType} values (omit or empty = all types).
|
|
8
|
+
* Either a region scope (`region-id` + `region-source`) or a global source allow-list (`sources`),
|
|
9
|
+
* never both. Optional `route-types` query param is a pipe-list of {@link RouteType} values.
|
|
11
10
|
* Includes page-based `limit` and `page` (defaults {@link PaginationParams.DEFAULT_LIMIT} / {@link PaginationParams.DEFAULT_PAGE}).
|
|
12
11
|
*/
|
|
13
12
|
export declare class RoutesParams extends PaginationParams {
|
|
14
13
|
/**
|
|
15
|
-
* Null when not region-scoped. When set, `source`
|
|
16
|
-
* for that region.
|
|
14
|
+
* Null when not region-scoped. When set, `source` is the single catalogue for that region.
|
|
17
15
|
*/
|
|
18
16
|
readonly region: {
|
|
19
17
|
id: string;
|
|
20
|
-
source: PageDataSource
|
|
18
|
+
source: PageDataSource;
|
|
21
19
|
} | null;
|
|
20
|
+
/** Global source allow-list when not region-scoped; null = all sources. Mutually exclusive with `region`. */
|
|
21
|
+
readonly sources: PageDataSource[] | null;
|
|
22
22
|
/** Null = no route-type filter; non-empty = allow-list (pipe-encoded in query strings as `route-types`). */
|
|
23
23
|
readonly routeTypes: RouteType[] | null;
|
|
24
24
|
readonly difficulty: DifficultyParams | null;
|
|
25
25
|
constructor(options: {
|
|
26
26
|
region: {
|
|
27
27
|
id: string;
|
|
28
|
-
source: PageDataSource
|
|
28
|
+
source: PageDataSource;
|
|
29
29
|
} | null;
|
|
30
|
+
sources?: PageDataSource[] | null;
|
|
30
31
|
routeTypes?: RouteType[] | null;
|
|
31
32
|
difficulty?: DifficultyParams | null;
|
|
32
33
|
limit?: number;
|
|
@@ -34,7 +35,7 @@ export declare class RoutesParams extends PaginationParams {
|
|
|
34
35
|
});
|
|
35
36
|
withPage(page: number): RoutesParams;
|
|
36
37
|
/** Null = all sources; non-empty = allow-list. */
|
|
37
|
-
private static
|
|
38
|
+
private static normalizeSourcesList;
|
|
38
39
|
toQueryString(): string;
|
|
39
40
|
static fromQueryStringParams(q: Record<string, string | undefined>): RoutesParams;
|
|
40
41
|
private static parseLimitQuery;
|
|
@@ -48,10 +49,12 @@ export declare class RoutesParams extends PaginationParams {
|
|
|
48
49
|
private static parseSourcePipe;
|
|
49
50
|
private static parseSourceToken;
|
|
50
51
|
/**
|
|
51
|
-
* Validates a JSON-like object: optional `region` null or `{ id, source }`
|
|
52
|
-
*
|
|
52
|
+
* Validates a JSON-like object: optional `region` null or `{ id, source }` with a single
|
|
53
|
+
* `source` string, optional top-level `region-id` / `region-source`, optional `sources`
|
|
54
|
+
* (string pipe-list or string array). `region` and `sources` must not both be active.
|
|
53
55
|
*/
|
|
54
56
|
static fromResult(result: unknown, requiredRegion?: boolean): RoutesParams;
|
|
57
|
+
private static optionalSourcesFromResult;
|
|
55
58
|
private static paginationFromResult;
|
|
56
59
|
private static optionalPositiveInt;
|
|
57
60
|
private static optionalRouteTypesFromResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routesParams.d.ts","sourceRoot":"","sources":["../../../../src/models/api/params/routesParams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,mCAAmC,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKtD
|
|
1
|
+
{"version":3,"file":"routesParams.d.ts","sourceRoot":"","sources":["../../../../src/models/api/params/routesParams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,mCAAmC,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKtD;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,gBAAgB;IAC9C;;OAEG;IACH,SAAgB,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC;IACtE,6GAA6G;IAC7G,SAAgB,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IACjD,4GAA4G;IAC5G,SAAgB,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC/C,SAAgB,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;gBAExC,OAAO,EAAE;QACjB,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,cAAc,CAAA;SAAE,GAAG,IAAI,CAAC;QACtD,OAAO,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;QAClC,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAChC,UAAU,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;QACrC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB;IAiDD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY;IAWpC,kDAAkD;IAClD,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAcnC,aAAa,IAAI,MAAM;IAgBvB,MAAM,CAAC,qBAAqB,CACxB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC,YAAY;IAgEf,OAAO,CAAC,MAAM,CAAC,eAAe;IAiB9B,OAAO,CAAC,MAAM,CAAC,cAAc;IAY7B,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAOlC,OAAO,CAAC,MAAM,CAAC,cAAc;IAQ7B,0EAA0E;IAC1E,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAcrC,kFAAkF;IAClF,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAUjC,OAAO,CAAC,MAAM,CAAC,eAAe;IAS9B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAU/B;;;;OAIG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,cAAc,UAAQ,GAAG,YAAY;IAkHxE,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAsBxC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAkBnC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAsBlC,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAwB3C,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAkB3C,OAAO,CAAC,MAAM,CAAC,mBAAmB;CAWrC"}
|
|
@@ -10,9 +10,8 @@ const difficultyParams_1 = require("./difficultyParams");
|
|
|
10
10
|
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11
11
|
/**
|
|
12
12
|
* Validated params for getRoutes (GET /routes).
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* Optional `route-types` query param is a pipe-list of {@link RouteType} values (omit or empty = all types).
|
|
13
|
+
* Either a region scope (`region-id` + `region-source`) or a global source allow-list (`sources`),
|
|
14
|
+
* never both. Optional `route-types` query param is a pipe-list of {@link RouteType} values.
|
|
16
15
|
* Includes page-based `limit` and `page` (defaults {@link PaginationParams.DEFAULT_LIMIT} / {@link PaginationParams.DEFAULT_PAGE}).
|
|
17
16
|
*/
|
|
18
17
|
class RoutesParams extends paginationParams_1.PaginationParams {
|
|
@@ -33,19 +32,29 @@ class RoutesParams extends paginationParams_1.PaginationParams {
|
|
|
33
32
|
throw new Error('RoutesParams.region.id must be non-empty when region is set');
|
|
34
33
|
}
|
|
35
34
|
if (!UUID_REGEX.test(id)) {
|
|
36
|
-
throw new Error('Query parameter "region" must be a valid UUID');
|
|
35
|
+
throw new Error('Query parameter "region-id" must be a valid UUID');
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
if (!Object.values(pageDataSource_1.PageDataSource).includes(reg.source)) {
|
|
38
|
+
throw new Error(`Invalid PageDataSource for region: ${JSON.stringify(reg.source)}`);
|
|
39
|
+
}
|
|
40
|
+
regionNorm = { id, source: reg.source };
|
|
41
|
+
}
|
|
42
|
+
const sourcesNorm = RoutesParams.normalizeSourcesList(options.sources ?? null);
|
|
43
|
+
if (regionNorm !== null &&
|
|
44
|
+
sourcesNorm !== null &&
|
|
45
|
+
sourcesNorm.length > 0) {
|
|
46
|
+
throw new Error('RoutesParams: region and sources cannot both be set');
|
|
40
47
|
}
|
|
41
48
|
super(limit, page);
|
|
42
49
|
this.region = regionNorm;
|
|
50
|
+
this.sources = sourcesNorm;
|
|
43
51
|
this.routeTypes = routeTypes;
|
|
44
52
|
this.difficulty = diff;
|
|
45
53
|
}
|
|
46
54
|
withPage(page) {
|
|
47
55
|
return new RoutesParams({
|
|
48
56
|
region: this.region,
|
|
57
|
+
sources: this.sources,
|
|
49
58
|
routeTypes: this.routeTypes,
|
|
50
59
|
difficulty: this.difficulty,
|
|
51
60
|
limit: this.limit,
|
|
@@ -53,7 +62,7 @@ class RoutesParams extends paginationParams_1.PaginationParams {
|
|
|
53
62
|
});
|
|
54
63
|
}
|
|
55
64
|
/** Null = all sources; non-empty = allow-list. */
|
|
56
|
-
static
|
|
65
|
+
static normalizeSourcesList(list) {
|
|
57
66
|
if (list == null || list.length === 0)
|
|
58
67
|
return null;
|
|
59
68
|
const out = [];
|
|
@@ -69,10 +78,11 @@ class RoutesParams extends paginationParams_1.PaginationParams {
|
|
|
69
78
|
toQueryString() {
|
|
70
79
|
const p = new URLSearchParams(super.toQueryString());
|
|
71
80
|
if (this.region !== null) {
|
|
72
|
-
p.set('region', this.region.id);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
p.set('region-id', this.region.id);
|
|
82
|
+
p.set('region-source', this.region.source);
|
|
83
|
+
}
|
|
84
|
+
if (this.sources != null && this.sources.length > 0) {
|
|
85
|
+
p.set('sources', this.sources.join('|'));
|
|
76
86
|
}
|
|
77
87
|
if (this.routeTypes != null && this.routeTypes.length > 0) {
|
|
78
88
|
p.set('route-types', this.routeTypes.join('|'));
|
|
@@ -83,30 +93,45 @@ class RoutesParams extends paginationParams_1.PaginationParams {
|
|
|
83
93
|
static fromQueryStringParams(q) {
|
|
84
94
|
const limit = RoutesParams.parseLimitQuery(q);
|
|
85
95
|
const page = RoutesParams.parsePageQuery(q);
|
|
86
|
-
const
|
|
87
|
-
const
|
|
96
|
+
const regionIdRaw = (q['region-id'] ?? q['Region-Id'] ?? '').trim();
|
|
97
|
+
const regionSourceRaw = (q['region-source'] ??
|
|
98
|
+
q['Region-Source'] ??
|
|
99
|
+
'').trim();
|
|
100
|
+
const sourcesRaw = (q.sources ?? q.Sources ?? '').trim();
|
|
88
101
|
const routeTypesStr = (q['route-types'] ?? q['Route-Types'] ?? '').trim();
|
|
89
102
|
const routeTypes = routeTypesStr === ''
|
|
90
103
|
? null
|
|
91
104
|
: RoutesParams.parseRouteTypePipe(routeTypesStr);
|
|
92
105
|
const difficulty = RoutesParams.normalizeDifficulty(difficultyParams_1.DifficultyParams.fromQueryStringParams(q));
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
const sourcesParsed = sourcesRaw === ''
|
|
107
|
+
? null
|
|
108
|
+
: RoutesParams.parseSourcePipe(sourcesRaw);
|
|
109
|
+
if (regionIdRaw === '') {
|
|
110
|
+
if (regionSourceRaw !== '') {
|
|
111
|
+
throw new Error('Query parameter "region-source" must not be set without "region-id"');
|
|
96
112
|
}
|
|
97
113
|
return new RoutesParams({
|
|
98
114
|
region: null,
|
|
115
|
+
sources: sourcesParsed,
|
|
99
116
|
routeTypes,
|
|
100
117
|
difficulty,
|
|
101
118
|
limit,
|
|
102
119
|
page,
|
|
103
120
|
});
|
|
104
121
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
if (!UUID_REGEX.test(regionIdRaw)) {
|
|
123
|
+
throw new Error('Query parameter "region-id" must be a valid UUID');
|
|
124
|
+
}
|
|
125
|
+
if (regionSourceRaw === '') {
|
|
126
|
+
throw new Error('Query parameter "region-source" is required when "region-id" is set');
|
|
127
|
+
}
|
|
128
|
+
if (sourcesParsed != null && sourcesParsed.length > 0) {
|
|
129
|
+
throw new Error('Query parameters "region-id" / "region-source" cannot be combined with "sources"');
|
|
130
|
+
}
|
|
131
|
+
const regionSource = RoutesParams.parseSourceToken(regionSourceRaw);
|
|
108
132
|
return new RoutesParams({
|
|
109
|
-
region: { id:
|
|
133
|
+
region: { id: regionIdRaw, source: regionSource },
|
|
134
|
+
sources: null,
|
|
110
135
|
routeTypes,
|
|
111
136
|
difficulty,
|
|
112
137
|
limit,
|
|
@@ -189,11 +214,12 @@ class RoutesParams extends paginationParams_1.PaginationParams {
|
|
|
189
214
|
if (s === lower || s === value)
|
|
190
215
|
return s;
|
|
191
216
|
}
|
|
192
|
-
throw new Error(`
|
|
217
|
+
throw new Error(`PageDataSource token must be one of: ${Object.values(pageDataSource_1.PageDataSource).join(', ')}`);
|
|
193
218
|
}
|
|
194
219
|
/**
|
|
195
|
-
* Validates a JSON-like object: optional `region` null or `{ id, source }`
|
|
196
|
-
*
|
|
220
|
+
* Validates a JSON-like object: optional `region` null or `{ id, source }` with a single
|
|
221
|
+
* `source` string, optional top-level `region-id` / `region-source`, optional `sources`
|
|
222
|
+
* (string pipe-list or string array). `region` and `sources` must not both be active.
|
|
197
223
|
*/
|
|
198
224
|
static fromResult(result, requiredRegion = false) {
|
|
199
225
|
if (result == null || typeof result !== 'object') {
|
|
@@ -201,69 +227,94 @@ class RoutesParams extends paginationParams_1.PaginationParams {
|
|
|
201
227
|
}
|
|
202
228
|
const r = result;
|
|
203
229
|
const { limit, page } = RoutesParams.paginationFromResult(r);
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
230
|
+
const flatId = RoutesParams.coerceTrimmedString(r['region-id'] ?? r['Region-Id'], 'region-id');
|
|
231
|
+
const flatSource = RoutesParams.coerceTrimmedString(r['region-source'] ?? r['Region-Source'], 'region-source');
|
|
232
|
+
const rawNested = r.region ?? r.Region;
|
|
233
|
+
if (typeof rawNested === 'string') {
|
|
234
|
+
throw new Error('RoutesParams.region must be an object { id, source } or null, not a string');
|
|
235
|
+
}
|
|
236
|
+
let regionNorm = null;
|
|
237
|
+
const hasFlatRegion = flatId !== '' || flatSource !== '';
|
|
238
|
+
const hasNestedRegion = rawNested !== null &&
|
|
239
|
+
rawNested !== undefined &&
|
|
240
|
+
typeof rawNested === 'object';
|
|
241
|
+
if (hasFlatRegion && hasNestedRegion) {
|
|
242
|
+
throw new Error('RoutesParams: use either nested region or region-id / region-source, not both');
|
|
243
|
+
}
|
|
244
|
+
if (hasFlatRegion) {
|
|
245
|
+
if (flatId === '') {
|
|
246
|
+
throw new Error('RoutesParams.region-id must be non-empty when region-source is set');
|
|
211
247
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
throw new Error('RoutesParams.region.id must be a valid UUID');
|
|
232
|
-
}
|
|
233
|
-
const sourceRaw = reg.source ?? reg.Source;
|
|
234
|
-
let sourceList = null;
|
|
235
|
-
if (sourceRaw === null || sourceRaw === undefined) {
|
|
236
|
-
sourceList = null;
|
|
237
|
-
}
|
|
238
|
-
else if (Array.isArray(sourceRaw)) {
|
|
239
|
-
sourceList = sourceRaw.map((item, i) => {
|
|
240
|
-
if (typeof item !== 'string') {
|
|
241
|
-
throw new Error(`RoutesParams.region.source[${i}] must be a string`);
|
|
242
|
-
}
|
|
243
|
-
return RoutesParams.parseSourceToken(item);
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
else if (typeof sourceRaw === 'string') {
|
|
247
|
-
if (sourceRaw.trim() !== '') {
|
|
248
|
-
sourceList = [RoutesParams.parseSourceToken(sourceRaw.trim())];
|
|
248
|
+
if (!UUID_REGEX.test(flatId)) {
|
|
249
|
+
throw new Error('RoutesParams.region-id must be a valid UUID');
|
|
250
|
+
}
|
|
251
|
+
if (flatSource === '') {
|
|
252
|
+
throw new Error('RoutesParams.region-source must be non-empty when region-id is set');
|
|
253
|
+
}
|
|
254
|
+
regionNorm = {
|
|
255
|
+
id: flatId,
|
|
256
|
+
source: RoutesParams.parseSourceToken(flatSource),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
else if (hasNestedRegion) {
|
|
260
|
+
const reg = rawNested;
|
|
261
|
+
const idStr = RoutesParams.coerceTrimmedString(reg.id ?? reg.Id, 'region.id');
|
|
262
|
+
if (idStr === '') {
|
|
263
|
+
throw new Error('RoutesParams.region must include non-empty id');
|
|
264
|
+
}
|
|
265
|
+
if (!UUID_REGEX.test(idStr)) {
|
|
266
|
+
throw new Error('RoutesParams.region.id must be a valid UUID');
|
|
249
267
|
}
|
|
268
|
+
const sourceRaw = reg.source ?? reg.Source;
|
|
269
|
+
if (sourceRaw === null || sourceRaw === undefined) {
|
|
270
|
+
throw new Error('RoutesParams.region.source must be a non-empty string');
|
|
271
|
+
}
|
|
272
|
+
if (typeof sourceRaw !== 'string' || sourceRaw.trim() === '') {
|
|
273
|
+
throw new Error('RoutesParams.region.source must be a non-empty string');
|
|
274
|
+
}
|
|
275
|
+
regionNorm = {
|
|
276
|
+
id: idStr,
|
|
277
|
+
source: RoutesParams.parseSourceToken(sourceRaw.trim()),
|
|
278
|
+
};
|
|
250
279
|
}
|
|
251
|
-
|
|
252
|
-
throw new Error('RoutesParams
|
|
280
|
+
if (requiredRegion && regionNorm === null) {
|
|
281
|
+
throw new Error('RoutesParams: region must be set when requiredRegion is true');
|
|
282
|
+
}
|
|
283
|
+
const sourcesNorm = RoutesParams.optionalSourcesFromResult(r);
|
|
284
|
+
if (regionNorm !== null &&
|
|
285
|
+
sourcesNorm !== null &&
|
|
286
|
+
sourcesNorm.length > 0) {
|
|
287
|
+
throw new Error('RoutesParams: region and sources cannot both be set');
|
|
253
288
|
}
|
|
254
289
|
const routeTypes = RoutesParams.optionalRouteTypesFromResult(r);
|
|
255
290
|
const difficulty = RoutesParams.normalizeDifficulty(RoutesParams.optionalDifficultyFromResult(r));
|
|
256
291
|
return new RoutesParams({
|
|
257
|
-
region:
|
|
258
|
-
|
|
259
|
-
source: RoutesParams.normalizeSourceList(sourceList),
|
|
260
|
-
},
|
|
292
|
+
region: regionNorm,
|
|
293
|
+
sources: sourcesNorm,
|
|
261
294
|
routeTypes,
|
|
262
295
|
difficulty,
|
|
263
296
|
limit,
|
|
264
297
|
page,
|
|
265
298
|
});
|
|
266
299
|
}
|
|
300
|
+
static optionalSourcesFromResult(r) {
|
|
301
|
+
const v = r.sources ?? r.Sources;
|
|
302
|
+
if (v === null || v === undefined || v === '')
|
|
303
|
+
return null;
|
|
304
|
+
if (typeof v === 'string') {
|
|
305
|
+
return RoutesParams.parseSourcePipe(v);
|
|
306
|
+
}
|
|
307
|
+
if (Array.isArray(v)) {
|
|
308
|
+
const list = v.map((item, i) => {
|
|
309
|
+
if (typeof item !== 'string') {
|
|
310
|
+
throw new Error(`RoutesParams.sources[${i}] must be a string`);
|
|
311
|
+
}
|
|
312
|
+
return RoutesParams.parseSourceToken(item);
|
|
313
|
+
});
|
|
314
|
+
return RoutesParams.normalizeSourcesList(list);
|
|
315
|
+
}
|
|
316
|
+
throw new Error('RoutesParams.sources must be a string, string[], or null');
|
|
317
|
+
}
|
|
267
318
|
static paginationFromResult(r) {
|
|
268
319
|
const limit = RoutesParams.optionalPositiveInt(r.limit ?? r.Limit, 'limit', paginationParams_1.PaginationParams.DEFAULT_LIMIT);
|
|
269
320
|
const page = RoutesParams.optionalPositiveInt(r.page ?? r.Page, 'page', paginationParams_1.PaginationParams.DEFAULT_PAGE);
|
|
@@ -310,10 +361,10 @@ class RoutesParams extends paginationParams_1.PaginationParams {
|
|
|
310
361
|
typeof nested !== 'object') {
|
|
311
362
|
throw new Error('RoutesParams.difficulty must be an object or null');
|
|
312
363
|
}
|
|
313
|
-
const
|
|
364
|
+
const diffInput = nested !== null && nested !== undefined
|
|
314
365
|
? nested
|
|
315
366
|
: r;
|
|
316
|
-
return difficultyParams_1.DifficultyParams.fromResult(
|
|
367
|
+
return difficultyParams_1.DifficultyParams.fromResult(diffInput);
|
|
317
368
|
}
|
|
318
369
|
static coerceTrimmedString(v, key) {
|
|
319
370
|
if (v === null || v === undefined) {
|
|
@@ -5,19 +5,23 @@ import './registerDifficultyFilterOptionsParsers';
|
|
|
5
5
|
import { DifficultyFilterOptions } from './difficultyFilterOptions';
|
|
6
6
|
/**
|
|
7
7
|
* Persisted explore / minimap route filter. Null fields mean “no constraint” on that axis.
|
|
8
|
+
* Maps only to {@link RoutesParams} `sources`, `routeTypes`, and `difficulty` — not `region`.
|
|
8
9
|
*/
|
|
9
10
|
export declare class RouteFilter {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
/** Null/empty = all data sources. */
|
|
12
|
+
sources: PageDataSource[] | null;
|
|
13
|
+
/** Null or empty = no route-type filter (all types). */
|
|
14
|
+
routeTypes: RouteType[] | null;
|
|
13
15
|
difficultyOptions: DifficultyFilterOptions | null;
|
|
14
|
-
constructor(
|
|
16
|
+
constructor(sources?: PageDataSource[] | null, routeTypes?: RouteType[] | null, difficultyOptions?: DifficultyFilterOptions | null);
|
|
15
17
|
toRoutesParams(): RoutesParams;
|
|
16
18
|
toJSON(): Record<string, unknown>;
|
|
17
19
|
toString(): string;
|
|
18
20
|
static fromJsonString(json: string): RouteFilter;
|
|
19
21
|
static fromJSON(parsed: unknown): RouteFilter;
|
|
20
|
-
private static
|
|
21
|
-
private static
|
|
22
|
+
private static normalizeRouteTypesList;
|
|
23
|
+
private static parseRouteTypesField;
|
|
24
|
+
private static parseRouteTypeToken;
|
|
25
|
+
private static parseSourcesField;
|
|
22
26
|
}
|
|
23
27
|
//# sourceMappingURL=routeFilter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routeFilter.d.ts","sourceRoot":"","sources":["../../../src/models/filters/routeFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,0CAA0C,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE
|
|
1
|
+
{"version":3,"file":"routeFilter.d.ts","sourceRoot":"","sources":["../../../src/models/filters/routeFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,0CAA0C,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE;;;GAGG;AACH,qBAAa,WAAW;IACpB,qCAAqC;IACrC,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IACjC,wDAAwD;IACxD,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,uBAAuB,GAAG,IAAI,CAAC;gBAG9C,OAAO,GAAE,cAAc,EAAE,GAAG,IAAW,EACvC,UAAU,GAAE,SAAS,EAAE,GAAG,IAAW,EACrC,iBAAiB,GAAE,uBAAuB,GAAG,IAAW;IAO5D,cAAc,IAAI,YAAY;IAoB9B,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAWjC,QAAQ,IAAI,MAAM;IAIlB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAYhD,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,WAAW;IAc7C,OAAO,CAAC,MAAM,CAAC,uBAAuB;IActC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAiBnC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAOlC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAmBnC"}
|
|
@@ -8,36 +8,24 @@ require("./registerDifficultyFilterOptionsParsers");
|
|
|
8
8
|
const difficultyFilterOptions_1 = require("./difficultyFilterOptions");
|
|
9
9
|
/**
|
|
10
10
|
* Persisted explore / minimap route filter. Null fields mean “no constraint” on that axis.
|
|
11
|
+
* Maps only to {@link RoutesParams} `sources`, `routeTypes`, and `difficulty` — not `region`.
|
|
11
12
|
*/
|
|
12
13
|
class RouteFilter {
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
16
|
-
this.routeType = routeType;
|
|
14
|
+
constructor(sources = null, routeTypes = null, difficultyOptions = null) {
|
|
15
|
+
this.sources = sources;
|
|
16
|
+
this.routeTypes = RouteFilter.normalizeRouteTypesList(routeTypes);
|
|
17
17
|
this.difficultyOptions = difficultyOptions;
|
|
18
18
|
}
|
|
19
19
|
toRoutesParams() {
|
|
20
|
-
const
|
|
21
|
-
? this.regionId.trim()
|
|
22
|
-
: null;
|
|
23
|
-
if (rid === null) {
|
|
24
|
-
if (this.source != null && this.source.length > 0) {
|
|
25
|
-
throw new Error('RouteFilter: source allow-list requires a non-empty regionId');
|
|
26
|
-
}
|
|
27
|
-
return new routesParams_1.RoutesParams({
|
|
28
|
-
region: null,
|
|
29
|
-
routeTypes: this.routeType !== null ? [this.routeType] : null,
|
|
30
|
-
difficulty: this.difficultyOptions !== null
|
|
31
|
-
? this.difficultyOptions.toDifficultyParams()
|
|
32
|
-
: null,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
const src = this.source == null || this.source.length === 0
|
|
20
|
+
const srcList = this.sources == null || this.sources.length === 0
|
|
36
21
|
? null
|
|
37
|
-
: [...this.
|
|
22
|
+
: [...this.sources];
|
|
38
23
|
return new routesParams_1.RoutesParams({
|
|
39
|
-
region:
|
|
40
|
-
|
|
24
|
+
region: null,
|
|
25
|
+
sources: srcList,
|
|
26
|
+
routeTypes: this.routeTypes != null && this.routeTypes.length > 0
|
|
27
|
+
? [...this.routeTypes]
|
|
28
|
+
: null,
|
|
41
29
|
difficulty: this.difficultyOptions !== null
|
|
42
30
|
? this.difficultyOptions.toDifficultyParams()
|
|
43
31
|
: null,
|
|
@@ -45,9 +33,8 @@ class RouteFilter {
|
|
|
45
33
|
}
|
|
46
34
|
toJSON() {
|
|
47
35
|
return {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
routeType: this.routeType,
|
|
36
|
+
sources: this.sources,
|
|
37
|
+
routeTypes: this.routeTypes,
|
|
51
38
|
difficultyOptions: this.difficultyOptions !== null
|
|
52
39
|
? this.difficultyOptions.toJSON()
|
|
53
40
|
: null,
|
|
@@ -71,29 +58,59 @@ class RouteFilter {
|
|
|
71
58
|
throw new Error('RouteFilter must be a JSON object');
|
|
72
59
|
}
|
|
73
60
|
const o = parsed;
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
? null
|
|
77
|
-
: String(o.regionId);
|
|
78
|
-
const routeType = o.routeType === null || o.routeType === undefined
|
|
79
|
-
? null
|
|
80
|
-
: RouteFilter.parseRouteType(o.routeType);
|
|
61
|
+
const sources = RouteFilter.parseSourcesField(o.sources);
|
|
62
|
+
const routeTypes = RouteFilter.parseRouteTypesField(o);
|
|
81
63
|
let difficultyOptions = null;
|
|
82
64
|
if (o.difficultyOptions != null && typeof o.difficultyOptions === 'object') {
|
|
83
65
|
difficultyOptions = difficultyFilterOptions_1.DifficultyFilterOptions.fromResult(o.difficultyOptions);
|
|
84
66
|
}
|
|
85
|
-
return new RouteFilter(
|
|
67
|
+
return new RouteFilter(sources, routeTypes, difficultyOptions);
|
|
86
68
|
}
|
|
87
|
-
static
|
|
69
|
+
static normalizeRouteTypesList(list) {
|
|
70
|
+
if (list == null || list.length === 0)
|
|
71
|
+
return null;
|
|
72
|
+
const out = [];
|
|
73
|
+
for (const t of list) {
|
|
74
|
+
if (!Object.values(routeType_1.RouteType).includes(t)) {
|
|
75
|
+
throw new Error(`Invalid RouteType: ${JSON.stringify(t)}`);
|
|
76
|
+
}
|
|
77
|
+
if (!out.includes(t))
|
|
78
|
+
out.push(t);
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
static parseRouteTypesField(o) {
|
|
83
|
+
const raw = o.routeTypes;
|
|
84
|
+
if (raw === null || raw === undefined) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
if (!Array.isArray(raw)) {
|
|
88
|
+
throw new Error('RouteFilter.routeTypes must be an array or null');
|
|
89
|
+
}
|
|
90
|
+
const types = raw.map((item, i) => {
|
|
91
|
+
if (typeof item !== 'string') {
|
|
92
|
+
throw new Error(`RouteFilter.routeTypes[${i}] must be a string`);
|
|
93
|
+
}
|
|
94
|
+
return RouteFilter.parseRouteTypeToken(item);
|
|
95
|
+
});
|
|
96
|
+
return RouteFilter.normalizeRouteTypesList(types);
|
|
97
|
+
}
|
|
98
|
+
static parseRouteTypeToken(v) {
|
|
99
|
+
if (!Object.values(routeType_1.RouteType).includes(v)) {
|
|
100
|
+
throw new Error(`Invalid RouteType: ${JSON.stringify(v)}`);
|
|
101
|
+
}
|
|
102
|
+
return v;
|
|
103
|
+
}
|
|
104
|
+
static parseSourcesField(v) {
|
|
88
105
|
if (v === null || v === undefined)
|
|
89
106
|
return null;
|
|
90
107
|
if (!Array.isArray(v)) {
|
|
91
|
-
throw new Error('RouteFilter.
|
|
108
|
+
throw new Error('RouteFilter.sources must be an array or null');
|
|
92
109
|
}
|
|
93
110
|
const out = [];
|
|
94
111
|
for (const item of v) {
|
|
95
112
|
if (typeof item !== 'string') {
|
|
96
|
-
throw new Error('RouteFilter.
|
|
113
|
+
throw new Error('RouteFilter.sources entries must be strings');
|
|
97
114
|
}
|
|
98
115
|
if (!Object.values(pageDataSource_1.PageDataSource).includes(item)) {
|
|
99
116
|
throw new Error(`Invalid PageDataSource: ${JSON.stringify(item)}`);
|
|
@@ -104,11 +121,5 @@ class RouteFilter {
|
|
|
104
121
|
}
|
|
105
122
|
return out.length === 0 ? null : out;
|
|
106
123
|
}
|
|
107
|
-
static parseRouteType(v) {
|
|
108
|
-
if (typeof v !== 'string' || !Object.values(routeType_1.RouteType).includes(v)) {
|
|
109
|
-
throw new Error(`Invalid RouteType: ${JSON.stringify(v)}`);
|
|
110
|
-
}
|
|
111
|
-
return v;
|
|
112
|
-
}
|
|
113
124
|
}
|
|
114
125
|
exports.RouteFilter = RouteFilter;
|