howlongtobeat-core 0.1.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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/esm/mod.d.ts +30 -0
  4. package/esm/mod.d.ts.map +1 -0
  5. package/esm/mod.js +31 -0
  6. package/esm/package.json +3 -0
  7. package/esm/src/HowLongToBeat.d.ts +63 -0
  8. package/esm/src/HowLongToBeat.d.ts.map +1 -0
  9. package/esm/src/HowLongToBeat.js +142 -0
  10. package/esm/src/http/client.d.ts +29 -0
  11. package/esm/src/http/client.d.ts.map +1 -0
  12. package/esm/src/http/client.js +250 -0
  13. package/esm/src/parser/json.d.ts +17 -0
  14. package/esm/src/parser/json.d.ts.map +1 -0
  15. package/esm/src/parser/json.js +113 -0
  16. package/esm/src/types.d.ts +179 -0
  17. package/esm/src/types.d.ts.map +1 -0
  18. package/esm/src/types.js +19 -0
  19. package/esm/src/utils/similarity.d.ts +28 -0
  20. package/esm/src/utils/similarity.d.ts.map +1 -0
  21. package/esm/src/utils/similarity.js +127 -0
  22. package/package.json +38 -0
  23. package/script/mod.d.ts +30 -0
  24. package/script/mod.d.ts.map +1 -0
  25. package/script/mod.js +39 -0
  26. package/script/package.json +3 -0
  27. package/script/src/HowLongToBeat.d.ts +63 -0
  28. package/script/src/HowLongToBeat.d.ts.map +1 -0
  29. package/script/src/HowLongToBeat.js +146 -0
  30. package/script/src/http/client.d.ts +29 -0
  31. package/script/src/http/client.d.ts.map +1 -0
  32. package/script/src/http/client.js +258 -0
  33. package/script/src/parser/json.d.ts +17 -0
  34. package/script/src/parser/json.d.ts.map +1 -0
  35. package/script/src/parser/json.js +118 -0
  36. package/script/src/types.d.ts +179 -0
  37. package/script/src/types.d.ts.map +1 -0
  38. package/script/src/types.js +22 -0
  39. package/script/src/utils/similarity.d.ts +28 -0
  40. package/script/src/utils/similarity.d.ts.map +1 -0
  41. package/script/src/utils/similarity.js +133 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # howlongtobeat-core
2
+
3
+ A TypeScript/Deno library to retrieve game completion times from
4
+ [HowLongToBeat.com](https://howlongtobeat.com).
5
+
6
+ [![JSR](https://jsr.io/badges/howlongtobeat-core)](https://jsr.io/howlongtobeat-core)
7
+ [![npm](https://img.shields.io/npm/v/howlongtobeat-core)](https://www.npmjs.com/package/howlongtobeat-core)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ## Features
11
+
12
+ - 🎮 Search games by name or HLTB ID
13
+ - ⏱️ Get completion times (Main Story, Main + Extra, Completionist)
14
+ - 🔍 Dual similarity algorithms (Gestalt & Levenshtein)
15
+ - 🎯 Filter by DLC, mods, or hacks
16
+ - 📦 Works with Deno, Node.js, and browsers
17
+ - 🔒 TypeScript-first with full type definitions
18
+
19
+ ## Installation
20
+
21
+ ### Deno
22
+
23
+ ```typescript
24
+ import { HowLongToBeat } from "jsr:howlongtobeat-core";
25
+ ```
26
+
27
+ ### Node.js / npm
28
+
29
+ ```bash
30
+ npm install howlongtobeat-core
31
+ ```
32
+
33
+ ```typescript
34
+ import { HowLongToBeat } from "howlongtobeat-core";
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ ### Search by Name
40
+
41
+ ```typescript
42
+ import { HowLongToBeat } from "howlongtobeat-core";
43
+
44
+ const hltb = new HowLongToBeat();
45
+ const results = await hltb.search("Elden Ring");
46
+
47
+ if (results && results.length > 0) {
48
+ const game = results[0];
49
+ console.log(`${game.gameName}`);
50
+ console.log(` Main Story: ${game.mainStory} hours`);
51
+ console.log(` Main + Extra: ${game.mainExtra} hours`);
52
+ console.log(` Completionist: ${game.completionist} hours`);
53
+ }
54
+ ```
55
+
56
+ ### Search by ID
57
+
58
+ ```typescript
59
+ const game = await hltb.searchById(68151); // Elden Ring
60
+ console.log(game?.gameName); // "Elden Ring"
61
+ ```
62
+
63
+ ### With Options
64
+
65
+ ```typescript
66
+ const hltb = new HowLongToBeat({
67
+ minimumSimilarity: 0.5, // Filter results below 50% similarity
68
+ autoFilterTimes: true, // Nullify irrelevant times (e.g., SP times for MP-only games)
69
+ similarityAlgorithm: "gestalt", // or "levenshtein"
70
+ });
71
+ ```
72
+
73
+ ### Filter DLC/Mods
74
+
75
+ ```typescript
76
+ import { HowLongToBeat, SearchModifiers } from "howlongtobeat-core";
77
+
78
+ const hltb = new HowLongToBeat();
79
+ const dlcOnly = await hltb.search("Dark Souls", SearchModifiers.ISOLATE_DLC);
80
+ ```
81
+
82
+ ## API Reference
83
+
84
+ ### `HowLongToBeat`
85
+
86
+ #### Constructor Options
87
+
88
+ | Option | Type | Default | Description |
89
+ | --------------------- | ---------------------------- | ----------- | ------------------------------------------------------ |
90
+ | `minimumSimilarity` | `number` | `0.4` | Filter results below this similarity threshold (0-1) |
91
+ | `autoFilterTimes` | `boolean` | `false` | Auto-nullify irrelevant time fields based on game type |
92
+ | `similarityAlgorithm` | `"gestalt" \| "levenshtein"` | `"gestalt"` | Algorithm for string similarity matching |
93
+
94
+ #### Methods
95
+
96
+ | Method | Returns | Description |
97
+ | ------------------------- | --------------------------------------- | -------------------- |
98
+ | `search(name, modifier?)` | `Promise<HowLongToBeatEntry[] \| null>` | Search games by name |
99
+ | `searchById(id)` | `Promise<HowLongToBeatEntry \| null>` | Get game by HLTB ID |
100
+
101
+ ### `HowLongToBeatEntry`
102
+
103
+ | Property | Type | Description |
104
+ | ------------------ | ------------------ | ---------------------------- |
105
+ | `gameId` | `number` | HLTB game ID |
106
+ | `gameName` | `string \| null` | Game title |
107
+ | `gameImageUrl` | `string \| null` | Cover image URL |
108
+ | `gameWebLink` | `string` | Link to HLTB page |
109
+ | `mainStory` | `number \| null` | Main story time (hours) |
110
+ | `mainExtra` | `number \| null` | Main + extras time (hours) |
111
+ | `completionist` | `number \| null` | 100% completion time (hours) |
112
+ | `allStyles` | `number \| null` | Average of all playstyles |
113
+ | `similarity` | `number` | Match similarity (0-1) |
114
+ | `reviewScore` | `number \| null` | User review score |
115
+ | `profilePlatforms` | `string[] \| null` | Available platforms |
116
+ | `releaseWorld` | `number \| null` | Release year |
117
+
118
+ ### `SearchModifiers`
119
+
120
+ | Value | Description |
121
+ | --------------- | --------------------- |
122
+ | `NONE` | No filter (default) |
123
+ | `ISOLATE_DLC` | Only show DLC |
124
+ | `ISOLATE_MODS` | Only show mods |
125
+ | `ISOLATE_HACKS` | Only show hacks |
126
+ | `HIDE_DLC` | Hide DLC from results |
127
+
128
+ ## Development
129
+
130
+ ```bash
131
+ # Run tests
132
+ deno task test
133
+
134
+ # Run unit tests only
135
+ deno task test:unit
136
+
137
+ # Run integration tests (requires network)
138
+ deno task test:integration
139
+
140
+ # Type check
141
+ deno task check
142
+
143
+ # Format code
144
+ deno task fmt
145
+
146
+ # Lint
147
+ deno task lint
148
+ ```
149
+
150
+ ## Credits
151
+
152
+ This is a TypeScript port of
153
+ [ScrappyCocco/HowLongToBeat-PythonAPI](https://github.com/ScrappyCocco/HowLongToBeat-PythonAPI).
154
+
155
+ ## License
156
+
157
+ MIT © 2026
package/esm/mod.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * HowLongToBeat API for Deno/Node.js
3
+ *
4
+ * A TypeScript wrapper for the HowLongToBeat.com website.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { HowLongToBeat, SearchModifiers } from "@tapan/howlongtobeat";
9
+ *
10
+ * const hltb = new HowLongToBeat({ minimumSimilarity: 0.5 });
11
+ *
12
+ * // Search by name
13
+ * const results = await hltb.search("Elden Ring");
14
+ * console.log(results?.[0]?.mainStory); // e.g., 50.5 hours
15
+ *
16
+ * // Search by ID
17
+ * const game = await hltb.searchById(10270);
18
+ * console.log(game?.gameName); // "Elden Ring"
19
+ *
20
+ * // Filter DLC
21
+ * const dlcOnly = await hltb.search("Dark Souls", SearchModifiers.ISOLATE_DLC);
22
+ * ```
23
+ *
24
+ * @module
25
+ */
26
+ export { HowLongToBeat } from "./src/HowLongToBeat.js";
27
+ export { SearchModifiers } from "./src/types.js";
28
+ export type { HowLongToBeatEntry, HowLongToBeatOptions, SimilarityAlgorithm } from "./src/types.js";
29
+ export { calculateSimilarity, gestaltSimilarity, levenshteinSimilarity } from "./src/utils/similarity.js";
30
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGpG,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC"}
package/esm/mod.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * HowLongToBeat API for Deno/Node.js
3
+ *
4
+ * A TypeScript wrapper for the HowLongToBeat.com website.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { HowLongToBeat, SearchModifiers } from "@tapan/howlongtobeat";
9
+ *
10
+ * const hltb = new HowLongToBeat({ minimumSimilarity: 0.5 });
11
+ *
12
+ * // Search by name
13
+ * const results = await hltb.search("Elden Ring");
14
+ * console.log(results?.[0]?.mainStory); // e.g., 50.5 hours
15
+ *
16
+ * // Search by ID
17
+ * const game = await hltb.searchById(10270);
18
+ * console.log(game?.gameName); // "Elden Ring"
19
+ *
20
+ * // Filter DLC
21
+ * const dlcOnly = await hltb.search("Dark Souls", SearchModifiers.ISOLATE_DLC);
22
+ * ```
23
+ *
24
+ * @module
25
+ */
26
+ // Main class
27
+ export { HowLongToBeat } from "./src/HowLongToBeat.js";
28
+ // Types and enums
29
+ export { SearchModifiers } from "./src/types.js";
30
+ // Utility exports for advanced usage
31
+ export { calculateSimilarity, gestaltSimilarity, levenshteinSimilarity } from "./src/utils/similarity.js";
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Main HowLongToBeat class
3
+ *
4
+ * Provides methods to search for games on HowLongToBeat.com
5
+ */
6
+ import type { HowLongToBeatEntry, HowLongToBeatOptions } from "./types.js";
7
+ import { SearchModifiers } from "./types.js";
8
+ /**
9
+ * HowLongToBeat API wrapper
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const hltb = new HowLongToBeat();
14
+ * const results = await hltb.search("The Witcher 3");
15
+ * console.log(results);
16
+ * ```
17
+ */
18
+ export declare class HowLongToBeat {
19
+ private readonly minimumSimilarity;
20
+ private readonly autoFilterTimes;
21
+ private readonly similarityAlgorithm;
22
+ private readonly similarityCalculator;
23
+ /**
24
+ * Create a new HowLongToBeat instance
25
+ *
26
+ * @param options - Configuration options
27
+ */
28
+ constructor(options?: HowLongToBeatOptions);
29
+ /**
30
+ * Search for games by name
31
+ *
32
+ * @param gameName - The name of the game to search for
33
+ * @param modifier - Optional search modifier to filter results
34
+ * @returns Array of matching games sorted by similarity, or null on error
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const hltb = new HowLongToBeat();
39
+ * const results = await hltb.search("Elden Ring");
40
+ * if (results && results.length > 0) {
41
+ * console.log(`Main story: ${results[0].mainStory} hours`);
42
+ * }
43
+ * ```
44
+ */
45
+ search(gameName: string, modifier?: SearchModifiers): Promise<HowLongToBeatEntry[] | null>;
46
+ /**
47
+ * Search for a game by its HLTB ID
48
+ *
49
+ * @param gameId - The unique game ID on HowLongToBeat
50
+ * @returns The matching game entry, or null if not found
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const hltb = new HowLongToBeat();
55
+ * const game = await hltb.searchById(10270); // Elden Ring
56
+ * if (game) {
57
+ * console.log(`${game.gameName}: ${game.mainStory} hours`);
58
+ * }
59
+ * ```
60
+ */
61
+ searchById(gameId: number): Promise<HowLongToBeatEntry | null>;
62
+ }
63
+ //# sourceMappingURL=HowLongToBeat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HowLongToBeat.d.ts","sourceRoot":"","sources":["../../src/src/HowLongToBeat.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAkB7C;;;;;;;;;GASG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAC1C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAmC;IAExE;;;;OAIG;gBACS,OAAO,GAAE,oBAAyB;IAY9C;;;;;;;;;;;;;;;OAeG;IACG,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,eAAsC,GAC/C,OAAO,CAAC,kBAAkB,EAAE,GAAG,IAAI,CAAC;IAuBvC;;;;;;;;;;;;;;OAcG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CA8CrE"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Main HowLongToBeat class
3
+ *
4
+ * Provides methods to search for games on HowLongToBeat.com
5
+ */
6
+ import { SearchModifiers } from "./types.js";
7
+ import { executeSearch, extractGameTitle, fetchGamePage, } from "./http/client.js";
8
+ import { filterBySimilarity, parseGameEntries } from "./parser/json.js";
9
+ import { createSimilarityCalculator } from "./utils/similarity.js";
10
+ /**
11
+ * Default options for HowLongToBeat
12
+ */
13
+ const DEFAULT_OPTIONS = {
14
+ minimumSimilarity: 0.4,
15
+ autoFilterTimes: false,
16
+ similarityAlgorithm: "gestalt",
17
+ };
18
+ /**
19
+ * HowLongToBeat API wrapper
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const hltb = new HowLongToBeat();
24
+ * const results = await hltb.search("The Witcher 3");
25
+ * console.log(results);
26
+ * ```
27
+ */
28
+ export class HowLongToBeat {
29
+ /**
30
+ * Create a new HowLongToBeat instance
31
+ *
32
+ * @param options - Configuration options
33
+ */
34
+ constructor(options = {}) {
35
+ Object.defineProperty(this, "minimumSimilarity", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: void 0
40
+ });
41
+ Object.defineProperty(this, "autoFilterTimes", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: void 0
46
+ });
47
+ Object.defineProperty(this, "similarityAlgorithm", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: void 0
52
+ });
53
+ Object.defineProperty(this, "similarityCalculator", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: void 0
58
+ });
59
+ this.minimumSimilarity = options.minimumSimilarity ??
60
+ DEFAULT_OPTIONS.minimumSimilarity;
61
+ this.autoFilterTimes = options.autoFilterTimes ??
62
+ DEFAULT_OPTIONS.autoFilterTimes;
63
+ this.similarityAlgorithm = options.similarityAlgorithm ??
64
+ DEFAULT_OPTIONS.similarityAlgorithm;
65
+ this.similarityCalculator = createSimilarityCalculator(this.similarityAlgorithm);
66
+ }
67
+ /**
68
+ * Search for games by name
69
+ *
70
+ * @param gameName - The name of the game to search for
71
+ * @param modifier - Optional search modifier to filter results
72
+ * @returns Array of matching games sorted by similarity, or null on error
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const hltb = new HowLongToBeat();
77
+ * const results = await hltb.search("Elden Ring");
78
+ * if (results && results.length > 0) {
79
+ * console.log(`Main story: ${results[0].mainStory} hours`);
80
+ * }
81
+ * ```
82
+ */
83
+ async search(gameName, modifier = SearchModifiers.NONE) {
84
+ if (!gameName || gameName.trim().length === 0) {
85
+ // TODO: implement proper error handling
86
+ return null;
87
+ }
88
+ const response = await executeSearch(gameName.trim(), modifier);
89
+ if (!response || !response.data) {
90
+ // TODO: implement proper error handling
91
+ return null;
92
+ }
93
+ const entries = parseGameEntries(response.data, gameName, this.autoFilterTimes, this.similarityCalculator);
94
+ return filterBySimilarity(entries, this.minimumSimilarity);
95
+ }
96
+ /**
97
+ * Search for a game by its HLTB ID
98
+ *
99
+ * @param gameId - The unique game ID on HowLongToBeat
100
+ * @returns The matching game entry, or null if not found
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * const hltb = new HowLongToBeat();
105
+ * const game = await hltb.searchById(10270); // Elden Ring
106
+ * if (game) {
107
+ * console.log(`${game.gameName}: ${game.mainStory} hours`);
108
+ * }
109
+ * ```
110
+ */
111
+ async searchById(gameId) {
112
+ if (!gameId || gameId <= 0) {
113
+ // TODO: implement proper error handling
114
+ return null;
115
+ }
116
+ // First, fetch the game page to get the title
117
+ const html = await fetchGamePage(gameId);
118
+ if (!html) {
119
+ // TODO: implement proper error handling
120
+ return null;
121
+ }
122
+ const gameTitle = extractGameTitle(html);
123
+ if (!gameTitle) {
124
+ // TODO: implement proper error handling
125
+ return null;
126
+ }
127
+ // Search using the extracted title
128
+ const response = await executeSearch(gameTitle);
129
+ if (!response || !response.data) {
130
+ // TODO: implement proper error handling
131
+ return null;
132
+ }
133
+ // Find the exact game by ID
134
+ const matchingGame = response.data.find((game) => game.game_id === gameId);
135
+ if (!matchingGame) {
136
+ // TODO: implement proper error handling
137
+ return null;
138
+ }
139
+ const entries = parseGameEntries([matchingGame], gameTitle, this.autoFilterTimes, this.similarityCalculator);
140
+ return entries.length > 0 ? entries[0] : null;
141
+ }
142
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * HTTP client for HowLongToBeat API
3
+ */
4
+ import type { HLTBSearchRequest, HLTBSearchResponse } from "../types.js";
5
+ /**
6
+ * Build search request body
7
+ */
8
+ export declare function buildSearchRequest(searchTerms: string[], modifier?: string, page?: number, size?: number): HLTBSearchRequest;
9
+ /**
10
+ * Execute a search request to HLTB API
11
+ */
12
+ export declare function executeSearch(gameName: string, modifier?: string): Promise<HLTBSearchResponse | null>;
13
+ /**
14
+ * Fetch game page HTML to extract game title
15
+ */
16
+ export declare function fetchGamePage(gameId: number): Promise<string | null>;
17
+ /**
18
+ * Extract game title from HLTB game page HTML
19
+ */
20
+ export declare function extractGameTitle(html: string): string | null;
21
+ /**
22
+ * Get base URL for constructing image and web links
23
+ */
24
+ export declare function getBaseUrl(): string;
25
+ /**
26
+ * Clear cached token and search URL (useful for testing)
27
+ */
28
+ export declare function clearCache(): void;
29
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/src/http/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAqJzE;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EAAE,EACrB,QAAQ,GAAE,MAAW,EACrB,IAAI,GAAE,MAAU,EAChB,IAAI,GAAE,MAAW,GAChB,iBAAiB,CA8BnB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAW,GACpB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAmCpC;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoB1E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY5D;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAIjC"}