-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsync.js
More file actions
99 lines (94 loc) · 2.67 KB
/
Copy pathsync.js
File metadata and controls
99 lines (94 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/* ==============================================
* SYNC — instantdb-shaped (<=50 col house)
* ----------------------------------------------
* We do NOT hard-depend on InstantDB. We depend
* on its SHAPE: { publish(event), subscribe(cb) }
* Inject a real one in prod, a fake in tests.
*
* Model (v0): everything is PUBLIC. Every event
* is broadcast to every node. A node ingests any
* event it has not seen, skipping its own echoes
* via event._origin. Ordering is best-effort;
* real vector clocks come later. Keep it simple.
*
* Two adapters, one shape:
* inMemorySync(bus) offline / test / demo
* instantAdminSync(cfg) live @instantdb/admin
* ============================================ */
'use strict';
// ---- a shared in-process bus (many nodes) ------
// This is the "network" for local multi-node demos
// and offline mode. It just keeps a public log and
// fans new events out to every listener.
function createBus() {
const log = [];
const listeners = new Set();
return {
log,
push(event) {
log.push(event);
listeners.forEach(fn => fn(event));
},
on(fn) { listeners.add(fn); return () =>
listeners.delete(fn); },
};
}
// ---- adapter: in-memory (offline/test/demo) ----
function inMemorySync(bus) {
return {
publish: event => bus.push(event),
subscribe: cb => {
// replay backlog, then stream live
for (const e of bus.log) cb(e);
return bus.on(cb);
},
};
}
// ---- adapter: live InstantDB admin (prod) ------
// Lazy-requires @instantdb/admin so this file
// loads fine when the package is absent. Wire your
// appId + adminToken to go live. This is the SHAPE;
// namespace/query names are placeholders to confirm
// once we read the instant admin docs/submodule.
function instantAdminSync(cfg) {
let db;
function open() {
if (db) return db;
let init;
try { init = require('@instantdb/admin').init; }
catch (e) {
throw new Error(
'install @instantdb/admin to go live');
}
db = init({
appId: cfg.appId,
adminToken: cfg.adminToken,
});
return db;
}
return {
publish: async event => {
const d = open();
await d.transact(
d.tx.events[event._id].update({
json: JSON.stringify(event),
origin: event._origin,
at: event._at,
}));
},
subscribe: cb => {
const d = open();
return d.subscribeQuery(
{ events: {} },
res => {
const rows = (res.data &&
res.data.events) || [];
for (const r of rows)
cb(JSON.parse(r.json));
});
},
};
}
module.exports = {
createBus, inMemorySync, instantAdminSync,
};