diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ba1f85daa..c3770bb25 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -340,31 +340,6 @@ updates: - dependency-name: eslint versions: [">=9"] - - package-ecosystem: npm - directory: /examples/nextjs-example - schedule: - # Our dependencies should be checked daily - interval: daily - assignees: - - blaine-arcjet - reviewers: - - blaine-arcjet - commit-message: - prefix: deps(example) - prefix-development: deps(example) - groups: - dependencies: - patterns: - - "*" - ignore: - # Ignore updates to the @types/node package due to conflict between - # Headers in DOM. - - dependency-name: "@types/node" - versions: [">18.18"] - # TODO(#539): Upgrade to eslint 9 - - dependency-name: eslint - versions: [">=9"] - - package-ecosystem: npm directory: /examples/nodejs-express-rl schedule: diff --git a/README.md b/README.md index b2fa3c394..1175a3190 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ @@ -15,7 +15,7 @@
[Arcjet][arcjet] helps developers protect their apps in just a few lines of -code. Implement rate limiting, bot protection, email verification & defense +code. Implement rate limiting, bot protection, email verification, and defense against common attacks. This is the monorepo containing various [Arcjet][arcjet] open source packages @@ -23,12 +23,14 @@ for JS. ## Quick start -- **Bun?** Use the [`@arcjet/bun`][npm-bun] package. +- **Bun?** Use the [`@arcjet/bun`][npm-bun] package with our [Bun quick start + guide][bun-quick-start]. - **Next.js?** Use the [`@arcjet/next`][npm-next] package with our [Next.js quick start guide][next-quick-start]. - **Node.js?** Use the [`@arcjet/node`][npm-node] package with our [Node.js quick start guide][node-quick-start]. -- **SvelteKit?** Use the [`@arcjet/sveltekit`][npm-sveltekit] package. +- **SvelteKit?** Use the [`@arcjet/sveltekit`][npm-sveltekit] package with our + [SvelteKit quick start guide][sveltekit-quick-start]. ## Get help @@ -199,9 +201,11 @@ Licensed under the [Apache License, Version 2.0][apache-license]. [arcjet]: https://arcjet.com [npm-bun]: https://www.npmjs.com/package/@arcjet/bun [npm-next]: https://www.npmjs.com/package/@arcjet/next +[bun-quick-start]: https://docs.arcjet.com/get-started/bun [next-quick-start]: https://docs.arcjet.com/get-started/nextjs [npm-node]: https://www.npmjs.com/package/@arcjet/node [node-quick-start]: https://docs.arcjet.com/get-started/nodejs +[sveltekit-quick-start]: https://docs.arcjet.com/get-started/sveltekit [npm-sveltekit]: https://www.npmjs.com/package/@arcjet/sveltekit [discord-invite]: https://discord.gg/TPra6jqZDC [support]: https://docs.arcjet.com/support diff --git a/analyze/README.md b/analyze/README.md index a3d9f8604..16faf79fd 100644 --- a/analyze/README.md +++ b/analyze/README.md @@ -1,7 +1,7 @@ @@ -17,7 +17,7 @@ [Arcjet][arcjet] helps developers protect their apps in just a few lines of -code. Implement rate limiting, bot protection, email verification & defense +code. Implement rate limiting, bot protection, email verification, and defense against common attacks. This is the [Arcjet][arcjet] local analysis engine. diff --git a/arcjet-bun/README.md b/arcjet-bun/README.md index 381b32699..81d300a73 100644 --- a/arcjet-bun/README.md +++ b/arcjet-bun/README.md @@ -1,7 +1,7 @@ @@ -17,11 +17,15 @@ [Arcjet][arcjet] helps developers protect their apps in just a few lines of -code. Implement rate limiting, bot protection, email verification & defense +code. Implement rate limiting, bot protection, email verification, and defense against common attacks. This is the [Arcjet][arcjet] SDK for [Bun.sh][bun-sh]. +## Getting started + +Visit the [quick start guide][quick-start] to get started. + ## Example app Try an Arcjet protected app live at [https://example.arcjet.com][example-url] @@ -116,6 +120,7 @@ Licensed under the [Apache License, Version 2.0][apache-license]. [arcjet]: https://arcjet.com [bun-sh]: https://bun.sh/ [example-url]: https://example.arcjet.com +[quick-start]: https://docs.arcjet.com/get-started/bun [example-source]: https://github.com/arcjet/arcjet-js-example [rate-limit-concepts-docs]: https://docs.arcjet.com/rate-limiting/concepts [shield-concepts-docs]: https://docs.arcjet.com/shield/concepts diff --git a/arcjet-next/README.md b/arcjet-next/README.md index 91592608d..4659ebaa6 100644 --- a/arcjet-next/README.md +++ b/arcjet-next/README.md @@ -1,7 +1,7 @@ @@ -17,7 +17,7 @@ [Arcjet][arcjet] helps developers protect their apps in just a few lines of -code. Implement rate limiting, bot protection, email verification & defense +code. Implement rate limiting, bot protection, email verification, and defense against common attacks. This is the [Arcjet][arcjet] SDK for the [Next.js][next-js] framework. @@ -27,7 +27,7 @@ package. ## Getting started -Visit [docs.arcjet.com][next-sdk-docs] to get started. +Visit the [quick start guide][quick-start] to get started. ## Example app @@ -130,6 +130,7 @@ Licensed under the [Apache License, Version 2.0][apache-license]. [arcjet]: https://arcjet.com [next-js]: https://nextjs.org/ [alt-sdk]: https://www.npmjs.com/package/@arcjet/node +[quick-start]: https://docs.arcjet.com/get-started/nextjs [next-sdk-docs]: https://docs.arcjet.com/reference/nextjs [example-url]: https://example.arcjet.com [example-source]: https://github.com/arcjet/arcjet-js-example diff --git a/arcjet-node/README.md b/arcjet-node/README.md index 1c8ab7b52..f57fc8d8c 100644 --- a/arcjet-node/README.md +++ b/arcjet-node/README.md @@ -1,7 +1,7 @@ @@ -17,7 +17,7 @@ [Arcjet][arcjet] helps developers protect their apps in just a few lines of -code. Implement rate limiting, bot protection, email verification & defense +code. Implement rate limiting, bot protection, email verification, and defense against common attacks. This is the [Arcjet][arcjet] SDK for [Node.js][node-js]. @@ -25,6 +25,10 @@ This is the [Arcjet][arcjet] SDK for [Node.js][node-js]. **Looking for our Next.js framework SDK?** Check out the [`@arcjet/next`][alt-sdk] package. +## Getting started + +Visit the [quick start guide][quick-start] to get started. + ## Example app Try an Arcjet protected app live at [https://example.arcjet.com][example-url] @@ -129,6 +133,7 @@ Licensed under the [Apache License, Version 2.0][apache-license]. [node-js]: https://nodejs.org/ [alt-sdk]: https://www.npmjs.com/package/@arcjet/next [example-url]: https://example.arcjet.com +[quick-start]: https://docs.arcjet.com/get-started/nodejs [example-source]: https://github.com/arcjet/arcjet-js-example [rate-limit-concepts-docs]: https://docs.arcjet.com/rate-limiting/concepts [shield-concepts-docs]: https://docs.arcjet.com/shield/concepts diff --git a/arcjet-sveltekit/README.md b/arcjet-sveltekit/README.md index d73cf2476..882ed126d 100644 --- a/arcjet-sveltekit/README.md +++ b/arcjet-sveltekit/README.md @@ -1,7 +1,7 @@ @@ -17,11 +17,15 @@ [Arcjet][arcjet] helps developers protect their apps in just a few lines of -code. Implement rate limiting, bot protection, email verification & defense +code. Implement rate limiting, bot protection, email verification, and defense against common attacks. This is the [Arcjet][arcjet] SDK for [SvelteKit][sveltekit]. +## Getting started + +Visit the [quick start guide][quick-start] to get started. + ## Example app Try an Arcjet protected app live at [https://example.arcjet.com][example-url] @@ -127,6 +131,7 @@ Licensed under the [Apache License, Version 2.0][apache-license]. [arcjet]: https://arcjet.com [sveltekit]: https://kit.svelte.dev/ [example-url]: https://example.arcjet.com +[quick-start]: https://docs.arcjet.com/get-started/sveltekit [example-source]: https://github.com/arcjet/arcjet-js-example [rate-limit-concepts-docs]: https://docs.arcjet.com/rate-limiting/concepts [shield-concepts-docs]: https://docs.arcjet.com/shield/concepts diff --git a/arcjet/README.md b/arcjet/README.md index cf10b5dad..5e9a05f7f 100644 --- a/arcjet/README.md +++ b/arcjet/README.md @@ -1,7 +1,7 @@ @@ -17,7 +17,7 @@ [Arcjet][arcjet] helps developers protect their apps in just a few lines of -code. Implement rate limiting, bot protection, email verification & defense +code. Implement rate limiting, bot protection, email verification, and defense against common attacks. This is the [Arcjet][arcjet] TypeScript and JavaScript SDK core. diff --git a/decorate/README.md b/decorate/README.md index c3a9e3be4..223b7a496 100644 --- a/decorate/README.md +++ b/decorate/README.md @@ -1,7 +1,7 @@ diff --git a/duration/README.md b/duration/README.md index e33706500..9e944b3e9 100644 --- a/duration/README.md +++ b/duration/README.md @@ -1,7 +1,7 @@ diff --git a/eslint-config/README.md b/eslint-config/README.md index a45d8f91d..a7cc2020b 100644 --- a/eslint-config/README.md +++ b/eslint-config/README.md @@ -1,7 +1,7 @@ diff --git a/examples/bun-rl/index.ts b/examples/bun-rl/index.ts index 01275138a..2b9eb3e75 100644 --- a/examples/bun-rl/index.ts +++ b/examples/bun-rl/index.ts @@ -1,13 +1,17 @@ -import arcjet, { fixedWindow, shield } from "@arcjet/bun"; +import arcjet, { shield, tokenBucket } from "@arcjet/bun"; const aj = arcjet({ - key: Bun.env.ARCJET_KEY!, + key: Bun.env.ARCJET_KEY!, // Get your site key from https://app.arcjet.com rules: [ + // Shield protects your app from common attacks like SQL injection shield({ mode: "LIVE" }), - fixedWindow({ - mode: "LIVE", - max: 1, - window: "1m", + // Create a token bucket rate limit. Other algorithms are supported. + tokenBucket({ + mode: "LIVE", // will block requests. Use "DRY_RUN" to log only + characteristics: ["userId"], // track requests by a custom user ID + refillRate: 5, // refill 5 tokens per interval + interval: 10, // refill every 10 seconds + capacity: 10, // bucket maximum capacity of 10 tokens }), ], }); @@ -16,12 +20,17 @@ const aj = arcjet({ export default { port: 3000, fetch: aj.handler(async (req) => { - const decision = await aj.protect(req); + const userId = "user123"; // Replace with your authenticated user ID + const decision = await aj.protect(req, { userId, requested: 5 }); // Deduct 5 tokens from the bucket console.log("Arcjet request ID", decision.id); console.log("Arcjet decision", decision.conclusion); if (decision.isDenied()) { - return new Response("Blocked", { status: 403 }); + if (decision.reason.isRateLimit()) { + return new Response("Too many requests", { status: 429 }); + } else { + return new Response("Forbidden", { status: 403 }); + } } return new Response("Hello world"); @@ -29,17 +38,26 @@ export default { }; // Or using the `Bun.serve()` API -// const server = Bun.serve({ -// port: 3000, -// fetch: aj.handler(async (req) => { -// const decision = await aj.protect(req); +/* +const server = Bun.serve({ + port: 3000, + fetch: aj.handler(async (req) => { + const userId = "user123"; // Replace with your authenticated user ID + const decision = await aj.protect(req, { userId, requested: 5 }); // Deduct 5 tokens from the bucket + console.log("Arcjet request ID", decision.id); + console.log("Arcjet decision", decision.conclusion); -// if (decision.isDenied()) { -// return new Response("Blocked", { status: 403 }); -// } + if (decision.isDenied()) { + if (decision.reason.isRateLimit()) { + return new Response("Too many requests", { status: 429 }); + } else { + return new Response("Forbidden", { status: 403 }); + } + } -// return new Response("Hello world"); -// }), -// }); + return new Response("Hello world"); + }), +}); -// console.log(`Listening on ${server.url}`); +console.log(`Listening on ${server.url}`); +*/ \ No newline at end of file diff --git a/examples/nextjs-example/.env.local.example b/examples/nextjs-example/.env.local.example deleted file mode 100644 index 0c183c7ac..000000000 --- a/examples/nextjs-example/.env.local.example +++ /dev/null @@ -1 +0,0 @@ -ARCJET_KEY= \ No newline at end of file diff --git a/examples/nextjs-example/.gitignore b/examples/nextjs-example/.gitignore deleted file mode 100644 index f36d623f3..000000000 --- a/examples/nextjs-example/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz -package-lock.json - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts \ No newline at end of file diff --git a/examples/nextjs-example/README.md b/examples/nextjs-example/README.md deleted file mode 100644 index de2870e11..000000000 --- a/examples/nextjs-example/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Arcjet Rate Limiting Example - -‼️ This example is [for the Next.js -repo](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md). - -This example uses the [Arcjet](https://arcjet.com/) SDK to implement a token -bucket rate limit for API routes. It does not require any additional -infrastructure e.g. Redis. - -The Arcjet SDK allows you to implement rate limiting, bot protection, email -verification & defense against common attacks. See [the -docs](https://docs.arcjet.com/) for details. - -## Deploy your own - -Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): - -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/arcjet-rate-limit&project-name=arcjet-rate-limit&repository-name=arcjet-rate-limit) - -## How to use - -Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), [pnpm](https://pnpm.io), or [Bun](https://bun.sh/docs/cli/bunx) to bootstrap the example: - -```bash -npx create-next-app --example arcjet-rate-limit arcjet-rate-limit-app -``` - -```bash -yarn create next-app --example arcjet-rate-limit arcjet-rate-limit-app -``` - -```bash -pnpm create next-app --example arcjet-rate-limit arcjet-rate-limit-app -``` - -```bash -bunx create-next-app --example arcjet-rate-limit arcjet-rate-limit-app -``` - -To run the example you need to: - -1. [Create a free Arcjet account](https://app.arcjet.com/) then follow the - instructions to add a site and get a key. -2. Rename `.env.local.example` to `.env.local` and add your Arcjet key. - -Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). diff --git a/examples/nextjs-example/app/api/arcjet/route.ts b/examples/nextjs-example/app/api/arcjet/route.ts deleted file mode 100644 index 53af5c428..000000000 --- a/examples/nextjs-example/app/api/arcjet/route.ts +++ /dev/null @@ -1,52 +0,0 @@ -import arcjet, { shield, tokenBucket } from "@arcjet/next"; -import { NextResponse } from "next/server"; - -const aj = arcjet({ - // Get your key from https://app.arcjet.com and set it as an environment - // variable. - key: process.env.ARCJET_KEY, - // Arcjet supports multiple rules including bot protection and email - // validation. See https://docs.arcjet.com - rules: [ - // Protect against common attacks with Arcjet Shield - shield({ - mode: "LIVE", // will block requests. Use "DRY_RUN" to log only - }), - // Create a token bucket rate limit. Fixed and sliding window rate limits - // are also supported. See https://docs.arcjet.com/rate-limiting/algorithms - tokenBucket({ - mode: "LIVE", // will block requests. Use "DRY_RUN" to log only - // Use one of the built in characteristics e.g. ip.src, or create a custom - // one. Any string is valid - here we use userId. See - // https://docs.arcjet.com/rate-limiting/configuration#characteristics - characteristics: ["userId"], // track requests by user ID - refillRate: 100, // refill 100 tokens per interval - interval: "1m", // 1 min interval - capacity: 200, // bucket maximum capacity of 200 tokens - }), - ], -}); - -export async function GET(req: Request) { - // The rate limit will be applied by userId and 50 tokens will be withdrawn - // per request. Based on the rules above, 2 requests will consume all 100 - // tokens in the bucket. The bucket will then refill by 100 tokens every - // minute to a maximum of 200. Set the user ID and requested tokens - // dynamically e.g. based on the authenticated user and the "cost" of a - // request e.g. AI tokens consumed. - const decision = await aj.protect(req, { userId: "user1", requested: 50 }); - - if (decision.isDenied()) { - return NextResponse.json( - { - error: "Too Many Requests", - reason: decision.reason, - }, - { - status: 429, - } - ); - } - - return NextResponse.json({ message: "Hello World" }); -} \ No newline at end of file diff --git a/examples/nextjs-example/app/layout.tsx b/examples/nextjs-example/app/layout.tsx deleted file mode 100644 index a14e64fcd..000000000 --- a/examples/nextjs-example/app/layout.tsx +++ /dev/null @@ -1,16 +0,0 @@ -export const metadata = { - title: 'Next.js', - description: 'Generated by Next.js', -} - -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - {children} - - ) -} diff --git a/examples/nextjs-example/app/page.tsx b/examples/nextjs-example/app/page.tsx deleted file mode 100644 index 57a3a822c..000000000 --- a/examples/nextjs-example/app/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -export default function Index() { - return ( -- To test the rate limit, browse to /api/arcjet{" "} - and refresh the page a few times. -
- ); -} \ No newline at end of file diff --git a/examples/nextjs-example/environment.d.ts b/examples/nextjs-example/environment.d.ts deleted file mode 100644 index 9ae2b0722..000000000 --- a/examples/nextjs-example/environment.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare namespace NodeJS { - export interface ProcessEnv { - readonly ARCJET_KEY: string; - } -} \ No newline at end of file diff --git a/examples/nextjs-example/next.config.mjs b/examples/nextjs-example/next.config.mjs deleted file mode 100644 index 4678774e6..000000000 --- a/examples/nextjs-example/next.config.mjs +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {}; - -export default nextConfig; diff --git a/examples/nextjs-example/package.json b/examples/nextjs-example/package.json deleted file mode 100644 index 9e07ef160..000000000 --- a/examples/nextjs-example/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@arcjet/next": "^1.0.0-alpha.8", - "next": "latest", - "react": "^18", - "react-dom": "^18" - }, - "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint": "^8", - "eslint-config-next": "14.2.3", - "typescript": "^5" - } -} \ No newline at end of file diff --git a/examples/nextjs-example/tsconfig.json b/examples/nextjs-example/tsconfig.json deleted file mode 100644 index e7ff90fd2..000000000 --- a/examples/nextjs-example/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/headers/README.md b/headers/README.md index 5d95d119f..b26a26037 100644 --- a/headers/README.md +++ b/headers/README.md @@ -1,7 +1,7 @@ diff --git a/ip/README.md b/ip/README.md index e205a89d7..ab85292d7 100644 --- a/ip/README.md +++ b/ip/README.md @@ -1,7 +1,7 @@ diff --git a/logger/README.md b/logger/README.md index de97eeaaf..0c5af4252 100644 --- a/logger/README.md +++ b/logger/README.md @@ -1,7 +1,7 @@ diff --git a/protocol/README.md b/protocol/README.md index d3e4eb5f5..9bd0aabcc 100644 --- a/protocol/README.md +++ b/protocol/README.md @@ -1,7 +1,7 @@ diff --git a/rollup-config/README.md b/rollup-config/README.md index b315012c6..31e8fc790 100644 --- a/rollup-config/README.md +++ b/rollup-config/README.md @@ -1,7 +1,7 @@ diff --git a/runtime/README.md b/runtime/README.md index 241b24fc3..cc9d1262a 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -1,7 +1,7 @@ diff --git a/sprintf/README.md b/sprintf/README.md index 654267638..310da1e92 100644 --- a/sprintf/README.md +++ b/sprintf/README.md @@ -1,7 +1,7 @@ diff --git a/tsconfig/README.md b/tsconfig/README.md index 170b381d5..451a0398d 100644 --- a/tsconfig/README.md +++ b/tsconfig/README.md @@ -1,7 +1,7 @@