Skip to content

Commit

Permalink
chore(example): Add SvelteKit app (#738)
Browse files Browse the repository at this point in the history
I've gotten this working, finally. This time I looked into the `withRules` and used that in this implementations.

I still need to finish the "how it's done" part of the README, but I'd love a review and feedback on the code and install guide, make sure I'm not missing anything.
  • Loading branch information
Ben Dechrai authored May 15, 2024
1 parent 73359f6 commit 56f7dd3
Show file tree
Hide file tree
Showing 27 changed files with 4,272 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,20 @@ updates:
dependencies:
patterns:
- "*"

- package-ecosystem: npm
directory: /examples/sveltekit
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:
- "*"
40 changes: 40 additions & 0 deletions .github/workflows/reusable-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,43 @@ jobs:
- name: Build
working-directory: examples/nodejs-hono-rl
run: npm run build

sveltekit:
name: SvelteKit
runs-on: ubuntu-latest
permissions:
contents: read
steps:
# Environment security
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
github.com:443
registry.npmjs.org:443
# Checkout
# Most toolchains require checkout first
- name: Checkout
uses: actions/checkout@v4

# Language toolchains
- name: Install Node
uses: actions/[email protected]
with:
node-version: 20

# Workflow

- name: Install dependencies
run: npm ci

- name: Install example dependencies
working-directory: examples/sveltekit
run: npm ci

- name: Build
working-directory: examples/sveltekit
run: npm run build
1 change: 1 addition & 0 deletions .trunk/trunk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ merge:
- Build examples / Next.js 14 + OpenAI
- Build examples / Next.js 14 + Page Router + withArcjet
- Build examples / Node.js + Hono + Rate Limit
- Build examples / SvelteKit
1 change: 1 addition & 0 deletions examples/sveltekit/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ARCJET_KEY=
13 changes: 13 additions & 0 deletions examples/sveltekit/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example

# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
31 changes: 31 additions & 0 deletions examples/sveltekit/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/** @type { import("eslint").Linter.Config } */
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:svelte/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
extraFileExtensions: ['.svelte']
},
env: {
browser: true,
es2017: true,
node: true
},
overrides: [
{
files: ['*.svelte'],
parser: 'svelte-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser'
}
}
]
};
10 changes: 10 additions & 0 deletions examples/sveltekit/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
1 change: 1 addition & 0 deletions examples/sveltekit/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
4 changes: 4 additions & 0 deletions examples/sveltekit/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
8 changes: 8 additions & 0 deletions examples/sveltekit/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}
53 changes: 53 additions & 0 deletions examples/sveltekit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<a href="https://arcjet.com" target="_arcjet-home">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://arcjet.com/arcjet-logo-minimal-dark-mark-all.svg">
<img src="https://arcjet.com/arcjet-logo-minimal-light-mark-all.svg" alt="Arcjet Logo" height="128" width="auto">
</picture>
</a>

# Arcjet Protection with Svelte

This example shows how to use Arcjet to protect [SvelteKit](https://kit.svelte.dev/) apps.

## How to use

1. From the root of the project, install the SDK dependencies.

```bash
npm ci
```

2. Enter this directory and install the example's dependencies.

```bash
cd examples/svelte
npm ci
```

3. Rename `.env.example` to `.env` and add your Arcjet key.

4. Start the server.

```bash
npm run dev
```

5. Visit `http://localhost:5173/` in a browser and follow the links to test the various examples.

7. Test shield by making this request:

```bash
curl -v -H "x-arcjet-suspicious: true" http://localhost:5173
```

## How it works

This example uses the generic [`arcjet`](https://www.npmjs.com/package/arcjet) package.

The `arcjet` instance is created in `/src/lib/server/arcjet.ts` and is configured to enable [Shield](https://docs.arcjet.com/shield) by default. This server-only module also provides a `transformEvent()` method that takes a Svelte event and transforms it into the format required by the `arcjet` package.
`/src/hooks.server.ts` imports the `arcjet` instance and runs the `protect()` method on all requests. The only exception is any requests who's pathanme is listed in `filteredRoutes`, in which case protection is left to that route's server code.
The rate-limited page has a server-side script file at `/src/routes/rate-limited/+page.server.ts`, which retrieves the `arcjet` instance, and then applies extra rate-limiting rules before calling the `protect()` method.
Finally, the rate-limited API end-point performs the same augmentation of the rules as the rate-limted web page, as can be seen in `/src/routes/api/rate-limited/+server.ts`.
Loading

0 comments on commit 56f7dd3

Please sign in to comment.