@voidhash/mimic-effect 0.0.9 → 1.0.0-beta.2
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/.turbo/turbo-build.log +136 -90
- package/README.md +385 -0
- package/dist/ColdStorage.cjs +60 -0
- package/dist/ColdStorage.d.cts +53 -0
- package/dist/ColdStorage.d.cts.map +1 -0
- package/dist/ColdStorage.d.mts +53 -0
- package/dist/ColdStorage.d.mts.map +1 -0
- package/dist/ColdStorage.mjs +60 -0
- package/dist/ColdStorage.mjs.map +1 -0
- package/dist/DocumentManager.cjs +263 -82
- package/dist/DocumentManager.d.cts +44 -22
- package/dist/DocumentManager.d.cts.map +1 -1
- package/dist/DocumentManager.d.mts +44 -22
- package/dist/DocumentManager.d.mts.map +1 -1
- package/dist/DocumentManager.mjs +259 -67
- package/dist/DocumentManager.mjs.map +1 -1
- package/dist/Errors.cjs +54 -0
- package/dist/Errors.d.cts +96 -0
- package/dist/Errors.d.cts.map +1 -0
- package/dist/Errors.d.mts +96 -0
- package/dist/Errors.d.mts.map +1 -0
- package/dist/Errors.mjs +48 -0
- package/dist/Errors.mjs.map +1 -0
- package/dist/HotStorage.cjs +100 -0
- package/dist/HotStorage.d.cts +70 -0
- package/dist/HotStorage.d.cts.map +1 -0
- package/dist/HotStorage.d.mts +70 -0
- package/dist/HotStorage.d.mts.map +1 -0
- package/dist/HotStorage.mjs +100 -0
- package/dist/HotStorage.mjs.map +1 -0
- package/dist/Metrics.cjs +143 -0
- package/dist/Metrics.d.cts +31 -0
- package/dist/Metrics.d.cts.map +1 -0
- package/dist/Metrics.d.mts +31 -0
- package/dist/Metrics.d.mts.map +1 -0
- package/dist/Metrics.mjs +126 -0
- package/dist/Metrics.mjs.map +1 -0
- package/dist/MimicAuthService.cjs +61 -45
- package/dist/MimicAuthService.d.cts +61 -48
- package/dist/MimicAuthService.d.cts.map +1 -1
- package/dist/MimicAuthService.d.mts +61 -48
- package/dist/MimicAuthService.d.mts.map +1 -1
- package/dist/MimicAuthService.mjs +60 -36
- package/dist/MimicAuthService.mjs.map +1 -1
- package/dist/MimicClusterServerEngine.cjs +521 -0
- package/dist/MimicClusterServerEngine.d.cts +17 -0
- package/dist/MimicClusterServerEngine.d.cts.map +1 -0
- package/dist/MimicClusterServerEngine.d.mts +17 -0
- package/dist/MimicClusterServerEngine.d.mts.map +1 -0
- package/dist/MimicClusterServerEngine.mjs +523 -0
- package/dist/MimicClusterServerEngine.mjs.map +1 -0
- package/dist/MimicServer.cjs +205 -96
- package/dist/MimicServer.d.cts +9 -110
- package/dist/MimicServer.d.cts.map +1 -1
- package/dist/MimicServer.d.mts +9 -110
- package/dist/MimicServer.d.mts.map +1 -1
- package/dist/MimicServer.mjs +206 -90
- package/dist/MimicServer.mjs.map +1 -1
- package/dist/MimicServerEngine.cjs +97 -0
- package/dist/MimicServerEngine.d.cts +78 -0
- package/dist/MimicServerEngine.d.cts.map +1 -0
- package/dist/MimicServerEngine.d.mts +78 -0
- package/dist/MimicServerEngine.d.mts.map +1 -0
- package/dist/MimicServerEngine.mjs +97 -0
- package/dist/MimicServerEngine.mjs.map +1 -0
- package/dist/PresenceManager.cjs +75 -91
- package/dist/PresenceManager.d.cts +17 -66
- package/dist/PresenceManager.d.cts.map +1 -1
- package/dist/PresenceManager.d.mts +17 -66
- package/dist/PresenceManager.d.mts.map +1 -1
- package/dist/PresenceManager.mjs +74 -78
- package/dist/PresenceManager.mjs.map +1 -1
- package/dist/Protocol.cjs +146 -0
- package/dist/Protocol.d.cts +203 -0
- package/dist/Protocol.d.cts.map +1 -0
- package/dist/Protocol.d.mts +203 -0
- package/dist/Protocol.d.mts.map +1 -0
- package/dist/Protocol.mjs +132 -0
- package/dist/Protocol.mjs.map +1 -0
- package/dist/Types.d.cts +172 -0
- package/dist/Types.d.cts.map +1 -0
- package/dist/Types.d.mts +172 -0
- package/dist/Types.d.mts.map +1 -0
- package/dist/_virtual/rolldown_runtime.cjs +1 -25
- package/dist/_virtual/rolldown_runtime.mjs +4 -1
- package/dist/index.cjs +37 -75
- package/dist/index.d.cts +13 -12
- package/dist/index.d.mts +13 -12
- package/dist/index.mjs +12 -12
- package/dist/testing/ColdStorageTestSuite.cjs +508 -0
- package/dist/testing/ColdStorageTestSuite.d.cts +36 -0
- package/dist/testing/ColdStorageTestSuite.d.cts.map +1 -0
- package/dist/testing/ColdStorageTestSuite.d.mts +36 -0
- package/dist/testing/ColdStorageTestSuite.d.mts.map +1 -0
- package/dist/testing/ColdStorageTestSuite.mjs +508 -0
- package/dist/testing/ColdStorageTestSuite.mjs.map +1 -0
- package/dist/testing/FailingStorage.cjs +135 -0
- package/dist/testing/FailingStorage.d.cts +43 -0
- package/dist/testing/FailingStorage.d.cts.map +1 -0
- package/dist/testing/FailingStorage.d.mts +43 -0
- package/dist/testing/FailingStorage.d.mts.map +1 -0
- package/dist/testing/FailingStorage.mjs +136 -0
- package/dist/testing/FailingStorage.mjs.map +1 -0
- package/dist/testing/HotStorageTestSuite.cjs +585 -0
- package/dist/testing/HotStorageTestSuite.d.cts +40 -0
- package/dist/testing/HotStorageTestSuite.d.cts.map +1 -0
- package/dist/testing/HotStorageTestSuite.d.mts +40 -0
- package/dist/testing/HotStorageTestSuite.d.mts.map +1 -0
- package/dist/testing/HotStorageTestSuite.mjs +585 -0
- package/dist/testing/HotStorageTestSuite.mjs.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.cjs +349 -0
- package/dist/testing/StorageIntegrationTestSuite.d.cts +35 -0
- package/dist/testing/StorageIntegrationTestSuite.d.cts.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.d.mts +35 -0
- package/dist/testing/StorageIntegrationTestSuite.d.mts.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.mjs +349 -0
- package/dist/testing/StorageIntegrationTestSuite.mjs.map +1 -0
- package/dist/testing/assertions.cjs +114 -0
- package/dist/testing/assertions.mjs +109 -0
- package/dist/testing/assertions.mjs.map +1 -0
- package/dist/testing/index.cjs +14 -0
- package/dist/testing/index.d.cts +6 -0
- package/dist/testing/index.d.mts +6 -0
- package/dist/testing/index.mjs +7 -0
- package/dist/testing/types.cjs +15 -0
- package/dist/testing/types.d.cts +90 -0
- package/dist/testing/types.d.cts.map +1 -0
- package/dist/testing/types.d.mts +90 -0
- package/dist/testing/types.d.mts.map +1 -0
- package/dist/testing/types.mjs +16 -0
- package/dist/testing/types.mjs.map +1 -0
- package/package.json +18 -3
- package/src/ColdStorage.ts +136 -0
- package/src/DocumentManager.ts +550 -190
- package/src/Errors.ts +114 -0
- package/src/HotStorage.ts +239 -0
- package/src/Metrics.ts +187 -0
- package/src/MimicAuthService.ts +126 -64
- package/src/MimicClusterServerEngine.ts +946 -0
- package/src/MimicServer.ts +448 -195
- package/src/MimicServerEngine.ts +276 -0
- package/src/PresenceManager.ts +169 -240
- package/src/Protocol.ts +350 -0
- package/src/Types.ts +231 -0
- package/src/index.ts +57 -23
- package/src/testing/ColdStorageTestSuite.ts +589 -0
- package/src/testing/FailingStorage.ts +286 -0
- package/src/testing/HotStorageTestSuite.ts +762 -0
- package/src/testing/StorageIntegrationTestSuite.ts +504 -0
- package/src/testing/assertions.ts +181 -0
- package/src/testing/index.ts +83 -0
- package/src/testing/types.ts +100 -0
- package/tests/ColdStorage.test.ts +24 -0
- package/tests/DocumentManager.test.ts +158 -287
- package/tests/HotStorage.test.ts +24 -0
- package/tests/MimicAuthService.test.ts +102 -134
- package/tests/MimicClusterServerEngine.test.ts +587 -0
- package/tests/MimicServer.test.ts +90 -226
- package/tests/MimicServerEngine.test.ts +521 -0
- package/tests/PresenceManager.test.ts +22 -63
- package/tests/Protocol.test.ts +190 -0
- package/tests/StorageIntegration.test.ts +259 -0
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +1 -1
- package/dist/DocumentProtocol.cjs +0 -94
- package/dist/DocumentProtocol.d.cts +0 -113
- package/dist/DocumentProtocol.d.cts.map +0 -1
- package/dist/DocumentProtocol.d.mts +0 -113
- package/dist/DocumentProtocol.d.mts.map +0 -1
- package/dist/DocumentProtocol.mjs +0 -89
- package/dist/DocumentProtocol.mjs.map +0 -1
- package/dist/MimicConfig.cjs +0 -60
- package/dist/MimicConfig.d.cts +0 -141
- package/dist/MimicConfig.d.cts.map +0 -1
- package/dist/MimicConfig.d.mts +0 -141
- package/dist/MimicConfig.d.mts.map +0 -1
- package/dist/MimicConfig.mjs +0 -50
- package/dist/MimicConfig.mjs.map +0 -1
- package/dist/MimicDataStorage.cjs +0 -83
- package/dist/MimicDataStorage.d.cts +0 -113
- package/dist/MimicDataStorage.d.cts.map +0 -1
- package/dist/MimicDataStorage.d.mts +0 -113
- package/dist/MimicDataStorage.d.mts.map +0 -1
- package/dist/MimicDataStorage.mjs +0 -74
- package/dist/MimicDataStorage.mjs.map +0 -1
- package/dist/WebSocketHandler.cjs +0 -365
- package/dist/WebSocketHandler.d.cts +0 -34
- package/dist/WebSocketHandler.d.cts.map +0 -1
- package/dist/WebSocketHandler.d.mts +0 -34
- package/dist/WebSocketHandler.d.mts.map +0 -1
- package/dist/WebSocketHandler.mjs +0 -355
- package/dist/WebSocketHandler.mjs.map +0 -1
- package/dist/auth/NoAuth.cjs +0 -43
- package/dist/auth/NoAuth.d.cts +0 -22
- package/dist/auth/NoAuth.d.cts.map +0 -1
- package/dist/auth/NoAuth.d.mts +0 -22
- package/dist/auth/NoAuth.d.mts.map +0 -1
- package/dist/auth/NoAuth.mjs +0 -36
- package/dist/auth/NoAuth.mjs.map +0 -1
- package/dist/errors.cjs +0 -74
- package/dist/errors.d.cts +0 -89
- package/dist/errors.d.cts.map +0 -1
- package/dist/errors.d.mts +0 -89
- package/dist/errors.d.mts.map +0 -1
- package/dist/errors.mjs +0 -67
- package/dist/errors.mjs.map +0 -1
- package/dist/storage/InMemoryDataStorage.cjs +0 -57
- package/dist/storage/InMemoryDataStorage.d.cts +0 -19
- package/dist/storage/InMemoryDataStorage.d.cts.map +0 -1
- package/dist/storage/InMemoryDataStorage.d.mts +0 -19
- package/dist/storage/InMemoryDataStorage.d.mts.map +0 -1
- package/dist/storage/InMemoryDataStorage.mjs +0 -48
- package/dist/storage/InMemoryDataStorage.mjs.map +0 -1
- package/src/DocumentProtocol.ts +0 -112
- package/src/MimicConfig.ts +0 -211
- package/src/MimicDataStorage.ts +0 -157
- package/src/WebSocketHandler.ts +0 -735
- package/src/auth/NoAuth.ts +0 -46
- package/src/errors.ts +0 -113
- package/src/storage/InMemoryDataStorage.ts +0 -66
- package/tests/DocumentProtocol.test.ts +0 -113
- package/tests/InMemoryDataStorage.test.ts +0 -190
- package/tests/MimicConfig.test.ts +0 -290
- package/tests/MimicDataStorage.test.ts +0 -190
- package/tests/NoAuth.test.ts +0 -94
- package/tests/WebSocketHandler.test.ts +0 -321
- package/tests/errors.test.ts +0 -77
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
import { __export } from "./_virtual/rolldown_runtime.mjs";
|
|
2
|
-
import { MimicServerConfigTag } from "./MimicConfig.mjs";
|
|
3
|
-
import { DocumentManagerTag } from "./DocumentManager.mjs";
|
|
4
|
-
import { MimicAuthServiceTag } from "./MimicAuthService.mjs";
|
|
5
|
-
import { PresenceManagerTag } from "./PresenceManager.mjs";
|
|
6
|
-
import { MessageParseError, MissingDocumentIdError } from "./errors.mjs";
|
|
7
|
-
import { _objectSpread2 } from "./_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.mjs";
|
|
8
|
-
import * as Effect from "effect/Effect";
|
|
9
|
-
import * as Stream from "effect/Stream";
|
|
10
|
-
import * as Duration from "effect/Duration";
|
|
11
|
-
import { Presence, Transaction } from "@voidhash/mimic";
|
|
12
|
-
import * as Fiber from "effect/Fiber";
|
|
13
|
-
|
|
14
|
-
//#region src/WebSocketHandler.ts
|
|
15
|
-
/**
|
|
16
|
-
* @since 0.0.1
|
|
17
|
-
* WebSocket connection handler using Effect Platform Socket API.
|
|
18
|
-
*/
|
|
19
|
-
var WebSocketHandler_exports = /* @__PURE__ */ __export({
|
|
20
|
-
extractDocumentId: () => extractDocumentId,
|
|
21
|
-
handleConnection: () => handleConnection,
|
|
22
|
-
makeHandler: () => makeHandler
|
|
23
|
-
});
|
|
24
|
-
/**
|
|
25
|
-
* Extract document ID from URL path.
|
|
26
|
-
* Expected format: /doc/{documentId}
|
|
27
|
-
*/
|
|
28
|
-
const extractDocumentId = (path) => {
|
|
29
|
-
const parts = path.replace(/^\/+/, "").split("/");
|
|
30
|
-
const docIndex = parts.lastIndexOf("doc");
|
|
31
|
-
const part = parts[docIndex + 1];
|
|
32
|
-
if (docIndex !== -1 && part) return Effect.succeed(decodeURIComponent(part));
|
|
33
|
-
return Effect.fail(new MissingDocumentIdError({}));
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* Decodes an encoded client message from the wire format.
|
|
37
|
-
*/
|
|
38
|
-
const decodeClientMessage = (encoded) => {
|
|
39
|
-
if (encoded.type === "submit") return {
|
|
40
|
-
type: "submit",
|
|
41
|
-
transaction: Transaction.decode(encoded.transaction)
|
|
42
|
-
};
|
|
43
|
-
return encoded;
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* Encodes a server message for the wire format.
|
|
47
|
-
*/
|
|
48
|
-
const encodeServerMessageForWire = (message) => {
|
|
49
|
-
if (message.type === "transaction") return {
|
|
50
|
-
type: "transaction",
|
|
51
|
-
transaction: Transaction.encode(message.transaction),
|
|
52
|
-
version: message.version
|
|
53
|
-
};
|
|
54
|
-
return message;
|
|
55
|
-
};
|
|
56
|
-
const parseClientMessage = (data) => Effect.try({
|
|
57
|
-
try: () => {
|
|
58
|
-
const text = typeof data === "string" ? data : new TextDecoder().decode(data);
|
|
59
|
-
return decodeClientMessage(JSON.parse(text));
|
|
60
|
-
},
|
|
61
|
-
catch: (cause) => new MessageParseError({ cause })
|
|
62
|
-
});
|
|
63
|
-
const encodeServerMessage = (message) => JSON.stringify(encodeServerMessageForWire(message));
|
|
64
|
-
/**
|
|
65
|
-
* Handle a WebSocket connection for a document.
|
|
66
|
-
*
|
|
67
|
-
* @param socket - The Effect Platform Socket
|
|
68
|
-
* @param path - The URL path (e.g., "/doc/my-document-id")
|
|
69
|
-
* @returns An Effect that handles the connection lifecycle
|
|
70
|
-
*/
|
|
71
|
-
const handleConnection = (socket, path) => Effect.gen(function* () {
|
|
72
|
-
const config = yield* MimicServerConfigTag;
|
|
73
|
-
const authService = yield* MimicAuthServiceTag;
|
|
74
|
-
const documentManager = yield* DocumentManagerTag;
|
|
75
|
-
const presenceManager = yield* PresenceManagerTag;
|
|
76
|
-
const documentId = yield* extractDocumentId(path);
|
|
77
|
-
const connectionId = crypto.randomUUID();
|
|
78
|
-
let state = {
|
|
79
|
-
documentId,
|
|
80
|
-
connectionId,
|
|
81
|
-
authenticated: false
|
|
82
|
-
};
|
|
83
|
-
let hasPresence = false;
|
|
84
|
-
const write = yield* socket.writer;
|
|
85
|
-
const sendMessage = (message) => write(encodeServerMessage(message));
|
|
86
|
-
const sendPresenceSnapshot = Effect.gen(function* () {
|
|
87
|
-
if (!config.presence) return;
|
|
88
|
-
yield* sendMessage({
|
|
89
|
-
type: "presence_snapshot",
|
|
90
|
-
selfId: connectionId,
|
|
91
|
-
presences: (yield* presenceManager.getSnapshot(documentId)).presences
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
const handleAuth = (token) => Effect.gen(function* () {
|
|
95
|
-
const result = yield* authService.authenticate(token);
|
|
96
|
-
if (result.success) {
|
|
97
|
-
state = _objectSpread2(_objectSpread2({}, state), {}, {
|
|
98
|
-
authenticated: true,
|
|
99
|
-
userId: result.userId
|
|
100
|
-
});
|
|
101
|
-
yield* sendMessage({
|
|
102
|
-
type: "auth_result",
|
|
103
|
-
success: true
|
|
104
|
-
});
|
|
105
|
-
yield* sendPresenceSnapshot;
|
|
106
|
-
} else yield* sendMessage({
|
|
107
|
-
type: "auth_result",
|
|
108
|
-
success: false,
|
|
109
|
-
error: result.error
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
const handlePresenceSet = (data) => Effect.gen(function* () {
|
|
113
|
-
if (!state.authenticated) return;
|
|
114
|
-
if (!config.presence) return;
|
|
115
|
-
const validated = Presence.validateSafe(config.presence, data);
|
|
116
|
-
if (validated === void 0) {
|
|
117
|
-
yield* Effect.logWarning("Invalid presence data received", {
|
|
118
|
-
connectionId,
|
|
119
|
-
data
|
|
120
|
-
});
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
yield* presenceManager.set(documentId, connectionId, {
|
|
124
|
-
data: validated,
|
|
125
|
-
userId: state.userId
|
|
126
|
-
});
|
|
127
|
-
hasPresence = true;
|
|
128
|
-
});
|
|
129
|
-
const handlePresenceClear = Effect.gen(function* () {
|
|
130
|
-
if (!state.authenticated) return;
|
|
131
|
-
if (!config.presence) return;
|
|
132
|
-
yield* presenceManager.remove(documentId, connectionId);
|
|
133
|
-
hasPresence = false;
|
|
134
|
-
});
|
|
135
|
-
const handleMessage = (message) => Effect.gen(function* () {
|
|
136
|
-
switch (message.type) {
|
|
137
|
-
case "auth":
|
|
138
|
-
yield* handleAuth(message.token);
|
|
139
|
-
break;
|
|
140
|
-
case "ping":
|
|
141
|
-
yield* sendMessage({ type: "pong" });
|
|
142
|
-
break;
|
|
143
|
-
case "submit":
|
|
144
|
-
if (!state.authenticated) {
|
|
145
|
-
yield* sendMessage({
|
|
146
|
-
type: "error",
|
|
147
|
-
transactionId: message.transaction.id,
|
|
148
|
-
reason: "Not authenticated"
|
|
149
|
-
});
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const submitResult = yield* documentManager.submit(documentId, message.transaction);
|
|
153
|
-
if (!submitResult.success) yield* sendMessage({
|
|
154
|
-
type: "error",
|
|
155
|
-
transactionId: message.transaction.id,
|
|
156
|
-
reason: submitResult.reason
|
|
157
|
-
});
|
|
158
|
-
break;
|
|
159
|
-
case "request_snapshot":
|
|
160
|
-
if (!state.authenticated) return;
|
|
161
|
-
yield* sendMessage(yield* Effect.catchAll(documentManager.getSnapshot(documentId), () => Effect.succeed({
|
|
162
|
-
type: "snapshot",
|
|
163
|
-
state: null,
|
|
164
|
-
version: 0
|
|
165
|
-
})));
|
|
166
|
-
break;
|
|
167
|
-
case "presence_set":
|
|
168
|
-
yield* handlePresenceSet(message.data);
|
|
169
|
-
break;
|
|
170
|
-
case "presence_clear":
|
|
171
|
-
yield* handlePresenceClear;
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
const subscribeFiber = yield* Effect.fork(Effect.gen(function* () {
|
|
176
|
-
while (!state.authenticated) yield* Effect.sleep(Duration.millis(100));
|
|
177
|
-
const broadcastStream = yield* Effect.catchAll(documentManager.subscribe(documentId), () => Effect.succeed(Stream.empty));
|
|
178
|
-
yield* Stream.runForEach(broadcastStream, (broadcast) => sendMessage(broadcast));
|
|
179
|
-
}).pipe(Effect.scoped));
|
|
180
|
-
const presenceFiber = yield* Effect.fork(Effect.gen(function* () {
|
|
181
|
-
if (!config.presence) return;
|
|
182
|
-
while (!state.authenticated) yield* Effect.sleep(Duration.millis(100));
|
|
183
|
-
const presenceStream = yield* presenceManager.subscribe(documentId);
|
|
184
|
-
yield* Stream.runForEach(presenceStream, (event) => Effect.gen(function* () {
|
|
185
|
-
if (event.id === connectionId) return;
|
|
186
|
-
if (event.type === "presence_update") yield* sendMessage({
|
|
187
|
-
type: "presence_update",
|
|
188
|
-
id: event.id,
|
|
189
|
-
data: event.data,
|
|
190
|
-
userId: event.userId
|
|
191
|
-
});
|
|
192
|
-
else if (event.type === "presence_remove") yield* sendMessage({
|
|
193
|
-
type: "presence_remove",
|
|
194
|
-
id: event.id
|
|
195
|
-
});
|
|
196
|
-
}));
|
|
197
|
-
}).pipe(Effect.scoped));
|
|
198
|
-
yield* Effect.addFinalizer(() => Effect.gen(function* () {
|
|
199
|
-
yield* Fiber.interrupt(subscribeFiber);
|
|
200
|
-
yield* Fiber.interrupt(presenceFiber);
|
|
201
|
-
if (hasPresence && config.presence) yield* presenceManager.remove(documentId, connectionId);
|
|
202
|
-
}));
|
|
203
|
-
yield* socket.runRaw((data) => Effect.gen(function* () {
|
|
204
|
-
yield* handleMessage(yield* parseClientMessage(data));
|
|
205
|
-
}).pipe(Effect.catchAll((error) => Effect.logError("Message handling error", error))));
|
|
206
|
-
});
|
|
207
|
-
/**
|
|
208
|
-
* Create a handler function for the WebSocket server.
|
|
209
|
-
* Returns a function that takes a socket and document ID.
|
|
210
|
-
*/
|
|
211
|
-
const makeHandler = Effect.gen(function* () {
|
|
212
|
-
const config = yield* MimicServerConfigTag;
|
|
213
|
-
const authService = yield* MimicAuthServiceTag;
|
|
214
|
-
const documentManager = yield* DocumentManagerTag;
|
|
215
|
-
const presenceManager = yield* PresenceManagerTag;
|
|
216
|
-
return (socket, documentId) => handleConnectionWithDocumentId(socket, documentId).pipe(Effect.provideService(MimicServerConfigTag, config), Effect.provideService(MimicAuthServiceTag, authService), Effect.provideService(DocumentManagerTag, documentManager), Effect.provideService(PresenceManagerTag, presenceManager), Effect.scoped);
|
|
217
|
-
});
|
|
218
|
-
/**
|
|
219
|
-
* Handle a WebSocket connection for a document (using document ID directly).
|
|
220
|
-
*/
|
|
221
|
-
const handleConnectionWithDocumentId = (socket, documentId) => Effect.gen(function* () {
|
|
222
|
-
const config = yield* MimicServerConfigTag;
|
|
223
|
-
const authService = yield* MimicAuthServiceTag;
|
|
224
|
-
const documentManager = yield* DocumentManagerTag;
|
|
225
|
-
const presenceManager = yield* PresenceManagerTag;
|
|
226
|
-
const connectionId = crypto.randomUUID();
|
|
227
|
-
let state = {
|
|
228
|
-
documentId,
|
|
229
|
-
connectionId,
|
|
230
|
-
authenticated: false
|
|
231
|
-
};
|
|
232
|
-
let hasPresence = false;
|
|
233
|
-
const write = yield* socket.writer;
|
|
234
|
-
const sendMessage = (message) => write(encodeServerMessage(message));
|
|
235
|
-
const sendPresenceSnapshot = Effect.gen(function* () {
|
|
236
|
-
if (!config.presence) return;
|
|
237
|
-
yield* sendMessage({
|
|
238
|
-
type: "presence_snapshot",
|
|
239
|
-
selfId: connectionId,
|
|
240
|
-
presences: (yield* presenceManager.getSnapshot(documentId)).presences
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
const handleAuth = (token) => Effect.gen(function* () {
|
|
244
|
-
const result = yield* authService.authenticate(token);
|
|
245
|
-
if (result.success) {
|
|
246
|
-
state = _objectSpread2(_objectSpread2({}, state), {}, {
|
|
247
|
-
authenticated: true,
|
|
248
|
-
userId: result.userId
|
|
249
|
-
});
|
|
250
|
-
yield* sendMessage({
|
|
251
|
-
type: "auth_result",
|
|
252
|
-
success: true
|
|
253
|
-
});
|
|
254
|
-
yield* sendPresenceSnapshot;
|
|
255
|
-
} else yield* sendMessage({
|
|
256
|
-
type: "auth_result",
|
|
257
|
-
success: false,
|
|
258
|
-
error: result.error
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
const handlePresenceSet = (data) => Effect.gen(function* () {
|
|
262
|
-
if (!state.authenticated) return;
|
|
263
|
-
if (!config.presence) return;
|
|
264
|
-
const validated = Presence.validateSafe(config.presence, data);
|
|
265
|
-
if (validated === void 0) {
|
|
266
|
-
yield* Effect.logWarning("Invalid presence data received", {
|
|
267
|
-
connectionId,
|
|
268
|
-
data
|
|
269
|
-
});
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
yield* presenceManager.set(documentId, connectionId, {
|
|
273
|
-
data: validated,
|
|
274
|
-
userId: state.userId
|
|
275
|
-
});
|
|
276
|
-
hasPresence = true;
|
|
277
|
-
});
|
|
278
|
-
const handlePresenceClear = Effect.gen(function* () {
|
|
279
|
-
if (!state.authenticated) return;
|
|
280
|
-
if (!config.presence) return;
|
|
281
|
-
yield* presenceManager.remove(documentId, connectionId);
|
|
282
|
-
hasPresence = false;
|
|
283
|
-
});
|
|
284
|
-
const handleMessage = (message) => Effect.gen(function* () {
|
|
285
|
-
switch (message.type) {
|
|
286
|
-
case "auth":
|
|
287
|
-
yield* handleAuth(message.token);
|
|
288
|
-
break;
|
|
289
|
-
case "ping":
|
|
290
|
-
yield* sendMessage({ type: "pong" });
|
|
291
|
-
break;
|
|
292
|
-
case "submit":
|
|
293
|
-
if (!state.authenticated) {
|
|
294
|
-
yield* sendMessage({
|
|
295
|
-
type: "error",
|
|
296
|
-
transactionId: message.transaction.id,
|
|
297
|
-
reason: "Not authenticated"
|
|
298
|
-
});
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
const submitResult = yield* documentManager.submit(documentId, message.transaction);
|
|
302
|
-
if (!submitResult.success) yield* sendMessage({
|
|
303
|
-
type: "error",
|
|
304
|
-
transactionId: message.transaction.id,
|
|
305
|
-
reason: submitResult.reason
|
|
306
|
-
});
|
|
307
|
-
break;
|
|
308
|
-
case "request_snapshot":
|
|
309
|
-
if (!state.authenticated) return;
|
|
310
|
-
yield* sendMessage(yield* documentManager.getSnapshot(documentId));
|
|
311
|
-
break;
|
|
312
|
-
case "presence_set":
|
|
313
|
-
yield* handlePresenceSet(message.data);
|
|
314
|
-
break;
|
|
315
|
-
case "presence_clear":
|
|
316
|
-
yield* handlePresenceClear;
|
|
317
|
-
break;
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
const subscribeFiber = yield* Effect.fork(Effect.gen(function* () {
|
|
321
|
-
while (!state.authenticated) yield* Effect.sleep(Duration.millis(100));
|
|
322
|
-
const broadcastStream = yield* documentManager.subscribe(documentId);
|
|
323
|
-
yield* Stream.runForEach(broadcastStream, (broadcast) => sendMessage(broadcast));
|
|
324
|
-
}).pipe(Effect.scoped));
|
|
325
|
-
const presenceFiber = yield* Effect.fork(Effect.gen(function* () {
|
|
326
|
-
if (!config.presence) return;
|
|
327
|
-
while (!state.authenticated) yield* Effect.sleep(Duration.millis(100));
|
|
328
|
-
const presenceStream = yield* presenceManager.subscribe(documentId);
|
|
329
|
-
yield* Stream.runForEach(presenceStream, (event) => Effect.gen(function* () {
|
|
330
|
-
if (event.id === connectionId) return;
|
|
331
|
-
if (event.type === "presence_update") yield* sendMessage({
|
|
332
|
-
type: "presence_update",
|
|
333
|
-
id: event.id,
|
|
334
|
-
data: event.data,
|
|
335
|
-
userId: event.userId
|
|
336
|
-
});
|
|
337
|
-
else if (event.type === "presence_remove") yield* sendMessage({
|
|
338
|
-
type: "presence_remove",
|
|
339
|
-
id: event.id
|
|
340
|
-
});
|
|
341
|
-
}));
|
|
342
|
-
}).pipe(Effect.scoped));
|
|
343
|
-
yield* Effect.addFinalizer(() => Effect.gen(function* () {
|
|
344
|
-
yield* Fiber.interrupt(subscribeFiber);
|
|
345
|
-
yield* Fiber.interrupt(presenceFiber);
|
|
346
|
-
if (hasPresence && config.presence) yield* presenceManager.remove(documentId, connectionId);
|
|
347
|
-
}));
|
|
348
|
-
yield* socket.runRaw((data) => Effect.gen(function* () {
|
|
349
|
-
yield* handleMessage(yield* parseClientMessage(data));
|
|
350
|
-
}).pipe(Effect.catchAll((error) => Effect.logError("Message handling error", error))));
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
//#endregion
|
|
354
|
-
export { WebSocketHandler_exports, extractDocumentId, handleConnection };
|
|
355
|
-
//# sourceMappingURL=WebSocketHandler.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketHandler.mjs","names":["state: ConnectionState"],"sources":["../src/WebSocketHandler.ts"],"sourcesContent":["/**\n * @since 0.0.1\n * WebSocket connection handler using Effect Platform Socket API.\n */\nimport * as Effect from \"effect/Effect\";\nimport * as Stream from \"effect/Stream\";\nimport * as Fiber from \"effect/Fiber\";\nimport * as Scope from \"effect/Scope\";\nimport * as Duration from \"effect/Duration\";\nimport type * as Socket from \"@effect/platform/Socket\";\nimport { Transaction, Presence } from \"@voidhash/mimic\";\n\nimport * as Protocol from \"./DocumentProtocol.js\";\nimport { MimicServerConfigTag } from \"./MimicConfig.js\";\nimport { MimicAuthServiceTag } from \"./MimicAuthService.js\";\nimport { DocumentManagerTag } from \"./DocumentManager.js\";\nimport { PresenceManagerTag } from \"./PresenceManager.js\";\nimport type * as PresenceManager from \"./PresenceManager.js\";\nimport {\n MessageParseError,\n MissingDocumentIdError,\n} from \"./errors.js\";\n\n// =============================================================================\n// Client Message Types (matching mimic-client Transport.ts)\n// =============================================================================\n\ninterface SubmitMessage {\n readonly type: \"submit\";\n readonly transaction: Protocol.Transaction;\n}\n\ninterface EncodedSubmitMessage {\n readonly type: \"submit\";\n readonly transaction: Transaction.EncodedTransaction;\n}\n\ninterface RequestSnapshotMessage {\n readonly type: \"request_snapshot\";\n}\n\ninterface PingMessage {\n readonly type: \"ping\";\n}\n\ninterface AuthMessage {\n readonly type: \"auth\";\n readonly token: string;\n}\n\ninterface PresenceSetMessage {\n readonly type: \"presence_set\";\n readonly data: unknown;\n}\n\ninterface PresenceClearMessage {\n readonly type: \"presence_clear\";\n}\n\ntype ClientMessage =\n | SubmitMessage\n | RequestSnapshotMessage\n | PingMessage\n | AuthMessage\n | PresenceSetMessage\n | PresenceClearMessage;\n\ntype EncodedClientMessage =\n | EncodedSubmitMessage\n | RequestSnapshotMessage\n | PingMessage\n | AuthMessage\n | PresenceSetMessage\n | PresenceClearMessage;\n\n// =============================================================================\n// Server Message Types (matching mimic-client Transport.ts)\n// =============================================================================\n\ninterface PongMessage {\n readonly type: \"pong\";\n}\n\ninterface AuthResultMessage {\n readonly type: \"auth_result\";\n readonly success: boolean;\n readonly error?: string;\n}\n\ninterface EncodedTransactionMessage {\n readonly type: \"transaction\";\n readonly transaction: Transaction.EncodedTransaction;\n readonly version: number;\n}\n\n// Presence server messages\ninterface PresenceSnapshotMessage {\n readonly type: \"presence_snapshot\";\n readonly selfId: string;\n readonly presences: Record<string, { data: unknown; userId?: string }>;\n}\n\ninterface PresenceUpdateMessage {\n readonly type: \"presence_update\";\n readonly id: string;\n readonly data: unknown;\n readonly userId?: string;\n}\n\ninterface PresenceRemoveMessage {\n readonly type: \"presence_remove\";\n readonly id: string;\n}\n\ntype ServerMessage =\n | Protocol.TransactionMessage\n | Protocol.SnapshotMessage\n | Protocol.ErrorMessage\n | PongMessage\n | AuthResultMessage\n | PresenceSnapshotMessage\n | PresenceUpdateMessage\n | PresenceRemoveMessage;\n\ntype EncodedServerMessage =\n | EncodedTransactionMessage\n | Protocol.SnapshotMessage\n | Protocol.ErrorMessage\n | PongMessage\n | AuthResultMessage\n | PresenceSnapshotMessage\n | PresenceUpdateMessage\n | PresenceRemoveMessage;\n\n// =============================================================================\n// WebSocket Connection State\n// =============================================================================\n\ninterface ConnectionState {\n readonly documentId: string;\n readonly connectionId: string;\n readonly authenticated: boolean;\n readonly userId?: string;\n}\n\n// =============================================================================\n// URL Path Parsing\n// =============================================================================\n\n/**\n * Extract document ID from URL path.\n * Expected format: /doc/{documentId}\n */\nexport const extractDocumentId = (\n path: string\n): Effect.Effect<string, MissingDocumentIdError> => {\n // Remove leading slash and split\n const parts = path.replace(/^\\/+/, \"\").split(\"/\");\n\n // Find the last occurrence of 'doc' in the path\n const docIndex = parts.lastIndexOf(\"doc\");\n const part = parts[docIndex + 1];\n if (docIndex !== -1 && part) {\n return Effect.succeed(decodeURIComponent(part));\n }\n return Effect.fail(new MissingDocumentIdError({}));\n};\n\n// =============================================================================\n// Message Parsing\n// =============================================================================\n\n/**\n * Decodes an encoded client message from the wire format.\n */\nconst decodeClientMessage = (encoded: EncodedClientMessage): ClientMessage => {\n if (encoded.type === \"submit\") {\n return {\n type: \"submit\",\n transaction: Transaction.decode(encoded.transaction),\n };\n }\n return encoded;\n};\n\n/**\n * Encodes a server message for the wire format.\n */\nconst encodeServerMessageForWire = (message: ServerMessage): EncodedServerMessage => {\n if (message.type === \"transaction\") {\n return {\n type: \"transaction\",\n transaction: Transaction.encode(message.transaction),\n version: message.version,\n };\n }\n return message;\n};\n\nconst parseClientMessage = (\n data: string | Uint8Array\n): Effect.Effect<ClientMessage, MessageParseError> =>\n Effect.try({\n try: () => {\n const text =\n typeof data === \"string\" ? data : new TextDecoder().decode(data);\n const encoded = JSON.parse(text) as EncodedClientMessage;\n return decodeClientMessage(encoded);\n },\n catch: (cause) => new MessageParseError({ cause }),\n });\n\nconst encodeServerMessage = (message: ServerMessage): string =>\n JSON.stringify(encodeServerMessageForWire(message));\n\n// =============================================================================\n// WebSocket Handler\n// =============================================================================\n\n/**\n * Handle a WebSocket connection for a document.\n *\n * @param socket - The Effect Platform Socket\n * @param path - The URL path (e.g., \"/doc/my-document-id\")\n * @returns An Effect that handles the connection lifecycle\n */\nexport const handleConnection = (\n socket: Socket.Socket,\n path: string\n): Effect.Effect<\n void,\n Socket.SocketError | MissingDocumentIdError | MessageParseError,\n MimicServerConfigTag | MimicAuthServiceTag | DocumentManagerTag | PresenceManagerTag | Scope.Scope\n> =>\n Effect.gen(function* () {\n const config = yield* MimicServerConfigTag;\n const authService = yield* MimicAuthServiceTag;\n const documentManager = yield* DocumentManagerTag;\n const presenceManager = yield* PresenceManagerTag;\n\n // Extract document ID from path\n const documentId = yield* extractDocumentId(path);\n const connectionId = crypto.randomUUID();\n\n // Track connection state\n let state: ConnectionState = {\n documentId,\n connectionId,\n authenticated: false, // Start unauthenticated, auth service will validate\n };\n\n // Track if this connection has set presence (for cleanup)\n let hasPresence = false;\n\n // Get the socket writer\n const write = yield* socket.writer;\n\n // Helper to send a message to the client\n const sendMessage = (message: ServerMessage) =>\n write(encodeServerMessage(message));\n\n // Send presence snapshot after auth\n const sendPresenceSnapshot = Effect.gen(function* () {\n if (!config.presence) return;\n\n const snapshot = yield* presenceManager.getSnapshot(documentId);\n yield* sendMessage({\n type: \"presence_snapshot\",\n selfId: connectionId,\n presences: snapshot.presences,\n });\n });\n\n // Handle authentication using the auth service\n const handleAuth = (token: string) =>\n Effect.gen(function* () {\n const result = yield* authService.authenticate(token);\n\n if (result.success) {\n state = {\n ...state,\n authenticated: true,\n userId: result.userId,\n };\n yield* sendMessage({ type: \"auth_result\", success: true });\n\n // Send presence snapshot after successful auth\n yield* sendPresenceSnapshot;\n } else {\n yield* sendMessage({\n type: \"auth_result\",\n success: false,\n error: result.error,\n });\n }\n });\n\n // Handle presence set\n const handlePresenceSet = (data: unknown) =>\n Effect.gen(function* () {\n if (!state.authenticated) return;\n if (!config.presence) return;\n\n // Validate presence data against schema\n const validated = Presence.validateSafe(config.presence, data);\n if (validated === undefined) {\n yield* Effect.logWarning(\"Invalid presence data received\", { connectionId, data });\n return;\n }\n\n // Store in presence manager\n yield* presenceManager.set(documentId, connectionId, {\n data: validated,\n userId: state.userId,\n });\n\n hasPresence = true;\n });\n\n // Handle presence clear\n const handlePresenceClear = Effect.gen(function* () {\n if (!state.authenticated) return;\n if (!config.presence) return;\n\n yield* presenceManager.remove(documentId, connectionId);\n hasPresence = false;\n });\n\n // Handle a client message\n const handleMessage = (message: ClientMessage) =>\n Effect.gen(function* () {\n switch (message.type) {\n case \"auth\":\n yield* handleAuth(message.token);\n break;\n\n case \"ping\":\n yield* sendMessage({ type: \"pong\" });\n break;\n\n case \"submit\":\n if (!state.authenticated) {\n yield* sendMessage({\n type: \"error\",\n transactionId: message.transaction.id,\n reason: \"Not authenticated\",\n });\n return;\n }\n // Submit to the document manager\n const submitResult = yield* documentManager.submit(\n documentId,\n message.transaction as any\n );\n // If rejected, send error (success is broadcast to all)\n if (!submitResult.success) {\n yield* sendMessage({\n type: \"error\",\n transactionId: message.transaction.id,\n reason: submitResult.reason,\n });\n }\n break;\n\n case \"request_snapshot\":\n if (!state.authenticated) {\n return;\n }\n const snapshot = yield* Effect.catchAll(\n documentManager.getSnapshot(documentId),\n () =>\n Effect.succeed({\n type: \"snapshot\" as const,\n state: null,\n version: 0,\n })\n );\n yield* sendMessage(snapshot);\n break;\n\n case \"presence_set\":\n yield* handlePresenceSet(message.data);\n break;\n\n case \"presence_clear\":\n yield* handlePresenceClear;\n break;\n }\n });\n\n // Subscribe to document broadcasts\n const subscribeFiber = yield* Effect.fork(\n Effect.gen(function* () {\n // Wait until authenticated before subscribing\n while (!state.authenticated) {\n yield* Effect.sleep(Duration.millis(100));\n }\n\n // Subscribe to the document\n const broadcastStream = yield* Effect.catchAll(\n documentManager.subscribe(documentId),\n () => Effect.succeed(Stream.empty)\n );\n\n // Forward broadcasts to the WebSocket\n yield* Stream.runForEach(broadcastStream, (broadcast) =>\n sendMessage(broadcast as ServerMessage)\n );\n }).pipe(Effect.scoped)\n );\n\n // Subscribe to presence events (if presence is enabled)\n const presenceFiber = yield* Effect.fork(\n Effect.gen(function* () {\n if (!config.presence) return;\n\n // Wait until authenticated before subscribing\n while (!state.authenticated) {\n yield* Effect.sleep(Duration.millis(100));\n }\n\n // Subscribe to presence events\n const presenceStream = yield* presenceManager.subscribe(documentId);\n\n // Forward presence events to the WebSocket, filtering out our own events (no-echo)\n yield* Stream.runForEach(presenceStream, (event) =>\n Effect.gen(function* () {\n // Don't echo our own presence events\n if (event.id === connectionId) return;\n\n if (event.type === \"presence_update\") {\n yield* sendMessage({\n type: \"presence_update\",\n id: event.id,\n data: event.data,\n userId: event.userId,\n });\n } else if (event.type === \"presence_remove\") {\n yield* sendMessage({\n type: \"presence_remove\",\n id: event.id,\n });\n }\n })\n );\n }).pipe(Effect.scoped)\n );\n\n // Ensure cleanup on disconnect\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n // Interrupt the subscribe fibers\n yield* Fiber.interrupt(subscribeFiber);\n yield* Fiber.interrupt(presenceFiber);\n\n // Remove presence if we had any\n if (hasPresence && config.presence) {\n yield* presenceManager.remove(documentId, connectionId);\n }\n })\n );\n\n // Process incoming messages\n yield* socket.runRaw((data) =>\n Effect.gen(function* () {\n const message = yield* parseClientMessage(data);\n yield* handleMessage(message);\n }).pipe(\n Effect.catchAll((error) =>\n Effect.logError(\"Message handling error\", error)\n )\n )\n );\n });\n\n// =============================================================================\n// WebSocket Server Handler Factory\n// =============================================================================\n\n/**\n * Create a handler function for the WebSocket server.\n * Returns a function that takes a socket and document ID.\n */\nexport const makeHandler = Effect.gen(function* () {\n const config = yield* MimicServerConfigTag;\n const authService = yield* MimicAuthServiceTag;\n const documentManager = yield* DocumentManagerTag;\n const presenceManager = yield* PresenceManagerTag;\n\n return (socket: Socket.Socket, documentId: string) =>\n handleConnectionWithDocumentId(socket, documentId).pipe(\n Effect.provideService(MimicServerConfigTag, config),\n Effect.provideService(MimicAuthServiceTag, authService),\n Effect.provideService(DocumentManagerTag, documentManager),\n Effect.provideService(PresenceManagerTag, presenceManager),\n Effect.scoped\n );\n});\n\n/**\n * Handle a WebSocket connection for a document (using document ID directly).\n */\nconst handleConnectionWithDocumentId = (\n socket: Socket.Socket,\n documentId: string\n): Effect.Effect<\n void,\n Socket.SocketError | MessageParseError,\n MimicServerConfigTag | MimicAuthServiceTag | DocumentManagerTag | PresenceManagerTag | Scope.Scope\n> =>\n Effect.gen(function* () {\n const config = yield* MimicServerConfigTag;\n const authService = yield* MimicAuthServiceTag;\n const documentManager = yield* DocumentManagerTag;\n const presenceManager = yield* PresenceManagerTag;\n\n const connectionId = crypto.randomUUID();\n\n // Track connection state\n let state: ConnectionState = {\n documentId,\n connectionId,\n authenticated: false,\n };\n\n // Track if this connection has set presence (for cleanup)\n let hasPresence = false;\n\n // Get the socket writer\n const write = yield* socket.writer;\n\n // Helper to send a message to the client\n const sendMessage = (message: ServerMessage) =>\n write(encodeServerMessage(message));\n\n // Send presence snapshot after auth\n const sendPresenceSnapshot = Effect.gen(function* () {\n if (!config.presence) return;\n\n const snapshot = yield* presenceManager.getSnapshot(documentId);\n yield* sendMessage({\n type: \"presence_snapshot\",\n selfId: connectionId,\n presences: snapshot.presences,\n });\n });\n\n // Handle authentication using the auth service\n const handleAuth = (token: string) =>\n Effect.gen(function* () {\n const result = yield* authService.authenticate(token);\n\n if (result.success) {\n state = {\n ...state,\n authenticated: true,\n userId: result.userId,\n };\n yield* sendMessage({ type: \"auth_result\", success: true });\n\n // Send presence snapshot after successful auth\n yield* sendPresenceSnapshot;\n } else {\n yield* sendMessage({\n type: \"auth_result\",\n success: false,\n error: result.error,\n });\n }\n });\n\n // Handle presence set\n const handlePresenceSet = (data: unknown) =>\n Effect.gen(function* () {\n if (!state.authenticated) return;\n if (!config.presence) return;\n\n // Validate presence data against schema\n const validated = Presence.validateSafe(config.presence, data);\n if (validated === undefined) {\n yield* Effect.logWarning(\"Invalid presence data received\", { connectionId, data });\n return;\n }\n\n // Store in presence manager\n yield* presenceManager.set(documentId, connectionId, {\n data: validated,\n userId: state.userId,\n });\n\n hasPresence = true;\n });\n\n // Handle presence clear\n const handlePresenceClear = Effect.gen(function* () {\n if (!state.authenticated) return;\n if (!config.presence) return;\n\n yield* presenceManager.remove(documentId, connectionId);\n hasPresence = false;\n });\n\n // Handle a client message\n const handleMessage = (message: ClientMessage) =>\n Effect.gen(function* () {\n switch (message.type) {\n case \"auth\":\n yield* handleAuth(message.token);\n break;\n\n case \"ping\":\n yield* sendMessage({ type: \"pong\" });\n break;\n\n case \"submit\":\n if (!state.authenticated) {\n yield* sendMessage({\n type: \"error\",\n transactionId: message.transaction.id,\n reason: \"Not authenticated\",\n });\n return;\n }\n const submitResult = yield* documentManager.submit(\n documentId,\n message.transaction as any\n );\n if (!submitResult.success) {\n yield* sendMessage({\n type: \"error\",\n transactionId: message.transaction.id,\n reason: submitResult.reason,\n });\n }\n break;\n\n case \"request_snapshot\":\n if (!state.authenticated) {\n return;\n }\n const snapshot = yield* documentManager.getSnapshot(documentId);\n yield* sendMessage(snapshot);\n break;\n\n case \"presence_set\":\n yield* handlePresenceSet(message.data);\n break;\n\n case \"presence_clear\":\n yield* handlePresenceClear;\n break;\n }\n });\n\n // Subscribe to document broadcasts\n const subscribeFiber = yield* Effect.fork(\n Effect.gen(function* () {\n // Wait until authenticated before subscribing\n while (!state.authenticated) {\n yield* Effect.sleep(Duration.millis(100));\n }\n\n // Subscribe to the document\n const broadcastStream = yield* documentManager.subscribe(documentId);\n\n // Forward broadcasts to the WebSocket\n yield* Stream.runForEach(broadcastStream, (broadcast) =>\n sendMessage(broadcast as ServerMessage)\n );\n }).pipe(Effect.scoped)\n );\n\n // Subscribe to presence events (if presence is enabled)\n const presenceFiber = yield* Effect.fork(\n Effect.gen(function* () {\n if (!config.presence) return;\n\n // Wait until authenticated before subscribing\n while (!state.authenticated) {\n yield* Effect.sleep(Duration.millis(100));\n }\n\n // Subscribe to presence events\n const presenceStream = yield* presenceManager.subscribe(documentId);\n\n // Forward presence events to the WebSocket, filtering out our own events (no-echo)\n yield* Stream.runForEach(presenceStream, (event) =>\n Effect.gen(function* () {\n // Don't echo our own presence events\n if (event.id === connectionId) return;\n\n if (event.type === \"presence_update\") {\n yield* sendMessage({\n type: \"presence_update\",\n id: event.id,\n data: event.data,\n userId: event.userId,\n });\n } else if (event.type === \"presence_remove\") {\n yield* sendMessage({\n type: \"presence_remove\",\n id: event.id,\n });\n }\n })\n );\n }).pipe(Effect.scoped)\n );\n\n // Ensure cleanup on disconnect\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n // Interrupt the subscribe fibers\n yield* Fiber.interrupt(subscribeFiber);\n yield* Fiber.interrupt(presenceFiber);\n\n // Remove presence if we had any\n if (hasPresence && config.presence) {\n yield* presenceManager.remove(documentId, connectionId);\n }\n })\n );\n\n // Process incoming messages\n yield* socket.runRaw((data) =>\n Effect.gen(function* () {\n const message = yield* parseClientMessage(data);\n yield* handleMessage(message);\n }).pipe(\n Effect.catchAll((error) =>\n Effect.logError(\"Message handling error\", error)\n )\n )\n );\n });\n"],"mappings":"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"}
|
package/dist/auth/NoAuth.cjs
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
-
const require_MimicAuthService = require('../MimicAuthService.cjs');
|
|
3
|
-
let effect_Effect = require("effect/Effect");
|
|
4
|
-
effect_Effect = require_rolldown_runtime.__toESM(effect_Effect);
|
|
5
|
-
let effect_Layer = require("effect/Layer");
|
|
6
|
-
effect_Layer = require_rolldown_runtime.__toESM(effect_Layer);
|
|
7
|
-
|
|
8
|
-
//#region src/auth/NoAuth.ts
|
|
9
|
-
/**
|
|
10
|
-
* @since 0.0.1
|
|
11
|
-
* No authentication implementation for Mimic connections.
|
|
12
|
-
* All connections are automatically authenticated (open access).
|
|
13
|
-
*/
|
|
14
|
-
var NoAuth_exports = /* @__PURE__ */ require_rolldown_runtime.__export({
|
|
15
|
-
layer: () => layer,
|
|
16
|
-
layerDefault: () => layerDefault
|
|
17
|
-
});
|
|
18
|
-
/**
|
|
19
|
-
* Authentication service that auto-succeeds all authentication requests.
|
|
20
|
-
* Use this for development or when authentication is handled externally.
|
|
21
|
-
*/
|
|
22
|
-
const noAuthService = { authenticate: (_token) => effect_Effect.succeed({ success: true }) };
|
|
23
|
-
/**
|
|
24
|
-
* Layer that provides no authentication (open access).
|
|
25
|
-
* All connections are automatically authenticated.
|
|
26
|
-
*
|
|
27
|
-
* WARNING: Only use this for development or when authentication
|
|
28
|
-
* is handled at a different layer (e.g., API gateway, reverse proxy).
|
|
29
|
-
*/
|
|
30
|
-
const layer = effect_Layer.succeed(require_MimicAuthService.MimicAuthServiceTag, noAuthService);
|
|
31
|
-
/**
|
|
32
|
-
* Default layer alias for convenience.
|
|
33
|
-
*/
|
|
34
|
-
const layerDefault = layer;
|
|
35
|
-
|
|
36
|
-
//#endregion
|
|
37
|
-
Object.defineProperty(exports, 'NoAuth_exports', {
|
|
38
|
-
enumerable: true,
|
|
39
|
-
get: function () {
|
|
40
|
-
return NoAuth_exports;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
exports.layerDefault = layerDefault;
|
package/dist/auth/NoAuth.d.cts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { MimicAuthServiceTag } from "../MimicAuthService.cjs";
|
|
2
|
-
import * as Layer from "effect/Layer";
|
|
3
|
-
|
|
4
|
-
//#region src/auth/NoAuth.d.ts
|
|
5
|
-
declare namespace NoAuth_d_exports {
|
|
6
|
-
export { layer, layerDefault };
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Layer that provides no authentication (open access).
|
|
10
|
-
* All connections are automatically authenticated.
|
|
11
|
-
*
|
|
12
|
-
* WARNING: Only use this for development or when authentication
|
|
13
|
-
* is handled at a different layer (e.g., API gateway, reverse proxy).
|
|
14
|
-
*/
|
|
15
|
-
declare const layer: Layer.Layer<MimicAuthServiceTag>;
|
|
16
|
-
/**
|
|
17
|
-
* Default layer alias for convenience.
|
|
18
|
-
*/
|
|
19
|
-
declare const layerDefault: Layer.Layer<MimicAuthServiceTag, never, never>;
|
|
20
|
-
//#endregion
|
|
21
|
-
export { NoAuth_d_exports };
|
|
22
|
-
//# sourceMappingURL=NoAuth.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NoAuth.d.cts","names":[],"sources":["../../src/auth/NoAuth.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;AAqCa,cAAA,KAAmB,EAAZ,KAAA,CAAM,KAAM,CAAA,mBAAD,CAAA;AAQ/B;;;cAAa,cAAY,KAAA,CAAA,MAAA"}
|
package/dist/auth/NoAuth.d.mts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { MimicAuthServiceTag } from "../MimicAuthService.mjs";
|
|
2
|
-
import * as Layer from "effect/Layer";
|
|
3
|
-
|
|
4
|
-
//#region src/auth/NoAuth.d.ts
|
|
5
|
-
declare namespace NoAuth_d_exports {
|
|
6
|
-
export { layer, layerDefault };
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Layer that provides no authentication (open access).
|
|
10
|
-
* All connections are automatically authenticated.
|
|
11
|
-
*
|
|
12
|
-
* WARNING: Only use this for development or when authentication
|
|
13
|
-
* is handled at a different layer (e.g., API gateway, reverse proxy).
|
|
14
|
-
*/
|
|
15
|
-
declare const layer: Layer.Layer<MimicAuthServiceTag>;
|
|
16
|
-
/**
|
|
17
|
-
* Default layer alias for convenience.
|
|
18
|
-
*/
|
|
19
|
-
declare const layerDefault: Layer.Layer<MimicAuthServiceTag, never, never>;
|
|
20
|
-
//#endregion
|
|
21
|
-
export { NoAuth_d_exports };
|
|
22
|
-
//# sourceMappingURL=NoAuth.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NoAuth.d.mts","names":[],"sources":["../../src/auth/NoAuth.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;AAqCa,cAAA,KAAmB,EAAZ,KAAA,CAAM,KAAM,CAAA,mBAAD,CAAA;AAQ/B;;;cAAa,cAAY,KAAA,CAAA,MAAA"}
|
package/dist/auth/NoAuth.mjs
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { __export } from "../_virtual/rolldown_runtime.mjs";
|
|
2
|
-
import { MimicAuthServiceTag } from "../MimicAuthService.mjs";
|
|
3
|
-
import * as Effect from "effect/Effect";
|
|
4
|
-
import * as Layer from "effect/Layer";
|
|
5
|
-
|
|
6
|
-
//#region src/auth/NoAuth.ts
|
|
7
|
-
/**
|
|
8
|
-
* @since 0.0.1
|
|
9
|
-
* No authentication implementation for Mimic connections.
|
|
10
|
-
* All connections are automatically authenticated (open access).
|
|
11
|
-
*/
|
|
12
|
-
var NoAuth_exports = /* @__PURE__ */ __export({
|
|
13
|
-
layer: () => layer,
|
|
14
|
-
layerDefault: () => layerDefault
|
|
15
|
-
});
|
|
16
|
-
/**
|
|
17
|
-
* Authentication service that auto-succeeds all authentication requests.
|
|
18
|
-
* Use this for development or when authentication is handled externally.
|
|
19
|
-
*/
|
|
20
|
-
const noAuthService = { authenticate: (_token) => Effect.succeed({ success: true }) };
|
|
21
|
-
/**
|
|
22
|
-
* Layer that provides no authentication (open access).
|
|
23
|
-
* All connections are automatically authenticated.
|
|
24
|
-
*
|
|
25
|
-
* WARNING: Only use this for development or when authentication
|
|
26
|
-
* is handled at a different layer (e.g., API gateway, reverse proxy).
|
|
27
|
-
*/
|
|
28
|
-
const layer = Layer.succeed(MimicAuthServiceTag, noAuthService);
|
|
29
|
-
/**
|
|
30
|
-
* Default layer alias for convenience.
|
|
31
|
-
*/
|
|
32
|
-
const layerDefault = layer;
|
|
33
|
-
|
|
34
|
-
//#endregion
|
|
35
|
-
export { NoAuth_exports, layerDefault };
|
|
36
|
-
//# sourceMappingURL=NoAuth.mjs.map
|
package/dist/auth/NoAuth.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NoAuth.mjs","names":["noAuthService: MimicAuthService","layer: Layer.Layer<MimicAuthServiceTag>"],"sources":["../../src/auth/NoAuth.ts"],"sourcesContent":["/**\n * @since 0.0.1\n * No authentication implementation for Mimic connections.\n * All connections are automatically authenticated (open access).\n */\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\n\nimport {\n MimicAuthServiceTag,\n type MimicAuthService,\n} from \"../MimicAuthService.js\";\n\n// =============================================================================\n// No-Auth Implementation\n// =============================================================================\n\n/**\n * Authentication service that auto-succeeds all authentication requests.\n * Use this for development or when authentication is handled externally.\n */\nconst noAuthService: MimicAuthService = {\n authenticate: (_token: string) =>\n Effect.succeed({ success: true as const }),\n};\n\n// =============================================================================\n// Layer\n// =============================================================================\n\n/**\n * Layer that provides no authentication (open access).\n * All connections are automatically authenticated.\n * \n * WARNING: Only use this for development or when authentication\n * is handled at a different layer (e.g., API gateway, reverse proxy).\n */\nexport const layer: Layer.Layer<MimicAuthServiceTag> = Layer.succeed(\n MimicAuthServiceTag,\n noAuthService\n);\n\n/**\n * Default layer alias for convenience.\n */\nexport const layerDefault = layer;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,MAAMA,gBAAkC,EACtC,eAAe,WACb,OAAO,QAAQ,EAAE,SAAS,MAAe,CAAC,EAC7C;;;;;;;;AAaD,MAAaC,QAA0C,MAAM,QAC3D,qBACA,cACD;;;;AAKD,MAAa,eAAe"}
|
package/dist/errors.cjs
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
-
let effect_Data = require("effect/Data");
|
|
3
|
-
effect_Data = require_rolldown_runtime.__toESM(effect_Data);
|
|
4
|
-
|
|
5
|
-
//#region src/errors.ts
|
|
6
|
-
/**
|
|
7
|
-
* @since 0.0.1
|
|
8
|
-
* Error types for the Mimic server.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Error when a document type is not found in the schema registry.
|
|
12
|
-
*/
|
|
13
|
-
var DocumentTypeNotFoundError = class extends effect_Data.TaggedError("DocumentTypeNotFoundError") {
|
|
14
|
-
get message() {
|
|
15
|
-
return `Document type not found: ${this.documentType}`;
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* Error when a document is not found.
|
|
20
|
-
*/
|
|
21
|
-
var DocumentNotFoundError = class extends effect_Data.TaggedError("DocumentNotFoundError") {
|
|
22
|
-
get message() {
|
|
23
|
-
return `Document not found: ${this.documentId}`;
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Error when authentication fails.
|
|
28
|
-
*/
|
|
29
|
-
var AuthenticationError = class extends effect_Data.TaggedError("AuthenticationError") {
|
|
30
|
-
get message() {
|
|
31
|
-
return `Authentication failed: ${this.reason}`;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Error when a transaction is rejected.
|
|
36
|
-
*/
|
|
37
|
-
var TransactionRejectedError = class extends effect_Data.TaggedError("TransactionRejectedError") {
|
|
38
|
-
get message() {
|
|
39
|
-
return `Transaction ${this.transactionId} rejected: ${this.reason}`;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
/**
|
|
43
|
-
* Error when parsing a client message fails.
|
|
44
|
-
*/
|
|
45
|
-
var MessageParseError = class extends effect_Data.TaggedError("MessageParseError") {
|
|
46
|
-
get message() {
|
|
47
|
-
return `Failed to parse message: ${String(this.cause)}`;
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* Error when the WebSocket connection is invalid.
|
|
52
|
-
*/
|
|
53
|
-
var InvalidConnectionError = class extends effect_Data.TaggedError("InvalidConnectionError") {
|
|
54
|
-
get message() {
|
|
55
|
-
return `Invalid connection: ${this.reason}`;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Error when the document ID is missing from the URL path.
|
|
60
|
-
*/
|
|
61
|
-
var MissingDocumentIdError = class extends effect_Data.TaggedError("MissingDocumentIdError") {
|
|
62
|
-
get message() {
|
|
63
|
-
return this.path ? `Document ID is required in the URL path: ${this.path}` : "Document ID is required in the URL path";
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
//#endregion
|
|
68
|
-
exports.AuthenticationError = AuthenticationError;
|
|
69
|
-
exports.DocumentNotFoundError = DocumentNotFoundError;
|
|
70
|
-
exports.DocumentTypeNotFoundError = DocumentTypeNotFoundError;
|
|
71
|
-
exports.InvalidConnectionError = InvalidConnectionError;
|
|
72
|
-
exports.MessageParseError = MessageParseError;
|
|
73
|
-
exports.MissingDocumentIdError = MissingDocumentIdError;
|
|
74
|
-
exports.TransactionRejectedError = TransactionRejectedError;
|