Researched the options first. PriceCharting is the standard for retro prices
but requires a paid subscription for both its API and its bulk download.
eBay's sold-price data sits behind the Marketplace Insights API, which is a
limited release closed to new developers. The free game-price APIs cover
current digital storefronts, not physical retro copies. So there is no free
route to sold prices, and this uses eBay Browse — active listings, which are
asking prices, labelled as such rather than presented as valuations.
Schema now holds three prices per game (loose, CIB, new), with marketValue
as whichever tier matches that copy's condition. Changing a condition
re-prices from the stored tiers with no further lookup, and the dashboard
can later show both actual value and what a collection would be worth
complete.
The judgement lives in classification and aggregation, both pure and both
tested without credentials:
* listings are sorted into tiers from their titles, and accessories,
reproductions and multi-game lots are discarded — a "box only" listing
at $45 counted as a copy would halve the loose estimate for a $130 cart
* the discard qualifier is required. The first version matched a bare
"box", which threw out "complete in box" and "with box and manual",
i.e. most of the CIB tier, while keeping exactly the listings the
filter existed to remove. A test asserting on tiers rather than counts
caught it.
* median with an interquartile trim, since one optimist asking 50x moves
a mean and not a median
* sample counts travel with the estimate, because a tier drawn from two
listings warrants less confidence than one drawn from thirty
Credentials are optional: with none set, /api/prices/status reports
configured=false and refresh answers 503 with instructions, while the rest
of the app is unaffected.
101 backend tests.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
54 lines
2.2 KiB
Bash
54 lines
2.2 KiB
Bash
# Copy to .env and fill in. .env is gitignored — never commit real secrets.
|
|
#
|
|
# The 2018 version of this project committed its live database password to the
|
|
# repository, which is why it now has to be treated as compromised. Keep secrets
|
|
# in .env, and keep .env out of git.
|
|
|
|
# --- Required --------------------------------------------------------------
|
|
# JWT signing key. Minimum 32 characters; the API refuses to start without it.
|
|
# Generate one with: openssl rand -base64 48
|
|
JWT_KEY=
|
|
|
|
# --- First-run seeding ------------------------------------------------------
|
|
# On a database with no users, the API creates this account and imports the 105
|
|
# games recovered from the 2018 MySQL dump. Once a user exists, this is ignored.
|
|
# Password rules: 12+ chars, upper, lower and a digit.
|
|
SEED_USERNAME=ckoch
|
|
SEED_EMAIL=you@example.com
|
|
SEED_PASSWORD=
|
|
|
|
# Set to false once you are past first run, or to start with an empty library.
|
|
SEED_ENABLED=true
|
|
|
|
# --- Optional ---------------------------------------------------------------
|
|
# Host port the web UI is published on.
|
|
WEB_PORT=8080
|
|
|
|
# Token lifetime in minutes. Default is 12 hours; there is no refresh flow, so
|
|
# expiry returns you to the login form.
|
|
JWT_LIFETIME_MINUTES=720
|
|
|
|
JWT_ISSUER=LudosData
|
|
JWT_AUDIENCE=LudosData
|
|
CORS_ORIGIN=http://localhost:8080
|
|
|
|
# --- Market value (optional) ------------------------------------------------
|
|
# Prices come from eBay's Browse API, which needs a free developer account.
|
|
#
|
|
# 1. Register at https://developer.ebay.com and create a developer account
|
|
# 2. Create an application keyset (Application Keys -> Production)
|
|
# 3. Copy the App ID (Client ID) and Cert ID (Client Secret) below
|
|
#
|
|
# Leave these blank and the pricing endpoints report 503 with an explanation;
|
|
# nothing else is affected.
|
|
#
|
|
# IMPORTANT: Browse returns ACTIVE LISTINGS, which are asking prices, not
|
|
# completed sales. eBay's sold-price data lives behind the Marketplace Insights
|
|
# API, which is a limited release not open to new developers. Expect these
|
|
# figures to read high — they are an upper bound, not a valuation.
|
|
EBAY_CLIENT_ID=
|
|
EBAY_CLIENT_SECRET=
|
|
|
|
# Set true to use eBay's sandbox while checking credentials.
|
|
EBAY_USE_SANDBOX=false
|