@pokemontcgapi/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/errors.js ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Gerarchia degli errori.
3
+ *
4
+ * Sottoclassi e non un solo tipo con un campo `code`, per una ragione pratica:
5
+ * chi integra scrive `catch (e) { if (e instanceof RateLimited) ... }`, e con un
6
+ * tipo solo dovrebbe confrontare stringhe — cioe' riscrivere a mano la
7
+ * tassonomia che noi gia' conosciamo, sbagliando i nomi.
8
+ *
9
+ * `QuotaExceeded` e' separato da `RateLimited` di proposito: sembrano lo stesso
10
+ * errore (entrambi 429) ma si trattano in modo opposto. Un rate limit passa
11
+ * aspettando; una quota mensile finita non passa mai, e riprovare e' solo un
12
+ * modo di consumare tempo. Il retry automatico di questo client riprova il
13
+ * primo e non riprova mai il secondo.
14
+ */
15
+ export class PokemonTcgApiError extends Error {
16
+ /** Codice stabile della tassonomia, es. `CARD_NOT_FOUND`. */
17
+ code;
18
+ status;
19
+ /**
20
+ * Sempre valorizzato quando la risposta e' passata dall'API: e' l'unica cosa
21
+ * che il supporto puo' cercare nei log. Va incluso in ogni bug report.
22
+ */
23
+ requestId;
24
+ details;
25
+ constructor(status, body) {
26
+ super(`${body.code}: ${body.message}`);
27
+ this.name = new.target.name;
28
+ this.code = body.code;
29
+ this.status = status;
30
+ this.requestId = body.request_id;
31
+ this.details = body.details;
32
+ }
33
+ }
34
+ /** 401 — chiave assente, malformata o revocata. */
35
+ export class AuthenticationError extends PokemonTcgApiError {
36
+ }
37
+ /** 403 — la chiave e' valida ma non puo' fare questa cosa. */
38
+ export class PermissionDeniedError extends PokemonTcgApiError {
39
+ }
40
+ /** 402 / UPGRADE_REQUIRED — serve un piano superiore. */
41
+ export class UpgradeRequiredError extends PokemonTcgApiError {
42
+ /** Finestra concessa dal piano corrente, quando l'API la dichiara. */
43
+ get permittedWindow() {
44
+ return this.details?.['permitted_window'];
45
+ }
46
+ }
47
+ /** 404 — la risorsa non esiste. Non e' un errore di rete: non si riprova. */
48
+ export class NotFoundError extends PokemonTcgApiError {
49
+ }
50
+ /** 400 / 422 — la richiesta e' sbagliata. `field` dice quale parametro. */
51
+ export class InvalidRequestError extends PokemonTcgApiError {
52
+ get field() {
53
+ const value = this.details?.['field'];
54
+ return typeof value === 'string' ? value : undefined;
55
+ }
56
+ }
57
+ /** 429 con Retry-After: passa aspettando. */
58
+ export class RateLimitedError extends PokemonTcgApiError {
59
+ /** Secondi da aspettare, dall'header `Retry-After`, se c'era. */
60
+ retryAfter;
61
+ constructor(status, body, retryAfter) {
62
+ super(status, body);
63
+ this.retryAfter = retryAfter;
64
+ }
65
+ }
66
+ /** 429 per quota di periodo esaurita: NON passa aspettando, e non si riprova. */
67
+ export class QuotaExceededError extends PokemonTcgApiError {
68
+ }
69
+ /** 5xx. */
70
+ export class ServerError extends PokemonTcgApiError {
71
+ }
72
+ /** La richiesta non e' mai arrivata: DNS, TLS, socket. */
73
+ export class ApiConnectionError extends Error {
74
+ /** `override` perche' Error dichiara gia' `cause` da ES2022. */
75
+ cause;
76
+ constructor(message, cause) {
77
+ super(message);
78
+ this.name = 'ApiConnectionError';
79
+ this.cause = cause;
80
+ }
81
+ }
82
+ /** La richiesta e' stata abbandonata da noi dopo `timeout`. */
83
+ export class ApiTimeoutError extends ApiConnectionError {
84
+ constructor(timeoutMs, cause) {
85
+ super(`Request timed out after ${timeoutMs}ms`, cause);
86
+ this.name = 'ApiTimeoutError';
87
+ }
88
+ }
89
+ /**
90
+ * Dal corpo dell'errore alla classe giusta.
91
+ *
92
+ * Si guarda PRIMA il `code` e poi lo status: lo status dice la famiglia, il
93
+ * code dice il caso, e i due casi che contano davvero (limite contro quota)
94
+ * condividono lo stesso status.
95
+ */
96
+ export function toApiError(status, body, retryAfter) {
97
+ const code = body.code;
98
+ if (code === 'QUOTA_EXCEEDED' || code === 'MONTHLY_QUOTA_EXCEEDED')
99
+ return new QuotaExceededError(status, body);
100
+ if (code === 'UPGRADE_REQUIRED' || status === 402)
101
+ return new UpgradeRequiredError(status, body);
102
+ if (status === 429)
103
+ return new RateLimitedError(status, body, retryAfter);
104
+ if (status === 401)
105
+ return new AuthenticationError(status, body);
106
+ if (status === 403)
107
+ return new PermissionDeniedError(status, body);
108
+ if (status === 404 || code.endsWith('_NOT_FOUND'))
109
+ return new NotFoundError(status, body);
110
+ if (status >= 500)
111
+ return new ServerError(status, body);
112
+ if (status >= 400)
113
+ return new InvalidRequestError(status, body);
114
+ return new PokemonTcgApiError(status, body);
115
+ }
116
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import { HttpClient, Page, type ClientOptions } from './client.js';
2
+ import type { Artist, BatchResult, Card, CardInclude, CardListParams, CardSet, CatalogStatus, Health, IdentifyOptions, ListParams, Locale, SetListParams, VisionResponse } from './types.js';
3
+ export * from './errors.js';
4
+ export * from './types.js';
5
+ export { Page } from './client.js';
6
+ export type { ClientOptions } from './client.js';
7
+ /**
8
+ * Client di pokemontcgapi.com.
9
+ *
10
+ * Le risorse rispecchiano i path (`client.cards.get`, `client.sets.cards`) cosi'
11
+ * che passare dalla documentazione al codice non richieda una tabella di
12
+ * conversione. Ogni metodo di lista torna una `Page`, che e' anche un
13
+ * `AsyncIterable`: si itera e la paginazione sparisce.
14
+ *
15
+ * ```ts
16
+ * const client = new PokemonTcgApi({ apiKey: process.env.PTCG_API_KEY });
17
+ *
18
+ * const card = await client.cards.get('base1-4', { include: ['prices'] });
19
+ * console.log(card.name, card.index_eur);
20
+ *
21
+ * for await (const set of client.sets.list({ region: 'JP' })) {
22
+ * console.log(set.code, set.name, set.release_date);
23
+ * }
24
+ * ```
25
+ */
26
+ export declare class PokemonTcgApi {
27
+ private readonly http;
28
+ readonly cards: CardsResource;
29
+ readonly sets: SetsResource;
30
+ readonly artists: ArtistsResource;
31
+ readonly reference: ReferenceResource;
32
+ readonly vision: VisionResource;
33
+ constructor(options?: ClientOptions);
34
+ /** Conteggi di catalogo e freschezza per fonte. */
35
+ status(): Promise<CatalogStatus>;
36
+ /** Liveness. Separato da `status()`: un ingest fermo non e' un servizio giu'. */
37
+ health(): Promise<Health>;
38
+ }
39
+ declare class CardsResource {
40
+ private readonly http;
41
+ constructor(http: HttpClient);
42
+ /** Ricerca sul catalogo. Torna la prima pagina, iterabile fino in fondo. */
43
+ search(params?: CardListParams): Promise<Page<Card>>;
44
+ /** Una carta per id. Accetta sia l'id nostro sia l'id alternativo. */
45
+ get(id: string, params?: {
46
+ select?: readonly string[];
47
+ include?: readonly CardInclude[];
48
+ lang?: Locale;
49
+ }): Promise<Card>;
50
+ /**
51
+ * Fino a 100 id in una richiesta.
52
+ *
53
+ * La risposta porta `requested` e `found`: gli id che non esistono vengono
54
+ * semplicemente omessi da `data`, non segnalati uno per uno. Confrontare i due
55
+ * numeri e' l'unico modo di accorgersene, quindi il tipo li espone entrambi.
56
+ */
57
+ batch(ids: readonly string[], params?: {
58
+ select?: readonly string[];
59
+ include?: readonly CardInclude[];
60
+ lang?: Locale;
61
+ }): Promise<BatchResult<Card>>;
62
+ }
63
+ declare class SetsResource {
64
+ private readonly http;
65
+ constructor(http: HttpClient);
66
+ /**
67
+ * Elenco dei set. `region` e' il filtro che vale la pena conoscere: `JP`
68
+ * restituisce le uscite giapponesi, che sono la parte piu' grande del
69
+ * catalogo e non sono traduzioni di quelle occidentali.
70
+ */
71
+ list(params?: SetListParams): Promise<Page<CardSet>>;
72
+ /** Un set per codice, slug o id alternativo. */
73
+ get(code: string): Promise<CardSet>;
74
+ /** Le carte di un set, in ordine di collezione. */
75
+ cards(code: string, params?: CardListParams): Promise<Page<Card>>;
76
+ }
77
+ declare class ArtistsResource {
78
+ private readonly http;
79
+ constructor(http: HttpClient);
80
+ list(params?: ListParams): Promise<Page<Artist>>;
81
+ get(slug: string): Promise<Artist>;
82
+ }
83
+ /**
84
+ * I vocabolari chiusi, per popolare i filtri di una UI senza indovinare le
85
+ * stringhe.
86
+ *
87
+ * `subtypes()` oggi torna una lista VUOTA: la colonna esiste ma non e'
88
+ * popolata su nessuna carta. Il metodo resta perche' il giorno in cui lo sara'
89
+ * non serve una nuova versione dell'SDK — ma non costruirci sopra una UI che
90
+ * assume almeno un elemento.
91
+ */
92
+ declare class ReferenceResource {
93
+ private readonly http;
94
+ constructor(http: HttpClient);
95
+ private list;
96
+ types(): Promise<readonly string[]>;
97
+ /** Vuoto al 2026-08-27. Vedi la nota sulla classe. */
98
+ subtypes(): Promise<readonly string[]>;
99
+ supertypes(): Promise<readonly string[]>;
100
+ rarities(): Promise<readonly string[]>;
101
+ }
102
+ /**
103
+ * Riconoscimento di una carta da una fotografia.
104
+ *
105
+ * Costa 25 crediti a chiamata contro l'uno di una lettura: e' l'unica rotta che
106
+ * non restituisce una riga ma l'esito del confronto con l'intero indice delle
107
+ * immagini. Vale la pena saperlo prima di metterla in un ciclo.
108
+ */
109
+ declare class VisionResource {
110
+ private readonly http;
111
+ constructor(http: HttpClient);
112
+ /**
113
+ * Manda una foto, ricevi i candidati in ordine.
114
+ *
115
+ * `image` accetta qualunque cosa `FormData` sappia allegare: un `Blob`, un
116
+ * `File` da un `<input capture="environment">`, o un `Uint8Array` che viene
117
+ * avvolto qui.
118
+ *
119
+ * **Leggi `decision` prima di `id`.** `id` e' valorizzato solo su `match`; su
120
+ * `ambiguous` e' `null` di proposito, perche' due stampe della stessa
121
+ * illustrazione dall'immagine sola non sono distinguibili e sceglierne una
122
+ * significa sbagliare meta' delle volte, proprio sulle carte che valgono di
123
+ * piu'. Se il tuo flusso sa da che set viene — chi inventaria una busta
124
+ * appena aperta lo sa — passalo in `set`: e' cio' che scioglie il pareggio.
125
+ *
126
+ * ```ts
127
+ * const { data } = await client.vision.identify(file, { set: 'sv3' });
128
+ * if (data.decision === 'match') add(data.id!);
129
+ * else showPicker(data.candidates);
130
+ * ```
131
+ */
132
+ identify(image: Blob | Uint8Array | ArrayBuffer, options?: IdentifyOptions): Promise<VisionResponse>;
133
+ }
134
+ export default PokemonTcgApi;
135
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,202 @@
1
+ import { HttpClient, Page } from './client.js';
2
+ export * from './errors.js';
3
+ export * from './types.js';
4
+ export { Page } from './client.js';
5
+ /**
6
+ * Client di pokemontcgapi.com.
7
+ *
8
+ * Le risorse rispecchiano i path (`client.cards.get`, `client.sets.cards`) cosi'
9
+ * che passare dalla documentazione al codice non richieda una tabella di
10
+ * conversione. Ogni metodo di lista torna una `Page`, che e' anche un
11
+ * `AsyncIterable`: si itera e la paginazione sparisce.
12
+ *
13
+ * ```ts
14
+ * const client = new PokemonTcgApi({ apiKey: process.env.PTCG_API_KEY });
15
+ *
16
+ * const card = await client.cards.get('base1-4', { include: ['prices'] });
17
+ * console.log(card.name, card.index_eur);
18
+ *
19
+ * for await (const set of client.sets.list({ region: 'JP' })) {
20
+ * console.log(set.code, set.name, set.release_date);
21
+ * }
22
+ * ```
23
+ */
24
+ export class PokemonTcgApi {
25
+ http;
26
+ cards;
27
+ sets;
28
+ artists;
29
+ reference;
30
+ vision;
31
+ constructor(options = {}) {
32
+ this.http = new HttpClient(options);
33
+ this.cards = new CardsResource(this.http);
34
+ this.sets = new SetsResource(this.http);
35
+ this.artists = new ArtistsResource(this.http);
36
+ this.reference = new ReferenceResource(this.http);
37
+ this.vision = new VisionResource(this.http);
38
+ }
39
+ /** Conteggi di catalogo e freschezza per fonte. */
40
+ status() {
41
+ return this.http.get('/v1/status');
42
+ }
43
+ /** Liveness. Separato da `status()`: un ingest fermo non e' un servizio giu'. */
44
+ health() {
45
+ return this.http.get('/v1/health');
46
+ }
47
+ }
48
+ class CardsResource {
49
+ http;
50
+ constructor(http) {
51
+ this.http = http;
52
+ }
53
+ /** Ricerca sul catalogo. Torna la prima pagina, iterabile fino in fondo. */
54
+ async search(params = {}) {
55
+ const body = await this.http.get('/v1/cards', { ...params });
56
+ return new Page(this.http, body);
57
+ }
58
+ /** Una carta per id. Accetta sia l'id nostro sia l'id alternativo. */
59
+ get(id, params = {}) {
60
+ return this.http.get(`/v1/cards/${encodeURIComponent(id)}`, { ...params });
61
+ }
62
+ /**
63
+ * Fino a 100 id in una richiesta.
64
+ *
65
+ * La risposta porta `requested` e `found`: gli id che non esistono vengono
66
+ * semplicemente omessi da `data`, non segnalati uno per uno. Confrontare i due
67
+ * numeri e' l'unico modo di accorgersene, quindi il tipo li espone entrambi.
68
+ */
69
+ batch(ids, params = {}) {
70
+ if (ids.length === 0)
71
+ return Promise.resolve({ data: [], requested: 0, found: 0 });
72
+ if (ids.length > 100) {
73
+ throw new RangeError(`batch() accepts at most 100 ids, received ${ids.length}. Chunk the list.`);
74
+ }
75
+ return this.http.get('/v1/cards/batch', { ids, ...params });
76
+ }
77
+ }
78
+ class SetsResource {
79
+ http;
80
+ constructor(http) {
81
+ this.http = http;
82
+ }
83
+ /**
84
+ * Elenco dei set. `region` e' il filtro che vale la pena conoscere: `JP`
85
+ * restituisce le uscite giapponesi, che sono la parte piu' grande del
86
+ * catalogo e non sono traduzioni di quelle occidentali.
87
+ */
88
+ async list(params = {}) {
89
+ const body = await this.http.get('/v1/sets', { ...params });
90
+ return new Page(this.http, body);
91
+ }
92
+ /** Un set per codice, slug o id alternativo. */
93
+ get(code) {
94
+ return this.http.get(`/v1/sets/${encodeURIComponent(code)}`);
95
+ }
96
+ /** Le carte di un set, in ordine di collezione. */
97
+ async cards(code, params = {}) {
98
+ const body = await this.http.get(`/v1/sets/${encodeURIComponent(code)}/cards`, { ...params });
99
+ return new Page(this.http, body);
100
+ }
101
+ }
102
+ class ArtistsResource {
103
+ http;
104
+ constructor(http) {
105
+ this.http = http;
106
+ }
107
+ async list(params = {}) {
108
+ const body = await this.http.get('/v1/artists', { ...params });
109
+ return new Page(this.http, body);
110
+ }
111
+ get(slug) {
112
+ return this.http.get(`/v1/artists/${encodeURIComponent(slug)}`);
113
+ }
114
+ }
115
+ /**
116
+ * I vocabolari chiusi, per popolare i filtri di una UI senza indovinare le
117
+ * stringhe.
118
+ *
119
+ * `subtypes()` oggi torna una lista VUOTA: la colonna esiste ma non e'
120
+ * popolata su nessuna carta. Il metodo resta perche' il giorno in cui lo sara'
121
+ * non serve una nuova versione dell'SDK — ma non costruirci sopra una UI che
122
+ * assume almeno un elemento.
123
+ */
124
+ class ReferenceResource {
125
+ http;
126
+ constructor(http) {
127
+ this.http = http;
128
+ }
129
+ async list(path) {
130
+ const body = await this.http.get(path);
131
+ return body.data;
132
+ }
133
+ types() {
134
+ return this.list('/v1/types');
135
+ }
136
+ /** Vuoto al 2026-08-27. Vedi la nota sulla classe. */
137
+ subtypes() {
138
+ return this.list('/v1/subtypes');
139
+ }
140
+ supertypes() {
141
+ return this.list('/v1/supertypes');
142
+ }
143
+ rarities() {
144
+ return this.list('/v1/rarities');
145
+ }
146
+ }
147
+ /**
148
+ * Riconoscimento di una carta da una fotografia.
149
+ *
150
+ * Costa 25 crediti a chiamata contro l'uno di una lettura: e' l'unica rotta che
151
+ * non restituisce una riga ma l'esito del confronto con l'intero indice delle
152
+ * immagini. Vale la pena saperlo prima di metterla in un ciclo.
153
+ */
154
+ class VisionResource {
155
+ http;
156
+ constructor(http) {
157
+ this.http = http;
158
+ }
159
+ /**
160
+ * Manda una foto, ricevi i candidati in ordine.
161
+ *
162
+ * `image` accetta qualunque cosa `FormData` sappia allegare: un `Blob`, un
163
+ * `File` da un `<input capture="environment">`, o un `Uint8Array` che viene
164
+ * avvolto qui.
165
+ *
166
+ * **Leggi `decision` prima di `id`.** `id` e' valorizzato solo su `match`; su
167
+ * `ambiguous` e' `null` di proposito, perche' due stampe della stessa
168
+ * illustrazione dall'immagine sola non sono distinguibili e sceglierne una
169
+ * significa sbagliare meta' delle volte, proprio sulle carte che valgono di
170
+ * piu'. Se il tuo flusso sa da che set viene — chi inventaria una busta
171
+ * appena aperta lo sa — passalo in `set`: e' cio' che scioglie il pareggio.
172
+ *
173
+ * ```ts
174
+ * const { data } = await client.vision.identify(file, { set: 'sv3' });
175
+ * if (data.decision === 'match') add(data.id!);
176
+ * else showPicker(data.candidates);
177
+ * ```
178
+ */
179
+ async identify(image, options = {}) {
180
+ const form = new FormData();
181
+ form.set('image', toBlob(image), 'card');
182
+ if (options.topK !== undefined)
183
+ form.set('top_k', String(options.topK));
184
+ if (options.set !== undefined)
185
+ form.set('set', options.set);
186
+ if (options.region !== undefined)
187
+ form.set('region', options.region);
188
+ // Nessun content-type esplicito: il boundary del multipart lo scrive fetch,
189
+ // e impostarlo a mano produce un corpo che il server non riesce a separare.
190
+ return this.http.post('/v1/vision/identify', form);
191
+ }
192
+ }
193
+ /** Porta i byte grezzi in un Blob, lasciando passare cio' che gia' lo e'. */
194
+ function toBlob(image) {
195
+ if (image instanceof Blob)
196
+ return image;
197
+ // Il tipo generico e non `image/jpeg`: il formato lo riconosce il server dai
198
+ // magic byte, e dichiarare quello sbagliato sarebbe peggio che tacere.
199
+ return new Blob([image], { type: 'application/octet-stream' });
200
+ }
201
+ export default PokemonTcgApi;
202
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}