From c7801d8b758c2503de302c411fe9a7ad5da3d894 Mon Sep 17 00:00:00 2001 From: psteinroe Date: Fri, 8 Dec 2023 22:49:00 +0100 Subject: [PATCH 1/3] initial commit --- .DS_Store | Bin 0 -> 6148 bytes .github/FUNDING.yml | 1 + .github/ISSUE_TEMPLATE/bug_report.md | 24 +++ .github/ISSUE_TEMPLATE/feature_request.md | 19 ++ .github/workflows/ci.yml | 43 ++++ .github/workflows/release.yml | 42 ++++ .../workflows/sync-renovate-changesets.yml | 110 +++++++++++ .github/workflows/update-prs.yml | 9 + README.md | 76 ++++++- biome.json | 17 ++ bun.lockb | Bin 0 -> 178534 bytes package.json | 67 +++++++ src/fastify-supabase.ts | 122 ++++++++++++ src/index.ts | 3 + test/fastify-supabase.test.ts | 185 ++++++++++++++++++ tsconfig.json | 20 ++ tsup.config.ts | 12 ++ 17 files changed, 749 insertions(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/sync-renovate-changesets.yml create mode 100644 .github/workflows/update-prs.yml create mode 100644 biome.json create mode 100755 bun.lockb create mode 100644 package.json create mode 100644 src/fastify-supabase.ts create mode 100644 src/index.ts create mode 100644 test/fastify-supabase.test.ts create mode 100644 tsconfig.json create mode 100644 tsup.config.ts diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9f59c4caec594405b74bb9896f31bb2ac9a3fe39 GIT binary patch literal 6148 zcmeHK%Z}496uoW(O=lR?1xT|&io~`mEib8J)9JK}k$}Yn!2(c8n$QW8iK`}|i>gxB z@DKa~TfT&UVFkwzq$H&aHV9R|l6@Te9{b*t#;%Eo4fCK!)FL7qMWA(n>JKKyMcJ~N z?l}T7ImZR%Gk{TwzKNr@3x(X4<4`AP5buUdr!_Mm+@7?KPed* zb{%OVi=utTLnW(^?jnhKGQ)^q9gvTVIbBhR>_1S7c5)W;sUOSC#fEr-()lS3Eutnk zIVJFq;XS2G@+*w56^2CtR!J!<`>{I}zXm;}GdiU)JtvpO6>pJEF^(IEfn(;7CWv3O zazqqTTH*cJ;?2pEaeH{*JM*pyjf(3v=^T-r(1@M^J6JO)uOyZFQc$XnoEJ1Ld&#Ve zUKW0Fh95B= z-19t5dPV`Gz~3t%_6G+=;6UR>q1-x9$twWRLbo)u#nCA^j>dt;jY5pTn4$s|mFX)6 zQ*`t@+Hat7qfpU_>B|SxD>HpVVRCiM??`uI1BIqG3K#{-3e?qOOPv4X-S_`8$vhba zi~@V50JBE!Xo!^b*}9dSIBOl0cPPSy-$tRNpwh>&Y>1=y7)2V!9MJ#{G;S242WI{V NNEu9J6!@nK`~r7j;Clc7 literal 0 HcmV?d00001 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..d197350 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [psteinroe] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..d1efe3c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "" +labels: bug +assignees: "" +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +If possible, open a PR with a failing test. Otherwise, describe how to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..d883b8f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "" +labels: enhancement +assignees: "" +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4cc4381 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: Continuous Integration + +on: + pull_request: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +jobs: + ci: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + fail-fast: false + + steps: + - id: checkout + name: Checkout + uses: actions/checkout@v3 + + - id: setup-bun + name: Setup Bun + uses: oven-sh/setup-bun@v1 + with: + bun-version: latest + + - id: install-deps + name: Install dependencies + run: bun install + + - id: check + name: Run check + run: bun run check + + - id: typecheck + name: Run typecheck + run: bun run typecheck + + - id: test + name: Run test + run: bun run test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..035f6ac --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,42 @@ +name: Release + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v2.4.0 + with: + version: 8.x.x + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 16 + cache: pnpm + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Build Packages + run: pnpm run build --filter='./packages/*' + + - name: Create a release + id: changesets + uses: changesets/action@v1 + with: + version: bun run ci:version + commit: "chore: update versions" + title: "chore: update versions" + publish: bun run ci:release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/sync-renovate-changesets.yml b/.github/workflows/sync-renovate-changesets.yml new file mode 100644 index 0000000..ab6dbd3 --- /dev/null +++ b/.github/workflows/sync-renovate-changesets.yml @@ -0,0 +1,110 @@ +name: Sync Renovate changeset +on: + workflow_dispatch: + pull_request_target: + paths: + - ".github/workflows/sync-renovate-changesets.yml" + - "bun.lockb" + - "package.json" + +jobs: + generate-changeset: + runs-on: ubuntu-latest + if: github.actor == 'renovate[bot]' && github.repository == 'psteinroe/fastify-supabase' + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + ref: ${{ github.head_ref }} + - name: Configure Git + run: | + git config --global user.email philipp@steinroetter.com + git config --global user.name 'Philipp Steinrötter (Bot)' + - name: Generate changeset + uses: actions/github-script@v7 + with: + script: | + const { promises: fs } = require("fs"); + // Parses package.json files and returns the package names + async function getPackagesNames(files) { + const names = []; + for (const file of files) { + const data = JSON.parse(await fs.readFile(file, "utf8")); + if (!data.private) { + names.push(data.name); + } + } + return names; + } + + async function createChangeset(fileName, packageBumps, packages) { + let message = ""; + for (const [pkg, bump] of packageBumps) { + message = message + `Updated dependency \`${pkg}\` to \`${bump}\`.\n`; + } + + const pkgs = packages.map((pkg) => `'${pkg}': patch`).join("\n"); + const body = `---\n${pkgs}\n---\n\n${message.trim()}\n`; + await fs.writeFile(fileName, body); + } + + async function getBumps(files) { + const bumps = new Map(); + for (const file of files) { + const data = JSON.parse(await fs.readFile(file, "utf8")); + const { stdout: changes } = await exec.getExecOutput("git", [ + "show", + file, + ]); + for (const change of changes.split("\n")) { + if (!change.startsWith("+ ")) { + continue; + } + const match = change.match(/"(.*?)"/g); + const pkg = match[0].replace(/"/g, ""); + const bump = match[1].replace(/"/g, ""); + // do not add changeset for dev dependencies + if ((data.dependencies && data.dependencies[pkg]) || (data.peerDependencies && data.peerDependencies[pkg])) { + bumps.set(pkg, bump); + } else { + console.log(`"${pkg}" is a dev dependency, skipping`) + } + } + } + return bumps; + } + + const branch = await exec.getExecOutput("git branch --show-current"); + if (!branch.stdout.startsWith("renovate/")) { + console.log("Not a renovate branch, skipping"); + return; + } + const diffOutput = await exec.getExecOutput("git diff --name-only HEAD~1"); + const diffFiles = diffOutput.stdout.split("\n"); + if (diffFiles.find((f) => f.startsWith(".changeset"))) { + console.log("Changeset already exists, skipping"); + return; + } + const files = diffFiles + .filter((file) => file !== "package.json") // skip root package.json + .filter((file) => file.includes("package.json")); + const packageNames = await getPackagesNames(files); + if (!packageNames.length) { + console.log("No package.json changes to published packages, skipping"); + return; + } + const { stdout: shortHash } = await exec.getExecOutput( + "git rev-parse --short HEAD" + ); + const fileName = `.changeset/renovate-${shortHash.trim()}.md`; + + const packageBumps = await getBumps(files); + if (packageBumps.size === 0) { + console.log("No valid bumps, skipping"); + return; + } + await createChangeset(fileName, packageBumps, packageNames); + await exec.exec("git", ["add", fileName]); + await exec.exec("git commit -C HEAD --amend --no-edit"); + await exec.exec("git push --force"); diff --git a/.github/workflows/update-prs.yml b/.github/workflows/update-prs.yml new file mode 100644 index 0000000..e6b5a5c --- /dev/null +++ b/.github/workflows/update-prs.yml @@ -0,0 +1,9 @@ +name: Update stale PRs +on: push + +jobs: + update-prs: + name: Run auto-update to update stale PRs + runs-on: ubuntu-latest + steps: + - uses: tibdex/auto-update@v2 diff --git a/README.md b/README.md index 39fae5b..6bd1a61 100644 --- a/README.md +++ b/README.md @@ -1 +1,75 @@ -# fastify-supabase \ No newline at end of file +# Supabase Plugin for Fastify + +A Fastify plugin to use authenticated Supabase clients in your API. + +Latest build +GitHub Stars + +## Installation + +Install with your favorite package manager. + +```bash +pnpm add @psteinroe/fastify-supabase +``` + +## Quick Start + +First, register `@fastify/jwt` with your Supabase JWT secret. You can obtain it from Supabase Studio. + +```ts +import fastifyJWT from "@fastify/jwt"; + +fastify.register(fastifyJWT, { + secret: SUPABASE_JWT_SECRET, +}); +``` + +Then, register the Supabase plugin. + +```ts +import fastifySupabase from "@hellomateo/fastify-supabase"; + +fastify.register(fastifySupabase, { + url: SUPABASE_URL, + anonKey: SUPABASE_ANON_KEY, + serviceKey: SUPABASE_SERVICE_KEY, + // you can pass any `SupabaseClientOptions` + options: {}, +}); +``` + +You can now access a `SupabaseClient` authenticated as the service role directly on the Fastify instance with `fastify.supabaseClient`. + +To protect a route and use a user-authenticated `SupabaseClient`, create a `onRequest` route handler to verify the JWT. Note that this is a `@fastify/jwt` feature. + +```ts +import { onRequestHookHandler } from "fastify"; + +export const verifyApiKey: onRequestHookHandler = async (request) => { + await request.jwtVerify(); +}; +``` + +Now pass the hook to the route handler. You can now access either a client authenticated with the service role via the Fastify instance, or a user-authenticated client via the request. + +```ts +import { FastifyInstance } from "fastify"; + +import { verifyApiKey } from "../helpers/verify"; + +export default async function routes(fastify: FastifyInstance) { + fastify.get("/health", { + onRequest: [verifyApiKey], + handler: async (request, reply) => { + // authenticated as the user + const { data } = request.supabaseClient.from("article").select("*"); + + // authenticated with service role + const { data } = fastify.supabaseClient.from("article").select("*"); + + return reply.send("OK"); + }, + }); +} +``` diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..a2dc099 --- /dev/null +++ b/biome.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.4.1/schema.json", + "organizeImports": { + "enabled": true + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + } +} diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..c802ac5f88e38e85835448bfa8714b76c3f6ad90 GIT binary patch literal 178534 zcmeFa2~^Gd_y2#&Aw(sSCQXKl1__arN-E8yNok(vfzlvzAw(pFOrbJM#-uVeXG~Ix zL>efPq5SslykFP3K8ADnuk~I3weD-(chB=09((WC@P56AbMC#;l8T|hL5fbEeu}Ps zOC+2^{RYD!@8j?6?dIv@D(~hWQl4EaZ6sQk#=RD-@eAB`3h1)q38{V8i| zEcVySAHwvb(QsUyVElr89D_Ze-q$tA-Bp=J^K|#~4}uZS1{m94fyu-E_Jcvdyi<^) zGfX3G8RW4%4;06leg))1WP};K7$}ze`?-dA`nuA5J$*f$ z<=y;-K{<{`fMbY84Pyc`hv;C z_O8KBp`Jc2v{slTTnE*l*pC~a5PHm6syvO#$5ZtYRJl73T1?bd+edJUxNZK?XXRNlqaDbyYM;~NZrAUS*ZdwaS# z1_ik~y1-Zm+#Sc5&+C-#8_zfo9sR;#e{uG3c69FJj>G!Gc|R<}7!RCRoX;1sjByNh z^18O#@ec6x^GApB@(e$m zpg5n>pg3R26B&6P$YZ}-Adllw1&ZT!4HU;SIKam<1lIRzMTT85B}V-Ipg7+FLH@9= zgK3Pjh(>b?b#ue`JzZU0r%h3zSxsWZHx%0AIu-(3*pHK7AN3F@+R1{rv3|~EM!B;; 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 literal 0 HcmV?d00001 diff --git a/package.json b/package.json new file mode 100644 index 0000000..250e255 --- /dev/null +++ b/package.json @@ -0,0 +1,67 @@ +{ + "name": "@psteinroe/fastify-supabase", + "version": "0.0.1", + "author": "Philipp Steinrötter ", + "type": "module", + "bugs": { + "url": "https://github.com/psteinroe/supabase-cache-helpers/issues" + }, + "main": "./dist/index.cjs", + "source": "./src/index.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + }, + "./package.json": "./package.json" + }, + "types": "./dist/index.d.ts", + "files": [ + "dist/**" + ], + "publishConfig": { + "access": "public" + }, + "license": "MIT", + "keywords": [ + "Supabase", + "Auth", + "Fastify" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/psteinroe/fastify-supabase.git" + }, + "scripts": { + "test": "bun test", + "test:watch": "bun test --watch", + "check": "biome check --apply ./**/*.ts", + "typecheck": "tsc --pretty --noEmit", + "build": "tsup", + "clear-branches": "git branch --merged | egrep -v \"(^\\*|main)\" | xargs git branch -d", + "merge-main": "git fetch origin main:main && git merge main", + "reset-git": "git checkout main && git pull && bun clear-branches", + "changeset": "changeset", + "ci:version": "changeset version", + "ci:release": "changeset publish" + }, + "peerDependencies": { + "@supabase/supabase-js": "^2.0.0" + }, + "dependencies": { + "@fastify/error": "3.4.1", + "fastify-plugin": "4.5.1" + }, + "devDependencies": { + "bun-plugin-dts": "0.2.1", + "@biomejs/biome": "1.4.1", + "@changesets/cli": "2.27.0", + "@fastify/jwt": "7.2.4", + "bun-types": "latest", + "fast-jwt": "3.3.2", + "fastify": "4.24.3", + "tsup": "8.0.0", + "typescript": "5.3.3" + } +} diff --git a/src/fastify-supabase.ts b/src/fastify-supabase.ts new file mode 100644 index 0000000..69ab3c9 --- /dev/null +++ b/src/fastify-supabase.ts @@ -0,0 +1,122 @@ +import createError from "@fastify/error"; +import type { JWT } from "@fastify/jwt"; +import { + SupabaseClient, + SupabaseClientOptions, + User, + createClient, +} from "@supabase/supabase-js"; +import type { FastifyPluginCallback, FastifyRequest } from "fastify"; +import fp from "fastify-plugin"; + +const AuthorizationTokenInvalidError = createError( + "FST_SB_AUTHORIZATION_TOKEN_INVALID", + "Authorization token is invalid", + 401, +); + +const NoUserDataFoundError = createError( + "FST_SB_NO_USER_DATA_FOUND", + "No user data found in the request. Make sure to run request.jwtVerify() before trying to access the user.", + 401, +); + +declare module "fastify" { + export interface FastifyInstance { + supabaseClient: SupabaseClient; + jwt: JWT; + } + export interface FastifyRequest { + _supabaseClient: SupabaseClient; + supabaseUser: User; + } +} + +export type FastifySupabasePluginOpts = { + url: string; + serviceKey: string; + anonKey: string; + options?: SupabaseClientOptions<"public">; +}; + +const fastifySupabase: FastifyPluginCallback = ( + fastify, + opts, + next, +) => { + const { url, serviceKey, anonKey, options } = opts; + + const supabase = createClient(url, serviceKey, options); + + if (fastify.supabaseClient) { + return next(new Error("fastify-supabase has already been registered")); + } + + fastify.decorate("supabaseClient", supabase); + + fastify.decorateRequest("_supabaseClient", null); + fastify.decorateRequest( + "supabaseClient", + { + getter() { + const req = this as unknown as FastifyRequest; + + if (req._supabaseClient) return req._supabaseClient; + + if ((req.user as { role?: string }).role === "service_role") { + req._supabaseClient = fastify.supabaseClient; + } else if ( + (req.user as { role?: string }).role && + (req.user as { role?: string }).role !== "anon" + ) { + const client = createClient(url, anonKey, { + ...options, + auth: { + ...options?.auth, + persistSession: false, + }, + global: { + ...options?.global, + headers: { + ...options?.global?.headers, + Authorization: `Bearer ${fastify.jwt.lookupToken(req)}`, + }, + }, + }); + req._supabaseClient = client as SupabaseClient; + } + + if (!req._supabaseClient) { + throw new AuthorizationTokenInvalidError(); + } + + return req._supabaseClient; + }, + }, + ["user"], + ); + + fastify.decorateRequest( + "supabaseUser", + { + getter() { + const req = this as unknown as FastifyRequest; + + if (!req.user) { + throw new NoUserDataFoundError(); + } + + return req.user as User; + }, + }, + ["user"], + ); + + next(); +}; + +export default fp(fastifySupabase, { + fastify: "4.x", + name: "fastify-supabase", + dependencies: ["@fastify/jwt"], +}); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..63b6a80 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,3 @@ +import { default as fastifySupabase } from "./fastify-supabase"; + +export default fastifySupabase; diff --git a/test/fastify-supabase.test.ts b/test/fastify-supabase.test.ts new file mode 100644 index 0000000..82c3841 --- /dev/null +++ b/test/fastify-supabase.test.ts @@ -0,0 +1,185 @@ +import { describe, expect, mock, spyOn, test } from "bun:test"; +import fastifyJWT from "@fastify/jwt"; +import { SupabaseClient } from "@supabase/supabase-js"; +import { createSigner } from "fast-jwt"; +import Fastify from "fastify"; +import fastifySupabase from "../src"; + +const JWT_SECRET = "super-secret-jwt-token-with-at-least-32-characters-long"; +const SERVICE_ROLE_TOKEN = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSJ9.vI9obAHOGyVVKa3pD--kJlyxp-Z2zV9UUMAhKpNLAcU"; +const ANON_TOKEN = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs"; +const signer = createSigner({ key: JWT_SECRET }); +const USER_ROLE_TOKEN = signer({ role: "authenticated" }); + +declare module "fastify" { + export interface FastifyRequest { + supabaseClient: SupabaseClient; + } +} + +const createTestServer = () => { + const fastify = Fastify(); + + fastify.register(fastifyJWT, { + secret: JWT_SECRET, + }); + + fastify.addHook("onRequest", async (request, reply) => { + try { + await request.jwtVerify(); + } catch (err) { + reply.send(err); + } + }); + + fastify.register(fastifySupabase, { + url: "https://test.com", + anonKey: ANON_TOKEN, + serviceKey: SERVICE_ROLE_TOKEN, + }); + + return fastify; +}; + +describe("fastify-supabase", () => { + test("register", async () => { + const fastify = Fastify(); + + fastify.register(fastifyJWT, { + secret: JWT_SECRET, + }); + + fastify.register(fastifySupabase, { + url: "https://test.com", + anonKey: "anon-key", + serviceKey: "service-key", + }); + + fastify.register(fastifySupabase, { + url: "https://test.com", + anonKey: "anon-key", + serviceKey: "service-key", + }); + + // .rejects does not work in bun yet: https://github.com/oven-sh/bun/issues/5602 + // await expect(fastify.ready()).rejects.toBe( + // "fastify-supabase has already been registered" + // ); + const spy = spyOn(fastify, "ready"); + try { + await fastify.ready(); + } catch (err) { + expect(err).toEqual( + new Error("fastify-supabase has already been registered"), + ); + } + expect(spy).toHaveBeenCalledTimes(1); + + expect(fastify.supabaseClient).toBeTruthy(); + }); + + // fastify.inject is not yet supported in bun: https://github.com/oven-sh/bun/pull/7485 + test.skip("service role", async () => { + const tracker = mock(() => { + // noop + }); + + const fastify = createTestServer(); + + fastify.get("/methods", (request, reply) => { + expect(request.supabaseClient).toEqual(fastify.supabaseClient); + tracker(); + reply.send(); + }); + + await fastify.inject({ + method: "get", + url: "/methods", + headers: { + authorization: `Bearer ${SERVICE_ROLE_TOKEN}`, + }, + }); + + expect(tracker).toHaveBeenCalledTimes(1); + }); + + // fastify.inject is not yet supported in bun: https://github.com/oven-sh/bun/pull/7485 + test.skip("anon role", async () => { + const tracker = mock(() => { + // noop + }); + + const fastify = createTestServer(); + + fastify.get("/methods", (request, reply) => { + expect(() => request.supabaseClient).toThrow( + "Authorization token is invalid", + ); + tracker(); + reply.send(); + }); + + await fastify.inject({ + method: "get", + url: "/methods", + headers: { + authorization: `Bearer ${ANON_TOKEN}`, + }, + }); + expect(tracker).toHaveBeenCalledTimes(1); + }); + + // fastify.inject is not yet supported in bun: https://github.com/oven-sh/bun/pull/7485 + test.skip("user role", async () => { + const tracker = mock(() => { + // noop + }); + + const fastify = createTestServer(); + + fastify.get("/methods", (request, reply) => { + // biome-ignore lint/complexity/useLiteralKeys: we want to make typescript happy + expect(request.supabaseClient["supabaseKey"]).toEqual(USER_ROLE_TOKEN); + tracker(); + reply.send(); + }); + + await fastify.inject({ + method: "get", + url: "/methods", + headers: { + authorization: `Bearer ${USER_ROLE_TOKEN}`, + }, + }); + + expect(tracker).toHaveBeenCalledTimes(1); + }); + + // fastify.inject is not yet supported in bun: https://github.com/oven-sh/bun/pull/7485 + test.skip("client cache", async () => { + const tracker = mock(() => { + // noop + }); + + const fastify = createTestServer(); + + fastify.get("/methods", (request, reply) => { + request._supabaseClient = "test" as unknown as SupabaseClient; + // biome-ignore lint/suspicious/noExplicitAny: we want to make typescript happy + expect(request.supabaseClient as any).toEqual("test"); + tracker(); + reply.send(); + }); + + await fastify.inject({ + method: "get", + url: "/methods", + headers: { + authorization: `Bearer ${USER_ROLE_TOKEN}`, + }, + }); + expect(tracker).toHaveBeenCalledTimes(1); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d93b504 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "include": ["src/**/*.ts"], + "compilerOptions": { + "lib": ["ESNext"], + "module": "esnext", + "target": "esnext", + "moduleResolution": "bundler", + "moduleDetection": "force", + "allowImportingTsExtensions": true, + "noEmit": true, + "strict": true, + "downlevelIteration": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "allowJs": true, + "types": ["bun-types"] + } +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..722363d --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,12 @@ +import type { Options } from "tsup"; + +export const tsup: Options = { + dts: true, + entryPoints: ["src/index.ts"], + format: ["cjs", "esm"], + legacyOutput: false, + sourcemap: true, + splitting: false, + bundle: true, + clean: true, +}; From 81f31b1aadc3f28a4153e46787ce894f685b623e Mon Sep 17 00:00:00 2001 From: psteinroe Date: Fri, 8 Dec 2023 22:54:01 +0100 Subject: [PATCH 2/3] chore: more docs --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6bd1a61..937d42f 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ export const verifyApiKey: onRequestHookHandler = async (request) => { }; ``` -Now pass the hook to the route handler. You can now access either a client authenticated with the service role via the Fastify instance, or a user-authenticated client via the request. +Now pass the hook to the route handler. You can now access either a client authenticated with the service role via the Fastify instance, or a user-authenticated client via the request. Thanks to `@fastify/jwt`, you can also access the Supabase `User` object on the request. ```ts import { FastifyInstance } from "fastify"; @@ -62,14 +62,24 @@ export default async function routes(fastify: FastifyInstance) { fastify.get("/health", { onRequest: [verifyApiKey], handler: async (request, reply) => { - // authenticated as the user + // authenticated as the user that is making the request const { data } = request.supabaseClient.from("article").select("*"); // authenticated with service role const { data } = fastify.supabaseClient.from("article").select("*"); + // access the `User` object on the request + const tenantId = request.user.app_metadata.tenantId; + return reply.send("OK"); }, }); } ``` + +Thats it! + +--- + +Fastify Supabase is created by [psteinroe](https://github.com/psteinroe). +Follow [@psteinroe](https://twitter.com/psteinroe) on Twitter for future project updates. From dc92fa5f87686f52c359351ba41f02cc5d3bb81e Mon Sep 17 00:00:00 2001 From: psteinroe Date: Fri, 8 Dec 2023 22:56:39 +0100 Subject: [PATCH 3/3] chore: changesets --- .changeset/README.md | 8 ++++++++ .changeset/config.json | 11 +++++++++++ .changeset/dirty-mangos-wash.md | 5 +++++ package.json | 4 ++-- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json create mode 100644 .changeset/dirty-mangos-wash.md diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..e5b6d8d --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..91b6a95 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.changeset/dirty-mangos-wash.md b/.changeset/dirty-mangos-wash.md new file mode 100644 index 0000000..f7f95bc --- /dev/null +++ b/.changeset/dirty-mangos-wash.md @@ -0,0 +1,5 @@ +--- +"@steinroe/fastify-supabase": patch +--- + +initial release diff --git a/package.json b/package.json index 250e255..24f148c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@psteinroe/fastify-supabase", - "version": "0.0.1", + "name": "@steinroe/fastify-supabase", + "version": "0.0.0", "author": "Philipp Steinrötter ", "type": "module", "bugs": {