Skip to content

Commit bfa883b

Browse files
committed
📝 update documentation
1 parent cf32b1f commit bfa883b

File tree

3 files changed

+172
-7
lines changed

3 files changed

+172
-7
lines changed

README.md

+170-5
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,179 @@ A library for developing offline-first web applications based on async data repl
1818
- [ ] Method for initial sync and cleanup of bad entries
1919
- [ ] Can we make it possible to sync to a file system, check: https://github.com/streetwriters/notesnook/tree/master/packages/streamable-fs
2020

21-
## Examples
21+
# Examples
22+
23+
<details>
2224

2325
For usage take a look at the `src/examples` directory which has examples for:
2426

25-
1. `src/example/websocket-server` - A Node.js erver using an in-memory db and the websocket interfaces
26-
2. `src/example/websocket-client-produce` - A Node.js client using the `WebsocketNodeJSConnector` that produces and replicates data from the server
27-
3. `src/example/websocket-client-watch` - A Node.js client using the `WebsocketNodeJSConnector` that replicates data from the server
28-
4. `src/example/browser` - Browser app using the `IndexedDBStore` and `WebsocketClientConnector`
27+
1. `pnpm run example:server` - Example can be found in `src/example/websocket-server` - A Node.js erver using an in-memory db and the websocket interfaces
28+
29+
```ts
30+
import { InMemoryOwnedStore } from "@sftsrv/synk/in-memory"
31+
import { WebSocket, WebSocketServer } from "ws"
32+
import { Changes } from "../types"
33+
import { Notify } from "../async/types"
34+
import { Data } from "./types"
35+
36+
let connections: WebSocket[] = []
37+
38+
const Command = Changes(Data)
39+
40+
const db = new InMemoryOwnedStore<Data>()
41+
db.put({
42+
version: 0,
43+
type: "user",
44+
id: "initial",
45+
name: "initial user",
46+
age: 5,
47+
})
48+
49+
const wss = new WebSocketServer({ port: 8080 }, () =>
50+
console.log("Server Listening")
51+
)
52+
53+
wss.on("connection", (ws) => {
54+
connections.push(ws)
55+
56+
ws.on("message", (data) => {
57+
const message = Command.safeParse(JSON.parse(data.toString()))
58+
if (!message.success) {
59+
console.error(message.error)
60+
return
61+
}
62+
63+
console.log(message)
64+
65+
const command = message.data
66+
67+
db.applyChanges(command)
68+
const changes = db.getChanges(command.version)
69+
const newVersion = db.getVersion()
70+
71+
console.log("changes to client", changes)
72+
73+
// send latest data to the client that submitted the change
74+
ws.send(JSON.stringify(changes))
75+
76+
// send a notification to all other clients that there is new data available
77+
const notify: Notify = {
78+
type: "notify",
79+
version: newVersion,
80+
}
81+
82+
connections.forEach((conn) => conn.send(JSON.stringify(notify)))
83+
})
84+
85+
ws.on("open", () => {
86+
console.log("open")
87+
connections.push(ws)
88+
})
89+
90+
ws.on("close", () => {
91+
console.log("closed")
92+
connections = connections.filter((conn) => conn !== ws)
93+
})
94+
95+
ws.on("error", (err) => {
96+
console.log(err)
97+
connections = connections.filter((conn) => conn !== ws)
98+
})
99+
})
100+
```
101+
102+
2. `pnpm run example:client-produce` - Example can be found in `src/example/websocket-client-produce` - A Node.js client using the `WebsocketNodeJSConnector` that produces and replicates data from the server
103+
104+
```ts
105+
import { WebsocketNodeJSClientConnector } from "@sftsrv/synk/websocket"
106+
import { InMemoryReplicatedStore } from "@sftsrv/synk/in-memory"
107+
import WebSocket from "ws"
108+
import { Data } from "./types"
109+
110+
const ws = new WebSocket("ws://localhost:8080")
111+
const db = new InMemoryReplicatedStore<Data>()
112+
113+
const connector = new WebsocketNodeJSClientConnector(db, ws, console.log, Data)
114+
115+
setInterval(() => {
116+
connector.putOne({
117+
type: "post",
118+
id: Date.now().toString(),
119+
version: db.getVersion(),
120+
userId: "1",
121+
content: "some content",
122+
})
123+
}, 5000)
124+
```
125+
126+
3. `pnpm run example:client-watch` - Example can be found in `src/example/websocket-client-watch` - A Node.js client using the `WebsocketNodeJSConnector` that replicates data from the server
127+
128+
```ts
129+
import { InMemoryReplicatedStore } from "@sftsrv/synk/in-memory"
130+
import { WebsocketNodeJSClientConnector } from "@sftsrv/synk/websocket"
131+
import WebSocket from "ws"
132+
import { Data } from "./types"
133+
134+
const ws = new WebSocket("ws://localhost:8080")
135+
const db = new InMemoryReplicatedStore<Data>()
136+
137+
const connector = new WebsocketNodeJSClientConnector(db, ws, console.log, Data)
138+
```
139+
140+
4. `pnpm run example:client-browser` - Example can be found in `src/example/browser` - Browser app using the `IndexedDBStore` and `WebsocketClientConnector`
141+
142+
```ts
143+
import { IndexedDBStore } from "@sftsrv/synk/indexed-db"
144+
import { WebsocketClientConnector } from "@sftsrv/synk/websocket"
145+
import { Data } from "../types"
146+
147+
const changes = document.getElementById("changes") as HTMLDivElement
148+
const database = document.getElementById("database") as HTMLDivElement
149+
const add = document.getElementById("add") as HTMLButtonElement
150+
const dlt = document.getElementById("delete") as HTMLButtonElement
151+
const input = document.getElementById("input") as HTMLInputElement
152+
153+
const main = async () => {
154+
console.log("Starting")
155+
const db = new IndexedDBStore<Data>("my-store")
156+
157+
const ws = new WebSocket("ws://localhost:8080")
158+
159+
const connector = new WebsocketClientConnector<Data>(db, ws, async (data) => {
160+
const version = await db.getVersion()
161+
const store = await db.getAll()
162+
changes.innerHTML = JSON.stringify(data, null, 2)
163+
database.innerHTML = JSON.stringify({ version, store }, null, 2)
164+
})
165+
166+
add.addEventListener("click", async () => {
167+
connector.putOne({
168+
version: await db.getVersion(),
169+
type: "user",
170+
id: new Date().toString(),
171+
name: input.value || "",
172+
age: Date.now(),
173+
})
174+
175+
input.value = ""
176+
})
177+
178+
dlt.addEventListener("click", async () => {
179+
const data = await db.getAll()
180+
const first = await data[0]
181+
182+
if (!first) {
183+
return
184+
}
185+
186+
await connector.delete(first)
187+
})
188+
}
189+
190+
main()
191+
```
192+
193+
</details>
29194

30195
> Running any client example requires the server to also be running, the relevant commands for running the examples can be found in the `package.json` file
31196

jsr.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://jsr.io/schema/config-file.v1.json",
33
"name": "@sftsrv/synk",
4-
"version": "0.0.4",
4+
"version": "0.0.5",
55
"exports": {
66
".": "./dist/index.js",
77
"./in-memory": "./dist/in-memory/index.js",

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sftsv/synk",
3-
"version": "0.0.3",
3+
"version": "0.0.5",
44
"description": "A library for developing offline-first web applications based on async data replication and synchronization between clients and the server",
55
"type": "commonjs",
66
"module": "dist/index.js",

0 commit comments

Comments
 (0)