@kubun/plugin-p2p 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/context/delegation.js +130 -1
- package/lib/context/group.js +1319 -1
- package/lib/context/hub.js +150 -1
- package/lib/context/join.js +80 -1
- package/lib/context/sync.js +19 -1
- package/lib/context/types.d.ts +3 -3
- package/lib/context/types.js +28 -1
- package/lib/groups/admin-roster.d.ts +130 -0
- package/lib/groups/admin-roster.js +184 -0
- package/lib/groups/broadcast-codec.js +6 -1
- package/lib/groups/broadcast.d.ts +105 -91
- package/lib/groups/broadcast.js +627 -1
- package/lib/groups/circle-projection.d.ts +122 -0
- package/lib/groups/circle-projection.js +288 -0
- package/lib/groups/circle-reducers.d.ts +178 -0
- package/lib/groups/circle-reducers.js +198 -0
- package/lib/groups/events.d.ts +5 -1
- package/lib/groups/events.js +10 -1
- package/lib/groups/group-anchor.d.ts +63 -0
- package/lib/groups/group-anchor.js +107 -0
- package/lib/groups/group-crypto.d.ts +19 -0
- package/lib/groups/group-crypto.js +85 -0
- package/lib/groups/group-handle-registry.d.ts +61 -2
- package/lib/groups/group-handle-registry.js +243 -1
- package/lib/groups/group-handlers.d.ts +29 -0
- package/lib/groups/group-handlers.js +92 -0
- package/lib/groups/group-health-monitor.d.ts +11 -0
- package/lib/groups/group-health-monitor.js +139 -1
- package/lib/groups/group-mls.d.ts +35 -0
- package/lib/groups/group-mls.js +164 -0
- package/lib/groups/group-peer-manager.d.ts +108 -0
- package/lib/groups/group-peer-manager.js +344 -0
- package/lib/groups/group-protocols.d.ts +297 -0
- package/lib/groups/group-protocols.js +174 -0
- package/lib/groups/invite-payload.d.ts +1 -1
- package/lib/groups/invite-payload.js +26 -1
- package/lib/groups/join-utils.d.ts +1 -0
- package/lib/groups/join-utils.js +104 -1
- package/lib/groups/ledger-affected-events.d.ts +15 -0
- package/lib/groups/ledger-affected-events.js +96 -0
- package/lib/groups/ledger-entry.d.ts +37 -0
- package/lib/groups/ledger-entry.js +56 -0
- package/lib/groups/ledger-fold.d.ts +56 -0
- package/lib/groups/ledger-fold.js +53 -0
- package/lib/groups/manager.d.ts +20 -71
- package/lib/groups/manager.js +281 -1
- package/lib/groups/mls-codec.d.ts +1 -1
- package/lib/groups/mls-codec.js +18 -1
- package/lib/groups/mls-encryptor.d.ts +2 -2
- package/lib/groups/mls-encryptor.js +30 -1
- package/lib/groups/mls-group-handle.d.ts +1 -1
- package/lib/groups/mls-group-handle.js +10 -1
- package/lib/groups/mls-json.js +17 -1
- package/lib/groups/mls-receive-errors.d.ts +29 -0
- package/lib/groups/mls-receive-errors.js +42 -0
- package/lib/groups/mls-state.d.ts +1 -1
- package/lib/groups/mls-state.js +56 -1
- package/lib/groups/store-received-grant.d.ts +4 -1
- package/lib/groups/store-received-grant.js +116 -1
- package/lib/groups/store-received-revocation.d.ts +3 -3
- package/lib/groups/store-received-revocation.js +82 -1
- package/lib/hub/ack-backoff.d.ts +22 -0
- package/lib/hub/ack-backoff.js +88 -0
- package/lib/hub/did-observing-transport.d.ts +13 -2
- package/lib/hub/did-observing-transport.js +126 -1
- package/lib/hub/errors.d.ts +0 -6
- package/lib/hub/errors.js +33 -1
- package/lib/hub/http-client.d.ts +28 -3
- package/lib/hub/http-client.js +32 -1
- package/lib/hub/hub-like.d.ts +24 -0
- package/lib/hub/hub-like.js +535 -0
- package/lib/hub/manager.js +198 -1
- package/lib/hub/wiring.d.ts +17 -48
- package/lib/hub/wiring.js +132 -1
- package/lib/index.d.ts +17 -16
- package/lib/index.js +392 -1
- package/lib/protocol.d.ts +1 -1
- package/lib/protocol.js +251 -1
- package/lib/schema.d.ts +2 -1
- package/lib/schema.js +439 -2
- package/lib/sync/authorize.d.ts +1 -1
- package/lib/sync/authorize.js +73 -1
- package/lib/sync/broadcast-queue.js +183 -1
- package/lib/sync/broadcast-sender.js +179 -1
- package/lib/sync/catalog-scope.js +68 -1
- package/lib/sync/errors.d.ts +3 -2
- package/lib/sync/errors.js +19 -1
- package/lib/sync/forwarder.js +277 -1
- package/lib/sync/handlers.js +160 -1
- package/lib/sync/hub-tunnel-sync-listener.d.ts +8 -4
- package/lib/sync/hub-tunnel-sync-listener.js +172 -1
- package/lib/sync/hub-tunnel-sync-provider.d.ts +14 -14
- package/lib/sync/hub-tunnel-sync-provider.js +64 -1
- package/lib/sync/merkle-apply.d.ts +5 -0
- package/lib/sync/merkle-apply.js +194 -1
- package/lib/sync/merkle-channel.d.ts +2 -2
- package/lib/sync/merkle-channel.js +182 -1
- package/lib/sync/merkle-tree.js +120 -1
- package/lib/sync/peer-registry.d.ts +1 -1
- package/lib/sync/peer-registry.js +107 -1
- package/lib/sync/receive-access-gate.js +24 -1
- package/lib/sync/scope-resolver.js +41 -1
- package/lib/sync/sync-client.d.ts +3 -3
- package/lib/sync/sync-client.js +192 -1
- package/lib/sync/sync-manager.d.ts +2 -2
- package/lib/sync/sync-manager.js +272 -1
- package/lib/types.d.ts +11 -0
- package/lib/types.js +2 -1
- package/lib/util/mutex.js +10 -1
- package/lib/utils.js +21 -1
- package/package.json +47 -40
- package/lib/groups/broadcast-service.d.ts +0 -263
- package/lib/groups/broadcast-service.js +0 -1
- package/lib/groups/rejoin-codec.d.ts +0 -14
- package/lib/groups/rejoin-codec.js +0 -1
- package/lib/groups/wire-frame.d.ts +0 -34
- package/lib/groups/wire-frame.js +0 -1
- package/lib/hub/circle-catchup-requester.d.ts +0 -58
- package/lib/hub/circle-catchup-requester.js +0 -1
- package/lib/hub/circle-catchup-responder.d.ts +0 -50
- package/lib/hub/circle-catchup-responder.js +0 -1
- package/lib/hub/connection-pool.d.ts +0 -43
- package/lib/hub/connection-pool.js +0 -1
- package/lib/hub/epoch-stale-detector.d.ts +0 -18
- package/lib/hub/epoch-stale-detector.js +0 -1
- package/lib/hub/forward-remote-broadcast.d.ts +0 -15
- package/lib/hub/forward-remote-broadcast.js +0 -1
- package/lib/hub/group-channel.d.ts +0 -89
- package/lib/hub/group-channel.js +0 -1
- package/lib/hub/hub-connection.d.ts +0 -96
- package/lib/hub/hub-connection.js +0 -1
- package/lib/hub/receive-handler.d.ts +0 -51
- package/lib/hub/receive-handler.js +0 -1
- package/lib/hub/rejoin-manager.d.ts +0 -78
- package/lib/hub/rejoin-manager.js +0 -1
- package/lib/hub/rejoin-responder.d.ts +0 -32
- package/lib/hub/rejoin-responder.js +0 -1
- package/lib/hub/relay-manager.d.ts +0 -142
- package/lib/hub/relay-manager.js +0 -1
- package/lib/hub/send-handler.d.ts +0 -40
- package/lib/hub/send-handler.js +0 -1
- package/lib/hub/tunnel-inbox.d.ts +0 -20
- package/lib/hub/tunnel-inbox.js +0 -1
- package/lib/hub/wait-for-gate.d.ts +0 -14
- package/lib/hub/wait-for-gate.js +0 -1
package/lib/sync/sync-manager.js
CHANGED
|
@@ -1 +1,272 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import { isSigningIdentity } from '@kokuin/token';
|
|
2
|
+
import { getGraphStore } from '@kubun/store-graph';
|
|
3
|
+
import { EventEmitter } from '@sozai/event';
|
|
4
|
+
import { applySyncMutations } from './merkle-apply.js';
|
|
5
|
+
import { buildMerkleTree } from './merkle-tree.js';
|
|
6
|
+
import { PeerRegistry } from './peer-registry.js';
|
|
7
|
+
import { SyncClient } from './sync-client.js';
|
|
8
|
+
export class SyncManager {
|
|
9
|
+
#deployClusters;
|
|
10
|
+
#graph;
|
|
11
|
+
#runtime;
|
|
12
|
+
#logger;
|
|
13
|
+
#peerRegistry;
|
|
14
|
+
#events = new EventEmitter();
|
|
15
|
+
#activeSessions = new Map();
|
|
16
|
+
#lastSyncByPeer = new Map();
|
|
17
|
+
#identity;
|
|
18
|
+
#serverResolver;
|
|
19
|
+
#storeUnreadable;
|
|
20
|
+
#defaultAccessLevel;
|
|
21
|
+
constructor(params){
|
|
22
|
+
this.#deployClusters = params.deployClusters;
|
|
23
|
+
this.#graph = params.graph;
|
|
24
|
+
this.#runtime = params.runtime;
|
|
25
|
+
this.#identity = params.identity;
|
|
26
|
+
this.#logger = params.logger;
|
|
27
|
+
this.#peerRegistry = new PeerRegistry({
|
|
28
|
+
runtime: params.runtime
|
|
29
|
+
});
|
|
30
|
+
this.#serverResolver = params.serverResolver;
|
|
31
|
+
this.#storeUnreadable = params.storeUnreadable ?? 'persist';
|
|
32
|
+
this.#defaultAccessLevel = params.defaultAccessLevel;
|
|
33
|
+
}
|
|
34
|
+
get peerRegistry() {
|
|
35
|
+
return this.#peerRegistry;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Configure the signing identity used for sync operations.
|
|
39
|
+
*/ setIdentity(identity) {
|
|
40
|
+
this.#identity = identity;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Configure the server resolver for direct transport connections.
|
|
44
|
+
*/ setServerResolver(resolver) {
|
|
45
|
+
this.#serverResolver = resolver;
|
|
46
|
+
}
|
|
47
|
+
// ---- Peer management (delegates to PeerRegistry) ----
|
|
48
|
+
async addPeer(params) {
|
|
49
|
+
await this.#peerRegistry.addPeer(params);
|
|
50
|
+
this.#logger.info('Peer added', {
|
|
51
|
+
peerDID: params.config.peerDID
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async removePeer(params) {
|
|
55
|
+
await this.#peerRegistry.removePeer(params);
|
|
56
|
+
this.#logger.info('Peer removed', {
|
|
57
|
+
peerDID: params.peerDID
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async updatePeerConfig(params) {
|
|
61
|
+
await this.#peerRegistry.updatePeer(params);
|
|
62
|
+
this.#logger.info('Peer updated', {
|
|
63
|
+
peerDID: params.peerDID
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async listPeers(params) {
|
|
67
|
+
return this.#peerRegistry.listPeers(params);
|
|
68
|
+
}
|
|
69
|
+
async getPeer(params) {
|
|
70
|
+
return this.#peerRegistry.getPeer(params);
|
|
71
|
+
}
|
|
72
|
+
// ---- Sync orchestration ----
|
|
73
|
+
async merkleSyncWithPeer(params) {
|
|
74
|
+
const { peerDID, scopes, delegationTokens = [], knownModelIDs, direction: requestedDirection } = params;
|
|
75
|
+
this.#logger.info('Starting Merkle sync with peer', {
|
|
76
|
+
peerDID,
|
|
77
|
+
scopes
|
|
78
|
+
});
|
|
79
|
+
const peer = await this.#peerRegistry.getPeer({
|
|
80
|
+
peerDID,
|
|
81
|
+
stores: params.stores
|
|
82
|
+
});
|
|
83
|
+
if (!peer) {
|
|
84
|
+
throw new Error(`Peer ${peerDID} not found`);
|
|
85
|
+
}
|
|
86
|
+
const sessionID = `merkle-sync-${peerDID}-${Date.now()}`;
|
|
87
|
+
const sessionData = {
|
|
88
|
+
peerID: peerDID,
|
|
89
|
+
startTime: Date.now(),
|
|
90
|
+
documentsAttempted: 0,
|
|
91
|
+
documentsCompleted: 0
|
|
92
|
+
};
|
|
93
|
+
this.#activeSessions.set(sessionID, sessionData);
|
|
94
|
+
this.#emitEvent({
|
|
95
|
+
type: 'started',
|
|
96
|
+
peerID: peerDID,
|
|
97
|
+
timestamp: Date.now()
|
|
98
|
+
});
|
|
99
|
+
let client;
|
|
100
|
+
try {
|
|
101
|
+
const identity = this.#identity;
|
|
102
|
+
if (!isSigningIdentity(identity)) {
|
|
103
|
+
throw new Error('Signing identity required for Merkle sync');
|
|
104
|
+
}
|
|
105
|
+
const syncClient = new SyncClient({
|
|
106
|
+
runtime: this.#runtime,
|
|
107
|
+
identity,
|
|
108
|
+
logger: this.#logger,
|
|
109
|
+
serverResolver: this.#serverResolver
|
|
110
|
+
});
|
|
111
|
+
client = await syncClient.connect(peer.endpoint, peerDID);
|
|
112
|
+
// Step 1: Negotiate scopes
|
|
113
|
+
const direction = requestedDirection ?? 'pull';
|
|
114
|
+
this.#logger.info('Negotiating sync scopes', {
|
|
115
|
+
scopes,
|
|
116
|
+
direction
|
|
117
|
+
});
|
|
118
|
+
const { acceptedScopes, excludedDocumentIDs, missingClusters, direction: agreedDirection } = await syncClient.negotiate(client, scopes, delegationTokens, knownModelIDs, direction);
|
|
119
|
+
if (acceptedScopes.length === 0) {
|
|
120
|
+
this.#logger.info('No scopes accepted by peer');
|
|
121
|
+
this.#lastSyncByPeer.set(peerDID, Date.now());
|
|
122
|
+
this.#emitEvent({
|
|
123
|
+
type: 'completed',
|
|
124
|
+
peerID: peerDID,
|
|
125
|
+
timestamp: Date.now()
|
|
126
|
+
});
|
|
127
|
+
this.#activeSessions.delete(sessionID);
|
|
128
|
+
return {
|
|
129
|
+
sessionID,
|
|
130
|
+
divergentBuckets: 0,
|
|
131
|
+
messagesReceived: 0,
|
|
132
|
+
messagesSent: 0,
|
|
133
|
+
missingClusters
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Step 1b: Deploy missing clusters before building merkle tree
|
|
137
|
+
if (missingClusters != null && Object.keys(missingClusters).length > 0) {
|
|
138
|
+
if (this.#deployClusters != null) {
|
|
139
|
+
this.#logger.info('Deploying missing clusters from peer', {
|
|
140
|
+
clusterCount: Object.keys(missingClusters).length
|
|
141
|
+
});
|
|
142
|
+
await this.#deployClusters(missingClusters);
|
|
143
|
+
} else {
|
|
144
|
+
this.#logger.warn('Missing clusters received but no deployClusters callback configured', {
|
|
145
|
+
clusterCount: Object.keys(missingClusters).length
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Step 2: Build local Merkle tree for accepted scopes
|
|
150
|
+
this.#logger.info('Building local Merkle tree', {
|
|
151
|
+
acceptedScopes
|
|
152
|
+
});
|
|
153
|
+
const graphStore = await getGraphStore(params.stores);
|
|
154
|
+
const documentIDs = await graphStore.getDocumentIDsForScope(acceptedScopes, excludedDocumentIDs);
|
|
155
|
+
const localEntries = await graphStore.getMutationLogForDocuments(documentIDs);
|
|
156
|
+
const localTree = buildMerkleTree(localEntries);
|
|
157
|
+
// Step 3: Sync with peer via bidirectional channel
|
|
158
|
+
const syncDirection = agreedDirection ?? direction;
|
|
159
|
+
this.#logger.info('Requesting Merkle sync from peer', {
|
|
160
|
+
localTreeBuckets: Object.keys(localTree.buckets).length,
|
|
161
|
+
direction: syncDirection
|
|
162
|
+
});
|
|
163
|
+
const syncResult = await syncClient.merkleSync(client, {
|
|
164
|
+
scopes: acceptedScopes,
|
|
165
|
+
excludedDocumentIDs,
|
|
166
|
+
localTree,
|
|
167
|
+
direction: syncDirection,
|
|
168
|
+
localEntries,
|
|
169
|
+
// Forward the same delegation tokens used during negotiate so the
|
|
170
|
+
// merkle-sync access gate authorizes the accepted non-owned scopes. A
|
|
171
|
+
// revocation landing between negotiate and sync fails the sync; the
|
|
172
|
+
// retry renegotiates with the updated revocation state.
|
|
173
|
+
delegationTokens
|
|
174
|
+
});
|
|
175
|
+
// Step 4: Apply received mutation JWTs locally
|
|
176
|
+
if (syncResult.mutationJWTs.length > 0) {
|
|
177
|
+
this.#logger.info('Applying sync mutations', {
|
|
178
|
+
mutations: syncResult.mutationJWTs.length
|
|
179
|
+
});
|
|
180
|
+
const applyResult = await applySyncMutations({
|
|
181
|
+
db: params.stores,
|
|
182
|
+
graph: this.#graph,
|
|
183
|
+
mutationJWTs: syncResult.mutationJWTs,
|
|
184
|
+
selfDID: this.#identity.id,
|
|
185
|
+
storeUnreadable: this.#storeUnreadable,
|
|
186
|
+
defaultAccessLevel: this.#defaultAccessLevel
|
|
187
|
+
});
|
|
188
|
+
sessionData.documentsCompleted = applyResult.applied;
|
|
189
|
+
if (applyResult.deferred > 0) {
|
|
190
|
+
this.#logger.info('Deferred sync mutations for retry next round', {
|
|
191
|
+
deferred: applyResult.deferred
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
this.#lastSyncByPeer.set(peerDID, Date.now());
|
|
196
|
+
this.#emitEvent({
|
|
197
|
+
type: 'completed',
|
|
198
|
+
peerID: peerDID,
|
|
199
|
+
timestamp: Date.now()
|
|
200
|
+
});
|
|
201
|
+
this.#logger.info('Merkle sync completed', {
|
|
202
|
+
divergentBuckets: syncResult.divergentBuckets,
|
|
203
|
+
mutationsReceived: syncResult.mutationJWTs.length
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
sessionID,
|
|
207
|
+
divergentBuckets: syncResult.divergentBuckets,
|
|
208
|
+
messagesReceived: syncResult.mutationJWTs.length,
|
|
209
|
+
messagesSent: syncResult.mutationsSent,
|
|
210
|
+
missingClusters
|
|
211
|
+
};
|
|
212
|
+
} catch (error) {
|
|
213
|
+
this.#logger.error('Merkle sync failed', {
|
|
214
|
+
peerDID,
|
|
215
|
+
error
|
|
216
|
+
});
|
|
217
|
+
this.#emitEvent({
|
|
218
|
+
type: 'error',
|
|
219
|
+
peerID: peerDID,
|
|
220
|
+
timestamp: Date.now(),
|
|
221
|
+
error: error instanceof Error ? error.message : String(error)
|
|
222
|
+
});
|
|
223
|
+
throw error;
|
|
224
|
+
} finally{
|
|
225
|
+
if (client != null) {
|
|
226
|
+
try {
|
|
227
|
+
client.abort('SyncComplete');
|
|
228
|
+
await client.dispose();
|
|
229
|
+
} catch {
|
|
230
|
+
// Transport may already be closed
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
this.#activeSessions.delete(sessionID);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// ---- Status ----
|
|
237
|
+
getStatus(params) {
|
|
238
|
+
const { peerDID } = params;
|
|
239
|
+
const sessions = Array.from(this.#activeSessions.values()).filter((s)=>!peerDID || s.peerID === peerDID).map((data)=>({
|
|
240
|
+
peerID: data.peerID,
|
|
241
|
+
startTime: data.startTime,
|
|
242
|
+
documentsAttempted: data.documentsAttempted,
|
|
243
|
+
documentsCompleted: data.documentsCompleted
|
|
244
|
+
}));
|
|
245
|
+
const lastSyncByPeer = {};
|
|
246
|
+
for (const [peer, time] of this.#lastSyncByPeer.entries()){
|
|
247
|
+
if (!peerDID || peer === peerDID) {
|
|
248
|
+
lastSyncByPeer[peer] = time;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
activeSessions: sessions,
|
|
253
|
+
lastSyncByPeer
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// ---- Events ----
|
|
257
|
+
onSyncEvent(callback) {
|
|
258
|
+
return this.#events.on('sync', callback);
|
|
259
|
+
}
|
|
260
|
+
#emitEvent(event) {
|
|
261
|
+
this.#events.emit('sync', event).catch((error)=>{
|
|
262
|
+
this.#logger.error('Error in sync event listener', {
|
|
263
|
+
error
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
// ---- Lifecycle ----
|
|
268
|
+
async dispose() {
|
|
269
|
+
this.#activeSessions.clear();
|
|
270
|
+
this.#lastSyncByPeer.clear();
|
|
271
|
+
}
|
|
272
|
+
}
|
package/lib/types.d.ts
CHANGED
|
@@ -101,6 +101,17 @@ export type GroupRequestContext = {
|
|
|
101
101
|
list: () => Promise<Array<GroupData>>;
|
|
102
102
|
get: (id: string) => Promise<GroupData | null>;
|
|
103
103
|
addMember: (groupID: string, memberDID: string, role: string) => Promise<GroupMemberData>;
|
|
104
|
+
/**
|
|
105
|
+
* Promote a member to admin or demote them back to member by emitting a
|
|
106
|
+
* self-signed `group.role.admin` ledger entry. Authority is rooted at the
|
|
107
|
+
* group's genesis anchor and folded on every peer, so a non-admin caller is
|
|
108
|
+
* rejected and the change converges identically across the group.
|
|
109
|
+
*/
|
|
110
|
+
setMemberRole: (params: {
|
|
111
|
+
groupID: string;
|
|
112
|
+
memberDID: string;
|
|
113
|
+
role: 'admin' | 'member';
|
|
114
|
+
}) => Promise<GroupMemberData>;
|
|
104
115
|
listMembers: (groupID: string) => Promise<Array<GroupMemberData>>;
|
|
105
116
|
createCircle: (params: {
|
|
106
117
|
groupID: string;
|
package/lib/types.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
// ---- Plugin API ----
|
|
2
|
+
export { };
|
package/lib/util/mutex.js
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
|
-
export function createMutex()
|
|
1
|
+
export function createMutex() {
|
|
2
|
+
let tail = Promise.resolve();
|
|
3
|
+
return {
|
|
4
|
+
run (fn) {
|
|
5
|
+
const next = tail.then(()=>fn());
|
|
6
|
+
tail = next.catch(()=>{});
|
|
7
|
+
return next;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/** Node returns a Timeout object with `unref()`; browsers return a number. */ export function unref(timer) {
|
|
2
|
+
;
|
|
3
|
+
timer.unref?.();
|
|
4
|
+
}
|
|
5
|
+
/** Resolve after `ms`, without keeping the process alive. */ export function sleep(ms) {
|
|
6
|
+
return new Promise((resolve)=>{
|
|
7
|
+
const timer = setTimeout(resolve, ms);
|
|
8
|
+
unref(timer);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export function bytesEqual(a, b) {
|
|
12
|
+
if (a.length !== b.length) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
for(let i = 0; i < a.length; i++){
|
|
16
|
+
if (a[i] !== b[i]) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/plugin-p2p",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"license": "see LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -14,54 +14,61 @@
|
|
|
14
14
|
],
|
|
15
15
|
"sideEffects": false,
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@
|
|
18
|
-
"@
|
|
19
|
-
"@
|
|
20
|
-
"@enkaku/
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
23
|
-
"@
|
|
24
|
-
"@
|
|
25
|
-
"@
|
|
26
|
-
"@enkaku/
|
|
27
|
-
"@enkaku/
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
30
|
-
"@enkaku/
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"@enkaku/
|
|
34
|
-
"@
|
|
17
|
+
"@sozai/async": "^0.1.0",
|
|
18
|
+
"@kumiai/broadcast": "^0.1.0",
|
|
19
|
+
"@kokuin/capability": "^0.1.0",
|
|
20
|
+
"@enkaku/client": "^0.18.1",
|
|
21
|
+
"@sozai/codec": "^0.1.0",
|
|
22
|
+
"@sozai/event": "^0.1.0",
|
|
23
|
+
"@sozai/generator": "^0.1.0",
|
|
24
|
+
"@kumiai/mls": "^0.1.0",
|
|
25
|
+
"@kumiai/rpc": "^0.1.0",
|
|
26
|
+
"@enkaku/http-fetch": "^0.18.1",
|
|
27
|
+
"@enkaku/http-serve": "^0.18.1",
|
|
28
|
+
"@kumiai/hub-protocol": "^0.1.0",
|
|
29
|
+
"@kumiai/hub-tunnel": "^0.1.0",
|
|
30
|
+
"@enkaku/protocol": "^0.18.1",
|
|
31
|
+
"@sozai/runtime": "^0.1.0",
|
|
32
|
+
"@sozai/schema": "^0.1.0",
|
|
33
|
+
"@enkaku/server": "^0.18.1",
|
|
34
|
+
"@sozai/stream": "^0.1.0",
|
|
35
|
+
"@kokuin/token": "^0.1.1",
|
|
36
|
+
"@enkaku/transport": "^0.18.1",
|
|
35
37
|
"@noble/hashes": "^2.2.0",
|
|
36
38
|
"graphql": "^16.14.2",
|
|
37
39
|
"kysely": "^0.29.2",
|
|
38
|
-
"
|
|
39
|
-
"@kubun/db
|
|
40
|
-
"@kubun/db": "^0.
|
|
41
|
-
"@kubun/
|
|
42
|
-
"@kubun/
|
|
43
|
-
"@kubun/
|
|
44
|
-
"@kubun/
|
|
45
|
-
"@kubun/
|
|
46
|
-
"@kubun/
|
|
47
|
-
"@kubun/
|
|
48
|
-
"@kubun/
|
|
49
|
-
"@kubun/
|
|
40
|
+
"ts-mls": "2.0.0-rc.13",
|
|
41
|
+
"@kubun/db": "^0.11.0",
|
|
42
|
+
"@kubun/db-adapter": "^0.11.0",
|
|
43
|
+
"@kubun/graphql": "^0.11.0",
|
|
44
|
+
"@kubun/hlc": "^0.11.0",
|
|
45
|
+
"@kubun/engine": "^0.11.0",
|
|
46
|
+
"@kubun/http-util": "^0.11.0",
|
|
47
|
+
"@kubun/logger": "^0.11.0",
|
|
48
|
+
"@kubun/client": "^0.11.0",
|
|
49
|
+
"@kubun/id": "^0.11.0",
|
|
50
|
+
"@kubun/mutation": "^0.11.0",
|
|
51
|
+
"@kubun/store-graph": "^0.11.0",
|
|
52
|
+
"@kubun/protocol": "^0.11.0",
|
|
53
|
+
"@kubun/store-delegation": "^0.11.0",
|
|
54
|
+
"@kubun/store-p2p": "^0.11.0"
|
|
50
55
|
},
|
|
51
56
|
"devDependencies": {
|
|
52
|
-
"@
|
|
57
|
+
"@kumiai/hub-server": "^0.1.0",
|
|
58
|
+
"@testcontainers/postgresql": "^12.0.4",
|
|
53
59
|
"get-port": "^7.2.0",
|
|
54
|
-
"@kubun/db-better-sqlite": "^0.
|
|
55
|
-
"@kubun/
|
|
56
|
-
"@kubun/plugin-connector": "^0.
|
|
57
|
-
"@kubun/db-
|
|
58
|
-
"@kubun/plugin-
|
|
59
|
-
"@kubun/plugin-
|
|
60
|
-
"@kubun/
|
|
60
|
+
"@kubun/db-better-sqlite": "^0.11.0",
|
|
61
|
+
"@kubun/db-node-sqlite": "^0.11.0",
|
|
62
|
+
"@kubun/plugin-connector": "^0.11.0",
|
|
63
|
+
"@kubun/db-postgres": "^0.11.0",
|
|
64
|
+
"@kubun/plugin-rpc": "^0.11.0",
|
|
65
|
+
"@kubun/plugin-http": "^0.11.0",
|
|
66
|
+
"@kubun/hub": "^0.11.0",
|
|
67
|
+
"@kubun/test-utils": "^0.11.0"
|
|
61
68
|
},
|
|
62
69
|
"scripts": {
|
|
63
70
|
"build:clean": "del lib",
|
|
64
|
-
"build:js": "swc src -d ./lib --config-file ../../swc.json --strip-leading-paths",
|
|
71
|
+
"build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
65
72
|
"build:types": "tsc --emitDeclarationOnly --skipLibCheck",
|
|
66
73
|
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
|
|
67
74
|
"test:types": "tsc --noEmit -p tsconfig.test.json",
|