Skip to content

Commit

Permalink
Merge pull request #2 from psteinroe/initial-commit
Browse files Browse the repository at this point in the history
initial commit
  • Loading branch information
psteinroe authored Dec 8, 2023
2 parents 59ce7d9 + dc92fa5 commit d356a30
Show file tree
Hide file tree
Showing 20 changed files with 783 additions and 1 deletion.
Binary file added .DS_Store
Binary file not shown.
8 changes: 8 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -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)
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
5 changes: 5 additions & 0 deletions .changeset/dirty-mangos-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@steinroe/fastify-supabase": patch
---

initial release
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: [psteinroe]
24 changes: 24 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -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.
19 changes: 19 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -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.
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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
42 changes: 42 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -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/[email protected]
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 }}
110 changes: 110 additions & 0 deletions .github/workflows/sync-renovate-changesets.yml
Original file line number Diff line number Diff line change
@@ -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 [email protected]
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");
9 changes: 9 additions & 0 deletions .github/workflows/update-prs.yml
Original file line number Diff line number Diff line change
@@ -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
86 changes: 85 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,85 @@
# fastify-supabase
# Supabase Plugin for Fastify

A Fastify plugin to use authenticated Supabase clients in your API.

<a href="https://github.com/psteinroe/fastify-supabase/actions/workflows/ci.yml"><img src="https://github.com/psteinroe/fastify-supabase/actions/workflows/ci.yml/badge.svg?branch=main" alt="Latest build" target="\_parent"></a>
<a href="https://github.com/psteinroe/fastify-supabase"><img src="https://img.shields.io/github/stars/psteinroe/fastify-supabase.svg?style=social&amp;label=Star" alt="GitHub Stars" target="\_parent"></a>

## 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. Thanks to `@fastify/jwt`, you can also access the Supabase `User` object on 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 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.
17 changes: 17 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -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
}
}
}
Binary file added bun.lockb
Binary file not shown.
Loading

0 comments on commit d356a30

Please sign in to comment.