tcgpriser 0.13.0 → 1.0.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.
- package/README.md +42 -5
- package/dist/index.cjs +42 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +153 -21
- package/dist/index.d.ts +153 -21
- package/dist/index.js +42 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,6 +80,31 @@ await tcgpriser.expansions.cards('eng-scarlet-violet-journey-together'); // cont
|
|
|
80
80
|
await tcgpriser.expansions.sealedProducts('eng-scarlet-violet-journey-together'); // content only
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
### Brands
|
|
84
|
+
|
|
85
|
+
The franchises and makers the catalogue carries — today just Pokémon, but `cards`/`products`/
|
|
86
|
+
`expansions` all accept a `brand` filter (an `id` or `technicalName`) in preparation for more.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
await tcgpriser.brands.list();
|
|
90
|
+
await tcgpriser.brands.get('pokemon');
|
|
91
|
+
|
|
92
|
+
// Scope any list to one brand. An unrecognized value is a 400, not a silently empty page.
|
|
93
|
+
await tcgpriser.cards.list({ brand: 'pokemon' });
|
|
94
|
+
await tcgpriser.expansions.list({ brand: 'pokemon' });
|
|
95
|
+
|
|
96
|
+
// Disambiguate a technicalName two brands might both use, on a single-item lookup.
|
|
97
|
+
await tcgpriser.products.get('booster-box', { brand: 'pokemon' });
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`productLine` narrows further, to what kind of catalogue item something is — `'tcg'` for every
|
|
101
|
+
card and sealed product today, plus `'accessory'` / `'collectible'` / `'boardGame'` /
|
|
102
|
+
`'videoGame'` / `'other'` for non-TCG items as the catalogue grows to carry them:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
await tcgpriser.cards.list({ productLine: 'tcg' });
|
|
106
|
+
```
|
|
107
|
+
|
|
83
108
|
### Pricing
|
|
84
109
|
|
|
85
110
|
`list()`/`get()`/`expansions.cards()`/`expansions.sealedProducts()` all return catalog content
|
|
@@ -147,11 +172,14 @@ Credits column applies only to calls that draw from your weekly allowance; see [
|
|
|
147
172
|
|
|
148
173
|
### `cards`
|
|
149
174
|
|
|
175
|
+
`list()`/`dailyStats()`/`estimatedValues()` all take `brand`/`productLine` filters — see
|
|
176
|
+
[Brands](#brands). `get()` takes `brand` too, to disambiguate a technicalName two brands share.
|
|
177
|
+
|
|
150
178
|
| Method | Description | Credits |
|
|
151
179
|
|---|---|---|
|
|
152
180
|
| `list(params)` | List cards, newest first | — |
|
|
153
181
|
| `search(params)` 🔒 | Free-text search on card and set names | 5 |
|
|
154
|
-
| `get(id)` | Fetch one card by id or technicalName | — |
|
|
182
|
+
| `get(id, params)` | Fetch one card by id or technicalName | — |
|
|
155
183
|
| `matches(id, params)` | Current shop listings matched to this card | — |
|
|
156
184
|
| `pricing(id)` | This card's current pricing snapshot | — |
|
|
157
185
|
| `pricingBatch(ids)` | Pricing for up to 200 cards at once, by id | — |
|
|
@@ -164,13 +192,14 @@ Credits column applies only to calls that draw from your weekly allowance; see [
|
|
|
164
192
|
|
|
165
193
|
### `products`
|
|
166
194
|
|
|
167
|
-
Sealed products only. Single cards live under `cards`.
|
|
195
|
+
Sealed products only. Single cards live under `cards`. `list()`/`dailyStats()`/`estimatedValues()`
|
|
196
|
+
take `brand`/`productLine` filters, and `get()` takes `brand` — see [Brands](#brands).
|
|
168
197
|
|
|
169
198
|
| Method | Description | Credits |
|
|
170
199
|
|---|---|---|
|
|
171
200
|
| `list(params)` | List sealed products, newest first | — |
|
|
172
201
|
| `search(params)` 🔒 | Free-text search on the product name | 5 |
|
|
173
|
-
| `get(id)` | Fetch one product by id or technicalName | — |
|
|
202
|
+
| `get(id, params)` | Fetch one product by id or technicalName | — |
|
|
174
203
|
| `matches(id, params)` | Current shop listings matched to this product | — |
|
|
175
204
|
| `pricing(id)` | This product's current pricing snapshot | — |
|
|
176
205
|
| `pricingBatch(ids)` | Pricing for up to 200 products at once, by id | — |
|
|
@@ -183,17 +212,25 @@ Sealed products only. Single cards live under `cards`.
|
|
|
183
212
|
|
|
184
213
|
### `expansions`
|
|
185
214
|
|
|
186
|
-
Cards and sealed products are always separate calls — nothing here merges them.
|
|
215
|
+
Cards and sealed products are always separate calls — nothing here merges them. `list()` takes a
|
|
216
|
+
`brand` filter — see [Brands](#brands).
|
|
187
217
|
|
|
188
218
|
| Method | Description | Credits |
|
|
189
219
|
|---|---|---|
|
|
190
|
-
| `list()` | Every expansion, with counts | — |
|
|
220
|
+
| `list(params)` | Every expansion, with counts | — |
|
|
191
221
|
| `get(technicalName)` | One expansion's metadata (no contents) | — |
|
|
192
222
|
| `cards(technicalName)` | Every card in the expansion, content only | — |
|
|
193
223
|
| `sealedProducts(technicalName)` | Every sealed product in the expansion, content only | — |
|
|
194
224
|
| `cardsLivePricing(technicalName)` 🔒 | Fresh pricing for every card in the expansion | 8 |
|
|
195
225
|
| `productsLivePricing(technicalName)` 🔒 | Fresh pricing for every sealed product in it | 8 |
|
|
196
226
|
|
|
227
|
+
### `brands`
|
|
228
|
+
|
|
229
|
+
| Method | Description |
|
|
230
|
+
|---|---|
|
|
231
|
+
| `list()` | Every brand the catalogue carries |
|
|
232
|
+
| `get(id)` | Fetch one brand by id or technicalName |
|
|
233
|
+
|
|
197
234
|
### `shops`
|
|
198
235
|
|
|
199
236
|
| Method | Description |
|
package/dist/index.cjs
CHANGED
|
@@ -223,6 +223,24 @@ var BargainsResource = class {
|
|
|
223
223
|
}
|
|
224
224
|
};
|
|
225
225
|
|
|
226
|
+
// src/resources/brands.ts
|
|
227
|
+
var BrandsResource = class {
|
|
228
|
+
constructor(http) {
|
|
229
|
+
this.http = http;
|
|
230
|
+
}
|
|
231
|
+
http;
|
|
232
|
+
/** `GET /brands`: every brand. Unwrapped to a plain array, nothing to paginate here — same
|
|
233
|
+
* shape as `expansions.list()`/`shops.list()`. */
|
|
234
|
+
async list(options = {}) {
|
|
235
|
+
const res = await this.http.get("/brands", options);
|
|
236
|
+
return res.data;
|
|
237
|
+
}
|
|
238
|
+
/** `GET /brands/{id}`: fetch one brand by its id or technicalName. */
|
|
239
|
+
get(idOrTechnicalName, options = {}) {
|
|
240
|
+
return this.http.get(`/brands/${encodeURIComponent(idOrTechnicalName)}`, options);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
226
244
|
// src/resources/cards.ts
|
|
227
245
|
var CardsResource = class {
|
|
228
246
|
constructor(http) {
|
|
@@ -239,9 +257,14 @@ var CardsResource = class {
|
|
|
239
257
|
const [query, requestOptions] = splitRequestOptions(params);
|
|
240
258
|
return this.http.get(`/cards/search${toQueryString(query)}`, requestOptions);
|
|
241
259
|
}
|
|
242
|
-
/** `GET /cards/{id}`: fetch one card by its id or technicalName.
|
|
243
|
-
|
|
244
|
-
|
|
260
|
+
/** `GET /cards/{id}`: fetch one card by its id or technicalName. Pass `brand` if two brands
|
|
261
|
+
* might share the same technicalName — see `GetCardParams`. */
|
|
262
|
+
get(idOrTechnicalName, params = {}) {
|
|
263
|
+
const [query, requestOptions] = splitRequestOptions(params);
|
|
264
|
+
return this.http.get(
|
|
265
|
+
`/cards/${encodeURIComponent(idOrTechnicalName)}${toQueryString(query)}`,
|
|
266
|
+
requestOptions
|
|
267
|
+
);
|
|
245
268
|
}
|
|
246
269
|
/** `GET /cards/{id}/matches`: current shop listings matched to this card (latest per shop). */
|
|
247
270
|
matches(idOrTechnicalName, params = {}) {
|
|
@@ -316,8 +339,12 @@ var ExpansionsResource = class {
|
|
|
316
339
|
}
|
|
317
340
|
http;
|
|
318
341
|
/** `GET /expansions`: every expansion. Unwrapped to a plain array, nothing to paginate here. */
|
|
319
|
-
async list(
|
|
320
|
-
const
|
|
342
|
+
async list(params = {}) {
|
|
343
|
+
const [query, requestOptions] = splitRequestOptions(params);
|
|
344
|
+
const res = await this.http.get(
|
|
345
|
+
`/expansions${toQueryString(query)}`,
|
|
346
|
+
requestOptions
|
|
347
|
+
);
|
|
321
348
|
return res.data;
|
|
322
349
|
}
|
|
323
350
|
/** `GET /expansions/{technicalName}`: metadata only — no cards or sealed products. Returns the
|
|
@@ -472,9 +499,14 @@ var ProductsResource = class {
|
|
|
472
499
|
const [query, requestOptions] = splitRequestOptions(params);
|
|
473
500
|
return this.http.get(`/product/search${toQueryString(query)}`, requestOptions);
|
|
474
501
|
}
|
|
475
|
-
/** `GET /product/{id}`: fetch one sealed product by its id or technicalName.
|
|
476
|
-
|
|
477
|
-
|
|
502
|
+
/** `GET /product/{id}`: fetch one sealed product by its id or technicalName. Pass `brand` if two
|
|
503
|
+
* brands might share the same technicalName — see `GetProductParams`. */
|
|
504
|
+
get(idOrTechnicalName, params = {}) {
|
|
505
|
+
const [query, requestOptions] = splitRequestOptions(params);
|
|
506
|
+
return this.http.get(
|
|
507
|
+
`/product/${encodeURIComponent(idOrTechnicalName)}${toQueryString(query)}`,
|
|
508
|
+
requestOptions
|
|
509
|
+
);
|
|
478
510
|
}
|
|
479
511
|
/** `GET /product/{id}/matches`: current shop listings matched to this product (latest per shop). */
|
|
480
512
|
matches(idOrTechnicalName, params = {}) {
|
|
@@ -687,6 +719,7 @@ var TcgPriser = class {
|
|
|
687
719
|
cards;
|
|
688
720
|
products;
|
|
689
721
|
expansions;
|
|
722
|
+
brands;
|
|
690
723
|
shops;
|
|
691
724
|
shopMatches;
|
|
692
725
|
shopMatchStats;
|
|
@@ -724,6 +757,7 @@ var TcgPriser = class {
|
|
|
724
757
|
this.cards = new CardsResource(http);
|
|
725
758
|
this.products = new ProductsResource(http);
|
|
726
759
|
this.expansions = new ExpansionsResource(http);
|
|
760
|
+
this.brands = new BrandsResource(http);
|
|
727
761
|
this.shops = new ShopsResource(http);
|
|
728
762
|
this.shopMatches = new ShopMatchesResource(http);
|
|
729
763
|
this.shopMatchStats = new ShopMatchStatsResource(http);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/bargains.ts","../src/resources/cards.ts","../src/resources/expansions.ts","../src/resources/packRates.ts","../src/resources/priceStats.ts","../src/resources/products.ts","../src/resources/shopMatchStats.ts","../src/resources/shopMatches.ts","../src/resources/shopUrls.ts","../src/resources/shops.ts","../src/resources/stats.ts","../src/resources/webhooks.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/** The stable error codes the API's `error.code` field can hold. */\nexport type TcgPriserErrorCode =\n | 'validationFailed'\n | 'unauthorized'\n | 'forbidden'\n | 'notFound'\n | 'conflict'\n | 'readOnlyField'\n | 'rateLimited'\n | 'premiumRequired'\n | 'businessRequired'\n | 'creditsExhausted'\n | 'internalError'\n /** The request exceeded its `timeoutMs` and was aborted client-side. Never sent by the API — the\n * one code this package raises on its own, so a stalled connection is distinguishable from a\n * server that answered. */\n | 'timeout'\n /** Response body wasn't the `{ error: { code, message } }` shape. Probably a proxy or gateway\n * error in front of the API. */\n | 'unknown';\n\n/** Thrown for any non-2xx response. Carries the parsed `{ code, message }` when the body matched\n * the API's error envelope, plus the raw status/body regardless so nothing gets lost. */\nexport class TcgPriserError extends Error {\n readonly statusCode: number;\n readonly statusText: string;\n readonly url: string;\n readonly code: TcgPriserErrorCode;\n readonly details: unknown;\n /** The raw response body, for debugging when `code`/`details` don't cover what you need. */\n readonly body: string;\n /**\n * Seconds to wait before retrying, from the `Retry-After` header. Present on `rateLimited`, and\n * on anything else a proxy in front of the API decides to send it with. Absent otherwise — an\n * error without it is not one that says retrying will help.\n */\n readonly retryAfter: number | undefined;\n /**\n * Credits left in this week's allowance, from `X-Credits-Remaining`. Present on errors from\n * charged routes — notably `creditsExhausted`, where it is `0`. Absent on uncharged routes and on\n * anything a proxy answered instead of the API.\n */\n readonly creditsRemaining: number | undefined;\n\n constructor(params: {\n statusCode: number;\n statusText: string;\n url: string;\n code: TcgPriserErrorCode;\n message: string;\n details?: unknown;\n body: string;\n retryAfter?: number;\n creditsRemaining?: number;\n }) {\n // `statusCode` is 0 for a client-side timeout, where there was no response to have a status.\n // Printing \"tcgpriser: 0 timeout - ...\" would read like a bug in the message itself.\n const status = params.statusCode === 0 ? '' : `${params.statusCode} `;\n super(`tcgpriser: ${status}${params.code} - ${params.message} (${params.url})`);\n this.name = 'TcgPriserError';\n this.statusCode = params.statusCode;\n this.statusText = params.statusText;\n this.url = params.url;\n this.code = params.code;\n this.details = params.details;\n this.body = params.body;\n this.retryAfter = params.retryAfter;\n this.creditsRemaining = params.creditsRemaining;\n }\n}\n","import { TcgPriserError, type TcgPriserErrorCode } from './errors.js';\n\nexport type QueryValue = string | number | boolean | undefined | null;\n\n/**\n * Builds a query string from a params object, dropping `undefined`/`null` entries so callers can\n * pass params straight through without filtering first.\n *\n * Takes a generic `object` instead of `Record<string, QueryValue>` on purpose. The params\n * interfaces (`ListCardsParams` etc.) intentionally have no index signature, otherwise any string\n * key would type-check.\n */\nexport function toQueryString<T extends object>(params: T): string {\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(params) as [string, QueryValue][]) {\n if (value === undefined || value === null) continue;\n search.set(key, String(value));\n }\n const query = search.toString();\n return query ? `?${query}` : '';\n}\n\n/**\n * Splits the per-call request options off a params object so they don't end up in the query string.\n *\n * `authToken` is the reason this exists: a bearer token has no business in a URL, because query\n * strings end up in server logs, browser history and `Referer` headers. `signal` and `timeoutMs`\n * ride along for the same structural reason — they configure the request rather than describe it,\n * and `String(anAbortSignal)` in a URL would be nonsense.\n */\nexport function splitRequestOptions<T extends RequestOptions>(\n params: T,\n): [Omit<T, keyof RequestOptions>, RequestOptions] {\n const { authToken, signal, timeoutMs, ...rest } = params;\n return [rest, { authToken, signal, timeoutMs }];\n}\n\n/** @deprecated Renamed to `splitRequestOptions`, which also splits off `signal`/`timeoutMs`. */\nexport const splitAuthToken = splitRequestOptions;\n\nconst KNOWN_ERROR_CODES: ReadonlySet<string> = new Set([\n 'validationFailed',\n 'unauthorized',\n 'forbidden',\n 'notFound',\n 'conflict',\n 'readOnlyField',\n 'rateLimited',\n 'premiumRequired',\n 'businessRequired',\n 'creditsExhausted',\n 'internalError',\n]);\n\n/** Parses a header that should hold a non-negative integer, ignoring anything that doesn't. */\nfunction readIntHeader(res: Response, name: string): number | undefined {\n const raw = res.headers.get(name);\n if (raw === null) return undefined;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;\n}\n\nasync function toApiError(res: Response, url: string): Promise<TcgPriserError> {\n const body = await res.text();\n let code: TcgPriserErrorCode = 'unknown';\n let message = res.statusText || 'Request failed';\n let details: unknown;\n\n try {\n const parsed = JSON.parse(body) as { error?: { code?: string; message?: string; details?: unknown } };\n if (parsed.error?.code && KNOWN_ERROR_CODES.has(parsed.error.code)) {\n code = parsed.error.code as TcgPriserErrorCode;\n }\n if (parsed.error?.message) message = parsed.error.message;\n details = parsed.error?.details;\n } catch {\n // Not the standard error envelope, maybe a proxy's HTML error page. Fall back to the status\n // text and leave `body` for anyone who wants to dig in.\n }\n\n return new TcgPriserError({\n statusCode: res.status,\n statusText: res.statusText,\n url,\n code,\n message,\n details,\n body,\n // Both are most useful on exactly the errors that carry them: `retryAfter` on `rateLimited`,\n // `creditsRemaining` on `creditsExhausted` (where it is 0) and on any error from a charged\n // route. Read unconditionally rather than branching on the code, since a proxy can return a\n // 429 with `Retry-After` and no envelope at all.\n retryAfter: readIntHeader(res, 'Retry-After'),\n creditsRemaining: readIntHeader(res, 'X-Credits-Remaining'),\n });\n}\n\nexport interface HttpClientOptions {\n baseUrl: string;\n fetch: typeof fetch;\n headers?: Record<string, string>;\n /** Default bearer token for premium endpoints, used when a call doesn't pass its own `authToken`. */\n authToken?: string;\n /** Default per-request timeout. See `RequestOptions.timeoutMs`. */\n timeoutMs?: number;\n}\n\n/**\n * Per-call overrides, accepted by every method — either standalone or merged into its params object\n * and split back out by `splitRequestOptions`.\n */\nexport interface RequestOptions {\n /**\n * Overrides the client's default `authToken` for this call. Pass `undefined` explicitly to force\n * an anonymous request even when the client has a default token.\n */\n authToken?: string;\n /**\n * Cancel the request from outside — a user navigating away, a parent operation being abandoned.\n * Composed with `timeoutMs`, so whichever fires first wins; aborting through this signal rejects\n * with the standard `AbortError`, not a `TcgPriserError`.\n */\n signal?: AbortSignal;\n /**\n * Milliseconds before this request is aborted, overriding the client's default. `0` disables the\n * timeout for this call, which is occasionally right for `expansions.cardsLivePricing()` on a very\n * large set. A timeout rejects with a `TcgPriserError` whose `code` is `'timeout'`.\n */\n timeoutMs?: number;\n}\n\n/** @deprecated Renamed to `RequestOptions`, which also carries `signal` and `timeoutMs`. */\nexport type PremiumOptions = RequestOptions;\n\n/**\n * Default request timeout.\n *\n * There was none, which meant a connection that opened and then stalled hung the caller forever\n * with no way out: `fetch` has no built-in timeout, and without a `signal` there is nothing to\n * cancel. A minute is well clear of the slowest thing the API does (a whole-expansion live-pricing\n * recompute) while still being a bound.\n */\nexport const DEFAULT_TIMEOUT_MS = 60_000;\n\n/**\n * Combines the caller's signal with a timeout into one signal, plus the cleanup that cancels the\n * timer once the request settles.\n *\n * Hand-rolled rather than `AbortSignal.any()` + `AbortSignal.timeout()`: those landed in Node 20,\n * and this package supports Node 18. `clear()` matters as much as the combining — a pending\n * `setTimeout` keeps the Node event loop alive, so a short-lived script that finished its work would\n * otherwise sit there until the last timeout elapsed instead of exiting.\n */\nfunction withTimeout(\n timeoutMs: number,\n callerSignal: AbortSignal | undefined,\n): { signal: AbortSignal | undefined; clear: () => void; timedOut: () => boolean } {\n if (timeoutMs <= 0) return { signal: callerSignal, clear: () => {}, timedOut: () => false };\n\n const controller = new AbortController();\n let expired = false;\n\n const timer = setTimeout(() => {\n expired = true;\n controller.abort();\n }, timeoutMs);\n\n const onCallerAbort = (): void => controller.abort();\n if (callerSignal) {\n if (callerSignal.aborted) controller.abort();\n else callerSignal.addEventListener('abort', onCallerAbort, { once: true });\n }\n\n return {\n signal: controller.signal,\n clear: () => {\n clearTimeout(timer);\n callerSignal?.removeEventListener('abort', onCallerAbort);\n },\n timedOut: () => expired,\n };\n}\n\n/** Thin wrapper around `fetch`: joins the base URL, adds default headers, applies the timeout, turns\n * non-2xx responses into a `TcgPriserError`. Every resource method goes through this instead of\n * calling `fetch` directly. */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n private readonly defaultHeaders: Record<string, string>;\n private readonly defaultAuthToken: string | undefined;\n private readonly defaultTimeoutMs: number;\n\n /**\n * The `X-Credits-Remaining` value from the most recent charged response, or `undefined` if no\n * charged call has been made yet. See `TcgPriser.creditsRemaining`.\n */\n creditsRemaining: number | undefined;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.fetchImpl = options.fetch;\n this.defaultHeaders = options.headers ?? {};\n this.defaultAuthToken = options.authToken;\n this.defaultTimeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n get<T>(path: string, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, undefined, requestOptions);\n }\n\n post<T>(path: string, body: unknown, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, body, requestOptions);\n }\n\n patch<T>(path: string, body: unknown, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, body, requestOptions);\n }\n\n delete<T>(path: string, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, undefined, requestOptions);\n }\n\n private async request<T>(\n method: string,\n path: string,\n body: unknown,\n requestOptions?: RequestOptions,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const authToken =\n requestOptions && 'authToken' in requestOptions ? requestOptions.authToken : this.defaultAuthToken;\n\n const headers: Record<string, string> = { Accept: 'application/json', ...this.defaultHeaders };\n if (authToken) headers.Authorization = `Bearer ${authToken}`;\n if (body !== undefined) headers['Content-Type'] = 'application/json';\n\n const timeoutMs = requestOptions?.timeoutMs ?? this.defaultTimeoutMs;\n const timeout = withTimeout(timeoutMs, requestOptions?.signal);\n\n let res: Response;\n try {\n res = await this.fetchImpl(url, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: timeout.signal,\n });\n } catch (error) {\n // Distinguish our own timeout from the caller cancelling. An abort we caused is a failure the\n // caller needs to see as one (and retry, or raise the limit); an abort they caused is them\n // getting what they asked for, so it propagates untouched as the standard `AbortError`.\n if (timeout.timedOut()) {\n throw new TcgPriserError({\n statusCode: 0,\n statusText: 'Timeout',\n url,\n code: 'timeout',\n message: `Request timed out after ${timeoutMs}ms`,\n body: '',\n });\n }\n throw error;\n } finally {\n timeout.clear();\n }\n\n // Read before the `res.ok` branch: a `creditsExhausted` rejection is exactly when a caller most\n // wants the balance, and it is charged routes that send this header at all.\n const credits = readIntHeader(res, 'X-Credits-Remaining');\n if (credits !== undefined) this.creditsRemaining = credits;\n\n if (!res.ok) throw await toApiError(res, url);\n if (res.status === 204) return undefined as T;\n return nullsToUndefined(await res.json()) as T;\n }\n}\n\n/** JSON has no `undefined`, so every optional field the API omits comes back over the wire as\n * `null`. Recurses through the parsed response and turns those into `undefined` so callers work\n * with idiomatic `foo?.bar` / `foo ?? fallback` instead of `foo !== null`, and so responses match\n * the `T | undefined` types in `generated/openapi.d.ts` (see `scripts/generate-types.mjs`). */\nfunction nullsToUndefined<T>(value: T): T {\n if (value === null) return undefined as T;\n if (Array.isArray(value)) return value.map(nullsToUndefined) as T;\n if (typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) result[key] = nullsToUndefined(v);\n return result as T;\n }\n return value;\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n Bargain,\n BargainReferenceSource,\n CardType,\n GradingCompany,\n ItemCondition,\n ListResponse,\n PaginationParams,\n} from '../types/index.js';\n\nexport interface ListBargainsParams extends RequestOptions {\n type?: 'sealed' | 'card' | 'all';\n}\n\nexport interface SearchBargainsParams extends PaginationParams {\n type?: 'sealed' | 'card' | 'all';\n /** Filter by shop technicalName. */\n shop?: string;\n /** Filter by which reference price source qualified the bargain. */\n referenceSource?: BargainReferenceSource;\n /** Minimum discount percentage. Default 10. */\n minDiscount?: number;\n /** Default `true`. */\n inStock?: boolean;\n cardType?: CardType;\n itemCondition?: ItemCondition;\n gradingCompany?: GradingCompany;\n grade?: number;\n /** Free-text search on product name / technicalName. */\n search?: string;\n}\n\nexport class BargainsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /bargains`: current shop listings priced notably below their reference price. Result\n * count is fixed by the API (no `limit`/`skip` on the public tier); `pagination.hasMore` tells\n * you if more exist. */\n list(params: ListBargainsParams = {}): Promise<ListResponse<Bargain>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/bargains${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /bargains/search`: like `list()`, but with real pagination and filters (shop, discount\n * threshold, card condition/grade, free-text search). Premium. */\n search(params: SearchBargainsParams = {}): Promise<ListResponse<Bargain>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/bargains/search${toQueryString(query)}`, requestOptions);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n Card,\n CardType,\n CatalogItemPricing,\n CatalogSlug,\n ItemReferencePrices,\n ItemShopMatches,\n ItemSoldPrices,\n ItemDailyStats,\n ItemEstimatedValue,\n ListResponse,\n LivePricingForItem,\n PaginationParams,\n ReferencePriceCardVariant,\n ReferencePriceProvider,\n} from '../types/index.js';\n\nexport interface ListCardsParams extends PaginationParams {}\n\nexport interface SearchCardsParams extends PaginationParams {\n /** Free-text search over card and set names. */\n search?: string;\n}\n\nexport interface CardMatchesParams extends PaginationParams {\n /** Keep only matches whose shop currently has stock. */\n inStock?: boolean;\n}\n\nexport interface CardReferencePricesParams extends RequestOptions {\n /** Bearer token for this call. Overrides the client's default `authToken`. */\n authToken?: string;\n /** Rolling window ending today, in days. Ignored when `from`/`to` are supplied. Default 90. */\n days?: number;\n /** `YYYY-MM-DD` */\n from?: string;\n /** `YYYY-MM-DD` */\n to?: string;\n provider?: ReferencePriceProvider;\n cardType?: CardType;\n variant?: ReferencePriceCardVariant;\n}\n\nexport interface CardPricesParams extends PaginationParams {}\n\n/** Filters for `cards.dailyStats()`. Narrow to one card, or to a whole expansion/category. */\nexport interface CardDailyStatsParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n productName?: string;\n technicalName?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n /** Category id (ObjectId), an alternative to `category`. */\n categoryId?: string;\n /** Expansion id (ObjectId), an alternative to `expansion`. */\n expansionId?: string;\n}\n\n/** Filters for `cards.estimatedValues()`. Note `page`/`limit`, not the `limit`/`skip` the rest of\n * the API paginates with — this endpoint predates that convention. */\nexport interface CardEstimatedValuesParams extends RequestOptions {\n page?: number;\n limit?: number;\n productName?: string;\n technicalName?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n}\n\nexport class CardsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /cards`: list cards, newest first. No free-text search — use `search()` for that. */\n list(params: ListCardsParams = {}): Promise<ListResponse<Card>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/search`: like `list()`, but with free-text search on card and set names. Premium. */\n search(params: SearchCardsParams = {}): Promise<ListResponse<Card>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards/search${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/{id}`: fetch one card by its id or technicalName. */\n get(idOrTechnicalName: string, options: RequestOptions = {}): Promise<Card> {\n return this.http.get(`/cards/${encodeURIComponent(idOrTechnicalName)}`, options);\n }\n\n /** `GET /cards/{id}/matches`: current shop listings matched to this card (latest per shop). */\n matches(idOrTechnicalName: string, params: CardMatchesParams = {}): Promise<ItemShopMatches> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/cards/${encodeURIComponent(idOrTechnicalName)}/matches${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /cards/{id}/reference-prices`: Cardmarket/TCGplayer/eBay/Tradera price history. Premium. */\n referencePrices(\n idOrTechnicalName: string,\n params: CardReferencePricesParams = {},\n ): Promise<ItemReferencePrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/cards/${encodeURIComponent(idOrTechnicalName)}/reference-prices${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /cards/{id}/prices`: individual marketplace sale records. Premium. */\n prices(idOrTechnicalName: string, params: CardPricesParams = {}): Promise<ItemSoldPrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards/${encodeURIComponent(idOrTechnicalName)}/prices${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/{id}/pricing/live`: computed fresh for this request, not read from the last\n * stats job. Premium. */\n livePricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<LivePricingForItem> {\n return this.http.get(`/cards/${encodeURIComponent(idOrTechnicalName)}/pricing/live`, options);\n }\n\n /** `GET /cards/{id}/pricing`: this card's current pricing snapshot — `retailPrice`,\n * `estimatedValue`, `lowestShopOffer`, `referencePriceSnapshotsByProvider` — refreshed once a day\n * by the nightly pricing/scraper jobs. `get()` returns content only; this is the separate,\n * shorter-cached call for the part of a card that actually changes day to day. */\n pricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<CatalogItemPricing> {\n return this.http.get(`/cards/${encodeURIComponent(idOrTechnicalName)}/pricing`, options);\n }\n\n /** `GET /cards/pricing`: pricing for up to 200 cards in one request, keyed by `id` — the batch\n * counterpart to `pricing()`, for a page of results (a search page, an expansion's contents) that\n * needs pricing for many items at once. Unlike `get()`/`pricing()`, this only accepts `id`s, not\n * technicalNames — pass the `id`s already on the cards you fetched. Ids with no match are\n * silently omitted from the result rather than causing an error. */\n pricingBatch(\n ids: string[],\n options: RequestOptions = {},\n ): Promise<ListResponse<CatalogItemPricing>> {\n return this.http.get(`/cards/pricing?ids=${ids.map(encodeURIComponent).join(',')}`, options);\n }\n\n /** `GET /cards/technical-names`: every card's `technicalName` and `updatedAt`, unpaginated and\n * with no pricing joins. Built for enumerating the whole catalog cheaply — a sitemap, or working\n * out which items changed since your last sync — where `list()` would make you page through full\n * card documents to learn the same two fields. */\n technicalNames(options: RequestOptions = {}): Promise<ListResponse<CatalogSlug>> {\n return this.http.get('/cards/technical-names', options);\n }\n\n /** `GET /cards/price-stats/daily`: daily average price history, cards only. The same data as\n * `client.priceStats.daily()`, scoped to the card catalog so a filter like `expansion` can't pull\n * in that expansion's sealed products too. */\n dailyStats(params: CardDailyStatsParams = {}): Promise<ListResponse<ItemDailyStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards/price-stats/daily${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/price-stats/estimated-values`: current estimated market value, cards only. The\n * card-scoped counterpart to `client.priceStats.estimatedValues()`. */\n estimatedValues(\n params: CardEstimatedValuesParams = {},\n ): Promise<ListResponse<ItemEstimatedValue>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/cards/price-stats/estimated-values${toQueryString(query)}`,\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type {\n Card,\n Expansion,\n ExpansionLivePricing,\n ExpansionRef,\n ListResponse,\n SealedProduct,\n} from '../types/index.js';\n\nexport class ExpansionsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /expansions`: every expansion. Unwrapped to a plain array, nothing to paginate here. */\n async list(options: RequestOptions = {}): Promise<Expansion[]> {\n const res = await this.http.get<{ data: Expansion[] }>('/expansions', options);\n return res.data;\n }\n\n /** `GET /expansions/{technicalName}`: metadata only — no cards or sealed products. Returns the\n * smaller `ExpansionRef`, not the full `Expansion`: this is a plain lookup by technicalName, not\n * the aggregation `list()` runs, so `sealedCount`/`cardCount`/`productCount` aren't available\n * here. See `cards()` and `sealedProducts()` for this expansion's contents. */\n get(technicalName: string, options: RequestOptions = {}): Promise<ExpansionRef> {\n return this.http.get(`/expansions/${encodeURIComponent(technicalName)}`, options);\n }\n\n /** `GET /expansions/{technicalName}/cards`: every card in this expansion. Content only, no\n * pricing fields — pass the `id`s from the result to `client.cards.pricingBatch()` if you need\n * pricing too. Sealed products are a separate call — see `sealedProducts()` — never merged into\n * this one. */\n cards(technicalName: string, options: RequestOptions = {}): Promise<ListResponse<Card>> {\n return this.http.get(`/expansions/${encodeURIComponent(technicalName)}/cards`, options);\n }\n\n /** `GET /expansions/{technicalName}/products`: every sealed product in this expansion. Content\n * only, no pricing fields — pass the `id`s from the result to `client.products.pricingBatch()`\n * if you need pricing too. Cards are a separate call — see `cards()` — never merged into this\n * one. */\n sealedProducts(\n technicalName: string,\n options: RequestOptions = {},\n ): Promise<ListResponse<SealedProduct>> {\n return this.http.get(`/expansions/${encodeURIComponent(technicalName)}/products`, options);\n }\n\n /** `GET /expansions/{technicalName}/cards/live-pricing`: computed fresh for every card in this\n * expansion, not read from the last stats job. Premium. */\n cardsLivePricing(\n technicalName: string,\n options: RequestOptions = {},\n ): Promise<ExpansionLivePricing> {\n return this.http.get(\n `/expansions/${encodeURIComponent(technicalName)}/cards/live-pricing`,\n options,\n );\n }\n\n /** `GET /expansions/{technicalName}/products/live-pricing`: computed fresh for every sealed\n * product in this expansion, not read from the last stats job. Premium. */\n productsLivePricing(\n technicalName: string,\n options: RequestOptions = {},\n ): Promise<ExpansionLivePricing> {\n return this.http.get(\n `/expansions/${encodeURIComponent(technicalName)}/products/live-pricing`,\n options,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type { PackRate } from '../types/index.js';\n\nexport class PackRatesResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /pack-rates`: pull-rate odds for every expansion that has them. Unwrapped to a plain\n * array, nothing to paginate here. */\n async list(options: RequestOptions = {}): Promise<PackRate[]> {\n const res = await this.http.get<{ data: PackRate[] }>('/pack-rates', options);\n return res.data;\n }\n\n /** `GET /pack-rates/{expansionId}`: pull-rate odds for one expansion. */\n get(expansionId: string, options: RequestOptions = {}): Promise<PackRate> {\n return this.http.get(`/pack-rates/${encodeURIComponent(expansionId)}`, options);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n CardType,\n GradingCompany,\n ItemCondition,\n ItemDailyStats,\n ItemEstimatedValue,\n ItemFullStats,\n ItemStats,\n ItemVariantDailyStats,\n ItemVariantStats,\n ListResponse,\n TopItem,\n} from '../types/index.js';\n\n/** Filters shared by `daily()` and `estimatedValues()`: all narrow which product(s) the stats\n * cover; combine as many as you like. */\nexport interface ProductFilterParams extends RequestOptions {\n productName?: string;\n technicalName?: string;\n priceChartingId?: string;\n modelNumber?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n}\n\nexport interface DailyPriceStatsParams extends ProductFilterParams {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n /** Expansion id (ObjectId), an alternative to `expansion` (technicalName). */\n expansionId?: string;\n /** Category id (ObjectId), an alternative to `category` (technicalName). */\n categoryId?: string;\n}\n\nexport interface EstimatedValuesParams extends ProductFilterParams {\n page?: number;\n limit?: number;\n}\n\nexport interface TopProductsParams extends RequestOptions {\n limit?: number;\n}\n\nexport interface ProductDailyStatsParams extends RequestOptions {\n /** Number of days to retrieve, from today backwards. Default 30. */\n days?: number;\n}\n\nexport interface ProductByVariantParams extends RequestOptions {\n /** Number of days to include in the average calculation. Default 30. */\n days?: number;\n}\n\nexport interface ProductDailyByVariantParams extends RequestOptions {\n cardType: CardType;\n /** Required when `cardType` is `'loose'`. */\n condition?: ItemCondition;\n /** Required when `cardType` is `'graded'`. */\n gradingCompany?: GradingCompany;\n /** Required when `cardType` is `'graded'`. */\n grade?: number;\n /** Number of days to retrieve. Default 30. */\n days?: number;\n}\n\nexport class PriceStatsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /price-stats/daily`: daily average price history, filtered to matching product(s). */\n daily(params: DailyPriceStatsParams = {}): Promise<ListResponse<ItemDailyStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/price-stats/daily${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /price-stats/estimated-values`: current estimated market value, filtered to matching\n * product(s). */\n estimatedValues(params: EstimatedValuesParams = {}): Promise<ListResponse<ItemEstimatedValue>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/price-stats/estimated-values${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /price-stats/top-products`: items ranked by shop availability (how many shops carry\n * them), not by price. */\n topProducts(params: TopProductsParams = {}): Promise<ListResponse<TopItem>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/price-stats/top-products${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /price-stats/product/{id}`: daily price history, current estimate, and a variant-count\n * summary for one product. Premium. */\n product(idOrTechnicalName: string, options: RequestOptions = {}): Promise<ItemStats> {\n return this.http.get(`/price-stats/product/${encodeURIComponent(idOrTechnicalName)}`, options);\n }\n\n /** `GET /price-stats/product/{id}/full`: everything `product()` has, plus the item's current\n * shop matches. Premium. */\n productFull(idOrTechnicalName: string, options: RequestOptions = {}): Promise<ItemFullStats> {\n return this.http.get(`/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/full`, options);\n }\n\n /** `GET /price-stats/product/{id}/daily`: daily price history for one product, with a\n * caller-chosen window. Premium. */\n productDaily(\n idOrTechnicalName: string,\n params: ProductDailyStatsParams = {},\n ): Promise<ItemDailyStats> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/daily${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /price-stats/product/{id}/daily-last-30`: daily price history for the last 30 days\n * exactly (no window param, for callers that want a stable cache key). Premium. */\n productDailyLast30(idOrTechnicalName: string, options: RequestOptions = {}): Promise<ItemDailyStats> {\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/daily-last-30`,\n options,\n );\n }\n\n /** `GET /price-stats/product/{id}/estimated-value`: current estimated value only. Premium. */\n productEstimatedValue(\n idOrTechnicalName: string,\n options: RequestOptions = {},\n ): Promise<ItemEstimatedValue> {\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/estimated-value`,\n options,\n );\n }\n\n /** `GET /price-stats/product/{id}/by-variant`: price stats broken out per card condition/grade.\n * Premium. */\n productByVariant(\n idOrTechnicalName: string,\n params: ProductByVariantParams = {},\n ): Promise<ItemVariantStats> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/by-variant${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /price-stats/product/{id}/daily-by-variant`: daily price history for one specific\n * condition/grade. `condition` is required for `cardType: 'loose'`; `gradingCompany` and `grade`\n * are required for `cardType: 'graded'`. Premium. */\n productDailyByVariant(\n idOrTechnicalName: string,\n params: ProductDailyByVariantParams,\n ): Promise<ItemVariantDailyStats> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/daily-by-variant${toQueryString(query)}`,\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n CardType,\n CatalogItemPricing,\n CatalogSlug,\n GradingCompany,\n ItemCondition,\n ItemDailyStats,\n ItemEstimatedValue,\n ItemReferencePrices,\n ItemShopMatches,\n ItemSoldPrices,\n ListResponse,\n LivePricingForItem,\n PaginationParams,\n ReferencePriceProvider,\n SealedProduct,\n} from '../types/index.js';\n\nexport interface ListProductsParams extends PaginationParams {}\n\nexport interface SearchProductsParams extends PaginationParams {\n /** Whitespace-separated tokens, each matched against the start of a word. */\n search?: string;\n}\n\nexport interface ProductMatchesParams extends PaginationParams {\n /** Keep only matches whose shop currently has stock. */\n inStock?: boolean;\n cardType?: CardType;\n condition?: ItemCondition;\n gradingCompany?: GradingCompany;\n grade?: number;\n}\n\nexport interface ProductReferencePricesParams extends RequestOptions {\n authToken?: string;\n /** Rolling window ending today, in days. Ignored when `from`/`to` are supplied. Default 90. */\n days?: number;\n /** `YYYY-MM-DD` */\n from?: string;\n /** `YYYY-MM-DD` */\n to?: string;\n provider?: ReferencePriceProvider;\n}\n\nexport interface ProductPricesParams extends PaginationParams {}\n\n/** Filters for `products.dailyStats()`. Narrow to one product, or to a whole expansion/category. */\nexport interface ProductDailyPriceStatsParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n productName?: string;\n technicalName?: string;\n priceChartingId?: string;\n modelNumber?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n /** Category id (ObjectId), an alternative to `category`. */\n categoryId?: string;\n /** Expansion id (ObjectId), an alternative to `expansion`. */\n expansionId?: string;\n}\n\n/** Filters for `products.estimatedValues()`. Note `page`/`limit`, not the `limit`/`skip` the rest\n * of the API paginates with — this endpoint predates that convention. */\nexport interface ProductEstimatedValuesParams extends RequestOptions {\n page?: number;\n limit?: number;\n productName?: string;\n technicalName?: string;\n priceChartingId?: string;\n modelNumber?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n}\n\n/** Sealed products: booster boxes, ETBs, tins, and the like. Single cards live under\n * `client.cards` instead. */\nexport class ProductsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /product`: list sealed products, newest first. No free-text search — use `search()` for\n * that. */\n list(params: ListProductsParams = {}): Promise<ListResponse<SealedProduct>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/product${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /product/search`: like `list()`, but with free-text search on the product name. Premium. */\n search(params: SearchProductsParams = {}): Promise<ListResponse<SealedProduct>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/product/search${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /product/{id}`: fetch one sealed product by its id or technicalName. */\n get(idOrTechnicalName: string, options: RequestOptions = {}): Promise<SealedProduct> {\n return this.http.get(`/product/${encodeURIComponent(idOrTechnicalName)}`, options);\n }\n\n /** `GET /product/{id}/matches`: current shop listings matched to this product (latest per shop). */\n matches(idOrTechnicalName: string, params: ProductMatchesParams = {}): Promise<ItemShopMatches> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/${encodeURIComponent(idOrTechnicalName)}/matches${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /product/{id}/reference-prices`: Cardmarket/TCGplayer/Tradera price history. Premium. */\n referencePrices(\n idOrTechnicalName: string,\n params: ProductReferencePricesParams = {},\n ): Promise<ItemReferencePrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/${encodeURIComponent(idOrTechnicalName)}/reference-prices${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /product/{id}/prices`: individual marketplace sale records. Premium. */\n prices(idOrTechnicalName: string, params: ProductPricesParams = {}): Promise<ItemSoldPrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/${encodeURIComponent(idOrTechnicalName)}/prices${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /product/{id}/pricing/live`: computed fresh for this request, not read from the last\n * stats job. Premium. */\n livePricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<LivePricingForItem> {\n return this.http.get(`/product/${encodeURIComponent(idOrTechnicalName)}/pricing/live`, options);\n }\n\n /** `GET /product/{id}/pricing`: this product's current pricing snapshot — `retailPrice`,\n * `estimatedValue`, `lowestShopOffer`, `referencePriceSnapshotsByProvider` — refreshed once a day\n * by the nightly pricing/scraper jobs. `get()` returns content only; this is the separate,\n * shorter-cached call for the part of a product that actually changes day to day. */\n pricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<CatalogItemPricing> {\n return this.http.get(`/product/${encodeURIComponent(idOrTechnicalName)}/pricing`, options);\n }\n\n /** `GET /product/pricing`: pricing for up to 200 sealed products in one request, keyed by `id` —\n * the batch counterpart to `pricing()`, for a page of results (a search page, an expansion's\n * contents) that needs pricing for many items at once. Unlike `get()`/`pricing()`, this only\n * accepts `id`s, not technicalNames — pass the `id`s already on the products you fetched. Ids with\n * no match are silently omitted from the result rather than causing an error. */\n pricingBatch(\n ids: string[],\n options: RequestOptions = {},\n ): Promise<ListResponse<CatalogItemPricing>> {\n return this.http.get(`/product/pricing?ids=${ids.map(encodeURIComponent).join(',')}`, options);\n }\n\n /** `GET /product/technical-names`: every sealed product's `technicalName` and `updatedAt`,\n * unpaginated and with no pricing joins. The sealed counterpart to\n * `client.cards.technicalNames()` — for sitemaps and incremental syncs. */\n technicalNames(options: RequestOptions = {}): Promise<ListResponse<CatalogSlug>> {\n return this.http.get('/product/technical-names', options);\n }\n\n /** `GET /product/price-stats/daily`: daily average price history, sealed products only. The same\n * data as `client.priceStats.daily()`, scoped to the sealed catalog so a filter like `expansion`\n * can't pull in that expansion's single cards too. */\n dailyStats(params: ProductDailyPriceStatsParams = {}): Promise<ListResponse<ItemDailyStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/product/price-stats/daily${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /product/price-stats/estimated-values`: current estimated market value, sealed products\n * only. The sealed-scoped counterpart to `client.priceStats.estimatedValues()`. */\n estimatedValues(\n params: ProductEstimatedValuesParams = {},\n ): Promise<ListResponse<ItemEstimatedValue>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/price-stats/estimated-values${toQueryString(query)}`,\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type { ItemPriceComparison, ItemShopPriceHistory, ShopPriceHistoryList } from '../types/index.js';\n\nexport interface ShopMatchStatsForProductParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n /** Filter to one shop's technicalName. */\n shop?: string;\n}\n\nexport interface ShopMatchStatsForShopParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n /** Maximum products to return. Default 20, max 50. */\n limit?: number;\n}\n\nexport interface CompareShopPricesParams extends RequestOptions {\n /** Product/card id or technicalName. */\n productId: string;\n /** `YYYY-MM-DD`: defaults to the latest date with data. */\n date?: string;\n}\n\n/** Historical shop-vs-price data, distinct from `client.shopMatches` (which is the current/latest\n * match state). Everything here is premium. */\nexport class ShopMatchStatsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /shop-match-stats/product/{productId}`: one product's price history, broken out per shop. */\n forProduct(\n productId: string,\n params: ShopMatchStatsForProductParams = {},\n ): Promise<ItemShopPriceHistory> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/shop-match-stats/product/${encodeURIComponent(productId)}${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /shop-match-stats/shop/{shop}`: one shop's price history, broken out per product. */\n forShop(shop: string, params: ShopMatchStatsForShopParams = {}): Promise<ShopPriceHistoryList> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-match-stats/shop/${encodeURIComponent(shop)}${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /shop-match-stats/compare`: one product's price at every shop that carries it, as of\n * one date (defaults to the latest). */\n compare(params: CompareShopPricesParams): Promise<ItemPriceComparison> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-match-stats/compare${toQueryString(query)}`, requestOptions);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type { ListResponse, PaginationParams, ShopMatch, ShopMatchesForShop, ShopMatchStats } from '../types/index.js';\n\nexport interface ListShopMatchesParams extends PaginationParams {\n /** Filter to one shop's technicalName. */\n shop?: string;\n inStock?: boolean;\n /** Filter by whether the listing has been resolved to a catalog item. */\n linked?: boolean;\n}\n\nexport interface ShopMatchesForShopParams extends PaginationParams {\n inStock?: boolean;\n}\n\n/** Raw shop-to-catalog match data: what's currently listed where, independent of which item or\n * shop you start from. For \"what does this card cost at each shop\" or \"what's in stock at this\n * shop\", prefer `client.cards.matches()` / `client.products.matches()` /\n * `client.shopMatches.forShop()`. */\nexport class ShopMatchesResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /shop-matches`: every current match across every shop (latest record per url+shop). */\n list(params: ListShopMatchesParams = {}): Promise<ListResponse<ShopMatch>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-matches${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /shop-matches/{shop}`: every current match at one shop (latest record per url). */\n forShop(technicalName: string, params: ShopMatchesForShopParams = {}): Promise<ShopMatchesForShop> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/shop-matches/${encodeURIComponent(technicalName)}${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /shop-matches/shops`: match counts per shop (based on latest records only). */\n shopStats(params: PaginationParams = {}): Promise<ListResponse<ShopMatchStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-matches/shops${toQueryString(query)}`, requestOptions);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type { ShopUrlMutationResult } from '../types/index.js';\n\nexport interface SubmitShopUrlParams extends RequestOptions {\n url: string;\n /** Shop technicalName. Auto-created if it doesn't exist yet. */\n shop: string;\n}\n\nexport interface AssignShopUrlProductParams extends RequestOptions {\n /** Product/card id to link, or `null` to unlink and let auto-matching resume. */\n productId: string | null;\n}\n\n/** Lets a signed-in subscriber contribute to the catalog: submit a shop URL for scraping, or\n * manually correct which product/card a URL resolves to. Both premium, both mutating. */\nexport class ShopUrlsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `POST /shop-urls/submit`: submit a shop URL for scraping. */\n submit(params: SubmitShopUrlParams): Promise<ShopUrlMutationResult> {\n const { url, shop, ...requestOptions } = params;\n return this.http.post('/shop-urls/submit', { url, shop }, requestOptions);\n }\n\n /** `PATCH /shop-urls/{id}/product`: manually assign (or clear) the product a shop URL resolves to. */\n assignProduct(\n shopUrlId: string,\n params: AssignShopUrlProductParams,\n ): Promise<ShopUrlMutationResult> {\n const { productId, ...requestOptions } = params;\n return this.http.patch(\n `/shop-urls/${encodeURIComponent(shopUrlId)}/product`,\n { productId },\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type { Shop } from '../types/index.js';\n\nexport interface ListShopsParams extends RequestOptions {\n active?: boolean;\n}\n\nexport class ShopsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /shops`: every tracked shop. Unwrapped to a plain array, nothing to paginate here. */\n async list(params: ListShopsParams = {}): Promise<Shop[]> {\n const [query, requestOptions] = splitRequestOptions(params);\n const res = await this.http.get<{ data: Shop[] }>(`/shops${toQueryString(query)}`, requestOptions);\n return res.data;\n }\n\n /** `GET /shops/{id}`: fetch one shop by its id or technicalName. */\n get(idOrTechnicalName: string, options: RequestOptions = {}): Promise<Shop> {\n return this.http.get(`/shops/${encodeURIComponent(idOrTechnicalName)}`, options);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type { PlatformStats } from '../types/index.js';\n\nexport class StatsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /stats`: platform-wide overview counts (shops, expansions, products, prices tracked). */\n platform(options: RequestOptions = {}): Promise<PlatformStats> {\n return this.http.get('/stats', options);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type {\n Acknowledgement,\n ListResponse,\n Webhook,\n WebhookEvent,\n WebhookTestResult,\n WebhookWithSecret,\n} from '../types/index.js';\n\nexport interface CreateWebhookParams extends RequestOptions {\n /**\n * Where deliveries are POSTed. Must be `https://` — the API rejects plaintext, since a delivery\n * carries the signature that authenticates it.\n */\n url: string;\n /** At least one event to subscribe to. */\n events: WebhookEvent[];\n}\n\n/**\n * Outbound webhooks: the API calls you when something changes, instead of you polling for it.\n *\n * Business tier, not Premium — a Premium token answers `403 businessRequired`. The feature is also\n * behind a server-side flag, and when that flag is off these answer `404 notFound` rather than 403,\n * so a `notFound` here means \"not enabled on this instance\", not \"wrong id\".\n */\nexport class WebhooksResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * `POST /webhooks`: register a new webhook.\n *\n * The returned `secret` is the only copy you will ever get — sign-verification depends on it and\n * no endpoint reads it back. Persist it here, at creation, or delete the webhook and make a new\n * one.\n */\n create(params: CreateWebhookParams): Promise<WebhookWithSecret> {\n const { url, events, ...requestOptions } = params;\n return this.http.post('/webhooks', { url, events }, requestOptions);\n }\n\n /** `GET /webhooks`: every webhook registered on this account. Secrets are never included. */\n list(options: RequestOptions = {}): Promise<ListResponse<Webhook>> {\n return this.http.get('/webhooks', options);\n }\n\n /** `DELETE /webhooks/{id}`: revoke a webhook. Deliveries stop immediately; its secret is void. */\n delete(webhookId: string, options: RequestOptions = {}): Promise<Acknowledgement> {\n return this.http.delete(`/webhooks/${encodeURIComponent(webhookId)}`, options);\n }\n\n /** `POST /webhooks/{id}/test`: send a sample delivery to the registered URL, so you can verify\n * your endpoint and your signature check before waiting on a real event. */\n test(webhookId: string, options: RequestOptions = {}): Promise<WebhookTestResult> {\n return this.http.post(`/webhooks/${encodeURIComponent(webhookId)}/test`, undefined, options);\n }\n}\n","import { HttpClient } from './http.js';\nimport { BargainsResource } from './resources/bargains.js';\nimport { CardsResource } from './resources/cards.js';\nimport { ExpansionsResource } from './resources/expansions.js';\nimport { PackRatesResource } from './resources/packRates.js';\nimport { PriceStatsResource } from './resources/priceStats.js';\nimport { ProductsResource } from './resources/products.js';\nimport { ShopMatchStatsResource } from './resources/shopMatchStats.js';\nimport { ShopMatchesResource } from './resources/shopMatches.js';\nimport { ShopUrlsResource } from './resources/shopUrls.js';\nimport { ShopsResource } from './resources/shops.js';\nimport { StatsResource } from './resources/stats.js';\nimport { WebhooksResource } from './resources/webhooks.js';\n\nexport const DEFAULT_BASE_URL = 'https://api.tcgpriser.se';\n\n/** Local dev, self-hosting and testing overrides. Most integrations never touch these. */\nexport interface TcgPriserAdvancedOptions {\n /** Point at a local dev server or a self-hosted instance. Defaults to production. */\n baseUrl?: string;\n /** Extra headers sent on every request, e.g. a custom `User-Agent`. */\n headers?: Record<string, string>;\n /** Swap in a different `fetch` (older Node, testing, a proxying agent). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /**\n * Default milliseconds before a request is aborted, for every call this client makes. Defaults to\n * `DEFAULT_TIMEOUT_MS` (60s). `0` disables the timeout entirely. Every method can override it per\n * call with `timeoutMs`.\n */\n timeoutMs?: number;\n}\n\nexport interface TcgPriserOptions {\n /**\n * A per-account API token, generated from your account page at tcgpriser.se/account/api-token.\n * Only needed for premium methods (`cards.prices()`, `priceStats.product()`,\n * `bargains.search()` etc.); public methods work fine without it. This client has no login flow\n * of its own, and doesn't need one: the API token is a long-lived, revocable secret made for\n * exactly this, so there's no OAuth dance to drive.\n *\n * Every premium method also accepts its own `authToken` to override this per call. Useful when\n * one server-side client is shared across requests for several different signed-in users.\n */\n authToken?: string;\n /** Local dev / self-hosting / testing overrides. Leave unset unless you know you need it. */\n advanced?: TcgPriserAdvancedOptions;\n}\n\n/**\n * Client for the tcgpriser.se API: Pokémon TCG price data, catalog, shop matches and bargains for\n * shops tracked in Sweden.\n *\n * ```ts\n * import { TcgPriser } from 'tcgpriser';\n *\n * const tcgpriser = new TcgPriser();\n * const card = await tcgpriser.cards.get('mega-evolution-ascended-heroes-fezandipiti-ex');\n * console.log(card.retailPrice, card.lowestShopOffer?.shop.name);\n * ```\n *\n * That example needs no token. Most of the API is public (https://api.tcgpriser.se/docs). A\n * smaller set of premium methods (live pricing, per-condition history, shop comparison, bargain\n * search, shop-URL submission) need a Premium subscriber's API token\n * (https://api.tcgpriser.se/premium-docs), generated from tcgpriser.se/account/api-token:\n *\n * ```ts\n * const tcgpriser = new TcgPriser(myApiToken); // shorthand for { authToken: myApiToken }\n * await tcgpriser.cards.livePricing('fezandipiti-ex');\n * ```\n */\nexport class TcgPriser {\n readonly cards: CardsResource;\n readonly products: ProductsResource;\n readonly expansions: ExpansionsResource;\n readonly shops: ShopsResource;\n readonly shopMatches: ShopMatchesResource;\n readonly shopMatchStats: ShopMatchStatsResource;\n readonly shopUrls: ShopUrlsResource;\n readonly priceStats: PriceStatsResource;\n readonly bargains: BargainsResource;\n readonly packRates: PackRatesResource;\n readonly stats: StatsResource;\n readonly webhooks: WebhooksResource;\n\n /** Holds the `HttpClient` so `creditsRemaining` can read the running value off it. */\n private readonly http: HttpClient;\n\n /**\n * @param optionsOrAuthToken A subscriber's API token (`new TcgPriser(myApiToken)`), a full\n * `TcgPriserOptions` object, or omit it entirely for an anonymous, public-only client.\n */\n constructor(optionsOrAuthToken?: string | TcgPriserOptions) {\n const options: TcgPriserOptions =\n typeof optionsOrAuthToken === 'string' ? { authToken: optionsOrAuthToken } : (optionsOrAuthToken ?? {});\n const advanced = options.advanced ?? {};\n\n if (!advanced.fetch && typeof fetch === 'undefined') {\n throw new Error(\n 'tcgpriser: no global fetch found. Pass { advanced: { fetch } } explicitly on Node < 18, or run on Node 18+.',\n );\n }\n\n const http = new HttpClient({\n timeoutMs: advanced.timeoutMs,\n baseUrl: advanced.baseUrl ?? DEFAULT_BASE_URL,\n // Bound to globalThis: both browsers and Node's undici implement fetch as a method that\n // checks its receiver, so an unbound reference throws \"Illegal invocation\" the moment it's\n // called through anything other than `window.fetch(...)`/`globalThis.fetch(...)` — which is\n // exactly what happens once HttpClient stores it and calls `this.fetchImpl(...)`.\n fetch: advanced.fetch ?? fetch.bind(globalThis),\n headers: advanced.headers,\n authToken: options.authToken,\n });\n\n this.cards = new CardsResource(http);\n this.products = new ProductsResource(http);\n this.expansions = new ExpansionsResource(http);\n this.shops = new ShopsResource(http);\n this.shopMatches = new ShopMatchesResource(http);\n this.shopMatchStats = new ShopMatchStatsResource(http);\n this.shopUrls = new ShopUrlsResource(http);\n this.priceStats = new PriceStatsResource(http);\n this.bargains = new BargainsResource(http);\n this.packRates = new PackRatesResource(http);\n this.stats = new StatsResource(http);\n this.webhooks = new WebhooksResource(http);\n this.http = http;\n }\n\n /**\n * Credits left in this week's allowance, as of the last charged call this client made.\n *\n * The API returns `X-Credits-Remaining` on every response it charges for, so this needs no extra\n * request — but it is only as current as your last premium call, and it is `undefined` until you\n * make one. Uncharged calls (every public method, and any call authenticated with something other\n * than an API token) don't update it, because the API doesn't meter them.\n *\n * ```ts\n * await tcgpriser.cards.livePricing('fezandipiti-ex');\n * if ((tcgpriser.creditsRemaining ?? Infinity) < 100) scheduleFewerRefreshes();\n * ```\n *\n * Reading it in a browser additionally needs the API to expose the header via CORS, which it does.\n */\n get creditsRemaining(): number | undefined {\n return this.http.creditsRemaining;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/resources/bargains.ts","../src/resources/brands.ts","../src/resources/cards.ts","../src/resources/expansions.ts","../src/resources/packRates.ts","../src/resources/priceStats.ts","../src/resources/products.ts","../src/resources/shopMatchStats.ts","../src/resources/shopMatches.ts","../src/resources/shopUrls.ts","../src/resources/shops.ts","../src/resources/stats.ts","../src/resources/webhooks.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/** The stable error codes the API's `error.code` field can hold. */\nexport type TcgPriserErrorCode =\n | 'validationFailed'\n | 'unauthorized'\n | 'forbidden'\n | 'notFound'\n | 'conflict'\n | 'readOnlyField'\n | 'rateLimited'\n | 'premiumRequired'\n | 'businessRequired'\n | 'creditsExhausted'\n | 'internalError'\n /** The request exceeded its `timeoutMs` and was aborted client-side. Never sent by the API — the\n * one code this package raises on its own, so a stalled connection is distinguishable from a\n * server that answered. */\n | 'timeout'\n /** Response body wasn't the `{ error: { code, message } }` shape. Probably a proxy or gateway\n * error in front of the API. */\n | 'unknown';\n\n/** Thrown for any non-2xx response. Carries the parsed `{ code, message }` when the body matched\n * the API's error envelope, plus the raw status/body regardless so nothing gets lost. */\nexport class TcgPriserError extends Error {\n readonly statusCode: number;\n readonly statusText: string;\n readonly url: string;\n readonly code: TcgPriserErrorCode;\n readonly details: unknown;\n /** The raw response body, for debugging when `code`/`details` don't cover what you need. */\n readonly body: string;\n /**\n * Seconds to wait before retrying, from the `Retry-After` header. Present on `rateLimited`, and\n * on anything else a proxy in front of the API decides to send it with. Absent otherwise — an\n * error without it is not one that says retrying will help.\n */\n readonly retryAfter: number | undefined;\n /**\n * Credits left in this week's allowance, from `X-Credits-Remaining`. Present on errors from\n * charged routes — notably `creditsExhausted`, where it is `0`. Absent on uncharged routes and on\n * anything a proxy answered instead of the API.\n */\n readonly creditsRemaining: number | undefined;\n\n constructor(params: {\n statusCode: number;\n statusText: string;\n url: string;\n code: TcgPriserErrorCode;\n message: string;\n details?: unknown;\n body: string;\n retryAfter?: number;\n creditsRemaining?: number;\n }) {\n // `statusCode` is 0 for a client-side timeout, where there was no response to have a status.\n // Printing \"tcgpriser: 0 timeout - ...\" would read like a bug in the message itself.\n const status = params.statusCode === 0 ? '' : `${params.statusCode} `;\n super(`tcgpriser: ${status}${params.code} - ${params.message} (${params.url})`);\n this.name = 'TcgPriserError';\n this.statusCode = params.statusCode;\n this.statusText = params.statusText;\n this.url = params.url;\n this.code = params.code;\n this.details = params.details;\n this.body = params.body;\n this.retryAfter = params.retryAfter;\n this.creditsRemaining = params.creditsRemaining;\n }\n}\n","import { TcgPriserError, type TcgPriserErrorCode } from './errors.js';\n\nexport type QueryValue = string | number | boolean | undefined | null;\n\n/**\n * Builds a query string from a params object, dropping `undefined`/`null` entries so callers can\n * pass params straight through without filtering first.\n *\n * Takes a generic `object` instead of `Record<string, QueryValue>` on purpose. The params\n * interfaces (`ListCardsParams` etc.) intentionally have no index signature, otherwise any string\n * key would type-check.\n */\nexport function toQueryString<T extends object>(params: T): string {\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(params) as [string, QueryValue][]) {\n if (value === undefined || value === null) continue;\n search.set(key, String(value));\n }\n const query = search.toString();\n return query ? `?${query}` : '';\n}\n\n/**\n * Splits the per-call request options off a params object so they don't end up in the query string.\n *\n * `authToken` is the reason this exists: a bearer token has no business in a URL, because query\n * strings end up in server logs, browser history and `Referer` headers. `signal` and `timeoutMs`\n * ride along for the same structural reason — they configure the request rather than describe it,\n * and `String(anAbortSignal)` in a URL would be nonsense.\n */\nexport function splitRequestOptions<T extends RequestOptions>(\n params: T,\n): [Omit<T, keyof RequestOptions>, RequestOptions] {\n const { authToken, signal, timeoutMs, ...rest } = params;\n return [rest, { authToken, signal, timeoutMs }];\n}\n\n/** @deprecated Renamed to `splitRequestOptions`, which also splits off `signal`/`timeoutMs`. */\nexport const splitAuthToken = splitRequestOptions;\n\nconst KNOWN_ERROR_CODES: ReadonlySet<string> = new Set([\n 'validationFailed',\n 'unauthorized',\n 'forbidden',\n 'notFound',\n 'conflict',\n 'readOnlyField',\n 'rateLimited',\n 'premiumRequired',\n 'businessRequired',\n 'creditsExhausted',\n 'internalError',\n]);\n\n/** Parses a header that should hold a non-negative integer, ignoring anything that doesn't. */\nfunction readIntHeader(res: Response, name: string): number | undefined {\n const raw = res.headers.get(name);\n if (raw === null) return undefined;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;\n}\n\nasync function toApiError(res: Response, url: string): Promise<TcgPriserError> {\n const body = await res.text();\n let code: TcgPriserErrorCode = 'unknown';\n let message = res.statusText || 'Request failed';\n let details: unknown;\n\n try {\n const parsed = JSON.parse(body) as { error?: { code?: string; message?: string; details?: unknown } };\n if (parsed.error?.code && KNOWN_ERROR_CODES.has(parsed.error.code)) {\n code = parsed.error.code as TcgPriserErrorCode;\n }\n if (parsed.error?.message) message = parsed.error.message;\n details = parsed.error?.details;\n } catch {\n // Not the standard error envelope, maybe a proxy's HTML error page. Fall back to the status\n // text and leave `body` for anyone who wants to dig in.\n }\n\n return new TcgPriserError({\n statusCode: res.status,\n statusText: res.statusText,\n url,\n code,\n message,\n details,\n body,\n // Both are most useful on exactly the errors that carry them: `retryAfter` on `rateLimited`,\n // `creditsRemaining` on `creditsExhausted` (where it is 0) and on any error from a charged\n // route. Read unconditionally rather than branching on the code, since a proxy can return a\n // 429 with `Retry-After` and no envelope at all.\n retryAfter: readIntHeader(res, 'Retry-After'),\n creditsRemaining: readIntHeader(res, 'X-Credits-Remaining'),\n });\n}\n\nexport interface HttpClientOptions {\n baseUrl: string;\n fetch: typeof fetch;\n headers?: Record<string, string>;\n /** Default bearer token for premium endpoints, used when a call doesn't pass its own `authToken`. */\n authToken?: string;\n /** Default per-request timeout. See `RequestOptions.timeoutMs`. */\n timeoutMs?: number;\n}\n\n/**\n * Per-call overrides, accepted by every method — either standalone or merged into its params object\n * and split back out by `splitRequestOptions`.\n */\nexport interface RequestOptions {\n /**\n * Overrides the client's default `authToken` for this call. Pass `undefined` explicitly to force\n * an anonymous request even when the client has a default token.\n */\n authToken?: string;\n /**\n * Cancel the request from outside — a user navigating away, a parent operation being abandoned.\n * Composed with `timeoutMs`, so whichever fires first wins; aborting through this signal rejects\n * with the standard `AbortError`, not a `TcgPriserError`.\n */\n signal?: AbortSignal;\n /**\n * Milliseconds before this request is aborted, overriding the client's default. `0` disables the\n * timeout for this call, which is occasionally right for `expansions.cardsLivePricing()` on a very\n * large set. A timeout rejects with a `TcgPriserError` whose `code` is `'timeout'`.\n */\n timeoutMs?: number;\n}\n\n/** @deprecated Renamed to `RequestOptions`, which also carries `signal` and `timeoutMs`. */\nexport type PremiumOptions = RequestOptions;\n\n/**\n * Default request timeout.\n *\n * There was none, which meant a connection that opened and then stalled hung the caller forever\n * with no way out: `fetch` has no built-in timeout, and without a `signal` there is nothing to\n * cancel. A minute is well clear of the slowest thing the API does (a whole-expansion live-pricing\n * recompute) while still being a bound.\n */\nexport const DEFAULT_TIMEOUT_MS = 60_000;\n\n/**\n * Combines the caller's signal with a timeout into one signal, plus the cleanup that cancels the\n * timer once the request settles.\n *\n * Hand-rolled rather than `AbortSignal.any()` + `AbortSignal.timeout()`: those landed in Node 20,\n * and this package supports Node 18. `clear()` matters as much as the combining — a pending\n * `setTimeout` keeps the Node event loop alive, so a short-lived script that finished its work would\n * otherwise sit there until the last timeout elapsed instead of exiting.\n */\nfunction withTimeout(\n timeoutMs: number,\n callerSignal: AbortSignal | undefined,\n): { signal: AbortSignal | undefined; clear: () => void; timedOut: () => boolean } {\n if (timeoutMs <= 0) return { signal: callerSignal, clear: () => {}, timedOut: () => false };\n\n const controller = new AbortController();\n let expired = false;\n\n const timer = setTimeout(() => {\n expired = true;\n controller.abort();\n }, timeoutMs);\n\n const onCallerAbort = (): void => controller.abort();\n if (callerSignal) {\n if (callerSignal.aborted) controller.abort();\n else callerSignal.addEventListener('abort', onCallerAbort, { once: true });\n }\n\n return {\n signal: controller.signal,\n clear: () => {\n clearTimeout(timer);\n callerSignal?.removeEventListener('abort', onCallerAbort);\n },\n timedOut: () => expired,\n };\n}\n\n/** Thin wrapper around `fetch`: joins the base URL, adds default headers, applies the timeout, turns\n * non-2xx responses into a `TcgPriserError`. Every resource method goes through this instead of\n * calling `fetch` directly. */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n private readonly defaultHeaders: Record<string, string>;\n private readonly defaultAuthToken: string | undefined;\n private readonly defaultTimeoutMs: number;\n\n /**\n * The `X-Credits-Remaining` value from the most recent charged response, or `undefined` if no\n * charged call has been made yet. See `TcgPriser.creditsRemaining`.\n */\n creditsRemaining: number | undefined;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n this.fetchImpl = options.fetch;\n this.defaultHeaders = options.headers ?? {};\n this.defaultAuthToken = options.authToken;\n this.defaultTimeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n get<T>(path: string, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('GET', path, undefined, requestOptions);\n }\n\n post<T>(path: string, body: unknown, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('POST', path, body, requestOptions);\n }\n\n patch<T>(path: string, body: unknown, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('PATCH', path, body, requestOptions);\n }\n\n delete<T>(path: string, requestOptions?: RequestOptions): Promise<T> {\n return this.request<T>('DELETE', path, undefined, requestOptions);\n }\n\n private async request<T>(\n method: string,\n path: string,\n body: unknown,\n requestOptions?: RequestOptions,\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const authToken =\n requestOptions && 'authToken' in requestOptions ? requestOptions.authToken : this.defaultAuthToken;\n\n const headers: Record<string, string> = { Accept: 'application/json', ...this.defaultHeaders };\n if (authToken) headers.Authorization = `Bearer ${authToken}`;\n if (body !== undefined) headers['Content-Type'] = 'application/json';\n\n const timeoutMs = requestOptions?.timeoutMs ?? this.defaultTimeoutMs;\n const timeout = withTimeout(timeoutMs, requestOptions?.signal);\n\n let res: Response;\n try {\n res = await this.fetchImpl(url, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: timeout.signal,\n });\n } catch (error) {\n // Distinguish our own timeout from the caller cancelling. An abort we caused is a failure the\n // caller needs to see as one (and retry, or raise the limit); an abort they caused is them\n // getting what they asked for, so it propagates untouched as the standard `AbortError`.\n if (timeout.timedOut()) {\n throw new TcgPriserError({\n statusCode: 0,\n statusText: 'Timeout',\n url,\n code: 'timeout',\n message: `Request timed out after ${timeoutMs}ms`,\n body: '',\n });\n }\n throw error;\n } finally {\n timeout.clear();\n }\n\n // Read before the `res.ok` branch: a `creditsExhausted` rejection is exactly when a caller most\n // wants the balance, and it is charged routes that send this header at all.\n const credits = readIntHeader(res, 'X-Credits-Remaining');\n if (credits !== undefined) this.creditsRemaining = credits;\n\n if (!res.ok) throw await toApiError(res, url);\n if (res.status === 204) return undefined as T;\n return nullsToUndefined(await res.json()) as T;\n }\n}\n\n/** JSON has no `undefined`, so every optional field the API omits comes back over the wire as\n * `null`. Recurses through the parsed response and turns those into `undefined` so callers work\n * with idiomatic `foo?.bar` / `foo ?? fallback` instead of `foo !== null`, and so responses match\n * the `T | undefined` types in `generated/openapi.d.ts` (see `scripts/generate-types.mjs`). */\nfunction nullsToUndefined<T>(value: T): T {\n if (value === null) return undefined as T;\n if (Array.isArray(value)) return value.map(nullsToUndefined) as T;\n if (typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) result[key] = nullsToUndefined(v);\n return result as T;\n }\n return value;\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n Bargain,\n BargainReferenceSource,\n CardType,\n GradingCompany,\n ItemCondition,\n ListResponse,\n PaginationParams,\n} from '../types/index.js';\n\nexport interface ListBargainsParams extends RequestOptions {\n type?: 'sealed' | 'card' | 'all';\n}\n\nexport interface SearchBargainsParams extends PaginationParams {\n type?: 'sealed' | 'card' | 'all';\n /** Filter by shop technicalName. */\n shop?: string;\n /** Filter by which reference price source qualified the bargain. */\n referenceSource?: BargainReferenceSource;\n /** Minimum discount percentage. Default 10. */\n minDiscount?: number;\n /** Default `true`. */\n inStock?: boolean;\n cardType?: CardType;\n itemCondition?: ItemCondition;\n gradingCompany?: GradingCompany;\n grade?: number;\n /** Free-text search on product name / technicalName. */\n search?: string;\n}\n\nexport class BargainsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /bargains`: current shop listings priced notably below their reference price. Result\n * count is fixed by the API (no `limit`/`skip` on the public tier); `pagination.hasMore` tells\n * you if more exist. */\n list(params: ListBargainsParams = {}): Promise<ListResponse<Bargain>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/bargains${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /bargains/search`: like `list()`, but with real pagination and filters (shop, discount\n * threshold, card condition/grade, free-text search). Premium. */\n search(params: SearchBargainsParams = {}): Promise<ListResponse<Bargain>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/bargains/search${toQueryString(query)}`, requestOptions);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type { Brand } from '../types/index.js';\n\n/** The franchises and makers the catalogue carries — what `brand` filters on `cards.list()`,\n * `products.list()` and `expansions.list()` accept. Read-only: brand rows are rare and deliberate\n * on the API side, so there is no create/update method here. */\nexport class BrandsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /brands`: every brand. Unwrapped to a plain array, nothing to paginate here — same\n * shape as `expansions.list()`/`shops.list()`. */\n async list(options: RequestOptions = {}): Promise<Brand[]> {\n const res = await this.http.get<{ data: Brand[] }>('/brands', options);\n return res.data;\n }\n\n /** `GET /brands/{id}`: fetch one brand by its id or technicalName. */\n get(idOrTechnicalName: string, options: RequestOptions = {}): Promise<Brand> {\n return this.http.get(`/brands/${encodeURIComponent(idOrTechnicalName)}`, options);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n Card,\n CardType,\n CatalogItemPricing,\n CatalogSlug,\n ItemReferencePrices,\n ItemShopMatches,\n ItemSoldPrices,\n ItemDailyStats,\n ItemEstimatedValue,\n ListResponse,\n LivePricingForItem,\n PaginationParams,\n ProductLine,\n ReferencePriceCardVariant,\n ReferencePriceProvider,\n} from '../types/index.js';\n\nexport interface ListCardsParams extends PaginationParams {\n /** Brand `id` or technicalName, e.g. `'pokemon'`. Scopes the listing to one game/universe. An\n * unrecognized value is a 400, not an empty page. */\n brand?: string;\n productLine?: ProductLine;\n}\n\nexport interface GetCardParams extends RequestOptions {\n /** Brand `id` or technicalName. Disambiguates a `technicalName` two brands both happen to use —\n * irrelevant while the catalogue carries only one brand, and unused for an `id` lookup. */\n brand?: string;\n}\n\nexport interface SearchCardsParams extends PaginationParams {\n /** Free-text search over card and set names. */\n search?: string;\n}\n\nexport interface CardMatchesParams extends PaginationParams {\n /** Keep only matches whose shop currently has stock. */\n inStock?: boolean;\n}\n\nexport interface CardReferencePricesParams extends RequestOptions {\n /** Bearer token for this call. Overrides the client's default `authToken`. */\n authToken?: string;\n /** Rolling window ending today, in days. Ignored when `from`/`to` are supplied. Default 90. */\n days?: number;\n /** `YYYY-MM-DD` */\n from?: string;\n /** `YYYY-MM-DD` */\n to?: string;\n provider?: ReferencePriceProvider;\n cardType?: CardType;\n variant?: ReferencePriceCardVariant;\n}\n\nexport interface CardPricesParams extends PaginationParams {}\n\n/** Filters for `cards.dailyStats()`. Narrow to one card, or to a whole expansion/category. */\nexport interface CardDailyStatsParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n productName?: string;\n technicalName?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n /** Category id (ObjectId), an alternative to `category`. */\n categoryId?: string;\n /** Expansion id (ObjectId), an alternative to `expansion`. */\n expansionId?: string;\n /** Brand technicalName. */\n brand?: string;\n /** Brand id (ObjectId), an alternative to `brand`. */\n brandId?: string;\n productLine?: ProductLine;\n}\n\n/** Filters for `cards.estimatedValues()`. Note `page`/`limit`, not the `limit`/`skip` the rest of\n * the API paginates with — this endpoint predates that convention. */\nexport interface CardEstimatedValuesParams extends RequestOptions {\n page?: number;\n limit?: number;\n productName?: string;\n technicalName?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n /** Brand technicalName. */\n brand?: string;\n /** Brand id (ObjectId), an alternative to `brand`. */\n brandId?: string;\n productLine?: ProductLine;\n}\n\nexport class CardsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /cards`: list cards, newest first. No free-text search — use `search()` for that. */\n list(params: ListCardsParams = {}): Promise<ListResponse<Card>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/search`: like `list()`, but with free-text search on card and set names. Premium. */\n search(params: SearchCardsParams = {}): Promise<ListResponse<Card>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards/search${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/{id}`: fetch one card by its id or technicalName. Pass `brand` if two brands\n * might share the same technicalName — see `GetCardParams`. */\n get(idOrTechnicalName: string, params: GetCardParams = {}): Promise<Card> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/cards/${encodeURIComponent(idOrTechnicalName)}${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /cards/{id}/matches`: current shop listings matched to this card (latest per shop). */\n matches(idOrTechnicalName: string, params: CardMatchesParams = {}): Promise<ItemShopMatches> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/cards/${encodeURIComponent(idOrTechnicalName)}/matches${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /cards/{id}/reference-prices`: Cardmarket/TCGplayer/eBay/Tradera price history. Premium. */\n referencePrices(\n idOrTechnicalName: string,\n params: CardReferencePricesParams = {},\n ): Promise<ItemReferencePrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/cards/${encodeURIComponent(idOrTechnicalName)}/reference-prices${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /cards/{id}/prices`: individual marketplace sale records. Premium. */\n prices(idOrTechnicalName: string, params: CardPricesParams = {}): Promise<ItemSoldPrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards/${encodeURIComponent(idOrTechnicalName)}/prices${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/{id}/pricing/live`: computed fresh for this request, not read from the last\n * stats job. Premium. */\n livePricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<LivePricingForItem> {\n return this.http.get(`/cards/${encodeURIComponent(idOrTechnicalName)}/pricing/live`, options);\n }\n\n /** `GET /cards/{id}/pricing`: this card's current pricing snapshot — `retailPrice`,\n * `estimatedValue`, `lowestShopOffer`, `referencePriceSnapshotsByProvider` — refreshed once a day\n * by the nightly pricing/scraper jobs. `get()` returns content only; this is the separate,\n * shorter-cached call for the part of a card that actually changes day to day. */\n pricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<CatalogItemPricing> {\n return this.http.get(`/cards/${encodeURIComponent(idOrTechnicalName)}/pricing`, options);\n }\n\n /** `GET /cards/pricing`: pricing for up to 200 cards in one request, keyed by `id` — the batch\n * counterpart to `pricing()`, for a page of results (a search page, an expansion's contents) that\n * needs pricing for many items at once. Unlike `get()`/`pricing()`, this only accepts `id`s, not\n * technicalNames — pass the `id`s already on the cards you fetched. Ids with no match are\n * silently omitted from the result rather than causing an error. */\n pricingBatch(\n ids: string[],\n options: RequestOptions = {},\n ): Promise<ListResponse<CatalogItemPricing>> {\n return this.http.get(`/cards/pricing?ids=${ids.map(encodeURIComponent).join(',')}`, options);\n }\n\n /** `GET /cards/technical-names`: every card's `technicalName` and `updatedAt`, unpaginated and\n * with no pricing joins. Built for enumerating the whole catalog cheaply — a sitemap, or working\n * out which items changed since your last sync — where `list()` would make you page through full\n * card documents to learn the same two fields. */\n technicalNames(options: RequestOptions = {}): Promise<ListResponse<CatalogSlug>> {\n return this.http.get('/cards/technical-names', options);\n }\n\n /** `GET /cards/price-stats/daily`: daily average price history, cards only. The same data as\n * `client.priceStats.daily()`, scoped to the card catalog so a filter like `expansion` can't pull\n * in that expansion's sealed products too. */\n dailyStats(params: CardDailyStatsParams = {}): Promise<ListResponse<ItemDailyStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/cards/price-stats/daily${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /cards/price-stats/estimated-values`: current estimated market value, cards only. The\n * card-scoped counterpart to `client.priceStats.estimatedValues()`. */\n estimatedValues(\n params: CardEstimatedValuesParams = {},\n ): Promise<ListResponse<ItemEstimatedValue>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/cards/price-stats/estimated-values${toQueryString(query)}`,\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n Card,\n Expansion,\n ExpansionLivePricing,\n ExpansionRef,\n ListResponse,\n SealedProduct,\n} from '../types/index.js';\n\nexport interface ListExpansionsParams extends RequestOptions {\n /** Brand `id` or technicalName, e.g. `'pokemon'`. An unrecognized value is a 400, not an empty\n * list. */\n brand?: string;\n}\n\nexport class ExpansionsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /expansions`: every expansion. Unwrapped to a plain array, nothing to paginate here. */\n async list(params: ListExpansionsParams = {}): Promise<Expansion[]> {\n const [query, requestOptions] = splitRequestOptions(params);\n const res = await this.http.get<{ data: Expansion[] }>(\n `/expansions${toQueryString(query)}`,\n requestOptions,\n );\n return res.data;\n }\n\n /** `GET /expansions/{technicalName}`: metadata only — no cards or sealed products. Returns the\n * smaller `ExpansionRef`, not the full `Expansion`: this is a plain lookup by technicalName, not\n * the aggregation `list()` runs, so `sealedCount`/`cardCount`/`productCount` aren't available\n * here. See `cards()` and `sealedProducts()` for this expansion's contents. */\n get(technicalName: string, options: RequestOptions = {}): Promise<ExpansionRef> {\n return this.http.get(`/expansions/${encodeURIComponent(technicalName)}`, options);\n }\n\n /** `GET /expansions/{technicalName}/cards`: every card in this expansion. Content only, no\n * pricing fields — pass the `id`s from the result to `client.cards.pricingBatch()` if you need\n * pricing too. Sealed products are a separate call — see `sealedProducts()` — never merged into\n * this one. */\n cards(technicalName: string, options: RequestOptions = {}): Promise<ListResponse<Card>> {\n return this.http.get(`/expansions/${encodeURIComponent(technicalName)}/cards`, options);\n }\n\n /** `GET /expansions/{technicalName}/products`: every sealed product in this expansion. Content\n * only, no pricing fields — pass the `id`s from the result to `client.products.pricingBatch()`\n * if you need pricing too. Cards are a separate call — see `cards()` — never merged into this\n * one. */\n sealedProducts(\n technicalName: string,\n options: RequestOptions = {},\n ): Promise<ListResponse<SealedProduct>> {\n return this.http.get(`/expansions/${encodeURIComponent(technicalName)}/products`, options);\n }\n\n /** `GET /expansions/{technicalName}/cards/live-pricing`: computed fresh for every card in this\n * expansion, not read from the last stats job. Premium. */\n cardsLivePricing(\n technicalName: string,\n options: RequestOptions = {},\n ): Promise<ExpansionLivePricing> {\n return this.http.get(\n `/expansions/${encodeURIComponent(technicalName)}/cards/live-pricing`,\n options,\n );\n }\n\n /** `GET /expansions/{technicalName}/products/live-pricing`: computed fresh for every sealed\n * product in this expansion, not read from the last stats job. Premium. */\n productsLivePricing(\n technicalName: string,\n options: RequestOptions = {},\n ): Promise<ExpansionLivePricing> {\n return this.http.get(\n `/expansions/${encodeURIComponent(technicalName)}/products/live-pricing`,\n options,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type { PackRate } from '../types/index.js';\n\nexport class PackRatesResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /pack-rates`: pull-rate odds for every expansion that has them. Unwrapped to a plain\n * array, nothing to paginate here. */\n async list(options: RequestOptions = {}): Promise<PackRate[]> {\n const res = await this.http.get<{ data: PackRate[] }>('/pack-rates', options);\n return res.data;\n }\n\n /** `GET /pack-rates/{expansionId}`: pull-rate odds for one expansion. */\n get(expansionId: string, options: RequestOptions = {}): Promise<PackRate> {\n return this.http.get(`/pack-rates/${encodeURIComponent(expansionId)}`, options);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n CardType,\n GradingCompany,\n ItemCondition,\n ItemDailyStats,\n ItemEstimatedValue,\n ItemFullStats,\n ItemStats,\n ItemVariantDailyStats,\n ItemVariantStats,\n ListResponse,\n ProductLine,\n TopItem,\n} from '../types/index.js';\n\n/** Filters shared by `daily()` and `estimatedValues()`: all narrow which product(s) the stats\n * cover; combine as many as you like. */\nexport interface ProductFilterParams extends RequestOptions {\n productName?: string;\n technicalName?: string;\n priceChartingId?: string;\n modelNumber?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n /** Brand technicalName. */\n brand?: string;\n /** Brand id (ObjectId), an alternative to `brand`. */\n brandId?: string;\n productLine?: ProductLine;\n}\n\nexport interface DailyPriceStatsParams extends ProductFilterParams {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n /** Expansion id (ObjectId), an alternative to `expansion` (technicalName). */\n expansionId?: string;\n /** Category id (ObjectId), an alternative to `category` (technicalName). */\n categoryId?: string;\n}\n\nexport interface EstimatedValuesParams extends ProductFilterParams {\n page?: number;\n limit?: number;\n}\n\nexport interface TopProductsParams extends RequestOptions {\n limit?: number;\n}\n\nexport interface ProductDailyStatsParams extends RequestOptions {\n /** Number of days to retrieve, from today backwards. Default 30. */\n days?: number;\n}\n\nexport interface ProductByVariantParams extends RequestOptions {\n /** Number of days to include in the average calculation. Default 30. */\n days?: number;\n}\n\nexport interface ProductDailyByVariantParams extends RequestOptions {\n cardType: CardType;\n /** Required when `cardType` is `'loose'`. */\n condition?: ItemCondition;\n /** Required when `cardType` is `'graded'`. */\n gradingCompany?: GradingCompany;\n /** Required when `cardType` is `'graded'`. */\n grade?: number;\n /** Number of days to retrieve. Default 30. */\n days?: number;\n}\n\nexport class PriceStatsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /price-stats/daily`: daily average price history, filtered to matching product(s). */\n daily(params: DailyPriceStatsParams = {}): Promise<ListResponse<ItemDailyStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/price-stats/daily${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /price-stats/estimated-values`: current estimated market value, filtered to matching\n * product(s). */\n estimatedValues(params: EstimatedValuesParams = {}): Promise<ListResponse<ItemEstimatedValue>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/price-stats/estimated-values${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /price-stats/top-products`: items ranked by shop availability (how many shops carry\n * them), not by price. */\n topProducts(params: TopProductsParams = {}): Promise<ListResponse<TopItem>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/price-stats/top-products${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /price-stats/product/{id}`: daily price history, current estimate, and a variant-count\n * summary for one product. Premium. */\n product(idOrTechnicalName: string, options: RequestOptions = {}): Promise<ItemStats> {\n return this.http.get(`/price-stats/product/${encodeURIComponent(idOrTechnicalName)}`, options);\n }\n\n /** `GET /price-stats/product/{id}/full`: everything `product()` has, plus the item's current\n * shop matches. Premium. */\n productFull(idOrTechnicalName: string, options: RequestOptions = {}): Promise<ItemFullStats> {\n return this.http.get(`/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/full`, options);\n }\n\n /** `GET /price-stats/product/{id}/daily`: daily price history for one product, with a\n * caller-chosen window. Premium. */\n productDaily(\n idOrTechnicalName: string,\n params: ProductDailyStatsParams = {},\n ): Promise<ItemDailyStats> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/daily${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /price-stats/product/{id}/daily-last-30`: daily price history for the last 30 days\n * exactly (no window param, for callers that want a stable cache key). Premium. */\n productDailyLast30(idOrTechnicalName: string, options: RequestOptions = {}): Promise<ItemDailyStats> {\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/daily-last-30`,\n options,\n );\n }\n\n /** `GET /price-stats/product/{id}/estimated-value`: current estimated value only. Premium. */\n productEstimatedValue(\n idOrTechnicalName: string,\n options: RequestOptions = {},\n ): Promise<ItemEstimatedValue> {\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/estimated-value`,\n options,\n );\n }\n\n /** `GET /price-stats/product/{id}/by-variant`: price stats broken out per card condition/grade.\n * Premium. */\n productByVariant(\n idOrTechnicalName: string,\n params: ProductByVariantParams = {},\n ): Promise<ItemVariantStats> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/by-variant${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /price-stats/product/{id}/daily-by-variant`: daily price history for one specific\n * condition/grade. `condition` is required for `cardType: 'loose'`; `gradingCompany` and `grade`\n * are required for `cardType: 'graded'`. Premium. */\n productDailyByVariant(\n idOrTechnicalName: string,\n params: ProductDailyByVariantParams,\n ): Promise<ItemVariantDailyStats> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/price-stats/product/${encodeURIComponent(idOrTechnicalName)}/daily-by-variant${toQueryString(query)}`,\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type {\n CardType,\n CatalogItemPricing,\n CatalogSlug,\n GradingCompany,\n ItemCondition,\n ItemDailyStats,\n ItemEstimatedValue,\n ItemReferencePrices,\n ItemShopMatches,\n ItemSoldPrices,\n ListResponse,\n LivePricingForItem,\n PaginationParams,\n ProductLine,\n ReferencePriceProvider,\n SealedProduct,\n} from '../types/index.js';\n\nexport interface ListProductsParams extends PaginationParams {\n /** Brand `id` or technicalName, e.g. `'pokemon'`. Scopes the listing to one game/universe. An\n * unrecognized value is a 400, not an empty page. */\n brand?: string;\n productLine?: ProductLine;\n}\n\nexport interface GetProductParams extends RequestOptions {\n /** Brand `id` or technicalName. Disambiguates a `technicalName` two brands both happen to use —\n * irrelevant while the catalogue carries only one brand, and unused for an `id` lookup. */\n brand?: string;\n}\n\nexport interface SearchProductsParams extends PaginationParams {\n /** Whitespace-separated tokens, each matched against the start of a word. */\n search?: string;\n}\n\nexport interface ProductMatchesParams extends PaginationParams {\n /** Keep only matches whose shop currently has stock. */\n inStock?: boolean;\n cardType?: CardType;\n condition?: ItemCondition;\n gradingCompany?: GradingCompany;\n grade?: number;\n}\n\nexport interface ProductReferencePricesParams extends RequestOptions {\n authToken?: string;\n /** Rolling window ending today, in days. Ignored when `from`/`to` are supplied. Default 90. */\n days?: number;\n /** `YYYY-MM-DD` */\n from?: string;\n /** `YYYY-MM-DD` */\n to?: string;\n provider?: ReferencePriceProvider;\n}\n\nexport interface ProductPricesParams extends PaginationParams {}\n\n/** Filters for `products.dailyStats()`. Narrow to one product, or to a whole expansion/category. */\nexport interface ProductDailyPriceStatsParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n productName?: string;\n technicalName?: string;\n priceChartingId?: string;\n modelNumber?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n /** Category id (ObjectId), an alternative to `category`. */\n categoryId?: string;\n /** Expansion id (ObjectId), an alternative to `expansion`. */\n expansionId?: string;\n /** Brand technicalName. */\n brand?: string;\n /** Brand id (ObjectId), an alternative to `brand`. */\n brandId?: string;\n productLine?: ProductLine;\n}\n\n/** Filters for `products.estimatedValues()`. Note `page`/`limit`, not the `limit`/`skip` the rest\n * of the API paginates with — this endpoint predates that convention. */\nexport interface ProductEstimatedValuesParams extends RequestOptions {\n page?: number;\n limit?: number;\n productName?: string;\n technicalName?: string;\n priceChartingId?: string;\n modelNumber?: string;\n /** Category technicalName. */\n category?: string;\n /** Expansion technicalName. */\n expansion?: string;\n /** Brand technicalName. */\n brand?: string;\n /** Brand id (ObjectId), an alternative to `brand`. */\n brandId?: string;\n productLine?: ProductLine;\n}\n\n/** Sealed products: booster boxes, ETBs, tins, and the like. Single cards live under\n * `client.cards` instead. */\nexport class ProductsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /product`: list sealed products, newest first. No free-text search — use `search()` for\n * that. */\n list(params: ListProductsParams = {}): Promise<ListResponse<SealedProduct>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/product${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /product/search`: like `list()`, but with free-text search on the product name. Premium. */\n search(params: SearchProductsParams = {}): Promise<ListResponse<SealedProduct>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/product/search${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /product/{id}`: fetch one sealed product by its id or technicalName. Pass `brand` if two\n * brands might share the same technicalName — see `GetProductParams`. */\n get(idOrTechnicalName: string, params: GetProductParams = {}): Promise<SealedProduct> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/${encodeURIComponent(idOrTechnicalName)}${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /product/{id}/matches`: current shop listings matched to this product (latest per shop). */\n matches(idOrTechnicalName: string, params: ProductMatchesParams = {}): Promise<ItemShopMatches> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/${encodeURIComponent(idOrTechnicalName)}/matches${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /product/{id}/reference-prices`: Cardmarket/TCGplayer/Tradera price history. Premium. */\n referencePrices(\n idOrTechnicalName: string,\n params: ProductReferencePricesParams = {},\n ): Promise<ItemReferencePrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/${encodeURIComponent(idOrTechnicalName)}/reference-prices${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /product/{id}/prices`: individual marketplace sale records. Premium. */\n prices(idOrTechnicalName: string, params: ProductPricesParams = {}): Promise<ItemSoldPrices> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/${encodeURIComponent(idOrTechnicalName)}/prices${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /product/{id}/pricing/live`: computed fresh for this request, not read from the last\n * stats job. Premium. */\n livePricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<LivePricingForItem> {\n return this.http.get(`/product/${encodeURIComponent(idOrTechnicalName)}/pricing/live`, options);\n }\n\n /** `GET /product/{id}/pricing`: this product's current pricing snapshot — `retailPrice`,\n * `estimatedValue`, `lowestShopOffer`, `referencePriceSnapshotsByProvider` — refreshed once a day\n * by the nightly pricing/scraper jobs. `get()` returns content only; this is the separate,\n * shorter-cached call for the part of a product that actually changes day to day. */\n pricing(idOrTechnicalName: string, options: RequestOptions = {}): Promise<CatalogItemPricing> {\n return this.http.get(`/product/${encodeURIComponent(idOrTechnicalName)}/pricing`, options);\n }\n\n /** `GET /product/pricing`: pricing for up to 200 sealed products in one request, keyed by `id` —\n * the batch counterpart to `pricing()`, for a page of results (a search page, an expansion's\n * contents) that needs pricing for many items at once. Unlike `get()`/`pricing()`, this only\n * accepts `id`s, not technicalNames — pass the `id`s already on the products you fetched. Ids with\n * no match are silently omitted from the result rather than causing an error. */\n pricingBatch(\n ids: string[],\n options: RequestOptions = {},\n ): Promise<ListResponse<CatalogItemPricing>> {\n return this.http.get(`/product/pricing?ids=${ids.map(encodeURIComponent).join(',')}`, options);\n }\n\n /** `GET /product/technical-names`: every sealed product's `technicalName` and `updatedAt`,\n * unpaginated and with no pricing joins. The sealed counterpart to\n * `client.cards.technicalNames()` — for sitemaps and incremental syncs. */\n technicalNames(options: RequestOptions = {}): Promise<ListResponse<CatalogSlug>> {\n return this.http.get('/product/technical-names', options);\n }\n\n /** `GET /product/price-stats/daily`: daily average price history, sealed products only. The same\n * data as `client.priceStats.daily()`, scoped to the sealed catalog so a filter like `expansion`\n * can't pull in that expansion's single cards too. */\n dailyStats(params: ProductDailyPriceStatsParams = {}): Promise<ListResponse<ItemDailyStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/product/price-stats/daily${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /product/price-stats/estimated-values`: current estimated market value, sealed products\n * only. The sealed-scoped counterpart to `client.priceStats.estimatedValues()`. */\n estimatedValues(\n params: ProductEstimatedValuesParams = {},\n ): Promise<ListResponse<ItemEstimatedValue>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/product/price-stats/estimated-values${toQueryString(query)}`,\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type { ItemPriceComparison, ItemShopPriceHistory, ShopPriceHistoryList } from '../types/index.js';\n\nexport interface ShopMatchStatsForProductParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n /** Filter to one shop's technicalName. */\n shop?: string;\n}\n\nexport interface ShopMatchStatsForShopParams extends RequestOptions {\n /** `YYYY-MM-DD` */\n startDate?: string;\n /** `YYYY-MM-DD` */\n endDate?: string;\n /** Maximum products to return. Default 20, max 50. */\n limit?: number;\n}\n\nexport interface CompareShopPricesParams extends RequestOptions {\n /** Product/card id or technicalName. */\n productId: string;\n /** `YYYY-MM-DD`: defaults to the latest date with data. */\n date?: string;\n}\n\n/** Historical shop-vs-price data, distinct from `client.shopMatches` (which is the current/latest\n * match state). Everything here is premium. */\nexport class ShopMatchStatsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /shop-match-stats/product/{productId}`: one product's price history, broken out per shop. */\n forProduct(\n productId: string,\n params: ShopMatchStatsForProductParams = {},\n ): Promise<ItemShopPriceHistory> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/shop-match-stats/product/${encodeURIComponent(productId)}${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /shop-match-stats/shop/{shop}`: one shop's price history, broken out per product. */\n forShop(shop: string, params: ShopMatchStatsForShopParams = {}): Promise<ShopPriceHistoryList> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-match-stats/shop/${encodeURIComponent(shop)}${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /shop-match-stats/compare`: one product's price at every shop that carries it, as of\n * one date (defaults to the latest). */\n compare(params: CompareShopPricesParams): Promise<ItemPriceComparison> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-match-stats/compare${toQueryString(query)}`, requestOptions);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type { ListResponse, PaginationParams, ShopMatch, ShopMatchesForShop, ShopMatchStats } from '../types/index.js';\n\nexport interface ListShopMatchesParams extends PaginationParams {\n /** Filter to one shop's technicalName. */\n shop?: string;\n inStock?: boolean;\n /** Filter by whether the listing has been resolved to a catalog item. */\n linked?: boolean;\n}\n\nexport interface ShopMatchesForShopParams extends PaginationParams {\n inStock?: boolean;\n}\n\n/** Raw shop-to-catalog match data: what's currently listed where, independent of which item or\n * shop you start from. For \"what does this card cost at each shop\" or \"what's in stock at this\n * shop\", prefer `client.cards.matches()` / `client.products.matches()` /\n * `client.shopMatches.forShop()`. */\nexport class ShopMatchesResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /shop-matches`: every current match across every shop (latest record per url+shop). */\n list(params: ListShopMatchesParams = {}): Promise<ListResponse<ShopMatch>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-matches${toQueryString(query)}`, requestOptions);\n }\n\n /** `GET /shop-matches/{shop}`: every current match at one shop (latest record per url). */\n forShop(technicalName: string, params: ShopMatchesForShopParams = {}): Promise<ShopMatchesForShop> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(\n `/shop-matches/${encodeURIComponent(technicalName)}${toQueryString(query)}`,\n requestOptions,\n );\n }\n\n /** `GET /shop-matches/shops`: match counts per shop (based on latest records only). */\n shopStats(params: PaginationParams = {}): Promise<ListResponse<ShopMatchStats>> {\n const [query, requestOptions] = splitRequestOptions(params);\n return this.http.get(`/shop-matches/shops${toQueryString(query)}`, requestOptions);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type { ShopUrlMutationResult } from '../types/index.js';\n\nexport interface SubmitShopUrlParams extends RequestOptions {\n url: string;\n /** Shop technicalName. Auto-created if it doesn't exist yet. */\n shop: string;\n}\n\nexport interface AssignShopUrlProductParams extends RequestOptions {\n /** Product/card id to link, or `null` to unlink and let auto-matching resume. */\n productId: string | null;\n}\n\n/** Lets a signed-in subscriber contribute to the catalog: submit a shop URL for scraping, or\n * manually correct which product/card a URL resolves to. Both premium, both mutating. */\nexport class ShopUrlsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `POST /shop-urls/submit`: submit a shop URL for scraping. */\n submit(params: SubmitShopUrlParams): Promise<ShopUrlMutationResult> {\n const { url, shop, ...requestOptions } = params;\n return this.http.post('/shop-urls/submit', { url, shop }, requestOptions);\n }\n\n /** `PATCH /shop-urls/{id}/product`: manually assign (or clear) the product a shop URL resolves to. */\n assignProduct(\n shopUrlId: string,\n params: AssignShopUrlProductParams,\n ): Promise<ShopUrlMutationResult> {\n const { productId, ...requestOptions } = params;\n return this.http.patch(\n `/shop-urls/${encodeURIComponent(shopUrlId)}/product`,\n { productId },\n requestOptions,\n );\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport { splitRequestOptions, toQueryString } from '../http.js';\nimport type { Shop } from '../types/index.js';\n\nexport interface ListShopsParams extends RequestOptions {\n active?: boolean;\n}\n\nexport class ShopsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /shops`: every tracked shop. Unwrapped to a plain array, nothing to paginate here. */\n async list(params: ListShopsParams = {}): Promise<Shop[]> {\n const [query, requestOptions] = splitRequestOptions(params);\n const res = await this.http.get<{ data: Shop[] }>(`/shops${toQueryString(query)}`, requestOptions);\n return res.data;\n }\n\n /** `GET /shops/{id}`: fetch one shop by its id or technicalName. */\n get(idOrTechnicalName: string, options: RequestOptions = {}): Promise<Shop> {\n return this.http.get(`/shops/${encodeURIComponent(idOrTechnicalName)}`, options);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type { PlatformStats } from '../types/index.js';\n\nexport class StatsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** `GET /stats`: platform-wide overview counts (shops, expansions, products, prices tracked). */\n platform(options: RequestOptions = {}): Promise<PlatformStats> {\n return this.http.get('/stats', options);\n }\n}\n","import type { HttpClient, RequestOptions } from '../http.js';\nimport type {\n Acknowledgement,\n ListResponse,\n Webhook,\n WebhookEvent,\n WebhookTestResult,\n WebhookWithSecret,\n} from '../types/index.js';\n\nexport interface CreateWebhookParams extends RequestOptions {\n /**\n * Where deliveries are POSTed. Must be `https://` — the API rejects plaintext, since a delivery\n * carries the signature that authenticates it.\n */\n url: string;\n /** At least one event to subscribe to. */\n events: WebhookEvent[];\n}\n\n/**\n * Outbound webhooks: the API calls you when something changes, instead of you polling for it.\n *\n * Business tier, not Premium — a Premium token answers `403 businessRequired`. The feature is also\n * behind a server-side flag, and when that flag is off these answer `404 notFound` rather than 403,\n * so a `notFound` here means \"not enabled on this instance\", not \"wrong id\".\n */\nexport class WebhooksResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * `POST /webhooks`: register a new webhook.\n *\n * The returned `secret` is the only copy you will ever get — sign-verification depends on it and\n * no endpoint reads it back. Persist it here, at creation, or delete the webhook and make a new\n * one.\n */\n create(params: CreateWebhookParams): Promise<WebhookWithSecret> {\n const { url, events, ...requestOptions } = params;\n return this.http.post('/webhooks', { url, events }, requestOptions);\n }\n\n /** `GET /webhooks`: every webhook registered on this account. Secrets are never included. */\n list(options: RequestOptions = {}): Promise<ListResponse<Webhook>> {\n return this.http.get('/webhooks', options);\n }\n\n /** `DELETE /webhooks/{id}`: revoke a webhook. Deliveries stop immediately; its secret is void. */\n delete(webhookId: string, options: RequestOptions = {}): Promise<Acknowledgement> {\n return this.http.delete(`/webhooks/${encodeURIComponent(webhookId)}`, options);\n }\n\n /** `POST /webhooks/{id}/test`: send a sample delivery to the registered URL, so you can verify\n * your endpoint and your signature check before waiting on a real event. */\n test(webhookId: string, options: RequestOptions = {}): Promise<WebhookTestResult> {\n return this.http.post(`/webhooks/${encodeURIComponent(webhookId)}/test`, undefined, options);\n }\n}\n","import { HttpClient } from './http.js';\nimport { BargainsResource } from './resources/bargains.js';\nimport { BrandsResource } from './resources/brands.js';\nimport { CardsResource } from './resources/cards.js';\nimport { ExpansionsResource } from './resources/expansions.js';\nimport { PackRatesResource } from './resources/packRates.js';\nimport { PriceStatsResource } from './resources/priceStats.js';\nimport { ProductsResource } from './resources/products.js';\nimport { ShopMatchStatsResource } from './resources/shopMatchStats.js';\nimport { ShopMatchesResource } from './resources/shopMatches.js';\nimport { ShopUrlsResource } from './resources/shopUrls.js';\nimport { ShopsResource } from './resources/shops.js';\nimport { StatsResource } from './resources/stats.js';\nimport { WebhooksResource } from './resources/webhooks.js';\n\nexport const DEFAULT_BASE_URL = 'https://api.tcgpriser.se';\n\n/** Local dev, self-hosting and testing overrides. Most integrations never touch these. */\nexport interface TcgPriserAdvancedOptions {\n /** Point at a local dev server or a self-hosted instance. Defaults to production. */\n baseUrl?: string;\n /** Extra headers sent on every request, e.g. a custom `User-Agent`. */\n headers?: Record<string, string>;\n /** Swap in a different `fetch` (older Node, testing, a proxying agent). Defaults to global `fetch`. */\n fetch?: typeof fetch;\n /**\n * Default milliseconds before a request is aborted, for every call this client makes. Defaults to\n * `DEFAULT_TIMEOUT_MS` (60s). `0` disables the timeout entirely. Every method can override it per\n * call with `timeoutMs`.\n */\n timeoutMs?: number;\n}\n\nexport interface TcgPriserOptions {\n /**\n * A per-account API token, generated from your account page at tcgpriser.se/account/api-token.\n * Only needed for premium methods (`cards.prices()`, `priceStats.product()`,\n * `bargains.search()` etc.); public methods work fine without it. This client has no login flow\n * of its own, and doesn't need one: the API token is a long-lived, revocable secret made for\n * exactly this, so there's no OAuth dance to drive.\n *\n * Every premium method also accepts its own `authToken` to override this per call. Useful when\n * one server-side client is shared across requests for several different signed-in users.\n */\n authToken?: string;\n /** Local dev / self-hosting / testing overrides. Leave unset unless you know you need it. */\n advanced?: TcgPriserAdvancedOptions;\n}\n\n/**\n * Client for the tcgpriser.se API: Pokémon TCG price data, catalog, shop matches and bargains for\n * shops tracked in Sweden.\n *\n * ```ts\n * import { TcgPriser } from 'tcgpriser';\n *\n * const tcgpriser = new TcgPriser();\n * const card = await tcgpriser.cards.get('mega-evolution-ascended-heroes-fezandipiti-ex');\n * console.log(card.retailPrice, card.lowestShopOffer?.shop.name);\n * ```\n *\n * That example needs no token. Most of the API is public (https://api.tcgpriser.se/docs). A\n * smaller set of premium methods (live pricing, per-condition history, shop comparison, bargain\n * search, shop-URL submission) need a Premium subscriber's API token\n * (https://api.tcgpriser.se/premium-docs), generated from tcgpriser.se/account/api-token:\n *\n * ```ts\n * const tcgpriser = new TcgPriser(myApiToken); // shorthand for { authToken: myApiToken }\n * await tcgpriser.cards.livePricing('fezandipiti-ex');\n * ```\n */\nexport class TcgPriser {\n readonly cards: CardsResource;\n readonly products: ProductsResource;\n readonly expansions: ExpansionsResource;\n readonly brands: BrandsResource;\n readonly shops: ShopsResource;\n readonly shopMatches: ShopMatchesResource;\n readonly shopMatchStats: ShopMatchStatsResource;\n readonly shopUrls: ShopUrlsResource;\n readonly priceStats: PriceStatsResource;\n readonly bargains: BargainsResource;\n readonly packRates: PackRatesResource;\n readonly stats: StatsResource;\n readonly webhooks: WebhooksResource;\n\n /** Holds the `HttpClient` so `creditsRemaining` can read the running value off it. */\n private readonly http: HttpClient;\n\n /**\n * @param optionsOrAuthToken A subscriber's API token (`new TcgPriser(myApiToken)`), a full\n * `TcgPriserOptions` object, or omit it entirely for an anonymous, public-only client.\n */\n constructor(optionsOrAuthToken?: string | TcgPriserOptions) {\n const options: TcgPriserOptions =\n typeof optionsOrAuthToken === 'string' ? { authToken: optionsOrAuthToken } : (optionsOrAuthToken ?? {});\n const advanced = options.advanced ?? {};\n\n if (!advanced.fetch && typeof fetch === 'undefined') {\n throw new Error(\n 'tcgpriser: no global fetch found. Pass { advanced: { fetch } } explicitly on Node < 18, or run on Node 18+.',\n );\n }\n\n const http = new HttpClient({\n timeoutMs: advanced.timeoutMs,\n baseUrl: advanced.baseUrl ?? DEFAULT_BASE_URL,\n // Bound to globalThis: both browsers and Node's undici implement fetch as a method that\n // checks its receiver, so an unbound reference throws \"Illegal invocation\" the moment it's\n // called through anything other than `window.fetch(...)`/`globalThis.fetch(...)` — which is\n // exactly what happens once HttpClient stores it and calls `this.fetchImpl(...)`.\n fetch: advanced.fetch ?? fetch.bind(globalThis),\n headers: advanced.headers,\n authToken: options.authToken,\n });\n\n this.cards = new CardsResource(http);\n this.products = new ProductsResource(http);\n this.expansions = new ExpansionsResource(http);\n this.brands = new BrandsResource(http);\n this.shops = new ShopsResource(http);\n this.shopMatches = new ShopMatchesResource(http);\n this.shopMatchStats = new ShopMatchStatsResource(http);\n this.shopUrls = new ShopUrlsResource(http);\n this.priceStats = new PriceStatsResource(http);\n this.bargains = new BargainsResource(http);\n this.packRates = new PackRatesResource(http);\n this.stats = new StatsResource(http);\n this.webhooks = new WebhooksResource(http);\n this.http = http;\n }\n\n /**\n * Credits left in this week's allowance, as of the last charged call this client made.\n *\n * The API returns `X-Credits-Remaining` on every response it charges for, so this needs no extra\n * request — but it is only as current as your last premium call, and it is `undefined` until you\n * make one. Uncharged calls (every public method, and any call authenticated with something other\n * than an API token) don't update it, because the API doesn't meter them.\n *\n * ```ts\n * await tcgpriser.cards.livePricing('fezandipiti-ex');\n * if ((tcgpriser.creditsRemaining ?? Infinity) < 100) scheduleFewerRefreshes();\n * ```\n *\n * Reading it in a browser additionally needs the API to expose the header via CORS, which it does.\n */\n get creditsRemaining(): number | undefined {\n return this.http.creditsRemaining;\n }\n}\n"]}
|