-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor types * add ref: eventemitter3 * remove rxjs (reimplemented with EventEmitter) * Create ci.node.yml * placeholder test * add CI bade to README * Create CHANGELOG.md
- Loading branch information
1 parent
ecad9b9
commit 0f546a8
Showing
10 changed files
with
302 additions
and
19 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 |
---|---|---|
@@ -0,0 +1,30 @@ | ||
name: ci.node | ||
|
||
on: | ||
push: | ||
branches: ["main"] | ||
pull_request: | ||
branches: ["main"] | ||
|
||
jobs: | ||
build: | ||
name: node.ci | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
node-version: [20.x] | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v3 | ||
|
||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
cache: "yarn" | ||
|
||
- run: yarn install | ||
- run: yarn audit | ||
- run: yarn build | ||
- run: yarn test |
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 |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Change Log | ||
All notable changes to this project will be documented in this file. | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
|
||
## [Unreleased] - YYYY-MM-DD | ||
#### Added | ||
#### Changed | ||
#### Deprecated | ||
#### Removed | ||
#### Fixed | ||
#### Security | ||
|
||
|
||
|
||
## [0.0.1] - YYYY-MM-DD | ||
#### Added | ||
- Setup initial project structure. | ||
- Copied over from [source](https://github.com/cellplatform/platform-0.2.0/tree/main/code/ext/ext.lib.automerge.webrtc/src/Store.Network.WebrtcAdapter) monorepo. | ||
- Setup CI/CD. | ||
#### Changed | ||
#### Deprecated | ||
#### Removed | ||
#### Fixed | ||
#### Security | ||
|
||
|
||
|
||
|
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
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 |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { describe, expect, it } from "vitest"; | ||
|
||
describe("NetworkAdapter", () => { | ||
it("placeholder", () => { | ||
expect(123).to.eql(123); | ||
}); | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { NetworkAdapter } from "@automerge/automerge-repo"; | ||
import { EventEmitter } from "eventemitter3"; | ||
import type * as t from "./t.js"; | ||
|
||
/** | ||
* An Automerge repo network-adapter for WebRTC (P2P) | ||
* | ||
* Based on: | ||
* MessageChannelNetworkAdapter (point-to-point) | ||
* https://github.com/automerge/automerge-repo/blob/main/packages/automerge-repo-network-messagechannel/src/index.ts | ||
* | ||
*/ | ||
export class WebrtcNetworkAdapter extends NetworkAdapter { | ||
#conn: t.DataConnection; | ||
#isReady = false; | ||
#disconnected = new EventEmitter<"disconnected">(); | ||
|
||
constructor(conn: t.DataConnection) { | ||
if (!conn) throw new Error(`A peerjs data-connection is required`); | ||
super(); | ||
this.#conn = conn; | ||
} | ||
|
||
connect(peerId: t.PeerId) { | ||
const senderId = (this.peerId = peerId); | ||
const conn = this.#conn; | ||
|
||
const handleOpen = () => this.#transmit({ type: "arrive", senderId, peerMetadata: {} }); | ||
const handleClose = () => this.emit("close"); | ||
const handleData = (e: any) => { | ||
const msg = e as t.WebrtcMessage; | ||
|
||
/** | ||
* Arrive. | ||
*/ | ||
if (msg.type === "arrive") { | ||
const { peerMetadata } = msg as t.ArriveMessage; | ||
const targetId = msg.senderId; | ||
this.#transmit({ type: "welcome", senderId, targetId, peerMetadata }); | ||
this.#announceConnection(targetId, peerMetadata); | ||
return; | ||
} | ||
|
||
/** | ||
* Welcome. | ||
*/ | ||
if (msg.type === "welcome") { | ||
const { peerMetadata } = msg as t.WelcomeMessage; | ||
this.#announceConnection(msg.senderId, peerMetadata); | ||
return; | ||
} | ||
|
||
/** | ||
* Default (data payload). | ||
*/ | ||
let payload = msg as t.Message; | ||
if ("data" in msg) payload = { ...payload, data: toUint8Array(msg.data!) }; | ||
this.emit("message", payload); | ||
}; | ||
|
||
conn.on("open", handleOpen); | ||
conn.on("close", handleClose); | ||
conn.on("data", handleData); | ||
|
||
this.#disconnected.on("disconnected", () => { | ||
this.#isReady = false; | ||
conn.off("open", handleOpen); | ||
conn.off("close", handleClose); | ||
conn.off("data", handleData); | ||
}); | ||
|
||
/** | ||
* Mark this channel as ready after 100ms, at this point there | ||
* must be something weird going on at the other end to cause us | ||
* to receive no response. | ||
*/ | ||
setTimeout(() => this.#setAsReady(), 100); | ||
} | ||
|
||
disconnect() { | ||
this.#disconnected.emit("disconnected"); | ||
} | ||
|
||
send(message: t.RepoMessage) { | ||
if (!this.#conn) throw new Error("Connection not ready"); | ||
if ("data" in message) { | ||
this.#transmit({ ...message, data: toUint8Array(message.data) }); | ||
} else { | ||
this.#transmit(message); | ||
} | ||
} | ||
|
||
#transmit(message: t.WebrtcMessage) { | ||
if (!this.#conn) throw new Error("Connection not ready"); | ||
this.#conn.send(message); | ||
} | ||
|
||
#setAsReady() { | ||
if (this.#isReady) return; | ||
this.#isReady = true; | ||
this.emit("ready", { network: this }); | ||
} | ||
|
||
#announceConnection(peerId: t.PeerId, peerMetadata: t.PeerMetadata) { | ||
this.#setAsReady(); | ||
this.emit("peer-candidate", { peerId, peerMetadata }); | ||
} | ||
} | ||
|
||
/** | ||
* Helpers | ||
*/ | ||
function toUint8Array(input: Uint8Array): Uint8Array { | ||
return input instanceof Uint8Array ? input : new Uint8Array(input); | ||
} |
This file was deleted.
Oops, something went wrong.
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,5 +1 @@ | ||
console.log("index.ts"); | ||
|
||
export function sum(a: number, b: number) { | ||
return a + b; | ||
} | ||
export { WebrtcNetworkAdapter } from "./NetworkAdapter.js"; |
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 |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/** | ||
* @automerge | ||
*/ | ||
import type { Message, PeerId, RepoMessage, StorageId } from "@automerge/automerge-repo"; | ||
export { Message, PeerId, RepoMessage }; | ||
|
||
/** | ||
* @peerjs | ||
*/ | ||
export type { DataConnection } from "peerjs"; | ||
|
||
/** | ||
* @internal | ||
* Based on: | ||
* MessageChannelNetworkAdapter | ||
* https://github.com/automerge/automerge-repo/blob/main/packages/automerge-repo-network-messagechannel/src/index.ts | ||
*/ | ||
export type IODirection = "incoming" | "outgoing"; | ||
|
||
export type WebrtcMessage = ArriveMessage | WelcomeMessage | Message; | ||
export type WebrtcMessageAlert = { | ||
direction: IODirection; | ||
message: WebrtcMessage; | ||
}; | ||
|
||
/** | ||
* Describes a peer intent to the system | ||
* storageId: the key for syncState to decide what the other peer already has | ||
* isEphemeral: to decide if we bother recording this peer's sync state | ||
*/ | ||
export interface PeerMetadata { | ||
storageId?: StorageId; | ||
isEphemeral?: boolean; | ||
} | ||
|
||
/** | ||
* Notify the network that we have arrived so everyone knows our peer ID | ||
*/ | ||
export type ArriveMessage = { | ||
type: "arrive"; | ||
|
||
/** The peer ID of the sender of this message */ | ||
senderId: PeerId; | ||
|
||
/** Arrive messages don't have a targetId */ | ||
targetId?: never; | ||
|
||
/** The peer metadata of the sender of this message */ | ||
peerMetadata: PeerMetadata; | ||
}; | ||
|
||
/** | ||
* Respond to an arriving peer with our peer ID | ||
*/ | ||
export type WelcomeMessage = { | ||
type: "welcome"; | ||
|
||
/** The peer ID of the recipient sender this message */ | ||
senderId: PeerId; | ||
|
||
/** The peer ID of the recipient of this message */ | ||
targetId: PeerId; | ||
|
||
/** The peer metadata of the sender of this message */ | ||
peerMetadata: PeerMetadata; | ||
}; |
Oops, something went wrong.