From 1b7bd935f72975e7089444f2c864d60d5469895d Mon Sep 17 00:00:00 2001 From: advra Date: Sun, 5 Jul 2026 10:31:53 -0700 Subject: [PATCH 1/9] Created pricing model. Added pricing to card and interfaces --- src/interfaces.d.ts | 4 + src/models/Card.ts | 10 ++- src/models/Other.d.ts | 167 ++++++++++++++++++++++++++---------------- 3 files changed, 118 insertions(+), 63 deletions(-) diff --git a/src/interfaces.d.ts b/src/interfaces.d.ts index cfad0a6..a9ba77f 100644 --- a/src/interfaces.d.ts +++ b/src/interfaces.d.ts @@ -1,3 +1,5 @@ +import type { Pricing } from "./models/Other" + export type SupportedLanguages = 'en' | 'fr' | 'es' | 'es-mx' | 'it' | 'pt' | 'pt-br' | 'de' | 'nl' | 'pl' | 'ru' | 'ja' | 'ko' | 'zh-tw' | 'id' | 'th' | 'zh-cn' @@ -316,6 +318,8 @@ export interface Card extends CardResume expanded: boolean } + pricing?: Pricing; + boosters?: BoosterList } diff --git a/src/models/Card.ts b/src/models/Card.ts index e57819a..52b5d98 100644 --- a/src/models/Card.ts +++ b/src/models/Card.ts @@ -1,6 +1,6 @@ import { objectLoop } from '@dzeio/object-util' import CardResume from './CardResume' -import type { Booster, Variants, VariantsDetailed } from './Other' +import type { Booster, Pricing, Variants, VariantsDetailed } from './Other' import type TCGdexSet from './Set' import type SetResume from './SetResume' @@ -195,6 +195,14 @@ export default class Card extends CardResume { expanded: boolean } + /** + * Card pricing object which ingests pricing based off tcgplayer and cardmarket + * + * Note: Not availible for all cards. + */ + + public pricing?: Pricing; + public boosters?: Array public override async getCard(): Promise { diff --git a/src/models/Other.d.ts b/src/models/Other.d.ts index 00c8b8f..87177dc 100644 --- a/src/models/Other.d.ts +++ b/src/models/Other.d.ts @@ -1,74 +1,117 @@ export interface Variants { - normal?: boolean - reverse?: boolean - holo?: boolean - firstEdition?: boolean + normal?: boolean + reverse?: boolean + holo?: boolean + firstEdition?: boolean } export interface Booster { - id: string - name: string - logo?: string - artwork_front?: string - artwork_back?: string + id: string + name: string + logo?: string + artwork_front?: string + artwork_back?: string } /** * A better version of variants with additionnal details on each variants */ export interface VariantsDetailed { - /** - * define the variant type - * - normal: no holographic elements - * - holo: the illustration has a foil - * - reverse: everything but the illustration is foiled - */ - type: string - /** - * Some older sets had specific subtypes for the cards - * i.e Base Set had shadowless with and without a 1st-edition stamp. - * and the Unlimited version of the set had no shadow. - */ - subtype?: string - /** - * define the size of the card - * - standard: the classic size of a card - * - jumbo: also said oversized, big card. - */ - size?: string - /** - * indicate that this variant has stamps - * a card may have multiple stamps, example "Ethan's Typhlosion pre-release staff" - * this was a pre-release card only given to staff and has both the set-logo and the staff stamp. - * - 1st-edition: a 1st-edition card (mostly for the first series of the game) - * - w-promo: - * - pre-release: - * - pokemon-center: a card that is stamped with the Pokémon Center logo - * - set-promo: a card that is stamped with the set logo - * - staff: a card that is stamped with the staff text - * - gamestop: a card that is stamped with the GameStop logo - * - eb-games: a card that is stamped with the EB Games logo - * - snowflake: a card that is stamped with a snowflake, available in the yearly advent calendar - * - trick-or-trade: a card that is stamped with a pikachu-pumpkin, available in the yearly halloween/trick-or-trade boosters - * - ace-trainer: a card that is stamped with a golden ACE TRAINER, won by getting 200 championship points in the season since 2025 season. - * - player-rewards-program: a card that is stamped with the player reward logo, available in the yearly player rewards program (play! pokemon prize pack) - * - etc... - */ - stamp?: Array - /** - * for the holo & reverse, **optional** indicate which foil is used on the card - */ - foil?: string - /** - * IDs from third part websites - */ - thirdParty?: { - cardmarket?: number - tcgplayer?: number - } - /** - * A unique ID defining this variant - */ - variantId: string + /** + * define the variant type + * - normal: no holographic elements + * - holo: the illustration has a foil + * - reverse: everything but the illustration is foiled + */ + type: string + /** + * Some older sets had specific subtypes for the cards + * i.e Base Set had shadowless with and without a 1st-edition stamp. + * and the Unlimited version of the set had no shadow. + */ + subtype?: string + /** + * define the size of the card + * - standard: the classic size of a card + * - jumbo: also said oversized, big card. + */ + size?: string + /** + * indicate that this variant has stamps + * a card may have multiple stamps, example "Ethan's Typhlosion pre-release staff" + * this was a pre-release card only given to staff and has both the set-logo and the staff stamp. + * - 1st-edition: a 1st-edition card (mostly for the first series of the game) + * - w-promo: + * - pre-release: + * - pokemon-center: a card that is stamped with the Pokémon Center logo + * - set-promo: a card that is stamped with the set logo + * - staff: a card that is stamped with the staff text + * - gamestop: a card that is stamped with the GameStop logo + * - eb-games: a card that is stamped with the EB Games logo + * - snowflake: a card that is stamped with a snowflake, available in the yearly advent calendar + * - trick-or-trade: a card that is stamped with a pikachu-pumpkin, available in the yearly halloween/trick-or-trade boosters + * - ace-trainer: a card that is stamped with a golden ACE TRAINER, won by getting 200 championship points in the season since 2025 season. + * - player-rewards-program: a card that is stamped with the player reward logo, available in the yearly player rewards program (play! pokemon prize pack) + * - etc... + */ + stamp?: Array + /** + * for the holo & reverse, **optional** indicate which foil is used on the card + */ + foil?: string + /** + * IDs from third part websites + */ + thirdParty?: { + cardmarket?: number + tcgplayer?: number + } + /** + * A unique ID defining this variant + */ + variantId: string +} + +export interface TcgplayerVariantPricing { + lowPrice: number; + midPrice: number; + highPrice: number; + marketPrice: number; + directLowPrice: number; +} + +/** + * Market pricing information from multiple sources + */ +export interface Pricing { + cardmarket?: { + idProduct: number; + updated?: number; + unit?: string; + avg?: number; + low?: number; + trend?: number; + avg1?: number; + avg7?: number; + avg30?: number; + 'avg-holo'?: number; + 'low-holo'?: number; + 'trend-holo'?: number; + 'avg1-holo'?: number; + 'avg7-holo'?: number; + 'avg30-holo'?: number; + } + tcgplayer?: { + productId: number; + updated: number; + unit: string; + normal?: TcgplayerVariantPricing; + holofoil?: TcgplayerVariantPricing; + 'reverse-holofoil'?: TcgplayerVariantPricing; + '1st-edition'?: TcgplayerVariantPricing; + '1st-edition-holofoil'?: TcgplayerVariantPricing; + 'unlimited'?: TcgplayerVariantPricing; + 'unlimited-holofoil'?: TcgplayerVariantPricing; + } } From 6a5571e85c35b63e5d3310214f477907a6a6a3ef Mon Sep 17 00:00:00 2001 From: advra Date: Sun, 5 Jul 2026 23:33:25 -0700 Subject: [PATCH 2/9] Added missing product ids --- src/models/Other.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/Other.d.ts b/src/models/Other.d.ts index 87177dc..9051899 100644 --- a/src/models/Other.d.ts +++ b/src/models/Other.d.ts @@ -86,8 +86,8 @@ export interface TcgplayerVariantPricing { */ export interface Pricing { cardmarket?: { - idProduct: number; - updated?: number; + idProduct?: number; + updated?: string; unit?: string; avg?: number; low?: number; @@ -104,7 +104,7 @@ export interface Pricing { } tcgplayer?: { productId: number; - updated: number; + updated: string; unit: string; normal?: TcgplayerVariantPricing; holofoil?: TcgplayerVariantPricing; From e02d4772c07718050529529b91e83795c3fc3b33 Mon Sep 17 00:00:00 2001 From: advra Date: Sun, 5 Jul 2026 23:37:01 -0700 Subject: [PATCH 3/9] Formatting --- src/models/Other.d.ts | 193 +++++++++++++++++++++--------------------- 1 file changed, 96 insertions(+), 97 deletions(-) diff --git a/src/models/Other.d.ts b/src/models/Other.d.ts index 9051899..a5aa6d4 100644 --- a/src/models/Other.d.ts +++ b/src/models/Other.d.ts @@ -1,117 +1,116 @@ export interface Variants { - normal?: boolean - reverse?: boolean - holo?: boolean - firstEdition?: boolean + normal?: boolean + reverse?: boolean + holo?: boolean + firstEdition?: boolean } export interface Booster { - - id: string - name: string - logo?: string - artwork_front?: string - artwork_back?: string + id: string + name: string + logo?: string + artwork_front?: string + artwork_back?: string } /** * A better version of variants with additionnal details on each variants */ export interface VariantsDetailed { - /** - * define the variant type - * - normal: no holographic elements - * - holo: the illustration has a foil - * - reverse: everything but the illustration is foiled - */ - type: string - /** - * Some older sets had specific subtypes for the cards - * i.e Base Set had shadowless with and without a 1st-edition stamp. - * and the Unlimited version of the set had no shadow. - */ - subtype?: string - /** - * define the size of the card - * - standard: the classic size of a card - * - jumbo: also said oversized, big card. - */ - size?: string - /** - * indicate that this variant has stamps - * a card may have multiple stamps, example "Ethan's Typhlosion pre-release staff" - * this was a pre-release card only given to staff and has both the set-logo and the staff stamp. - * - 1st-edition: a 1st-edition card (mostly for the first series of the game) - * - w-promo: - * - pre-release: - * - pokemon-center: a card that is stamped with the Pokémon Center logo - * - set-promo: a card that is stamped with the set logo - * - staff: a card that is stamped with the staff text - * - gamestop: a card that is stamped with the GameStop logo - * - eb-games: a card that is stamped with the EB Games logo - * - snowflake: a card that is stamped with a snowflake, available in the yearly advent calendar - * - trick-or-trade: a card that is stamped with a pikachu-pumpkin, available in the yearly halloween/trick-or-trade boosters - * - ace-trainer: a card that is stamped with a golden ACE TRAINER, won by getting 200 championship points in the season since 2025 season. - * - player-rewards-program: a card that is stamped with the player reward logo, available in the yearly player rewards program (play! pokemon prize pack) - * - etc... - */ - stamp?: Array - /** - * for the holo & reverse, **optional** indicate which foil is used on the card - */ - foil?: string - /** - * IDs from third part websites - */ - thirdParty?: { - cardmarket?: number - tcgplayer?: number - } - /** - * A unique ID defining this variant - */ - variantId: string + /** + * define the variant type + * - normal: no holographic elements + * - holo: the illustration has a foil + * - reverse: everything but the illustration is foiled + */ + type: string + /** + * Some older sets had specific subtypes for the cards + * i.e Base Set had shadowless with and without a 1st-edition stamp. + * and the Unlimited version of the set had no shadow. + */ + subtype?: string + /** + * define the size of the card + * - standard: the classic size of a card + * - jumbo: also said oversized, big card. + */ + size?: string + /** + * indicate that this variant has stamps + * a card may have multiple stamps, example "Ethan's Typhlosion pre-release staff" + * this was a pre-release card only given to staff and has both the set-logo and the staff stamp. + * - 1st-edition: a 1st-edition card (mostly for the first series of the game) + * - w-promo: + * - pre-release: + * - pokemon-center: a card that is stamped with the Pokémon Center logo + * - set-promo: a card that is stamped with the set logo + * - staff: a card that is stamped with the staff text + * - gamestop: a card that is stamped with the GameStop logo + * - eb-games: a card that is stamped with the EB Games logo + * - snowflake: a card that is stamped with a snowflake, available in the yearly advent calendar + * - trick-or-trade: a card that is stamped with a pikachu-pumpkin, available in the yearly halloween/trick-or-trade boosters + * - ace-trainer: a card that is stamped with a golden ACE TRAINER, won by getting 200 championship points in the season since 2025 season. + * - player-rewards-program: a card that is stamped with the player reward logo, available in the yearly player rewards program (play! pokemon prize pack) + * - etc... + */ + stamp?: Array + /** + * for the holo & reverse, **optional** indicate which foil is used on the card + */ + foil?: string + /** + * IDs from third part websites + */ + thirdParty?: { + cardmarket?: number + tcgplayer?: number + } + /** + * A unique ID defining this variant + */ + variantId: string } export interface TcgplayerVariantPricing { - lowPrice: number; - midPrice: number; - highPrice: number; - marketPrice: number; - directLowPrice: number; + lowPrice: number; + midPrice: number; + highPrice: number; + marketPrice: number; + directLowPrice: number; } /** * Market pricing information from multiple sources */ export interface Pricing { - cardmarket?: { - idProduct?: number; - updated?: string; - unit?: string; - avg?: number; - low?: number; - trend?: number; - avg1?: number; - avg7?: number; - avg30?: number; - 'avg-holo'?: number; - 'low-holo'?: number; - 'trend-holo'?: number; - 'avg1-holo'?: number; - 'avg7-holo'?: number; - 'avg30-holo'?: number; - } - tcgplayer?: { - productId: number; - updated: string; - unit: string; - normal?: TcgplayerVariantPricing; - holofoil?: TcgplayerVariantPricing; - 'reverse-holofoil'?: TcgplayerVariantPricing; - '1st-edition'?: TcgplayerVariantPricing; - '1st-edition-holofoil'?: TcgplayerVariantPricing; - 'unlimited'?: TcgplayerVariantPricing; - 'unlimited-holofoil'?: TcgplayerVariantPricing; - } + cardmarket?: { + idProduct?: number; + updated?: string; + unit?: string; + avg?: number; + low?: number; + trend?: number; + avg1?: number; + avg7?: number; + avg30?: number; + 'avg-holo'?: number; + 'low-holo'?: number; + 'trend-holo'?: number; + 'avg1-holo'?: number; + 'avg7-holo'?: number; + 'avg30-holo'?: number; + } + tcgplayer?: { + productId: number; + updated: string; + unit: string; + normal?: TcgplayerVariantPricing; + holofoil?: TcgplayerVariantPricing; + 'reverse-holofoil'?: TcgplayerVariantPricing; + '1st-edition'?: TcgplayerVariantPricing; + '1st-edition-holofoil'?: TcgplayerVariantPricing; + 'unlimited'?: TcgplayerVariantPricing; + 'unlimited-holofoil'?: TcgplayerVariantPricing; + } } From 00a7a44e10c88df18080888b292961b341cad2dd Mon Sep 17 00:00:00 2001 From: advra Date: Fri, 10 Jul 2026 08:55:45 -0700 Subject: [PATCH 4/9] Added DS_Store to gitignore --- .DS_Store | Bin 0 -> 6148 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..954b3cdd228cbac7c51ffe19cc15856abbbee929 GIT binary patch literal 6148 zcmeHKu}T9$5S@)DNmNj56cIUVMbJjEIz#*d#a2xsMo7G%ruG`a!cHs&8wI~Xu(h!e zEbSHi3g7Im$*h+|D-qcVyYFsiX6NPYvV?;1%!+{6z)$w;RwL?b03{Iltej^B3u>$Hii)7MC!VyL??*zkYmJ zas8E^{zg^28>XL-O4-l4RHY`Boa!`spN^0mD*eN68-~M|dFpYSN%ts+4<*bePn-B0 z(GDG=Kjb@?)7Ww6D9LN#X7N*-4)aNFy(3+IA@d8Uf>i=HhgGIJBz=<0OftC9S|^(; z8FcbHbu(97cZl{WM(rIaQrA~as$!p?vIrH|cpPwG_?N$6qyyTs~ zOPF^ST9xSlnl*SmC0lqe(h-v5dqF&3&OB1V?opDD*F^{dR>KG4oIH|~>@4W(E z0at-Ob34NO|7!R1znkRmyaHZ Date: Fri, 10 Jul 2026 08:58:12 -0700 Subject: [PATCH 5/9] Added all existing tcgplayer pokemon variants and support for future untyped in the api --- src/models/Other.d.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/models/Other.d.ts b/src/models/Other.d.ts index a5aa6d4..4a10548 100644 --- a/src/models/Other.d.ts +++ b/src/models/Other.d.ts @@ -80,6 +80,18 @@ export interface TcgplayerVariantPricing { directLowPrice: number; } +const TCGPLAYER_VARIANTS = [ + 'normal', + 'holofoil', + 'reverse-holofoil', + '1st-edition', + '1st-edition-holofoil', + 'unlimited', + 'unlimited-holofoil', +] as const; + +type TcgplayerVariantKey = typeof TCGPLAYER_VARIANTS[number]; + /** * Market pricing information from multiple sources */ @@ -105,12 +117,9 @@ export interface Pricing { productId: number; updated: string; unit: string; - normal?: TcgplayerVariantPricing; - holofoil?: TcgplayerVariantPricing; - 'reverse-holofoil'?: TcgplayerVariantPricing; - '1st-edition'?: TcgplayerVariantPricing; - '1st-edition-holofoil'?: TcgplayerVariantPricing; - 'unlimited'?: TcgplayerVariantPricing; - 'unlimited-holofoil'?: TcgplayerVariantPricing; + } & { + [K in TcgplayerVariantKey]?: TcgplayerVariantPricing; + } & { + [variant: string]: TcgplayerVariantPricing | undefined; } } From cde9939cba3488b31a3045b8a6311cb7d9d830b9 Mon Sep 17 00:00:00 2001 From: advra Date: Fri, 10 Jul 2026 09:19:23 -0700 Subject: [PATCH 6/9] Added DS_Store to ignore macbook dir files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index dc46084..38ef676 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ coverage # Dist files dist src/version.js + +.DS_Store \ No newline at end of file From 5a97f63bd3536752ecb0df9cfc401e5490e07fbd Mon Sep 17 00:00:00 2001 From: advra Date: Fri, 10 Jul 2026 09:20:15 -0700 Subject: [PATCH 7/9] Removed ds_store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 954b3cdd228cbac7c51ffe19cc15856abbbee929..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKu}T9$5S@)DNmNj56cIUVMbJjEIz#*d#a2xsMo7G%ruG`a!cHs&8wI~Xu(h!e zEbSHi3g7Im$*h+|D-qcVyYFsiX6NPYvV?;1%!+{6z)$w;RwL?b03{Iltej^B3u>$Hii)7MC!VyL??*zkYmJ zas8E^{zg^28>XL-O4-l4RHY`Boa!`spN^0mD*eN68-~M|dFpYSN%ts+4<*bePn-B0 z(GDG=Kjb@?)7Ww6D9LN#X7N*-4)aNFy(3+IA@d8Uf>i=HhgGIJBz=<0OftC9S|^(; z8FcbHbu(97cZl{WM(rIaQrA~as$!p?vIrH|cpPwG_?N$6qyyTs~ zOPF^ST9xSlnl*SmC0lqe(h-v5dqF&3&OB1V?opDD*F^{dR>KG4oIH|~>@4W(E z0at-Ob34NO|7!R1znkRmyaHZ Date: Wed, 15 Jul 2026 01:09:38 -0700 Subject: [PATCH 8/9] Moved productId to variant. Added pricing object to variant --- src/models/Other.d.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/models/Other.d.ts b/src/models/Other.d.ts index 4a10548..4107562 100644 --- a/src/models/Other.d.ts +++ b/src/models/Other.d.ts @@ -60,12 +60,9 @@ export interface VariantsDetailed { */ foil?: string /** - * IDs from third part websites + * pricing data from third party websites */ - thirdParty?: { - cardmarket?: number - tcgplayer?: number - } + pricing?: Pricing; /** * A unique ID defining this variant */ @@ -73,6 +70,7 @@ export interface VariantsDetailed { } export interface TcgplayerVariantPricing { + productId: number; lowPrice: number; midPrice: number; highPrice: number; @@ -114,7 +112,6 @@ export interface Pricing { 'avg30-holo'?: number; } tcgplayer?: { - productId: number; updated: string; unit: string; } & { From 4a1f8aceb5ecf427c3f0c91c9b55c53b855ad4f8 Mon Sep 17 00:00:00 2001 From: advra Date: Wed, 15 Jul 2026 01:11:39 -0700 Subject: [PATCH 9/9] Added unit test --- __tests__/basic.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/__tests__/basic.test.ts b/__tests__/basic.test.ts index dac9cea..fca5b58 100644 --- a/__tests__/basic.test.ts +++ b/__tests__/basic.test.ts @@ -158,3 +158,15 @@ test(`Variant Detailed`, async () => { expect((await tcgdex.card.get('me02-001'))?.variantsDetailed?.[0].type).toBeTruthy() }) + +test(`Variant Pricing`, async () => { + const tcgdex = new TCGdex('en') + TCGdex.fetch = fetch + const card = await tcgdex.card.get('me02-001') + // for backwards compatibility until V3 + expect(card?.pricing).toBeTruthy() + const normalVariant = card?.variantsDetailed?.find(v => v.type === 'normal') + expect(normalVariant?.pricing?.cardmarket).toBeTruthy() + expect(normalVariant?.pricing?.tcgplayer).toBeTruthy() +}) +