@voidhash/mimic-effect 1.0.0-beta.15 → 1.0.0-beta.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/ColdStorage.cjs +1 -1
  2. package/dist/ColdStorage.d.cts +2 -2
  3. package/dist/ColdStorage.d.cts.map +1 -1
  4. package/dist/ColdStorage.d.mts +2 -2
  5. package/dist/ColdStorage.d.mts.map +1 -1
  6. package/dist/ColdStorage.mjs +2 -2
  7. package/dist/ColdStorage.mjs.map +1 -1
  8. package/dist/DocumentInstance.cjs +13 -13
  9. package/dist/DocumentInstance.mjs +13 -13
  10. package/dist/DocumentInstance.mjs.map +1 -1
  11. package/dist/Errors.d.cts +8 -8
  12. package/dist/Errors.d.cts.map +1 -1
  13. package/dist/Errors.d.mts +8 -8
  14. package/dist/Errors.d.mts.map +1 -1
  15. package/dist/HotStorage.cjs +1 -1
  16. package/dist/HotStorage.d.cts +2 -2
  17. package/dist/HotStorage.d.mts +2 -2
  18. package/dist/HotStorage.mjs +2 -2
  19. package/dist/HotStorage.mjs.map +1 -1
  20. package/dist/Metrics.cjs +6 -6
  21. package/dist/Metrics.d.cts +21 -23
  22. package/dist/Metrics.d.cts.map +1 -1
  23. package/dist/Metrics.d.mts +21 -23
  24. package/dist/Metrics.d.mts.map +1 -1
  25. package/dist/Metrics.mjs +7 -7
  26. package/dist/Metrics.mjs.map +1 -1
  27. package/dist/MimicAuthService.cjs +1 -1
  28. package/dist/MimicAuthService.d.cts +2 -2
  29. package/dist/MimicAuthService.d.cts.map +1 -1
  30. package/dist/MimicAuthService.d.mts +2 -2
  31. package/dist/MimicAuthService.d.mts.map +1 -1
  32. package/dist/MimicAuthService.mjs +2 -2
  33. package/dist/MimicAuthService.mjs.map +1 -1
  34. package/dist/MimicClusterServerEngine.cjs +38 -41
  35. package/dist/MimicClusterServerEngine.d.cts +1 -1
  36. package/dist/MimicClusterServerEngine.d.mts +1 -1
  37. package/dist/MimicClusterServerEngine.mjs +31 -34
  38. package/dist/MimicClusterServerEngine.mjs.map +1 -1
  39. package/dist/MimicServer.cjs +23 -23
  40. package/dist/MimicServer.d.cts +3 -3
  41. package/dist/MimicServer.d.cts.map +1 -1
  42. package/dist/MimicServer.d.mts +3 -3
  43. package/dist/MimicServer.d.mts.map +1 -1
  44. package/dist/MimicServer.mjs +22 -22
  45. package/dist/MimicServer.mjs.map +1 -1
  46. package/dist/MimicServerEngine.cjs +13 -13
  47. package/dist/MimicServerEngine.d.cts +2 -2
  48. package/dist/MimicServerEngine.d.mts +2 -2
  49. package/dist/MimicServerEngine.mjs +14 -14
  50. package/dist/MimicServerEngine.mjs.map +1 -1
  51. package/dist/PresenceManager.cjs +4 -4
  52. package/dist/PresenceManager.d.cts +2 -2
  53. package/dist/PresenceManager.d.mts +2 -2
  54. package/dist/PresenceManager.mjs +5 -5
  55. package/dist/PresenceManager.mjs.map +1 -1
  56. package/dist/Types.d.cts +1 -1
  57. package/dist/Types.d.mts +1 -1
  58. package/dist/testing/ColdStorageTestSuite.cjs +3 -3
  59. package/dist/testing/ColdStorageTestSuite.mjs +3 -3
  60. package/dist/testing/ColdStorageTestSuite.mjs.map +1 -1
  61. package/dist/testing/HotStorageTestSuite.cjs +13 -13
  62. package/dist/testing/HotStorageTestSuite.mjs +13 -13
  63. package/dist/testing/HotStorageTestSuite.mjs.map +1 -1
  64. package/dist/testing/StorageIntegrationTestSuite.cjs +3 -3
  65. package/dist/testing/StorageIntegrationTestSuite.mjs +3 -3
  66. package/dist/testing/StorageIntegrationTestSuite.mjs.map +1 -1
  67. package/dist/testing/types.d.cts +1 -1
  68. package/dist/testing/types.d.cts.map +1 -1
  69. package/dist/testing/types.d.mts +3 -3
  70. package/dist/testing/types.d.mts.map +1 -1
  71. package/package.json +17 -21
  72. package/src/ColdStorage.ts +4 -5
  73. package/src/DocumentInstance.ts +13 -13
  74. package/src/HotStorage.ts +3 -3
  75. package/src/Metrics.ts +22 -16
  76. package/src/MimicAuthService.ts +3 -3
  77. package/src/MimicClusterServerEngine.ts +35 -35
  78. package/src/MimicServer.ts +26 -30
  79. package/src/MimicServerEngine.ts +15 -15
  80. package/src/PresenceManager.ts +6 -6
  81. package/src/Types.ts +1 -1
  82. package/src/testing/ColdStorageTestSuite.ts +3 -3
  83. package/src/testing/HotStorageTestSuite.ts +17 -17
  84. package/src/testing/StorageIntegrationTestSuite.ts +3 -3
  85. package/.turbo/turbo-build.log +0 -154
  86. package/tests/ColdStorage.test.ts +0 -24
  87. package/tests/DocumentInstance.test.ts +0 -669
  88. package/tests/HotStorage.test.ts +0 -24
  89. package/tests/MimicAuthService.test.ts +0 -153
  90. package/tests/MimicClusterServerEngine.test.ts +0 -587
  91. package/tests/MimicServer.test.ts +0 -142
  92. package/tests/MimicServerEngine.test.ts +0 -547
  93. package/tests/PresenceManager.test.ts +0 -380
  94. package/tests/Protocol.test.ts +0 -190
  95. package/tests/StorageIntegration.test.ts +0 -259
  96. package/tsconfig.build.json +0 -24
  97. package/tsconfig.json +0 -8
  98. package/tsdown.config.ts +0 -18
  99. package/vitest.mts +0 -11
@@ -9,7 +9,7 @@ let effect = require("effect");
9
9
  /**
10
10
  * Context tag for ColdStorage service
11
11
  */
12
- var ColdStorageTag = class extends effect.Context.Tag("@voidhash/mimic-effect/ColdStorage")() {};
12
+ var ColdStorageTag = class extends effect.ServiceMap.Service()("@voidhash/mimic-effect/ColdStorage") {};
13
13
  /**
14
14
  * Create a ColdStorage layer from an Effect that produces a ColdStorage service.
15
15
  *
@@ -1,6 +1,6 @@
1
1
  import { StoredDocument } from "./Types.cjs";
2
2
  import { ColdStorageError } from "./Errors.cjs";
3
- import { Context, Effect, Layer } from "effect";
3
+ import { Effect, Layer, ServiceMap } from "effect";
4
4
 
5
5
  //#region src/ColdStorage.d.ts
6
6
 
@@ -26,7 +26,7 @@ interface ColdStorage {
26
26
  */
27
27
  readonly delete: (documentId: string) => Effect.Effect<void, ColdStorageError>;
28
28
  }
29
- declare const ColdStorageTag_base: Context.TagClass<ColdStorageTag, "@voidhash/mimic-effect/ColdStorage", ColdStorage>;
29
+ declare const ColdStorageTag_base: ServiceMap.ServiceClass<ColdStorageTag, "@voidhash/mimic-effect/ColdStorage", ColdStorage>;
30
30
  /**
31
31
  * Context tag for ColdStorage service
32
32
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ColdStorage.d.cts","names":[],"sources":["../src/ColdStorage.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AA2CC,UAvBgB,WAAA,CAuBhB;;;;;EASY,SAAA,IAAA,EAAA,CAAA,UAAe,EAAA,MAAQ,EAAA,GAzB7B,MAAA,CAAO,MA4BX,CA5BkB,cA4BlB,GAAA,SAAA,EA5B8C,gBA4B9C,CAAA;EA4Cc;AAyCjB;;EAvDwB,SAAA,IAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAnDV,cAmDU,EAAA,GAlDjB,MAAA,CAAO,MAkDU,CAAA,IAAA,EAlDG,gBAkDH,CAAA;EAAa;;;EACtB,SAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GA5CR,MAAA,CAAO,MA4CC,CAAA,IAAA,EA5CY,gBA4CZ,CAAA;;cA3Cd,mBA2CiC,kBAAA,eAAA,EAAA,oCAAA,aAAA,CAAA;;;;cAlCrB,cAAA,SAAuB,mBAAA;;;;;;;kBA+CnB,QAAA;;;;oBAIS,KAAA,CAAM,MAAM;;cAqCzB;;uBAvDH,MAAA,CAAO,OAAO,aAAa,GAAG,OACrC,KAAA,CAAM,MAAM,gBAAgB,GAAG"}
1
+ {"version":3,"file":"ColdStorage.d.cts","names":[],"sources":["../src/ColdStorage.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AA2CC,UAvBgB,WAAA,CAuBhB;;;;;EASY,SAAA,IAAA,EAAA,CAAA,UAAe,EAAA,MAAQ,EAAA,GAzB7B,MAAA,CAAO,MA2Bb,CA3BoB,cA2BpB,GAAA,SAAA,EA3BgD,gBA2BhD,CAAA;EA4CgB;AAyCjB;;EAvDwB,SAAA,IAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAlDV,cAkDU,EAAA,GAjDjB,MAAA,CAAO,MAiDU,CAAA,IAAA,EAjDG,gBAiDH,CAAA;EAAa;;;EACtB,SAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GA3CR,MAAA,CAAO,MA2CC,CAAA,IAAA,EA3CY,gBA2CZ,CAAA;;cA1Cd,mBA0CiC,yBAAA,eAAA,EAAA,oCAAA,aAAA,CAAA;;;;cAjCrB,cAAA,SAAuB,mBAAA;;;;;;;kBA8CnB,QAAA;;;;oBAIS,KAAA,CAAM,MAAM;;cAqCzB;;uBAvDH,MAAA,CAAO,OAAO,aAAa,GAAG,OACrC,KAAA,CAAM,MAAM,gBAAgB,GAAG"}
@@ -1,6 +1,6 @@
1
1
  import { StoredDocument } from "./Types.mjs";
2
2
  import { ColdStorageError } from "./Errors.mjs";
3
- import { Context, Effect, Layer } from "effect";
3
+ import { Effect, Layer, ServiceMap } from "effect";
4
4
 
5
5
  //#region src/ColdStorage.d.ts
6
6
 
@@ -26,7 +26,7 @@ interface ColdStorage {
26
26
  */
27
27
  readonly delete: (documentId: string) => Effect.Effect<void, ColdStorageError>;
28
28
  }
29
- declare const ColdStorageTag_base: Context.TagClass<ColdStorageTag, "@voidhash/mimic-effect/ColdStorage", ColdStorage>;
29
+ declare const ColdStorageTag_base: ServiceMap.ServiceClass<ColdStorageTag, "@voidhash/mimic-effect/ColdStorage", ColdStorage>;
30
30
  /**
31
31
  * Context tag for ColdStorage service
32
32
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ColdStorage.d.mts","names":[],"sources":["../src/ColdStorage.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AA2CC,UAvBgB,WAAA,CAuBhB;;;;;EASY,SAAA,IAAA,EAAA,CAAA,UAAe,EAAA,MAAQ,EAAA,GAzB7B,MAAA,CAAO,MA4BX,CA5BkB,cA4BlB,GAAA,SAAA,EA5B8C,gBA4B9C,CAAA;EA4Cc;AAyCjB;;EAvDwB,SAAA,IAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAnDV,cAmDU,EAAA,GAlDjB,MAAA,CAAO,MAkDU,CAAA,IAAA,EAlDG,gBAkDH,CAAA;EAAa;;;EACtB,SAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GA5CR,MAAA,CAAO,MA4CC,CAAA,IAAA,EA5CY,gBA4CZ,CAAA;;cA3Cd,mBA2CiC,kBAAA,eAAA,EAAA,oCAAA,aAAA,CAAA;;;;cAlCrB,cAAA,SAAuB,mBAAA;;;;;;;kBA+CnB,QAAA;;;;oBAIS,KAAA,CAAM,MAAM;;cAqCzB;;uBAvDH,MAAA,CAAO,OAAO,aAAa,GAAG,OACrC,KAAA,CAAM,MAAM,gBAAgB,GAAG"}
1
+ {"version":3,"file":"ColdStorage.d.mts","names":[],"sources":["../src/ColdStorage.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AA2CC,UAvBgB,WAAA,CAuBhB;;;;;EASY,SAAA,IAAA,EAAA,CAAA,UAAe,EAAA,MAAQ,EAAA,GAzB7B,MAAA,CAAO,MA2Bb,CA3BoB,cA2BpB,GAAA,SAAA,EA3BgD,gBA2BhD,CAAA;EA4CgB;AAyCjB;;EAvDwB,SAAA,IAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAlDV,cAkDU,EAAA,GAjDjB,MAAA,CAAO,MAiDU,CAAA,IAAA,EAjDG,gBAiDH,CAAA;EAAa;;;EACtB,SAAA,MAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,GA3CR,MAAA,CAAO,MA2CC,CAAA,IAAA,EA3CY,gBA2CZ,CAAA;;cA1Cd,mBA0CiC,yBAAA,eAAA,EAAA,oCAAA,aAAA,CAAA;;;;cAjCrB,cAAA,SAAuB,mBAAA;;;;;;;kBA8CnB,QAAA;;;;oBAIS,KAAA,CAAM,MAAM;;cAqCzB;;uBAvDH,MAAA,CAAO,OAAO,aAAa,GAAG,OACrC,KAAA,CAAM,MAAM,gBAAgB,GAAG"}
@@ -1,4 +1,4 @@
1
- import { Context, Effect, HashMap, Layer, Ref } from "effect";
1
+ import { Effect, HashMap, Layer, Ref, ServiceMap } from "effect";
2
2
 
3
3
  //#region src/ColdStorage.ts
4
4
  /**
@@ -9,7 +9,7 @@ import { Context, Effect, HashMap, Layer, Ref } from "effect";
9
9
  /**
10
10
  * Context tag for ColdStorage service
11
11
  */
12
- var ColdStorageTag = class extends Context.Tag("@voidhash/mimic-effect/ColdStorage")() {};
12
+ var ColdStorageTag = class extends ServiceMap.Service()("@voidhash/mimic-effect/ColdStorage") {};
13
13
  /**
14
14
  * Create a ColdStorage layer from an Effect that produces a ColdStorage service.
15
15
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ColdStorage.mjs","names":[],"sources":["../src/ColdStorage.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect - ColdStorage\n *\n * Interface and implementations for document snapshot storage.\n */\nimport { Context, Effect, HashMap, Layer, Ref } from \"effect\";\nimport type { StoredDocument } from \"./Types\";\nimport { ColdStorageError } from \"./Errors\";\n\n// =============================================================================\n// ColdStorage Interface\n// =============================================================================\n\n/**\n * ColdStorage interface for storing document snapshots.\n *\n * This is the \"cold\" tier of the two-tier storage system.\n * It stores complete document snapshots less frequently (on periodic intervals\n * or after a threshold of transactions).\n */\nexport interface ColdStorage {\n /**\n * Load a document snapshot.\n * Returns undefined if the document doesn't exist.\n */\n readonly load: (\n documentId: string\n ) => Effect.Effect<StoredDocument | undefined, ColdStorageError>;\n\n /**\n * Save a document snapshot.\n */\n readonly save: (\n documentId: string,\n document: StoredDocument\n ) => Effect.Effect<void, ColdStorageError>;\n\n /**\n * Delete a document snapshot.\n */\n readonly delete: (\n documentId: string\n ) => Effect.Effect<void, ColdStorageError>;\n}\n\n// =============================================================================\n// Context Tag\n// =============================================================================\n\n/**\n * Context tag for ColdStorage service\n */\nexport class ColdStorageTag extends Context.Tag(\"@voidhash/mimic-effect/ColdStorage\")<\n ColdStorageTag,\n ColdStorage\n>() {}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a ColdStorage layer from an Effect that produces a ColdStorage service.\n *\n * This allows you to access other Effect services when implementing custom storage.\n *\n * @example\n * ```typescript\n * const Cold = ColdStorage.make(\n * Effect.gen(function*() {\n * const redis = yield* RedisService\n *\n * return {\n * load: (documentId) => redis.get(`doc:${documentId}`).pipe(\n * Effect.map(data => data ? JSON.parse(data) : undefined)\n * ),\n * save: (documentId, document) =>\n * redis.set(`doc:${documentId}`, JSON.stringify(document)),\n * delete: (documentId) => redis.del(`doc:${documentId}`),\n * }\n * })\n * )\n * ```\n */\nexport const make = <E, R>(\n effect: Effect.Effect<ColdStorage, E, R>\n): Layer.Layer<ColdStorageTag, E, R> =>\n Layer.effect(ColdStorageTag, effect);\n\n// =============================================================================\n// InMemory Implementation\n// =============================================================================\n\n/**\n * In-memory ColdStorage implementation.\n *\n * Useful for testing and development. Not suitable for production\n * as data is lost when the process restarts.\n */\nexport namespace InMemory {\n /**\n * Create an in-memory ColdStorage layer.\n */\n export const make = (): Layer.Layer<ColdStorageTag> =>\n Layer.effect(\n ColdStorageTag,\n Effect.fn(\"cold-storage.in-memory.create\")(function* () {\n const store = yield* Ref.make(HashMap.empty<string, StoredDocument>());\n\n return {\n load: Effect.fn(\"cold-storage.load\")(function* (documentId: string) {\n const current = yield* Ref.get(store);\n const result = HashMap.get(current, documentId);\n return result._tag === \"Some\" ? result.value : undefined;\n }),\n\n save: Effect.fn(\"cold-storage.save\")(\n function* (documentId: string, document: StoredDocument) {\n yield* Ref.update(store, (map) =>\n HashMap.set(map, documentId, document)\n );\n }\n ),\n\n delete: Effect.fn(\"cold-storage.delete\")(\n function* (documentId: string) {\n yield* Ref.update(store, (map) =>\n HashMap.remove(map, documentId)\n );\n }\n ),\n };\n })()\n );\n}\n\n// =============================================================================\n// Re-export namespace\n// =============================================================================\n\nexport const ColdStorage = {\n Tag: ColdStorageTag,\n make,\n InMemory,\n};\n"],"mappings":";;;;;;;;;;;AAoDA,IAAa,iBAAb,cAAoC,QAAQ,IAAI,qCAAqC,EAGlF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AA6BJ,MAAa,QACX,WAEA,MAAM,OAAO,gBAAgB,OAAO;;;wBAiBlC,MAAM,OACJ,gBACA,OAAO,GAAG,gCAAgC,CAAC,aAAa;EACtD,MAAM,QAAQ,OAAO,IAAI,KAAK,QAAQ,OAA+B,CAAC;AAEtE,SAAO;GACL,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,YAAoB;IAClE,MAAM,UAAU,OAAO,IAAI,IAAI,MAAM;IACrC,MAAM,SAAS,QAAQ,IAAI,SAAS,WAAW;AAC/C,WAAO,OAAO,SAAS,SAAS,OAAO,QAAQ;KAC/C;GAEF,MAAM,OAAO,GAAG,oBAAoB,CAClC,WAAW,YAAoB,UAA0B;AACvD,WAAO,IAAI,OAAO,QAAQ,QACxB,QAAQ,IAAI,KAAK,YAAY,SAAS,CACvC;KAEJ;GAED,QAAQ,OAAO,GAAG,sBAAsB,CACtC,WAAW,YAAoB;AAC7B,WAAO,IAAI,OAAO,QAAQ,QACxB,QAAQ,OAAO,KAAK,WAAW,CAChC;KAEJ;GACF;GACD,EAAE,CACL;;AAOL,MAAa,cAAc;CACzB,KAAK;CACL;CACA;CACD"}
1
+ {"version":3,"file":"ColdStorage.mjs","names":[],"sources":["../src/ColdStorage.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect - ColdStorage\n *\n * Interface and implementations for document snapshot storage.\n */\nimport { Effect, HashMap, Layer, Ref, ServiceMap } from \"effect\";\nimport type { StoredDocument } from \"./Types\";\nimport { ColdStorageError } from \"./Errors\";\n\n// =============================================================================\n// ColdStorage Interface\n// =============================================================================\n\n/**\n * ColdStorage interface for storing document snapshots.\n *\n * This is the \"cold\" tier of the two-tier storage system.\n * It stores complete document snapshots less frequently (on periodic intervals\n * or after a threshold of transactions).\n */\nexport interface ColdStorage {\n /**\n * Load a document snapshot.\n * Returns undefined if the document doesn't exist.\n */\n readonly load: (\n documentId: string\n ) => Effect.Effect<StoredDocument | undefined, ColdStorageError>;\n\n /**\n * Save a document snapshot.\n */\n readonly save: (\n documentId: string,\n document: StoredDocument\n ) => Effect.Effect<void, ColdStorageError>;\n\n /**\n * Delete a document snapshot.\n */\n readonly delete: (\n documentId: string\n ) => Effect.Effect<void, ColdStorageError>;\n}\n\n// =============================================================================\n// Context Tag\n// =============================================================================\n\n/**\n * Context tag for ColdStorage service\n */\nexport class ColdStorageTag extends ServiceMap.Service<ColdStorageTag, ColdStorage>()(\n \"@voidhash/mimic-effect/ColdStorage\"\n) {}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a ColdStorage layer from an Effect that produces a ColdStorage service.\n *\n * This allows you to access other Effect services when implementing custom storage.\n *\n * @example\n * ```typescript\n * const Cold = ColdStorage.make(\n * Effect.gen(function*() {\n * const redis = yield* RedisService\n *\n * return {\n * load: (documentId) => redis.get(`doc:${documentId}`).pipe(\n * Effect.map(data => data ? JSON.parse(data) : undefined)\n * ),\n * save: (documentId, document) =>\n * redis.set(`doc:${documentId}`, JSON.stringify(document)),\n * delete: (documentId) => redis.del(`doc:${documentId}`),\n * }\n * })\n * )\n * ```\n */\nexport const make = <E, R>(\n effect: Effect.Effect<ColdStorage, E, R>\n): Layer.Layer<ColdStorageTag, E, R> =>\n Layer.effect(ColdStorageTag, effect);\n\n// =============================================================================\n// InMemory Implementation\n// =============================================================================\n\n/**\n * In-memory ColdStorage implementation.\n *\n * Useful for testing and development. Not suitable for production\n * as data is lost when the process restarts.\n */\nexport namespace InMemory {\n /**\n * Create an in-memory ColdStorage layer.\n */\n export const make = (): Layer.Layer<ColdStorageTag> =>\n Layer.effect(\n ColdStorageTag,\n Effect.fn(\"cold-storage.in-memory.create\")(function* () {\n const store = yield* Ref.make(HashMap.empty<string, StoredDocument>());\n\n return {\n load: Effect.fn(\"cold-storage.load\")(function* (documentId: string) {\n const current = yield* Ref.get(store);\n const result = HashMap.get(current, documentId);\n return result._tag === \"Some\" ? result.value : undefined;\n }),\n\n save: Effect.fn(\"cold-storage.save\")(\n function* (documentId: string, document: StoredDocument) {\n yield* Ref.update(store, (map) =>\n HashMap.set(map, documentId, document)\n );\n }\n ),\n\n delete: Effect.fn(\"cold-storage.delete\")(\n function* (documentId: string) {\n yield* Ref.update(store, (map) =>\n HashMap.remove(map, documentId)\n );\n }\n ),\n };\n })()\n );\n}\n\n// =============================================================================\n// Re-export namespace\n// =============================================================================\n\nexport const ColdStorage = {\n Tag: ColdStorageTag,\n make,\n InMemory,\n};\n"],"mappings":";;;;;;;;;;;AAoDA,IAAa,iBAAb,cAAoC,WAAW,SAAsC,CACnF,qCACD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AA6BF,MAAa,QACX,WAEA,MAAM,OAAO,gBAAgB,OAAO;;;wBAiBlC,MAAM,OACJ,gBACA,OAAO,GAAG,gCAAgC,CAAC,aAAa;EACtD,MAAM,QAAQ,OAAO,IAAI,KAAK,QAAQ,OAA+B,CAAC;AAEtE,SAAO;GACL,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,YAAoB;IAClE,MAAM,UAAU,OAAO,IAAI,IAAI,MAAM;IACrC,MAAM,SAAS,QAAQ,IAAI,SAAS,WAAW;AAC/C,WAAO,OAAO,SAAS,SAAS,OAAO,QAAQ;KAC/C;GAEF,MAAM,OAAO,GAAG,oBAAoB,CAClC,WAAW,YAAoB,UAA0B;AACvD,WAAO,IAAI,OAAO,QAAQ,QACxB,QAAQ,IAAI,KAAK,YAAY,SAAS,CACvC;KAEJ;GAED,QAAQ,OAAO,GAAG,sBAAsB,CACtC,WAAW,YAAoB;AAC7B,WAAO,IAAI,OAAO,QAAQ,QACxB,QAAQ,OAAO,KAAK,WAAW,CAChC;KAEJ;GACF;GACD,EAAE,CACL;;AAOL,MAAa,cAAc;CACzB,KAAK;CACL;CACA;CACD"}
@@ -68,9 +68,9 @@ const make = (documentId, config, coldStorage, hotStorage) => effect.Effect.gen(
68
68
  const walEntries = yield* hotStorage.getEntries(documentId, initialVersion);
69
69
  yield* verifyWalContinuity(documentId, walEntries, initialVersion);
70
70
  yield* replayWalEntries(documentId, document, walEntries);
71
- if (storedDoc) yield* effect.Metric.increment(require_Metrics.documentsRestored);
72
- else yield* effect.Metric.increment(require_Metrics.documentsCreated);
73
- yield* effect.Metric.incrementBy(require_Metrics.documentsActive, 1);
71
+ if (storedDoc) yield* effect.Metric.update(require_Metrics.documentsRestored, 1);
72
+ else yield* effect.Metric.update(require_Metrics.documentsCreated, 1);
73
+ yield* effect.Metric.update(require_Metrics.documentsActive, 1);
74
74
  const getSnapshotTracking = effect.Effect.gen(function* () {
75
75
  return {
76
76
  lastSnapshotVersion: yield* effect.Ref.get(lastSnapshotVersionRef),
@@ -94,12 +94,12 @@ const make = (documentId, config, coldStorage, hotStorage) => effect.Effect.gen(
94
94
  const storedDoc$1 = createStoredDocument(snapshotResult.state, snapshotResult.version, SCHEMA_VERSION);
95
95
  yield* coldStorage.save(documentId, storedDoc$1);
96
96
  const snapshotDuration = Date.now() - snapshotStartTime;
97
- yield* effect.Metric.increment(require_Metrics.storageSnapshots);
97
+ yield* effect.Metric.update(require_Metrics.storageSnapshots, 1);
98
98
  yield* effect.Metric.update(require_Metrics.storageSnapshotLatency, snapshotDuration);
99
99
  yield* effect.Ref.set(lastSnapshotVersionRef, snapshotResult.version);
100
100
  yield* effect.Ref.set(lastSnapshotTimeRef, Date.now());
101
101
  yield* effect.Ref.set(transactionsSinceSnapshotRef, 0);
102
- yield* effect.Effect.catchAll(hotStorage.truncate(documentId, snapshotResult.version), (e) => effect.Effect.logWarning("WAL truncate failed - will retry on next snapshot", {
102
+ yield* effect.Effect["catch"](hotStorage.truncate(documentId, snapshotResult.version), (e) => effect.Effect.logWarning("WAL truncate failed - will retry on next snapshot", {
103
103
  documentId,
104
104
  version: snapshotResult.version,
105
105
  error: e
@@ -113,7 +113,7 @@ const make = (documentId, config, coldStorage, hotStorage) => effect.Effect.gen(
113
113
  yield* effect.Ref.set(lastActivityTimeRef, Date.now());
114
114
  const validation = document.validate(transaction);
115
115
  if (!validation.valid) {
116
- yield* effect.Metric.increment(require_Metrics.transactionsRejected);
116
+ yield* effect.Metric.update(require_Metrics.transactionsRejected, 1);
117
117
  const latency$1 = Date.now() - submitStartTime;
118
118
  yield* effect.Metric.update(require_Metrics.transactionsLatency, latency$1);
119
119
  return {
@@ -127,14 +127,14 @@ const make = (documentId, config, coldStorage, hotStorage) => effect.Effect.gen(
127
127
  timestamp: Date.now()
128
128
  };
129
129
  const snapshotVersion = yield* effect.Ref.get(lastSnapshotVersionRef);
130
- const appendResult = yield* effect.Effect.either(hotStorage.appendWithCheck(documentId, walEntry, validation.nextVersion, snapshotVersion));
131
- if (appendResult._tag === "Left") {
130
+ const appendResult = yield* effect.Effect.result(hotStorage.appendWithCheck(documentId, walEntry, validation.nextVersion, snapshotVersion));
131
+ if (appendResult._tag === "Failure") {
132
132
  yield* effect.Effect.logError("WAL append failed", {
133
133
  documentId,
134
134
  version: validation.nextVersion,
135
- error: appendResult.left
135
+ error: appendResult.failure
136
136
  });
137
- yield* effect.Metric.increment(require_Metrics.walAppendFailures);
137
+ yield* effect.Metric.update(require_Metrics.walAppendFailures, 1);
138
138
  const latency$1 = Date.now() - submitStartTime;
139
139
  yield* effect.Metric.update(require_Metrics.transactionsLatency, latency$1);
140
140
  return {
@@ -145,8 +145,8 @@ const make = (documentId, config, coldStorage, hotStorage) => effect.Effect.gen(
145
145
  document.apply(transaction);
146
146
  const latency = Date.now() - submitStartTime;
147
147
  yield* effect.Metric.update(require_Metrics.transactionsLatency, latency);
148
- yield* effect.Metric.increment(require_Metrics.transactionsProcessed);
149
- yield* effect.Metric.increment(require_Metrics.storageWalAppends);
148
+ yield* effect.Metric.update(require_Metrics.transactionsProcessed, 1);
149
+ yield* effect.Metric.update(require_Metrics.storageWalAppends, 1);
150
150
  yield* effect.Ref.update(transactionsSinceSnapshotRef, (n) => n + 1);
151
151
  yield* checkSnapshotTriggers();
152
152
  return {
@@ -196,7 +196,7 @@ const verifyWalContinuity = effect.Effect.fn("document.wal.verify")(function* (d
196
196
  firstWalVersion,
197
197
  expectedFirst
198
198
  });
199
- yield* effect.Metric.increment(require_Metrics.storageVersionGaps);
199
+ yield* effect.Metric.update(require_Metrics.storageVersionGaps, 1);
200
200
  }
201
201
  for (let i = 1; i < walEntries.length; i++) {
202
202
  const prev = walEntries[i - 1].version;
@@ -68,9 +68,9 @@ const make = (documentId, config, coldStorage, hotStorage) => Effect.gen(functio
68
68
  const walEntries = yield* hotStorage.getEntries(documentId, initialVersion);
69
69
  yield* verifyWalContinuity(documentId, walEntries, initialVersion);
70
70
  yield* replayWalEntries(documentId, document, walEntries);
71
- if (storedDoc) yield* Metric.increment(documentsRestored);
72
- else yield* Metric.increment(documentsCreated);
73
- yield* Metric.incrementBy(documentsActive, 1);
71
+ if (storedDoc) yield* Metric.update(documentsRestored, 1);
72
+ else yield* Metric.update(documentsCreated, 1);
73
+ yield* Metric.update(documentsActive, 1);
74
74
  const getSnapshotTracking = Effect.gen(function* () {
75
75
  return {
76
76
  lastSnapshotVersion: yield* Ref.get(lastSnapshotVersionRef),
@@ -94,12 +94,12 @@ const make = (documentId, config, coldStorage, hotStorage) => Effect.gen(functio
94
94
  const storedDoc$1 = createStoredDocument(snapshotResult.state, snapshotResult.version, SCHEMA_VERSION);
95
95
  yield* coldStorage.save(documentId, storedDoc$1);
96
96
  const snapshotDuration = Date.now() - snapshotStartTime;
97
- yield* Metric.increment(storageSnapshots);
97
+ yield* Metric.update(storageSnapshots, 1);
98
98
  yield* Metric.update(storageSnapshotLatency, snapshotDuration);
99
99
  yield* Ref.set(lastSnapshotVersionRef, snapshotResult.version);
100
100
  yield* Ref.set(lastSnapshotTimeRef, Date.now());
101
101
  yield* Ref.set(transactionsSinceSnapshotRef, 0);
102
- yield* Effect.catchAll(hotStorage.truncate(documentId, snapshotResult.version), (e) => Effect.logWarning("WAL truncate failed - will retry on next snapshot", {
102
+ yield* Effect["catch"](hotStorage.truncate(documentId, snapshotResult.version), (e) => Effect.logWarning("WAL truncate failed - will retry on next snapshot", {
103
103
  documentId,
104
104
  version: snapshotResult.version,
105
105
  error: e
@@ -113,7 +113,7 @@ const make = (documentId, config, coldStorage, hotStorage) => Effect.gen(functio
113
113
  yield* Ref.set(lastActivityTimeRef, Date.now());
114
114
  const validation = document.validate(transaction);
115
115
  if (!validation.valid) {
116
- yield* Metric.increment(transactionsRejected);
116
+ yield* Metric.update(transactionsRejected, 1);
117
117
  const latency$1 = Date.now() - submitStartTime;
118
118
  yield* Metric.update(transactionsLatency, latency$1);
119
119
  return {
@@ -127,14 +127,14 @@ const make = (documentId, config, coldStorage, hotStorage) => Effect.gen(functio
127
127
  timestamp: Date.now()
128
128
  };
129
129
  const snapshotVersion = yield* Ref.get(lastSnapshotVersionRef);
130
- const appendResult = yield* Effect.either(hotStorage.appendWithCheck(documentId, walEntry, validation.nextVersion, snapshotVersion));
131
- if (appendResult._tag === "Left") {
130
+ const appendResult = yield* Effect.result(hotStorage.appendWithCheck(documentId, walEntry, validation.nextVersion, snapshotVersion));
131
+ if (appendResult._tag === "Failure") {
132
132
  yield* Effect.logError("WAL append failed", {
133
133
  documentId,
134
134
  version: validation.nextVersion,
135
- error: appendResult.left
135
+ error: appendResult.failure
136
136
  });
137
- yield* Metric.increment(walAppendFailures);
137
+ yield* Metric.update(walAppendFailures, 1);
138
138
  const latency$1 = Date.now() - submitStartTime;
139
139
  yield* Metric.update(transactionsLatency, latency$1);
140
140
  return {
@@ -145,8 +145,8 @@ const make = (documentId, config, coldStorage, hotStorage) => Effect.gen(functio
145
145
  document.apply(transaction);
146
146
  const latency = Date.now() - submitStartTime;
147
147
  yield* Metric.update(transactionsLatency, latency);
148
- yield* Metric.increment(transactionsProcessed);
149
- yield* Metric.increment(storageWalAppends);
148
+ yield* Metric.update(transactionsProcessed, 1);
149
+ yield* Metric.update(storageWalAppends, 1);
150
150
  yield* Ref.update(transactionsSinceSnapshotRef, (n) => n + 1);
151
151
  yield* checkSnapshotTriggers();
152
152
  return {
@@ -196,7 +196,7 @@ const verifyWalContinuity = Effect.fn("document.wal.verify")(function* (document
196
196
  firstWalVersion,
197
197
  expectedFirst
198
198
  });
199
- yield* Metric.increment(storageVersionGaps);
199
+ yield* Metric.update(storageVersionGaps, 1);
200
200
  }
201
201
  for (let i = 1; i < walEntries.length; i++) {
202
202
  const prev = walEntries[i - 1].version;
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentInstance.mjs","names":["initialState: Primitive.InferState<TSchema> | undefined","initial: Primitive.InferSetInput<TSchema> | undefined","Metrics.documentsRestored","Metrics.documentsCreated","Metrics.documentsActive","walEntries","storedDoc","Metrics.storageSnapshots","Metrics.storageSnapshotLatency","Metrics.transactionsRejected","latency","Metrics.transactionsLatency","walEntry: WalEntry","Metrics.walAppendFailures","Metrics.transactionsProcessed","Metrics.storageWalAppends","Metrics.storageVersionGaps","snapshotState: Primitive.InferState<TSchema> | undefined"],"sources":["../src/DocumentInstance.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect - DocumentInstance\n *\n * Manages the lifecycle of a single document including:\n * - Restoration from storage (cold storage + WAL replay)\n * - Transaction submission with WAL persistence\n * - Snapshot saving and trigger checking\n *\n * Used by both MimicServerEngine (single-node) and MimicClusterServerEngine (clustered).\n */\nimport { Duration, Effect, Metric, PubSub, Ref } from \"effect\";\nimport { Document, type Primitive, type Transaction } from \"@voidhash/mimic\";\nimport { ServerDocument } from \"@voidhash/mimic/server\";\nimport type { StoredDocument, WalEntry } from \"./Types\";\nimport type { ServerBroadcast } from \"./Protocol\";\nimport type { ColdStorage } from \"./ColdStorage\";\nimport type { HotStorage } from \"./HotStorage\";\nimport type { ColdStorageError } from \"./Errors\";\nimport type { HotStorageError } from \"./Errors\";\nimport * as Metrics from \"./Metrics\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Result of submitting a transaction\n */\nexport type SubmitResult =\n | { readonly success: true; readonly version: number }\n | { readonly success: false; readonly reason: string };\n\n/**\n * Configuration for a DocumentInstance\n */\nexport interface DocumentInstanceConfig<TSchema extends Primitive.AnyPrimitive> {\n readonly schema: TSchema;\n readonly initial?:\n | Primitive.InferSetInput<TSchema>\n | ((ctx: { documentId: string }) => Effect.Effect<Primitive.InferSetInput<TSchema>>);\n readonly maxTransactionHistory: number;\n readonly snapshot: {\n readonly interval: Duration.Duration;\n readonly transactionThreshold: number;\n };\n}\n\n/**\n * Snapshot tracking state\n */\nexport interface SnapshotTracking {\n readonly lastSnapshotVersion: number;\n readonly lastSnapshotTime: number;\n readonly transactionsSinceSnapshot: number;\n}\n\n/**\n * A DocumentInstance manages a single document's lifecycle\n */\nexport interface DocumentInstance<TSchema extends Primitive.AnyPrimitive> {\n /** The underlying ServerDocument */\n readonly document: ServerDocument.ServerDocument<TSchema>;\n /** PubSub for broadcasting messages to subscribers */\n readonly pubsub: PubSub.PubSub<ServerBroadcast>;\n /** Current snapshot tracking state */\n readonly getSnapshotTracking: Effect.Effect<SnapshotTracking>;\n /** Submit a transaction */\n readonly submit: (transaction: Transaction.Transaction) => Effect.Effect<SubmitResult, ColdStorageError | HotStorageError>;\n /** Save a snapshot to cold storage */\n readonly saveSnapshot: () => Effect.Effect<void, ColdStorageError | HotStorageError>;\n /** Check if snapshot should be triggered and save if needed */\n readonly checkSnapshotTriggers: () => Effect.Effect<void, ColdStorageError | HotStorageError>;\n /** Update last activity time (for external tracking) */\n readonly touch: () => Effect.Effect<void>;\n /** Get current document version */\n readonly getVersion: () => number;\n /** Get document snapshot (flat state format) */\n readonly getSnapshot: () => { state: unknown; version: number };\n /**\n * Get tree-like snapshot for rendering.\n * The snapshot is a type-safe, readonly structure where trees\n * are converted from flat state to nested/hierarchical structure.\n */\n readonly toSnapshot: () => Primitive.InferSnapshot<TSchema>;\n /** Check if document has unsnapshot transactions that need persisting */\n readonly needsSnapshot: () => Effect.Effect<boolean>;\n /** Get the last activity timestamp for idle detection */\n readonly getLastActivityTime: () => Effect.Effect<number>;\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a DocumentInstance for a single document.\n *\n * This handles:\n * - Loading from cold storage or computing initial state\n * - Persisting initial state immediately (crash safety)\n * - Replaying WAL entries\n * - Transaction submission with WAL persistence\n * - Snapshot saving\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n documentId: string,\n config: DocumentInstanceConfig<TSchema>,\n coldStorage: ColdStorage,\n hotStorage: HotStorage\n): Effect.Effect<DocumentInstance<TSchema>, ColdStorageError | HotStorageError> =>\n Effect.gen(function* () {\n // Current schema version (hard-coded to 1 for now)\n const SCHEMA_VERSION = 1;\n\n // 1. Load snapshot from ColdStorage\n const storedDoc = yield* coldStorage.load(documentId);\n\n // Track initial values - only one will be set:\n // - initialState: raw state from storage (already in internal format)\n // - initial: computed from config (needs conversion to state format)\n let initialState: Primitive.InferState<TSchema> | undefined;\n let initial: Primitive.InferSetInput<TSchema> | undefined;\n let initialVersion = 0;\n\n if (storedDoc) {\n // Loading from storage - state is already in internal format\n initialState = storedDoc.state as Primitive.InferState<TSchema>;\n initialVersion = storedDoc.version;\n } else {\n // New document - compute initial value (set input format)\n initial = yield* computeInitialState(config, documentId);\n }\n\n // 2. Create PubSub for broadcasting\n const pubsub = yield* PubSub.unbounded<ServerBroadcast>();\n\n // 3. Create refs for tracking\n const lastSnapshotVersionRef = yield* Ref.make(initialVersion);\n const lastSnapshotTimeRef = yield* Ref.make(Date.now());\n const transactionsSinceSnapshotRef = yield* Ref.make(0);\n const lastActivityTimeRef = yield* Ref.make(Date.now());\n\n // 4. Create ServerDocument with callbacks\n const document = ServerDocument.make({\n schema: config.schema,\n initial,\n initialState,\n initialVersion,\n maxTransactionHistory: config.maxTransactionHistory,\n onBroadcast: (message: ServerDocument.TransactionMessage) => {\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"transaction\",\n transaction: message.transaction,\n version: message.version,\n })\n );\n },\n onRejection: (transactionId: string, reason: string) => {\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"error\",\n transactionId,\n reason,\n })\n );\n },\n });\n\n // 5. If this is a new document, immediately save to cold storage\n // This ensures the initial state is durable before any transactions are accepted.\n if (!storedDoc) {\n const initialStoredDoc = createStoredDocument(document.get(), 0, SCHEMA_VERSION);\n yield* coldStorage.save(documentId, initialStoredDoc);\n yield* Effect.logDebug(\"Initial state persisted to cold storage\", { documentId });\n }\n\n // 6. Load WAL entries\n const walEntries = yield* hotStorage.getEntries(documentId, initialVersion);\n\n // 7. Verify WAL continuity (warning only, non-blocking)\n yield* verifyWalContinuity(documentId, walEntries, initialVersion);\n\n // 8. Replay WAL entries\n yield* replayWalEntries(documentId, document, walEntries);\n\n // Track metrics\n if (storedDoc) {\n yield* Metric.increment(Metrics.documentsRestored);\n } else {\n yield* Metric.increment(Metrics.documentsCreated);\n }\n yield* Metric.incrementBy(Metrics.documentsActive, 1);\n\n // ==========================================================================\n // Instance Methods\n // ==========================================================================\n\n const getSnapshotTracking = Effect.gen(function* () {\n return {\n lastSnapshotVersion: yield* Ref.get(lastSnapshotVersionRef),\n lastSnapshotTime: yield* Ref.get(lastSnapshotTimeRef),\n transactionsSinceSnapshot: yield* Ref.get(transactionsSinceSnapshotRef),\n };\n });\n\n const saveSnapshot = Effect.fn(\"document.snapshot.save\")(function* () {\n const targetVersion = document.getVersion();\n const lastSnapshotVersion = yield* Ref.get(lastSnapshotVersionRef);\n\n // Idempotency check: skip if already snapshotted at this version\n if (targetVersion <= lastSnapshotVersion) {\n return;\n }\n\n const snapshotStartTime = Date.now();\n\n // Load base snapshot from cold storage\n const baseSnapshot = yield* coldStorage.load(documentId);\n const baseVersion = baseSnapshot?.version ?? 0;\n const baseState = baseSnapshot?.state as Primitive.InferState<TSchema> | undefined;\n\n // Load WAL entries from base to target\n const walEntries = yield* hotStorage.getEntries(documentId, baseVersion);\n\n // Compute snapshot state by replaying WAL on base\n const snapshotResult = computeSnapshotState(\n config.schema,\n baseState,\n walEntries,\n targetVersion\n );\n\n if (!snapshotResult) {\n return;\n }\n\n // Re-check before saving (in case another snapshot completed while we were working)\n const currentLastSnapshot = yield* Ref.get(lastSnapshotVersionRef);\n if (snapshotResult.version <= currentLastSnapshot) {\n return;\n }\n\n const storedDoc = createStoredDocument(\n snapshotResult.state,\n snapshotResult.version,\n SCHEMA_VERSION\n );\n\n // Save to ColdStorage\n yield* coldStorage.save(documentId, storedDoc);\n\n // Track snapshot metrics\n const snapshotDuration = Date.now() - snapshotStartTime;\n yield* Metric.increment(Metrics.storageSnapshots);\n yield* Metric.update(Metrics.storageSnapshotLatency, snapshotDuration);\n\n // Update tracking BEFORE truncate (for idempotency on retry)\n yield* Ref.set(lastSnapshotVersionRef, snapshotResult.version);\n yield* Ref.set(lastSnapshotTimeRef, Date.now());\n yield* Ref.set(transactionsSinceSnapshotRef, 0);\n\n // Truncate WAL - non-fatal, will be retried on next snapshot\n yield* Effect.catchAll(hotStorage.truncate(documentId, snapshotResult.version), (e) =>\n Effect.logWarning(\"WAL truncate failed - will retry on next snapshot\", {\n documentId,\n version: snapshotResult.version,\n error: e,\n })\n );\n });\n\n const checkSnapshotTriggers = Effect.fn(\"document.snapshot.check-triggers\")(function* () {\n const txCount = yield* Ref.get(transactionsSinceSnapshotRef);\n const lastTime = yield* Ref.get(lastSnapshotTimeRef);\n\n if (shouldTriggerSnapshot(txCount, lastTime, config.snapshot)) {\n yield* saveSnapshot();\n }\n });\n\n const submit = Effect.fn(\"document.transaction.submit\")(function* (\n transaction: Transaction.Transaction\n ) {\n const submitStartTime = Date.now();\n\n // Update activity time\n yield* Ref.set(lastActivityTimeRef, Date.now());\n\n // Phase 1: Validate (no side effects)\n const validation = document.validate(transaction);\n\n if (!validation.valid) {\n yield* Metric.increment(Metrics.transactionsRejected);\n const latency = Date.now() - submitStartTime;\n yield* Metric.update(Metrics.transactionsLatency, latency);\n\n return {\n success: false as const,\n reason: validation.reason,\n };\n }\n\n // Phase 2: Append to WAL with gap check (BEFORE state mutation)\n const walEntry: WalEntry = {\n transaction,\n version: validation.nextVersion,\n timestamp: Date.now(),\n };\n\n // Get the current snapshot version to pass as baseVersion for gap checking\n // This ensures correct validation after truncation or restart\n const snapshotVersion = yield* Ref.get(lastSnapshotVersionRef);\n\n const appendResult = yield* Effect.either(\n hotStorage.appendWithCheck(documentId, walEntry, validation.nextVersion, snapshotVersion)\n );\n\n if (appendResult._tag === \"Left\") {\n yield* Effect.logError(\"WAL append failed\", {\n documentId,\n version: validation.nextVersion,\n error: appendResult.left,\n });\n yield* Metric.increment(Metrics.walAppendFailures);\n\n const latency = Date.now() - submitStartTime;\n yield* Metric.update(Metrics.transactionsLatency, latency);\n\n return {\n success: false as const,\n reason: \"Storage unavailable. Please retry.\",\n };\n }\n\n // Phase 3: Apply (state mutation + broadcast)\n document.apply(transaction);\n\n // Track metrics\n const latency = Date.now() - submitStartTime;\n yield* Metric.update(Metrics.transactionsLatency, latency);\n yield* Metric.increment(Metrics.transactionsProcessed);\n yield* Metric.increment(Metrics.storageWalAppends);\n\n // Increment transaction count\n yield* Ref.update(transactionsSinceSnapshotRef, (n) => n + 1);\n\n // Check snapshot triggers\n yield* checkSnapshotTriggers();\n\n return {\n success: true as const,\n version: validation.nextVersion,\n };\n });\n\n const touch = Effect.fn(\"document.touch\")(function* () {\n yield* Ref.set(lastActivityTimeRef, Date.now());\n });\n\n const needsSnapshot = () =>\n Effect.map(Ref.get(transactionsSinceSnapshotRef), (n) => n > 0);\n\n const getLastActivityTime = () => Ref.get(lastActivityTimeRef);\n\n return {\n document,\n pubsub,\n getSnapshotTracking,\n submit,\n saveSnapshot,\n checkSnapshotTriggers,\n touch,\n getVersion: () => document.getVersion(),\n getSnapshot: () => document.getSnapshot(),\n toSnapshot: () => document.toSnapshot(),\n needsSnapshot,\n getLastActivityTime,\n };\n });\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Compute initial state for a new document.\n */\nconst computeInitialState = <TSchema extends Primitive.AnyPrimitive>(\n config: DocumentInstanceConfig<TSchema>,\n documentId: string\n): Effect.Effect<Primitive.InferSetInput<TSchema> | undefined> => {\n if (config.initial === undefined) {\n return Effect.succeed(undefined);\n }\n\n if (typeof config.initial === \"function\") {\n return (config.initial as (ctx: { documentId: string }) => Effect.Effect<Primitive.InferSetInput<TSchema>>)({\n documentId,\n });\n }\n\n return Effect.succeed(config.initial as Primitive.InferSetInput<TSchema>);\n};\n\n/**\n * Verify WAL continuity and log warnings for any gaps.\n */\nconst verifyWalContinuity = Effect.fn(\"document.wal.verify\")(function* (\n documentId: string,\n walEntries: readonly WalEntry[],\n baseVersion: number\n) {\n if (walEntries.length === 0) {\n return;\n }\n\n const firstWalVersion = walEntries[0]!.version;\n const expectedFirst = baseVersion + 1;\n\n if (firstWalVersion !== expectedFirst) {\n yield* Effect.logWarning(\"WAL version gap detected\", {\n documentId,\n snapshotVersion: baseVersion,\n firstWalVersion,\n expectedFirst,\n });\n yield* Metric.increment(Metrics.storageVersionGaps);\n }\n\n for (let i = 1; i < walEntries.length; i++) {\n const prev = walEntries[i - 1]!.version;\n const curr = walEntries[i]!.version;\n if (curr !== prev + 1) {\n yield* Effect.logWarning(\"WAL internal gap detected\", {\n documentId,\n previousVersion: prev,\n currentVersion: curr,\n });\n }\n }\n});\n\n/**\n * Replay WAL entries onto a ServerDocument.\n */\nconst replayWalEntries = Effect.fn(\"document.wal.replay\")(function* (\n documentId: string,\n document: ServerDocument.ServerDocument<Primitive.AnyPrimitive>,\n walEntries: readonly WalEntry[]\n) {\n for (const entry of walEntries) {\n const result = document.submit(entry.transaction);\n if (!result.success) {\n yield* Effect.logWarning(\"Skipping corrupted WAL entry\", {\n documentId,\n version: entry.version,\n reason: result.reason,\n });\n }\n }\n});\n\n/**\n * Compute snapshot state by replaying WAL entries on a base state.\n */\nconst computeSnapshotState = <TSchema extends Primitive.AnyPrimitive>(\n schema: TSchema,\n baseState: Primitive.InferState<TSchema> | undefined,\n walEntries: readonly WalEntry[],\n targetVersion: number\n): { state: Primitive.InferState<TSchema>; version: number } | undefined => {\n const relevantEntries = walEntries.filter((e) => e.version <= targetVersion);\n\n if (relevantEntries.length === 0 && baseState === undefined) {\n return undefined;\n }\n\n let snapshotState: Primitive.InferState<TSchema> | undefined = baseState;\n for (const entry of relevantEntries) {\n const tempDoc = Document.make(schema, { initialState: snapshotState });\n tempDoc.apply(entry.transaction.ops);\n snapshotState = tempDoc.get();\n }\n\n if (snapshotState === undefined) {\n return undefined;\n }\n\n const snapshotVersion =\n relevantEntries.length > 0 ? relevantEntries[relevantEntries.length - 1]!.version : 0;\n\n return { state: snapshotState, version: snapshotVersion };\n};\n\n/**\n * Check if a snapshot should be triggered.\n */\nconst shouldTriggerSnapshot = (\n transactionsSinceSnapshot: number,\n lastSnapshotTime: number,\n config: { interval: Duration.Duration; transactionThreshold: number }\n): boolean => {\n const now = Date.now();\n const intervalMs = Duration.toMillis(config.interval);\n\n if (transactionsSinceSnapshot >= config.transactionThreshold) {\n return true;\n }\n\n if (now - lastSnapshotTime >= intervalMs) {\n return true;\n }\n\n return false;\n};\n\n/**\n * Create a StoredDocument for persistence.\n */\nconst createStoredDocument = (\n state: unknown,\n version: number,\n schemaVersion: number\n): StoredDocument => ({\n state,\n version,\n schemaVersion,\n savedAt: Date.now(),\n});\n\n// =============================================================================\n// Re-export namespace\n// =============================================================================\n\nexport const DocumentInstance = {\n make,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"DocumentInstance.mjs","names":["initialState: Primitive.InferState<TSchema> | undefined","initial: Primitive.InferSetInput<TSchema> | undefined","Metrics.documentsRestored","Metrics.documentsCreated","Metrics.documentsActive","walEntries","storedDoc","Metrics.storageSnapshots","Metrics.storageSnapshotLatency","Metrics.transactionsRejected","latency","Metrics.transactionsLatency","walEntry: WalEntry","Metrics.walAppendFailures","Metrics.transactionsProcessed","Metrics.storageWalAppends","Metrics.storageVersionGaps","snapshotState: Primitive.InferState<TSchema> | undefined"],"sources":["../src/DocumentInstance.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect - DocumentInstance\n *\n * Manages the lifecycle of a single document including:\n * - Restoration from storage (cold storage + WAL replay)\n * - Transaction submission with WAL persistence\n * - Snapshot saving and trigger checking\n *\n * Used by both MimicServerEngine (single-node) and MimicClusterServerEngine (clustered).\n */\nimport { Duration, Effect, Metric, PubSub, Ref } from \"effect\";\nimport { Document, type Primitive, type Transaction } from \"@voidhash/mimic\";\nimport { ServerDocument } from \"@voidhash/mimic/server\";\nimport type { StoredDocument, WalEntry } from \"./Types\";\nimport type { ServerBroadcast } from \"./Protocol\";\nimport type { ColdStorage } from \"./ColdStorage\";\nimport type { HotStorage } from \"./HotStorage\";\nimport type { ColdStorageError } from \"./Errors\";\nimport type { HotStorageError } from \"./Errors\";\nimport * as Metrics from \"./Metrics\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Result of submitting a transaction\n */\nexport type SubmitResult =\n | { readonly success: true; readonly version: number }\n | { readonly success: false; readonly reason: string };\n\n/**\n * Configuration for a DocumentInstance\n */\nexport interface DocumentInstanceConfig<TSchema extends Primitive.AnyPrimitive> {\n readonly schema: TSchema;\n readonly initial?:\n | Primitive.InferSetInput<TSchema>\n | ((ctx: { documentId: string }) => Effect.Effect<Primitive.InferSetInput<TSchema>>);\n readonly maxTransactionHistory: number;\n readonly snapshot: {\n readonly interval: Duration.Duration;\n readonly transactionThreshold: number;\n };\n}\n\n/**\n * Snapshot tracking state\n */\nexport interface SnapshotTracking {\n readonly lastSnapshotVersion: number;\n readonly lastSnapshotTime: number;\n readonly transactionsSinceSnapshot: number;\n}\n\n/**\n * A DocumentInstance manages a single document's lifecycle\n */\nexport interface DocumentInstance<TSchema extends Primitive.AnyPrimitive> {\n /** The underlying ServerDocument */\n readonly document: ServerDocument.ServerDocument<TSchema>;\n /** PubSub for broadcasting messages to subscribers */\n readonly pubsub: PubSub.PubSub<ServerBroadcast>;\n /** Current snapshot tracking state */\n readonly getSnapshotTracking: Effect.Effect<SnapshotTracking>;\n /** Submit a transaction */\n readonly submit: (transaction: Transaction.Transaction) => Effect.Effect<SubmitResult, ColdStorageError | HotStorageError>;\n /** Save a snapshot to cold storage */\n readonly saveSnapshot: () => Effect.Effect<void, ColdStorageError | HotStorageError>;\n /** Check if snapshot should be triggered and save if needed */\n readonly checkSnapshotTriggers: () => Effect.Effect<void, ColdStorageError | HotStorageError>;\n /** Update last activity time (for external tracking) */\n readonly touch: () => Effect.Effect<void>;\n /** Get current document version */\n readonly getVersion: () => number;\n /** Get document snapshot (flat state format) */\n readonly getSnapshot: () => { state: unknown; version: number };\n /**\n * Get tree-like snapshot for rendering.\n * The snapshot is a type-safe, readonly structure where trees\n * are converted from flat state to nested/hierarchical structure.\n */\n readonly toSnapshot: () => Primitive.InferSnapshot<TSchema>;\n /** Check if document has unsnapshot transactions that need persisting */\n readonly needsSnapshot: () => Effect.Effect<boolean>;\n /** Get the last activity timestamp for idle detection */\n readonly getLastActivityTime: () => Effect.Effect<number>;\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a DocumentInstance for a single document.\n *\n * This handles:\n * - Loading from cold storage or computing initial state\n * - Persisting initial state immediately (crash safety)\n * - Replaying WAL entries\n * - Transaction submission with WAL persistence\n * - Snapshot saving\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n documentId: string,\n config: DocumentInstanceConfig<TSchema>,\n coldStorage: ColdStorage,\n hotStorage: HotStorage\n): Effect.Effect<DocumentInstance<TSchema>, ColdStorageError | HotStorageError> =>\n Effect.gen(function* () {\n // Current schema version (hard-coded to 1 for now)\n const SCHEMA_VERSION = 1;\n\n // 1. Load snapshot from ColdStorage\n const storedDoc = yield* coldStorage.load(documentId);\n\n // Track initial values - only one will be set:\n // - initialState: raw state from storage (already in internal format)\n // - initial: computed from config (needs conversion to state format)\n let initialState: Primitive.InferState<TSchema> | undefined;\n let initial: Primitive.InferSetInput<TSchema> | undefined;\n let initialVersion = 0;\n\n if (storedDoc) {\n // Loading from storage - state is already in internal format\n initialState = storedDoc.state as Primitive.InferState<TSchema>;\n initialVersion = storedDoc.version;\n } else {\n // New document - compute initial value (set input format)\n initial = yield* computeInitialState(config, documentId);\n }\n\n // 2. Create PubSub for broadcasting\n const pubsub = yield* PubSub.unbounded<ServerBroadcast>();\n\n // 3. Create refs for tracking\n const lastSnapshotVersionRef = yield* Ref.make(initialVersion);\n const lastSnapshotTimeRef = yield* Ref.make(Date.now());\n const transactionsSinceSnapshotRef = yield* Ref.make(0);\n const lastActivityTimeRef = yield* Ref.make(Date.now());\n\n // 4. Create ServerDocument with callbacks\n const document = ServerDocument.make({\n schema: config.schema,\n initial,\n initialState,\n initialVersion,\n maxTransactionHistory: config.maxTransactionHistory,\n onBroadcast: (message: ServerDocument.TransactionMessage) => {\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"transaction\",\n transaction: message.transaction,\n version: message.version,\n })\n );\n },\n onRejection: (transactionId: string, reason: string) => {\n Effect.runSync(\n PubSub.publish(pubsub, {\n type: \"error\",\n transactionId,\n reason,\n })\n );\n },\n });\n\n // 5. If this is a new document, immediately save to cold storage\n // This ensures the initial state is durable before any transactions are accepted.\n if (!storedDoc) {\n const initialStoredDoc = createStoredDocument(document.get(), 0, SCHEMA_VERSION);\n yield* coldStorage.save(documentId, initialStoredDoc);\n yield* Effect.logDebug(\"Initial state persisted to cold storage\", { documentId });\n }\n\n // 6. Load WAL entries\n const walEntries = yield* hotStorage.getEntries(documentId, initialVersion);\n\n // 7. Verify WAL continuity (warning only, non-blocking)\n yield* verifyWalContinuity(documentId, walEntries, initialVersion);\n\n // 8. Replay WAL entries\n yield* replayWalEntries(documentId, document, walEntries);\n\n // Track metrics\n if (storedDoc) {\n yield* Metric.update(Metrics.documentsRestored, 1);\n } else {\n yield* Metric.update(Metrics.documentsCreated, 1);\n }\n yield* Metric.update(Metrics.documentsActive, 1);\n\n // ==========================================================================\n // Instance Methods\n // ==========================================================================\n\n const getSnapshotTracking = Effect.gen(function* () {\n return {\n lastSnapshotVersion: yield* Ref.get(lastSnapshotVersionRef),\n lastSnapshotTime: yield* Ref.get(lastSnapshotTimeRef),\n transactionsSinceSnapshot: yield* Ref.get(transactionsSinceSnapshotRef),\n };\n });\n\n const saveSnapshot = Effect.fn(\"document.snapshot.save\")(function* () {\n const targetVersion = document.getVersion();\n const lastSnapshotVersion = yield* Ref.get(lastSnapshotVersionRef);\n\n // Idempotency check: skip if already snapshotted at this version\n if (targetVersion <= lastSnapshotVersion) {\n return;\n }\n\n const snapshotStartTime = Date.now();\n\n // Load base snapshot from cold storage\n const baseSnapshot = yield* coldStorage.load(documentId);\n const baseVersion = baseSnapshot?.version ?? 0;\n const baseState = baseSnapshot?.state as Primitive.InferState<TSchema> | undefined;\n\n // Load WAL entries from base to target\n const walEntries = yield* hotStorage.getEntries(documentId, baseVersion);\n\n // Compute snapshot state by replaying WAL on base\n const snapshotResult = computeSnapshotState(\n config.schema,\n baseState,\n walEntries,\n targetVersion\n );\n\n if (!snapshotResult) {\n return;\n }\n\n // Re-check before saving (in case another snapshot completed while we were working)\n const currentLastSnapshot = yield* Ref.get(lastSnapshotVersionRef);\n if (snapshotResult.version <= currentLastSnapshot) {\n return;\n }\n\n const storedDoc = createStoredDocument(\n snapshotResult.state,\n snapshotResult.version,\n SCHEMA_VERSION\n );\n\n // Save to ColdStorage\n yield* coldStorage.save(documentId, storedDoc);\n\n // Track snapshot metrics\n const snapshotDuration = Date.now() - snapshotStartTime;\n yield* Metric.update(Metrics.storageSnapshots, 1);\n yield* Metric.update(Metrics.storageSnapshotLatency, snapshotDuration);\n\n // Update tracking BEFORE truncate (for idempotency on retry)\n yield* Ref.set(lastSnapshotVersionRef, snapshotResult.version);\n yield* Ref.set(lastSnapshotTimeRef, Date.now());\n yield* Ref.set(transactionsSinceSnapshotRef, 0);\n\n // Truncate WAL - non-fatal, will be retried on next snapshot\n yield* Effect[\"catch\"](hotStorage.truncate(documentId, snapshotResult.version), (e) =>\n Effect.logWarning(\"WAL truncate failed - will retry on next snapshot\", {\n documentId,\n version: snapshotResult.version,\n error: e,\n })\n );\n });\n\n const checkSnapshotTriggers = Effect.fn(\"document.snapshot.check-triggers\")(function* () {\n const txCount = yield* Ref.get(transactionsSinceSnapshotRef);\n const lastTime = yield* Ref.get(lastSnapshotTimeRef);\n\n if (shouldTriggerSnapshot(txCount, lastTime, config.snapshot)) {\n yield* saveSnapshot();\n }\n });\n\n const submit = Effect.fn(\"document.transaction.submit\")(function* (\n transaction: Transaction.Transaction\n ) {\n const submitStartTime = Date.now();\n\n // Update activity time\n yield* Ref.set(lastActivityTimeRef, Date.now());\n\n // Phase 1: Validate (no side effects)\n const validation = document.validate(transaction);\n\n if (!validation.valid) {\n yield* Metric.update(Metrics.transactionsRejected, 1);\n const latency = Date.now() - submitStartTime;\n yield* Metric.update(Metrics.transactionsLatency, latency);\n\n return {\n success: false as const,\n reason: validation.reason,\n };\n }\n\n // Phase 2: Append to WAL with gap check (BEFORE state mutation)\n const walEntry: WalEntry = {\n transaction,\n version: validation.nextVersion,\n timestamp: Date.now(),\n };\n\n // Get the current snapshot version to pass as baseVersion for gap checking\n // This ensures correct validation after truncation or restart\n const snapshotVersion = yield* Ref.get(lastSnapshotVersionRef);\n\n const appendResult = yield* Effect.result(\n hotStorage.appendWithCheck(documentId, walEntry, validation.nextVersion, snapshotVersion)\n );\n\n if (appendResult._tag === \"Failure\") {\n yield* Effect.logError(\"WAL append failed\", {\n documentId,\n version: validation.nextVersion,\n error: appendResult.failure,\n });\n yield* Metric.update(Metrics.walAppendFailures, 1);\n\n const latency = Date.now() - submitStartTime;\n yield* Metric.update(Metrics.transactionsLatency, latency);\n\n return {\n success: false as const,\n reason: \"Storage unavailable. Please retry.\",\n };\n }\n\n // Phase 3: Apply (state mutation + broadcast)\n document.apply(transaction);\n\n // Track metrics\n const latency = Date.now() - submitStartTime;\n yield* Metric.update(Metrics.transactionsLatency, latency);\n yield* Metric.update(Metrics.transactionsProcessed, 1);\n yield* Metric.update(Metrics.storageWalAppends, 1);\n\n // Increment transaction count\n yield* Ref.update(transactionsSinceSnapshotRef, (n) => n + 1);\n\n // Check snapshot triggers\n yield* checkSnapshotTriggers();\n\n return {\n success: true as const,\n version: validation.nextVersion,\n };\n });\n\n const touch = Effect.fn(\"document.touch\")(function* () {\n yield* Ref.set(lastActivityTimeRef, Date.now());\n });\n\n const needsSnapshot = () =>\n Effect.map(Ref.get(transactionsSinceSnapshotRef), (n) => n > 0);\n\n const getLastActivityTime = () => Ref.get(lastActivityTimeRef);\n\n return {\n document,\n pubsub,\n getSnapshotTracking,\n submit,\n saveSnapshot,\n checkSnapshotTriggers,\n touch,\n getVersion: () => document.getVersion(),\n getSnapshot: () => document.getSnapshot(),\n toSnapshot: () => document.toSnapshot(),\n needsSnapshot,\n getLastActivityTime,\n };\n });\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Compute initial state for a new document.\n */\nconst computeInitialState = <TSchema extends Primitive.AnyPrimitive>(\n config: DocumentInstanceConfig<TSchema>,\n documentId: string\n): Effect.Effect<Primitive.InferSetInput<TSchema> | undefined> => {\n if (config.initial === undefined) {\n return Effect.succeed(undefined);\n }\n\n if (typeof config.initial === \"function\") {\n return (config.initial as (ctx: { documentId: string }) => Effect.Effect<Primitive.InferSetInput<TSchema>>)({\n documentId,\n });\n }\n\n return Effect.succeed(config.initial as Primitive.InferSetInput<TSchema>);\n};\n\n/**\n * Verify WAL continuity and log warnings for any gaps.\n */\nconst verifyWalContinuity = Effect.fn(\"document.wal.verify\")(function* (\n documentId: string,\n walEntries: readonly WalEntry[],\n baseVersion: number\n) {\n if (walEntries.length === 0) {\n return;\n }\n\n const firstWalVersion = walEntries[0]!.version;\n const expectedFirst = baseVersion + 1;\n\n if (firstWalVersion !== expectedFirst) {\n yield* Effect.logWarning(\"WAL version gap detected\", {\n documentId,\n snapshotVersion: baseVersion,\n firstWalVersion,\n expectedFirst,\n });\n yield* Metric.update(Metrics.storageVersionGaps, 1);\n }\n\n for (let i = 1; i < walEntries.length; i++) {\n const prev = walEntries[i - 1]!.version;\n const curr = walEntries[i]!.version;\n if (curr !== prev + 1) {\n yield* Effect.logWarning(\"WAL internal gap detected\", {\n documentId,\n previousVersion: prev,\n currentVersion: curr,\n });\n }\n }\n});\n\n/**\n * Replay WAL entries onto a ServerDocument.\n */\nconst replayWalEntries = Effect.fn(\"document.wal.replay\")(function* (\n documentId: string,\n document: ServerDocument.ServerDocument<Primitive.AnyPrimitive>,\n walEntries: readonly WalEntry[]\n) {\n for (const entry of walEntries) {\n const result = document.submit(entry.transaction);\n if (!result.success) {\n yield* Effect.logWarning(\"Skipping corrupted WAL entry\", {\n documentId,\n version: entry.version,\n reason: result.reason,\n });\n }\n }\n});\n\n/**\n * Compute snapshot state by replaying WAL entries on a base state.\n */\nconst computeSnapshotState = <TSchema extends Primitive.AnyPrimitive>(\n schema: TSchema,\n baseState: Primitive.InferState<TSchema> | undefined,\n walEntries: readonly WalEntry[],\n targetVersion: number\n): { state: Primitive.InferState<TSchema>; version: number } | undefined => {\n const relevantEntries = walEntries.filter((e) => e.version <= targetVersion);\n\n if (relevantEntries.length === 0 && baseState === undefined) {\n return undefined;\n }\n\n let snapshotState: Primitive.InferState<TSchema> | undefined = baseState;\n for (const entry of relevantEntries) {\n const tempDoc = Document.make(schema, { initialState: snapshotState });\n tempDoc.apply(entry.transaction.ops);\n snapshotState = tempDoc.get();\n }\n\n if (snapshotState === undefined) {\n return undefined;\n }\n\n const snapshotVersion =\n relevantEntries.length > 0 ? relevantEntries[relevantEntries.length - 1]!.version : 0;\n\n return { state: snapshotState, version: snapshotVersion };\n};\n\n/**\n * Check if a snapshot should be triggered.\n */\nconst shouldTriggerSnapshot = (\n transactionsSinceSnapshot: number,\n lastSnapshotTime: number,\n config: { interval: Duration.Duration; transactionThreshold: number }\n): boolean => {\n const now = Date.now();\n const intervalMs = Duration.toMillis(config.interval);\n\n if (transactionsSinceSnapshot >= config.transactionThreshold) {\n return true;\n }\n\n if (now - lastSnapshotTime >= intervalMs) {\n return true;\n }\n\n return false;\n};\n\n/**\n * Create a StoredDocument for persistence.\n */\nconst createStoredDocument = (\n state: unknown,\n version: number,\n schemaVersion: number\n): StoredDocument => ({\n state,\n version,\n schemaVersion,\n savedAt: Date.now(),\n});\n\n// =============================================================================\n// Re-export namespace\n// =============================================================================\n\nexport const DocumentInstance = {\n make,\n};\n"],"mappings":"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"}
package/dist/Errors.d.cts CHANGED
@@ -2,7 +2,7 @@ import * as effect_Types0 from "effect/Types";
2
2
  import * as effect_Cause0 from "effect/Cause";
3
3
 
4
4
  //#region src/Errors.d.ts
5
- declare const ColdStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
5
+ declare const ColdStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
6
6
  readonly _tag: "ColdStorageError";
7
7
  } & Readonly<A>;
8
8
  /**
@@ -13,7 +13,7 @@ declare class ColdStorageError extends ColdStorageError_base<{
13
13
  readonly operation: "load" | "save" | "delete";
14
14
  readonly cause: unknown;
15
15
  }> {}
16
- declare const HotStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
16
+ declare const HotStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
17
17
  readonly _tag: "HotStorageError";
18
18
  } & Readonly<A>;
19
19
  /**
@@ -24,7 +24,7 @@ declare class HotStorageError extends HotStorageError_base<{
24
24
  readonly operation: "append" | "getEntries" | "truncate" | "appendWithCheck";
25
25
  readonly cause: unknown;
26
26
  }> {}
27
- declare const WalVersionGapError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
27
+ declare const WalVersionGapError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
28
28
  readonly _tag: "WalVersionGapError";
29
29
  } & Readonly<A>;
30
30
  /**
@@ -39,7 +39,7 @@ declare class WalVersionGapError extends WalVersionGapError_base<{
39
39
  readonly expectedVersion: number;
40
40
  readonly actualPreviousVersion: number | undefined;
41
41
  }> {}
42
- declare const AuthenticationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
42
+ declare const AuthenticationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
43
43
  readonly _tag: "AuthenticationError";
44
44
  } & Readonly<A>;
45
45
  /**
@@ -48,7 +48,7 @@ declare const AuthenticationError_base: new <A extends Record<string, any> = {}>
48
48
  declare class AuthenticationError extends AuthenticationError_base<{
49
49
  readonly reason: string;
50
50
  }> {}
51
- declare const AuthorizationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
51
+ declare const AuthorizationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
52
52
  readonly _tag: "AuthorizationError";
53
53
  } & Readonly<A>;
54
54
  /**
@@ -59,7 +59,7 @@ declare class AuthorizationError extends AuthorizationError_base<{
59
59
  readonly required: "read" | "write";
60
60
  readonly actual: "read" | "write";
61
61
  }> {}
62
- declare const MissingDocumentIdError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
62
+ declare const MissingDocumentIdError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
63
63
  readonly _tag: "MissingDocumentIdError";
64
64
  } & Readonly<A>;
65
65
  /**
@@ -68,7 +68,7 @@ declare const MissingDocumentIdError_base: new <A extends Record<string, any> =
68
68
  declare class MissingDocumentIdError extends MissingDocumentIdError_base<{
69
69
  readonly path: string;
70
70
  }> {}
71
- declare const MessageParseError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
71
+ declare const MessageParseError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
72
72
  readonly _tag: "MessageParseError";
73
73
  } & Readonly<A>;
74
74
  /**
@@ -77,7 +77,7 @@ declare const MessageParseError_base: new <A extends Record<string, any> = {}>(a
77
77
  declare class MessageParseError extends MessageParseError_base<{
78
78
  readonly cause: unknown;
79
79
  }> {}
80
- declare const TransactionRejectedError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
80
+ declare const TransactionRejectedError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
81
81
  readonly _tag: "TransactionRejectedError";
82
82
  } & Readonly<A>;
83
83
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Errors.d.cts","names":[],"sources":["../src/Errors.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAca,gBAAA,SAAyB;;;;;cAIjC;;;;;AAJL;AAIK,cAKQ,eAAA,SAAwB,oBALhC,CAAA;;;;;cASA;;;;;;;AAJL;AAIK;;cASQ,kBAAA,SAA2B;;;;;cAInC;;;;;AAJL;AAIK,cASQ,mBAAA,SAA4B,wBATpC,CAAA;;;cAaA;;;;;;cAKQ,kBAAA,SAA2B;;;EAT3B,SAAA,MAAA,EAAA,MAAoB,GAAA,OAAA;AAI5B,CAAA,CAAA,CAAA;cASA;;;;;;cASQ,sBAAA,SAA+B;;;cAIvC;EAjBQ,SAAA,IAAA,EAAA,mBAA2B;AAInC,CAAA,WAAA,EAAA,CAAA;;;;cAkBQ,iBAAA,SAA0B;;;cAElC;;;;;AAXL;AAIK,cAgBQ,wBAAA,SAAiC,6BAhBzC,CAAA;;;;;;;KA8BO,UAAA,GACR,mBACA,kBACA,qBACA,sBACA,qBACA,yBACA,oBACA"}
1
+ {"version":3,"file":"Errors.d.cts","names":[],"sources":["../src/Errors.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAca,gBAAA,SAAyB;;;;;cAIjC;;;;;;cAKQ,eAAA,SAAwB;;;EATxB,SAAA,KAAA,EAAA,OAAiB;AAIzB,CAAA,CAAA,CAAA;cASA;;;;;;;;;;cASQ,kBAAA,SAA2B;;;;;AATnC,cAaA,wBAbA,EAAA,IAAA,CAAA,gBAAA,CAAA,MAAA,EAAA,GAAA,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,IAAA,2BAAA,CAAA,iBAAA,OAAA,KAAA,SAAA,MAAA,GAAA,KAAA,IAAA,IAAA,EAAA,CAAA,EAAA,EAAA,IAAA,EAAA,iBAAA,OAAA,KAAA,SAAA,MAAA,GAAA,KAAA,IAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,kCAAA;;;;;;cAsBQ,mBAAA,SAA4B;;;cAIpC;;;;;;cAKQ,kBAAA,SAA2B;EAtB3B,SAAA,MAAA,EAAA,MAAmB;EAI3B,SAAA,QAAA,EAAA,MAAA,GAAA,OAAA;;;cAsBA;;;;;;cASQ,sBAAA,SAA+B;;;cAIvC;;;AA1BL;AAIK;;cA2BQ,iBAAA,SAA0B;;;cAElC;;;;;;cASQ,wBAAA,SAAiC;;;;AAjC9C;AAIK;;KA2CO,UAAA,GACR,mBACA,kBACA,qBACA,sBACA,qBACA,yBACA,oBACA"}
package/dist/Errors.d.mts CHANGED
@@ -2,7 +2,7 @@ import * as effect_Types0 from "effect/Types";
2
2
  import * as effect_Cause0 from "effect/Cause";
3
3
 
4
4
  //#region src/Errors.d.ts
5
- declare const ColdStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
5
+ declare const ColdStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
6
6
  readonly _tag: "ColdStorageError";
7
7
  } & Readonly<A>;
8
8
  /**
@@ -13,7 +13,7 @@ declare class ColdStorageError extends ColdStorageError_base<{
13
13
  readonly operation: "load" | "save" | "delete";
14
14
  readonly cause: unknown;
15
15
  }> {}
16
- declare const HotStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
16
+ declare const HotStorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
17
17
  readonly _tag: "HotStorageError";
18
18
  } & Readonly<A>;
19
19
  /**
@@ -24,7 +24,7 @@ declare class HotStorageError extends HotStorageError_base<{
24
24
  readonly operation: "append" | "getEntries" | "truncate" | "appendWithCheck";
25
25
  readonly cause: unknown;
26
26
  }> {}
27
- declare const WalVersionGapError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
27
+ declare const WalVersionGapError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
28
28
  readonly _tag: "WalVersionGapError";
29
29
  } & Readonly<A>;
30
30
  /**
@@ -39,7 +39,7 @@ declare class WalVersionGapError extends WalVersionGapError_base<{
39
39
  readonly expectedVersion: number;
40
40
  readonly actualPreviousVersion: number | undefined;
41
41
  }> {}
42
- declare const AuthenticationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
42
+ declare const AuthenticationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
43
43
  readonly _tag: "AuthenticationError";
44
44
  } & Readonly<A>;
45
45
  /**
@@ -48,7 +48,7 @@ declare const AuthenticationError_base: new <A extends Record<string, any> = {}>
48
48
  declare class AuthenticationError extends AuthenticationError_base<{
49
49
  readonly reason: string;
50
50
  }> {}
51
- declare const AuthorizationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
51
+ declare const AuthorizationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
52
52
  readonly _tag: "AuthorizationError";
53
53
  } & Readonly<A>;
54
54
  /**
@@ -59,7 +59,7 @@ declare class AuthorizationError extends AuthorizationError_base<{
59
59
  readonly required: "read" | "write";
60
60
  readonly actual: "read" | "write";
61
61
  }> {}
62
- declare const MissingDocumentIdError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
62
+ declare const MissingDocumentIdError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
63
63
  readonly _tag: "MissingDocumentIdError";
64
64
  } & Readonly<A>;
65
65
  /**
@@ -68,7 +68,7 @@ declare const MissingDocumentIdError_base: new <A extends Record<string, any> =
68
68
  declare class MissingDocumentIdError extends MissingDocumentIdError_base<{
69
69
  readonly path: string;
70
70
  }> {}
71
- declare const MessageParseError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
71
+ declare const MessageParseError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
72
72
  readonly _tag: "MessageParseError";
73
73
  } & Readonly<A>;
74
74
  /**
@@ -77,7 +77,7 @@ declare const MessageParseError_base: new <A extends Record<string, any> = {}>(a
77
77
  declare class MessageParseError extends MessageParseError_base<{
78
78
  readonly cause: unknown;
79
79
  }> {}
80
- declare const TransactionRejectedError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
80
+ declare const TransactionRejectedError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.MatchRecord<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }, void, { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => effect_Cause0.YieldableError & {
81
81
  readonly _tag: "TransactionRejectedError";
82
82
  } & Readonly<A>;
83
83
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Errors.d.mts","names":[],"sources":["../src/Errors.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAca,gBAAA,SAAyB;;;;;cAIjC;;;;;AAJL;AAIK,cAKQ,eAAA,SAAwB,oBALhC,CAAA;;;;;cASA;;;;;;;AAJL;AAIK;;cASQ,kBAAA,SAA2B;;;;;cAInC;;;;;AAJL;AAIK,cASQ,mBAAA,SAA4B,wBATpC,CAAA;;;cAaA;;;;;;cAKQ,kBAAA,SAA2B;;;EAT3B,SAAA,MAAA,EAAA,MAAoB,GAAA,OAAA;AAI5B,CAAA,CAAA,CAAA;cASA;;;;;;cASQ,sBAAA,SAA+B;;;cAIvC;EAjBQ,SAAA,IAAA,EAAA,mBAA2B;AAInC,CAAA,WAAA,EAAA,CAAA;;;;cAkBQ,iBAAA,SAA0B;;;cAElC;;;;;AAXL;AAIK,cAgBQ,wBAAA,SAAiC,6BAhBzC,CAAA;;;;;;;KA8BO,UAAA,GACR,mBACA,kBACA,qBACA,sBACA,qBACA,yBACA,oBACA"}
1
+ {"version":3,"file":"Errors.d.mts","names":[],"sources":["../src/Errors.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAca,gBAAA,SAAyB;;;;;cAIjC;;;;;;cAKQ,eAAA,SAAwB;;;EATxB,SAAA,KAAA,EAAA,OAAiB;AAIzB,CAAA,CAAA,CAAA;cASA;;;;;;;;;;cASQ,kBAAA,SAA2B;;;;;AATnC,cAaA,wBAbA,EAAA,IAAA,CAAA,gBAAA,CAAA,MAAA,EAAA,GAAA,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,IAAA,2BAAA,CAAA,iBAAA,OAAA,KAAA,SAAA,MAAA,GAAA,KAAA,IAAA,IAAA,EAAA,CAAA,EAAA,EAAA,IAAA,EAAA,iBAAA,OAAA,KAAA,SAAA,MAAA,GAAA,KAAA,IAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,kCAAA;;;;;;cAsBQ,mBAAA,SAA4B;;;cAIpC;;;;;;cAKQ,kBAAA,SAA2B;EAtB3B,SAAA,MAAA,EAAA,MAAmB;EAI3B,SAAA,QAAA,EAAA,MAAA,GAAA,OAAA;;;cAsBA;;;;;;cASQ,sBAAA,SAA+B;;;cAIvC;;;AA1BL;AAIK;;cA2BQ,iBAAA,SAA0B;;;cAElC;;;;;;cASQ,wBAAA,SAAiC;;;;AAjC9C;AAIK;;KA2CO,UAAA,GACR,mBACA,kBACA,qBACA,sBACA,qBACA,yBACA,oBACA"}
@@ -10,7 +10,7 @@ let effect = require("effect");
10
10
  /**
11
11
  * Context tag for HotStorage service
12
12
  */
13
- var HotStorageTag = class extends effect.Context.Tag("@voidhash/mimic-effect/HotStorage")() {};
13
+ var HotStorageTag = class extends effect.ServiceMap.Service()("@voidhash/mimic-effect/HotStorage") {};
14
14
  /**
15
15
  * Create a HotStorage layer from an Effect that produces a HotStorage service.
16
16
  *
@@ -1,6 +1,6 @@
1
1
  import { WalEntry } from "./Types.cjs";
2
2
  import { HotStorageError, WalVersionGapError } from "./Errors.cjs";
3
- import { Context, Effect, Layer } from "effect";
3
+ import { Effect, Layer, ServiceMap } from "effect";
4
4
 
5
5
  //#region src/HotStorage.d.ts
6
6
 
@@ -47,7 +47,7 @@ interface HotStorage {
47
47
  */
48
48
  readonly truncate: (documentId: string, upToVersion: number) => Effect.Effect<void, HotStorageError>;
49
49
  }
50
- declare const HotStorageTag_base: Context.TagClass<HotStorageTag, "@voidhash/mimic-effect/HotStorage", HotStorage>;
50
+ declare const HotStorageTag_base: ServiceMap.ServiceClass<HotStorageTag, "@voidhash/mimic-effect/HotStorage", HotStorage>;
51
51
  /**
52
52
  * Context tag for HotStorage service
53
53
  */
@@ -1,6 +1,6 @@
1
1
  import { WalEntry } from "./Types.mjs";
2
2
  import { HotStorageError, WalVersionGapError } from "./Errors.mjs";
3
- import { Context, Effect, Layer } from "effect";
3
+ import { Effect, Layer, ServiceMap } from "effect";
4
4
 
5
5
  //#region src/HotStorage.d.ts
6
6
 
@@ -47,7 +47,7 @@ interface HotStorage {
47
47
  */
48
48
  readonly truncate: (documentId: string, upToVersion: number) => Effect.Effect<void, HotStorageError>;
49
49
  }
50
- declare const HotStorageTag_base: Context.TagClass<HotStorageTag, "@voidhash/mimic-effect/HotStorage", HotStorage>;
50
+ declare const HotStorageTag_base: ServiceMap.ServiceClass<HotStorageTag, "@voidhash/mimic-effect/HotStorage", HotStorage>;
51
51
  /**
52
52
  * Context tag for HotStorage service
53
53
  */
@@ -1,5 +1,5 @@
1
1
  import { WalVersionGapError } from "./Errors.mjs";
2
- import { Context, Effect, HashMap, Layer, Ref } from "effect";
2
+ import { Effect, HashMap, Layer, Ref, ServiceMap } from "effect";
3
3
 
4
4
  //#region src/HotStorage.ts
5
5
  /**
@@ -10,7 +10,7 @@ import { Context, Effect, HashMap, Layer, Ref } from "effect";
10
10
  /**
11
11
  * Context tag for HotStorage service
12
12
  */
13
- var HotStorageTag = class extends Context.Tag("@voidhash/mimic-effect/HotStorage")() {};
13
+ var HotStorageTag = class extends ServiceMap.Service()("@voidhash/mimic-effect/HotStorage") {};
14
14
  /**
15
15
  * Create a HotStorage layer from an Effect that produces a HotStorage service.
16
16
  *