feat: accept KV_REST_API_* env vars as Upstash fallback

Vercel Marketplace Upstash integration injects KV_REST_API_URL and
KV_REST_API_TOKEN — different names from vanilla Upstash signup
(UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN). Adapter and
migration script now accept either form, so the operator doesn't have
to duplicate values when sharing an Upstash DB provisioned via the
Vercel integration. UPSTASH_* takes precedence when both are set.
This commit is contained in:
tiennm99 committed 2026-05-09 20:17:06 +07:00
1 parent 771b5ebf8e
commit 987837c1d8
4 files changed
+24 -12

No files matched your search

+3 -1
View File
@@ -10,7 +10,9 @@ TELEGRAM_WEBHOOK_SECRET=
# Variable name kept as WORKER_URL for register-webhook.js compatibility.
WORKER_URL=https://store-scraper-bot.vercel.app/api/webhook
# Upstash Redis credentials — required by migrate-atlas-to-upstash.js
# Upstash Redis credentials — required by migrate-atlas-to-upstash.js.
# If the Vercel Marketplace Upstash integration is set up, the bot also
# accepts KV_REST_API_URL / KV_REST_API_TOKEN as fallbacks (see upstash.js).
UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=
KEY_PREFIX=store-scraper-bot:
+4 -1
View File
@@ -4,7 +4,10 @@ TELEGRAM_BOT_USERNAME=your_bot_username
TELEGRAM_WEBHOOK_SECRET=generate_a_random_string_at_least_32_chars
# Upstash Redis (REST API; same DB can be shared with other Vercel projects
# because KEY_PREFIX namespaces this bot's keys)
# because KEY_PREFIX namespaces this bot's keys).
# If the Vercel Marketplace Upstash integration is enabled, the project will
# already have KV_REST_API_URL and KV_REST_API_TOKEN — the adapter accepts
# those as fallbacks, so duplication is optional.
UPSTASH_REDIS_REST_URL=https://xxx.upstash.io
UPSTASH_REDIS_REST_TOKEN=your_upstash_rest_token
KEY_PREFIX=store-scraper-bot:
+6 -4
View File
@@ -45,12 +45,14 @@ async function main() {
const mongoUri = process.env.MONGODB_URI;
if (!mongoUri) exitWith('MONGODB_URI not set; check .env.deploy');
const upstashUrl = process.env.UPSTASH_REDIS_REST_URL;
const upstashToken = process.env.UPSTASH_REDIS_REST_TOKEN;
// Accept either Upstash naming convention (vanilla signup) or Vercel
// Marketplace integration names — same as the runtime adapter.
const upstashUrl = process.env.UPSTASH_REDIS_REST_URL ?? process.env.KV_REST_API_URL;
const upstashToken = process.env.UPSTASH_REDIS_REST_TOKEN ?? process.env.KV_REST_API_TOKEN;
const dryRun = process.argv.includes('--dry-run');
if (!dryRun) {
if (!upstashUrl) exitWith('UPSTASH_REDIS_REST_URL not set; check .env.deploy');
if (!upstashToken) exitWith('UPSTASH_REDIS_REST_TOKEN not set; check .env.deploy');
if (!upstashUrl) exitWith('UPSTASH_REDIS_REST_URL (or KV_REST_API_URL) not set; check .env.deploy');
if (!upstashToken) exitWith('UPSTASH_REDIS_REST_TOKEN (or KV_REST_API_TOKEN) not set; check .env.deploy');
}
const includeCache = process.argv.includes('--include-cache');
+11 -6
View File
@@ -29,13 +29,18 @@ export class UpstashUnavailable extends Error {
// Build a handle bundling the Redis client and the key prefix together.
// The handle is what callers pass into getJson/putJson/del/scan — it stays
// opaque so repositories never need to know about prefixing themselves.
//
// Accepts both env var naming conventions:
// - UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN (vanilla Upstash signup)
// - KV_REST_API_URL / KV_REST_API_TOKEN (Vercel Marketplace integration)
// so the operator doesn't have to duplicate vars when the bot shares an
// Upstash DB provisioned via Vercel.
export function createUpstashClient(env) {
if (!env?.UPSTASH_REDIS_REST_URL) throw new UpstashUnavailable('UPSTASH_REDIS_REST_URL');
if (!env?.UPSTASH_REDIS_REST_TOKEN) throw new UpstashUnavailable('UPSTASH_REDIS_REST_TOKEN');
const client = new Redis({
url: env.UPSTASH_REDIS_REST_URL,
token: env.UPSTASH_REDIS_REST_TOKEN,
});
const url = env?.UPSTASH_REDIS_REST_URL ?? env?.KV_REST_API_URL;
const token = env?.UPSTASH_REDIS_REST_TOKEN ?? env?.KV_REST_API_TOKEN;
if (!url) throw new UpstashUnavailable('UPSTASH_REDIS_REST_URL or KV_REST_API_URL');
if (!token) throw new UpstashUnavailable('UPSTASH_REDIS_REST_TOKEN or KV_REST_API_TOKEN');
const client = new Redis({ url, token });
const prefix = env.KEY_PREFIX ?? DEFAULT_KEY_PREFIX;
return { client, prefix };
}