@docukit/docsync 0.0.1-alpha.1

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.
Files changed (76) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +1 -0
  3. package/dist/src/client/index.d.ts +158 -0
  4. package/dist/src/client/index.d.ts.map +1 -0
  5. package/dist/src/client/index.js +832 -0
  6. package/dist/src/client/index.js.map +1 -0
  7. package/dist/src/client/providers/indexeddb.d.ts +15 -0
  8. package/dist/src/client/providers/indexeddb.d.ts.map +1 -0
  9. package/dist/src/client/providers/indexeddb.js +79 -0
  10. package/dist/src/client/providers/indexeddb.js.map +1 -0
  11. package/dist/src/exports/client.d.ts +4 -0
  12. package/dist/src/exports/client.d.ts.map +1 -0
  13. package/dist/src/exports/client.js +3 -0
  14. package/dist/src/exports/client.js.map +1 -0
  15. package/dist/src/exports/docnode.d.ts +2 -0
  16. package/dist/src/exports/docnode.d.ts.map +1 -0
  17. package/dist/src/exports/docnode.js +2 -0
  18. package/dist/src/exports/docnode.js.map +1 -0
  19. package/dist/src/exports/index.d.ts +3 -0
  20. package/dist/src/exports/index.d.ts.map +1 -0
  21. package/dist/src/exports/index.js +3 -0
  22. package/dist/src/exports/index.js.map +1 -0
  23. package/dist/src/exports/server.d.ts +5 -0
  24. package/dist/src/exports/server.d.ts.map +1 -0
  25. package/dist/src/exports/server.js +4 -0
  26. package/dist/src/exports/server.js.map +1 -0
  27. package/dist/src/exports/testing.d.ts +7 -0
  28. package/dist/src/exports/testing.d.ts.map +1 -0
  29. package/dist/src/exports/testing.js +6 -0
  30. package/dist/src/exports/testing.js.map +1 -0
  31. package/dist/src/server/cli.d.ts +2 -0
  32. package/dist/src/server/cli.d.ts.map +1 -0
  33. package/dist/src/server/cli.js +10 -0
  34. package/dist/src/server/cli.js.map +1 -0
  35. package/dist/src/server/index.d.ts +37 -0
  36. package/dist/src/server/index.d.ts.map +1 -0
  37. package/dist/src/server/index.js +450 -0
  38. package/dist/src/server/index.js.map +1 -0
  39. package/dist/src/server/providers/memory.d.ts +17 -0
  40. package/dist/src/server/providers/memory.d.ts.map +1 -0
  41. package/dist/src/server/providers/memory.js +72 -0
  42. package/dist/src/server/providers/memory.js.map +1 -0
  43. package/dist/src/server/providers/postgres/drizzle.config.d.ts +3 -0
  44. package/dist/src/server/providers/postgres/drizzle.config.d.ts.map +1 -0
  45. package/dist/src/server/providers/postgres/drizzle.config.js +10 -0
  46. package/dist/src/server/providers/postgres/drizzle.config.js.map +1 -0
  47. package/dist/src/server/providers/postgres/index.d.ts +6 -0
  48. package/dist/src/server/providers/postgres/index.d.ts.map +1 -0
  49. package/dist/src/server/providers/postgres/index.js +83 -0
  50. package/dist/src/server/providers/postgres/index.js.map +1 -0
  51. package/dist/src/server/providers/postgres/schema.d.ts +159 -0
  52. package/dist/src/server/providers/postgres/schema.d.ts.map +1 -0
  53. package/dist/src/server/providers/postgres/schema.js +34 -0
  54. package/dist/src/server/providers/postgres/schema.js.map +1 -0
  55. package/dist/src/shared/debounce.d.ts +2 -0
  56. package/dist/src/shared/debounce.d.ts.map +1 -0
  57. package/dist/src/shared/debounce.js +10 -0
  58. package/dist/src/shared/debounce.js.map +1 -0
  59. package/dist/src/shared/docBinding.d.ts +17 -0
  60. package/dist/src/shared/docBinding.d.ts.map +1 -0
  61. package/dist/src/shared/docBinding.js +41 -0
  62. package/dist/src/shared/docBinding.js.map +1 -0
  63. package/dist/src/shared/throttle.d.ts +30 -0
  64. package/dist/src/shared/throttle.d.ts.map +1 -0
  65. package/dist/src/shared/throttle.js +51 -0
  66. package/dist/src/shared/throttle.js.map +1 -0
  67. package/dist/src/shared/types.d.ts +387 -0
  68. package/dist/src/shared/types.d.ts.map +1 -0
  69. package/dist/src/shared/types.js +6 -0
  70. package/dist/src/shared/types.js.map +1 -0
  71. package/dist/src/shared/utils.d.ts +2 -0
  72. package/dist/src/shared/utils.d.ts.map +1 -0
  73. package/dist/src/shared/utils.js +11 -0
  74. package/dist/src/shared/utils.js.map +1 -0
  75. package/dist/tsconfig.build.tsbuildinfo +1 -0
  76. package/package.json +68 -0
@@ -0,0 +1,450 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
2
+ import { Server } from "socket.io";
3
+ import {} from "../shared/types.js";
4
+ const OPERATION_THRESHOLD = 100;
5
+ export class DocSyncServer {
6
+ _io;
7
+ _docBinding;
8
+ _provider;
9
+ _authenticate;
10
+ _authorize;
11
+ // TODO: see comment in sync-operations
12
+ _LRUCache = new Map();
13
+ // Track presence state per document: docId -> Record<clientId, presence data>
14
+ _presenceByDoc = new Map();
15
+ // Track which sockets are subscribed to which documents (for cleanup on disconnect)
16
+ _socketToDocsMap = new Map();
17
+ // Event handlers
18
+ _clientConnectHandlers = new Set();
19
+ _clientDisconnectHandlers = new Set();
20
+ _syncRequestHandlers = new Set();
21
+ constructor(config) {
22
+ this._io = new Server(config.port ?? 8080, {
23
+ cors: {
24
+ origin: "*",
25
+ },
26
+ // Performance: Only WebSocket transport, no polling
27
+ transports: ["websocket"],
28
+ });
29
+ this._docBinding = config.docBinding;
30
+ this._provider = new config.provider();
31
+ this._authenticate = config.authenticate.bind(config);
32
+ this._authorize = config.authorize?.bind(config);
33
+ this._setupSocketServer();
34
+ }
35
+ _setupSocketServer() {
36
+ // Middleware: authenticate before allowing connection
37
+ this._io.use((socket, next) => {
38
+ const { token, deviceId, clientId } = socket.handshake.auth;
39
+ if (!token || typeof token !== "string") {
40
+ next(new Error("Authentication required: no token provided"));
41
+ return;
42
+ }
43
+ if (!deviceId || typeof deviceId !== "string") {
44
+ next(new Error("Device ID required"));
45
+ return;
46
+ }
47
+ // TODO: should I check that no one is using an already taken ID, presumably intentionally?
48
+ if (!clientId || typeof clientId !== "string" || clientId.length === 0) {
49
+ next(new Error("Client ID required"));
50
+ return;
51
+ }
52
+ this._authenticate({ token })
53
+ .then((authResult) => {
54
+ if (!authResult) {
55
+ next(new Error("Authentication failed: invalid token"));
56
+ return;
57
+ }
58
+ // Attach authenticated context to socket data
59
+ socket.data = {
60
+ userId: authResult.userId,
61
+ deviceId,
62
+ clientId,
63
+ context: authResult.context ?? {},
64
+ };
65
+ next();
66
+ })
67
+ .catch((err) => {
68
+ next(new Error(`Authentication error: ${String(err)}`));
69
+ });
70
+ });
71
+ // Handle connection errors (auth failures)
72
+ this._io.engine.on("connection_error", (err) => {
73
+ // Try to extract deviceId from the failed connection request
74
+ const deviceId = err.req._query?.deviceId ?? "unknown";
75
+ this._emit(this._clientDisconnectHandlers, {
76
+ userId: "unknown",
77
+ deviceId,
78
+ socketId: "unknown",
79
+ reason: `Authentication failed: ${err.message}`,
80
+ });
81
+ });
82
+ this._io.on("connection", (socket) => {
83
+ const { userId, deviceId, clientId, context } = socket.data;
84
+ // Emit client connect event
85
+ this._emit(this._clientConnectHandlers, {
86
+ userId,
87
+ deviceId,
88
+ socketId: socket.id,
89
+ context,
90
+ });
91
+ // Handle disconnect
92
+ socket.on("disconnect", (reason) => {
93
+ // Get all documents this socket was subscribed to
94
+ const subscribedDocs = this._socketToDocsMap.get(socket.id);
95
+ if (subscribedDocs) {
96
+ // Clean up presence for all documents this socket was in
97
+ for (const docId of subscribedDocs) {
98
+ const presenceForDoc = this._presenceByDoc.get(docId);
99
+ // Immediately broadcast removal to OTHER clients
100
+ socket.to(`doc:${docId}`).emit("presence", {
101
+ docId,
102
+ presence: { [clientId]: null },
103
+ });
104
+ // Clean up presence map if the socket had presence
105
+ if (presenceForDoc?.[clientId] !== undefined) {
106
+ delete presenceForDoc[clientId];
107
+ if (Object.keys(presenceForDoc).length === 0) {
108
+ this._presenceByDoc.delete(docId);
109
+ }
110
+ }
111
+ }
112
+ // Remove socket from tracking map
113
+ this._socketToDocsMap.delete(socket.id);
114
+ }
115
+ this._emit(this._clientDisconnectHandlers, {
116
+ userId,
117
+ deviceId,
118
+ socketId: socket.id,
119
+ reason,
120
+ });
121
+ });
122
+ // Helper to check authorization
123
+ const checkAuth = async (event) => {
124
+ if (!this._authorize)
125
+ return true;
126
+ return this._authorize(event);
127
+ };
128
+ const applyPresenceUpdate = ({ docId, presence, }) => {
129
+ // Update server's presence state for this document
130
+ const currentPresence = this._presenceByDoc.get(docId) ?? {};
131
+ if (presence === null || presence === undefined) {
132
+ // Delete the presence entry for this client
133
+ delete currentPresence[clientId];
134
+ // Only keep the map entry if there are other sockets with presence
135
+ if (Object.keys(currentPresence).length > 0) {
136
+ this._presenceByDoc.set(docId, currentPresence);
137
+ }
138
+ else {
139
+ this._presenceByDoc.delete(docId);
140
+ }
141
+ }
142
+ else {
143
+ // Set the presence for this client
144
+ const newPresence = { ...currentPresence, [clientId]: presence };
145
+ this._presenceByDoc.set(docId, newPresence);
146
+ }
147
+ // Broadcast to other clients (undefined → null for JSON)
148
+ socket.to(`doc:${docId}`).emit("presence", {
149
+ docId,
150
+ presence: { [clientId]: presence ?? null },
151
+ });
152
+ };
153
+ // TypeScript errors if any handler is missing
154
+ const handlers = {
155
+ "sync-operations": async (payload, cb) => {
156
+ const { docId, operations = [], clock } = payload;
157
+ const startTime = Date.now();
158
+ const authorized = await checkAuth({
159
+ type: "sync-operations",
160
+ payload,
161
+ userId,
162
+ context,
163
+ });
164
+ if (!authorized) {
165
+ const errorEvent = {
166
+ type: "AuthorizationError",
167
+ message: "Access denied",
168
+ };
169
+ // Emit sync request event with authorization error
170
+ this._emit(this._syncRequestHandlers, {
171
+ userId,
172
+ deviceId,
173
+ socketId: socket.id,
174
+ status: "error",
175
+ req: payload,
176
+ error: errorEvent,
177
+ durationMs: Date.now() - startTime,
178
+ });
179
+ // Return error response
180
+ cb({
181
+ error: errorEvent,
182
+ });
183
+ return;
184
+ }
185
+ // Auto-subscribe to the document room on first sync
186
+ const room = this._io.sockets.adapter.rooms.get(`doc:${docId}`);
187
+ if (!room?.has(socket.id)) {
188
+ await socket.join(`doc:${docId}`);
189
+ // Track that this socket is subscribed to this document
190
+ if (!this._socketToDocsMap.has(socket.id)) {
191
+ this._socketToDocsMap.set(socket.id, new Set());
192
+ }
193
+ this._socketToDocsMap.get(socket.id).add(docId);
194
+ // Send current presence state to newly joined client
195
+ const presence = this._presenceByDoc.get(docId);
196
+ if (presence)
197
+ socket.emit("presence", { docId, presence });
198
+ }
199
+ if ("presence" in payload) {
200
+ applyPresenceUpdate({ docId, presence: payload.presence });
201
+ }
202
+ try {
203
+ // TODO: cache documents that have not been modified for append
204
+ // only operations without performing read operations
205
+ // TODO: with caching, ensure we don't save two operations for the same docId
206
+ // in the same millisecond to avoid PRIMARY KEY (docId, clock) conflicts
207
+ const result = await this._provider.transaction("readwrite", async (ctx) => {
208
+ // 1. Get operations the client doesn't have (clock > clientClock)
209
+ // We query BEFORE inserting so we don't return the client's own operations
210
+ const serverOps = await ctx.getOperations({ docId, clock });
211
+ // 2. Get server document only if its clock > client clock
212
+ const serverDoc = await ctx.getSerializedDoc(docId);
213
+ // 3. Save client operations if provided (returns the new clock)
214
+ const newClock = await ctx.saveOperations({
215
+ docId,
216
+ operations,
217
+ });
218
+ // 4. Return data
219
+ return {
220
+ docId,
221
+ ...(serverOps.length > 0
222
+ ? { operations: serverOps.flat() }
223
+ : {}),
224
+ ...(serverDoc?.serializedDoc
225
+ ? { serializedDoc: serverDoc.serializedDoc }
226
+ : {}),
227
+ clock: newClock,
228
+ };
229
+ });
230
+ // Return success response
231
+ cb({
232
+ data: {
233
+ docId: result.docId,
234
+ ...(result.operations ? { operations: result.operations } : {}),
235
+ ...(result.serializedDoc
236
+ ? { serializedDoc: result.serializedDoc }
237
+ : {}),
238
+ clock: result.clock,
239
+ },
240
+ });
241
+ // Get collaboration metrics and notify other clients in single pass
242
+ const docRoom = this._io.sockets.adapter.rooms.get(`doc:${payload.docId}`);
243
+ const devicesInRoom = new Set();
244
+ const shouldNotifyClients = payload.operations && payload.operations.length > 0;
245
+ if (docRoom) {
246
+ for (const socketId of docRoom) {
247
+ const targetSocket = this._io.sockets.sockets.get(socketId);
248
+ if (!targetSocket)
249
+ continue;
250
+ const targetDeviceId = targetSocket.data.deviceId;
251
+ // Collect device IDs for metrics
252
+ devicesInRoom.add(targetDeviceId);
253
+ // Notify other clients (skip sender and same device)
254
+ if (shouldNotifyClients) {
255
+ if (targetSocket.id !== socket.id &&
256
+ targetDeviceId !== deviceId) {
257
+ targetSocket.emit("dirty", { docId: payload.docId });
258
+ }
259
+ }
260
+ }
261
+ }
262
+ // Emit sync request event (success)
263
+ this._emit(this._syncRequestHandlers, {
264
+ userId,
265
+ deviceId,
266
+ socketId: socket.id,
267
+ status: "success",
268
+ req: {
269
+ docId: payload.docId,
270
+ operations,
271
+ clock: payload.clock,
272
+ },
273
+ ...(result.operations || result.serializedDoc
274
+ ? {
275
+ res: {
276
+ ...(result.operations
277
+ ? { operations: result.operations }
278
+ : {}),
279
+ ...(result.serializedDoc
280
+ ? { serializedDoc: result.serializedDoc }
281
+ : {}),
282
+ clock: result.clock,
283
+ },
284
+ }
285
+ : {}),
286
+ durationMs: Date.now() - startTime,
287
+ clientsCount: docRoom?.size ?? 0,
288
+ devicesCount: devicesInRoom.size,
289
+ });
290
+ // Squash operations if threshold is reached
291
+ if (result.operations &&
292
+ result.operations.length >= OPERATION_THRESHOLD) {
293
+ const { docId, operations: serverOps, serializedDoc, clock, } = result;
294
+ const operations = [...serverOps, ...(payload.operations ?? [])];
295
+ const doc = serializedDoc
296
+ ? this._docBinding.deserialize(serializedDoc)
297
+ : this._docBinding.create("test", docId).doc;
298
+ operations?.forEach((operation) => {
299
+ this._docBinding.applyOperations(doc, operation);
300
+ });
301
+ const newSerializedDoc = this._docBinding.serialize(doc);
302
+ await this._provider.transaction("readwrite", async (ctx) => {
303
+ await ctx.saveSerializedDoc({
304
+ docId,
305
+ serializedDoc: newSerializedDoc,
306
+ clock,
307
+ });
308
+ await ctx.deleteOperations({ docId, count: 1 });
309
+ });
310
+ }
311
+ }
312
+ catch (error) {
313
+ const errorMessage = error instanceof Error ? error.message : String(error);
314
+ const errorEvent = {
315
+ type: "DatabaseError",
316
+ message: errorMessage,
317
+ };
318
+ // Emit sync request event with error
319
+ this._emit(this._syncRequestHandlers, {
320
+ userId,
321
+ deviceId,
322
+ socketId: socket.id,
323
+ status: "error",
324
+ req: {
325
+ docId: payload.docId,
326
+ operations,
327
+ clock: payload.clock,
328
+ },
329
+ error: {
330
+ ...errorEvent,
331
+ ...(error instanceof Error && error.stack
332
+ ? { stack: error.stack }
333
+ : {}),
334
+ },
335
+ durationMs: Date.now() - startTime,
336
+ });
337
+ // Return error response
338
+ cb({
339
+ error: errorEvent,
340
+ });
341
+ return;
342
+ }
343
+ },
344
+ "delete-doc": async (payload, cb) => {
345
+ const authorized = await checkAuth({
346
+ type: "delete-doc",
347
+ payload,
348
+ userId,
349
+ context,
350
+ });
351
+ if (!authorized) {
352
+ // console.log("Authorization denied for delete-doc", {
353
+ // userId,
354
+ // payload,
355
+ // });
356
+ cb({ success: false });
357
+ return;
358
+ }
359
+ cb({ success: true });
360
+ },
361
+ "unsubscribe-doc": async ({ docId }, cb) => {
362
+ // Leave the room for this document
363
+ await socket.leave(`doc:${docId}`);
364
+ // Remove from socket-to-docs tracking
365
+ const subscribedDocs = this._socketToDocsMap.get(socket.id);
366
+ if (subscribedDocs) {
367
+ subscribedDocs.delete(docId);
368
+ if (subscribedDocs.size === 0) {
369
+ this._socketToDocsMap.delete(socket.id);
370
+ }
371
+ }
372
+ // Clean up presence state for this socket in this document
373
+ const presenceForDoc = this._presenceByDoc.get(docId);
374
+ if (presenceForDoc) {
375
+ // Immediately broadcast presence removal to OTHER clients
376
+ if (presenceForDoc[clientId] !== undefined) {
377
+ socket.to(`doc:${docId}`).emit("presence", {
378
+ docId,
379
+ presence: { [clientId]: null },
380
+ });
381
+ }
382
+ delete presenceForDoc[clientId];
383
+ // Only delete the map entry if no sockets remain
384
+ if (Object.keys(presenceForDoc).length === 0) {
385
+ this._presenceByDoc.delete(docId);
386
+ }
387
+ }
388
+ cb({ success: true });
389
+ },
390
+ presence: async ({ docId, presence }, cb) => {
391
+ applyPresenceUpdate({ docId, presence });
392
+ // Return success
393
+ cb({ data: void undefined });
394
+ },
395
+ };
396
+ // Register handlers
397
+ for (const event of Object.keys(handlers)) {
398
+ socket.on(event, handlers[event]);
399
+ }
400
+ });
401
+ }
402
+ /**
403
+ * Close the server and all connections.
404
+ */
405
+ async close() {
406
+ await this._io.close();
407
+ }
408
+ // ============================================================================
409
+ // Event Registration Methods
410
+ // ============================================================================
411
+ /**
412
+ * Register a handler for client connection events.
413
+ * @returns Unsubscribe function
414
+ */
415
+ onClientConnect(handler) {
416
+ this._clientConnectHandlers.add(handler);
417
+ return () => {
418
+ this._clientConnectHandlers.delete(handler);
419
+ };
420
+ }
421
+ /**
422
+ * Register a handler for client disconnection events.
423
+ * @returns Unsubscribe function
424
+ */
425
+ onClientDisconnect(handler) {
426
+ this._clientDisconnectHandlers.add(handler);
427
+ return () => {
428
+ this._clientDisconnectHandlers.delete(handler);
429
+ };
430
+ }
431
+ /**
432
+ * Register a handler for sync request events.
433
+ * @returns Unsubscribe function
434
+ */
435
+ onSyncRequest(handler) {
436
+ this._syncRequestHandlers.add(handler);
437
+ return () => {
438
+ this._syncRequestHandlers.delete(handler);
439
+ };
440
+ }
441
+ // ============================================================================
442
+ // Event Emitters (private methods)
443
+ // ============================================================================
444
+ _emit(handlers, event) {
445
+ for (const handler of handlers) {
446
+ handler(event);
447
+ }
448
+ }
449
+ }
450
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Provider, TransactionContext } from "../../shared/types.js";
2
+ /**
3
+ * In-memory server provider for testing.
4
+ * Stores documents and operations in memory - data is lost when the process ends.
5
+ */
6
+ export declare class InMemoryServerProvider<S, O> implements Provider<S, O, "server"> {
7
+ private _docs;
8
+ private _operations;
9
+ private _clockCounterByDocId;
10
+ private _nextClock;
11
+ transaction<T>(_mode: "readonly" | "readwrite", callback: (ctx: TransactionContext<S, O, "server">) => Promise<T>): Promise<T>;
12
+ /** For testing: clear all data */
13
+ clear(): void;
14
+ /** For testing: get stored operations count */
15
+ getOperationsCount(docId: string): number;
16
+ }
17
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/server/providers/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAY1E;;;GAGG;AACH,qBAAa,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAE,YAAW,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC;IAC3E,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,oBAAoB,CAA6B;IAEzD,OAAO,CAAC,UAAU;IAOZ,WAAW,CAAC,CAAC,EACjB,KAAK,EAAE,UAAU,GAAG,WAAW,EAC/B,QAAQ,EAAE,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAChE,OAAO,CAAC,CAAC,CAAC;IAoDb,kCAAkC;IAClC,KAAK,IAAI,IAAI;IAMb,+CAA+C;IAC/C,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAG1C"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * In-memory server provider for testing.
3
+ * Stores documents and operations in memory - data is lost when the process ends.
4
+ */
5
+ export class InMemoryServerProvider {
6
+ _docs = new Map();
7
+ _operations = new Map();
8
+ _clockCounterByDocId = new Map();
9
+ _nextClock(docId) {
10
+ const current = this._clockCounterByDocId.get(docId) ?? 0;
11
+ const next = current + 1;
12
+ this._clockCounterByDocId.set(docId, next);
13
+ return next;
14
+ }
15
+ async transaction(_mode, callback) {
16
+ // In-memory provider doesn't need real transactions since operations are synchronous
17
+ const ctx = {
18
+ getSerializedDoc: async (docId) => {
19
+ return this._docs.get(docId);
20
+ },
21
+ getOperations: async ({ docId, clock }) => {
22
+ const allOps = this._operations.get(docId) ?? [];
23
+ const serverOps = allOps
24
+ .filter((op) => op.clock > clock)
25
+ .map((op) => [op.operations]);
26
+ return serverOps;
27
+ },
28
+ deleteOperations: async ({ docId, count }) => {
29
+ const allOps = this._operations.get(docId) ?? [];
30
+ allOps.splice(0, count);
31
+ if (allOps.length === 0) {
32
+ this._operations.delete(docId);
33
+ }
34
+ else {
35
+ this._operations.set(docId, allOps);
36
+ }
37
+ },
38
+ saveOperations: async ({ docId, operations }) => {
39
+ if (operations.length === 0) {
40
+ // Return current clock if no operations to save
41
+ const allOps = this._operations.get(docId) ?? [];
42
+ return allOps.length > 0
43
+ ? Math.max(...allOps.map((op) => op.clock))
44
+ : 0;
45
+ }
46
+ // Increment clock and save operations
47
+ const newClock = this._nextClock(docId);
48
+ const docOps = this._operations.get(docId) ?? [];
49
+ for (const op of operations) {
50
+ docOps.push({ operations: op, clock: newClock });
51
+ }
52
+ this._operations.set(docId, docOps);
53
+ return newClock;
54
+ },
55
+ saveSerializedDoc: async ({ docId, serializedDoc, clock }) => {
56
+ this._docs.set(docId, { serializedDoc, clock });
57
+ },
58
+ };
59
+ return callback(ctx);
60
+ }
61
+ /** For testing: clear all data */
62
+ clear() {
63
+ this._docs.clear();
64
+ this._operations.clear();
65
+ this._clockCounterByDocId.clear();
66
+ }
67
+ /** For testing: get stored operations count */
68
+ getOperationsCount(docId) {
69
+ return this._operations.get(docId)?.length ?? 0;
70
+ }
71
+ }
72
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../../src/server/providers/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("drizzle-kit").Config;
2
+ export default _default;
3
+ //# sourceMappingURL=drizzle.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle.config.d.ts","sourceRoot":"","sources":["../../../../../src/server/providers/postgres/drizzle.config.ts"],"names":[],"mappings":";AAEA,wBAOG"}
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from "drizzle-kit";
2
+ export default defineConfig({
3
+ out: "./drizzle",
4
+ schema: "./src/server/providers/postgres/schema.ts",
5
+ dialect: "postgresql",
6
+ dbCredentials: {
7
+ url: process.env.DOCNODE_DB_URL,
8
+ },
9
+ });
10
+ //# sourceMappingURL=drizzle.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle.config.js","sourceRoot":"","sources":["../../../../../src/server/providers/postgres/drizzle.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAe,YAAY,CAAC;IAC1B,GAAG,EAAE,WAAW;IAChB,MAAM,EAAE,2CAA2C;IACnD,OAAO,EAAE,YAAY;IACrB,aAAa,EAAE;QACb,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,cAAe;KACjC;CACF,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Provider, TransactionContext } from "../../../shared/types.js";
2
+ export declare class PostgresProvider<S, O> implements Provider<S, O, "server"> {
3
+ private _db;
4
+ transaction<T>(_mode: "readonly" | "readwrite", callback: (ctx: TransactionContext<S, O, "server">) => Promise<T>): Promise<T>;
5
+ }
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/server/providers/postgres/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE7E,qBAAa,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAE,YAAW,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC;IACrE,OAAO,CAAC,GAAG,CAAoC;IAEzC,WAAW,CAAC,CAAC,EACjB,KAAK,EAAE,UAAU,GAAG,WAAW,EAC/B,QAAQ,EAAE,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAChE,OAAO,CAAC,CAAC,CAAC;CAgGd"}