From 29c902138fc837986770d599a3acbf1567bfc391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cahid=20Arda=20=C3=96z?= Date: Wed, 9 Oct 2024 18:12:39 +0300 Subject: [PATCH] Replace throw on missing env with warning (#1311) * fix: replace throw on missing env with warning * fix: check url/token only if they exist * fix: only replace if baseUrl exists * fix: rm throw from client because of vercel pre-rendering, the error was thrown when turbo was used * fix: rm platform tests --- pkg/error.ts | 2 +- pkg/http.ts | 14 ++++++++++++-- platforms/cloudflare.ts | 34 +++++++++++++++++++--------------- platforms/fastly.ts | 25 +++++++++++++++---------- platforms/nodejs.ts | 39 ++++++++++++++++++++++----------------- 5 files changed, 69 insertions(+), 45 deletions(-) diff --git a/pkg/error.ts b/pkg/error.ts index 7e27c36d..02a0b9f9 100644 --- a/pkg/error.ts +++ b/pkg/error.ts @@ -11,7 +11,7 @@ export class UpstashError extends Error { export class UrlError extends Error { constructor(url: string) { super( - `Upstash Redis client was passed an invalid URL. You should pass the URL together with https. Received: "${url}". ` + `Upstash Redis client was passed an invalid URL. You should pass a URL starting with https. Received: "${url}". ` ); this.name = "UrlError"; } diff --git a/pkg/http.ts b/pkg/http.ts index 72c6e319..e01075ee 100644 --- a/pkg/http.ts +++ b/pkg/http.ts @@ -127,6 +127,7 @@ export class HttpClient implements Requester { }; public readYourWrites: boolean; public upstashSyncToken = ""; + private hasCredentials: boolean; public readonly retry: { attempts: number; @@ -145,7 +146,7 @@ export class HttpClient implements Requester { this.upstashSyncToken = ""; this.readYourWrites = config.readYourWrites ?? true; - this.baseUrl = config.baseUrl.replace(/\/$/, ""); + this.baseUrl = (config.baseUrl || "").replace(/\/$/, ""); /** * regex to check if the baseUrl starts with http:// or https:// @@ -157,7 +158,7 @@ export class HttpClient implements Requester { * - `$` asserts the position at the end of the string. */ const urlRegex = /^https?:\/\/[^\s#$./?].\S*$/; - if (!urlRegex.test(this.baseUrl)) { + if (this.baseUrl && !urlRegex.test(this.baseUrl)) { throw new UrlError(this.baseUrl); } @@ -167,6 +168,8 @@ export class HttpClient implements Requester { ...config.headers, }; + this.hasCredentials = Boolean(this.baseUrl && this.headers.authorization.split(" ")[1]); + if (this.options.responseEncoding === "base64") { this.headers["Upstash-Encoding"] = "base64"; } @@ -206,6 +209,13 @@ export class HttpClient implements Requester { backend: this.options.backend, }; + if (!this.hasCredentials) { + console.warn( + "[Upstash Redis] Redis client was initialized without url or token." + + " Failed to execute command." + ); + } + /** * We've recieved a new `upstash-sync-token` in the previous response. We use it in the next request to observe the effects of previous requests. */ diff --git a/platforms/cloudflare.ts b/platforms/cloudflare.ts index 9a705c14..c62e4920 100644 --- a/platforms/cloudflare.ts +++ b/platforms/cloudflare.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ import type { RequesterConfig } from "../pkg/http"; import { HttpClient } from "../pkg/http"; import * as core from "../pkg/redis"; @@ -56,27 +55,32 @@ export class Redis extends core.Redis { */ constructor(config: RedisConfigCloudflare, env?: Env) { if (!config.url) { - throw new Error( + console.warn( `[Upstash Redis] The 'url' property is missing or undefined in your Redis config.` ); + } else if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) { + console.warn( + "[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!" + ); } if (!config.token) { - throw new Error( + console.warn( `[Upstash Redis] The 'token' property is missing or undefined in your Redis config.` ); - } - - if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) { - console.warn("The redis url contains whitespace or newline, which can cause errors!"); - } - if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) { - console.warn("The redis token contains whitespace or newline, which can cause errors!"); + } else if ( + config.token.startsWith(" ") || + config.token.endsWith(" ") || + /\r|\n/.test(config.token!) + ) { + console.warn( + "[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!" + ); } const client = new HttpClient({ retry: config.retry, - baseUrl: config.url, + baseUrl: config.url!, headers: { authorization: `Bearer ${config.token}` }, responseEncoding: config.responseEncoding, signal: config.signal, @@ -127,13 +131,13 @@ export class Redis extends core.Redis { const token = env?.UPSTASH_REDIS_REST_TOKEN ?? UPSTASH_REDIS_REST_TOKEN; if (!url) { - throw new Error( - "Unable to find environment variable: `UPSTASH_REDIS_REST_URL`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_URL`" + console.warn( + "[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_URL`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_URL`" ); } if (!token) { - throw new Error( - "Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_TOKEN`" + console.warn( + "[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`. Please add it via `wrangler secret put UPSTASH_REDIS_REST_TOKEN`" ); } return new Redis({ ...opts, url, token }, env); diff --git a/platforms/fastly.ts b/platforms/fastly.ts index 4ca91384..59435174 100644 --- a/platforms/fastly.ts +++ b/platforms/fastly.ts @@ -53,26 +53,31 @@ export class Redis extends core.Redis { */ constructor(config: RedisConfigFastly) { if (!config.url) { - throw new Error( + console.warn( `[Upstash Redis] The 'url' property is missing or undefined in your Redis config.` ); + } else if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) { + console.warn( + "[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!" + ); } if (!config.token) { - throw new Error( + console.warn( `[Upstash Redis] The 'token' property is missing or undefined in your Redis config.` ); - } - - if (config.url.startsWith(" ") || config.url.endsWith(" ") || /\r|\n/.test(config.url)) { - console.warn("The redis url contains whitespace or newline, which can cause errors!"); - } - if (config.token.startsWith(" ") || config.token.endsWith(" ") || /\r|\n/.test(config.token)) { - console.warn("The redis token contains whitespace or newline, which can cause errors!"); + } else if ( + config.token.startsWith(" ") || + config.token.endsWith(" ") || + /\r|\n/.test(config.token) + ) { + console.warn( + "[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!" + ); } const client = new HttpClient({ - baseUrl: config.url, + baseUrl: config.url!, retry: config.retry, headers: { authorization: `Bearer ${config.token}` }, options: { backend: config.backend }, diff --git a/platforms/nodejs.ts b/platforms/nodejs.ts index f86b88af..7099be10 100644 --- a/platforms/nodejs.ts +++ b/platforms/nodejs.ts @@ -102,34 +102,35 @@ export class Redis extends core.Redis { } if (!configOrRequester.url) { - throw new Error( + console.warn( `[Upstash Redis] The 'url' property is missing or undefined in your Redis config.` ); - } - - if (!configOrRequester.token) { - throw new Error( - `[Upstash Redis] The 'token' property is missing or undefined in your Redis config.` - ); - } - - if ( + } else if ( configOrRequester.url.startsWith(" ") || configOrRequester.url.endsWith(" ") || /\r|\n/.test(configOrRequester.url) ) { - console.warn("The redis url contains whitespace or newline, which can cause errors!"); + console.warn( + "[Upstash Redis] The redis url contains whitespace or newline, which can cause errors!" + ); } - if ( + + if (!configOrRequester.token) { + console.warn( + `[Upstash Redis] The 'token' property is missing or undefined in your Redis config.` + ); + } else if ( configOrRequester.token.startsWith(" ") || configOrRequester.token.endsWith(" ") || /\r|\n/.test(configOrRequester.token) ) { - console.warn("The redis token contains whitespace or newline, which can cause errors!"); + console.warn( + "[Upstash Redis] The redis token contains whitespace or newline, which can cause errors!" + ); } const client = new HttpClient({ - baseUrl: configOrRequester.url, + baseUrl: configOrRequester.url!, retry: configOrRequester.retry, headers: { authorization: `Bearer ${configOrRequester.token}` }, @@ -175,18 +176,22 @@ export class Redis extends core.Redis { if (process.env === undefined) { throw new TypeError( - 'Unable to get environment variables, `process.env` is undefined. If you are deploying to cloudflare, please import from "@upstash/redis/cloudflare" instead' + '[Upstash Redis] Unable to get environment variables, `process.env` is undefined. If you are deploying to cloudflare, please import from "@upstash/redis/cloudflare" instead' ); } + // @ts-ignore process will be defined in node const url = process.env.UPSTASH_REDIS_REST_URL || process.env.KV_REST_API_URL; if (!url) { - throw new Error("Unable to find environment variable: `UPSTASH_REDIS_REST_URL`"); + console.warn("[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_URL`"); } + // @ts-ignore process will be defined in node const token = process.env.UPSTASH_REDIS_REST_TOKEN || process.env.KV_REST_API_TOKEN; if (!token) { - throw new Error("Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`"); + console.warn( + "[Upstash Redis] Unable to find environment variable: `UPSTASH_REDIS_REST_TOKEN`" + ); } return new Redis({ ...config, url, token }); }