-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
update partykit server, persist to db
- Loading branch information
1 parent
ea98398
commit 4365620
Showing
4 changed files
with
374 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,3 +27,6 @@ dist-ssr | |
|
||
# dev persisted state | ||
.partykit | ||
|
||
# secrets | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,84 @@ | ||
import type * as Party from "partykit/server"; | ||
import { onConnect } from "y-partykit"; | ||
import { createClient } from "@supabase/supabase-js"; | ||
import { Buffer } from "node:buffer"; | ||
import * as Y from "yjs"; | ||
|
||
export default class PlayServer implements Party.Server { | ||
constructor(public room: Party.Room) {} | ||
async onRequest(req: Party.Request) { | ||
const parsedUrl = new URL(req.url); | ||
if (req.method === "GET" && parsedUrl.searchParams.has("dump")) { | ||
const data = await this.room.storage.list(); | ||
const items = [...data.entries()].map(([key, value]) => [ | ||
key, | ||
// @ts-ignore | ||
[...value], | ||
]); | ||
return new Response(JSON.stringify(items)); | ||
} | ||
// Create a single supabase client for interacting with your database | ||
const supabase = createClient( | ||
process.env.SUPABASE_URL as string, | ||
process.env.SUPABASE_KEY as string, | ||
{ auth: { persistSession: false } } | ||
); | ||
|
||
return new Response("Not found"); | ||
} | ||
export default class implements Party.Server { | ||
constructor(public room: Party.Room) {} | ||
|
||
onMessage( | ||
async onMessage( | ||
message: string | ArrayBuffer | ArrayBufferView, | ||
sender: Party.Connection<unknown> | ||
): void | Promise<void> { | ||
): Promise<void> { | ||
if (typeof message === "string") { | ||
this.room.broadcast(message); | ||
} | ||
} | ||
async onConnect(ws: Party.Connection<unknown>) { | ||
// optionally look for events here to filter out valid ones? | ||
return await onConnect(ws, this.room, { | ||
persist: { | ||
mode: "snapshot", | ||
|
||
async onConnect(connection: Party.Connection) { | ||
const room = this.room; | ||
|
||
await onConnect(connection, this.room, { | ||
async load() { | ||
// This is called once per "room" when the first user connects | ||
|
||
// Let's make a Yjs document | ||
const doc = new Y.Doc(); | ||
|
||
// Load the document from the database | ||
const { data, error } = await supabase | ||
.from("documents") | ||
.select("document") | ||
.eq("name", room.id) | ||
.maybeSingle(); | ||
|
||
if (error) { | ||
throw new Error(error.message); | ||
} | ||
|
||
if (data) { | ||
// If the document exists on the database, | ||
// apply it to the Yjs document | ||
Y.applyUpdate( | ||
doc, | ||
new Uint8Array(Buffer.from(data.document, "base64")) | ||
); | ||
} | ||
|
||
// Return the Yjs document | ||
return doc; | ||
}, | ||
callback: { | ||
handler: async (doc) => { | ||
// This is called every few seconds if the document has changed | ||
|
||
// convert the Yjs document to a Uint8Array | ||
const content = Y.encodeStateAsUpdate(doc); | ||
|
||
// Save the document to the database | ||
const { data: _data, error } = await supabase | ||
.from("documents") | ||
.upsert( | ||
{ | ||
name: room.id, | ||
document: Buffer.from(content).toString("base64"), | ||
}, | ||
{ onConflict: "name" } | ||
); | ||
|
||
if (error) { | ||
console.error("failed to save:", error); | ||
} | ||
}, | ||
}, | ||
}); | ||
} | ||
} | ||
|
||
PlayServer satisfies Party.Worker; |
Oops, something went wrong.