diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/export_store.js | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/scripts/export_store.js b/scripts/export_store.js new file mode 100644 index 0000000..d69ac29 --- /dev/null +++ b/scripts/export_store.js @@ -0,0 +1,53 @@ +#!/usr/bin/env node +// Writes the store catalogue to web/src/data/store.json. +// +// The store reads its catalogue from the server. With no server the page +// rendered its heading over an empty shop, which looks like a fault rather +// than a feature that needs signing in. This file is the same fallback the +// text packs already use: bundled with the client, served from the database +// and merged over the top once a server exists. +// +// Run it after changing prices or adding items: +// node scripts/export_store.js +// +// It shells out to psql so it needs no node dependencies, matching the rest +// of the scripts here. +const { execFileSync } = require('node:child_process'); +const { writeFileSync } = require('node:fs'); +const { join } = require('node:path'); + +const URL = process.env.DATABASE_URL + || 'postgresql://typerpunk:typerpunk@localhost/typerpunk'; + +function query(sql) { + const out = execFileSync('psql', [URL, '-At', '-c', sql], { encoding: 'utf8' }); + return JSON.parse(out.trim() || '[]'); +} + +const cosmetics = query(` + SELECT COALESCE(json_agg(row_to_json(c) ORDER BY c.category, c.price_cents), '[]'::json) + FROM (SELECT id, name, category, price_cents, value FROM cosmetics) c`); + +const bundles = query(` + SELECT COALESCE(json_agg(b ORDER BY b.sort_order), '[]'::json) FROM ( + SELECT b.id, b.name, b.description, b.price_cents, b.sort_order, + COALESCE(SUM(c.price_cents), 0)::int AS full_price_cents, + COALESCE(ARRAY_AGG(c.id ORDER BY c.id) + FILTER (WHERE c.id IS NOT NULL), '{}') AS items + FROM bundles b + LEFT JOIN bundle_items bi ON bi.bundle_id = b.id + LEFT JOIN cosmetics c ON c.id = bi.cosmetic_id + GROUP BY b.id, b.name, b.description, b.price_cents, b.sort_order + ) b`); + +const merch = query(` + SELECT COALESCE(json_agg(m ORDER BY m.sort_order), '[]'::json) FROM ( + SELECT id, name, description, price_cents, shipping_cents, kind, variants, sort_order + FROM merch WHERE available + ) m`); + +for (const row of [...bundles, ...merch]) delete row.sort_order; + +const out = join(__dirname, '..', 'web', 'src', 'data', 'store.json'); +writeFileSync(out, JSON.stringify({ cosmetics, bundles, merch }, null, 2) + '\n'); +console.log(`Wrote ${cosmetics.length} cosmetics, ${bundles.length} bundles and ${merch.length} merch items to ${out}`); |