From ca3bb39066e9dd541ea61b245e31ba01add32944 Mon Sep 17 00:00:00 2001 From: Enes Akar Date: Mon, 30 May 2022 09:36:33 -0700 Subject: [PATCH 01/12] fix broken links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d68af68..99f07683 100644 --- a/README.md +++ b/README.md @@ -130,8 +130,8 @@ export default { } ``` -- [Code example service worker](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-workers) -- [Code example module worker](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-workers-modules) +- [Code example Wrangler 2](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-worker-wrangler2) +- [Code example Wrangler 1](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-worker) - [Documentation](https://docs.upstash.com/redis/tutorials/cloudflare_workers_with_redis) #### Fastly From 4eed96c11fa40ace156161709bb8dd2dd47c62e8 Mon Sep 17 00:00:00 2001 From: Enes Akar Date: Mon, 30 May 2022 16:51:22 -0700 Subject: [PATCH 02/12] Update README.md --- README.md | 314 ------------------------------------------------------ 1 file changed, 314 deletions(-) diff --git a/README.md b/README.md index 99f07683..4ea7ffa2 100644 --- a/README.md +++ b/README.md @@ -23,320 +23,6 @@ See [the list of APIs](https://docs.upstash.com/features/restapi#rest---redis-api-compatibility) supported. -## Upgrading to v1.4.0 **(ReferenceError: fetch is not defined)** - -If you are running on nodejs v17 and earlier, `fetch` will not be natively -supported. Platforms like Vercel, Netlify, Deno, Fastly etc. provide a polyfill -for you. But if you are running on bare node, you need to either specify a -polyfill yourself or change the import path to: - -```typescript -import { Redis } from "@upstash/redis/with-fetch"; -``` - -## Upgrading from v0.2.0? - -Please read the -[migration guide](https://github.com/upstash/upstash-redis#migrating-to-v1). For -further explanation we wrote a -[blog post](https://blog.upstash.com/upstash-redis-sdk-v1). - -## Quick Start - -### Install - -#### npm - -```bash -npm install @upstash/redis -``` - -#### Deno - -```ts -import { Redis } from "https://deno.land/x/upstash_redis/mod.ts"; -``` - -### Create database - -Create a new redis database on [upstash](https://console.upstash.com/) - -### Environments - -We support various platforms, such as nodejs, cloudflare and fastly. Platforms -differ slightly when it comes to environment variables and their `fetch` api. -Please use the correct import when deploying to special platforms. - -#### Node.js - -Examples: Vercel, Netlify, AWS Lambda - -If you are running on nodejs you can set `UPSTASH_REDIS_REST_URL` and -`UPSTASH_REDIS_REST_TOKEN` as environment variable and create a redis instance -like this: - -```ts -import { Redis } from "@upstash/redis" - -const redis = new Redis({ - url: , - token: , -}) - -// or load directly from env -const redis = Redis.fromEnv() -``` - -If you are running on nodejs v17 and earlier, `fetch` will not be natively -supported. Platforms like Vercel, Netlify, Deno, Fastly etc. provide a polyfill -for you. But if you are running on bare node, you need to either specify a -polyfill yourself or change the import path to: - -```typescript -import { Redis } from "@upstash/redis/with-fetch"; -``` - -- [Code example](https://github.com/upstash/upstash-redis/blob/main/examples/nodejs) - -#### Cloudflare Workers - -Cloudflare handles environment variables differently than nodejs. Please add -`UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` using -`wrangler secret put ...` or in the cloudflare dashboard. - -Afterwards you can create a redis instance: - -```ts -import { Redis } from "@upstash/redis/cloudflare" - -const redis = new Redis({ - url: , - token: , -}) - - -// or load directly from global env - -// service worker -const redis = Redis.fromEnv() - - -// module worker -export default { - async fetch(request: Request, env: Bindings) { - const redis = Redis.fromEnv(env) - // ... - } -} -``` - -- [Code example Wrangler 2](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-worker-wrangler2) -- [Code example Wrangler 1](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-worker) -- [Documentation](https://docs.upstash.com/redis/tutorials/cloudflare_workers_with_redis) - -#### Fastly - -Fastly introduces a concept called -[backend](https://developer.fastly.com/reference/api/services/backend/). You -need to configure a backend in your `fastly.toml`. An example can be found -[here](https://github.com/upstash/upstash-redis/blob/main/examples/fastly/fastly.toml). -Until the fastly api stabilizes we recommend creating an instance manually: - -```ts -import { Redis } from "@upstash/redis/fastly" - -const redis = new Redis({ - url: , - token: , - backend: , -}) -``` - -- [Code example](https://github.com/upstash/upstash-redis/tree/main/examples/fastly) -- [Documentation](https://blog.upstash.com/fastly-compute-edge-with-redi) - -#### Deno - -Examples: [Deno Deploy](https://deno.com/deploy), -[Netlify Edge](https://www.netlify.com/products/edge/) - -```ts -import { Redis } from "https://deno.land/x/upstash_redis/mod.ts" - -const redis = new Redis({ - url: , - token: , -}) - -// or -const redis = Redis.fromEnv(); -``` - -### Working with types - -Most commands allow you to provide a type to make working with typescript -easier. - -```ts -const data = await redis.get("key"); -// data is typed as `MyCustomType` -``` - -## Migrating to v1 - -### Explicit authentication - -The library is no longer automatically trying to load connection secrets from -environment variables. You must either supply them yourself: - -```ts -import { Redis } from "@upstash/redis" - -const redis = new Redis({ - url: , - token: , -}) -``` - -Or use one of the static constructors to load from environment variables: - -```ts -// Nodejs -import { Redis } from "@upstash/redis"; -const redis = Redis.fromEnv(); -``` - -```ts -// or when deploying to cloudflare workers -import { Redis } from "@upstash/redis/cloudflare"; -const redis = Redis.fromEnv(); -``` - -### Error handling - -Errors are now thrown automatically instead of being returned to you. - -```ts -// old -const { data, error } = await set("key", "value"); -if (error) { - throw new Error(error); -} - -// new -const data = await redis.set("key", "value"); // error is thrown automatically -``` - -## Pipeline - -`v1.0.0` introduces redis pipelines. Pipelining commands allows you to send a -single http request with multiple commands. - -```ts -import { Redis } from "@upstash/redis"; - -const redis = new Redis({ - /* auth */ -}); - -const p = redis.pipeline(); - -// Now you can chain multiple commands to create your pipeline: - -p.set("key", 2); -p.incr("key"); - -// or inline: -p.hset("key2", "field", { hello: "world" }).hvals("key2"); - -// Execute the pipeline once you are done building it: -// `exec` returns an array where each element represents the response of a command in the pipeline. -// You can optionally provide a type like this to get a typed response. -const res = await p.exec<[Type1, Type2, Type3]>(); -``` - -For more information about pipelines using REST see -[here](https://blog.upstash.com/pipeline). - -### Advanced - -A low level `Command` class can be imported from `@upstash/redis` in case you -need more control about types and or (de)serialization. - -By default all objects you are storing in redis are serialized using -`JSON.stringify` and recursively deserialized as well. Here's an example how you -could customize that behaviour. Keep in mind that you need to provide a `fetch` -polyfill if you are running on nodejs. We recommend -[isomorphic-fetch](https://www.npmjs.com/package/isomorphic-fetch). - -```ts -import { Command } from "@upstash/redis/commands" -import { HttpClient } from "@upstash/redis/http" - -/** - * TData represents what the user will enter or receive, - * TResult is the raw data returned from upstash, which may need to be - * transformed or parsed. - */ -const deserialize: (raw: TResult) => TData = ... - -class CustomGetCommand extends Command { - constructor(key: string, ) { - super(["get", key], { deserialize }) - } -} - -const client = new HttpClient({ - baseUrl: , - headers: { - authorization: `Bearer ${}`, - }, -}) - -const res = new CustomGetCommand("key").exec(client) -``` - -### Additional information - -#### `keepalive` - -`@upstash/redis` is capable of reusing connections where possible to minimize -latency. Connections can be reused if the client is stored in memory and not -initialized with every new function invocation. The easiest way to achieve this -is by creating the client outside of your handler and adding an https agent: - -```ts -// Nextjs api route -import { Redis } from "@upstash/redis"; -import https from "https"; - -const redis = Redis.fromEnv({ - agent: new https.Agent({ keepAlive: true }), -}); - -export default async function (req, res) { - // use redis here -} -``` - -Whenever your hot lambda receives a new request the client is already -initialized and the previously established connection to upstash is reused. - -#### Javascript MAX_SAFE_INTEGER - -Javascript can not handle numbers larger than `2^53 -1` safely and would return -wrong results when trying to deserialize them. In these cases the default -deserializer will return them as string instead. This might cause a mismatch -with your custom types. - -```ts -await redis.set("key", "101600000000150081467"); -const res = await redis("get"); -``` - -In this example `res` will still be a string despite the type annotation. Please -keep that in mind and adjust accordingly. - ## Docs See [the documentation](https://docs.upstash.com/features/javascriptsdk) for From f22e6e36cff6e3ebcc4afaae1ab85ff356d657d7 Mon Sep 17 00:00:00 2001 From: Enes Akar Date: Mon, 30 May 2022 16:52:07 -0700 Subject: [PATCH 03/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ea7ffa2..0bb2b486 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ supported. ## Docs -See [the documentation](https://docs.upstash.com/features/javascriptsdk) for +See [the documentation](https://docs.upstash.com/features/javascriptsdk/getstarted) for details. ## Contributing From 7f854e8df7d531f65e3a69ee22bf9baa8afd2fb8 Mon Sep 17 00:00:00 2001 From: Enes Akar Date: Mon, 30 May 2022 16:52:57 -0700 Subject: [PATCH 04/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bb2b486..0eac42f7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ supported. ## Docs -See [the documentation](https://docs.upstash.com/features/javascriptsdk/getstarted) for +See [the documentation](https://docs.upstash.com/redis/sdks/javascriptsdk/getstarted) for details. ## Contributing From 3733663a2284d48154552862c3d07187e73ad770 Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 07:04:08 +0200 Subject: [PATCH 05/12] style: fmt --- examples/nodejs/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/nodejs/index.js b/examples/nodejs/index.js index 2d5c92f1..d5e0bce7 100644 --- a/examples/nodejs/index.js +++ b/examples/nodejs/index.js @@ -1,6 +1,13 @@ import { Redis } from "@upstash/redis/with-fetch"; -const redis = Redis.fromEnv(); +const redis = new Redis({ + url: "", + token: "", + retry: { + maxRetries: 5, + backoff: (retryCoount) => Math.exp(retryCoount) * 50, + }, +}); async function run() { const key = "key"; const value = { hello: "world" }; From ce4c3b7528693e2e249a411fc581927dbcc7b4f8 Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 07:05:35 +0200 Subject: [PATCH 06/12] style: fmt --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0eac42f7..7911c899 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,9 @@ supported. ## Docs -See [the documentation](https://docs.upstash.com/redis/sdks/javascriptsdk/getstarted) for -details. +See +[the documentation](https://docs.upstash.com/redis/sdks/javascriptsdk/getstarted) +for details. ## Contributing From 9a46dc89f795e6e889e909bfa56c4c6208d83959 Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 07:10:58 +0200 Subject: [PATCH 07/12] chore: rename cloudflare examples --- .github/workflows/tests.yaml | 38 +++++++++---------- .../.gitignore | 0 .../README.md | 2 +- .../bindings.d.ts | 0 .../build.js | 0 .../package.json | 0 .../src/index.ts | 0 .../test.ts | 0 .../tsconfig.json | 0 .../wrangler.toml | 2 +- .../README.md | 0 .../index.js | 0 .../package.json | 2 +- .../test.ts | 0 .../wrangler.toml | 2 +- 15 files changed, 23 insertions(+), 23 deletions(-) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/.gitignore (100%) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/README.md (95%) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/bindings.d.ts (100%) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/build.js (100%) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/package.json (100%) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/src/index.ts (100%) rename examples/{cloudflare-worker-wrangler2 => cloudflare-workers-with-wrangler-1}/test.ts (100%) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/tsconfig.json (100%) rename examples/{cloudflare-worker => cloudflare-workers-with-wrangler-1}/wrangler.toml (90%) rename examples/{cloudflare-worker-wrangler2 => cloudflare-workers}/README.md (100%) rename examples/{cloudflare-worker-wrangler2 => cloudflare-workers}/index.js (100%) rename examples/{cloudflare-worker-wrangler2 => cloudflare-workers}/package.json (91%) rename examples/{cloudflare-worker => cloudflare-workers}/test.ts (100%) rename examples/{cloudflare-worker-wrangler2 => cloudflare-workers}/wrangler.toml (83%) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d50a22cb..7cde324e 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -233,7 +233,7 @@ jobs: - name: Test run: deno test --allow-net --allow-env ./examples/nextjs_edge/test.ts - cloudflare-worker-local: + cloudflare-workers-with-wrangler-1-local: environment: local needs: - test @@ -268,11 +268,11 @@ jobs: run: | pnpm add @upstash/redis@../../dist pnpm install -g miniflare @cloudflare/wrangler - working-directory: examples/cloudflare-worker + working-directory: examples/cloudflare-workers-with-wrangler-1 - name: Start example run: miniflare -b UPSTASH_REDIS_REST_URL=http://127.0.0.1:6379 -b UPSTASH_REDIS_REST_TOKEN=${{ secrets.UPSTASH_AUTH_TOKEN }} & - working-directory: examples/cloudflare-worker + working-directory: examples/cloudflare-workers-with-wrangler-1 - run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8787)" != "200" ]]; do sleep 1; done timeout-minutes: 2 @@ -282,7 +282,7 @@ jobs: env: DEPLOYMENT_URL: http://localhost:8787 - cloudflare-worker-deployed: + cloudflare-workers-with-wrangler-1-deployed: environment: deployed needs: - release @@ -306,11 +306,11 @@ jobs: run: | pnpm add @upstash/redis@${{needs.release.outputs.version}} pnpm install -g @cloudflare/wrangler - working-directory: examples/cloudflare-worker + working-directory: examples/cloudflare-workers-with-wrangler-1 - name: Deploy run: wrangler publish - working-directory: examples/cloudflare-worker + working-directory: examples/cloudflare-workers-with-wrangler-1 env: CF_API_TOKEN: ${{secrets.CF_API_TOKEN}} @@ -321,7 +321,7 @@ jobs: - cloudflare-worker-wrangler2-local: + cloudflare-workers-local: environment: local needs: - test @@ -354,15 +354,15 @@ jobs: - name: Install example run: pnpm add @upstash/redis@../../dist - working-directory: examples/cloudflare-worker-wrangler2 + working-directory: examples/cloudflare-workers - name: Add account ID run: echo 'account_id = "${{ secrets.CLOUDFLARE_ACCOUNT_ID }}"' >> wrangler.toml - working-directory: examples/cloudflare-worker-wrangler2 + working-directory: examples/cloudflare-workers - name: Start example run: pnpm dev & - working-directory: examples/cloudflare-worker-wrangler2 + working-directory: examples/cloudflare-workers env: CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} @@ -370,11 +370,11 @@ jobs: timeout-minutes: 2 - name: Test - run: deno test -A ./examples/cloudflare-worker-wrangler2/test.ts + run: deno test -A ./examples/cloudflare-workers/test.ts env: DEPLOYMENT_URL: http://localhost:8787 - cloudflare-worker-wrangler2-deployed: + cloudflare-workers-deployed: environment: deployed needs: - release @@ -398,22 +398,22 @@ jobs: - name: Install example run: | pnpm add @upstash/redis@${{needs.release.outputs.version}} - working-directory: examples/cloudflare-worker-wrangler2 + working-directory: examples/cloudflare-workers - name: Add account ID run: echo 'account_id = "${{ secrets.CLOUDFLARE_ACCOUNT_ID }}"' >> wrangler.toml - working-directory: examples/cloudflare-worker-wrangler2 + working-directory: examples/cloudflare-workers - name: Deploy run: pnpm deploy - working-directory: examples/cloudflare-worker-wrangler2 + working-directory: examples/cloudflare-workers env: CLOUDFLARE_API_TOKEN: ${{secrets.CF_API_TOKEN}} - name: Test - run: deno test -A ./examples/cloudflare-worker-wrangler2/test.ts + run: deno test -A ./examples/cloudflare-workers/test.ts env: - DEPLOYMENT_URL: https://cloudflare-worker-wrangler2.upstash.workers.dev + DEPLOYMENT_URL: https://cloudflare-workers.upstash.workers.dev fastly-local: environment: local @@ -623,8 +623,8 @@ jobs: - fastly-local - nextjs-local - nextjs-edge-local - - cloudflare-worker-local - - cloudflare-worker-wrangler2-local + - cloudflare-workers-with-wrangler-1-local + - cloudflare-workers-local name: Release runs-on: ubuntu-latest diff --git a/examples/cloudflare-worker/.gitignore b/examples/cloudflare-workers-with-wrangler-1/.gitignore similarity index 100% rename from examples/cloudflare-worker/.gitignore rename to examples/cloudflare-workers-with-wrangler-1/.gitignore diff --git a/examples/cloudflare-worker/README.md b/examples/cloudflare-workers-with-wrangler-1/README.md similarity index 95% rename from examples/cloudflare-worker/README.md rename to examples/cloudflare-workers-with-wrangler-1/README.md index 1b6182c6..c3251bc3 100644 --- a/examples/cloudflare-worker/README.md +++ b/examples/cloudflare-workers-with-wrangler-1/README.md @@ -1,4 +1,4 @@ -# Cloudflare Worker Example +# Cloudflare Workers Example This example uses [Wrangler 1](https://developers.cloudflare.com/workers/wrangler/) to create a diff --git a/examples/cloudflare-worker/bindings.d.ts b/examples/cloudflare-workers-with-wrangler-1/bindings.d.ts similarity index 100% rename from examples/cloudflare-worker/bindings.d.ts rename to examples/cloudflare-workers-with-wrangler-1/bindings.d.ts diff --git a/examples/cloudflare-worker/build.js b/examples/cloudflare-workers-with-wrangler-1/build.js similarity index 100% rename from examples/cloudflare-worker/build.js rename to examples/cloudflare-workers-with-wrangler-1/build.js diff --git a/examples/cloudflare-worker/package.json b/examples/cloudflare-workers-with-wrangler-1/package.json similarity index 100% rename from examples/cloudflare-worker/package.json rename to examples/cloudflare-workers-with-wrangler-1/package.json diff --git a/examples/cloudflare-worker/src/index.ts b/examples/cloudflare-workers-with-wrangler-1/src/index.ts similarity index 100% rename from examples/cloudflare-worker/src/index.ts rename to examples/cloudflare-workers-with-wrangler-1/src/index.ts diff --git a/examples/cloudflare-worker-wrangler2/test.ts b/examples/cloudflare-workers-with-wrangler-1/test.ts similarity index 100% rename from examples/cloudflare-worker-wrangler2/test.ts rename to examples/cloudflare-workers-with-wrangler-1/test.ts diff --git a/examples/cloudflare-worker/tsconfig.json b/examples/cloudflare-workers-with-wrangler-1/tsconfig.json similarity index 100% rename from examples/cloudflare-worker/tsconfig.json rename to examples/cloudflare-workers-with-wrangler-1/tsconfig.json diff --git a/examples/cloudflare-worker/wrangler.toml b/examples/cloudflare-workers-with-wrangler-1/wrangler.toml similarity index 90% rename from examples/cloudflare-worker/wrangler.toml rename to examples/cloudflare-workers-with-wrangler-1/wrangler.toml index 60bb1ce1..a13e487e 100644 --- a/examples/cloudflare-worker/wrangler.toml +++ b/examples/cloudflare-workers-with-wrangler-1/wrangler.toml @@ -1,4 +1,4 @@ -name = "upstash-modules-worker" +name = "upstash-redis-with-wrangler-1" type = "javascript" workers_dev = true diff --git a/examples/cloudflare-worker-wrangler2/README.md b/examples/cloudflare-workers/README.md similarity index 100% rename from examples/cloudflare-worker-wrangler2/README.md rename to examples/cloudflare-workers/README.md diff --git a/examples/cloudflare-worker-wrangler2/index.js b/examples/cloudflare-workers/index.js similarity index 100% rename from examples/cloudflare-worker-wrangler2/index.js rename to examples/cloudflare-workers/index.js diff --git a/examples/cloudflare-worker-wrangler2/package.json b/examples/cloudflare-workers/package.json similarity index 91% rename from examples/cloudflare-worker-wrangler2/package.json rename to examples/cloudflare-workers/package.json index c87fee7c..c4c6a8e9 100644 --- a/examples/cloudflare-worker-wrangler2/package.json +++ b/examples/cloudflare-workers/package.json @@ -1,5 +1,5 @@ { - "name": "wrangler2", + "name": "cloudflare-workers", "version": "1.0.0", "description": "Example project using wrangler2", "author": "Andreas Thomas ", diff --git a/examples/cloudflare-worker/test.ts b/examples/cloudflare-workers/test.ts similarity index 100% rename from examples/cloudflare-worker/test.ts rename to examples/cloudflare-workers/test.ts diff --git a/examples/cloudflare-worker-wrangler2/wrangler.toml b/examples/cloudflare-workers/wrangler.toml similarity index 83% rename from examples/cloudflare-worker-wrangler2/wrangler.toml rename to examples/cloudflare-workers/wrangler.toml index 6d51a082..8020e229 100644 --- a/examples/cloudflare-worker-wrangler2/wrangler.toml +++ b/examples/cloudflare-workers/wrangler.toml @@ -1,4 +1,4 @@ -name = "cloudflare-worker-wrangler2" +name = "upstash-redis" main = "index.js" compatibility_date = "2022-05-27" From 771c40a271ceebb0f856802d2ce1353209178caf Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 07:44:10 +0200 Subject: [PATCH 08/12] ci: fix paths --- .github/workflows/tests.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index c47fc33d..fd90514d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -273,7 +273,8 @@ jobs: timeout-minutes: 2 - name: Test - run: deno test -A ./examples/cloudflare-worker/test.ts + run: deno test -A ./test.ts + working-directory: examples/cloudflare-workers-with-wrangler-1 env: DEPLOYMENT_URL: http://localhost:8787 @@ -309,7 +310,8 @@ jobs: CF_API_TOKEN: ${{secrets.CF_API_TOKEN}} - name: Test - run: deno test -A ./examples/cloudflare-worker/test.ts + run: deno test -A ./test.ts + working-directory: examples/cloudflare-workers-with-wrangler-1 env: DEPLOYMENT_URL: https://upstash-modules-worker.upstash.workers.dev @@ -363,7 +365,8 @@ jobs: timeout-minutes: 2 - name: Test - run: deno test -A ./examples/cloudflare-workers/test.ts + run: deno test -A ./test.ts + working-directory: examples/cloudflare-workers env: DEPLOYMENT_URL: http://localhost:8787 @@ -403,7 +406,8 @@ jobs: CLOUDFLARE_API_TOKEN: ${{secrets.CF_API_TOKEN}} - name: Test - run: deno test -A ./examples/cloudflare-workers/test.ts + run: deno test -A ./test.ts + working-directory: examples/cloudflare-workers env: DEPLOYMENT_URL: https://cloudflare-workers.upstash.workers.dev From e91c9bdf1e93b0ac9a3dc6caef4d76ca55a7d9f7 Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 08:01:41 +0200 Subject: [PATCH 09/12] revert: readme --- README.md | 323 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 318 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7911c899..d22f1783 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ It is the only connectionless (HTTP based) Redis client and designed for: - Serverless functions (AWS Lambda ...) - Cloudflare Workers (see - [the example](https://github.com/upstash/upstash-redis/tree/master/examples/cloudflare-workers)) + [the example](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-workers)) - Fastly Compute@Edge (see - [the example](https://github.com/upstash/upstash-redis/tree/master/examples/fastly)) + [the example](https://github.com/upstash/upstash-redis/tree/main/examples/fastly)) - Next.js, Jamstack ... - Client side web/mobile applications - WebAssembly @@ -23,11 +23,324 @@ See [the list of APIs](https://docs.upstash.com/features/restapi#rest---redis-api-compatibility) supported. +## Upgrading to v1.4.0 **(ReferenceError: fetch is not defined)** + +If you are running on nodejs v17 and earlier, `fetch` will not be natively +supported. Platforms like Vercel, Netlify, Deno, Fastly etc. provide a polyfill +for you. But if you are running on bare node, you need to either specify a +polyfill yourself or change the import path to: + +```typescript +import { Redis } from "@upstash/redis/with-fetch"; +``` + +## Upgrading from v0.2.0? + +Please read the +[migration guide](https://github.com/upstash/upstash-redis#migrating-to-v1). For +further explanation we wrote a +[blog post](https://blog.upstash.com/upstash-redis-sdk-v1). + +## Quick Start + +### Install + +#### npm + +```bash +npm install @upstash/redis +``` + +#### Deno + +```ts +import { Redis } from "https://deno.land/x/upstash_redis/mod.ts"; +``` + +### Create database + +Create a new redis database on [upstash](https://console.upstash.com/) + +### Environments + +We support various platforms, such as nodejs, cloudflare and fastly. Platforms +differ slightly when it comes to environment variables and their `fetch` api. +Please use the correct import when deploying to special platforms. + +#### Node.js + +Examples: Vercel, Netlify, AWS Lambda + +If you are running on nodejs you can set `UPSTASH_REDIS_REST_URL` and +`UPSTASH_REDIS_REST_TOKEN` as environment variable and create a redis instance +like this: + +```ts +import { Redis } from "@upstash/redis" + +const redis = new Redis({ + url: , + token: , +}) + +// or load directly from env +const redis = Redis.fromEnv() +``` + +If you are running on nodejs v17 and earlier, `fetch` will not be natively +supported. Platforms like Vercel, Netlify, Deno, Fastly etc. provide a polyfill +for you. But if you are running on bare node, you need to either specify a +polyfill yourself or change the import path to: + +```typescript +import { Redis } from "@upstash/redis/with-fetch"; +``` + +- [Code example](https://github.com/upstash/upstash-redis/blob/main/examples/nodejs) + +#### Cloudflare Workers + +Cloudflare handles environment variables differently than nodejs. Please add +`UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` using +`wrangler secret put ...` or in the cloudflare dashboard. + +Afterwards you can create a redis instance: + +```ts +import { Redis } from "@upstash/redis/cloudflare" + +const redis = new Redis({ + url: , + token: , +}) + + +// or load directly from global env + +// service worker +const redis = Redis.fromEnv() + + +// module worker +export default { + async fetch(request: Request, env: Bindings) { + const redis = Redis.fromEnv(env) + // ... + } +} +``` + +- [Code example Wrangler 2](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-workers) +- [Code example Wrangler 1](https://github.com/upstash/upstash-redis/tree/main/examples/cloudflare-workers-with-wrangler-1) +- [Documentation](https://docs.upstash.com/redis/tutorials/cloudflare_workers_with_redis) + +#### Fastly + +Fastly introduces a concept called +[backend](https://developer.fastly.com/reference/api/services/backend/). You +need to configure a backend in your `fastly.toml`. An example can be found +[here](https://github.com/upstash/upstash-redis/blob/main/examples/fastly/fastly.toml). +Until the fastly api stabilizes we recommend creating an instance manually: + +```ts +import { Redis } from "@upstash/redis/fastly" + +const redis = new Redis({ + url: , + token: , + backend: , +}) +``` + +- [Code example](https://github.com/upstash/upstash-redis/tree/main/examples/fastly) +- [Documentation](https://blog.upstash.com/fastly-compute-edge-with-redi) + +#### Deno + +Examples: [Deno Deploy](https://deno.com/deploy), +[Netlify Edge](https://www.netlify.com/products/edge/) + +```ts +import { Redis } from "https://deno.land/x/upstash_redis/mod.ts" + +const redis = new Redis({ + url: , + token: , +}) + +// or +const redis = Redis.fromEnv(); +``` + +### Working with types + +Most commands allow you to provide a type to make working with typescript +easier. + +```ts +const data = await redis.get("key"); +// data is typed as `MyCustomType` +``` + +## Migrating to v1 + +### Explicit authentication + +The library is no longer automatically trying to load connection secrets from +environment variables. You must either supply them yourself: + +```ts +import { Redis } from "@upstash/redis" + +const redis = new Redis({ + url: , + token: , +}) +``` + +Or use one of the static constructors to load from environment variables: + +```ts +// Nodejs +import { Redis } from "@upstash/redis"; +const redis = Redis.fromEnv(); +``` + +```ts +// or when deploying to cloudflare workers +import { Redis } from "@upstash/redis/cloudflare"; +const redis = Redis.fromEnv(); +``` + +### Error handling + +Errors are now thrown automatically instead of being returned to you. + +```ts +// old +const { data, error } = await set("key", "value"); +if (error) { + throw new Error(error); +} + +// new +const data = await redis.set("key", "value"); // error is thrown automatically +``` + +## Pipeline + +`v1.0.0` introduces redis pipelines. Pipelining commands allows you to send a +single http request with multiple commands. + +```ts +import { Redis } from "@upstash/redis"; + +const redis = new Redis({ + /* auth */ +}); + +const p = redis.pipeline(); + +// Now you can chain multiple commands to create your pipeline: + +p.set("key", 2); +p.incr("key"); + +// or inline: +p.hset("key2", "field", { hello: "world" }).hvals("key2"); + +// Execute the pipeline once you are done building it: +// `exec` returns an array where each element represents the response of a command in the pipeline. +// You can optionally provide a type like this to get a typed response. +const res = await p.exec<[Type1, Type2, Type3]>(); +``` + +For more information about pipelines using REST see +[here](https://blog.upstash.com/pipeline). + +### Advanced + +A low level `Command` class can be imported from `@upstash/redis` in case you +need more control about types and or (de)serialization. + +By default all objects you are storing in redis are serialized using +`JSON.stringify` and recursively deserialized as well. Here's an example how you +could customize that behaviour. Keep in mind that you need to provide a `fetch` +polyfill if you are running on nodejs. We recommend +[isomorphic-fetch](https://www.npmjs.com/package/isomorphic-fetch). + +```ts +import { Command } from "@upstash/redis/commands" +import { HttpClient } from "@upstash/redis/http" + +/** + * TData represents what the user will enter or receive, + * TResult is the raw data returned from upstash, which may need to be + * transformed or parsed. + */ +const deserialize: (raw: TResult) => TData = ... + +class CustomGetCommand extends Command { + constructor(key: string, ) { + super(["get", key], { deserialize }) + } +} + +const client = new HttpClient({ + baseUrl: , + headers: { + authorization: `Bearer ${}`, + }, +}) + +const res = new CustomGetCommand("key").exec(client) +``` + +### Additional information + +#### `keepalive` + +`@upstash/redis` is capable of reusing connections where possible to minimize +latency. Connections can be reused if the client is stored in memory and not +initialized with every new function invocation. The easiest way to achieve this +is by creating the client outside of your handler and adding an https agent: + +```ts +// Nextjs api route +import { Redis } from "@upstash/redis"; +import https from "https"; + +const redis = Redis.fromEnv({ + agent: new https.Agent({ keepAlive: true }), +}); + +export default async function (req, res) { + // use redis here +} +``` + +Whenever your hot lambda receives a new request the client is already +initialized and the previously established connection to upstash is reused. + +#### Javascript MAX_SAFE_INTEGER + +Javascript can not handle numbers larger than `2^53 -1` safely and would return +wrong results when trying to deserialize them. In these cases the default +deserializer will return them as string instead. This might cause a mismatch +with your custom types. + +```ts +await redis.set("key", "101600000000150081467"); +const res = await redis("get"); +``` + +In this example `res` will still be a string despite the type annotation. Please +keep that in mind and adjust accordingly. + ## Docs -See -[the documentation](https://docs.upstash.com/redis/sdks/javascriptsdk/getstarted) -for details. +See [the documentation](https://docs.upstash.com/features/javascriptsdk) for +details. ## Contributing From 54791e8f5afae3edc15b9cbb8c8ac4c169ad91bb Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 08:14:42 +0200 Subject: [PATCH 10/12] ci: wait for server --- .github/workflows/tests.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index fd90514d..87bc1a55 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -356,13 +356,13 @@ jobs: working-directory: examples/cloudflare-workers - name: Start example - run: pnpm dev & + run: pnpm dev & sleep 5 working-directory: examples/cloudflare-workers env: CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} - - run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8787)" != "200" ]]; do sleep 1; done - timeout-minutes: 2 + # - run: while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8787)" != "200" ]]; do sleep 1; done + # timeout-minutes: 2 - name: Test run: deno test -A ./test.ts From 508dfc267b8e4cd14b3d6b54aa4cf2e96565ad0d Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 08:21:04 +0200 Subject: [PATCH 11/12] ci: log response --- examples/cloudflare-workers/test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/cloudflare-workers/test.ts b/examples/cloudflare-workers/test.ts index 158a75b4..88349c63 100644 --- a/examples/cloudflare-workers/test.ts +++ b/examples/cloudflare-workers/test.ts @@ -9,6 +9,9 @@ Deno.test("works", async () => { console.log({ deploymentURL }); const url = `${deploymentURL}/`; const res = await fetch(url); + if (res.status !== 200) { + console.log(await res.text()); + } assertEquals(res.status, 200); const json = (await res.json()) as { count: number }; assertEquals(typeof json.count, "number"); From 4f555d23d7d8c6b674213d4fabafa6a45c31bcb8 Mon Sep 17 00:00:00 2001 From: Andreas Thomas Date: Tue, 31 May 2022 08:32:47 +0200 Subject: [PATCH 12/12] ci: redeploy workers --- .github/workflows/tests.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 87bc1a55..63f3802d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -313,7 +313,7 @@ jobs: run: deno test -A ./test.ts working-directory: examples/cloudflare-workers-with-wrangler-1 env: - DEPLOYMENT_URL: https://upstash-modules-worker.upstash.workers.dev + DEPLOYMENT_URL: https://upstash-redis-with-wrangler-1.upstash.workers.dev @@ -409,7 +409,7 @@ jobs: run: deno test -A ./test.ts working-directory: examples/cloudflare-workers env: - DEPLOYMENT_URL: https://cloudflare-workers.upstash.workers.dev + DEPLOYMENT_URL: https://upstash-redis.upstash.workers.dev fastly-local: needs: