@treeviz/familysearch-catalog-sdk 1.0.1
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/LICENSE +21 -0
- package/README.md +329 -0
- package/dist/cache/index.cjs +93 -0
- package/dist/cache/index.d.cts +48 -0
- package/dist/cache/index.d.ts +48 -0
- package/dist/cache/index.js +91 -0
- package/dist/catalog/index.cjs +459 -0
- package/dist/catalog/index.d.cts +143 -0
- package/dist/catalog/index.d.ts +143 -0
- package/dist/catalog/index.js +453 -0
- package/dist/client/index.cjs +773 -0
- package/dist/client/index.d.cts +138 -0
- package/dist/client/index.d.ts +138 -0
- package/dist/client/index.js +771 -0
- package/dist/index-BEg-_3Kd.d.cts +114 -0
- package/dist/index-BEg-_3Kd.d.ts +114 -0
- package/dist/index-BaNFN7C2.d.cts +255 -0
- package/dist/index-BaNFN7C2.d.ts +255 -0
- package/dist/index.cjs +1632 -0
- package/dist/index.d.cts +109 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +1621 -0
- package/dist/parser/index.cjs +119 -0
- package/dist/parser/index.d.cts +1 -0
- package/dist/parser/index.d.ts +1 -0
- package/dist/parser/index.js +111 -0
- package/dist/places/index.cjs +165 -0
- package/dist/places/index.d.cts +69 -0
- package/dist/places/index.d.ts +69 -0
- package/dist/places/index.js +163 -0
- package/package.json +90 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 idavidka and @treeviz contributors
|
|
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,329 @@
|
|
|
1
|
+
# @treeviz/familysearch-catalog-sdk
|
|
2
|
+
|
|
3
|
+
> Part of the [@treeviz](https://www.npmjs.com/org/treeviz) organization - A collection of tools for genealogy data processing and visualization.
|
|
4
|
+
|
|
5
|
+
A modern TypeScript SDK for interacting with the FamilySearch Catalog and Places APIs. This package provides reusable utilities for resolving place names, looking up parish records, and extracting coverage periods from genealogical records.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- πΊοΈ **Places API** - Search and normalize place names
|
|
10
|
+
- π **Catalog API** - Search parish and civil records
|
|
11
|
+
- π **Metadata Parsing** - Extract parish names, date ranges, and registry types
|
|
12
|
+
- πΎ **Smart Caching** - In-memory LRU cache with TTL support
|
|
13
|
+
- π **OAuth Integration** - Reuses `@treeviz/familysearch-sdk` for authentication
|
|
14
|
+
- π **TypeScript-first** - Full type definitions included
|
|
15
|
+
- β‘ **Promise-based** - Modern async/await API
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @treeviz/familysearch-catalog-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { FamilySearchCatalog } from "@treeviz/familysearch-catalog-sdk";
|
|
27
|
+
|
|
28
|
+
// Initialize the resolver
|
|
29
|
+
const resolver = new FamilySearchCatalog({
|
|
30
|
+
clientId: process.env.FS_CLIENT_ID!,
|
|
31
|
+
clientSecret: process.env.FS_CLIENT_SECRET,
|
|
32
|
+
environment: "production",
|
|
33
|
+
enableCache: true,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Resolve a place name
|
|
37
|
+
const result = await resolver.resolvePlace("Kismaros, Hungary");
|
|
38
|
+
|
|
39
|
+
console.log(result);
|
|
40
|
+
// Output:
|
|
41
|
+
// {
|
|
42
|
+
// placeId: "...",
|
|
43
|
+
// standardizedName: "Kismaros, Pest, Hungary",
|
|
44
|
+
// registry: "Roman Catholic Parish of Nagymaros",
|
|
45
|
+
// coverage: "1730-1895",
|
|
46
|
+
// sources: [...]
|
|
47
|
+
// }
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
### Basic Place Resolution
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const result = await resolver.resolvePlace("Budapest");
|
|
56
|
+
|
|
57
|
+
if (result) {
|
|
58
|
+
console.log(`Standardized: ${result.standardizedName}`);
|
|
59
|
+
console.log(`Registry: ${result.registry}`);
|
|
60
|
+
console.log(`Coverage: ${result.coverage}`);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Search Places
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const places = await resolver.searchPlaces("Kismaros", 5);
|
|
68
|
+
|
|
69
|
+
for (const place of places) {
|
|
70
|
+
console.log(`${place.name} - ${place.fullName}`);
|
|
71
|
+
|
|
72
|
+
// URLs are automatically generated for the configured environment
|
|
73
|
+
console.log(`Place details: ${place.url}`);
|
|
74
|
+
console.log(`Catalog search: ${place.catalogUrl}`);
|
|
75
|
+
console.log(`Records search: ${place.recordsUrl}`);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Note:** The SDK automatically generates FamilySearch web UI URLs (`url`, `catalogUrl`, `recordsUrl`) for each place result based on the configured environment (production/beta/integration).
|
|
80
|
+
|
|
81
|
+
### Search Catalog
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const records = await resolver.searchCatalog("Kismaros, Hungary");
|
|
85
|
+
|
|
86
|
+
for (const record of records) {
|
|
87
|
+
console.log(`${record.title} (${record.coverageYears})`);
|
|
88
|
+
console.log(`Author: ${record.author}`);
|
|
89
|
+
console.log(`URL: ${record.url}`);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Using Individual Modules
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { CatalogPlacesClient, PlacesAPI, CatalogAPI } from "@treeviz/familysearch-catalog-sdk";
|
|
97
|
+
|
|
98
|
+
const client = new CatalogPlacesClient({
|
|
99
|
+
clientId: process.env.FS_CLIENT_ID!,
|
|
100
|
+
environment: "production",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const places = new PlacesAPI(client);
|
|
104
|
+
const catalog = new CatalogAPI(client);
|
|
105
|
+
|
|
106
|
+
// Search places
|
|
107
|
+
const placeResults = await places.searchPlace("Budapest");
|
|
108
|
+
|
|
109
|
+
// Search catalog
|
|
110
|
+
const catalogResults = await catalog.searchByPlace("Budapest");
|
|
111
|
+
|
|
112
|
+
// Extract coverage period
|
|
113
|
+
const coverage = catalog.getCoveragePeriod(catalogResults);
|
|
114
|
+
console.log(`Coverage: ${coverage?.startYear}-${coverage?.endYear}`);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Parser Utilities
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import * as Parser from "@treeviz/familysearch-catalog-sdk/parser";
|
|
121
|
+
|
|
122
|
+
// Extract parish name from title
|
|
123
|
+
const parish = Parser.extractParishName("Roman Catholic Parish of Nagymaros");
|
|
124
|
+
console.log(parish); // "Nagymaros"
|
|
125
|
+
|
|
126
|
+
// Parse date range
|
|
127
|
+
const range = Parser.parseDateRange("Records from 1730-1895");
|
|
128
|
+
console.log(range); // { start: 1730, end: 1895 }
|
|
129
|
+
|
|
130
|
+
// Extract registry type
|
|
131
|
+
const type = Parser.extractRegistryType("Roman Catholic Parish of Nagymaros");
|
|
132
|
+
console.log(type); // "Roman Catholic"
|
|
133
|
+
|
|
134
|
+
// Normalize place name
|
|
135
|
+
const normalized = Parser.normalizePlaceName("KismarΓ³s");
|
|
136
|
+
console.log(normalized); // "kismaros"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Caching
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
const resolver = new FamilySearchCatalog({
|
|
143
|
+
clientId: process.env.FS_CLIENT_ID!,
|
|
144
|
+
enableCache: true,
|
|
145
|
+
cacheTTL: 3600, // 1 hour
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// First call - makes API request
|
|
149
|
+
await resolver.resolvePlace("Budapest");
|
|
150
|
+
|
|
151
|
+
// Second call - uses cached result
|
|
152
|
+
await resolver.resolvePlace("Budapest");
|
|
153
|
+
|
|
154
|
+
// Clear cache
|
|
155
|
+
resolver.clearCache();
|
|
156
|
+
|
|
157
|
+
// Get cache stats
|
|
158
|
+
const stats = resolver.getCacheStats();
|
|
159
|
+
console.log(`Cache size: ${stats.size}, enabled: ${stats.enabled}`);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Authentication
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// Set access token for authenticated requests
|
|
166
|
+
resolver.setAccessToken("your-oauth-token");
|
|
167
|
+
|
|
168
|
+
// Now you can make authenticated requests
|
|
169
|
+
const result = await resolver.resolvePlace("Budapest");
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## API Reference
|
|
173
|
+
|
|
174
|
+
### FamilySearchCatalog
|
|
175
|
+
|
|
176
|
+
The main class for high-level operations.
|
|
177
|
+
|
|
178
|
+
#### Constructor
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
new FamilySearchCatalog(config: CatalogPlacesClientConfig)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Config options:**
|
|
185
|
+
- `clientId` (required) - FamilySearch OAuth client ID
|
|
186
|
+
- `clientSecret` (optional) - FamilySearch OAuth client secret
|
|
187
|
+
- `environment` (optional) - Environment: `"production"` (default), `"beta"`, or `"integration"`
|
|
188
|
+
- `enableCache` (optional) - Enable caching (default: `true`)
|
|
189
|
+
- `cacheTTL` (optional) - Cache TTL in seconds (default: `3600`)
|
|
190
|
+
- `debug` (optional) - Enable debug logging (default: `false`)
|
|
191
|
+
|
|
192
|
+
#### Methods
|
|
193
|
+
|
|
194
|
+
- `resolvePlace(placeName, options?)` - Resolve a place name
|
|
195
|
+
- `searchPlaces(query, count?)` - Search for places
|
|
196
|
+
- `searchCatalog(placeName, count?)` - Search catalog
|
|
197
|
+
- `getPlaceById(placeId)` - Get place details by ID
|
|
198
|
+
- `setAccessToken(token)` - Set OAuth access token
|
|
199
|
+
- `clearCache()` - Clear the cache
|
|
200
|
+
- `getCacheStats()` - Get cache statistics
|
|
201
|
+
|
|
202
|
+
### PlacesAPI
|
|
203
|
+
|
|
204
|
+
Low-level Places API.
|
|
205
|
+
|
|
206
|
+
- `searchPlace(query, options?)` - Search for places
|
|
207
|
+
- `getPlaceById(placeId)` - Get place by ID
|
|
208
|
+
- `normalizePlace(placeName)` - Normalize a place name
|
|
209
|
+
|
|
210
|
+
### CatalogAPI
|
|
211
|
+
|
|
212
|
+
Low-level Catalog API.
|
|
213
|
+
|
|
214
|
+
- `searchByPlace(placeName, options?)` - Search catalog by place
|
|
215
|
+
- `getRecordDetails(recordId)` - Get catalog record details
|
|
216
|
+
- `getCoveragePeriod(records)` - Extract coverage period from records
|
|
217
|
+
- `extractParishInfo(records)` - Extract parish information
|
|
218
|
+
|
|
219
|
+
### Parser Utilities
|
|
220
|
+
|
|
221
|
+
- `extractParishName(title)` - Extract parish name from title
|
|
222
|
+
- `extractRegistryType(title)` - Extract registry type
|
|
223
|
+
- `parseDateRange(text)` - Parse date range from text
|
|
224
|
+
- `extractAuthor(attribution)` - Extract author name
|
|
225
|
+
- `formatYearRange(start, end)` - Format year range as string
|
|
226
|
+
- `normalizePlaceName(placeName)` - Normalize place name for comparison
|
|
227
|
+
- `calculateSimilarity(str1, str2)` - Calculate string similarity
|
|
228
|
+
|
|
229
|
+
## Type Definitions
|
|
230
|
+
|
|
231
|
+
### ResolvedPlace
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
interface ResolvedPlace {
|
|
235
|
+
placeId: string;
|
|
236
|
+
standardizedName: string;
|
|
237
|
+
registry: string;
|
|
238
|
+
coverage: string;
|
|
239
|
+
sources: CatalogSource[];
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### CatalogSource
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
interface CatalogSource {
|
|
247
|
+
id: string;
|
|
248
|
+
title: string;
|
|
249
|
+
author: string;
|
|
250
|
+
years: string;
|
|
251
|
+
url: string;
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### PlaceSearchResult
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
interface PlaceSearchResult {
|
|
259
|
+
id: string;
|
|
260
|
+
name: string;
|
|
261
|
+
fullName: string;
|
|
262
|
+
type?: string;
|
|
263
|
+
latitude?: number;
|
|
264
|
+
longitude?: number;
|
|
265
|
+
parent?: {
|
|
266
|
+
id: string;
|
|
267
|
+
name: string;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### CatalogSearchResult
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
interface CatalogSearchResult {
|
|
276
|
+
id: string;
|
|
277
|
+
title: string;
|
|
278
|
+
author: string;
|
|
279
|
+
coverageYears: string;
|
|
280
|
+
place: string;
|
|
281
|
+
type: string;
|
|
282
|
+
url: string;
|
|
283
|
+
metadata?: Record<string, unknown>;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Dependencies
|
|
288
|
+
|
|
289
|
+
This package depends on:
|
|
290
|
+
- `@treeviz/familysearch-sdk` - For OAuth authentication and base HTTP client
|
|
291
|
+
|
|
292
|
+
## Development
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Install dependencies
|
|
296
|
+
npm install
|
|
297
|
+
|
|
298
|
+
# Build
|
|
299
|
+
npm run build
|
|
300
|
+
|
|
301
|
+
# Run tests
|
|
302
|
+
npm test
|
|
303
|
+
|
|
304
|
+
# Watch mode
|
|
305
|
+
npm run dev
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Related Packages
|
|
309
|
+
|
|
310
|
+
- [@treeviz/familysearch-sdk](https://www.npmjs.com/package/@treeviz/familysearch-sdk) - Core FamilySearch API SDK
|
|
311
|
+
- [@treeviz/gedcom-parser](https://www.npmjs.com/package/@treeviz/gedcom-parser) - GEDCOM file parser
|
|
312
|
+
|
|
313
|
+
## Contributing
|
|
314
|
+
|
|
315
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
316
|
+
|
|
317
|
+
## License
|
|
318
|
+
|
|
319
|
+
MIT License - see [LICENSE](LICENSE) file for details
|
|
320
|
+
|
|
321
|
+
Copyright (c) 2026 idavidka and @treeviz contributors
|
|
322
|
+
|
|
323
|
+
## Author
|
|
324
|
+
|
|
325
|
+
idavidka and @treeviz contributors
|
|
326
|
+
|
|
327
|
+
## Repository
|
|
328
|
+
|
|
329
|
+
https://github.com/idavidka/familysearch-catalog-sdk
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/cache/index.ts
|
|
4
|
+
var MemoryCache = class {
|
|
5
|
+
/**
|
|
6
|
+
* Create a new memory cache
|
|
7
|
+
* @param maxSize Maximum number of entries (default: 1000)
|
|
8
|
+
* @param defaultTTL Default TTL in seconds (default: 3600 = 1 hour)
|
|
9
|
+
*/
|
|
10
|
+
constructor(maxSize = 1e3, defaultTTL = 3600) {
|
|
11
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
12
|
+
this.maxSize = maxSize;
|
|
13
|
+
this.defaultTTL = defaultTTL;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get value from cache
|
|
17
|
+
*/
|
|
18
|
+
get(key) {
|
|
19
|
+
const entry = this.cache.get(key);
|
|
20
|
+
if (!entry) {
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
23
|
+
const now = Date.now();
|
|
24
|
+
const age = (now - entry.timestamp) / 1e3;
|
|
25
|
+
if (age > entry.ttl) {
|
|
26
|
+
this.cache.delete(key);
|
|
27
|
+
return void 0;
|
|
28
|
+
}
|
|
29
|
+
this.cache.delete(key);
|
|
30
|
+
this.cache.set(key, entry);
|
|
31
|
+
return entry.data;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Set value in cache
|
|
35
|
+
*/
|
|
36
|
+
set(key, value, ttl) {
|
|
37
|
+
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
38
|
+
const firstKey = this.cache.keys().next().value;
|
|
39
|
+
if (firstKey !== void 0) {
|
|
40
|
+
this.cache.delete(firstKey);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const entry = {
|
|
44
|
+
data: value,
|
|
45
|
+
timestamp: Date.now(),
|
|
46
|
+
ttl: ttl ?? this.defaultTTL
|
|
47
|
+
};
|
|
48
|
+
this.cache.set(key, entry);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if key exists in cache
|
|
52
|
+
*/
|
|
53
|
+
has(key) {
|
|
54
|
+
const value = this.get(key);
|
|
55
|
+
return value !== void 0;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Delete key from cache
|
|
59
|
+
*/
|
|
60
|
+
delete(key) {
|
|
61
|
+
return this.cache.delete(key);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Clear all cache entries
|
|
65
|
+
*/
|
|
66
|
+
clear() {
|
|
67
|
+
this.cache.clear();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get cache size
|
|
71
|
+
*/
|
|
72
|
+
size() {
|
|
73
|
+
return this.cache.size;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Clean up expired entries
|
|
77
|
+
*/
|
|
78
|
+
cleanup() {
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
const keysToDelete = [];
|
|
81
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
82
|
+
const age = (now - entry.timestamp) / 1e3;
|
|
83
|
+
if (age > entry.ttl) {
|
|
84
|
+
keysToDelete.push(key);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
for (const key of keysToDelete) {
|
|
88
|
+
this.cache.delete(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
exports.MemoryCache = MemoryCache;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { c as Cache } from '../index-BaNFN7C2.cjs';
|
|
2
|
+
export { d as CacheEntry } from '../index-BaNFN7C2.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* In-memory LRU cache with TTL support
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare class MemoryCache implements Cache {
|
|
9
|
+
private cache;
|
|
10
|
+
private readonly maxSize;
|
|
11
|
+
private readonly defaultTTL;
|
|
12
|
+
/**
|
|
13
|
+
* Create a new memory cache
|
|
14
|
+
* @param maxSize Maximum number of entries (default: 1000)
|
|
15
|
+
* @param defaultTTL Default TTL in seconds (default: 3600 = 1 hour)
|
|
16
|
+
*/
|
|
17
|
+
constructor(maxSize?: number, defaultTTL?: number);
|
|
18
|
+
/**
|
|
19
|
+
* Get value from cache
|
|
20
|
+
*/
|
|
21
|
+
get<T>(key: string): T | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Set value in cache
|
|
24
|
+
*/
|
|
25
|
+
set<T>(key: string, value: T, ttl?: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Check if key exists in cache
|
|
28
|
+
*/
|
|
29
|
+
has(key: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Delete key from cache
|
|
32
|
+
*/
|
|
33
|
+
delete(key: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Clear all cache entries
|
|
36
|
+
*/
|
|
37
|
+
clear(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get cache size
|
|
40
|
+
*/
|
|
41
|
+
size(): number;
|
|
42
|
+
/**
|
|
43
|
+
* Clean up expired entries
|
|
44
|
+
*/
|
|
45
|
+
cleanup(): void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { Cache, MemoryCache };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { c as Cache } from '../index-BaNFN7C2.js';
|
|
2
|
+
export { d as CacheEntry } from '../index-BaNFN7C2.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* In-memory LRU cache with TTL support
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare class MemoryCache implements Cache {
|
|
9
|
+
private cache;
|
|
10
|
+
private readonly maxSize;
|
|
11
|
+
private readonly defaultTTL;
|
|
12
|
+
/**
|
|
13
|
+
* Create a new memory cache
|
|
14
|
+
* @param maxSize Maximum number of entries (default: 1000)
|
|
15
|
+
* @param defaultTTL Default TTL in seconds (default: 3600 = 1 hour)
|
|
16
|
+
*/
|
|
17
|
+
constructor(maxSize?: number, defaultTTL?: number);
|
|
18
|
+
/**
|
|
19
|
+
* Get value from cache
|
|
20
|
+
*/
|
|
21
|
+
get<T>(key: string): T | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Set value in cache
|
|
24
|
+
*/
|
|
25
|
+
set<T>(key: string, value: T, ttl?: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Check if key exists in cache
|
|
28
|
+
*/
|
|
29
|
+
has(key: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Delete key from cache
|
|
32
|
+
*/
|
|
33
|
+
delete(key: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Clear all cache entries
|
|
36
|
+
*/
|
|
37
|
+
clear(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get cache size
|
|
40
|
+
*/
|
|
41
|
+
size(): number;
|
|
42
|
+
/**
|
|
43
|
+
* Clean up expired entries
|
|
44
|
+
*/
|
|
45
|
+
cleanup(): void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { Cache, MemoryCache };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// src/cache/index.ts
|
|
2
|
+
var MemoryCache = class {
|
|
3
|
+
/**
|
|
4
|
+
* Create a new memory cache
|
|
5
|
+
* @param maxSize Maximum number of entries (default: 1000)
|
|
6
|
+
* @param defaultTTL Default TTL in seconds (default: 3600 = 1 hour)
|
|
7
|
+
*/
|
|
8
|
+
constructor(maxSize = 1e3, defaultTTL = 3600) {
|
|
9
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
10
|
+
this.maxSize = maxSize;
|
|
11
|
+
this.defaultTTL = defaultTTL;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get value from cache
|
|
15
|
+
*/
|
|
16
|
+
get(key) {
|
|
17
|
+
const entry = this.cache.get(key);
|
|
18
|
+
if (!entry) {
|
|
19
|
+
return void 0;
|
|
20
|
+
}
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
const age = (now - entry.timestamp) / 1e3;
|
|
23
|
+
if (age > entry.ttl) {
|
|
24
|
+
this.cache.delete(key);
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
this.cache.delete(key);
|
|
28
|
+
this.cache.set(key, entry);
|
|
29
|
+
return entry.data;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Set value in cache
|
|
33
|
+
*/
|
|
34
|
+
set(key, value, ttl) {
|
|
35
|
+
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
36
|
+
const firstKey = this.cache.keys().next().value;
|
|
37
|
+
if (firstKey !== void 0) {
|
|
38
|
+
this.cache.delete(firstKey);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const entry = {
|
|
42
|
+
data: value,
|
|
43
|
+
timestamp: Date.now(),
|
|
44
|
+
ttl: ttl ?? this.defaultTTL
|
|
45
|
+
};
|
|
46
|
+
this.cache.set(key, entry);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if key exists in cache
|
|
50
|
+
*/
|
|
51
|
+
has(key) {
|
|
52
|
+
const value = this.get(key);
|
|
53
|
+
return value !== void 0;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Delete key from cache
|
|
57
|
+
*/
|
|
58
|
+
delete(key) {
|
|
59
|
+
return this.cache.delete(key);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Clear all cache entries
|
|
63
|
+
*/
|
|
64
|
+
clear() {
|
|
65
|
+
this.cache.clear();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get cache size
|
|
69
|
+
*/
|
|
70
|
+
size() {
|
|
71
|
+
return this.cache.size;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Clean up expired entries
|
|
75
|
+
*/
|
|
76
|
+
cleanup() {
|
|
77
|
+
const now = Date.now();
|
|
78
|
+
const keysToDelete = [];
|
|
79
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
80
|
+
const age = (now - entry.timestamp) / 1e3;
|
|
81
|
+
if (age > entry.ttl) {
|
|
82
|
+
keysToDelete.push(key);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const key of keysToDelete) {
|
|
86
|
+
this.cache.delete(key);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export { MemoryCache };
|