Files
tabler/.build/import-payments.ts

95 lines
4.6 KiB
JavaScript

#!/usr/bin/env node
// Imports payment provider assets from the tabler/tabler-payments repo: the light
// and dark SVGs (minified with svgo), the $payment-providers list and the demo data.
//
// Run: pnpm run import:payments
// Then: pnpm run generate:tokens — refreshes PaymentProvider in shared/lib/tokens.ts
import { execFileSync } from 'node:child_process'
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join, dirname, relative } from 'node:path'
import { fileURLToPath } from 'node:url'
import { optimizeSvgDir } from './optimize-svg.js'
const __dirname = dirname(fileURLToPath(import.meta.url))
const repoRoot = join(__dirname, '..')
const imgDir = join(repoRoot, 'core', 'img', 'payments')
const scssFile = join(repoRoot, 'core', 'scss', '_variables.scss')
const dataFile = join(repoRoot, 'shared', 'data', 'payments.json')
let cloneDir: string | undefined
function resolveSourceDir(): string {
const candidates = [process.env.TABLER_PAYMENTS_DIR, join(repoRoot, '..', 'tabler-payments')].filter((dir): dir is string => Boolean(dir))
for (const dir of candidates) {
if (existsSync(join(dir, 'src', 'light'))) return dir
}
cloneDir = mkdtempSync(join(tmpdir(), 'tabler-payments-'))
console.log('No local checkout found, cloning tabler/tabler-payments…')
execFileSync('git', ['clone', '--depth', '1', 'https://github.com/tabler/tabler-payments.git', cloneDir], { stdio: 'inherit' })
return cloneDir
}
// Sorted by file name, so 'amazon-pay' comes before 'amazon' — as in an `ls`.
const svgNames = (dir: string) =>
readdirSync(dir)
.filter((file) => file.endsWith('.svg'))
.sort()
.map((file) => file.slice(0, -'.svg'.length))
try {
const sourceDir = resolveSourceDir()
const lightDir = join(sourceDir, 'src', 'light')
const darkDir = join(sourceDir, 'src', 'dark')
const metaFile = join(sourceDir, 'payments.json')
for (const path of [lightDir, darkDir, metaFile]) {
if (!existsSync(path)) throw new Error(`import-payments: missing ${path} — not a tabler-payments checkout?`)
}
const providers = svgNames(lightDir)
const darkProviders = svgNames(darkDir)
if (providers.join() !== darkProviders.join()) {
const light = new Set(providers)
const dark = new Set(darkProviders)
const onlyLight = providers.filter((name) => !dark.has(name))
const onlyDark = darkProviders.filter((name) => !light.has(name))
throw new Error(`import-payments: light/dark sets differ (only light: ${onlyLight.join(', ') || '—'}; only dark: ${onlyDark.join(', ') || '—'})`)
}
const previous = existsSync(imgDir) ? new Set(svgNames(imgDir).map((name) => name.replace(/-dark$/, ''))) : new Set<string>()
rmSync(imgDir, { recursive: true, force: true })
mkdirSync(imgDir, { recursive: true })
for (const name of providers) {
copyFileSync(join(lightDir, `${name}.svg`), join(imgDir, `${name}.svg`))
copyFileSync(join(darkDir, `${name}.svg`), join(imgDir, `${name}-dark.svg`))
}
optimizeSvgDir(imgDir)
const scss = readFileSync(scssFile, 'utf8')
const listPattern = /(\$payment-providers: \(\n)[\s\S]*?(\n\);)/
if (!listPattern.test(scss)) throw new Error(`import-payments: $payment-providers list not found in ${scssFile}`)
const listBody = providers.map((name) => ` '${name}'`).join(',\n')
writeFileSync(scssFile, scss.replace(listPattern, `$1${listBody}$2`))
const meta = JSON.parse(readFileSync(metaFile, 'utf8')) as { name: string; logo: string }[]
const names = new Map(meta.map((entry) => [entry.logo, entry.name]))
for (const logo of names.keys()) {
if (!providers.includes(logo)) console.warn(`import-payments: payments.json entry '${logo}' has no SVG — skipped`)
}
const data = providers.map((logo) => {
const name = names.get(logo)
if (!name) console.warn(`import-payments: no payments.json metadata for '${logo}' — using the slug as name`)
return { name: name ?? logo, logo }
})
writeFileSync(dataFile, `${JSON.stringify(data, null, 2)}\n`)
const added = providers.filter((name) => !previous.has(name))
const removed = [...previous].filter((name) => !providers.includes(name))
console.log(`Imported ${providers.length} payment providers from ${relative(repoRoot, sourceDir)} (${added.length} added, ${removed.length} removed)`)
if (added.length) console.log(` added: ${added.join(', ')}`)
if (removed.length) console.log(` removed: ${removed.join(', ')}`)
console.log('Now run `pnpm run generate:tokens` to refresh shared/lib/tokens.ts')
} finally {
if (cloneDir) rmSync(cloneDir, { recursive: true, force: true })
}