From 42bfe878121d9c103ed2ab401651237fdff45520 Mon Sep 17 00:00:00 2001 From: thomas-bassett Date: Mon, 26 Jan 2026 23:38:29 +0000 Subject: [PATCH 1/9] POC --- .bruno/graphql/v3/cards - serie.bru | 162 ++ .bruno/graphql/v3/folder.bru | 8 + .bruno/graphql/v3/serie - cards.bru | 157 ++ meta/definitions/graphql.gql | 2 +- meta/definitions/v3-graphql.gql | 532 ++++ server/.gitignore | 6 +- server/compiler/index.ts | 109 +- server/package-lock.json | 3277 ++++++++++++++++++++++ server/package.json | 1 + server/public/v3/.gitkeep | 0 server/src/V3/components/Card.ts | 142 + server/src/V3/components/Serie.ts | 108 + server/src/V3/components/Set.ts | 114 + server/src/V3/graphql/index.ts | 71 + server/src/V3/graphql/mappers/pricing.ts | 41 + server/src/V3/graphql/resolver.ts | 126 + server/src/V3/model/Card.ts | 191 ++ server/src/V3/model/CardResume.ts | 24 + server/src/V3/model/Other.d.ts | 15 + server/src/V3/model/Serie.ts | 7 + server/src/V3/model/SerieResume.ts | 5 + server/src/V3/model/Set.ts | 71 + server/src/V3/model/SetResume.ts | 19 + server/src/index.ts | 4 + 24 files changed, 5136 insertions(+), 56 deletions(-) create mode 100644 .bruno/graphql/v3/cards - serie.bru create mode 100644 .bruno/graphql/v3/folder.bru create mode 100644 .bruno/graphql/v3/serie - cards.bru create mode 100644 meta/definitions/v3-graphql.gql create mode 100644 server/package-lock.json create mode 100644 server/public/v3/.gitkeep create mode 100644 server/src/V3/components/Card.ts create mode 100644 server/src/V3/components/Serie.ts create mode 100644 server/src/V3/components/Set.ts create mode 100644 server/src/V3/graphql/index.ts create mode 100644 server/src/V3/graphql/mappers/pricing.ts create mode 100644 server/src/V3/graphql/resolver.ts create mode 100644 server/src/V3/model/Card.ts create mode 100644 server/src/V3/model/CardResume.ts create mode 100644 server/src/V3/model/Other.d.ts create mode 100644 server/src/V3/model/Serie.ts create mode 100644 server/src/V3/model/SerieResume.ts create mode 100644 server/src/V3/model/Set.ts create mode 100644 server/src/V3/model/SetResume.ts diff --git a/.bruno/graphql/v3/cards - serie.bru b/.bruno/graphql/v3/cards - serie.bru new file mode 100644 index 0000000000..3c56018659 --- /dev/null +++ b/.bruno/graphql/v3/cards - serie.bru @@ -0,0 +1,162 @@ +meta { + name: cards > serie + type: graphql + seq: 1 +} + +post { + url: {{BASE_URL}}/v3/graphql + body: graphql + auth: inherit +} + +body:graphql { + query MyQuery { + cards(filters: { id: "eq:base1-1" }) { + abilities { + name + effect + type + } + attacks { + name + damage + effect + cost + } + category + description + dexId + effect + energyType + evolveFrom + hp + id + illustrator + image + item { + effect + name + } + legal { + expanded + standard + } + level + localId + name + rarity + regulationMark + resistances { + type + value + } + retreat + set { + id + name + logo + symbol + serie { + id + logo + name + sets { + id + } + } + tcgOnline + releaseDate + # legal { + # standard, + # expanded + # } + + cardCount { + firstEd + holo + normal + official + reverse + total + } + cards { + id + } + boosters { + id + name + logo + artwork_front + artwork_back + } + } + stage + suffix + trainerType + types + variants { + firstEdition + holo + normal + reverse + wPromo + } + variants_detailed { + type + size + stamps + foil + } + boosters { + id + name + logo + artwork_front + artwork_back + } + weaknesses { + type + value + } + pricing { + cardmarket { + updated + unit + idProduct + avg + low + trend + avg1 + avg7 + avg30 + avgHolo + lowHolo + trendHolo + avg1Holo + avg7Holo + avg30Holo + } + tcgplayer { + updated + unit + prices { + productId + name + lowPrice + midPrice + highPrice + marketPrice + directLowPrice + } + } + } + } + } + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/.bruno/graphql/v3/folder.bru b/.bruno/graphql/v3/folder.bru new file mode 100644 index 0000000000..4a348fcc3b --- /dev/null +++ b/.bruno/graphql/v3/folder.bru @@ -0,0 +1,8 @@ +meta { + name: v3 + seq: 7 +} + +auth { + mode: inherit +} diff --git a/.bruno/graphql/v3/serie - cards.bru b/.bruno/graphql/v3/serie - cards.bru new file mode 100644 index 0000000000..29edf5d0b2 --- /dev/null +++ b/.bruno/graphql/v3/serie - cards.bru @@ -0,0 +1,157 @@ +meta { + name: serie > cards + type: graphql + seq: 2 +} + +post { + url: {{BASE_URL}}/v3/graphql + body: graphql + auth: inherit +} + +body:graphql { + query MyQuery { + series(filters: { id: "eq:base" }) { + id + logo + name + sets { + id + name + logo + symbol + serie { + id + sets { + id + } + } + tcgOnline + releaseDate + cardCount { + firstEd + holo + normal + official + reverse + total + } + cards { + abilities { + name + effect + type + } + attacks { + name + damage + effect + cost + } + category + description + dexId + effect + energyType + evolveFrom + hp + id + illustrator + image + item { + effect + name + } + legal { + expanded + standard + } + level + localId + name + rarity + regulationMark + resistances { + type + value + } + retreat + stage + suffix + trainerType + types + variants { + firstEdition + holo + normal + reverse + wPromo + } + variants_detailed { + type + size + stamps + foil + } + boosters { + id + name + logo + artwork_front + artwork_back + } + weaknesses { + type + value + } + pricing { + cardmarket { + updated + unit + idProduct + avg + low + trend + avg1 + avg7 + avg30 + avgHolo + lowHolo + trendHolo + avg1Holo + avg7Holo + avg30Holo + } + tcgplayer { + updated + unit + prices { + productId + name + lowPrice + midPrice + highPrice + marketPrice + directLowPrice + } + } + } + } + boosters { + id + name + logo + artwork_front + artwork_back + } + } + } + } + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/meta/definitions/graphql.gql b/meta/definitions/graphql.gql index 3f2b7dcffc..797ea3e03f 100644 --- a/meta/definitions/graphql.gql +++ b/meta/definitions/graphql.gql @@ -1,5 +1,5 @@ ################## -# Global # +# V2 # ################## # Locale Directive ex: {sets @locale(fr)} diff --git a/meta/definitions/v3-graphql.gql b/meta/definitions/v3-graphql.gql new file mode 100644 index 0000000000..037fee92bd --- /dev/null +++ b/meta/definitions/v3-graphql.gql @@ -0,0 +1,532 @@ +################## +# V3 # +################## + +# Locale Directive ex: {sets @locale(fr)} +directive @locale ( + """The language to use""" + lang: String! +) on FIELD + +""" +Every queries available on the GraphQL API + +If you have more queries that you would like added, make a new issue here + +https://github.com/tcgdex/cards-database/issues/new/choose +""" + +type Query { + """Find the cards""" + cards(filters: CardsFilters, pagination: Pagination, sort: Sort): [Card] + + """Find the series""" + series(filters: SerieFilters, pagination: Pagination, sort: Sort): [Serie] + + # + # """Find the sets""" + # sets(filters: SetFilters, pagination: Pagination, sort: Sort): [Set] + # + # """Find one card (using the id and set is deprecated)""" + # card( + # id: ID, + # set: String, + # """The new way to filter""" + # filters: CardsFilters + # ): Card + # + # """Find one set (using the id is deprecated)""" + # set( + # id: ID, + # """The new way to filter""" + # filters: SetFilters + # ): Set + # + # """Find one serie (using the id is deprecated)""" + # serie( + # id: ID, + # """The new way to filter""" + # filters: SerieFilters + # ): Serie + +} + +"""Paginate the datas you fetch""" +input Pagination { + """Indicate the page number (from 1)""" + page: Int! + """Indicate the number of items in one page""" + itemsPerPage: Int + count: Float @deprecated(reason: "use itemsPerPage instead") +} + +"""Change how the data is sorted""" +input Sort { + """Indicate which field it will sort using""" + field: String! + """Indicate how it is sorted ("ASC" or "DESC) (default: "ASC")""" + order: String +} + +################## +# Card # +################## + +"""a Card filters""" +input CardsFilters { + """Filter on the card's category (Pokemon, Trainer or Energy)""" + category: String + + """Filter on the card's decription""" + description: String + + """Filter for the card energy type (normal or special)""" + energyType: String + + """Filter for the previous evolution of the current pokémon""" + evolveFrom: String + + """Filter on the Pokémon's HPs""" + hp: Int + + """Filter on the card id""" + id: ID + + """Filter for the card's local id""" + localId: String + + """Filter on the pokémon national pokédex number""" + dexId: Int + + """Filter on the illustrator name""" + illustrator: String + + image: String @deprecated(reason: "this only indicate if a file is present or not, it should not be a filter") + + """Filter on ths Pokémon's level""" + level: Int + + """Filter on the Card's name""" + name: String + + """ + Filter on the card's rarity + + see: https://api.tcgdex.net/v2/en/rarities for the full list + """ + rarity: String + + """Filter on the card's regulation mark""" + regulationMark: String + + """Filter on the Card evolution stage""" + stage: String + + """Filter on the card suffix""" + suffix: String + + """Filter on the trainer type""" + trainerType: String + + """Filter on the retreat point cost""" + retreat: Int +} + +""" +Define what is a card for GraphQL +""" +type Card { + """The pokémon abilities""" + abilities: [AbilitiesListItem] + + """The pokémon attacks""" + attacks: [AttacksListItem] + + """The card category ('Pokemon' | 'Trainer' | 'Energy')""" + category: String! + + """The card description (mostly the Poédex description)""" + description: String + + """The pokémon(s) Pokédex IDs (Pokémons appearing on the card image & name)""" + dexId: [Int] + + """the energy/trainer effect""" + effect: String + + """the energy type ('Normal' | 'Special')""" + energyType: String + + """the previous evolution of the current pokémon""" + evolveFrom: String + + """the Pokémon's HPs""" + hp: Int + + """the card id""" + id: String! + + """the illustrator name""" + illustrator: String + + """The card's image if available (see the docs for more details)""" + image: String + + """The Pokémon's item""" + item: Item + + """The card legality in tournaments""" + legal: Legal! + + """The Pokémon level""" + level: Int + + """the card's local id""" + localId: String! + + """the Card's name""" + name: String! + + """ + the card's rarity + + see: https://api.tcgdex.net/v2/en/rarities for the full list + """ + rarity: String! + + """the card's regulation mark""" + regulationMark: String + + """The pokémon resistances""" + resistances: [WeakResListItem] + + """The Card retreat cost""" + retreat: Int + + "The card's set" + set: Set! + + """the Card evolution stage""" + stage: String + + """the card suffix""" + suffix: String + + """the trainer type""" + trainerType: String + + """The pokémon type(s) (trivia: Even the TCG implemented at some point multiple types for a single card)""" + types: [String] + + """The card variants""" + variants: Variants + + """Detailed card variants, including type, size, and stamps""" + variants_detailed: [DetailedVariants] + + """The boosters in which the card is available""" + boosters: [Booster] + + """The pokémon weaknesses""" + weaknesses: [WeakResListItem] + + pricing: Pricing + # Currently not in any cards + # weight: String! +} + +type Pricing { + cardmarket: CardMarketPricing + tcgplayer: tcgplayerPricing +} + +type CardMarketPricing { + updated: String + unit: String + idProduct: Int + avg: Float + low: Float + trend: Float + avg1: Float + avg7: Float + avg30: Float + avgHolo: Float + lowHolo: Float + trendHolo: Float + avg1Holo: Float + avg7Holo: Float + avg30Holo: Float +} + +type tcgplayerPricing { + updated: String + unit: String + prices: [TCGPlayerPriceVariant] +} + +type TCGPlayerPriceVariant { + name: String! # e.g., "holofoil", "1st-edition-holofoil" + productId: Int + lowPrice: Float + midPrice: Float + highPrice: Float + marketPrice: Float + directLowPrice: Float +} +""" +define a single ability +""" +type AbilitiesListItem { + """The ability effect""" + effect: String + + """The ability name""" + name: String + + """the ability type ('Pokemon Power' | 'Poke-BODY' | 'Poke-POWER' | 'Ability' | 'Ancient Trait')""" + type: String +} + +""" +define a single attack +""" +type AttacksListItem { + """The attack cost in energies (can be affected by the effect)""" + cost: [String] + + """The attack damage (can be affected by the effect)""" + damage: String + + """The attack additionnal effect""" + effect: String + + """The attack name""" + name: String! +} + +""" +Indicate the item a pokémon has on him +""" +type Item { + """the item effect""" + effect: String! + + """the item name""" + name: String! +} + +""" +Indicate the legality of a card for official tournaments +""" +type Legal { + """Is the card playable in expanded tournaments?""" + expanded: Boolean + + """Is the card playable in standard tournaments?""" + standard: Boolean +} + +""" +Definition for the Weakness and REsistance elements +""" +type WeakResListItem { + """the Weakness/resistance type""" + type: String! + + """the Weakness/resistance modifier (can be 2x or 30+ or nothing)""" + value: String +} + +""" +All the card variants +""" +type Variants { + """is the card available in a first edition version?""" + firstEdition: Boolean! + + """can the card be found has an holo?""" + holo: Boolean! + + """can the card be found without special elements?""" + normal: Boolean! + + """Can the card be found a a reverse holo version?""" + reverse: Boolean! + + """was the card a wPromo card?""" + wPromo: Boolean! +} + +""" +Detailed card variants +""" +type DetailedVariants { + """The type of card, e.g., 'normal', 'reverse', 'holo', etc.""" + type: String! + """The size of the card, e.g., 'standard', 'jumbo', etc.""" + size: String! + """Any stamps the variant may have, e.g., '1st-edition', 'Staff', etc.""" + stamps: [String] + """The type of foil""" + foil: String +} +""" +A booster pack for Pokémon TCG cards + +Boosters represent the different pack designs that cards can be obtained from within a set. +Each set may have multiple booster pack designs (e.g., themed around specific Pokémon). +""" +type Booster { + """ + The booster unique identifier + + Format: boo_- + """ + id: String! + + """The display name of the booster pack""" + name: String! + + """The booster pack logo image URL if available""" + logo: String + + """The front artwork image URL of the booster pack if available""" + artwork_front: String + + """The back artwork image URL of the booster pack if available""" + artwork_back: String +} + +################## +# Set # +################## + +""" +Describe a single set +""" +type Set { + """Indicate how much cards is in the set""" + cardCount: CardCount! + + """list the cards in the set""" + cards: [Card] + + """The Set id""" + id: String! + + """The set logo if available""" + logo: String + + """The set's name""" + name: String! + + """The set's symbol if available""" + symbol: String + + """The Set serie""" + serie: Serie + + """The set official release date""" + releaseDate: String + + """The set tcgOnline code if available in the APP""" + tcgOnline: String + + """ + The booster pack designs available for this set + + A set may have multiple booster pack designs, often themed around different Pokémon + """ + boosters: [Booster] +} + +""" +Filters for the set query +""" +input SetFilters { + """The Set id""" + id: String + + """The set's name""" + name: String + + """The Set serie""" + serie: String + + """The set official release date""" + releaseDate: String + + """The set tcgOnline code if available in the APP""" + tcgOnline: String +} + +""" +Indicate how much cards a set contains + +It also indicate how much card for a specific variant +""" +type CardCount { + """The number of first edition cards in the set""" + firstEd: Int + + """The number of holo cards in the set""" + holo: Int + + """The number of normal cards in the set""" + normal: Int + + """The number of cards that are not hidden (generally in the bottom left/right)""" + official: Int! + + """The number of reverse cards in the set""" + reverse: Int + + """The total number of cards in the set""" + total: Int! +} + +################## +# Serie # +################## + +""" +A Pokémon TCG serie +""" +type Serie { + """The Serie ID""" + id: String! + + """The serie's logo if available""" + logo: String + + """the serie's name""" + name: String! + """the list of sets that are part of the serie""" + sets: [Set] +} + +""" +The Serie filters +""" +input SerieFilters { + """the serie's id""" + id: String + + """The name of the serie""" + name: String +} + +################## +# StringEndpoint # +################## + +""" +currently unused but is the general endpoint for every other elements +""" +type StringEndpoint { + """The list of cards that are available in the endpoint""" + cards: [Card]! + + """The endpoint element name""" + name: String! +} diff --git a/server/.gitignore b/server/.gitignore index b36d0e8307..d18cd8eaae 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,7 +1,7 @@ /node_modules /dist /generated -/public/**/graphql.gql -/public/**/api.d.ts -/public/**/openapi.yaml +/public/**/*graphql.gql +/public/**/*api.d.ts +/public/**/*openapi.yaml .env diff --git a/server/compiler/index.ts b/server/compiler/index.ts index 582d190542..b30c7eb1d0 100644 --- a/server/compiler/index.ts +++ b/server/compiler/index.ts @@ -12,62 +12,67 @@ const LANGS: Array = [ const DIST_FOLDER = './generated' ;(async () => { - const paths = (await fs.readdir('./compiler/endpoints')).filter((p) => p.endsWith('.ts')) - - // Prefetch the pictures at the start as it can bug because of bad connection - console.log('1. Loading remote sources') - await fetchRemoteFile('https://assets.tcgdex.net/datas.json') - - // Delete dist folder to be sure to have a clean base - try { - await fs.rm(DIST_FOLDER, {recursive: true}) - } catch {} - - console.log('\n2. Loading informations from GIT') - await loadLastEdits() - - console.log('\n3. Compiling Files') - - // Process each languages - let progressIndex = 0 - for await (const lang of LANGS) { - // loop through """endpoints""" - for await (const file of paths) { - - // final folder path - const folder = `${DIST_FOLDER}/${lang}` - - // console.log('files1:', await fs.readdir('.')) - // console.log('files2:', await fs.readdir(DIST_FOLDER)) - // console.log('files3:', await fs.readdir(folder)) - - // Make the folder - try { - await fs.mkdir(folder, { recursive: true }) - } catch { - // idk why it throws when file is present even if nodejs says it should not throw... - // maybe Bun changed how the throws works... - } - - // Import the """Endpoint""" - const fn = (await import(`./endpoints/${file}`)).default as FileFunction - - // Run the function - console.log(' ', 'Compiling', lang, file) - const item = await fn(lang) - - // Write to file - await fs.writeFile(`${folder}/${file.replace('.ts', '')}.json`, JSON.stringify( - item - )) - - console.log(`${(++progressIndex / (LANGS.length * paths.length) * 100).toFixed(2).padStart(5, '0')}%`, 'Compiled ', lang, file) - } - } + // const paths = (await fs.readdir('./compiler/endpoints')).filter((p) => p.endsWith('.ts')) + // + // // Prefetch the pictures at the start as it can bug because of bad connection + // console.log('1. Loading remote sources') + // await fetchRemoteFile('https://assets.tcgdex.net/datas.json') + // + // // Delete dist folder to be sure to have a clean base + // try { + // await fs.rm(DIST_FOLDER, {recursive: true}) + // } catch {} + // + // console.log('\n2. Loading informations from GIT') + // await loadLastEdits() + // + // console.log('\n3. Compiling Files') + // + // // Process each languages + // let progressIndex = 0 + // for await (const lang of LANGS) { + // // loop through """endpoints""" + // for await (const file of paths) { + // + // // final folder path + // const folder = `${DIST_FOLDER}/${lang}` + // + // // console.log('files1:', await fs.readdir('.')) + // // console.log('files2:', await fs.readdir(DIST_FOLDER)) + // // console.log('files3:', await fs.readdir(folder)) + // + // // Make the folder + // try { + // await fs.mkdir(folder, { recursive: true }) + // } catch { + // // idk why it throws when file is present even if nodejs says it should not throw... + // // maybe Bun changed how the throws works... + // } + // + // // Import the """Endpoint""" + // const fn = (await import(`./endpoints/${file}`)).default as FileFunction + // + // // Run the function + // console.log(' ', 'Compiling', lang, file) + // const item = await fn(lang) + // + // // Write to file + // await fs.writeFile(`${folder}/${file.replace('.ts', '')}.json`, JSON.stringify( + // item + // )) + // + // console.log(`${(++progressIndex / (LANGS.length * paths.length) * 100).toFixed(2).padStart(5, '0')}%`, 'Compiled ', lang, file) + // } + // } console.log('4. Copying static files to public folder') // Finally copy definitions files to the public folder :D for await (const file of await fs.readdir('../meta/definitions')) { + if( file.startsWith("v3-")){ + await fs.copyFile('../meta/definitions/' + file, `./public/v3/${file}`) + continue + } + await fs.copyFile('../meta/definitions/' + file, './public/v2/' + file) } diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 0000000000..2913e31d64 --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,3277 @@ +{ + "name": "@tcgdex/server", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@tcgdex/server", + "license": "MIT", + "dependencies": { + "@cachex/memory": "^1.0.1", + "@dzeio/config": "^1.1.12", + "@dzeio/object-util": "^1.9.1", + "@dzeio/queue": "^1.2.1", + "@graphql-tools/schema": "^10.0.31", + "@sentry/node": "^8.55.0", + "@tcgdex/sdk": "^2.6.0", + "apicache": "^1.6.3", + "express": "^4.21.2", + "graphql": "^15.10.1", + "graphql-http": "^1.22.4", + "ruru": "^2.0.0-beta.22", + "swagger-ui-express": "^5.0.1", + "yaml": "^2.7.1" + }, + "devDependencies": { + "@types/apicache": "^1.6.7", + "@types/express": "^4.17.21", + "@types/node": "^20.17.32", + "@types/swagger-ui-express": "^4.1.8", + "@typescript/native-preview": "^7.0.0-dev.20250805.1", + "glob": "^10.4.5", + "typescript": "^4.9.5" + } + }, + "node_modules/@cachex/core": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@dzeio/object-util": "^1.8.3" + } + }, + "node_modules/@cachex/memory": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@cachex/core": "^1" + } + }, + "node_modules/@cachex/web-storage": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@cachex/core": "^1" + } + }, + "node_modules/@dzeio/config": { + "version": "1.1.12", + "license": "MIT", + "dependencies": { + "package.json": "^2.0.1" + }, + "peerDependencies": { + "@dzeio/object-util": ">=1.4.2", + "@typescript-eslint/parser": ">=5.18.0", + "next": ">=12.1.0", + "next-pre-css": ">=1.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/parser": { + "optional": true + }, + "next": { + "optional": true + }, + "next-pre-css": { + "optional": true + } + } + }, + "node_modules/@dzeio/object-util": { + "version": "1.9.1", + "license": "MIT" + }, + "node_modules/@dzeio/queue": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "license": "MIT" + }, + "node_modules/@graphql-tools/merge": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.1.7.tgz", + "integrity": "sha512-Y5E1vTbTabvcXbkakdFUt4zUIzB1fyaEnVmIWN0l0GMed2gdD01TpZWLUm4RNAxpturvolrb24oGLQrBbPLSoQ==", + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^11.0.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/schema": { + "version": "10.0.31", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.31.tgz", + "integrity": "sha512-ZewRgWhXef6weZ0WiP7/MV47HXiuFbFpiDUVLQl6mgXsWSsGELKFxQsyUCBos60Qqy1JEFAIu3Ns6GGYjGkqkQ==", + "license": "MIT", + "dependencies": { + "@graphql-tools/merge": "^9.1.7", + "@graphql-tools/utils": "^11.0.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/utils": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz", + "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "@whatwg-node/promise-helpers": "^1.0.0", + "cross-inspect": "1.0.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.57.2", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.30.1", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.30.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.57.2", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.46.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.43.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.36" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.16.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.47.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify": { + "version": "0.44.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.19.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.43.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.47.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.45.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.57.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.1", + "@opentelemetry/semantic-conventions": "1.28.0", + "forwarded-parse": "2.1.2", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/instrumentation": { + "version": "0.57.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.1", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/instrumentation/node_modules/@opentelemetry/api-logs": { + "version": "0.57.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.47.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.7.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.44.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.47.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.44.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.51.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.46.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.45.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.45.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core": { + "version": "0.44.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.50.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "1.27.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.27.0", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.46.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.18.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.10.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.30.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.32.0", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@prisma/instrumentation": { + "version": "5.22.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.8", + "@opentelemetry/instrumentation": "^0.49 || ^0.50 || ^0.51 || ^0.52.0 || ^0.53.0", + "@opentelemetry/sdk-trace-base": "^1.22" + } + }, + "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/instrumentation": { + "version": "0.53.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/instrumentation/node_modules/@opentelemetry/api-logs": { + "version": "0.53.0", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@sentry/core": { + "version": "8.55.0", + "license": "MIT", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/node": { + "version": "8.55.0", + "license": "MIT", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/instrumentation-amqplib": "^0.46.0", + "@opentelemetry/instrumentation-connect": "0.43.0", + "@opentelemetry/instrumentation-dataloader": "0.16.0", + "@opentelemetry/instrumentation-express": "0.47.0", + "@opentelemetry/instrumentation-fastify": "0.44.1", + "@opentelemetry/instrumentation-fs": "0.19.0", + "@opentelemetry/instrumentation-generic-pool": "0.43.0", + "@opentelemetry/instrumentation-graphql": "0.47.0", + "@opentelemetry/instrumentation-hapi": "0.45.1", + "@opentelemetry/instrumentation-http": "0.57.1", + "@opentelemetry/instrumentation-ioredis": "0.47.0", + "@opentelemetry/instrumentation-kafkajs": "0.7.0", + "@opentelemetry/instrumentation-knex": "0.44.0", + "@opentelemetry/instrumentation-koa": "0.47.0", + "@opentelemetry/instrumentation-lru-memoizer": "0.44.0", + "@opentelemetry/instrumentation-mongodb": "0.51.0", + "@opentelemetry/instrumentation-mongoose": "0.46.0", + "@opentelemetry/instrumentation-mysql": "0.45.0", + "@opentelemetry/instrumentation-mysql2": "0.45.0", + "@opentelemetry/instrumentation-nestjs-core": "0.44.0", + "@opentelemetry/instrumentation-pg": "0.50.0", + "@opentelemetry/instrumentation-redis-4": "0.46.0", + "@opentelemetry/instrumentation-tedious": "0.18.0", + "@opentelemetry/instrumentation-undici": "0.10.0", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.28.0", + "@prisma/instrumentation": "5.22.0", + "@sentry/core": "8.55.0", + "@sentry/opentelemetry": "8.55.0", + "import-in-the-middle": "^1.11.2" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/opentelemetry": { + "version": "8.55.0", + "license": "MIT", + "dependencies": { + "@sentry/core": "8.55.0" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.28.0" + } + }, + "node_modules/@tcgdex/sdk": { + "version": "2.6.0", + "license": "MIT", + "dependencies": { + "@cachex/memory": "^1", + "@cachex/web-storage": "^1", + "@dzeio/object-util": "^1", + "isomorphic-unfetch": "^3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/apicache": { + "version": "1.6.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/redis": "^2.8.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.36", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/interpret": { + "version": "1.1.3", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.17.32", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/pg": { + "version": "8.6.1", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.18", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/redis": { + "version": "2.8.32", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.7.0", + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "license": "MIT" + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript/native-preview": { + "version": "7.0.0-dev.20250805.1", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsgo": "bin/tsgo.js" + }, + "engines": { + "node": ">=20.6.0" + }, + "optionalDependencies": { + "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20250805.1", + "@typescript/native-preview-darwin-x64": "7.0.0-dev.20250805.1", + "@typescript/native-preview-linux-arm": "7.0.0-dev.20250805.1", + "@typescript/native-preview-linux-arm64": "7.0.0-dev.20250805.1", + "@typescript/native-preview-linux-x64": "7.0.0-dev.20250805.1", + "@typescript/native-preview-win32-arm64": "7.0.0-dev.20250805.1", + "@typescript/native-preview-win32-x64": "7.0.0-dev.20250805.1" + } + }, + "node_modules/@typescript/native-preview-win32-x64": { + "version": "7.0.0-dev.20250805.1", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.6.0" + } + }, + "node_modules/@whatwg-node/promise-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@whatwg-node/promise-helpers/-/promise-helpers-1.3.2.tgz", + "integrity": "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/abs": { + "version": "1.3.15", + "license": "MIT", + "dependencies": { + "ul": "^5.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/apicache": { + "version": "1.6.3", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/capture-stack-trace": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/create-error-class": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "capture-stack-trace": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cross-inspect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.1.tgz", + "integrity": "sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deffy": { + "version": "2.2.5", + "license": "MIT", + "dependencies": { + "typpy": "^2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/err": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "typpy": "^2.2.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "license": "MIT" + }, + "node_modules/exec-limiter": { + "version": "3.2.14", + "license": "MIT", + "dependencies": { + "limit-it": "^3.0.0", + "typpy": "^2.1.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/fresh": { + "version": "0.5.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.name": { + "version": "1.0.14", + "license": "MIT", + "dependencies": { + "noop6": "^1.0.1" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/git-package-json": { + "version": "1.4.11", + "license": "MIT", + "dependencies": { + "deffy": "^2.2.1", + "err": "^1.1.1", + "gry": "^5.0.0", + "normalize-package-data": "^2.3.5", + "oargv": "^3.4.1", + "one-by-one": "^3.1.0", + "r-json": "^1.2.1", + "r-package-json": "^1.0.0", + "tmp": "0.0.28" + } + }, + "node_modules/git-source": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "git-url-parse": "^5.0.1" + } + }, + "node_modules/git-up": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "is-ssh": "^1.0.0", + "parse-url": "^1.0.0" + } + }, + "node_modules/git-url-parse": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "git-up": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "5.7.1", + "license": "MIT", + "dependencies": { + "create-error-class": "^3.0.1", + "duplexer2": "^0.1.4", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "node-status-codes": "^1.0.0", + "object-assign": "^4.0.1", + "parse-json": "^2.1.0", + "pinkie-promise": "^2.0.0", + "read-all-stream": "^3.0.0", + "readable-stream": "^2.0.5", + "timed-out": "^3.0.0", + "unzip-response": "^1.0.2", + "url-parse-lax": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0 <7" + } + }, + "node_modules/graphile-config": { + "version": "0.0.1-beta.15", + "license": "MIT", + "dependencies": { + "@types/interpret": "^1.1.1", + "@types/node": "^20.5.7", + "@types/semver": "^7.5.1", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "interpret": "^3.1.1", + "semver": "^7.5.4", + "tslib": "^2.6.2", + "yargs": "^17.7.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/graphile-config/node_modules/debug": { + "version": "4.4.0", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/graphile-config/node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/graphql": { + "version": "15.10.1", + "license": "MIT", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/graphql-http": { + "version": "1.22.4", + "license": "MIT", + "workspaces": [ + "implementations/**/*" + ], + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, + "node_modules/gry": { + "version": "5.0.8", + "license": "MIT", + "dependencies": { + "abs": "^1.2.1", + "exec-limiter": "^3.0.0", + "one-by-one": "^3.0.0", + "ul": "^5.0.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "license": "ISC" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-in-the-middle": { + "version": "1.13.1", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "license": "ISC" + }, + "node_modules/interpret": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-redirect": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-retry-allowed": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-ssh": { + "version": "1.4.1", + "license": "MIT", + "dependencies": { + "protocols": "^2.0.1" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/isomorphic-unfetch": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, + "node_modules/iterate-object": { + "version": "1.3.5", + "license": "MIT" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/limit-it": { + "version": "3.2.11", + "license": "MIT", + "dependencies": { + "typpy": "^2.0.0" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "dev": true, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-status-codes": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/noop6": { + "version": "1.0.10", + "license": "MIT" + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/oargv": { + "version": "3.4.11", + "license": "MIT", + "dependencies": { + "iterate-object": "^1.1.0", + "ul": "^5.0.0" + } + }, + "node_modules/obj-def": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "deffy": "^2.2.2" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/one-by-one": { + "version": "3.2.9", + "license": "MIT", + "dependencies": { + "obj-def": "^1.0.0", + "sliced": "^1.0.1" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json": { + "version": "2.4.0", + "license": "MIT", + "dependencies": { + "got": "^5.0.0", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/package-json-path": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "abs": "^1.2.1" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "5.7.2", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/package.json": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "git-package-json": "^1.4.0", + "git-source": "^1.1.0", + "package-json": "^2.3.1" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-url": { + "version": "1.3.11", + "license": "MIT", + "dependencies": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0" + } + }, + "node_modules/parse-url/node_modules/protocols": { + "version": "1.4.8", + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.9.5", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prepend-http": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/protocols": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/r-json": { + "version": "1.3.1", + "license": "MIT", + "dependencies": { + "w-json": "1.3.10" + } + }, + "node_modules/r-package-json": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "package-json-path": "^1.0.0", + "r-json": "^1.2.1" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/read-all-stream": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "pinkie-promise": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/registry-auth-token": { + "version": "3.4.0", + "license": "MIT", + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/require-in-the-middle/node_modules/debug": { + "version": "4.4.0", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/require-in-the-middle/node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.10", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ruru": { + "version": "2.0.0-beta.22", + "license": "MIT", + "dependencies": { + "@emotion/is-prop-valid": "^1.2.1", + "graphile-config": "^0.0.1-beta.15", + "graphql": "^16.1.0-experimental-stream-defer.6", + "http-proxy": "^1.18.1", + "tslib": "^2.6.2", + "yargs": "^17.7.2" + }, + "bin": { + "ruru": "dist/cli-run.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphile-config": "^0.0.1-beta.15", + "graphql": "^16.1.0-experimental-stream-defer.6" + } + }, + "node_modules/ruru/node_modules/graphql": { + "version": "16.11.0", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "license": "BSD-2-Clause" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sliced": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.21", + "license": "CC0-1.0" + }, + "node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.21.0", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, + "node_modules/swagger-ui-express": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/timed-out": { + "version": "3.1.3", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tmp": { + "version": "0.0.28", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "license": "0BSD" + }, + "node_modules/type-is": { + "version": "1.6.18", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typpy": { + "version": "2.4.0", + "license": "MIT", + "dependencies": { + "function.name": "^1.0.3" + } + }, + "node_modules/ul": { + "version": "5.2.16", + "license": "MIT", + "dependencies": { + "deffy": "^2.2.2", + "typpy": "^2.3.4" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "license": "MIT" + }, + "node_modules/unfetch": { + "version": "4.2.0", + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unzip-response": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/url-parse-lax": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/w-json": { + "version": "1.3.10", + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/string-width/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.7.1", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/server/package.json b/server/package.json index e9776bf169..90c81d45d5 100644 --- a/server/package.json +++ b/server/package.json @@ -14,6 +14,7 @@ "@dzeio/config": "^1.1.12", "@dzeio/object-util": "^1.9.1", "@dzeio/queue": "^1.2.1", + "@graphql-tools/schema": "^10.0.31", "@sentry/node": "^8.55.0", "@tcgdex/sdk": "^2.6.0", "apicache": "^1.6.3", diff --git a/server/public/v3/.gitkeep b/server/public/v3/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/server/src/V3/components/Card.ts b/server/src/V3/components/Card.ts new file mode 100644 index 0000000000..8f3f8ade09 --- /dev/null +++ b/server/src/V3/components/Card.ts @@ -0,0 +1,142 @@ +import Cache from '@cachex/memory' +import { objectOmit } from '@dzeio/object-util' +import { SupportedLanguages } from '@tcgdex/sdk' +import de from '../../../generated/de/cards.json' +import en from '../../../generated/en/cards.json' +import esmx from '../../../generated/es-mx/cards.json' +import es from '../../../generated/es/cards.json' +import fr from '../../../generated/fr/cards.json' +import id from '../../../generated/id/cards.json' +import it from '../../../generated/it/cards.json' +import ja from '../../../generated/ja/cards.json' +import ko from '../../../generated/ko/cards.json' +import nl from '../../../generated/nl/cards.json' +import pl from '../../../generated/pl/cards.json' +import ptbr from '../../../generated/pt-br/cards.json' +import ptpt from '../../../generated/pt-pt/cards.json' +import pt from '../../../generated/pt/cards.json' +import ru from '../../../generated/ru/cards.json' +import th from '../../../generated/th/cards.json' +import zhcn from '../../../generated/zh-cn/cards.json' +import zhtw from '../../../generated/zh-tw/cards.json' +import { getCardMarketPrice } from '../../libs/providers/cardmarket' +import { getTCGPlayerPrice } from '../../libs/providers/tcgplayer' +import { executeQuery, type Query } from '../../libs/QueryEngine/filter' +import Card from "../model/Card"; +import { getSetById } from "./Set"; + +// any is CompiledCard that is currently not mapped correctly +const list: Record<`${string | any}${SupportedLanguages | string}`, any> = {} + +// @ts-ignore ts can't load file +en.forEach((it) => list[`${it.id.toLowerCase()}en`] = it) +// @ts-ignore ts can't load file +fr.forEach((it) => list[`${it.id.toLowerCase()}fr`] = it) +// @ts-ignore ts can't load file +es.forEach((it) => list[`${it.id.toLowerCase()}es`] = it) +esmx.forEach((it) => list[`${it.id.toLowerCase()}es-mx`] = it) +// @ts-ignore ts can't load file +it.forEach((it) => list[`${it.id.toLowerCase()}it`] = it) +// @ts-ignore ts can't load file +pt.forEach((it) => list[`${it.id.toLowerCase()}pt`] = it) +ptbr.forEach((it) => list[`${it.id.toLowerCase()}pt-br`] = it) +// @ts-expect-error there is currently not cards here +ptpt.forEach((it) => list[`${it.id.toLowerCase()}pt-pt`] = it) +// @ts-ignore ts can't load file +de.forEach((it) => list[`${it.id.toLowerCase()}de`] = it) +// @ts-expect-error there is currently not cards here +nl.forEach((it) => list[`${it.id.toLowerCase()}nl`] = it) +// @ts-expect-error there is currently not cards here +pl.forEach((it) => list[`${it.id.toLowerCase()}pl`] = it) +// @ts-expect-error there is currently not cards here +ru.forEach((it) => list[`${it.id.toLowerCase()}ru`] = it) +// @ts-ignore +ja.forEach((it) => list[`${it.id.toLowerCase()}ja`] = it) +// @ts-expect-error there is currently not cards here +ko.forEach((it) => list[`${it.id.toLowerCase()}ko`] = it) +// @ts-ignore ts can't load file +zhtw.forEach((it) => list[`${it.id.toLowerCase()}zh-tw`] = it) +id.forEach((it) => list[`${it.id.toLowerCase()}id`] = it) +// @ts-ignore +th.forEach((it) => list[`${it.id.toLowerCase()}th`] = it) +zhcn.forEach((it) => list[`${it.id.toLowerCase()}zh-cn`] = it) + +const cards = { + en: en, + fr: fr, + es: es, + 'es-mx': esmx, + it: it, + pt: pt, + 'pt-br': ptbr, + 'pt-pt': ptpt, + de: de, + nl: nl, + pl: pl, + ru: ru, + ja: ja, + ko: ko, + 'zh-tw': zhtw, + id: id, + th: th, + 'zh-cn': zhcn, +} as const + +const cache = new Cache() + +type MappedCard = any // (typeof en)[number] + +export async function getAllCards(lang: SupportedLanguages): Promise> { + return Promise.all((cards[lang] as Array).map((it) => loadCard(lang, it.id))) as Promise> +} + +/** + * Function that do the hard work of loading the card with the external processors + * + * It should run once until it's timeout runout :D + * @param lang + * @param id + */ +async function loadCard(lang: SupportedLanguages, id: string): Promise { + const key = `${id}${lang}`.toLowerCase() + const value = cache.get(key) + + // expect the cache to be present + if (value) { + return value + } + // console.time(`loading card ${id}${lang}`) + + // console.time('fetching DB') + // @ts-expect-error flemme + const card = list[key] + if (!card) { + return null + } + + //Get Pricing info + const [cardmarket, tcgplayer] = await Promise.all([ + getCardMarketPrice(card), + getTCGPlayerPrice(card), + ]) + + //Get detailed set info + const d_set = await getSetById(lang,card.set.id) + + const res = { + ...objectOmit(card, 'thirdParty'), + set: d_set, + pricing: { + cardmarket: cardmarket, + tcgplayer: tcgplayer + } + } as MappedCard + // console.timeEnd('remapping card') + cache.set(key, res, 60 * 60) + // console.timeEnd(`loading card ${id}${lang}`) + return res +} + +export async function findCards(lang: SupportedLanguages, query: Query) { + return executeQuery(await getAllCards(lang), query).data +} diff --git a/server/src/V3/components/Serie.ts b/server/src/V3/components/Serie.ts new file mode 100644 index 0000000000..9416eef3ed --- /dev/null +++ b/server/src/V3/components/Serie.ts @@ -0,0 +1,108 @@ +import type { SupportedLanguages } from '@tcgdex/sdk' +import { executeQuery, type Query } from '../../libs/QueryEngine/filter' + +import de from '../../../generated/de/series.json' +import en from '../../../generated/en/series.json' +import es from '../../../generated/es/series.json' +import esmx from '../../../generated/es-mx/series.json' +import fr from '../../../generated/fr/series.json' +import id from '../../../generated/id/series.json' +import it from '../../../generated/it/series.json' +import ja from '../../../generated/ja/series.json' +import ko from '../../../generated/ko/series.json' +import nl from '../../../generated/nl/series.json' +import pl from '../../../generated/pl/series.json' +import ptbr from '../../../generated/pt-br/series.json' +import ptpt from '../../../generated/pt-pt/series.json' +import pt from '../../../generated/pt/series.json' +import ru from '../../../generated/ru/series.json' +import th from '../../../generated/th/series.json' +import zhcn from '../../../generated/zh-cn/series.json' +import zhtw from '../../../generated/zh-tw/series.json' +import Cache from "@cachex/memory"; +import type Serie from "../model/Serie"; +import { objectOmit } from "@dzeio/object-util"; +import { getSetById } from "./Set"; + +const series = { + en: en, + fr: fr, + es: es, + 'es-mx': esmx, + it: it, + pt: pt, + 'pt-br': ptbr, + 'pt-pt': ptpt, + de: de, + nl: nl, + pl: pl, + ru: ru, + ja: ja, + ko: ko, + 'zh-tw': zhtw, + id: id, + th: th, + 'zh-cn': zhcn, +} as const + +const cache = new Cache() + +type MappedSerie = any // (typeof en)[number] + +export async function getAllSeries(lang: SupportedLanguages): Promise> { + return Promise.all((series[lang] as Array).map((serie) => transformSerie(lang, serie))) +} + +async function transformSerie(lang: SupportedLanguages ,serie: MappedSerie): Promise { + let sets = [] + + for (const set of serie.sets) { + let d_set = await getSetById(lang, set.id) + if (d_set) { + sets.push(d_set) + } + } + + serie.sets = sets + + return serie +} + +export async function findSeries(lang: SupportedLanguages, query: Query) { + return executeQuery(await getAllSeries(lang), query).data +} + +async function loadSerie(lang: SupportedLanguages, id: string): Promise { + const key = id.toLowerCase() + const value = cache.get(key) + + // expect the cache to be present + if (value) { + return value + } + + const serie = series[lang].find((it) => it.id.toLowerCase() === key) + if (!serie) { + return null + } + + const res = { + ...objectOmit(serie, 'sets'), + } as MappedSerie + + cache.set(key, res, 60 * 60) + return res +} + +export async function getSerieById(lang: SupportedLanguages, id: string) { + return loadSerie(lang, id) +} + + +export async function findOneSerie(lang: SupportedLanguages, query: Query) { + const res = await findSeries(lang, query) + if (res.length === 0) { + return undefined + } + return res[0] +} diff --git a/server/src/V3/components/Set.ts b/server/src/V3/components/Set.ts new file mode 100644 index 0000000000..fc3d810f1b --- /dev/null +++ b/server/src/V3/components/Set.ts @@ -0,0 +1,114 @@ +import { executeQuery, type Query } from '../../libs/QueryEngine/filter' +import { objectOmit } from '@dzeio/object-util' +import type tcgdexSet from '../model/Set' +import de from '../../../generated/de/sets.json' +import en from '../../../generated/en/sets.json' +import es from '../../../generated/es/sets.json' +import esmx from '../../../generated/es-mx/sets.json' +import fr from '../../../generated/fr/sets.json' +import id from '../../../generated/id/sets.json' +import it from '../../../generated/it/sets.json' +import ja from '../../../generated/ja/sets.json' +import ko from '../../../generated/ko/sets.json' +import nl from '../../../generated/nl/sets.json' +import pl from '../../../generated/pl/sets.json' +import ptbr from '../../../generated/pt-br/sets.json' +import ptpt from '../../../generated/pt-pt/sets.json' +import pt from '../../../generated/pt/sets.json' +import ru from '../../../generated/ru/sets.json' +import th from '../../../generated/th/sets.json' +import zhcn from '../../../generated/zh-cn/sets.json' +import zhtw from '../../../generated/zh-tw/sets.json' +import { SupportedLanguages } from "@tcgdex/sdk" +import Cache from "@cachex/memory"; +import { getSerieById } from "./Serie"; +import { getCardById } from "../../V2/Components/Card"; + +export const sets = { + en: en, + fr: fr, + es: es, + 'es-mx': esmx, + it: it, + pt: pt, + 'pt-br': ptbr, + 'pt-pt': ptpt, + de: de, + nl: nl, + pl: pl, + ru: ru, + ja: ja, + ko: ko, + 'zh-tw': zhtw, + id: id, + th: th, + 'zh-cn': zhcn, +} as const + +const cache = new Cache() + +type MappedSet = any // (typeof en)[number] + +export async function getAllSets(lang: SupportedLanguages): Promise> { + return Promise.all((sets[lang] as Array).map(transformSet)) +} + +async function transformSet(set: MappedSet): Promise { + return { + ...objectOmit(set, 'thirdParty'), + // pricing: { + // cardmarket: await getCardMarketPrice(card), + // tcgplayer: await getTCGPlayerPrice(card) + // } + } +} + +async function loadSet(lang: SupportedLanguages, id: string): Promise { + const key = id.toLowerCase() + const value = cache.get(key) + + // expect the cache to be present + if (value) { + return value + } + + const set = sets[lang].find((it) => it.id.toLowerCase() === key) + if (!set) { + return null + } + + const serie = await getSerieById(lang, set.serie.id); + + let cards = [] + for (const card of set.cards) { + let d_card = await getCardById(lang, card.id) + if (d_card) { + cards.push(d_card) + } + } + + const res = { + ...objectOmit(set), + cards: cards, + serie: serie + } as MappedSet + + cache.set(key, res, 60 * 60) + return res +} + +export async function getSetById(lang: SupportedLanguages, id: string) { + return loadSet(lang, id) +} + +export async function findSets(lang: SupportedLanguages, query: Query) { + return executeQuery(await getAllSets(lang), query).data +} + +export async function findOneSet(lang: SupportedLanguages, query: Query) { + const res = await findSets(lang, query) + if (res.length === 0) { + return undefined + } + return res[0] +} diff --git a/server/src/V3/graphql/index.ts b/server/src/V3/graphql/index.ts new file mode 100644 index 0000000000..5f21134b37 --- /dev/null +++ b/server/src/V3/graphql/index.ts @@ -0,0 +1,71 @@ +import express from 'express' +import fs from 'node:fs' +import { type GraphQLError } from 'graphql' +import { createHandler } from 'graphql-http/lib/use/express' +import { type ruruHTML as RuruHTML } from 'ruru/dist/server' +/** @ts-expect-error typing is not correctly mapped (real type at ruru/dist/server.d.ts) */ +import { makeHTMLParts, ruruHTML as tmp } from 'ruru/server' +import resolvers from './resolver' +import { makeExecutableSchema } from "@graphql-tools/schema"; + + +const ruruHTML: typeof RuruHTML = tmp + +// Init Express Router +const router = express.Router() + +/** + * Drawbacks + * Attack.damage is a string instead of possibly being a number or a string + */ +const typeDefs = fs.readFileSync('./public/v3/v3-graphql.gql', 'utf-8') + +// Error Logging for debugging +function graphQLErrorHandle(error: Readonly) { + if (process.env.NODE_ENV !== 'production') { + console.error(error) + } + if (!('source' in error)) { + const columns = (process?.stdout?.columns ?? 32) - 7 + const dashes = ''.padEnd(columns / 2, '-') + + console.error(`\x1b[91m${dashes} ERROR ${dashes}\x1b[0m`) + console.error('GraphQL Error') + console.error(error.message) + console.error(`\x1b[91m${dashes} ERROR ${dashes}\x1b[0m`) + } else if (error.source) { + const columns = (process?.stdout?.columns ?? 32) - 7 + const dashes = ''.padEnd(columns / 2, '-') + + console.error(`\x1b[91m${dashes} ERROR ${dashes}\x1b[0m`) + console.error('GraphQL Error') + console.error(error.message) + console.error(error.source?.body) + console.error(`\x1b[91m${dashes} ERROR ${dashes}\x1b[0m`) + } + return error +} + +const schema = makeExecutableSchema({ + typeDefs, + resolvers, +}); + +const graphql = createHandler({ + schema: schema, + formatError: graphQLErrorHandle +}) + +// Add graphql to the route +router.get('/', (_, res) => { + res.type('html') + res.end(ruruHTML({ endpoint: '/v3/graphql' }, { + ...makeHTMLParts(), + titleTag: 'GraphiQL - TCGdex API V3' + })) +}) + + +router.post('/', graphql) + +export default router diff --git a/server/src/V3/graphql/mappers/pricing.ts b/server/src/V3/graphql/mappers/pricing.ts new file mode 100644 index 0000000000..e47351eaa8 --- /dev/null +++ b/server/src/V3/graphql/mappers/pricing.ts @@ -0,0 +1,41 @@ +function mapCardMarketPricing(pricing: any) { + if (!pricing) return null; + const { updated, unit, idProduct, avg, low, trend, avg1, avg7, avg30, ...holos } = pricing; + return { + updated, + unit, + idProduct, + avg, + low, + trend, + avg1, + avg7, + avg30, + avgHolo: holos['avg-holo'], + lowHolo: holos['low-holo'], + trendHolo: holos['trend-holo'], + avg1Holo: holos['avg1-holo'], + avg7Holo: holos['avg7-holo'], + avg30Holo: holos['avg30-holo'], + } +} + +function mapTcgplayerPricing(pricing: any) { + if (!pricing) return null; + const { updated, unit, ...variants } = pricing; + return { + updated, + unit, + prices: Object.entries(variants).map(([name, value]: [string, any]) => ({ + name, + productId: value.productId, + lowPrice: value.lowPrice, + midPrice: value.midPrice, + highPrice: value.highPrice, + marketPrice: value.marketPrice, + directLowPrice: value.directLowPrice, + })), + }; +} + +export { mapCardMarketPricing, mapTcgplayerPricing }; diff --git a/server/src/V3/graphql/resolver.ts b/server/src/V3/graphql/resolver.ts new file mode 100644 index 0000000000..3ded097a83 --- /dev/null +++ b/server/src/V3/graphql/resolver.ts @@ -0,0 +1,126 @@ +import type { SupportedLanguages } from '@tcgdex/sdk' +import { type Query, Sort } from '../../libs/QueryEngine/filter' +import { recordToQuery } from '../../libs/QueryEngine/parsers' +import { checkLanguage } from '../../util' +import { findCards } from "../components/Card"; +import { mapCardMarketPricing, mapTcgplayerPricing } from "./mappers/pricing"; +import { findSeries } from "../components/Serie"; + +// TODO: make a better way to find the language +function getLang(e: any): SupportedLanguages { + // get the locale directive + const langArgument = e?.fieldNodes?.[0]?.directives?.[0]?.arguments?.[0]?.value + + if (!langArgument) { + return 'en' + } + + if (langArgument.kind === 'Variable') { + return e.variableValues[langArgument.name.value] + } + return langArgument.value +} + +const middleware = (fn: (lang: SupportedLanguages, query: Query) => any) => ( + _parent: any, + args: any, + _context: any, + info: any +) => { + // get the locale directive + const lang = getLang(info) + + const query = recordToQuery(args.filters ?? args) + + // Deprecated code handling + if (args.pagination) { + query.$page = args.pagination.page ?? 1 + query.$limit = args.pagination.itemsPerPage ?? 100 + } + + if (args.sort) { + query.$sort = { + [args.sort.field]: args.sort.order === 'DESC' ? Sort.DESC : Sort.ASC + } + } + + if (!checkLanguage(lang)) { + return undefined + } + + return fn(lang, query) +} + + +export default { + // Query Endpoints + Query: { + cards: middleware((lang, query) => { + return findCards(lang, query); + }), + + series: middleware((lang, query) => { + return findSeries(lang, query); + }) + }, + + // Mapping Resolvers + Card: { + set: (parent: any) => { + if (!parent.set) return null; + return { ...parent.set, _fromCard: true }; + }, + pricing: (parent: any) => { + return parent.pricing; + }, + }, + + Set: { + cards: (parent: any) => { + // Omit cards if this is loaded from a card to prevent circular loading + if (parent._fromCard) { + return null; + } + return parent.cards + }, + + serie: (parent: any) => { + if (!parent.serie) return null; + return { ...parent.serie, _fromSet: true }; + } + }, + + Serie : { + sets: (parent: any) => { + // Omit sets if this is loaded from a set to prevent circular loading + if (parent._fromSet) { + return null; + } + return parent.sets + }, + }, + + Pricing:{ + tcgplayer: (parent: any) => mapTcgplayerPricing(parent.tcgplayer), + cardmarket: (parent: any) => mapCardMarketPricing(parent.cardmarket), + } + // card: middleware((lang, query) => { + // return findOneCard(lang, query) + // }), + // + // // Set Endpoints + // set: middleware((lang, query) => { + // return findOneSet(lang, query) + // }), + // sets: middleware((lang, query) => { + // return findSets(lang, query) + // }), + // + // // Serie Endpoints + // serie: middleware((lang, query) => { + // return findOneSerie(lang, query) + // }), + // series: middleware((lang, query) => { + // return findSeries(lang, query) + // }), +}; diff --git a/server/src/V3/model/Card.ts b/server/src/V3/model/Card.ts new file mode 100644 index 0000000000..ceb29c6393 --- /dev/null +++ b/server/src/V3/model/Card.ts @@ -0,0 +1,191 @@ +import CardResume from './CardResume' +import type { Booster, Variants } from './Other' +import type tcgdexSet from './Set' + +// TODO: sort elements by alphabetical order +export default class Card extends CardResume { + /** + * Card illustrator + */ + public illustrator?: string + + /** + * Card Rarity + * + * - None https://www.tcgdex.net/database/sm/smp/SM01 + * - Common https://www.tcgdex.net/database/xy/xy9/1 + * - Uncommon https://www.tcgdex.net/database/xy/xy9/2 + * - Rare https://www.tcgdex.net/database/xy/xy9/3 + * - Ultra Rare + * - Secret Rare + */ + public rarity!: string + + /** + * Card Category + * + * - Pokemon + * - Trainer + * - Energy + */ + public category!: string + + /** + * Card Variants (Override Set Variants) + */ + public variants?: Variants + + /** + * Card Set + */ + public set!: tcgdexSet + + /** + * Pokemon only elements + */ + + /** + * Pokemon Pokedex ID + */ + public dexId?: Array + + /** + * Pokemon HP + */ + public hp?: number + + /** + * Pokemon Types + * ex for multiple https://www.tcgdex.net/database/ex/ex13/17 + */ + public types?: Array + + /** + * Pokemon Sub Evolution + */ + public evolveFrom?: string + + /** + * Pokemon Weight + */ + public weight?: string + + /** + * Pokemon Description + */ + public description?: string + + /** + * Level of the Pokemon + * + * NOTE: can be equal to 'X' when the pokemon is a LEVEL-UP one + */ + public level?: number | string + + /** + * Pokemon Stage + * + * - Basic https://www.tcgdex.net/database/xy/xy9/1 + * - BREAK https://www.tcgdex.net/database/xy/xy9/18 + * - LEVEL-UP https://www.tcgdex.net/database/dp/dp1/121 + * - MEGA https://www.tcgdex.net/database/xy/xy1/2 + * - RESTORED https://www.tcgdex.net/database/bw/bw5/53 + * - Stage1 https://www.tcgdex.net/database/xy/xy9/2 + * - Stage2 https://www.tcgdex.net/database/xy/xy9/3 + * - VMAX https://www.tcgdex.net/database/swsh/swsh1/50 + */ + public stage?: string + + /** + * Card Suffix + * + * - EX https://www.tcgdex.net/database/ex/ex2/94 + * - GX https://www.tcgdex.net/database/sm/sm12/4 + * - V https://www.tcgdex.net/database/swsh/swsh1/1 + * - Legend https://www.tcgdex.net/database/hgss/hgss1/114 + * - Prime https://www.tcgdex.net/database/hgss/hgss2/85 + * - SP https://www.tcgdex.net/database/pl/pl1/7 + * - TAG TEAM-GX https://www.tcgdex.net/database/sm/sm12/226 + */ + public suffix?: string + + /** + * Pokemon Held Item + * + * ex https://www.tcgdex.net/database/dp/dp2/75 + */ + public item?: { + name: string + effect: string + } + + /** + * Pokemon Abilities + * + * multi abilities ex https://www.tcgdex.net/database/ex/ex15/10 + */ + public abilities?: Array<{ + type: string + name: string + effect: string + }> + + /** + * Pokemon Attacks + */ + public attacks?: Array<{ + cost?: Array + name: string + effect?: string + damage?: string | number + }> + + /** + * Pokemon Weaknesses + */ + public weaknesses?: Array<{ + type: string + value?: string + }> + + public resistances?: Array<{ + type: string + value?: string + }> + + public retreat?: number + + // Trainer/Energy + public effect?: string + + // Trainer Only + public trainerType?: string + + // Energy Only + public energyType?: string + + /** + * Define the rotation mark on cards >= Sword & Shield + */ + public regulationMark?: string + + /** + * Card ability to be played in official tournaments + * + * Note: all cards are avaialable to play in unlimited tournaments + */ + public legal!: { + + /** + * Ability to play in standard tournaments + */ + standard: boolean + + /** + * Ability to play in expanded tournaments + */ + expanded: boolean + } + + public boosters?: Array +} diff --git a/server/src/V3/model/CardResume.ts b/server/src/V3/model/CardResume.ts new file mode 100644 index 0000000000..48103194b7 --- /dev/null +++ b/server/src/V3/model/CardResume.ts @@ -0,0 +1,24 @@ +export default class CardResume { + /** + * Globally unique card ID based on the set ID and the cards ID within the set + */ + public id!: string + + /** + * Card image url without the extension and quality + * + * @see {@link getImageURL} + */ + public image?: string + + /** + * ID indexing this card within its set, usually just its number + */ + public localId!: string + + /** + * Card Name (Including the suffix if next to card name) + */ + public name!: string + +} diff --git a/server/src/V3/model/Other.d.ts b/server/src/V3/model/Other.d.ts new file mode 100644 index 0000000000..3c75056f57 --- /dev/null +++ b/server/src/V3/model/Other.d.ts @@ -0,0 +1,15 @@ +export interface Variants { + normal?: boolean + reverse?: boolean + holo?: boolean + firstEdition?: boolean +} + +export interface Booster { + + id: string + name: string + logo?: string + artwork_front?: string + artwork_back?: string +} diff --git a/server/src/V3/model/Serie.ts b/server/src/V3/model/Serie.ts new file mode 100644 index 0000000000..6e7a994d58 --- /dev/null +++ b/server/src/V3/model/Serie.ts @@ -0,0 +1,7 @@ + +import SerieResume from './SerieResume' +import SetResume from './SetResume' + +export default class Serie extends SerieResume { + public sets?: Array +} diff --git a/server/src/V3/model/SerieResume.ts b/server/src/V3/model/SerieResume.ts new file mode 100644 index 0000000000..35bd539886 --- /dev/null +++ b/server/src/V3/model/SerieResume.ts @@ -0,0 +1,5 @@ +export default class SerieResume { + public id!: string + public name!: string + public logo?: string +} diff --git a/server/src/V3/model/Set.ts b/server/src/V3/model/Set.ts new file mode 100644 index 0000000000..62baecdc35 --- /dev/null +++ b/server/src/V3/model/Set.ts @@ -0,0 +1,71 @@ +import CardResume from './CardResume' +import type { Booster } from './Other' +import type SerieResume from './SerieResume' + +// biome-ignore lint/suspicious/noShadowRestrictedNames: +export default class Set { + public id!: string + public name!: string + public logo?: string + public symbol?: string + public serie!: SerieResume + public tcgOnline?: string + + public releaseDate!: string + + /** + * Designate if the set is usable in tournaments + * + * Note: this is specific to the set and if a + * card is banned from the set it will still be true + */ + public legal!: { + + /** + * Ability to play in standard tournaments + */ + standard: boolean + + /** + * Ability to play in expanded tournaments + */ + expanded: boolean + } + + public cardCount!: { + + /** + * total of number of cards + */ + total: number + + /** + * number of cards officialy (on the bottom of each cards) + */ + official: number + + /** + * number of cards having a normal version + */ + normal: number + + /** + * number of cards having an reverse version + */ + reverse: number + + /** + * number of cards having an holo version + */ + holo: number + + /** + * Number of possible cards + */ + firstEd?: number + } + + public cards?: Array + + public boosters?: Array +} diff --git a/server/src/V3/model/SetResume.ts b/server/src/V3/model/SetResume.ts new file mode 100644 index 0000000000..eeab60752e --- /dev/null +++ b/server/src/V3/model/SetResume.ts @@ -0,0 +1,19 @@ + +export default class SetResume { + public id!: string + public name!: string + public logo?: string + public symbol?: string + public cardCount!: { + + /** + * total of number of cards + */ + total: number + + /** + * number of cards officialy (on the bottom of each cards) + */ + official: number + } +} diff --git a/server/src/index.ts b/server/src/index.ts index ccc8167abe..a6cf9acb8c 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -2,6 +2,7 @@ import express, { type Response } from 'express' import jsonEndpoints from './V2/endpoints/jsonEndpoints' import openapi from './V2/endpoints/openapi' import graphql from './V2/graphql' +import graphqlV3 from './V3/graphql' import cluster from 'node:cluster' import { availableParallelism } from "node:os" import { Errors, sendError } from './libs/Errors' @@ -136,6 +137,9 @@ if (cluster.isPrimary) { // Status page server.use('/status', status) + // Setup v3 previews + server.use(`/v3/graphql`, graphqlV3) + // handle 404 errors server.use((_, res) => { sendError(Errors.NOT_FOUND, res) From 9313d8f9868a075f9d88f6ecf295db55cf9f73a7 Mon Sep 17 00:00:00 2001 From: thomas-bassett Date: Mon, 26 Jan 2026 23:45:31 +0000 Subject: [PATCH 2/9] Update bun.lock --- server/bun.lock | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/bun.lock b/server/bun.lock index b852e40ba5..12f1ad4038 100644 --- a/server/bun.lock +++ b/server/bun.lock @@ -8,6 +8,7 @@ "@dzeio/config": "^1.1.12", "@dzeio/object-util": "^1.9.1", "@dzeio/queue": "^1.2.1", + "@graphql-tools/schema": "^10.0.31", "@sentry/node": "^8.55.0", "@tcgdex/sdk": "^2.6.0", "apicache": "^1.6.3", @@ -46,6 +47,14 @@ "@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="], + "@graphql-tools/merge": ["@graphql-tools/merge@9.1.7", "", { "dependencies": { "@graphql-tools/utils": "^11.0.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-Y5E1vTbTabvcXbkakdFUt4zUIzB1fyaEnVmIWN0l0GMed2gdD01TpZWLUm4RNAxpturvolrb24oGLQrBbPLSoQ=="], + + "@graphql-tools/schema": ["@graphql-tools/schema@10.0.31", "", { "dependencies": { "@graphql-tools/merge": "^9.1.7", "@graphql-tools/utils": "^11.0.0", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-ZewRgWhXef6weZ0WiP7/MV47HXiuFbFpiDUVLQl6mgXsWSsGELKFxQsyUCBos60Qqy1JEFAIu3Ns6GGYjGkqkQ=="], + + "@graphql-tools/utils": ["@graphql-tools/utils@11.0.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA=="], + + "@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="], + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], @@ -188,6 +197,8 @@ "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20250805.1", "", { "os": "win32", "cpu": "x64" }, "sha512-urtTmSfc8/CkE8zWV3+WN5k8rbBZqYaP2xQeNbkJNAO0+eM7DdKvWzen1ehJuHkk3TJ5t4mLj45G4nN50D2PIQ=="], + "@whatwg-node/promise-helpers": ["@whatwg-node/promise-helpers@1.3.2", "", { "dependencies": { "tslib": "^2.6.3" } }, "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA=="], + "abs": ["abs@1.3.15", "", { "dependencies": { "ul": "^5.0.0" } }, "sha512-bpFChpVyZ2F2ppgx7qjZ5TTEO6VVwBauUZDZibpclRGhfcXTHyj11nlqwrg5dN1knxCchssROehm76uCcCayRA=="], "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], @@ -240,6 +251,8 @@ "create-error-class": ["create-error-class@3.0.2", "", { "dependencies": { "capture-stack-trace": "^1.0.0" } }, "sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw=="], + "cross-inspect": ["cross-inspect@1.0.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], From 2b308b30d0fe0333fea6366f8cd2ab0baf3393de Mon Sep 17 00:00:00 2001 From: thomas-bassett Date: Mon, 26 Jan 2026 23:49:51 +0000 Subject: [PATCH 3/9] Uncomment main compiler workflow in index.ts Restores the main async compilation logic by uncommenting code that loads remote sources, cleans the dist folder, loads git info, and compiles endpoint files for each language. This enables the compiler to function as intended instead of being disabled by commented code. --- server/compiler/index.ts | 104 +++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/server/compiler/index.ts b/server/compiler/index.ts index b30c7eb1d0..c4e2c97ae2 100644 --- a/server/compiler/index.ts +++ b/server/compiler/index.ts @@ -12,58 +12,58 @@ const LANGS: Array = [ const DIST_FOLDER = './generated' ;(async () => { - // const paths = (await fs.readdir('./compiler/endpoints')).filter((p) => p.endsWith('.ts')) - // - // // Prefetch the pictures at the start as it can bug because of bad connection - // console.log('1. Loading remote sources') - // await fetchRemoteFile('https://assets.tcgdex.net/datas.json') - // - // // Delete dist folder to be sure to have a clean base - // try { - // await fs.rm(DIST_FOLDER, {recursive: true}) - // } catch {} - // - // console.log('\n2. Loading informations from GIT') - // await loadLastEdits() - // - // console.log('\n3. Compiling Files') - // - // // Process each languages - // let progressIndex = 0 - // for await (const lang of LANGS) { - // // loop through """endpoints""" - // for await (const file of paths) { - // - // // final folder path - // const folder = `${DIST_FOLDER}/${lang}` - // - // // console.log('files1:', await fs.readdir('.')) - // // console.log('files2:', await fs.readdir(DIST_FOLDER)) - // // console.log('files3:', await fs.readdir(folder)) - // - // // Make the folder - // try { - // await fs.mkdir(folder, { recursive: true }) - // } catch { - // // idk why it throws when file is present even if nodejs says it should not throw... - // // maybe Bun changed how the throws works... - // } - // - // // Import the """Endpoint""" - // const fn = (await import(`./endpoints/${file}`)).default as FileFunction - // - // // Run the function - // console.log(' ', 'Compiling', lang, file) - // const item = await fn(lang) - // - // // Write to file - // await fs.writeFile(`${folder}/${file.replace('.ts', '')}.json`, JSON.stringify( - // item - // )) - // - // console.log(`${(++progressIndex / (LANGS.length * paths.length) * 100).toFixed(2).padStart(5, '0')}%`, 'Compiled ', lang, file) - // } - // } + const paths = (await fs.readdir('./compiler/endpoints')).filter((p) => p.endsWith('.ts')) + + // Prefetch the pictures at the start as it can bug because of bad connection + console.log('1. Loading remote sources') + await fetchRemoteFile('https://assets.tcgdex.net/datas.json') + + // Delete dist folder to be sure to have a clean base + try { + await fs.rm(DIST_FOLDER, {recursive: true}) + } catch {} + + console.log('\n2. Loading informations from GIT') + await loadLastEdits() + + console.log('\n3. Compiling Files') + + // Process each languages + let progressIndex = 0 + for await (const lang of LANGS) { + // loop through """endpoints""" + for await (const file of paths) { + + // final folder path + const folder = `${DIST_FOLDER}/${lang}` + + // console.log('files1:', await fs.readdir('.')) + // console.log('files2:', await fs.readdir(DIST_FOLDER)) + // console.log('files3:', await fs.readdir(folder)) + + // Make the folder + try { + await fs.mkdir(folder, { recursive: true }) + } catch { + // idk why it throws when file is present even if nodejs says it should not throw... + // maybe Bun changed how the throws works... + } + + // Import the """Endpoint""" + const fn = (await import(`./endpoints/${file}`)).default as FileFunction + + // Run the function + console.log(' ', 'Compiling', lang, file) + const item = await fn(lang) + + // Write to file + await fs.writeFile(`${folder}/${file.replace('.ts', '')}.json`, JSON.stringify( + item + )) + + console.log(`${(++progressIndex / (LANGS.length * paths.length) * 100).toFixed(2).padStart(5, '0')}%`, 'Compiled ', lang, file) + } + } console.log('4. Copying static files to public folder') // Finally copy definitions files to the public folder :D From 4e0e6191fd769cdd862fbb439dc09a34d0ce7c34 Mon Sep 17 00:00:00 2001 From: thomas-bassett Date: Mon, 26 Jan 2026 23:52:46 +0000 Subject: [PATCH 4/9] Enable sets query in GraphQL API Uncommented and activated the 'sets' query in the GraphQL schema and resolver. Updated Set.ts to properly transform sets and include card details for each set. This allows clients to fetch sets with their associated cards. --- meta/definitions/v3-graphql.gql | 6 +++--- server/src/V3/components/Set.ts | 18 ++++++++++++------ server/src/V3/graphql/resolver.ts | 5 +++++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/meta/definitions/v3-graphql.gql b/meta/definitions/v3-graphql.gql index 037fee92bd..66dabc8745 100644 --- a/meta/definitions/v3-graphql.gql +++ b/meta/definitions/v3-graphql.gql @@ -20,12 +20,12 @@ type Query { """Find the cards""" cards(filters: CardsFilters, pagination: Pagination, sort: Sort): [Card] + """Find the sets""" + sets(filters: SetFilters, pagination: Pagination, sort: Sort): [Set] + """Find the series""" series(filters: SerieFilters, pagination: Pagination, sort: Sort): [Serie] - # - # """Find the sets""" - # sets(filters: SetFilters, pagination: Pagination, sort: Sort): [Set] # # """Find one card (using the id and set is deprecated)""" # card( diff --git a/server/src/V3/components/Set.ts b/server/src/V3/components/Set.ts index fc3d810f1b..edee181368 100644 --- a/server/src/V3/components/Set.ts +++ b/server/src/V3/components/Set.ts @@ -50,16 +50,22 @@ const cache = new Cache() type MappedSet = any // (typeof en)[number] export async function getAllSets(lang: SupportedLanguages): Promise> { - return Promise.all((sets[lang] as Array).map(transformSet)) + return Promise.all((sets[lang] as Array).map((set) => transformSet(lang, set))) } -async function transformSet(set: MappedSet): Promise { +async function transformSet(lang: SupportedLanguages,set: MappedSet): Promise { + let cards = [] + + for (const card of set.cards) { + let d_card = await getCardById(lang, card.id) + if (d_card) { + cards.push(d_card) + } + } + return { ...objectOmit(set, 'thirdParty'), - // pricing: { - // cardmarket: await getCardMarketPrice(card), - // tcgplayer: await getTCGPlayerPrice(card) - // } + cards: cards, } } diff --git a/server/src/V3/graphql/resolver.ts b/server/src/V3/graphql/resolver.ts index 3ded097a83..b5eedbe153 100644 --- a/server/src/V3/graphql/resolver.ts +++ b/server/src/V3/graphql/resolver.ts @@ -5,6 +5,7 @@ import { checkLanguage } from '../../util' import { findCards } from "../components/Card"; import { mapCardMarketPricing, mapTcgplayerPricing } from "./mappers/pricing"; import { findSeries } from "../components/Serie"; +import { findSets } from "../components/Set"; // TODO: make a better way to find the language function getLang(e: any): SupportedLanguages { @@ -59,6 +60,10 @@ export default { return findCards(lang, query); }), + sets: middleware((lang, query) => { + return findSets(lang, query); + }), + series: middleware((lang, query) => { return findSeries(lang, query); }) From 26b19275af65ea9038f13e483cdd6c1c9c8e33e6 Mon Sep 17 00:00:00 2001 From: thomas-bassett Date: Tue, 31 Mar 2026 11:26:47 +0100 Subject: [PATCH 5/9] Mid - add lang support (nonfunctioning) had to switch laptops due to upgrade so had to push this mid work. this may or may not work for now --- .bruno/graphql/v3/multi-lang support.bru | 35 +++++++++++++ meta/definitions/v3-graphql.gql | 62 ++++++++++++++++++++++++ server/src/V3/graphql/resolver.ts | 34 +++++++++++++ server/src/libs/QueryEngine/parsers.ts | 2 +- 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 .bruno/graphql/v3/multi-lang support.bru diff --git a/.bruno/graphql/v3/multi-lang support.bru b/.bruno/graphql/v3/multi-lang support.bru new file mode 100644 index 0000000000..ce32ea1fef --- /dev/null +++ b/.bruno/graphql/v3/multi-lang support.bru @@ -0,0 +1,35 @@ +meta { + name: multi-lang support + type: graphql + seq: 3 +} + +post { + url: {{BASE_URL}}/v3/graphql + body: graphql + auth: inherit +} + +body:graphql { + query { + cards(filters: {}) { + id + locales(langs: ["en", "fr", "de"]) { + name + attacks { + name + damage + effect + cost + } + description + } + } + } + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/meta/definitions/v3-graphql.gql b/meta/definitions/v3-graphql.gql index 66dabc8745..85d2f546fd 100644 --- a/meta/definitions/v3-graphql.gql +++ b/meta/definitions/v3-graphql.gql @@ -132,6 +132,65 @@ input CardsFilters { retreat: Int } +""" +Define locale used for multiple languages support +""" +type CardLocaleData { + lang: String! + + """The pokémon abilities""" + abilities: [AbilitiesListItem] + + """The pokémon attacks""" + attacks: [AttacksListItem] + + """The card category ('Pokemon' | 'Trainer' | 'Energy')""" + category: String! + + """The card description (mostly the Poédex description)""" + description: String + + """the energy/trainer effect""" + effect: String + + """the energy type ('Normal' | 'Special')""" + energyType: String + + """the previous evolution of the current pokémon""" + evolveFrom: String + + """The card's image if available (see the docs for more details)""" + image: String + + """the Card's name""" + name: String! + + """ + the card's rarity + + see: https://api.tcgdex.net/v2/en/rarities for the full list + """ + rarity: String! + + "The card's set" + set: Set! + + """the card suffix""" + suffix: String + + """the trainer type""" + trainerType: String + + """The pokémon type(s) (trivia: Even the TCG implemented at some point multiple types for a single card)""" + types: [String] + + """Detailed card variants, including type, size, and stamps""" + variants_detailed: [DetailedVariants] + + """The pokémon weaknesses""" + weaknesses: [WeakResListItem] +} + """ Define what is a card for GraphQL """ @@ -233,6 +292,9 @@ type Card { pricing: Pricing # Currently not in any cards # weight: String! + + """Locale specific data for the card, e.g., abilities, attacks, description, etc. in a specific language""" + locales(langs: [String!]): [CardLocaleData] } type Pricing { diff --git a/server/src/V3/graphql/resolver.ts b/server/src/V3/graphql/resolver.ts index b5eedbe153..f0ec7110f1 100644 --- a/server/src/V3/graphql/resolver.ts +++ b/server/src/V3/graphql/resolver.ts @@ -7,6 +7,10 @@ import { mapCardMarketPricing, mapTcgplayerPricing } from "./mappers/pricing"; import { findSeries } from "../components/Serie"; import { findSets } from "../components/Set"; +// TODO: once api is the source of truth for supported languages, remove this and use the one from the api instead +const SUPPORTED_LANGUAGES = ['en', 'fr', 'es', 'it', 'pt', 'de', 'nl', 'pl', 'ru', 'zh-tw', 'zh-cn', 'ja', 'ko'] + + // TODO: make a better way to find the language function getLang(e: any): SupportedLanguages { // get the locale directive @@ -22,6 +26,20 @@ function getLang(e: any): SupportedLanguages { return langArgument.value } +// function getLang(info: GraphQLResolveInfo): SupportedLanguages { +// const directives = info.fieldNodes[0]?.directives ?? [] +// const localeDirective = directives.find(d => d.name.value === 'locale') +// const langArg = localeDirective?.arguments?.find(a => a.name.value === 'lang') +// +// if (!langArg) return 'en' +// +// if (langArg.value.kind === 'Variable') { +// return info.variableValues[langArg.value.name.value] as SupportedLanguages +// } +// +// return (langArg.value as StringValueNode).value as SupportedLanguages +// } + const middleware = (fn: (lang: SupportedLanguages, query: Query) => any) => ( _parent: any, args: any, @@ -78,6 +96,22 @@ export default { pricing: (parent: any) => { return parent.pricing; }, + locales: async (parent: any, args: { langs?: SupportedLanguages[] }) => { + const langs = args.langs ?? SUPPORTED_LANGUAGES + const query = recordToQuery(parent) + + return Promise.all( + langs + .filter(checkLanguage) + .map(async (lang: SupportedLanguages) => { + const [card] = await findCards(lang, query) + return { + lang, + ...card + } + }) + ) + } }, Set: { diff --git a/server/src/libs/QueryEngine/parsers.ts b/server/src/libs/QueryEngine/parsers.ts index 1196506f53..cd90f39e0e 100644 --- a/server/src/libs/QueryEngine/parsers.ts +++ b/server/src/libs/QueryEngine/parsers.ts @@ -205,4 +205,4 @@ function parseParam(_key: string, value: string | number): QueryValues } return { $or: items.map((it) => process(it)) } -} \ No newline at end of file +} From 4045508dec453622e18f0ad0eb288f9e8adf1060 Mon Sep 17 00:00:00 2001 From: Thomas <91132581+thomas-bassett@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:26:58 +0100 Subject: [PATCH 6/9] multi lang support for cards --- .bruno/graphql/v3/multi-lang support.bru | 3 +- package-lock.json | 2101 ++++++++++++++++++++++ server/package-lock.json | 102 ++ server/src/V3/components/Card.ts | 5 + server/src/V3/graphql/resolver.ts | 38 +- 5 files changed, 2229 insertions(+), 20 deletions(-) create mode 100644 package-lock.json diff --git a/.bruno/graphql/v3/multi-lang support.bru b/.bruno/graphql/v3/multi-lang support.bru index ce32ea1fef..451a906901 100644 --- a/.bruno/graphql/v3/multi-lang support.bru +++ b/.bruno/graphql/v3/multi-lang support.bru @@ -12,9 +12,10 @@ post { body:graphql { query { - cards(filters: {}) { + cards(filters: { id: "eq:base1-1" }) { id locales(langs: ["en", "fr", "de"]) { + lang name attacks { name diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..6d03c9fad1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2101 @@ +{ + "name": "cards-database", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@dzeio/object-util": "^1.9.2", + "@dzeio/queue": "^1.2.1", + "@types/glob": "^9.0.0", + "@types/jscodeshift": "^17.3.0", + "@types/node": "^20.0.0", + "glob": "^10.0.0", + "jscodeshift": "^17.3.0", + "ts-node": "^10.0.0", + "typescript": "^5.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.28.6.tgz", + "integrity": "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz", + "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-flow": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", + "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", + "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", + "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.27.1.tgz", + "integrity": "sha512-ez3a2it5Fn6P54W8QkbfIyyIbxlXvcxyWHHvno1Wg0Ej5eiJY5hBb8ExttoIOJJk7V2dZE6prP7iby5q2aQ0Lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-transform-flow-strip-types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.28.6.tgz", + "integrity": "sha512-pgcbbEl/dWQYb6L6Yew6F94rdwygfuv+vJ/tXfwIOYAfPB6TNWpXUMEtEq3YuTeHRdvMIhvz13bkT9CNaS+wqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@dzeio/object-util": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@dzeio/object-util/-/object-util-1.9.2.tgz", + "integrity": "sha512-L3EBaHnDmf/+LAC61eCgWzcGXjbaOoFB4ml3eeOFxKlVlO6IZ2BpdstoqgAfLNKqdy4Ixp7TlP5z4ohdPxfSLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@dzeio/queue": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@dzeio/queue/-/queue-1.2.1.tgz", + "integrity": "sha512-OBwp2sqLaqsJXMMtk4SPNTk4iT/KqKYz8+8nKDMIn+JqsAuvfndbPyHG4q7XAyLuGDSuDbR4lF3fLtC3ahwaPw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/glob": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-9.0.0.tgz", + "integrity": "sha512-00UxlRaIUvYm4R4W9WYkN8/J+kV8fmOQ7okeH6YFtGWFMt3odD45tpG5yA5wnL7HE6lLgjaTW5n14ju2hl2NNA==", + "deprecated": "This is a stub types definition. glob provides its own type definitions, so you do not need this installed.", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "*" + } + }, + "node_modules/@types/jscodeshift": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/@types/jscodeshift/-/jscodeshift-17.3.0.tgz", + "integrity": "sha512-ogvGG8VQQqAQQ096uRh+d6tBHrYuZjsumHirKtvBa5qEyTMN3IQJ7apo+sw9lxaB/iKWIhbbLlF3zmAWk9XQIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "recast": "^0.23.11" + } + }, + "node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.13.tgz", + "integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001784", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001784.tgz", + "integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.330", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.330.tgz", + "integrity": "sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/flow-parser": { + "version": "0.307.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.307.1.tgz", + "integrity": "sha512-MIkG26VVtubK0OKgqY17oaMDgCIPgeEMt+XcdNho+aHldUH0uWkQ1uhf8TGxac99vOPTPpUh5OSK5LAmtXUvZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jscodeshift": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-17.3.0.tgz", + "integrity": "sha512-LjFrGOIORqXBU+jwfC9nbkjmQfFldtMIoS6d9z2LG/lkmyNXsJAySPT+2SWXJEoE68/bCWcxKpXH37npftgmow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/preset-flow": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", + "@babel/register": "^7.24.6", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.7", + "neo-async": "^2.5.0", + "picocolors": "^1.0.1", + "recast": "^0.23.11", + "tmp": "^0.2.3", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/server/package-lock.json b/server/package-lock.json index 2913e31d64..d77106fd49 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1030,6 +1030,108 @@ "@typescript/native-preview-win32-x64": "7.0.0-dev.20250805.1" } }, + "node_modules/@typescript/native-preview-darwin-arm64": { + "version": "7.0.0-dev.20250805.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20250805.1.tgz", + "integrity": "sha512-zde7Znjvzx+leJmOCR8FxTBG14sw8r6o8Uz9gaFjv5ziM84NxsRWH2x7Qi92mtC7Dpjl6HFyMH0O7V2MnQBiAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.6.0" + } + }, + "node_modules/@typescript/native-preview-darwin-x64": { + "version": "7.0.0-dev.20250805.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20250805.1.tgz", + "integrity": "sha512-/SPr/zuISYr61JNF8Y6H3hz0pAjqPUPI+K1tpKdPytdddLsHUL0JPV6Lo0jRHyGchUyBINQa3Ur5xgmEEHHWsg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.6.0" + } + }, + "node_modules/@typescript/native-preview-linux-arm": { + "version": "7.0.0-dev.20250805.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20250805.1.tgz", + "integrity": "sha512-1uHvm/fadBA9RsgDAgQqh5s0Fnpp0GF/AfraD1gCkUYTIWOQKa00SSnuWKNgZLEoUn6mceVjAh4bpetOZrnB1Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.6.0" + } + }, + "node_modules/@typescript/native-preview-linux-arm64": { + "version": "7.0.0-dev.20250805.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20250805.1.tgz", + "integrity": "sha512-YGD2wrzoRta9avc7tmCSQ7Bkp6darqtG7Sk6oFqoM0x/hqzWM1iNUNbDDkcuUqRhwT6lIileKeOCg0idmlwPfg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.6.0" + } + }, + "node_modules/@typescript/native-preview-linux-x64": { + "version": "7.0.0-dev.20250805.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20250805.1.tgz", + "integrity": "sha512-VJbCgCEyPi+zL4ZIaASKwPpzm5hWB11mu+9R7Ut+hX9NQ6WaighiNJilWgCKNxa7/7BsAqa2VGTGUcz+62qWKA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.6.0" + } + }, + "node_modules/@typescript/native-preview-win32-arm64": { + "version": "7.0.0-dev.20250805.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20250805.1.tgz", + "integrity": "sha512-qptMfyam9YSkKSQ0aF5HrgIkBGgpASsD8q88yN5RhA4irbf0GO5phmii3BzKYS93PN3saYVW6DVJQYhBh9qy6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.6.0" + } + }, "node_modules/@typescript/native-preview-win32-x64": { "version": "7.0.0-dev.20250805.1", "cpu": [ diff --git a/server/src/V3/components/Card.ts b/server/src/V3/components/Card.ts index 8f3f8ade09..029e937d62 100644 --- a/server/src/V3/components/Card.ts +++ b/server/src/V3/components/Card.ts @@ -137,6 +137,11 @@ async function loadCard(lang: SupportedLanguages, id: string): Promise { + return loadCard(lang, id) +} + + export async function findCards(lang: SupportedLanguages, query: Query) { return executeQuery(await getAllCards(lang), query).data } diff --git a/server/src/V3/graphql/resolver.ts b/server/src/V3/graphql/resolver.ts index f0ec7110f1..c3615a3eb7 100644 --- a/server/src/V3/graphql/resolver.ts +++ b/server/src/V3/graphql/resolver.ts @@ -2,7 +2,7 @@ import type { SupportedLanguages } from '@tcgdex/sdk' import { type Query, Sort } from '../../libs/QueryEngine/filter' import { recordToQuery } from '../../libs/QueryEngine/parsers' import { checkLanguage } from '../../util' -import { findCards } from "../components/Card"; +import { findCards, getCardById } from "../components/Card"; import { mapCardMarketPricing, mapTcgplayerPricing } from "./mappers/pricing"; import { findSeries } from "../components/Serie"; import { findSets } from "../components/Set"; @@ -74,16 +74,19 @@ const middleware = (fn: (lang: SupportedLanguages, query: Query) => any) => ( export default { // Query Endpoints Query: { - cards: middleware((lang, query) => { - return findCards(lang, query); + cards: middleware(async (lang, query) => { + const result = await findCards(lang, query) + return result.map(card => ({ ...card, _query: query })) }), - sets: middleware((lang, query) => { - return findSets(lang, query); + sets: middleware(async (lang, query) => { + const result = await findSets(lang, query) + return result.map(set => ({ ...set, _query: query })) }), - series: middleware((lang, query) => { - return findSeries(lang, query); + series: middleware(async (lang, query) => { + const result = await findSeries(lang, query) + return result.map(series => ({ ...series, _query: query })) }) }, @@ -97,21 +100,18 @@ export default { return parent.pricing; }, locales: async (parent: any, args: { langs?: SupportedLanguages[] }) => { - const langs = args.langs ?? SUPPORTED_LANGUAGES - const query = recordToQuery(parent) + const langs = args.langs ?? SUPPORTED_LANGUAGES; return Promise.all( - langs - .filter(checkLanguage) + langs.filter(checkLanguage) .map(async (lang: SupportedLanguages) => { - const [card] = await findCards(lang, query) - return { - lang, - ...card - } + const card = await getCardById(lang, parent.id); + if (!card) return null; + return { lang, ...card } }) - ) + ).then(results => results.filter(Boolean)) } + }, Set: { @@ -129,7 +129,7 @@ export default { } }, - Serie : { + Serie: { sets: (parent: any) => { // Omit sets if this is loaded from a set to prevent circular loading if (parent._fromSet) { @@ -139,7 +139,7 @@ export default { }, }, - Pricing:{ + Pricing: { tcgplayer: (parent: any) => mapTcgplayerPricing(parent.tcgplayer), cardmarket: (parent: any) => mapCardMarketPricing(parent.cardmarket), } From 37461d0317ba2545739b6847de22195a1c42e9cf Mon Sep 17 00:00:00 2001 From: Thomas <91132581+thomas-bassett@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:58:51 +0100 Subject: [PATCH 7/9] revert some no longer needed things --- server/src/V3/graphql/resolver.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/server/src/V3/graphql/resolver.ts b/server/src/V3/graphql/resolver.ts index c3615a3eb7..fa636b3e99 100644 --- a/server/src/V3/graphql/resolver.ts +++ b/server/src/V3/graphql/resolver.ts @@ -74,19 +74,16 @@ const middleware = (fn: (lang: SupportedLanguages, query: Query) => any) => ( export default { // Query Endpoints Query: { - cards: middleware(async (lang, query) => { - const result = await findCards(lang, query) - return result.map(card => ({ ...card, _query: query })) + cards: middleware((lang, query) => { + return findCards(lang, query) }), - sets: middleware(async (lang, query) => { - const result = await findSets(lang, query) - return result.map(set => ({ ...set, _query: query })) + sets: middleware((lang, query) => { + return findSets(lang, query) }), - series: middleware(async (lang, query) => { - const result = await findSeries(lang, query) - return result.map(series => ({ ...series, _query: query })) + series: middleware((lang, query) => { + return findSeries(lang, query) }) }, From f33fa304d1eab19cfeb4073fbc066c75ea3612f8 Mon Sep 17 00:00:00 2001 From: Thomas <91132581+thomas-bassett@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:08:25 +0100 Subject: [PATCH 8/9] add multi lang set support --- .bruno/graphql/v3/multi-lang support set.bru | 29 ++++++++++++++++++++ meta/definitions/v3-graphql.gql | 19 +++++++++++++ server/src/V3/graphql/resolver.ts | 15 ++++++++-- 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 .bruno/graphql/v3/multi-lang support set.bru diff --git a/.bruno/graphql/v3/multi-lang support set.bru b/.bruno/graphql/v3/multi-lang support set.bru new file mode 100644 index 0000000000..d09c1a01f8 --- /dev/null +++ b/.bruno/graphql/v3/multi-lang support set.bru @@ -0,0 +1,29 @@ +meta { + name: multi-lang support set + type: graphql + seq: 4 +} + +post { + url: {{BASE_URL}}/v3/graphql + body: graphql + auth: inherit +} + +body:graphql { + query { + sets(filters: { id: "eq:base1" }) { + id + locales(langs: ["en", "fr", "de"]) { + lang + name + } + } + } + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/meta/definitions/v3-graphql.gql b/meta/definitions/v3-graphql.gql index 85d2f546fd..87a1726d50 100644 --- a/meta/definitions/v3-graphql.gql +++ b/meta/definitions/v3-graphql.gql @@ -463,6 +463,22 @@ type Booster { # Set # ################## +type SetLocaleData { + lang: String! + + """The set's name""" + name: String! + + """The set's official release date""" + releaseDate: String + + """The set's logo if available""" + logo: String + + """The set's symbol if available""" + symbol: String +} + """ Describe a single set """ @@ -500,6 +516,9 @@ type Set { A set may have multiple booster pack designs, often themed around different Pokémon """ boosters: [Booster] + + """Locale specific data for the set, e.g., name, release date, logo, etc. in a specific language""" + locales(langs: [String!]): [SetLocaleData] } """ diff --git a/server/src/V3/graphql/resolver.ts b/server/src/V3/graphql/resolver.ts index fa636b3e99..bdfcddb1d8 100644 --- a/server/src/V3/graphql/resolver.ts +++ b/server/src/V3/graphql/resolver.ts @@ -5,7 +5,7 @@ import { checkLanguage } from '../../util' import { findCards, getCardById } from "../components/Card"; import { mapCardMarketPricing, mapTcgplayerPricing } from "./mappers/pricing"; import { findSeries } from "../components/Serie"; -import { findSets } from "../components/Set"; +import { findSets, getSetById } from "../components/Set"; // TODO: once api is the source of truth for supported languages, remove this and use the one from the api instead const SUPPORTED_LANGUAGES = ['en', 'fr', 'es', 'it', 'pt', 'de', 'nl', 'pl', 'ru', 'zh-tw', 'zh-cn', 'ja', 'ko'] @@ -108,7 +108,6 @@ export default { }) ).then(results => results.filter(Boolean)) } - }, Set: { @@ -123,6 +122,18 @@ export default { serie: (parent: any) => { if (!parent.serie) return null; return { ...parent.serie, _fromSet: true }; + }, + + locales: async (parent: any, args: { langs?: SupportedLanguages[] }) => { + const langs = args.langs ?? SUPPORTED_LANGUAGES; + return Promise.all( + langs.filter(checkLanguage) + .map(async (lang: SupportedLanguages) => { + const set = await getSetById(lang, parent.id); + if (!set) return null; + return { lang, ...set}; + }) + ) } }, From d8f589119fcd047149bcaeca6276ffe6c2718f79 Mon Sep 17 00:00:00 2001 From: Thomas <91132581+thomas-bassett@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:14:18 +0100 Subject: [PATCH 9/9] add multi lang series support --- .../graphql/v3/multi-lang support series.bru | 29 +++++++++++++++++++ meta/definitions/v3-graphql.gql | 14 +++++++++ server/src/V3/graphql/resolver.ts | 14 ++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 .bruno/graphql/v3/multi-lang support series.bru diff --git a/.bruno/graphql/v3/multi-lang support series.bru b/.bruno/graphql/v3/multi-lang support series.bru new file mode 100644 index 0000000000..9526fa6cfd --- /dev/null +++ b/.bruno/graphql/v3/multi-lang support series.bru @@ -0,0 +1,29 @@ +meta { + name: multi-lang support series + type: graphql + seq: 5 +} + +post { + url: {{BASE_URL}}/v3/graphql + body: graphql + auth: inherit +} + +body:graphql { + query { + series(filters: { id: "eq:base" }) { + id + locales(langs: ["en", "fr", "de"]) { + lang + name + } + } + } + +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/meta/definitions/v3-graphql.gql b/meta/definitions/v3-graphql.gql index 87a1726d50..0c5908dda8 100644 --- a/meta/definitions/v3-graphql.gql +++ b/meta/definitions/v3-graphql.gql @@ -570,6 +570,17 @@ type CardCount { # Serie # ################## +type SerieLocaleData { + lang: String! + + """The serie's name""" + name: String! + + """The serie's logo if available""" + logo: String +} + + """ A Pokémon TCG serie """ @@ -584,6 +595,9 @@ type Serie { name: String! """the list of sets that are part of the serie""" sets: [Set] + + """Locale specific data for the serie, e.g., name, logo, etc. in a specific language""" + locales(langs: [String!]): [SerieLocaleData] } """ diff --git a/server/src/V3/graphql/resolver.ts b/server/src/V3/graphql/resolver.ts index bdfcddb1d8..407b8e7e34 100644 --- a/server/src/V3/graphql/resolver.ts +++ b/server/src/V3/graphql/resolver.ts @@ -4,7 +4,7 @@ import { recordToQuery } from '../../libs/QueryEngine/parsers' import { checkLanguage } from '../../util' import { findCards, getCardById } from "../components/Card"; import { mapCardMarketPricing, mapTcgplayerPricing } from "./mappers/pricing"; -import { findSeries } from "../components/Serie"; +import { findSeries, getSerieById } from "../components/Serie"; import { findSets, getSetById } from "../components/Set"; // TODO: once api is the source of truth for supported languages, remove this and use the one from the api instead @@ -145,6 +145,18 @@ export default { } return parent.sets }, + + locales: async (parent: any, args: { langs?: SupportedLanguages[] }) => { + const langs = args.langs ?? SUPPORTED_LANGUAGES; + return Promise.all( + langs.filter(checkLanguage) + .map(async (lang: SupportedLanguages) => { + const serie = await getSerieById(lang, parent.id); + if (!serie) return null; + return { lang, ...serie}; + }) + ) + } }, Pricing: {