@voidhash/mimic-effect 0.0.3 → 0.0.4

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @voidhash/mimic-effect@0.0.3 build /home/runner/work/mimic/mimic/packages/mimic-effect
2
+ > @voidhash/mimic-effect@0.0.4 build /home/runner/work/mimic/mimic/packages/mimic-effect
3
3
  > tsdown
4
4
 
5
5
  ℹ tsdown v0.18.2 powered by rolldown v1.0.0-beta.55
@@ -9,15 +9,15 @@
9
9
  ℹ tsconfig: tsconfig.json
10
10
  ℹ Build start
11
11
  ℹ [CJS] dist/index.cjs  2.79 kB │ gzip: 0.52 kB
12
- ℹ [CJS] dist/WebSocketHandler.cjs 13.86 kB │ gzip: 2.46 kB
13
- ℹ [CJS] dist/MimicServer.cjs 10.22 kB │ gzip: 2.47 kB
14
- ℹ [CJS] dist/DocumentManager.cjs  4.68 kB │ gzip: 1.38 kB
12
+ ℹ [CJS] dist/WebSocketHandler.cjs 13.83 kB │ gzip: 2.46 kB
13
+ ℹ [CJS] dist/MimicServer.cjs  5.93 kB │ gzip: 1.78 kB
14
+ ℹ [CJS] dist/DocumentManager.cjs  4.69 kB │ gzip: 1.38 kB
15
15
  ℹ [CJS] dist/PresenceManager.cjs  4.25 kB │ gzip: 1.19 kB
16
16
  ℹ [CJS] dist/MimicDataStorage.cjs  3.13 kB │ gzip: 0.96 kB
17
17
  ℹ [CJS] dist/DocumentProtocol.cjs  2.85 kB │ gzip: 0.79 kB
18
18
  ℹ [CJS] dist/errors.cjs  2.33 kB │ gzip: 0.63 kB
19
+ ℹ [CJS] dist/MimicConfig.cjs  2.32 kB │ gzip: 0.79 kB
19
20
  ℹ [CJS] dist/storage/InMemoryDataStorage.cjs  2.21 kB │ gzip: 0.80 kB
20
- ℹ [CJS] dist/MimicConfig.cjs  2.15 kB │ gzip: 0.74 kB
21
21
  ℹ [CJS] dist/MimicAuthService.cjs  2.12 kB │ gzip: 0.69 kB
22
22
  ℹ [CJS] dist/auth/NoAuth.cjs  1.52 kB │ gzip: 0.63 kB
23
23
  ℹ [CJS] dist/_virtual/rolldown_runtime.cjs  1.31 kB │ gzip: 0.61 kB
@@ -26,41 +26,41 @@
26
26
  ℹ [CJS] dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPrimitive.cjs  0.52 kB │ gzip: 0.32 kB
27
27
  ℹ [CJS] dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/defineProperty.cjs  0.40 kB │ gzip: 0.24 kB
28
28
  ℹ [CJS] dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPropertyKey.cjs  0.37 kB │ gzip: 0.23 kB
29
- ℹ [CJS] 18 files, total: 56.19 kB
29
+ ℹ [CJS] 18 files, total: 52.04 kB
30
30
  ℹ [CJS] dist/MimicDataStorage.d.cts.map 1.96 kB │ gzip: 0.73 kB
31
31
  ℹ [CJS] dist/DocumentProtocol.d.cts.map 1.35 kB │ gzip: 0.52 kB
32
32
  ℹ [CJS] dist/MimicAuthService.d.cts.map 0.97 kB │ gzip: 0.51 kB
33
- ℹ [CJS] dist/MimicServer.d.cts.map 0.95 kB │ gzip: 0.43 kB
34
- ℹ [CJS] dist/MimicConfig.d.cts.map 0.77 kB │ gzip: 0.41 kB
33
+ ℹ [CJS] dist/MimicConfig.d.cts.map 0.88 kB │ gzip: 0.46 kB
35
34
  ℹ [CJS] dist/errors.d.cts.map 0.77 kB │ gzip: 0.36 kB
36
35
  ℹ [CJS] dist/WebSocketHandler.d.cts.map 0.74 kB │ gzip: 0.35 kB
37
36
  ℹ [CJS] dist/PresenceManager.d.cts.map 0.69 kB │ gzip: 0.36 kB
37
+ ℹ [CJS] dist/MimicServer.d.cts.map 0.63 kB │ gzip: 0.33 kB
38
38
  ℹ [CJS] dist/DocumentManager.d.cts.map 0.52 kB │ gzip: 0.29 kB
39
39
  ℹ [CJS] dist/storage/InMemoryDataStorage.d.cts.map 0.26 kB │ gzip: 0.18 kB
40
40
  ℹ [CJS] dist/auth/NoAuth.d.cts.map 0.22 kB │ gzip: 0.17 kB
41
41
  ℹ [CJS] dist/index.d.cts 1.52 kB │ gzip: 0.37 kB
42
- ℹ [CJS] dist/MimicServer.d.cts 7.24 kB │ gzip: 2.01 kB
43
42
  ℹ [CJS] dist/MimicDataStorage.d.cts 4.84 kB │ gzip: 1.19 kB
43
+ ℹ [CJS] dist/MimicConfig.d.cts 4.11 kB │ gzip: 1.11 kB
44
44
  ℹ [CJS] dist/errors.d.cts 4.08 kB │ gzip: 0.75 kB
45
+ ℹ [CJS] dist/MimicServer.d.cts 4.00 kB │ gzip: 1.47 kB
45
46
  ℹ [CJS] dist/DocumentProtocol.d.cts 3.78 kB │ gzip: 0.78 kB
46
- ℹ [CJS] dist/MimicConfig.d.cts 3.47 kB │ gzip: 0.94 kB
47
47
  ℹ [CJS] dist/PresenceManager.d.cts 3.00 kB │ gzip: 0.90 kB
48
48
  ℹ [CJS] dist/MimicAuthService.d.cts 2.38 kB │ gzip: 0.77 kB
49
49
  ℹ [CJS] dist/DocumentManager.d.cts 1.77 kB │ gzip: 0.63 kB
50
50
  ℹ [CJS] dist/WebSocketHandler.d.cts 1.73 kB │ gzip: 0.63 kB
51
51
  ℹ [CJS] dist/auth/NoAuth.d.cts 0.72 kB │ gzip: 0.40 kB
52
52
  ℹ [CJS] dist/storage/InMemoryDataStorage.d.cts 0.65 kB │ gzip: 0.33 kB
53
- ℹ [CJS] 23 files, total: 44.41 kB
54
- ✔ Build complete in 5918ms
53
+ ℹ [CJS] 23 files, total: 41.59 kB
54
+ ✔ Build complete in 6093ms
55
55
  ℹ [ESM] dist/index.mjs  1.45 kB │ gzip: 0.36 kB
56
56
  ℹ [ESM] dist/WebSocketHandler.mjs.map 29.74 kB │ gzip: 5.00 kB
57
- ℹ [ESM] dist/MimicServer.mjs.map 15.45 kB │ gzip: 3.84 kB
58
- ℹ [ESM] dist/WebSocketHandler.mjs 12.38 kB │ gzip: 2.34 kB
57
+ ℹ [ESM] dist/WebSocketHandler.mjs 12.36 kB │ gzip: 2.34 kB
59
58
  ℹ [ESM] dist/PresenceManager.mjs.map 10.45 kB │ gzip: 2.54 kB
60
- ℹ [ESM] dist/DocumentManager.mjs.map  9.78 kB │ gzip: 2.79 kB
61
- ℹ [ESM] dist/MimicServer.mjs  8.91 kB │ gzip: 2.35 kB
59
+ ℹ [ESM] dist/DocumentManager.mjs.map  9.84 kB │ gzip: 2.81 kB
60
+ ℹ [ESM] dist/MimicServer.mjs.map  9.65 kB │ gzip: 3.00 kB
62
61
  ℹ [ESM] dist/MimicDataStorage.mjs.map  6.27 kB │ gzip: 1.55 kB
63
- ℹ [ESM] dist/MimicConfig.mjs.map  4.59 kB │ gzip: 1.25 kB
62
+ ℹ [ESM] dist/MimicConfig.mjs.map  5.48 kB │ gzip: 1.50 kB
63
+ ℹ [ESM] dist/MimicServer.mjs  5.12 kB │ gzip: 1.69 kB
64
64
  ℹ [ESM] dist/MimicAuthService.mjs.map  4.09 kB │ gzip: 1.10 kB
65
65
  ℹ [ESM] dist/DocumentProtocol.mjs.map  4.07 kB │ gzip: 1.01 kB
66
66
  ℹ [ESM] dist/DocumentManager.mjs  3.75 kB │ gzip: 1.25 kB
@@ -71,19 +71,19 @@
71
71
  ℹ [ESM] dist/DocumentProtocol.mjs  2.44 kB │ gzip: 0.73 kB
72
72
  ℹ [ESM] dist/MimicDataStorage.d.mts.map  1.96 kB │ gzip: 0.73 kB
73
73
  ℹ [ESM] dist/errors.mjs  1.95 kB │ gzip: 0.57 kB
74
+ ℹ [ESM] dist/MimicConfig.mjs  1.90 kB │ gzip: 0.70 kB
74
75
  ℹ [ESM] dist/auth/NoAuth.mjs.map  1.82 kB │ gzip: 0.68 kB
75
- ℹ [ESM] dist/MimicConfig.mjs  1.75 kB │ gzip: 0.65 kB
76
76
  ℹ [ESM] dist/MimicAuthService.mjs  1.74 kB │ gzip: 0.61 kB
77
77
  ℹ [ESM] dist/storage/InMemoryDataStorage.mjs  1.68 kB │ gzip: 0.71 kB
78
78
  ℹ [ESM] dist/DocumentProtocol.d.mts.map  1.35 kB │ gzip: 0.52 kB
79
79
  ℹ [ESM] dist/auth/NoAuth.mjs  1.21 kB │ gzip: 0.56 kB
80
80
  ℹ [ESM] dist/MimicAuthService.d.mts.map  0.97 kB │ gzip: 0.51 kB
81
- ℹ [ESM] dist/MimicServer.d.mts.map  0.95 kB │ gzip: 0.43 kB
82
81
  ℹ [ESM] dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.mjs  0.90 kB │ gzip: 0.42 kB
83
- ℹ [ESM] dist/MimicConfig.d.mts.map  0.77 kB │ gzip: 0.41 kB
82
+ ℹ [ESM] dist/MimicConfig.d.mts.map  0.88 kB │ gzip: 0.46 kB
84
83
  ℹ [ESM] dist/errors.d.mts.map  0.77 kB │ gzip: 0.36 kB
85
84
  ℹ [ESM] dist/WebSocketHandler.d.mts.map  0.74 kB │ gzip: 0.35 kB
86
85
  ℹ [ESM] dist/PresenceManager.d.mts.map  0.69 kB │ gzip: 0.36 kB
86
+ ℹ [ESM] dist/MimicServer.d.mts.map  0.63 kB │ gzip: 0.33 kB
87
87
  ℹ [ESM] dist/DocumentManager.d.mts.map  0.52 kB │ gzip: 0.29 kB
88
88
  ℹ [ESM] dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPrimitive.mjs  0.47 kB │ gzip: 0.30 kB
89
89
  ℹ [ESM] dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/typeof.mjs  0.43 kB │ gzip: 0.24 kB
@@ -93,16 +93,16 @@
93
93
  ℹ [ESM] dist/storage/InMemoryDataStorage.d.mts.map  0.26 kB │ gzip: 0.18 kB
94
94
  ℹ [ESM] dist/auth/NoAuth.d.mts.map  0.22 kB │ gzip: 0.17 kB
95
95
  ℹ [ESM] dist/index.d.mts  1.52 kB │ gzip: 0.37 kB
96
- ℹ [ESM] dist/MimicServer.d.mts  7.24 kB │ gzip: 2.01 kB
97
96
  ℹ [ESM] dist/MimicDataStorage.d.mts  4.84 kB │ gzip: 1.19 kB
97
+ ℹ [ESM] dist/MimicConfig.d.mts  4.11 kB │ gzip: 1.11 kB
98
98
  ℹ [ESM] dist/errors.d.mts  4.08 kB │ gzip: 0.75 kB
99
+ ℹ [ESM] dist/MimicServer.d.mts  4.00 kB │ gzip: 1.47 kB
99
100
  ℹ [ESM] dist/DocumentProtocol.d.mts  3.78 kB │ gzip: 0.78 kB
100
- ℹ [ESM] dist/MimicConfig.d.mts  3.47 kB │ gzip: 0.94 kB
101
101
  ℹ [ESM] dist/PresenceManager.d.mts  3.00 kB │ gzip: 0.90 kB
102
102
  ℹ [ESM] dist/MimicAuthService.d.mts  2.38 kB │ gzip: 0.77 kB
103
103
  ℹ [ESM] dist/DocumentManager.d.mts  1.77 kB │ gzip: 0.63 kB
104
104
  ℹ [ESM] dist/WebSocketHandler.d.mts  1.73 kB │ gzip: 0.63 kB
105
105
  ℹ [ESM] dist/auth/NoAuth.d.mts  0.72 kB │ gzip: 0.40 kB
106
106
  ℹ [ESM] dist/storage/InMemoryDataStorage.d.mts  0.65 kB │ gzip: 0.33 kB
107
- ℹ [ESM] 52 files, total: 183.11 kB
108
- ✔ Build complete in 5945ms
107
+ ℹ [ESM] 52 files, total: 171.79 kB
108
+ ✔ Build complete in 6104ms
@@ -5,14 +5,14 @@ let effect_Effect = require("effect/Effect");
5
5
  effect_Effect = require_rolldown_runtime.__toESM(effect_Effect);
6
6
  let effect_Layer = require("effect/Layer");
7
7
  effect_Layer = require_rolldown_runtime.__toESM(effect_Layer);
8
- let effect_Context = require("effect/Context");
9
- effect_Context = require_rolldown_runtime.__toESM(effect_Context);
10
8
  let effect_PubSub = require("effect/PubSub");
11
9
  effect_PubSub = require_rolldown_runtime.__toESM(effect_PubSub);
12
10
  let effect_Ref = require("effect/Ref");
13
11
  effect_Ref = require_rolldown_runtime.__toESM(effect_Ref);
14
12
  let effect_HashMap = require("effect/HashMap");
15
13
  effect_HashMap = require_rolldown_runtime.__toESM(effect_HashMap);
14
+ let effect_Context = require("effect/Context");
15
+ effect_Context = require_rolldown_runtime.__toESM(effect_Context);
16
16
  let effect_Stream = require("effect/Stream");
17
17
  effect_Stream = require_rolldown_runtime.__toESM(effect_Stream);
18
18
  let _voidhash_mimic_server = require("@voidhash/mimic/server");
@@ -45,7 +45,7 @@ const makeDocumentManager = effect_Effect.gen(function* () {
45
45
  return existing.value;
46
46
  }
47
47
  const rawState = yield* effect_Effect.catchAll(storage.load(documentId), () => effect_Effect.succeed(void 0));
48
- const initialState = rawState !== void 0 ? yield* storage.onLoad(rawState) : void 0;
48
+ const initialState = rawState !== void 0 ? yield* storage.onLoad(rawState) : config.initial;
49
49
  const pubsub = yield* effect_PubSub.unbounded();
50
50
  const serverDocument = _voidhash_mimic_server.ServerDocument.make({
51
51
  schema: config.schema,
@@ -1,10 +1,10 @@
1
1
  import { ServerBroadcast, SnapshotMessage, SubmitResult } from "./DocumentProtocol.cjs";
2
2
  import { MimicServerConfigTag } from "./MimicConfig.cjs";
3
3
  import { MimicDataStorageTag } from "./MimicDataStorage.cjs";
4
- import * as Effect from "effect/Effect";
5
4
  import * as Layer from "effect/Layer";
6
- import * as Context from "effect/Context";
7
5
  import { Transaction } from "@voidhash/mimic";
6
+ import * as Effect from "effect/Effect";
7
+ import * as Context from "effect/Context";
8
8
  import * as Scope from "effect/Scope";
9
9
  import * as Stream from "effect/Stream";
10
10
 
@@ -3,10 +3,10 @@ import { MimicServerConfigTag } from "./MimicConfig.mjs";
3
3
  import { MimicDataStorageTag } from "./MimicDataStorage.mjs";
4
4
  import * as Effect from "effect/Effect";
5
5
  import * as Layer from "effect/Layer";
6
- import * as Context from "effect/Context";
7
6
  import * as PubSub from "effect/PubSub";
8
7
  import * as Ref from "effect/Ref";
9
8
  import * as HashMap from "effect/HashMap";
9
+ import * as Context from "effect/Context";
10
10
  import * as Stream from "effect/Stream";
11
11
  import { ServerDocument } from "@voidhash/mimic/server";
12
12
 
@@ -38,7 +38,7 @@ const makeDocumentManager = Effect.gen(function* () {
38
38
  return existing.value;
39
39
  }
40
40
  const rawState = yield* Effect.catchAll(storage.load(documentId), () => Effect.succeed(void 0));
41
- const initialState = rawState !== void 0 ? yield* storage.onLoad(rawState) : void 0;
41
+ const initialState = rawState !== void 0 ? yield* storage.onLoad(rawState) : config.initial;
42
42
  const pubsub = yield* PubSub.unbounded();
43
43
  const serverDocument = ServerDocument.make({
44
44
  schema: config.schema,
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentManager.mjs","names":["instance: DocumentInstance","layer: Layer.Layer<\n DocumentManagerTag,\n never,\n MimicServerConfigTag | MimicDataStorageTag\n>"],"sources":["../src/DocumentManager.ts"],"sourcesContent":["/**\n * @since 0.0.1\n * Document manager that handles multiple document instances.\n */\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Ref from \"effect/Ref\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as Context from \"effect/Context\";\nimport * as Scope from \"effect/Scope\";\nimport * as Stream from \"effect/Stream\";\nimport type { Primitive, Transaction } from \"@voidhash/mimic\";\nimport { ServerDocument } from \"@voidhash/mimic/server\";\n\nimport * as Protocol from \"./DocumentProtocol.js\";\nimport { MimicServerConfigTag } from \"./MimicConfig.js\";\nimport { MimicDataStorageTag } from \"./MimicDataStorage.js\";\nimport { DocumentNotFoundError } from \"./errors.js\";\n\n// =============================================================================\n// Document Instance\n// =============================================================================\n\n/**\n * A managed document instance that holds state and manages subscribers.\n */\ninterface DocumentInstance {\n /** The underlying ServerDocument */\n readonly document: ServerDocument.ServerDocument<Primitive.AnyPrimitive>;\n /** PubSub for broadcasting messages to subscribers */\n readonly pubsub: PubSub.PubSub<Protocol.ServerBroadcast>;\n /** Reference count for cleanup */\n readonly refCount: Ref.Ref<number>;\n}\n\n// =============================================================================\n// Document Manager Service\n// =============================================================================\n\n/**\n * Service interface for the DocumentManager.\n */\nexport interface DocumentManager {\n /**\n * Submit a transaction to a document.\n */\n readonly submit: (\n documentId: string,\n transaction: Transaction.Transaction\n ) => Effect.Effect<Protocol.SubmitResult>;\n\n /**\n * Get a snapshot of a document.\n */\n readonly getSnapshot: (\n documentId: string\n ) => Effect.Effect<Protocol.SnapshotMessage>;\n\n /**\n * Subscribe to broadcasts for a document.\n * Returns a Stream of server broadcasts.\n */\n readonly subscribe: (\n documentId: string\n ) => Effect.Effect<\n Stream.Stream<Protocol.ServerBroadcast>,\n never,\n Scope.Scope\n >;\n}\n\n/**\n * Context tag for DocumentManager.\n */\nexport class DocumentManagerTag extends Context.Tag(\n \"@voidhash/mimic-server-effect/DocumentManager\"\n)<DocumentManagerTag, DocumentManager>() {}\n\n// =============================================================================\n// Document Manager Implementation\n// =============================================================================\n\n/**\n * Create the DocumentManager service.\n */\nconst makeDocumentManager = Effect.gen(function* () {\n const config = yield* MimicServerConfigTag;\n const storage = yield* MimicDataStorageTag;\n \n // Map of document ID to document instance\n const documents = yield* Ref.make(\n HashMap.empty<string, DocumentInstance>()\n );\n\n // Get or create a document instance\n const getOrCreateDocument = (\n documentId: string\n ): Effect.Effect<DocumentInstance> =>\n Effect.gen(function* () {\n const current = yield* Ref.get(documents);\n const existing = HashMap.get(current, documentId);\n\n if (existing._tag === \"Some\") {\n // Increment ref count\n yield* Ref.update(existing.value.refCount, (n) => n + 1);\n return existing.value;\n }\n\n // Load initial state from storage\n const rawState = yield* Effect.catchAll(\n storage.load(documentId),\n () => Effect.succeed(undefined)\n );\n\n // Transform loaded state with onLoad hook\n const initialState = rawState !== undefined\n ? yield* storage.onLoad(rawState)\n : undefined;\n\n // Create PubSub for broadcasting\n const pubsub = yield* PubSub.unbounded<Protocol.ServerBroadcast>();\n\n // Create ServerDocument with broadcast callback\n const serverDocument = ServerDocument.make({\n schema: config.schema,\n initialState: initialState as Primitive.InferState<typeof config.schema> | undefined,\n maxTransactionHistory: config.maxTransactionHistory,\n onBroadcast: (transactionMessage) => {\n // Get current state and save to storage\n const currentState = serverDocument.get();\n \n // Run save in background (fire-and-forget with error logging)\n Effect.runFork(\n Effect.gen(function* () {\n if (currentState !== undefined) {\n const transformedState = yield* storage.onSave(currentState);\n yield* Effect.catchAll(\n storage.save(documentId, transformedState),\n (error) => Effect.logError(\"Failed to save document\", error)\n );\n }\n })\n );\n\n // Broadcast to subscribers\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"transaction\",\n transaction: transactionMessage.transaction as Protocol.Transaction,\n version: transactionMessage.version,\n })\n );\n },\n onRejection: (transactionId, reason) => {\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"error\",\n transactionId,\n reason,\n })\n );\n },\n });\n\n const refCount = yield* Ref.make(1);\n\n const instance: DocumentInstance = {\n document: serverDocument,\n pubsub,\n refCount,\n };\n\n // Store in map\n yield* Ref.update(documents, (map) =>\n HashMap.set(map, documentId, instance)\n );\n\n return instance;\n });\n\n // Submit a transaction\n const submit = (\n documentId: string,\n transaction: Transaction.Transaction\n ): Effect.Effect<Protocol.SubmitResult> =>\n Effect.gen(function* () {\n const instance = yield* getOrCreateDocument(documentId);\n const result = instance.document.submit(transaction);\n return result;\n });\n\n // Get a snapshot\n const getSnapshot = (\n documentId: string\n ): Effect.Effect<Protocol.SnapshotMessage> =>\n Effect.gen(function* () {\n const instance = yield* getOrCreateDocument(documentId);\n const snapshot = instance.document.getSnapshot();\n return snapshot;\n });\n\n // Subscribe to broadcasts\n const subscribe = (\n documentId: string\n ): Effect.Effect<\n Stream.Stream<Protocol.ServerBroadcast>,\n never,\n Scope.Scope\n > =>\n Effect.gen(function* () {\n const instance = yield* getOrCreateDocument(documentId);\n\n // Subscribe to the PubSub\n const queue = yield* PubSub.subscribe(instance.pubsub);\n\n // Ensure cleanup on scope close\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n // Decrement ref count\n const count = yield* Ref.updateAndGet(\n instance.refCount,\n (n) => n - 1\n );\n\n // If no more subscribers, we could clean up the document\n // For now, we keep it alive (could add idle timeout)\n })\n );\n\n // Convert queue to stream\n return Stream.fromQueue(queue);\n });\n\n const manager: DocumentManager = {\n submit,\n getSnapshot,\n subscribe,\n };\n\n return manager;\n});\n\n/**\n * Layer that provides DocumentManager.\n * Requires MimicServerConfigTag and MimicDataStorageTag.\n */\nexport const layer: Layer.Layer<\n DocumentManagerTag,\n never,\n MimicServerConfigTag | MimicDataStorageTag\n> = Layer.effect(DocumentManagerTag, makeDocumentManager);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA2EA,IAAa,qBAAb,cAAwC,QAAQ,IAC9C,gDACD,EAAuC,CAAC;;;;AASzC,MAAM,sBAAsB,OAAO,IAAI,aAAa;CAClD,MAAM,SAAS,OAAO;CACtB,MAAM,UAAU,OAAO;CAGvB,MAAM,YAAY,OAAO,IAAI,KAC3B,QAAQ,OAAiC,CAC1C;CAGD,MAAM,uBACJ,eAEA,OAAO,IAAI,aAAa;EACtB,MAAM,UAAU,OAAO,IAAI,IAAI,UAAU;EACzC,MAAM,WAAW,QAAQ,IAAI,SAAS,WAAW;AAEjD,MAAI,SAAS,SAAS,QAAQ;AAE5B,UAAO,IAAI,OAAO,SAAS,MAAM,WAAW,MAAM,IAAI,EAAE;AACxD,UAAO,SAAS;;EAIlB,MAAM,WAAW,OAAO,OAAO,SAC7B,QAAQ,KAAK,WAAW,QAClB,OAAO,QAAQ,OAAU,CAChC;EAGD,MAAM,eAAe,aAAa,SAC9B,OAAO,QAAQ,OAAO,SAAS,GAC/B;EAGJ,MAAM,SAAS,OAAO,OAAO,WAAqC;EAGlE,MAAM,iBAAiB,eAAe,KAAK;GACzC,QAAQ,OAAO;GACD;GACd,uBAAuB,OAAO;GAC9B,cAAc,uBAAuB;IAEnC,MAAM,eAAe,eAAe,KAAK;AAGzC,WAAO,QACL,OAAO,IAAI,aAAa;AACtB,SAAI,iBAAiB,QAAW;MAC9B,MAAM,mBAAmB,OAAO,QAAQ,OAAO,aAAa;AAC5D,aAAO,OAAO,SACZ,QAAQ,KAAK,YAAY,iBAAiB,GACzC,UAAU,OAAO,SAAS,2BAA2B,MAAM,CAC7D;;MAEH,CACH;AAGD,WAAO,QACL,OAAO,QAAQ,QAAQ;KACrB,MAAM;KACN,aAAa,mBAAmB;KAChC,SAAS,mBAAmB;KAC7B,CAAC,CACH;;GAEH,cAAc,eAAe,WAAW;AACtC,WAAO,QACL,OAAO,QAAQ,QAAQ;KACrB,MAAM;KACN;KACA;KACD,CAAC,CACH;;GAEJ,CAAC;EAIF,MAAMA,WAA6B;GACjC,UAAU;GACV;GACA,UALe,OAAO,IAAI,KAAK,EAAE;GAMlC;AAGD,SAAO,IAAI,OAAO,YAAY,QAC5B,QAAQ,IAAI,KAAK,YAAY,SAAS,CACvC;AAED,SAAO;GACP;CAGJ,MAAM,UACJ,YACA,gBAEA,OAAO,IAAI,aAAa;AAGtB,UAFiB,OAAO,oBAAoB,WAAW,EAC/B,SAAS,OAAO,YAAY;GAEpD;CAGJ,MAAM,eACJ,eAEA,OAAO,IAAI,aAAa;AAGtB,UAFiB,OAAO,oBAAoB,WAAW,EAC7B,SAAS,aAAa;GAEhD;CAGJ,MAAM,aACJ,eAMA,OAAO,IAAI,aAAa;EACtB,MAAM,WAAW,OAAO,oBAAoB,WAAW;EAGvD,MAAM,QAAQ,OAAO,OAAO,UAAU,SAAS,OAAO;AAGtD,SAAO,OAAO,mBACZ,OAAO,IAAI,aAAa;AAER,UAAO,IAAI,aACvB,SAAS,WACR,MAAM,IAAI,EACZ;IAID,CACH;AAGD,SAAO,OAAO,UAAU,MAAM;GAC9B;AAQJ,QANiC;EAC/B;EACA;EACA;EACD;EAGD;;;;;AAMF,MAAaC,QAIT,MAAM,OAAO,oBAAoB,oBAAoB"}
1
+ {"version":3,"file":"DocumentManager.mjs","names":["instance: DocumentInstance","layer: Layer.Layer<\n DocumentManagerTag,\n never,\n MimicServerConfigTag | MimicDataStorageTag\n>"],"sources":["../src/DocumentManager.ts"],"sourcesContent":["/**\n * @since 0.0.1\n * Document manager that handles multiple document instances.\n */\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Ref from \"effect/Ref\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as Context from \"effect/Context\";\nimport * as Scope from \"effect/Scope\";\nimport * as Stream from \"effect/Stream\";\nimport type { Primitive, Transaction } from \"@voidhash/mimic\";\nimport { ServerDocument } from \"@voidhash/mimic/server\";\n\nimport * as Protocol from \"./DocumentProtocol.js\";\nimport { MimicServerConfigTag } from \"./MimicConfig.js\";\nimport { MimicDataStorageTag } from \"./MimicDataStorage.js\";\nimport { DocumentNotFoundError } from \"./errors.js\";\n\n// =============================================================================\n// Document Instance\n// =============================================================================\n\n/**\n * A managed document instance that holds state and manages subscribers.\n */\ninterface DocumentInstance {\n /** The underlying ServerDocument */\n readonly document: ServerDocument.ServerDocument<Primitive.AnyPrimitive>;\n /** PubSub for broadcasting messages to subscribers */\n readonly pubsub: PubSub.PubSub<Protocol.ServerBroadcast>;\n /** Reference count for cleanup */\n readonly refCount: Ref.Ref<number>;\n}\n\n// =============================================================================\n// Document Manager Service\n// =============================================================================\n\n/**\n * Service interface for the DocumentManager.\n */\nexport interface DocumentManager {\n /**\n * Submit a transaction to a document.\n */\n readonly submit: (\n documentId: string,\n transaction: Transaction.Transaction\n ) => Effect.Effect<Protocol.SubmitResult>;\n\n /**\n * Get a snapshot of a document.\n */\n readonly getSnapshot: (\n documentId: string\n ) => Effect.Effect<Protocol.SnapshotMessage>;\n\n /**\n * Subscribe to broadcasts for a document.\n * Returns a Stream of server broadcasts.\n */\n readonly subscribe: (\n documentId: string\n ) => Effect.Effect<\n Stream.Stream<Protocol.ServerBroadcast>,\n never,\n Scope.Scope\n >;\n}\n\n/**\n * Context tag for DocumentManager.\n */\nexport class DocumentManagerTag extends Context.Tag(\n \"@voidhash/mimic-server-effect/DocumentManager\"\n)<DocumentManagerTag, DocumentManager>() {}\n\n// =============================================================================\n// Document Manager Implementation\n// =============================================================================\n\n/**\n * Create the DocumentManager service.\n */\nconst makeDocumentManager = Effect.gen(function* () {\n const config = yield* MimicServerConfigTag;\n const storage = yield* MimicDataStorageTag;\n \n // Map of document ID to document instance\n const documents = yield* Ref.make(\n HashMap.empty<string, DocumentInstance>()\n );\n\n // Get or create a document instance\n const getOrCreateDocument = (\n documentId: string\n ): Effect.Effect<DocumentInstance> =>\n Effect.gen(function* () {\n const current = yield* Ref.get(documents);\n const existing = HashMap.get(current, documentId);\n\n if (existing._tag === \"Some\") {\n // Increment ref count\n yield* Ref.update(existing.value.refCount, (n) => n + 1);\n return existing.value;\n }\n\n // Load initial state from storage\n const rawState = yield* Effect.catchAll(\n storage.load(documentId),\n () => Effect.succeed(undefined)\n );\n\n // Transform loaded state with onLoad hook, or use configured initial state for new docs\n const initialState = rawState !== undefined\n ? yield* storage.onLoad(rawState)\n : config.initial;\n\n // Create PubSub for broadcasting\n const pubsub = yield* PubSub.unbounded<Protocol.ServerBroadcast>();\n\n // Create ServerDocument with broadcast callback\n const serverDocument = ServerDocument.make({\n schema: config.schema,\n initialState: initialState as Primitive.InferState<typeof config.schema> | undefined,\n maxTransactionHistory: config.maxTransactionHistory,\n onBroadcast: (transactionMessage) => {\n // Get current state and save to storage\n const currentState = serverDocument.get();\n \n // Run save in background (fire-and-forget with error logging)\n Effect.runFork(\n Effect.gen(function* () {\n if (currentState !== undefined) {\n const transformedState = yield* storage.onSave(currentState);\n yield* Effect.catchAll(\n storage.save(documentId, transformedState),\n (error) => Effect.logError(\"Failed to save document\", error)\n );\n }\n })\n );\n\n // Broadcast to subscribers\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"transaction\",\n transaction: transactionMessage.transaction as Protocol.Transaction,\n version: transactionMessage.version,\n })\n );\n },\n onRejection: (transactionId, reason) => {\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"error\",\n transactionId,\n reason,\n })\n );\n },\n });\n\n const refCount = yield* Ref.make(1);\n\n const instance: DocumentInstance = {\n document: serverDocument,\n pubsub,\n refCount,\n };\n\n // Store in map\n yield* Ref.update(documents, (map) =>\n HashMap.set(map, documentId, instance)\n );\n\n return instance;\n });\n\n // Submit a transaction\n const submit = (\n documentId: string,\n transaction: Transaction.Transaction\n ): Effect.Effect<Protocol.SubmitResult> =>\n Effect.gen(function* () {\n const instance = yield* getOrCreateDocument(documentId);\n const result = instance.document.submit(transaction);\n return result;\n });\n\n // Get a snapshot\n const getSnapshot = (\n documentId: string\n ): Effect.Effect<Protocol.SnapshotMessage> =>\n Effect.gen(function* () {\n const instance = yield* getOrCreateDocument(documentId);\n const snapshot = instance.document.getSnapshot();\n return snapshot;\n });\n\n // Subscribe to broadcasts\n const subscribe = (\n documentId: string\n ): Effect.Effect<\n Stream.Stream<Protocol.ServerBroadcast>,\n never,\n Scope.Scope\n > =>\n Effect.gen(function* () {\n const instance = yield* getOrCreateDocument(documentId);\n\n // Subscribe to the PubSub\n const queue = yield* PubSub.subscribe(instance.pubsub);\n\n // Ensure cleanup on scope close\n yield* Effect.addFinalizer(() =>\n Effect.gen(function* () {\n // Decrement ref count\n const count = yield* Ref.updateAndGet(\n instance.refCount,\n (n) => n - 1\n );\n\n // If no more subscribers, we could clean up the document\n // For now, we keep it alive (could add idle timeout)\n })\n );\n\n // Convert queue to stream\n return Stream.fromQueue(queue);\n });\n\n const manager: DocumentManager = {\n submit,\n getSnapshot,\n subscribe,\n };\n\n return manager;\n});\n\n/**\n * Layer that provides DocumentManager.\n * Requires MimicServerConfigTag and MimicDataStorageTag.\n */\nexport const layer: Layer.Layer<\n DocumentManagerTag,\n never,\n MimicServerConfigTag | MimicDataStorageTag\n> = Layer.effect(DocumentManagerTag, makeDocumentManager);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA2EA,IAAa,qBAAb,cAAwC,QAAQ,IAC9C,gDACD,EAAuC,CAAC;;;;AASzC,MAAM,sBAAsB,OAAO,IAAI,aAAa;CAClD,MAAM,SAAS,OAAO;CACtB,MAAM,UAAU,OAAO;CAGvB,MAAM,YAAY,OAAO,IAAI,KAC3B,QAAQ,OAAiC,CAC1C;CAGD,MAAM,uBACJ,eAEA,OAAO,IAAI,aAAa;EACtB,MAAM,UAAU,OAAO,IAAI,IAAI,UAAU;EACzC,MAAM,WAAW,QAAQ,IAAI,SAAS,WAAW;AAEjD,MAAI,SAAS,SAAS,QAAQ;AAE5B,UAAO,IAAI,OAAO,SAAS,MAAM,WAAW,MAAM,IAAI,EAAE;AACxD,UAAO,SAAS;;EAIlB,MAAM,WAAW,OAAO,OAAO,SAC7B,QAAQ,KAAK,WAAW,QAClB,OAAO,QAAQ,OAAU,CAChC;EAGD,MAAM,eAAe,aAAa,SAC9B,OAAO,QAAQ,OAAO,SAAS,GAC/B,OAAO;EAGX,MAAM,SAAS,OAAO,OAAO,WAAqC;EAGlE,MAAM,iBAAiB,eAAe,KAAK;GACzC,QAAQ,OAAO;GACD;GACd,uBAAuB,OAAO;GAC9B,cAAc,uBAAuB;IAEnC,MAAM,eAAe,eAAe,KAAK;AAGzC,WAAO,QACL,OAAO,IAAI,aAAa;AACtB,SAAI,iBAAiB,QAAW;MAC9B,MAAM,mBAAmB,OAAO,QAAQ,OAAO,aAAa;AAC5D,aAAO,OAAO,SACZ,QAAQ,KAAK,YAAY,iBAAiB,GACzC,UAAU,OAAO,SAAS,2BAA2B,MAAM,CAC7D;;MAEH,CACH;AAGD,WAAO,QACL,OAAO,QAAQ,QAAQ;KACrB,MAAM;KACN,aAAa,mBAAmB;KAChC,SAAS,mBAAmB;KAC7B,CAAC,CACH;;GAEH,cAAc,eAAe,WAAW;AACtC,WAAO,QACL,OAAO,QAAQ,QAAQ;KACrB,MAAM;KACN;KACA;KACD,CAAC,CACH;;GAEJ,CAAC;EAIF,MAAMA,WAA6B;GACjC,UAAU;GACV;GACA,UALe,OAAO,IAAI,KAAK,EAAE;GAMlC;AAGD,SAAO,IAAI,OAAO,YAAY,QAC5B,QAAQ,IAAI,KAAK,YAAY,SAAS,CACvC;AAED,SAAO;GACP;CAGJ,MAAM,UACJ,YACA,gBAEA,OAAO,IAAI,aAAa;AAGtB,UAFiB,OAAO,oBAAoB,WAAW,EAC/B,SAAS,OAAO,YAAY;GAEpD;CAGJ,MAAM,eACJ,eAEA,OAAO,IAAI,aAAa;AAGtB,UAFiB,OAAO,oBAAoB,WAAW,EAC7B,SAAS,aAAa;GAEhD;CAGJ,MAAM,aACJ,eAMA,OAAO,IAAI,aAAa;EACtB,MAAM,WAAW,OAAO,oBAAoB,WAAW;EAGvD,MAAM,QAAQ,OAAO,OAAO,UAAU,SAAS,OAAO;AAGtD,SAAO,OAAO,mBACZ,OAAO,IAAI,aAAa;AAER,UAAO,IAAI,aACvB,SAAS,WACR,MAAM,IAAI,EACZ;IAID,CACH;AAGD,SAAO,OAAO,UAAU,MAAM;GAC9B;AAQJ,QANiC;EAC/B;EACA;EACA;EACD;EAGD;;;;;AAMF,MAAaC,QAIT,MAAM,OAAO,oBAAoB,oBAAoB"}
@@ -1,5 +1,5 @@
1
- import * as Effect from "effect/Effect";
2
1
  import * as Layer from "effect/Layer";
2
+ import * as Effect from "effect/Effect";
3
3
  import * as Context from "effect/Context";
4
4
 
5
5
  //#region src/MimicAuthService.d.ts
@@ -5,6 +5,7 @@ let effect_Context = require("effect/Context");
5
5
  effect_Context = require_rolldown_runtime.__toESM(effect_Context);
6
6
  let effect_Duration = require("effect/Duration");
7
7
  effect_Duration = require_rolldown_runtime.__toESM(effect_Duration);
8
+ let _voidhash_mimic = require("@voidhash/mimic");
8
9
 
9
10
  //#region src/MimicConfig.ts
10
11
  /**
@@ -27,7 +28,8 @@ const make = (options) => {
27
28
  maxTransactionHistory: (_options$maxTransacti = options.maxTransactionHistory) !== null && _options$maxTransacti !== void 0 ? _options$maxTransacti : 1e3,
28
29
  heartbeatInterval: effect_Duration.decode((_options$heartbeatInt = options.heartbeatInterval) !== null && _options$heartbeatInt !== void 0 ? _options$heartbeatInt : "30 seconds"),
29
30
  heartbeatTimeout: effect_Duration.decode((_options$heartbeatTim = options.heartbeatTimeout) !== null && _options$heartbeatTim !== void 0 ? _options$heartbeatTim : "10 seconds"),
30
- presence: options.presence
31
+ presence: options.presence,
32
+ initial: options.initial !== void 0 ? _voidhash_mimic.Primitive.applyDefaults(options.schema, options.initial) : void 0
31
33
  };
32
34
  };
33
35
  /**
@@ -1,6 +1,6 @@
1
1
  import * as Layer from "effect/Layer";
2
- import * as Context from "effect/Context";
3
2
  import { Presence, Primitive } from "@voidhash/mimic";
3
+ import * as Context from "effect/Context";
4
4
  import * as Duration from "effect/Duration";
5
5
  import { DurationInput } from "effect/Duration";
6
6
 
@@ -45,6 +45,12 @@ interface MimicServerConfig<TSchema extends Primitive.AnyPrimitive = Primitive.A
45
45
  * @default undefined (presence disabled)
46
46
  */
47
47
  readonly presence: Presence.AnyPresence | undefined;
48
+ /**
49
+ * Initial state for new documents.
50
+ * Used when a document is created and no existing state is found in storage.
51
+ * @default undefined (documents start empty)
52
+ */
53
+ readonly initial: Primitive.InferState<TSchema> | undefined;
48
54
  }
49
55
  /**
50
56
  * Options for creating a MimicServerConfig.
@@ -80,6 +86,16 @@ interface MimicServerConfigOptions<TSchema extends Primitive.AnyPrimitive = Prim
80
86
  * @default undefined (presence disabled)
81
87
  */
82
88
  readonly presence?: Presence.AnyPresence;
89
+ /**
90
+ * Initial state for new documents.
91
+ * Used when a document is created and no existing state is found in storage.
92
+ *
93
+ * Type-safe: required fields (without defaults) must be provided,
94
+ * while optional fields and fields with defaults can be omitted.
95
+ *
96
+ * @default undefined (documents start empty or use schema defaults)
97
+ */
98
+ readonly initial?: Primitive.InferSetInput<TSchema>;
83
99
  }
84
100
  /**
85
101
  * Create a MimicServerConfig from options.
@@ -1 +1 @@
1
- {"version":3,"file":"MimicConfig.d.cts","names":[],"sources":["../src/MimicConfig.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;AAoBiB,UAAA,iBAAiB,CAAA,gBAAiB,SAAA,CAAU,YAA3B,GAA0C,SAAA,CAAU,YAApD,CAAA,CAAA;EAAiB;;;EAU3B,SAAS,MAAA,EANd,OAMc;EAYH;;;;EAmBb,SAAA,WAAA,EA/BO,QAAA,CAAS,QA+BQ;EAAiB;;;;EAsB3B,SAAA,qBAAA,EAAA,MAAA;EAMD;;;AAa9B;EAAqC,SAAU,iBAAA,EA5DjB,QAAA,CAAS,QA4DQ;EACX;;;;EAChB,SAAA,gBAAA,EAxDS,QAAA,CAAS,QAwDlB;EAOjB;;;;;qBAxDkB,QAAA,CAAS;AAiE9B;AAOA;;;AACW,UAnEM,wBAmEN,CAAA,gBAnE+C,SAAA,CAAU,YAmEzD,GAnEwE,SAAA,CAAU,YAmElF,CAAA,CAAA;EACI;;;mBAhEI;;;;;yBAMM;;;;;;;;;;+BAYM;;;;;8BAMD;;;;;;sBAOR,QAAA,CAAS;;;;;cAMlB,uBAAwB,SAAA,CAAU,uBACpC,yBAAyB,aACjC,kBAAkB;cAOlB;;;;cASU,oBAAA,SAA6B,yBAAA;;;;cAO7B,wBAAyB,SAAA,CAAU,uBACrC,yBAAyB,aACjC,KAAA,CAAM,MAAM"}
1
+ {"version":3,"file":"MimicConfig.d.cts","names":[],"sources":["../src/MimicConfig.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;AAoBiB,UAAA,iBAAiB,CAAA,gBAAiB,SAAA,CAAU,YAA3B,GAA0C,SAAA,CAAU,YAApD,CAAA,CAAA;EAAiB;;;EAU3B,SAAS,MAAA,EANd,OAMc;EAYH;;;;EAoBV,SAAU,WAAA,EAhCN,QAAA,CAAS,QAgCH;EAAU;AAMxC;;;EAImB,SAAA,qBAAA,EAAA,MAAA;EAMM;;;;EAoCoB,SAAA,iBAAA,EAxEf,QAAA,CAAS,QAwEM;EAAxB;;AAMrB;;EACoC,SAAA,gBAAA,EAzEP,QAAA,CAAS,QAyEF;EAAzB;;;;AAWR;qBA7EkB,QAAA,CAAS;;;;;AAsF9B;EAOa,SAGuC,OAAA,EAzFhC,SAAA,CAAU,UAyFsB,CAzFX,OAyFW,CAAA,GAAA,SAAA;;;;;AAD3C,UAlFQ,wBAkFR,CAAA,gBAlFiD,SAAA,CAAU,YAkF3D,GAlF0E,SAAA,CAAU,YAkFpF,CAAA,CAAA;EAAK;;;mBA9EK;;;;;yBAMM;;;;;;;;;;+BAYM;;;;;8BAMD;;;;;;sBAOR,QAAA,CAAS;;;;;;;;;;qBAWV,SAAA,CAAU,cAAc;;;;;cAMhC,uBAAwB,SAAA,CAAU,uBACpC,yBAAyB,aACjC,kBAAkB;cAUlB;;;;cASU,oBAAA,SAA6B,yBAAA;;;;cAO7B,wBAAyB,SAAA,CAAU,uBACrC,yBAAyB,aACjC,KAAA,CAAM,MAAM"}
@@ -45,6 +45,12 @@ interface MimicServerConfig<TSchema extends Primitive.AnyPrimitive = Primitive.A
45
45
  * @default undefined (presence disabled)
46
46
  */
47
47
  readonly presence: Presence.AnyPresence | undefined;
48
+ /**
49
+ * Initial state for new documents.
50
+ * Used when a document is created and no existing state is found in storage.
51
+ * @default undefined (documents start empty)
52
+ */
53
+ readonly initial: Primitive.InferState<TSchema> | undefined;
48
54
  }
49
55
  /**
50
56
  * Options for creating a MimicServerConfig.
@@ -80,6 +86,16 @@ interface MimicServerConfigOptions<TSchema extends Primitive.AnyPrimitive = Prim
80
86
  * @default undefined (presence disabled)
81
87
  */
82
88
  readonly presence?: Presence.AnyPresence;
89
+ /**
90
+ * Initial state for new documents.
91
+ * Used when a document is created and no existing state is found in storage.
92
+ *
93
+ * Type-safe: required fields (without defaults) must be provided,
94
+ * while optional fields and fields with defaults can be omitted.
95
+ *
96
+ * @default undefined (documents start empty or use schema defaults)
97
+ */
98
+ readonly initial?: Primitive.InferSetInput<TSchema>;
83
99
  }
84
100
  /**
85
101
  * Create a MimicServerConfig from options.
@@ -1 +1 @@
1
- {"version":3,"file":"MimicConfig.d.mts","names":[],"sources":["../src/MimicConfig.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;AAoBiB,UAAA,iBAAiB,CAAA,gBAAiB,SAAA,CAAU,YAA3B,GAA0C,SAAA,CAAU,YAApD,CAAA,CAAA;EAAiB;;;EAU3B,SAAS,MAAA,EANd,OAMc;EAYH;;;;EAmBb,SAAA,WAAA,EA/BO,QAAA,CAAS,QA+BQ;EAAiB;;;;EAsB3B,SAAA,qBAAA,EAAA,MAAA;EAMD;;;AAa9B;EAAqC,SAAU,iBAAA,EA5DjB,QAAA,CAAS,QA4DQ;EACX;;;;EAChB,SAAA,gBAAA,EAxDS,QAAA,CAAS,QAwDlB;EAOjB;;;;;qBAxDkB,QAAA,CAAS;AAiE9B;AAOA;;;AACW,UAnEM,wBAmEN,CAAA,gBAnE+C,SAAA,CAAU,YAmEzD,GAnEwE,SAAA,CAAU,YAmElF,CAAA,CAAA;EACI;;;mBAhEI;;;;;yBAMM;;;;;;;;;;+BAYM;;;;;8BAMD;;;;;;sBAOR,QAAA,CAAS;;;;;cAMlB,uBAAwB,SAAA,CAAU,uBACpC,yBAAyB,aACjC,kBAAkB;cAOlB;;;;cASU,oBAAA,SAA6B,yBAAA;;;;cAO7B,wBAAyB,SAAA,CAAU,uBACrC,yBAAyB,aACjC,KAAA,CAAM,MAAM"}
1
+ {"version":3,"file":"MimicConfig.d.mts","names":[],"sources":["../src/MimicConfig.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;AAoBiB,UAAA,iBAAiB,CAAA,gBAAiB,SAAA,CAAU,YAA3B,GAA0C,SAAA,CAAU,YAApD,CAAA,CAAA;EAAiB;;;EAU3B,SAAS,MAAA,EANd,OAMc;EAYH;;;;EAoBV,SAAU,WAAA,EAhCN,QAAA,CAAS,QAgCH;EAAU;AAMxC;;;EAImB,SAAA,qBAAA,EAAA,MAAA;EAMM;;;;EAoCoB,SAAA,iBAAA,EAxEf,QAAA,CAAS,QAwEM;EAAxB;;AAMrB;;EACoC,SAAA,gBAAA,EAzEP,QAAA,CAAS,QAyEF;EAAzB;;;;AAWR;qBA7EkB,QAAA,CAAS;;;;;AAsF9B;EAOa,SAGuC,OAAA,EAzFhC,SAAA,CAAU,UAyFsB,CAzFX,OAyFW,CAAA,GAAA,SAAA;;;;;AAD3C,UAlFQ,wBAkFR,CAAA,gBAlFiD,SAAA,CAAU,YAkF3D,GAlF0E,SAAA,CAAU,YAkFpF,CAAA,CAAA;EAAK;;;mBA9EK;;;;;yBAMM;;;;;;;;;;+BAYM;;;;;8BAMD;;;;;;sBAOR,QAAA,CAAS;;;;;;;;;;qBAWV,SAAA,CAAU,cAAc;;;;;cAMhC,uBAAwB,SAAA,CAAU,uBACpC,yBAAyB,aACjC,kBAAkB;cAUlB;;;;cASU,oBAAA,SAA6B,yBAAA;;;;cAO7B,wBAAyB,SAAA,CAAU,uBACrC,yBAAyB,aACjC,KAAA,CAAM,MAAM"}
@@ -2,6 +2,7 @@ import { __export } from "./_virtual/rolldown_runtime.mjs";
2
2
  import * as Layer from "effect/Layer";
3
3
  import * as Context from "effect/Context";
4
4
  import * as Duration from "effect/Duration";
5
+ import { Primitive } from "@voidhash/mimic";
5
6
 
6
7
  //#region src/MimicConfig.ts
7
8
  /**
@@ -24,7 +25,8 @@ const make = (options) => {
24
25
  maxTransactionHistory: (_options$maxTransacti = options.maxTransactionHistory) !== null && _options$maxTransacti !== void 0 ? _options$maxTransacti : 1e3,
25
26
  heartbeatInterval: Duration.decode((_options$heartbeatInt = options.heartbeatInterval) !== null && _options$heartbeatInt !== void 0 ? _options$heartbeatInt : "30 seconds"),
26
27
  heartbeatTimeout: Duration.decode((_options$heartbeatTim = options.heartbeatTimeout) !== null && _options$heartbeatTim !== void 0 ? _options$heartbeatTim : "10 seconds"),
27
- presence: options.presence
28
+ presence: options.presence,
29
+ initial: options.initial !== void 0 ? Primitive.applyDefaults(options.schema, options.initial) : void 0
28
30
  };
29
31
  };
30
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"MimicConfig.mjs","names":[],"sources":["../src/MimicConfig.ts"],"sourcesContent":["/**\n * @since 0.0.1\n * Configuration types for the Mimic server.\n */\nimport * as Context from \"effect/Context\";\nimport * as Duration from \"effect/Duration\";\nimport type { DurationInput } from \"effect/Duration\";\nimport * as Layer from \"effect/Layer\";\nimport type { Primitive, Presence } from \"@voidhash/mimic\";\n\n// =============================================================================\n// Mimic Server Configuration\n// =============================================================================\n\n/**\n * Configuration for the Mimic server.\n * \n * Note: Authentication and persistence are now handled by injectable services\n * (MimicAuthService and MimicDataStorage) rather than config options.\n */\nexport interface MimicServerConfig<TSchema extends Primitive.AnyPrimitive = Primitive.AnyPrimitive> {\n /**\n * The schema defining the document structure.\n */\n readonly schema: TSchema;\n\n /**\n * Maximum idle time for a document before it is cleaned up.\n * @default \"5 minutes\"\n */\n readonly maxIdleTime: Duration.Duration;\n\n /**\n * Maximum number of processed transaction IDs to track for deduplication.\n * @default 1000\n */\n readonly maxTransactionHistory: number;\n\n /**\n * Heartbeat interval for WebSocket connections.\n * @default \"30 seconds\"\n */\n readonly heartbeatInterval: Duration.Duration;\n\n /**\n * Timeout for heartbeat responses before considering connection dead.\n * @default \"10 seconds\"\n */\n readonly heartbeatTimeout: Duration.Duration;\n\n /**\n * Optional presence schema for ephemeral per-user data.\n * When provided, enables presence features on WebSocket connections.\n * @default undefined (presence disabled)\n */\n readonly presence: Presence.AnyPresence | undefined;\n}\n\n/**\n * Options for creating a MimicServerConfig.\n */\nexport interface MimicServerConfigOptions<TSchema extends Primitive.AnyPrimitive = Primitive.AnyPrimitive> {\n /**\n * The schema defining the document structure.\n */\n readonly schema: TSchema;\n\n /**\n * Maximum idle time for a document before it is cleaned up.\n * @default \"5 minutes\"\n */\n readonly maxIdleTime?: DurationInput;\n\n /**\n * Maximum number of processed transaction IDs to track for deduplication.\n * @default 1000\n */\n readonly maxTransactionHistory?: number;\n\n /**\n * Heartbeat interval for WebSocket connections.\n * @default \"30 seconds\"\n */\n readonly heartbeatInterval?: DurationInput;\n\n /**\n * Timeout for heartbeat responses.\n * @default \"10 seconds\"\n */\n readonly heartbeatTimeout?: DurationInput;\n\n /**\n * Optional presence schema for ephemeral per-user data.\n * When provided, enables presence features on WebSocket connections.\n * @default undefined (presence disabled)\n */\n readonly presence?: Presence.AnyPresence;\n}\n\n/**\n * Create a MimicServerConfig from options.\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n options: MimicServerConfigOptions<TSchema>\n): MimicServerConfig<TSchema> => ({\n schema: options.schema,\n maxIdleTime: Duration.decode(options.maxIdleTime ?? \"5 minutes\"),\n maxTransactionHistory: options.maxTransactionHistory ?? 1000,\n heartbeatInterval: Duration.decode(options.heartbeatInterval ?? \"30 seconds\"),\n heartbeatTimeout: Duration.decode(options.heartbeatTimeout ?? \"10 seconds\"),\n presence: options.presence,\n});\n\n// =============================================================================\n// Context Tag\n// =============================================================================\n\n/**\n * Context tag for MimicServerConfig.\n */\nexport class MimicServerConfigTag extends Context.Tag(\n \"@voidhash/mimic-server-effect/MimicServerConfig\"\n)<MimicServerConfigTag, MimicServerConfig>() {}\n\n/**\n * Create a Layer that provides MimicServerConfig.\n */\nexport const layer = <TSchema extends Primitive.AnyPrimitive>(\n options: MimicServerConfigOptions<TSchema>\n): Layer.Layer<MimicServerConfigTag> =>\n Layer.succeed(MimicServerConfigTag, make(options));\n"],"mappings":";;;;;;;;;;;;;;;;;;AAsGA,MAAa,QACX,YAC+B;;QAAC;EAChC,QAAQ,QAAQ;EAChB,aAAa,SAAS,+BAAO,QAAQ,kFAAe,YAAY;EAChE,gDAAuB,QAAQ,8FAAyB;EACxD,mBAAmB,SAAS,gCAAO,QAAQ,0FAAqB,aAAa;EAC7E,kBAAkB,SAAS,gCAAO,QAAQ,yFAAoB,aAAa;EAC3E,UAAU,QAAQ;EACnB;;;;;AASD,IAAa,uBAAb,cAA0C,QAAQ,IAChD,kDACD,EAA2C,CAAC;;;;AAK7C,MAAa,SACX,YAEA,MAAM,QAAQ,sBAAsB,KAAK,QAAQ,CAAC"}
1
+ {"version":3,"file":"MimicConfig.mjs","names":[],"sources":["../src/MimicConfig.ts"],"sourcesContent":["/**\n * @since 0.0.1\n * Configuration types for the Mimic server.\n */\nimport * as Context from \"effect/Context\";\nimport * as Duration from \"effect/Duration\";\nimport type { DurationInput } from \"effect/Duration\";\nimport * as Layer from \"effect/Layer\";\nimport { Primitive, Presence } from \"@voidhash/mimic\";\n\n// =============================================================================\n// Mimic Server Configuration\n// =============================================================================\n\n/**\n * Configuration for the Mimic server.\n * \n * Note: Authentication and persistence are now handled by injectable services\n * (MimicAuthService and MimicDataStorage) rather than config options.\n */\nexport interface MimicServerConfig<TSchema extends Primitive.AnyPrimitive = Primitive.AnyPrimitive> {\n /**\n * The schema defining the document structure.\n */\n readonly schema: TSchema;\n\n /**\n * Maximum idle time for a document before it is cleaned up.\n * @default \"5 minutes\"\n */\n readonly maxIdleTime: Duration.Duration;\n\n /**\n * Maximum number of processed transaction IDs to track for deduplication.\n * @default 1000\n */\n readonly maxTransactionHistory: number;\n\n /**\n * Heartbeat interval for WebSocket connections.\n * @default \"30 seconds\"\n */\n readonly heartbeatInterval: Duration.Duration;\n\n /**\n * Timeout for heartbeat responses before considering connection dead.\n * @default \"10 seconds\"\n */\n readonly heartbeatTimeout: Duration.Duration;\n\n /**\n * Optional presence schema for ephemeral per-user data.\n * When provided, enables presence features on WebSocket connections.\n * @default undefined (presence disabled)\n */\n readonly presence: Presence.AnyPresence | undefined;\n\n /**\n * Initial state for new documents.\n * Used when a document is created and no existing state is found in storage.\n * @default undefined (documents start empty)\n */\n readonly initial: Primitive.InferState<TSchema> | undefined;\n}\n\n/**\n * Options for creating a MimicServerConfig.\n */\nexport interface MimicServerConfigOptions<TSchema extends Primitive.AnyPrimitive = Primitive.AnyPrimitive> {\n /**\n * The schema defining the document structure.\n */\n readonly schema: TSchema;\n\n /**\n * Maximum idle time for a document before it is cleaned up.\n * @default \"5 minutes\"\n */\n readonly maxIdleTime?: DurationInput;\n\n /**\n * Maximum number of processed transaction IDs to track for deduplication.\n * @default 1000\n */\n readonly maxTransactionHistory?: number;\n\n /**\n * Heartbeat interval for WebSocket connections.\n * @default \"30 seconds\"\n */\n readonly heartbeatInterval?: DurationInput;\n\n /**\n * Timeout for heartbeat responses.\n * @default \"10 seconds\"\n */\n readonly heartbeatTimeout?: DurationInput;\n\n /**\n * Optional presence schema for ephemeral per-user data.\n * When provided, enables presence features on WebSocket connections.\n * @default undefined (presence disabled)\n */\n readonly presence?: Presence.AnyPresence;\n\n /**\n * Initial state for new documents.\n * Used when a document is created and no existing state is found in storage.\n *\n * Type-safe: required fields (without defaults) must be provided,\n * while optional fields and fields with defaults can be omitted.\n *\n * @default undefined (documents start empty or use schema defaults)\n */\n readonly initial?: Primitive.InferSetInput<TSchema>;\n}\n\n/**\n * Create a MimicServerConfig from options.\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n options: MimicServerConfigOptions<TSchema>\n): MimicServerConfig<TSchema> => ({\n schema: options.schema,\n maxIdleTime: Duration.decode(options.maxIdleTime ?? \"5 minutes\"),\n maxTransactionHistory: options.maxTransactionHistory ?? 1000,\n heartbeatInterval: Duration.decode(options.heartbeatInterval ?? \"30 seconds\"),\n heartbeatTimeout: Duration.decode(options.heartbeatTimeout ?? \"10 seconds\"),\n presence: options.presence,\n initial: options.initial !== undefined\n ? Primitive.applyDefaults(options.schema, options.initial as Partial<Primitive.InferState<TSchema>>)\n : undefined,\n});\n\n// =============================================================================\n// Context Tag\n// =============================================================================\n\n/**\n * Context tag for MimicServerConfig.\n */\nexport class MimicServerConfigTag extends Context.Tag(\n \"@voidhash/mimic-server-effect/MimicServerConfig\"\n)<MimicServerConfigTag, MimicServerConfig>() {}\n\n/**\n * Create a Layer that provides MimicServerConfig.\n */\nexport const layer = <TSchema extends Primitive.AnyPrimitive>(\n options: MimicServerConfigOptions<TSchema>\n): Layer.Layer<MimicServerConfigTag> =>\n Layer.succeed(MimicServerConfigTag, make(options));\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwHA,MAAa,QACX,YAC+B;;QAAC;EAChC,QAAQ,QAAQ;EAChB,aAAa,SAAS,+BAAO,QAAQ,kFAAe,YAAY;EAChE,gDAAuB,QAAQ,8FAAyB;EACxD,mBAAmB,SAAS,gCAAO,QAAQ,0FAAqB,aAAa;EAC7E,kBAAkB,SAAS,gCAAO,QAAQ,yFAAoB,aAAa;EAC3E,UAAU,QAAQ;EAClB,SAAS,QAAQ,YAAY,SACzB,UAAU,cAAc,QAAQ,QAAQ,QAAQ,QAAkD,GAClG;EACL;;;;;AASD,IAAa,uBAAb,cAA0C,QAAQ,IAChD,kDACD,EAA2C,CAAC;;;;AAK7C,MAAa,SACX,YAEA,MAAM,QAAQ,sBAAsB,KAAK,QAAQ,CAAC"}
@@ -1,5 +1,5 @@
1
- import * as Effect from "effect/Effect";
2
1
  import * as Layer from "effect/Layer";
2
+ import * as Effect from "effect/Effect";
3
3
  import * as Context from "effect/Context";
4
4
  import * as effect_Types6 from "effect/Types";
5
5
  import * as effect_Cause6 from "effect/Cause";
@@ -10,9 +10,6 @@ let effect_Effect = require("effect/Effect");
10
10
  effect_Effect = require_rolldown_runtime.__toESM(effect_Effect);
11
11
  let effect_Layer = require("effect/Layer");
12
12
  effect_Layer = require_rolldown_runtime.__toESM(effect_Layer);
13
- let effect_Context = require("effect/Context");
14
- effect_Context = require_rolldown_runtime.__toESM(effect_Context);
15
- let _effect_platform_SocketServer = require("@effect/platform/SocketServer");
16
13
  let _effect_platform = require("@effect/platform");
17
14
 
18
15
  //#region src/MimicServer.ts
@@ -21,120 +18,14 @@ let _effect_platform = require("@effect/platform");
21
18
  * Mimic server layer composition.
22
19
  */
23
20
  var MimicServer_exports = /* @__PURE__ */ require_rolldown_runtime.__export({
24
- MimicWebSocketHandler: () => MimicWebSocketHandler,
25
21
  documentManagerLayer: () => documentManagerLayer,
26
- handlerLayer: () => handlerLayer,
27
- layer: () => layer,
28
- layerHttpLayerRouter: () => layerHttpLayerRouter,
29
- run: () => run
22
+ layerHttpLayerRouter: () => layerHttpLayerRouter
30
23
  });
31
24
  /**
32
- * Tag for the WebSocket handler function.
33
- */
34
- var MimicWebSocketHandler = class extends effect_Context.Tag("@voidhash/mimic-server-effect/MimicWebSocketHandler")() {};
35
- /**
36
- * Create a Mimic WebSocket handler layer.
37
- *
38
- * This layer provides a handler function that can be used with any WebSocket server
39
- * implementation. The handler takes a socket and document ID and manages the
40
- * document synchronization.
41
- *
42
- * By default, uses in-memory storage and no authentication.
43
- * Override these by providing MimicDataStorage and MimicAuthService layers.
44
- *
45
- * @example
46
- * ```typescript
47
- * import { MimicServer, MimicAuthService } from "@voidhash/mimic-effect";
48
- * import { Primitive } from "@voidhash/mimic";
49
- *
50
- * const TodoSchema = Primitive.Struct({
51
- * title: Primitive.String(),
52
- * completed: Primitive.Boolean(),
53
- * });
54
- *
55
- * // Create the handler layer with defaults
56
- * const HandlerLayer = MimicServer.layer({
57
- * basePath: "/mimic/todo",
58
- * schema: TodoSchema
59
- * });
60
- *
61
- * // Or with custom auth
62
- * const HandlerLayerWithAuth = MimicServer.layer({
63
- * basePath: "/mimic/todo",
64
- * schema: TodoSchema
65
- * }).pipe(
66
- * Layer.provideMerge(MimicAuthService.layer({
67
- * authHandler: (token) => ({ success: true, userId: "user-123" })
68
- * }))
69
- * );
70
- * ```
71
- */
72
- const layer = (options) => {
73
- const configLayer = require_MimicConfig.layer({
74
- schema: options.schema,
75
- maxTransactionHistory: options.maxTransactionHistory,
76
- presence: options.presence
77
- });
78
- return effect_Layer.merge(effect_Layer.effect(MimicWebSocketHandler, require_WebSocketHandler.makeHandler).pipe(effect_Layer.provide(require_DocumentManager.layer), effect_Layer.provide(require_PresenceManager.layer), effect_Layer.provide(configLayer)), require_DocumentManager.layer.pipe(effect_Layer.provide(configLayer))).pipe(effect_Layer.provide(require_InMemoryDataStorage.layerDefault), effect_Layer.provide(require_NoAuth.layerDefault));
79
- };
80
- /**
81
- * Create the Mimic server handler layer.
82
- * This layer provides the WebSocket handler that can be used with any WebSocket server.
83
- *
84
- * @example
85
- * ```typescript
86
- * import { MimicServer } from "@voidhash/mimic-server-effect";
87
- * import { SocketServer } from "@effect/platform/SocketServer";
88
- * import { Primitive } from "@voidhash/mimic";
89
- *
90
- * // Define your document schema
91
- * const TodoSchema = Primitive.Struct({
92
- * title: Primitive.String(),
93
- * completed: Primitive.Boolean(),
94
- * });
95
- *
96
- * // Create the server layer
97
- * const serverLayer = MimicServer.handlerLayer({
98
- * schema: TodoSchema,
99
- * });
100
- *
101
- * // Run with your socket server
102
- * Effect.gen(function* () {
103
- * const handler = yield* MimicServer.MimicWebSocketHandler;
104
- * const server = yield* SocketServer;
105
- *
106
- * yield* server.run((socket) =>
107
- * // Extract document ID from request and call handler
108
- * handler(socket, "my-document-id")
109
- * );
110
- * }).pipe(
111
- * Effect.provide(serverLayer),
112
- * Effect.provide(YourSocketServerLayer),
113
- * );
114
- * ```
115
- */
116
- const handlerLayer = (options) => effect_Layer.effect(MimicWebSocketHandler, require_WebSocketHandler.makeHandler).pipe(effect_Layer.provide(require_DocumentManager.layer), effect_Layer.provide(require_PresenceManager.layer), effect_Layer.provide(require_MimicConfig.layer(options)), effect_Layer.provide(require_InMemoryDataStorage.layerDefault), effect_Layer.provide(require_NoAuth.layerDefault));
117
- /**
118
25
  * Create the document manager layer.
119
26
  */
120
27
  const documentManagerLayer = (options) => require_DocumentManager.layer.pipe(effect_Layer.provide(require_MimicConfig.layer(options)), effect_Layer.provide(require_InMemoryDataStorage.layerDefault), effect_Layer.provide(require_NoAuth.layerDefault));
121
28
  /**
122
- * Run a Mimic WebSocket server with the provided handler.
123
- *
124
- * This is a helper that:
125
- * 1. Gets the WebSocket handler from context
126
- * 2. Runs the socket server with the handler
127
- *
128
- * Note: The document ID extraction from socket is implementation-specific.
129
- * You may need to customize this based on your socket server.
130
- */
131
- const run = (extractDocumentId$1) => effect_Effect.gen(function* () {
132
- const handler = yield* MimicWebSocketHandler;
133
- yield* (yield* _effect_platform_SocketServer.SocketServer).run((socket) => effect_Effect.gen(function* () {
134
- yield* handler(socket, yield* extractDocumentId$1(socket));
135
- }).pipe(effect_Effect.catchAll((error) => effect_Effect.logError("Connection error", error))));
136
- });
137
- /**
138
29
  * Create the HTTP handler effect for WebSocket upgrade.
139
30
  * This handler:
140
31
  * 1. Extracts the document ID from the URL path
@@ -209,7 +100,8 @@ const layerHttpLayerRouter = (options) => {
209
100
  const configLayer = require_MimicConfig.layer({
210
101
  schema: options.schema,
211
102
  maxTransactionHistory: options.maxTransactionHistory,
212
- presence: options.presence
103
+ presence: options.presence,
104
+ initial: options.initial
213
105
  });
214
106
  const authLayer = (_options$authLayer = options.authLayer) !== null && _options$authLayer !== void 0 ? _options$authLayer : require_NoAuth.layerDefault;
215
107
  const storageLayer = (_options$storageLayer = options.storageLayer) !== null && _options$storageLayer !== void 0 ? _options$storageLayer : require_InMemoryDataStorage.layerDefault;