Skip to content

Commit

Permalink
s/this.id/this.room, added some docs
Browse files Browse the repository at this point in the history
  • Loading branch information
threepointone committed May 28, 2024
1 parent ff3855e commit 7f86d79
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 27 deletions.
5 changes: 5 additions & 0 deletions .changeset/rude-paws-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"partyflare": patch
---

s/this.id/this.room, added some docs
3 changes: 3 additions & 0 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ jobs:
- name: Modify package.json version
run: bun .github/version-script.js

- run: bun run copy-readme

- run: bun run build

- run: bun run check

- run: npm publish --tag beta
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:

- run: bun install

- run: bun run copy-readme

- run: bun run build

- id: changesets
Expand Down
Empty file removed .prettierignore
Empty file.
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
> [!CAUTION]
> Experimental early work, not recommended for production use.
## partyflare

A lightweight api for durable objects, inspired by [PartyKit](https://www.partykit.io/).
Expand All @@ -9,15 +12,48 @@ npm install partyflare
```ts
import { Party } from "partyflare";

// define any durable objects you want to use
export class MyParty extends Party {
onConnect(connection) {
console.log("connected", connection.id);
console.log("connected", connection.id, "to room", this.room);
}
onMessage(connection, message) {
console.log("message", connection.id, message);
// send the message to all connections
this.broadcast(
message,
/* optionally exclude any connections that shouldn't recieve the message */
[connection.id]
);
}
}

export default {
fetch(req: Request, env) {
// setup your fetch handler to use configured parties
fetch(request, env) {
return Party.match(req, env) || new Response("Not Found", { status: 404 });
}
};
```

## Overrides on `Party`

You can override the following methods on `Party` to add custom behavior:

#### Lifecycle hooks: (all optionally `async`)

- `onStart()` - when the party is started for the first time (or or waking up after hibernating)
- `onConnect(connection, connContext)` - when a new connection is established
- `onMessage(connection, message)` - when a message is received from a connection
- `onClose(connection, code, reason, wasClean)` - when a connection is closed
- `onError(error)` - when an error occurs on a connection
- `onRequest(request): Response` - when a request is received from the fetch handler
- `getConnectionTags(connection, connContext)` - return an array of tags for a connection

## `Party.match(request, env)`

This is a static method on `Party` that will return a `Response` if the request matches a party, or `null` if no party matches. This is useful for defining multiple parties in a single script.

It's default behaviour is to match a url that looks like `/parties/:party/:name` to a party named `:party`, and use `:name` as the room name.

You can override this behavior by [TODO].
2 changes: 1 addition & 1 deletion examples/chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"description": "",
"main": "index.js",
"scripts": {
"dev": "wrangler dev"
"start": "wrangler dev"
},
"keywords": [],
"author": "",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"check:lint": "eslint \"**/*.[tj]s?(x)\" --max-warnings=0 --report-unused-disable-directives",
"check:repo": "manypkg check",
"check:type": "find . -name 'tsconfig.json' -not -path '*/node_modules/*' -print0 | xargs -0 -I {} bash -c 'echo \"tsc --project {}\"; tsc --project {} || exit 255' || exit 1",
"copy-readme": "cp README.md packages/partyflare/README.md",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
Expand Down
41 changes: 19 additions & 22 deletions packages/partyflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ function assert(condition: unknown, message: string): asserts condition {

export type WSMessage = ArrayBuffer | ArrayBufferView | string;

function getRoomAndPartyNameFromUrl(url: URL) {
// /parties/:name/:id
function getPartyAndRoomFromUrl(url: URL) {
// /parties/:party/:name
const parts = url.pathname.split("/");
if (parts[0] === "parties" && parts.length < 3) {
return null;
Expand Down Expand Up @@ -89,7 +89,7 @@ export class Party<Env> extends DurableObject<Env> {
return acc;
}, {});

const roomDetails = getRoomAndPartyNameFromUrl(new URL(req.url));
const roomDetails = getPartyAndRoomFromUrl(new URL(req.url));
if (!roomDetails) {
return null;
} else {
Expand All @@ -108,15 +108,15 @@ export class Party<Env> extends DurableObject<Env> {
connectionManager: ConnectionManager;
ParentClass: typeof Party;

#_id: string | undefined;
get id(): string {
if (!this.#_id) {
#_room: string | undefined;
get room(): string {
if (!this.#_room) {
throw new Error("This party has not been initialised yet.");
}
return this.#_id;
return this.#_room;
}
set id(id: string) {
this.#_id = id;
set room(room: string) {
this.#_room = room;
}

constructor(ctx: DurableObjectState, env: Env) {
Expand All @@ -127,7 +127,6 @@ export class Party<Env> extends DurableObject<Env> {
? new HibernatingConnectionManager(ctx)
: new InMemoryConnectionManager();
}
// implemented
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);

Expand Down Expand Up @@ -155,7 +154,7 @@ export class Party<Env> extends DurableObject<Env> {

let connection: Connection = Object.assign(serverWebSocket, {
id: connectionId,
room: this.id,
room: this.room,
state: null as unknown as ConnectionState<unknown>,
setState<T = unknown>(setState: T | ConnectionSetStateFn<T>) {
let state: T;
Expand All @@ -178,7 +177,7 @@ export class Party<Env> extends DurableObject<Env> {
// Accept the websocket connection
connection = this.connectionManager.accept(connection, {
tags,
room: this.id
room: this.room
});

if (!this.ParentClass.options.hibernate) {
Expand Down Expand Up @@ -227,23 +226,21 @@ export class Party<Env> extends DurableObject<Env> {
return this.onError(connection, error);
}

// async alarm(): void | Promise<void> {}

async #initializeFromRequest(req: Request) {
const roomId = this.getRoomFromRequest(req);
const room = this.#getRoomFromRequest(req);

assert(roomId, "No room details found in request");
assert(room, "No room details found in request");

this.id = roomId;
this.room = room;
this.#initialized = true;
await this.onStart();
}

async #initializeFromConnection(connection: Connection) {
const roomId = this.getRoomFromConnection(connection);
assert(roomId, "No room details found in request");
const room = this.#getRoomFromConnection(connection);
assert(room, "No room details found in request");

this.id = roomId;
this.room = room;
this.#initialized = true;
await this.onStart();
}
Expand Down Expand Up @@ -346,7 +343,7 @@ export class Party<Env> extends DurableObject<Env> {
return new Response("Not Found", { status: 404 });
}

getRoomFromRequest(req: Request): string {
#getRoomFromRequest(req: Request): string {
// get the room from the request
// headers: x-partyflare-room

Expand All @@ -358,7 +355,7 @@ export class Party<Env> extends DurableObject<Env> {

return room;
}
getRoomFromConnection(connection: Connection): string {
#getRoomFromConnection(connection: Connection): string {
return connection.room;
}
}
4 changes: 2 additions & 2 deletions packages/partyflare/src/tests/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ export class Stateful extends Party<Env> {
): void | Promise<void> {
connection.send(
JSON.stringify({
id: this.id
room: this.room
})
);
}
onRequest(
_request: Request<unknown, CfProperties<unknown>>
): Response | Promise<Response> {
return Response.json({
id: this.id
room: this.room
});
}
}
Expand Down

0 comments on commit 7f86d79

Please sign in to comment.