ropegeo-common 1.1.2 → 1.1.4
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/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/types/api/getRoutePreview/pagePreview.d.ts +2 -0
- package/dist/types/api/getRoutePreview/pagePreview.d.ts.map +1 -1
- package/dist/types/api/getRoutePreview/pagePreview.js +2 -0
- package/dist/types/api/search/regionPreview.d.ts +3 -1
- package/dist/types/api/search/regionPreview.d.ts.map +1 -1
- package/dist/types/api/search/regionPreview.js +13 -0
- package/dist/types/api/search/searchCursor.d.ts +17 -0
- package/dist/types/api/search/searchCursor.d.ts.map +1 -0
- package/dist/types/api/search/searchCursor.js +58 -0
- package/dist/types/api/search/searchParams.d.ts +34 -0
- package/dist/types/api/search/searchParams.d.ts.map +1 -0
- package/dist/types/api/search/searchParams.js +153 -0
- package/dist/types/api/search/searchResults.d.ts +3 -1
- package/dist/types/api/search/searchResults.d.ts.map +1 -1
- package/dist/types/api/search/searchResults.js +8 -0
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export { RoutesGeojson } from './types/api/getRoutes/routeGeojson';
|
|
|
7
7
|
export type { RopewikiImageView } from './types/api/getRopewikiPageView/ropewikiImageView';
|
|
8
8
|
export type { RopewikiBetaSectionView } from './types/api/getRopewikiPageView/ropewikiBetaSectionView';
|
|
9
9
|
export type { RopewikiPageView } from './types/api/getRopewikiPageView/ropewikiPageView';
|
|
10
|
-
export
|
|
11
|
-
export
|
|
10
|
+
export { RegionPreview } from './types/api/search/regionPreview';
|
|
11
|
+
export { SearchCursor } from './types/api/search/searchCursor';
|
|
12
|
+
export type { SearchCursorType } from './types/api/search/searchCursor';
|
|
13
|
+
export { SearchParams } from './types/api/search/searchParams';
|
|
14
|
+
export type { SearchOrder } from './types/api/search/searchParams';
|
|
15
|
+
export { SearchResults } from './types/api/search/searchResults';
|
|
12
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACtH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACjG,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,YAAY,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AACvG,YAAY,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AACzF,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACtH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACjG,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,YAAY,EAAE,uBAAuB,EAAE,MAAM,yDAAyD,CAAC;AACvG,YAAY,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RoutesGeojson = exports.RouteType = exports.Route = exports.PagePreview = exports.PermitStatus = exports.DifficultyWater = exports.DifficultyTime = exports.DifficultyTechnical = exports.DifficultyRisk = exports.Difficulty = exports.PageDataSource = void 0;
|
|
3
|
+
exports.SearchResults = exports.SearchParams = exports.SearchCursor = exports.RegionPreview = exports.RoutesGeojson = exports.RouteType = exports.Route = exports.PagePreview = exports.PermitStatus = exports.DifficultyWater = exports.DifficultyTime = exports.DifficultyTechnical = exports.DifficultyRisk = exports.Difficulty = exports.PageDataSource = void 0;
|
|
4
4
|
var pageDataSource_1 = require("./types/pageDataSource");
|
|
5
5
|
Object.defineProperty(exports, "PageDataSource", { enumerable: true, get: function () { return pageDataSource_1.PageDataSource; } });
|
|
6
6
|
var difficulty_1 = require("./types/difficulty");
|
|
@@ -18,3 +18,11 @@ Object.defineProperty(exports, "Route", { enumerable: true, get: function () { r
|
|
|
18
18
|
Object.defineProperty(exports, "RouteType", { enumerable: true, get: function () { return route_1.RouteType; } });
|
|
19
19
|
var routeGeojson_1 = require("./types/api/getRoutes/routeGeojson");
|
|
20
20
|
Object.defineProperty(exports, "RoutesGeojson", { enumerable: true, get: function () { return routeGeojson_1.RoutesGeojson; } });
|
|
21
|
+
var regionPreview_1 = require("./types/api/search/regionPreview");
|
|
22
|
+
Object.defineProperty(exports, "RegionPreview", { enumerable: true, get: function () { return regionPreview_1.RegionPreview; } });
|
|
23
|
+
var searchCursor_1 = require("./types/api/search/searchCursor");
|
|
24
|
+
Object.defineProperty(exports, "SearchCursor", { enumerable: true, get: function () { return searchCursor_1.SearchCursor; } });
|
|
25
|
+
var searchParams_1 = require("./types/api/search/searchParams");
|
|
26
|
+
Object.defineProperty(exports, "SearchParams", { enumerable: true, get: function () { return searchParams_1.SearchParams; } });
|
|
27
|
+
var searchResults_1 = require("./types/api/search/searchResults");
|
|
28
|
+
Object.defineProperty(exports, "SearchResults", { enumerable: true, get: function () { return searchResults_1.SearchResults; } });
|
|
@@ -25,6 +25,8 @@ export interface GetRopewikiPagePreviewRow {
|
|
|
25
25
|
* Used by GET /route/{routeId}/preview.
|
|
26
26
|
*/
|
|
27
27
|
export declare class PagePreview {
|
|
28
|
+
/** Discriminator for search results: always 'page' */
|
|
29
|
+
readonly previewType: "page";
|
|
28
30
|
/** Page identifier (e.g. RopewikiPage id) */
|
|
29
31
|
id: string;
|
|
30
32
|
/** Source of the page (e.g. ropewiki) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagePreview.d.ts","sourceRoot":"","sources":["../../../../src/types/api/getRoutePreview/pagePreview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,WAAW;IACpB,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,iDAAiD;IACjD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oDAAoD;IACpD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2IAA2I;IAC3I,UAAU,EAAE,UAAU,CAAC;IACvB,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,yDAAyD;IACzD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0DAA0D;IAC1D,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;gBAGxB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,MAAM,EAAE,YAAY,GAAG,IAAI;IAe/B;;OAEG;IACH,MAAM,CAAC,SAAS,CACZ,GAAG,EAAE,yBAAyB,EAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,OAAO,CAAC,EAAE,MAAM,EAAE,GACnB,WAAW;IAsBd,OAAO,CAAC,MAAM,CAAC,WAAW;CAK7B"}
|
|
1
|
+
{"version":3,"file":"pagePreview.d.ts","sourceRoot":"","sources":["../../../../src/types/api/getRoutePreview/pagePreview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,WAAW;IACpB,sDAAsD;IACtD,QAAQ,CAAC,WAAW,EAAG,MAAM,CAAU;IACvC,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,iDAAiD;IACjD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oDAAoD;IACpD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2IAA2I;IAC3I,UAAU,EAAE,UAAU,CAAC;IACvB,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,yDAAyD;IACzD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0DAA0D;IAC1D,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;gBAGxB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,MAAM,EAAE,YAAY,GAAG,IAAI;IAe/B;;OAEG;IACH,MAAM,CAAC,SAAS,CACZ,GAAG,EAAE,yBAAyB,EAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,OAAO,CAAC,EAAE,MAAM,EAAE,GACnB,WAAW;IAsBd,OAAO,CAAC,MAAM,CAAC,WAAW;CAK7B"}
|
|
@@ -10,6 +10,8 @@ const pageDataSource_1 = require("../../pageDataSource");
|
|
|
10
10
|
*/
|
|
11
11
|
class PagePreview {
|
|
12
12
|
constructor(id, source, imageUrl, rating, ratingCount, title, regions, difficulty, mapData, externalLink, permit) {
|
|
13
|
+
/** Discriminator for search results: always 'page' */
|
|
14
|
+
this.previewType = 'page';
|
|
13
15
|
this.id = id;
|
|
14
16
|
this.source = source;
|
|
15
17
|
this.imageUrl = imageUrl;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { PageDataSource } from '../../pageDataSource';
|
|
2
|
-
export
|
|
2
|
+
export declare class RegionPreview {
|
|
3
|
+
readonly previewType: "region";
|
|
3
4
|
id: string;
|
|
4
5
|
name: string;
|
|
5
6
|
parents: string[];
|
|
6
7
|
pageCount: number;
|
|
7
8
|
imageUrl: string | null;
|
|
8
9
|
source: PageDataSource;
|
|
10
|
+
constructor(id: string, name: string, parents: string[], pageCount: number, imageUrl: string | null, source: PageDataSource);
|
|
9
11
|
}
|
|
10
12
|
//# sourceMappingURL=regionPreview.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regionPreview.d.ts","sourceRoot":"","sources":["../../../../src/types/api/search/regionPreview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,
|
|
1
|
+
{"version":3,"file":"regionPreview.d.ts","sourceRoot":"","sources":["../../../../src/types/api/search/regionPreview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,qBAAa,aAAa;IACtB,QAAQ,CAAC,WAAW,EAAG,QAAQ,CAAU;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;gBAGnB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,cAAc;CAS7B"}
|
|
@@ -1,2 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RegionPreview = void 0;
|
|
4
|
+
class RegionPreview {
|
|
5
|
+
constructor(id, name, parents, pageCount, imageUrl, source) {
|
|
6
|
+
this.previewType = 'region';
|
|
7
|
+
this.id = id;
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.parents = parents;
|
|
10
|
+
this.pageCount = pageCount;
|
|
11
|
+
this.imageUrl = imageUrl;
|
|
12
|
+
this.source = source;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.RegionPreview = RegionPreview;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type SearchCursorType = 'page' | 'region';
|
|
2
|
+
/**
|
|
3
|
+
* Cursor for search API pagination. Encodes to base64url for the nextCursor string.
|
|
4
|
+
*/
|
|
5
|
+
export declare class SearchCursor {
|
|
6
|
+
readonly sortKey: number;
|
|
7
|
+
readonly type: SearchCursorType;
|
|
8
|
+
readonly id: string;
|
|
9
|
+
constructor(sortKey: number, type: SearchCursorType, id: string);
|
|
10
|
+
encodeBase64(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Decodes a base64url-encoded cursor string. Throws if the string is invalid
|
|
13
|
+
* or does not represent a valid SearchCursor.
|
|
14
|
+
*/
|
|
15
|
+
static decodeBase64(encoded: string): SearchCursor;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=searchCursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchCursor.d.ts","sourceRoot":"","sources":["../../../../src/types/api/search/searchCursor.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjD;;GAEG;AACH,qBAAa,YAAY;aAED,OAAO,EAAE,MAAM;aACf,IAAI,EAAE,gBAAgB;aACtB,EAAE,EAAE,MAAM;gBAFV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,gBAAgB,EACtB,EAAE,EAAE,MAAM;IAG9B,YAAY,IAAI,MAAM;IAMtB;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;CAmCrD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.SearchCursor = void 0;
|
|
5
|
+
const ENCODING = 'utf8';
|
|
6
|
+
const BASE64URL = 'base64url';
|
|
7
|
+
/**
|
|
8
|
+
* Cursor for search API pagination. Encodes to base64url for the nextCursor string.
|
|
9
|
+
*/
|
|
10
|
+
class SearchCursor {
|
|
11
|
+
constructor(sortKey, type, id) {
|
|
12
|
+
this.sortKey = sortKey;
|
|
13
|
+
this.type = type;
|
|
14
|
+
this.id = id;
|
|
15
|
+
}
|
|
16
|
+
encodeBase64() {
|
|
17
|
+
return Buffer.from(JSON.stringify({ sortKey: this.sortKey, type: this.type, id: this.id }), ENCODING).toString(BASE64URL);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Decodes a base64url-encoded cursor string. Throws if the string is invalid
|
|
21
|
+
* or does not represent a valid SearchCursor.
|
|
22
|
+
*/
|
|
23
|
+
static decodeBase64(encoded) {
|
|
24
|
+
if (typeof encoded !== 'string' || encoded === '') {
|
|
25
|
+
throw new Error('Search cursor must be a non-empty string');
|
|
26
|
+
}
|
|
27
|
+
let decoded;
|
|
28
|
+
try {
|
|
29
|
+
const json = Buffer.from(encoded, BASE64URL).toString(ENCODING);
|
|
30
|
+
decoded = JSON.parse(json);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
34
|
+
throw new Error(`Invalid search cursor encoding: ${message}`);
|
|
35
|
+
}
|
|
36
|
+
if (decoded == null ||
|
|
37
|
+
typeof decoded !== 'object' ||
|
|
38
|
+
!('sortKey' in decoded) ||
|
|
39
|
+
!('type' in decoded) ||
|
|
40
|
+
!('id' in decoded)) {
|
|
41
|
+
throw new Error('Search cursor must be an object with sortKey, type, and id');
|
|
42
|
+
}
|
|
43
|
+
const obj = decoded;
|
|
44
|
+
const type = obj.type;
|
|
45
|
+
if (type !== 'page' && type !== 'region') {
|
|
46
|
+
throw new Error(`Search cursor type must be "page" or "region", got: ${JSON.stringify(type)}`);
|
|
47
|
+
}
|
|
48
|
+
if (typeof obj.id !== 'string') {
|
|
49
|
+
throw new Error(`Search cursor id must be a string, got: ${typeof obj.id}`);
|
|
50
|
+
}
|
|
51
|
+
const sortKey = Number(obj.sortKey);
|
|
52
|
+
if (Number.isNaN(sortKey)) {
|
|
53
|
+
throw new Error(`Search cursor sortKey must be a number, got: ${JSON.stringify(obj.sortKey)}`);
|
|
54
|
+
}
|
|
55
|
+
return new SearchCursor(sortKey, type, obj.id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.SearchCursor = SearchCursor;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SearchCursor } from './searchCursor';
|
|
2
|
+
export type SearchOrder = 'similarity' | 'quality';
|
|
3
|
+
/**
|
|
4
|
+
* Validated search parameters. Cursor is stored decoded (SearchCursor | null).
|
|
5
|
+
* The constructor accepts an encoded cursor string and decodes it.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SearchParams {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly similarityThreshold: number;
|
|
10
|
+
readonly includePages: boolean;
|
|
11
|
+
readonly includeRegions: boolean;
|
|
12
|
+
readonly includeAka: boolean;
|
|
13
|
+
readonly regionId: string | null;
|
|
14
|
+
readonly order: SearchOrder;
|
|
15
|
+
readonly limit: number;
|
|
16
|
+
readonly cursor: SearchCursor | null;
|
|
17
|
+
constructor(name: string, similarityThreshold: number, includePages: boolean, includeRegions: boolean, includeAka: boolean, regionId: string | null, order: SearchOrder, limit: number, cursorEncoded: string | null);
|
|
18
|
+
/**
|
|
19
|
+
* Returns an object suitable for use as query string parameters.
|
|
20
|
+
* Cursor is encoded for the query string.
|
|
21
|
+
*/
|
|
22
|
+
toQueryStringParams(): Record<string, string>;
|
|
23
|
+
/**
|
|
24
|
+
* Parses and validates query string parameters. Throws with a descriptive
|
|
25
|
+
* error message if any value is invalid.
|
|
26
|
+
*/
|
|
27
|
+
static fromQueryStringParams(q: Record<string, string | undefined>): SearchParams;
|
|
28
|
+
/**
|
|
29
|
+
* Parses a boolean from a query string value. Returns defaultValue when value is undefined or empty.
|
|
30
|
+
* Throws when value is a non-empty string that is not "true", "false", "1", or "0" (case-insensitive).
|
|
31
|
+
*/
|
|
32
|
+
private static parseBoolean;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=searchParams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchParams.d.ts","sourceRoot":"","sources":["../../../../src/types/api/search/searchParams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,SAAS,CAAC;AAOnD;;;GAGG;AACH,qBAAa,YAAY;IACrB,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,mBAAmB,EAAE,MAAM,CAAC;IAC5C,SAAgB,YAAY,EAAE,OAAO,CAAC;IACtC,SAAgB,cAAc,EAAE,OAAO,CAAC;IACxC,SAAgB,UAAU,EAAE,OAAO,CAAC;IACpC,SAAgB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,SAAgB,KAAK,EAAE,WAAW,CAAC;IACnC,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,SAAgB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;gBAGxC,IAAI,EAAE,MAAM,EACZ,mBAAmB,EAAE,MAAM,EAC3B,YAAY,EAAE,OAAO,EACrB,cAAc,EAAE,OAAO,EACvB,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,GAAG,IAAI;IAqEhC;;;OAGG;IACH,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAmB7C;;;OAGG;IACH,MAAM,CAAC,qBAAqB,CACxB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC,YAAY;IA2Ff;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;CAY9B"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SearchParams = void 0;
|
|
4
|
+
const searchCursor_1 = require("./searchCursor");
|
|
5
|
+
const DEFAULT_LIMIT = 20;
|
|
6
|
+
/** UUID v4 format: 8-4-4-4-12 hex digits */
|
|
7
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8
|
+
/**
|
|
9
|
+
* Validated search parameters. Cursor is stored decoded (SearchCursor | null).
|
|
10
|
+
* The constructor accepts an encoded cursor string and decodes it.
|
|
11
|
+
*/
|
|
12
|
+
class SearchParams {
|
|
13
|
+
constructor(name, similarityThreshold, includePages, includeRegions, includeAka, regionId, order, limit, cursorEncoded) {
|
|
14
|
+
if (typeof name !== 'string' || name.trim() === '') {
|
|
15
|
+
throw new Error('Missing or empty required query parameter: name');
|
|
16
|
+
}
|
|
17
|
+
if (typeof similarityThreshold !== 'number' ||
|
|
18
|
+
Number.isNaN(similarityThreshold) ||
|
|
19
|
+
similarityThreshold < 0 ||
|
|
20
|
+
similarityThreshold > 1) {
|
|
21
|
+
throw new Error('Query parameter "similarity" must be a number between 0 and 1');
|
|
22
|
+
}
|
|
23
|
+
if (!includePages && !includeRegions) {
|
|
24
|
+
throw new Error('At least one of include-pages or include-regions must be true');
|
|
25
|
+
}
|
|
26
|
+
if (includeAka && !includePages) {
|
|
27
|
+
throw new Error('include-aka cannot be true when include-pages is false');
|
|
28
|
+
}
|
|
29
|
+
if (order !== 'similarity' && order !== 'quality') {
|
|
30
|
+
throw new Error('Query parameter "order" must be one of: similarity, quality');
|
|
31
|
+
}
|
|
32
|
+
const limitNum = Number(limit);
|
|
33
|
+
if (Number.isNaN(limitNum) ||
|
|
34
|
+
!Number.isInteger(limitNum) ||
|
|
35
|
+
limitNum < 1) {
|
|
36
|
+
throw new Error('Query parameter "limit" must be a whole number greater than 0');
|
|
37
|
+
}
|
|
38
|
+
const trimmedRegionId = (regionId !== null && regionId !== '' ? regionId.trim() : null) || null;
|
|
39
|
+
if (trimmedRegionId !== null && !UUID_REGEX.test(trimmedRegionId)) {
|
|
40
|
+
throw new Error('Query parameter "region" must be a valid UUID');
|
|
41
|
+
}
|
|
42
|
+
this.name = name;
|
|
43
|
+
this.similarityThreshold = similarityThreshold;
|
|
44
|
+
this.includePages = includePages;
|
|
45
|
+
this.includeRegions = includeRegions;
|
|
46
|
+
this.includeAka = includeAka;
|
|
47
|
+
this.regionId = trimmedRegionId;
|
|
48
|
+
this.order = order;
|
|
49
|
+
this.limit = limit;
|
|
50
|
+
if (cursorEncoded === null || cursorEncoded === '') {
|
|
51
|
+
this.cursor = null;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
try {
|
|
55
|
+
this.cursor = searchCursor_1.SearchCursor.decodeBase64(cursorEncoded);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new Error('Invalid or malformed query parameter: cursor');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns an object suitable for use as query string parameters.
|
|
64
|
+
* Cursor is encoded for the query string.
|
|
65
|
+
*/
|
|
66
|
+
toQueryStringParams() {
|
|
67
|
+
const params = {
|
|
68
|
+
name: this.name,
|
|
69
|
+
similarity: String(this.similarityThreshold),
|
|
70
|
+
'include-pages': String(this.includePages),
|
|
71
|
+
'include-regions': String(this.includeRegions),
|
|
72
|
+
'include-aka': String(this.includeAka),
|
|
73
|
+
order: this.order,
|
|
74
|
+
limit: String(this.limit),
|
|
75
|
+
};
|
|
76
|
+
if (this.regionId !== null && this.regionId !== '') {
|
|
77
|
+
params.region = this.regionId;
|
|
78
|
+
}
|
|
79
|
+
if (this.cursor !== null) {
|
|
80
|
+
params.cursor = this.cursor.encodeBase64();
|
|
81
|
+
}
|
|
82
|
+
return params;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Parses and validates query string parameters. Throws with a descriptive
|
|
86
|
+
* error message if any value is invalid.
|
|
87
|
+
*/
|
|
88
|
+
static fromQueryStringParams(q) {
|
|
89
|
+
const name = (q.name ?? q.Name ?? '').trim();
|
|
90
|
+
if (!name) {
|
|
91
|
+
throw new Error('Missing or empty required query parameter: name');
|
|
92
|
+
}
|
|
93
|
+
const limitParam = q.limit ?? q.Limit ?? '';
|
|
94
|
+
let limit;
|
|
95
|
+
if (limitParam === '') {
|
|
96
|
+
limit = DEFAULT_LIMIT;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const limitNum = Number(limitParam);
|
|
100
|
+
if (Number.isNaN(limitNum) ||
|
|
101
|
+
!Number.isInteger(limitNum) ||
|
|
102
|
+
limitNum < 1) {
|
|
103
|
+
throw new Error('Query parameter "limit" must be a whole number greater than 0');
|
|
104
|
+
}
|
|
105
|
+
limit = limitNum;
|
|
106
|
+
}
|
|
107
|
+
const cursorRaw = (q.cursor ?? q.Cursor ?? '').trim();
|
|
108
|
+
const cursorEncoded = cursorRaw === '' ? null : cursorRaw;
|
|
109
|
+
const similarityParam = q.similarity ?? q.Similarity ?? '';
|
|
110
|
+
const similarity = similarityParam === '' ? 0.5 : Number(similarityParam);
|
|
111
|
+
const orderParam = (q.order ?? q.Order ?? '').trim().toLowerCase();
|
|
112
|
+
if (orderParam !== '' &&
|
|
113
|
+
orderParam !== 'similarity' &&
|
|
114
|
+
orderParam !== 'quality') {
|
|
115
|
+
throw new Error('Query parameter "order" must be one of: similarity, quality');
|
|
116
|
+
}
|
|
117
|
+
const order = orderParam === 'quality' ? 'quality' : 'similarity';
|
|
118
|
+
const includePages = SearchParams.parseBoolean(q['include-pages'] ?? q['Include-Pages'], true);
|
|
119
|
+
const includeRegions = SearchParams.parseBoolean(q['include-regions'] ?? q['Include-Regions'], true);
|
|
120
|
+
if (!includePages && !includeRegions) {
|
|
121
|
+
throw new Error('At least one of include-pages or include-regions must be true');
|
|
122
|
+
}
|
|
123
|
+
const includeAkaParam = q['include-aka'] ?? q['Include-Aka'];
|
|
124
|
+
const includeAkaExplicit = (includeAkaParam ?? '').trim() !== '';
|
|
125
|
+
let includeAka = SearchParams.parseBoolean(includeAkaParam, true);
|
|
126
|
+
if (!includeAkaExplicit && !includePages) {
|
|
127
|
+
includeAka = false;
|
|
128
|
+
}
|
|
129
|
+
if (includeAkaExplicit && includeAka && !includePages) {
|
|
130
|
+
throw new Error('include-aka cannot be true when include-pages is false');
|
|
131
|
+
}
|
|
132
|
+
const region = (q.region ?? q.Region ?? '').trim() || null;
|
|
133
|
+
if (region !== null && !UUID_REGEX.test(region)) {
|
|
134
|
+
throw new Error('Query parameter "region" must be a valid UUID');
|
|
135
|
+
}
|
|
136
|
+
return new SearchParams(name, similarity, includePages, includeRegions, includeAka, region, order, limit, cursorEncoded);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Parses a boolean from a query string value. Returns defaultValue when value is undefined or empty.
|
|
140
|
+
* Throws when value is a non-empty string that is not "true", "false", "1", or "0" (case-insensitive).
|
|
141
|
+
*/
|
|
142
|
+
static parseBoolean(value, defaultValue) {
|
|
143
|
+
if (value === undefined || value === '')
|
|
144
|
+
return defaultValue;
|
|
145
|
+
const lower = value.toLowerCase().trim();
|
|
146
|
+
if (lower === 'true' || lower === '1')
|
|
147
|
+
return true;
|
|
148
|
+
if (lower === 'false' || lower === '0')
|
|
149
|
+
return false;
|
|
150
|
+
throw new Error(`Query parameter value must be true, false, 1, or 0 (case-insensitive), got: ${JSON.stringify(value)}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.SearchParams = SearchParams;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { PagePreview } from '../getRoutePreview/pagePreview';
|
|
2
2
|
import { RegionPreview } from './regionPreview';
|
|
3
|
-
|
|
3
|
+
import { SearchCursor } from './searchCursor';
|
|
4
|
+
export declare class SearchResults {
|
|
4
5
|
results: (PagePreview | RegionPreview)[];
|
|
5
6
|
nextCursor: string;
|
|
7
|
+
constructor(results: (PagePreview | RegionPreview)[], nextCursorCursor: SearchCursor | null);
|
|
6
8
|
}
|
|
7
9
|
//# sourceMappingURL=searchResults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchResults.d.ts","sourceRoot":"","sources":["../../../../src/types/api/search/searchResults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"searchResults.d.ts","sourceRoot":"","sources":["../../../../src/types/api/search/searchResults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,qBAAa,aAAa;IACtB,OAAO,EAAE,CAAC,WAAW,GAAG,aAAa,CAAC,EAAE,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;gBAEP,OAAO,EAAE,CAAC,WAAW,GAAG,aAAa,CAAC,EAAE,EAAE,gBAAgB,EAAE,YAAY,GAAG,IAAI;CAI9F"}
|
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SearchResults = void 0;
|
|
4
|
+
class SearchResults {
|
|
5
|
+
constructor(results, nextCursorCursor) {
|
|
6
|
+
this.results = results;
|
|
7
|
+
this.nextCursor = nextCursorCursor !== null ? nextCursorCursor.encodeBase64() : '';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.SearchResults = SearchResults;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ropegeo-common",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "Shared types and utilities for RopeGeo and WebScraper",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"repository": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/jest": "^29.5.14",
|
|
19
|
+
"@types/node": "^22.10.0",
|
|
19
20
|
"jest": "^30.2.0",
|
|
20
21
|
"ts-jest": "^29.2.5",
|
|
21
22
|
"typescript": "^5.9.3"
|