From 7987824a3b6c8ae50aa83c1511799312f64f6e54 Mon Sep 17 00:00:00 2001
From: Ben McCann <322311+benmccann@users.noreply.github.com>
Date: Tue, 27 May 2025 16:50:37 -0700
Subject: [PATCH] feat: add SvelteKit support
---
README.md | 13 +++++++++-
grant.js | 8 +++++++
lib/handler/sveltekit.js | 51 ++++++++++++++++++++++++++++++++++++++++
lib/session.js | 8 +++----
4 files changed, 75 insertions(+), 5 deletions(-)
create mode 100644 lib/handler/sveltekit.js
diff --git a/README.md b/README.md
index f5a3e9b7..c5eba75f 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
- **[Providers](#grant)**
- **Handlers**
- - [Express](#handlers) / [Koa](#handlers) / [Hapi](#handlers) / [Fastify](#handlers)
+ - [Express](#handlers) / [Koa](#handlers) / [Hapi](#handlers) / [Fastify](#handlers) / [SvelteKit](#handlers)
- [AWS Lambda](#handlers) / [Azure Function](#handlers) / [Google Cloud Function](#handlers) / [Vercel](#handlers)
- **Configuration**
- [Basics](#configuration-basics) / [Description](#configuration-description) / [Values](#configuration-values) / [Scopes](#configuration-scopes)
@@ -102,6 +102,17 @@ fastify()
```
+SvelteKit
+
+```js
+import grant from 'grant';
+
+export const handle = grant.sveltekit({
+ config: {/*configuration - see below*/}, session: {secret: 'grant'}
+});
+```
+
+
### Serverless Functions
AWS Lambda
diff --git a/grant.js b/grant.js
index c2d210b0..6f5a4fab 100644
--- a/grant.js
+++ b/grant.js
@@ -64,6 +64,9 @@ function grant ({handler, ...rest}) {
else if (handler === 'vercel') {
return require('./lib/handler/vercel')(rest)
}
+ else if (handler === 'sveltekit') {
+ return require('./lib/handler/sveltekit')(rest)
+ }
}
grant.express = (options) => {
@@ -135,5 +138,10 @@ grant.vercel = (options) => {
return options ? handler(options) : handler
}
+grant.sveltekit = (options) => {
+ var handler = require('./lib/handler/sveltekit')
+ return options ? handler(options) : handler
+}
+
grant.default = grant
module.exports = grant
diff --git a/lib/handler/sveltekit.js b/lib/handler/sveltekit.js
new file mode 100644
index 00000000..24c7b387
--- /dev/null
+++ b/lib/handler/sveltekit.js
@@ -0,0 +1,51 @@
+var qs = require('qs')
+var Grant = require('../grant')
+var Session = require('../session')
+
+module.exports = function (args = {}) {
+ var grant = Grant(args.config ? args : {config: args})
+ app.config = grant.config
+
+ var regex = new RegExp([
+ '^',
+ app.config.defaults.prefix,
+ /(?:\/([^\/\?]+?))/.source, // /:provider
+ /(?:\/([^\/\?]+?))?/.source, // /:override?
+ /(?:\/$|\/?\?+.*)?$/.source, // querystring
+ ].join(''), 'i')
+
+ var store = Session(args.session)
+
+ async function app ({ event, resolve }) {
+ var session = store(event.request)
+ var match = regex.exec(event.url.pathname + event.url.search)
+ if (!match) {
+ return resolve(event)
+ }
+
+ var {location, session:sess, state} = await grant({
+ method: event.request.method,
+ params: {provider: match[1], override: match[2]},
+ query: qs.parse(event.url.searchParams.toString()),
+ body: qs.parse(await event.request.text()),
+ state,
+ session: (await session.get()).grant,
+ })
+
+ await session.set({grant: sess})
+
+ if (location) {
+ return new Response(null, {
+ status: 307,
+ headers: {
+ location,
+ 'set-cookie': session.headers['set-cookie']
+ }
+ })
+ } else {
+ return resolve(event)
+ }
+ }
+
+ return app
+}
diff --git a/lib/session.js b/lib/session.js
index e76898e6..2f19b7e8 100644
--- a/lib/session.js
+++ b/lib/session.js
@@ -15,12 +15,12 @@ module.exports = ({name, secret, cookie:options, store}) => {
var embed = !store
return (req) => {
- var headers = Object.keys(req.headers)
+ var headerObj = req.headers instanceof Headers;
+ var headers = (headerObj ? Array.from(req.headers.keys()) : Object.keys(req.headers))
.filter((key) => /(?:set-)?cookie/i.test(key))
- .reduce((all, key) => (all[key.toLowerCase()] = req.headers[key], all), {})
-
+ .reduce((all, key) => (all[key.toLowerCase()] = headerObj ? req.headers.get(key) : req.headers[key], all), {})
headers['set-cookie'] =
- headers['set-cookie'] ||
+ (headerObj ? headers.get('set-cookie') : headers['set-cookie']) ||
(req.multiValueHeaders && req.multiValueHeaders['Set-Cookie']) ||
[]