From c476d826181afdd121cc80331abfa94d5f06785e Mon Sep 17 00:00:00 2001 From: Avior Date: Sun, 12 May 2024 00:51:56 +0200 Subject: [PATCH] feat: Add an updated field to the card field (#460) --- Dockerfile | 4 +++ meta/codeshift.ts | 14 ++++++++++ meta/definitions/api.d.ts | 4 ++- server/compiler/index.ts | 4 ++- server/compiler/utils/cardUtil.ts | 12 ++++++--- server/compiler/utils/util.ts | 43 +++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1a053d3cd0..10ec65d907 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,10 @@ FROM docker.io/oven/bun:1-alpine as BUILD_IMAGE # go to work folder WORKDIR /usr/src/app +# Add git as it is used to fetch updated times +RUN apk add git &&\ +git config --global safe.directory '*' + ADD --chown=bun:bun package.json bun.lockb ./ ADD --chown=bun:bun server/package.json server/bun.lockb ./server/ diff --git a/meta/codeshift.ts b/meta/codeshift.ts index 17ae328532..a5d97241ab 100644 --- a/meta/codeshift.ts +++ b/meta/codeshift.ts @@ -56,6 +56,20 @@ function simplify(base: ObjectExpression): ObjectField { } } +function exists(path: ObjectExpression | ArrayExpression, key: string | number) { + if (path.type === 'ObjectExpression') { + path.properties.forEach((p) => { + const prop = p as Property + if ((prop.key as Identifier).name === (key + '')) { + return true + } + }) + return false + } else { + + } +} + function set(j: JSCodeshift, path: ObjectExpression | ArrayExpression, value: Possible, key: string | number, options?: {override?: boolean}) { let exists = false diff --git a/meta/definitions/api.d.ts b/meta/definitions/api.d.ts index f2ca522a1f..a484e20f58 100644 --- a/meta/definitions/api.d.ts +++ b/meta/definitions/api.d.ts @@ -261,7 +261,9 @@ export interface Card extends CardResume { * Ability to play in expanded tournaments */ expanded: boolean; - }; + } + + updated: string } /** diff --git a/server/compiler/index.ts b/server/compiler/index.ts index 8bf6c67a65..fbf7313e96 100644 --- a/server/compiler/index.ts +++ b/server/compiler/index.ts @@ -2,7 +2,7 @@ import { promises as fs } from 'fs' import { SupportedLanguages } from '../../interfaces' import { FileFunction } from './compilerInterfaces' -import { fetchRemoteFile } from './utils/util' +import { fetchRemoteFile, loadLastEdits } from './utils/util' const LANGS: Array = ['en', 'fr', 'es', 'it', 'pt', 'de'] @@ -20,6 +20,8 @@ const DIST_FOLDER = './generated' await fs.rm(DIST_FOLDER, {recursive: true}) } catch {} + console.log('Loading files last edit') + await loadLastEdits() console.log('Let\'s GO !') diff --git a/server/compiler/utils/cardUtil.ts b/server/compiler/utils/cardUtil.ts index 1c4b4443d0..4670073f88 100644 --- a/server/compiler/utils/cardUtil.ts +++ b/server/compiler/utils/cardUtil.ts @@ -1,9 +1,10 @@ /* eslint-disable sort-keys */ +import { exec } from 'child_process' import { Card, Set, SupportedLanguages, Types } from '../../../interfaces' import { CardResume, Card as CardSingle } from '../../../meta/definitions/api' import { setToSetSimple } from './setUtil' import translate from './translationUtil' -import { DB_PATH, cardIsLegal, fetchRemoteFile, smartGlob } from './util' +import { DB_PATH, cardIsLegal, fetchRemoteFile, getLastEdit, smartGlob } from './util' export async function getCardPictures(cardId: string, card: Card, lang: SupportedLanguages): Promise { try { @@ -106,8 +107,8 @@ export async function cardToCardSingle(localId: string, card: Card, lang: Suppor legal: { standard: cardIsLegal('standard', card, localId), expanded: cardIsLegal('expanded', card, localId) - } - + }, + updated: await getCardLastEdit(localId, card) } } @@ -161,3 +162,8 @@ export async function getCards(lang: SupportedLanguages, set?: Set): Promise= b ? 1 : -1 }) } + +async function getCardLastEdit(localId: string, card: Card): Promise { + const path = `../data/${card.set.serie.name.en}/${card.set.name.en ?? card.set.name.fr}/${localId}.ts` + return getLastEdit(path) +} diff --git a/server/compiler/utils/util.ts b/server/compiler/utils/util.ts index 736859e4c7..9b20e73cf6 100644 --- a/server/compiler/utils/util.ts +++ b/server/compiler/utils/util.ts @@ -1,3 +1,4 @@ +import { exec } from 'node:child_process' import { glob } from 'glob' import { Card, Set } from '../../../interfaces' import * as legals from '../../../meta/legals' @@ -79,3 +80,45 @@ export function setIsLegal(type: 'standard' | 'expanded', set: Set): boolean { } return false } + +function runCommand(command: string): Promise { + return new Promise((res, rej) => { + exec(command, (err, out) => { + if (err) { + rej(err) + return + } + res(out) + }) + }) +} + +let lastEditsCache: Record = {} +export async function loadLastEdits() { + const firstCommand = 'git ls-tree -r --name-only HEAD ../data' + const files = (await runCommand(firstCommand)).split('\n') + console.log('Loaded files tree', files.length, 'files') + console.log('Loading their last edit time') + let processed = 0 + for (let file of files) { + file = file.replace(/"/g, '').replace("\\303\\251", "é") + try { + lastEditsCache[file] = await runCommand(`git log -1 --pretty="format:%cd" --date=iso-strict "${file}"`) + } catch { + console.warn('could not load file', file, 'hope it does not break everything else lol') + } + processed++ + if (processed % 1000 === 0) { + console.log('loaded', processed, 'out of', files.length, 'files') + } + } + console.log('done loading files') +} + +export function getLastEdit(path: string): string { + const date = lastEditsCache[path] + if (!date) { + throw new Error(`edit date not found for file ${path}`) + } + return date +}