mirror of
https://github.com/tcgdex/cards-database.git
synced 2025-06-13 00:09:18 +00:00
feature: Implement new Server infrastructure with GraphQL. (#132)
* Added new compiler to db Signed-off-by: Avior <florian.bouillon@delta-wings.net> * Add compiled DB to artifacts Signed-off-by: Avior <florian.bouillon@delta-wings.net> * Fixed space error Signed-off-by: Avior <florian.bouillon@delta-wings.net> * Fixed? Signed-off-by: Avior <florian.bouillon@delta-wings.net> * Update node.js.yml * Update node.js.yml * Made change so the db is no longer dependent on the SDK Signed-off-by: Avior <florian.bouillon@delta-wings.net> * f Signed-off-by: Avior <florian.bouillon@delta-wings.net> * Fixed artifact Signed-off-by: Avior <florian.bouillon@delta-wings.net> * U Signed-off-by: Avior <florian.bouillon@delta-wings.net> * \Changed folder Signed-off-by: Avior <florian.bouillon@delta-wings.net> * Fixede? Signed-off-by: Avior <florian.bouillon@delta-wings.net> * Try with everything * saved the file ;) * ignore compiler * Fixed prebuild being run again * Fixed public folder Signed-off-by: Avior <github@avior.me> * fixed graphql file Signed-off-by: Avior <github@avior.me> * fixed? Signed-off-by: Avior <github@avior.me> * Check tree because life is potato Signed-off-by: Avior <github@avior.me> * this is harder Signed-off-by: Avior <github@avior.me> * f Signed-off-by: Avior <github@avior.me> * Fixed? Signed-off-by: Avior <github@avior.me> * r Signed-off-by: Avior <github@avior.me> * fd Signed-off-by: Avior <github@avior.me> * added back context Signed-off-by: Avior <github@avior.me> * ah Signed-off-by: Avior <github@avior.me> * AAH Signed-off-by: Avior <github@avior.me> * AAAH Signed-off-by: Avior <github@avior.me> * ffffffffffffffffff Signed-off-by: Avior <github@avior.me> * fix: Changed the default builder Signed-off-by: Avior <github@avior.me> * Removed useless tree function Signed-off-by: Avior <github@avior.me>
This commit is contained in:
7
server/compiler/compilerInterfaces.d.ts
vendored
Normal file
7
server/compiler/compilerInterfaces.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export interface Endpoint<Index extends {} = {}, Item extends {} = {}, SubItem extends {} = {}, C = undefined> {
|
||||
index(common: C): Promise<Index | undefined>
|
||||
item(common: C): Promise<Record<string, Item> | undefined>
|
||||
sub?(common: C, item: string): Promise<Record<string, SubItem> | undefined>
|
||||
common?(): Promise<C>
|
||||
}
|
30
server/compiler/endpoints/cards.ts
Normal file
30
server/compiler/endpoints/cards.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { Card as CardSingle, CardResume } from '../../../meta/definitions/api'
|
||||
import { Card, Languages } from '../../../interfaces'
|
||||
import { Endpoint } from '../compilerInterfaces'
|
||||
import { cardToCardSimple, cardToCardSingle, getCards } from '../utils/cardUtil'
|
||||
|
||||
type CardList = Array<CardResume>
|
||||
|
||||
export default class implements Endpoint<CardList, CardSingle, Record<string, unknown>, Array<[string, Card]>> {
|
||||
|
||||
public constructor(
|
||||
private lang: keyof Languages
|
||||
) {}
|
||||
|
||||
public async index(common: Array<[string, Card]>): Promise<CardList> {
|
||||
return Promise.all(common.map((c) => cardToCardSimple(c[0], c[1], this.lang)))
|
||||
}
|
||||
|
||||
public async item(common: Array<[string, Card]>): Promise<Record<string, CardSingle>> {
|
||||
const items: Record<string, CardSingle> = {}
|
||||
for await (const card of common) {
|
||||
items[`${card[1].set.id}-${card[0]}`] = await cardToCardSingle(card[0], card[1], this.lang)
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
public async common(): Promise<Array<[string, Card]>> {
|
||||
return getCards(this.lang)
|
||||
}
|
||||
|
||||
}
|
33
server/compiler/endpoints/series.ts
Normal file
33
server/compiler/endpoints/series.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Serie as SerieSingle, SerieResume } from '../../../meta/definitions/api'
|
||||
import { Languages, Serie } from '../../../interfaces'
|
||||
import { Endpoint } from '../compilerInterfaces'
|
||||
import { getSeries, serieToSerieSimple, serieToSerieSingle } from '../utils/serieUtil'
|
||||
|
||||
type SerieList = Array<SerieResume>
|
||||
|
||||
export default class implements Endpoint<SerieList, SerieSingle, Record<string, any>, Array<Serie>> {
|
||||
|
||||
public constructor(
|
||||
private lang: keyof Languages
|
||||
) {}
|
||||
|
||||
public async index(common: Array<Serie>): Promise<Array<SerieResume>> {
|
||||
return Promise.all(common.map((s) => serieToSerieSimple(s, this.lang)))
|
||||
}
|
||||
|
||||
public async item(common: Array<Serie>): Promise<Record<string, SerieSingle>> {
|
||||
const items: Record<string, SerieSingle> = {}
|
||||
for await (const val of common) {
|
||||
const gen = await serieToSerieSingle(val, this.lang)
|
||||
const name = val.name[this.lang] as string
|
||||
items[name] = gen
|
||||
items[val.id] = gen
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
public async common(): Promise<Array<Serie>> {
|
||||
return getSeries(this.lang)
|
||||
}
|
||||
|
||||
}
|
57
server/compiler/endpoints/sets.ts
Normal file
57
server/compiler/endpoints/sets.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { Set as SetSingle, Card as CardSingle, SetResume } from '../../../meta/definitions/api'
|
||||
import { getSets, isSetAvailable, setToSetSimple, setToSetSingle } from '../utils/setUtil'
|
||||
import { Languages, Set } from '../../../interfaces'
|
||||
import { Endpoint } from '../compilerInterfaces'
|
||||
import { cardToCardSingle, getCards } from '../utils/cardUtil'
|
||||
|
||||
type SetList = Array<SetResume>
|
||||
|
||||
export default class implements Endpoint<SetList, SetSingle, CardSingle, Array<Set>> {
|
||||
|
||||
public constructor(
|
||||
private lang: keyof Languages
|
||||
) {}
|
||||
|
||||
public async index(common: Array<Set>): Promise<SetList> {
|
||||
const sets = common
|
||||
.sort((a, b) => a.releaseDate > b.releaseDate ? 1 : -1)
|
||||
|
||||
const tmp: SetList = await Promise.all(sets.map((el) => setToSetSimple(el, this.lang)))
|
||||
|
||||
return tmp
|
||||
}
|
||||
|
||||
public async item(common: Array<Set>): Promise<Record<string, SetSingle>> {
|
||||
const sets = await Promise.all(common
|
||||
.map((set) => setToSetSingle(set, this.lang)))
|
||||
const res: Record<string, SetSingle> = {}
|
||||
|
||||
for (const set of sets) {
|
||||
res[set.name] = set
|
||||
res[set.id] = set
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
public async common(): Promise<Array<Set>> {
|
||||
return getSets(undefined, this.lang)
|
||||
}
|
||||
|
||||
public async sub(common: Array<Set>, item: string): Promise<Record<string, CardSingle> | undefined> {
|
||||
const set = common.find((s) => s.name[this.lang] === item || s.id === item)
|
||||
|
||||
if (!set || !isSetAvailable(set, this.lang)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const lit = await getCards(this.lang, set)
|
||||
const list: Record<string, CardSingle> = {}
|
||||
for await (const card of lit) {
|
||||
list[card[0]] = await cardToCardSingle(card[0], card[1], this.lang)
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
}
|
63
server/compiler/index.ts
Normal file
63
server/compiler/index.ts
Normal file
@ -0,0 +1,63 @@
|
||||
/* eslint-disable max-statements */
|
||||
import { Endpoint } from './compilerInterfaces'
|
||||
import { promises as fs } from 'fs'
|
||||
import { fetchRemoteFile } from './utils/util'
|
||||
|
||||
const LANGS = ['en', 'fr', 'es', 'it', 'pt', 'de']
|
||||
|
||||
const DIST_FOLDER = './generated'
|
||||
|
||||
;(async () => {
|
||||
const paths = (await fs.readdir('./compiler/endpoints')).filter((p) => p.endsWith('.ts'))
|
||||
|
||||
console.log('Prefetching pictures')
|
||||
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('Let\'s GO !')
|
||||
|
||||
// Process each languages
|
||||
for await (const lang of LANGS) {
|
||||
console.log('Processing', lang)
|
||||
// loop through """endpoints"""
|
||||
for await (const file of paths) {
|
||||
|
||||
// final folder path
|
||||
const folder = `${DIST_FOLDER}/${lang}`
|
||||
|
||||
// Make the folder
|
||||
await fs.mkdir(folder, {recursive: true})
|
||||
|
||||
// Import the """Endpoint"""
|
||||
const Ep = (await import(`./endpoints/${file}`)).default
|
||||
|
||||
const endpoint = new Ep(lang) as Endpoint
|
||||
|
||||
console.log(file, 'Running Common')
|
||||
let common: any | null = null
|
||||
|
||||
if (endpoint.common) {
|
||||
common = await endpoint.common()
|
||||
}
|
||||
|
||||
console.log(file, 'Running Item')
|
||||
const item = await endpoint.item(common)
|
||||
|
||||
// Write to file
|
||||
await fs.writeFile(`${folder}/${file.replace('.ts', '')}.json`, JSON.stringify(item))
|
||||
|
||||
console.log(file, 'Finished Item')
|
||||
}
|
||||
}
|
||||
|
||||
// Finally copy definitions files to the public folder :D
|
||||
for await (const file of await fs.readdir('../meta/definitions')) {
|
||||
await fs.copyFile('../meta/definitions/' + file, './public/v2/' + file)
|
||||
}
|
||||
|
||||
})()
|
153
server/compiler/utils/cardUtil.ts
Normal file
153
server/compiler/utils/cardUtil.ts
Normal file
@ -0,0 +1,153 @@
|
||||
/* eslint-disable sort-keys */
|
||||
import { setToSetSimple } from './setUtil'
|
||||
import { cardIsLegal, DB_PATH, fetchRemoteFile, smartGlob } from './util'
|
||||
import { Set, SupportedLanguages, Card, Types } from '../../../interfaces'
|
||||
import { Card as CardSingle, CardResume } from '../../../meta/definitions/api'
|
||||
import translate from './translationUtil'
|
||||
|
||||
export async function getCardPictures(cardId: string, card: Card, lang: SupportedLanguages): Promise<string | undefined> {
|
||||
try {
|
||||
const file = await fetchRemoteFile('https://assets.tcgdex.net/datas.json')
|
||||
const fileExists = Boolean(file[lang]?.[card.set.serie.id]?.[card.set.id]?.[cardId])
|
||||
if (fileExists) {
|
||||
return `https://assets.tcgdex.net/${lang}/${card.set.serie.id}/${card.set.id}/${cardId}`
|
||||
}
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export async function cardToCardSimple(id: string, card: Card, lang: SupportedLanguages): Promise<CardResume> {
|
||||
const cardName = card.name[lang]
|
||||
if (!cardName) {
|
||||
throw new Error(`Card (${card.set.id}-${id}) has no name in (${lang})`)
|
||||
}
|
||||
const img = await getCardPictures(id, card, lang)
|
||||
return {
|
||||
id: `${card.set.id}-${id}`,
|
||||
image: img,
|
||||
localId: id,
|
||||
name: cardName
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
export async function cardToCardSingle(localId: string, card: Card, lang: SupportedLanguages): Promise<CardSingle> {
|
||||
const image = await getCardPictures(localId, card, lang)
|
||||
|
||||
if (!card.name[lang]) {
|
||||
throw new Error(`Card (${localId}) dont exist in (${lang})`)
|
||||
}
|
||||
|
||||
return {
|
||||
category: translate('category', card.category, lang) as any,
|
||||
id: `${card.set.id}-${localId}`,
|
||||
illustrator: card.illustrator,
|
||||
image,
|
||||
localId,
|
||||
name: card.name[lang] as string,
|
||||
|
||||
rarity: translate('rarity', card.rarity, lang) as any,
|
||||
set: await setToSetSimple(card.set, lang),
|
||||
variants: {
|
||||
firstEdition: typeof card.variants?.firstEdition === 'boolean' ? card.variants.firstEdition : false,
|
||||
holo: typeof card.variants?.holo === 'boolean' ? card.variants.holo : true,
|
||||
normal: typeof card.variants?.normal === 'boolean' ? card.variants.normal : true,
|
||||
reverse: typeof card.variants?.reverse === 'boolean' ? card.variants.reverse : true
|
||||
},
|
||||
|
||||
|
||||
dexId: card.dexId,
|
||||
hp: card.hp,
|
||||
types: card.types?.map((t) => translate('types', t, lang)) as Array<Types>,
|
||||
evolveFrom: card.evolveFrom && card.evolveFrom[lang],
|
||||
weight: card.weight,
|
||||
description: card.description ? card.description[lang] as string : undefined,
|
||||
level: card.level,
|
||||
stage: translate('stage', card.stage, lang) as any,
|
||||
suffix: translate('suffix', card.suffix, lang) as any,
|
||||
item: card.item ? {
|
||||
name: card.item.name[lang] as string,
|
||||
effect: card.item.effect[lang] as string
|
||||
} : undefined,
|
||||
|
||||
abilities: card.abilities?.map((el) => ({
|
||||
type: translate('abilityType', el.type, lang) as any,
|
||||
name: el.name[lang] as string,
|
||||
effect: el.effect[lang] as string
|
||||
})),
|
||||
|
||||
attacks: card.attacks?.map((el) => ({
|
||||
cost: el.cost?.map((t) => translate('types', t, lang)) as Array<Types>,
|
||||
name: el.name[lang] as string,
|
||||
effect: el.effect ? el.effect[lang] : undefined,
|
||||
damage: el.damage
|
||||
})),
|
||||
weaknesses: card.weaknesses?.map((el) => ({
|
||||
type: translate('types', el.type, lang) as Types,
|
||||
value: el.value
|
||||
})),
|
||||
|
||||
resistances: card.resistances?.map((el) => ({
|
||||
type: translate('types', el.type, lang) as Types,
|
||||
value: el.value
|
||||
})),
|
||||
|
||||
retreat: card.retreat,
|
||||
|
||||
effect: card.effect ? card.effect[lang] : undefined,
|
||||
|
||||
trainerType: translate('trainerType', card.trainerType, lang) as any,
|
||||
energyType: translate('energyType', card.energyType, lang) as any,
|
||||
regulationMark: card.regulationMark,
|
||||
|
||||
legal: {
|
||||
standard: cardIsLegal('standard', card, localId),
|
||||
expanded: cardIsLegal('expanded', card, localId)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param setName the setname of the card
|
||||
* @param id the local id of the card
|
||||
* @returns [the local id, the Card object]
|
||||
*/
|
||||
export async function getCard(serie: string, setName: string, id: string): Promise<Card> {
|
||||
return (await import(`../../${DB_PATH}/data/${serie}/${setName}/${id}.js`)).default
|
||||
}
|
||||
|
||||
export async function getCards(lang: SupportedLanguages, set?: Set): Promise<Array<[string, Card]>> {
|
||||
const cards = await smartGlob(`${DB_PATH}/data/${(set && set.serie.name.en) ?? '*'}/${(set && set.name.en) ?? '*'}/*.js`)
|
||||
const list: Array<[string, Card]> = []
|
||||
for (const path of cards) {
|
||||
const id = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.'))
|
||||
const setName = (set && set.name.en) ?? (() => {
|
||||
const part1 = path.substr(0, path.lastIndexOf(id) - 1)
|
||||
return part1.substr(part1.lastIndexOf('/') + 1)
|
||||
})()
|
||||
const serieName = (set && set.serie.name.en) ?? (() => {
|
||||
const part1 = path.substr(0, path.lastIndexOf(setName) - 1)
|
||||
return part1.substr(part1.lastIndexOf('/') + 1)
|
||||
})()
|
||||
// console.log(path, id, setName)
|
||||
const c = await getCard(serieName, setName, id)
|
||||
if (!c.name[lang]) {
|
||||
continue
|
||||
}
|
||||
list.push([id, c])
|
||||
}
|
||||
|
||||
// Sort by id when possible
|
||||
return list.sort(([a], [b]) => {
|
||||
const ra = parseInt(a, 10)
|
||||
const rb = parseInt(b, 10)
|
||||
if (!isNaN(ra) && !isNaN(rb)) {
|
||||
return ra - rb
|
||||
}
|
||||
return a >= b ? 1 : -1
|
||||
})
|
||||
}
|
66
server/compiler/utils/serieUtil.ts
Normal file
66
server/compiler/utils/serieUtil.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { DB_PATH, smartGlob } from './util'
|
||||
import { setToSetSimple, getSets } from './setUtil'
|
||||
import { Serie, SupportedLanguages, Set } from '../../../interfaces'
|
||||
import { Serie as SerieSingle, SerieResume } from '../../../meta/definitions/api'
|
||||
|
||||
export async function getSerie(name: string): Promise<Serie> {
|
||||
return (await import(`../../${DB_PATH}/data/${name}.js`)).default
|
||||
}
|
||||
|
||||
export async function isSerieAvailable(serie: Serie, lang: SupportedLanguages): Promise<boolean> {
|
||||
if (!serie.name[lang]) {
|
||||
return false
|
||||
}
|
||||
const sets = await getSets(serie.name.en, lang)
|
||||
return sets.length > 0
|
||||
}
|
||||
|
||||
export async function getSeries(lang: SupportedLanguages): Promise<Array<Serie>> {
|
||||
let series: Array<Serie> = (await Promise.all((await smartGlob(`${DB_PATH}/data/*.js`))
|
||||
// Find Serie's name
|
||||
.map((it) => it.substring(it.lastIndexOf('/') + 1, it.length - 3))
|
||||
// Fetch the Serie
|
||||
.map((it) => getSerie(it))))
|
||||
// Filter the serie if no name's exists in the selected lang
|
||||
.filter((serie) => Boolean(serie.name[lang]))
|
||||
|
||||
// Filter available series
|
||||
const isAvailable = await Promise.all(series.map((serie) => isSerieAvailable(serie, lang)))
|
||||
series = series.filter((_, index) => isAvailable[index])
|
||||
|
||||
// Sort series by the first set release date
|
||||
const tmp: Array<[Serie, Set | undefined]> = await Promise.all(series.map(async (it) => [
|
||||
it,
|
||||
(await getSets(it.name.en, lang))
|
||||
.reduce<Set | undefined>((p, c) => p ? p.releaseDate < c.releaseDate ? p : c : c, undefined) as Set
|
||||
] as [Serie, Set]))
|
||||
|
||||
return tmp.sort((a, b) => (a[1] ? a[1].releaseDate : '0') > (b[1] ? b[1].releaseDate : '0') ? 1 : -1).map((it) => it[0])
|
||||
}
|
||||
|
||||
export async function serieToSerieSimple(serie: Serie, lang: SupportedLanguages): Promise<SerieResume> {
|
||||
const setsTmp = await getSets(serie.name.en, lang)
|
||||
const sets = await Promise.all(setsTmp
|
||||
.sort((a, b) => a.releaseDate > b.releaseDate ? 1 : -1)
|
||||
.map((el) => setToSetSimple(el, lang)))
|
||||
const logo = sets.find((set) => set.logo)?.logo
|
||||
return {
|
||||
id: serie.id,
|
||||
logo,
|
||||
name: serie.name[lang] as string
|
||||
}
|
||||
}
|
||||
|
||||
export async function serieToSerieSingle(serie: Serie, lang: SupportedLanguages): Promise<SerieSingle> {
|
||||
const setsTmp = await getSets(serie.name.en, lang)
|
||||
const sets = await Promise.all(setsTmp
|
||||
.sort((a, b) => a.releaseDate > b.releaseDate ? 1 : -1)
|
||||
.map((el) => setToSetSimple(el, lang)))
|
||||
const logo = sets.find((set) => set.logo)?.logo
|
||||
return {
|
||||
id: serie.id,
|
||||
logo,
|
||||
name: serie.name[lang] as string,
|
||||
sets
|
||||
}
|
||||
}
|
104
server/compiler/utils/setUtil.ts
Normal file
104
server/compiler/utils/setUtil.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { Set, SupportedLanguages } from '../../../interfaces'
|
||||
import { DB_PATH, fetchRemoteFile, setIsLegal, smartGlob } from './util'
|
||||
import { cardToCardSimple, getCards } from './cardUtil'
|
||||
import { SetResume, Set as SetSingle } from '../../../meta/definitions/api'
|
||||
|
||||
interface t {
|
||||
[key: string]: Set
|
||||
}
|
||||
|
||||
const setCache: t = {}
|
||||
|
||||
export function isSetAvailable(set: Set, lang: SupportedLanguages): boolean {
|
||||
return lang in set.name && lang in set.serie.name
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set
|
||||
* @param name the name of the set (don't include.js/.ts)
|
||||
*/
|
||||
export async function getSet(name: string, serie = '*'): Promise<Set> {
|
||||
if (!setCache[name]) {
|
||||
try {
|
||||
const [path] = await smartGlob(`${DB_PATH}/data/${serie}/${name}.js`)
|
||||
setCache[name] = (await import('../../' + path)).default
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
console.error(`Error trying to import importing (${`db/data/${serie}/${name}.js`})`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
return setCache[name]
|
||||
}
|
||||
|
||||
// Dont use cache as it wont necessary have them all
|
||||
export async function getSets(serie = '*', lang: SupportedLanguages): Promise<Array<Set>> {
|
||||
// list sets names
|
||||
const rawSets = (await smartGlob(`${DB_PATH}/data/${serie}/*.js`)).map((set) => set.substring(set.lastIndexOf('/') + 1, set.lastIndexOf('.')))
|
||||
// Fetch sets
|
||||
const sets = (await Promise.all(rawSets.map((set) => getSet(set, serie))))
|
||||
// Filter sets
|
||||
.filter((set) => isSetAvailable(set, lang))
|
||||
// Sort sets by release date
|
||||
.sort((a, b) => a.releaseDate > b.releaseDate ? 1 : -1)
|
||||
return sets
|
||||
}
|
||||
|
||||
export async function getSetPictures(set: Set, lang: SupportedLanguages): Promise<[string | undefined, string | undefined]> {
|
||||
try {
|
||||
const file = await fetchRemoteFile('https://assets.tcgdex.net/datas.json')
|
||||
const logoExists = file[lang]?.[set.serie.id]?.[set.id]?.logo ? `https://assets.tcgdex.net/${lang}/${set.serie.id}/${set.id}/logo` : undefined
|
||||
const symbolExists = file.univ?.[set.serie.id]?.[set.id]?.symbol ? `https://assets.tcgdex.net/univ/${set.serie.id}/${set.id}/symbol` : undefined
|
||||
return [
|
||||
logoExists,
|
||||
symbolExists
|
||||
]
|
||||
} catch {
|
||||
return [undefined, undefined]
|
||||
}
|
||||
}
|
||||
|
||||
export async function setToSetSimple(set: Set, lang: SupportedLanguages): Promise<SetResume> {
|
||||
const cards = await getCards(lang, set)
|
||||
const pics = await getSetPictures(set, lang)
|
||||
return {
|
||||
cardCount: {
|
||||
official: set.cardCount.official,
|
||||
total: Math.max(set.cardCount.official, cards.length)
|
||||
},
|
||||
id: set.id,
|
||||
logo: pics[0],
|
||||
name: set.name[lang] as string,
|
||||
symbol: pics[1]
|
||||
}
|
||||
}
|
||||
|
||||
export async function setToSetSingle(set: Set, lang: SupportedLanguages): Promise<SetSingle> {
|
||||
const cards = await getCards(lang, set)
|
||||
const pics = await getSetPictures(set, lang)
|
||||
return {
|
||||
cardCount: {
|
||||
firstEd: cards.reduce((count, card) => count + (card[1].variants?.firstEdition ? 1 : 0), 0),
|
||||
holo: cards.reduce((count, card) => count + (card[1].variants?.holo ? 1 : 0), 0),
|
||||
normal: cards.reduce((count, card) => count + (card[1].variants?.normal ? 1 : 0), 0),
|
||||
official: set.cardCount.official,
|
||||
reverse: cards.reduce((count, card) => count + (card[1].variants?.reverse ? 1 : 0), 0),
|
||||
total: Math.max(set.cardCount.official, cards.length)
|
||||
},
|
||||
cards: await Promise.all(cards.map(([id, card]) => cardToCardSimple(id, card, lang))),
|
||||
id: set.id,
|
||||
legal: {
|
||||
expanded: setIsLegal('expanded', set),
|
||||
standard: setIsLegal('standard', set)
|
||||
},
|
||||
logo: pics[0],
|
||||
name: set.name[lang] as string,
|
||||
releaseDate: set.releaseDate,
|
||||
serie: {
|
||||
id: set.serie.id,
|
||||
name: set.serie.name[lang] as string
|
||||
},
|
||||
symbol: pics[1],
|
||||
tcgOnline: set.tcgOnline
|
||||
}
|
||||
}
|
31
server/compiler/utils/translationUtil.ts
Normal file
31
server/compiler/utils/translationUtil.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { SupportedLanguages } from '../../../interfaces'
|
||||
import es from '../../../meta/translations/es.json'
|
||||
import it from '../../../meta/translations/it.json'
|
||||
import pt from '../../../meta/translations/pt.json'
|
||||
import de from '../../../meta/translations/de.json'
|
||||
import fr from '../../../meta/translations/fr.json'
|
||||
|
||||
type translatable = 'types' | 'rarity' | 'stage' | 'category' | 'suffix' | 'abilityType' | 'trainerType' | 'energyType'
|
||||
|
||||
const translations: Record<string, Record<translatable, Record<string, string>>> = {
|
||||
es,
|
||||
fr,
|
||||
it,
|
||||
pt,
|
||||
de
|
||||
}
|
||||
|
||||
export default function translate(item: translatable, key: string | undefined, lang: SupportedLanguages): string | undefined {
|
||||
if (!key) {
|
||||
return key
|
||||
}
|
||||
// Temporary trenslations are in english while they are being worked on
|
||||
if (lang === 'en' || !Object.keys(translations).includes(lang)) {
|
||||
return key
|
||||
}
|
||||
const res = translations[lang]?.[item]?.[key]
|
||||
if (!res) {
|
||||
throw new Error(`Could not find translation for ${lang}.${item}.${key}`)
|
||||
}
|
||||
return res
|
||||
}
|
59
server/compiler/utils/util.ts
Normal file
59
server/compiler/utils/util.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { Card, Set } from '../../../interfaces'
|
||||
import glob from 'glob'
|
||||
import fetch from 'node-fetch'
|
||||
import * as legals from '../../../meta/legals'
|
||||
|
||||
interface fileCacheInterface {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export const DB_PATH = "../../"
|
||||
|
||||
const fileCache: fileCacheInterface = {}
|
||||
|
||||
export async function fetchRemoteFile<T = any>(url: string): Promise<T> {
|
||||
if (!fileCache[url]) {
|
||||
const resp = await fetch(url, {
|
||||
timeout: 60 * 1000
|
||||
})
|
||||
fileCache[url] = resp.json()
|
||||
}
|
||||
return fileCache[url]
|
||||
}
|
||||
|
||||
const globCache: Record<string, Array<string>> = {}
|
||||
|
||||
export async function smartGlob(query: string): Promise<Array<string>> {
|
||||
if (!globCache[query]) {
|
||||
globCache[query] = await new Promise((res) => {
|
||||
glob(query, (_, matches) => res(matches))
|
||||
})
|
||||
}
|
||||
return globCache[query]
|
||||
}
|
||||
|
||||
export function cardIsLegal(type: 'standard' | 'expanded', card: Card, localId: string): boolean {
|
||||
const legal = legals[type]
|
||||
if (
|
||||
legal.includes.series.includes(card.set.serie.id) ||
|
||||
legal.includes.sets.includes(card.set.id) ||
|
||||
card.regulationMark && legal.includes.regulationMark.includes(card.regulationMark)
|
||||
) {
|
||||
return !(
|
||||
legal.excludes.sets.includes(card.set.id) ||
|
||||
legal.excludes.cards.includes(`${card.set.id}-${localId}`)
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function setIsLegal(type: 'standard' | 'expanded', set: Set): boolean {
|
||||
const legal = legals[type]
|
||||
if (
|
||||
legal.includes.series.includes(set.serie.id) ||
|
||||
legal.includes.sets.includes(set.id)
|
||||
) {
|
||||
return !legal.excludes.sets.includes(set.id)
|
||||
}
|
||||
return false
|
||||
}
|
Reference in New Issue
Block a user