@livestore/utils 0.5.0-dev.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/Deferred.d.ts.map +1 -1
  3. package/dist/NoopTracer.d.ts.map +1 -1
  4. package/dist/NoopTracer.test.js +13 -1
  5. package/dist/NoopTracer.test.js.map +1 -1
  6. package/dist/base64.d.ts.map +1 -1
  7. package/dist/binary.d.ts.map +1 -1
  8. package/dist/browser/Opfs/Opfs.js +5 -5
  9. package/dist/browser/Opfs/Opfs.js.map +1 -1
  10. package/dist/browser/Opfs/debug-utils.d.ts.map +1 -1
  11. package/dist/browser/Opfs/debug-utils.js +2 -2
  12. package/dist/browser/Opfs/mod.js +3 -3
  13. package/dist/browser/Opfs/utils.d.ts +6 -6
  14. package/dist/browser/Opfs/utils.js +1 -1
  15. package/dist/browser/WebChannelBrowser.d.ts.map +1 -1
  16. package/dist/browser/WebChannelBrowser.js +4 -4
  17. package/dist/browser/WebError.d.ts +2 -2
  18. package/dist/browser/WebError.d.ts.map +1 -1
  19. package/dist/browser/WebError.js +1 -1
  20. package/dist/browser/WebError.js.map +1 -1
  21. package/dist/browser/WebError.test.js +1 -1
  22. package/dist/browser/WebLock.d.ts +1 -1
  23. package/dist/browser/WebLock.d.ts.map +1 -1
  24. package/dist/browser/mod.js +6 -6
  25. package/dist/cuid/cuid.browser.d.ts.map +1 -1
  26. package/dist/cuid/cuid.node.d.ts.map +1 -1
  27. package/dist/effect/Debug.d.ts.map +1 -1
  28. package/dist/effect/Debug.js +2 -4
  29. package/dist/effect/Debug.js.map +1 -1
  30. package/dist/effect/Effect.d.ts.map +1 -1
  31. package/dist/effect/Effect.js +5 -5
  32. package/dist/effect/Effect.js.map +1 -1
  33. package/dist/effect/Effect.test.js +2 -2
  34. package/dist/effect/Effect.test.js.map +1 -1
  35. package/dist/effect/OtelTracer.d.ts.map +1 -1
  36. package/dist/effect/RpcClient.d.ts +7 -7
  37. package/dist/effect/RpcClient.d.ts.map +1 -1
  38. package/dist/effect/RpcClient.js +65 -56
  39. package/dist/effect/RpcClient.js.map +1 -1
  40. package/dist/effect/Schema/debug-diff.d.ts.map +1 -1
  41. package/dist/effect/Schema/debug-diff.test.js +1 -1
  42. package/dist/effect/Schema/index.d.ts.map +1 -1
  43. package/dist/effect/Schema/index.js +4 -4
  44. package/dist/effect/Schema/index.js.map +1 -1
  45. package/dist/effect/Stream.d.ts.map +1 -1
  46. package/dist/effect/Stream.js.map +1 -1
  47. package/dist/effect/Stream.test.js +1 -1
  48. package/dist/effect/Subscribable.d.ts.map +1 -1
  49. package/dist/effect/SubscriptionRef.d.ts.map +1 -1
  50. package/dist/effect/TaskTracing.d.ts.map +1 -1
  51. package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
  52. package/dist/effect/WebChannel/WebChannel.js +6 -6
  53. package/dist/effect/WebChannel/WebChannel.js.map +1 -1
  54. package/dist/effect/WebChannel/WebChannel.test.js +1 -1
  55. package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts.map +1 -1
  56. package/dist/effect/WebChannel/broadcastChannelWithAck.js +3 -3
  57. package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
  58. package/dist/effect/WebChannel/common.d.ts.map +1 -1
  59. package/dist/effect/WebChannel/mod.js +3 -3
  60. package/dist/effect/WebSocket.d.ts +1 -1
  61. package/dist/effect/WebSocket.d.ts.map +1 -1
  62. package/dist/effect/WebSocket.js +1 -1
  63. package/dist/effect/WebSocket.js.map +1 -1
  64. package/dist/effect/WebSocket.test.js +2 -2
  65. package/dist/effect/WebSocket.test.js.map +1 -1
  66. package/dist/effect/mod.browser-build.test.js.map +1 -1
  67. package/dist/effect/mod.d.ts +11 -11
  68. package/dist/effect/mod.d.ts.map +1 -1
  69. package/dist/effect/mod.js +26 -26
  70. package/dist/effect/mod.js.map +1 -1
  71. package/dist/effect/spanEvent.d.ts.map +1 -1
  72. package/dist/effect/spanEvent.test.js +1 -1
  73. package/dist/env.d.ts.map +1 -1
  74. package/dist/env.js +1 -1
  75. package/dist/env.js.map +1 -1
  76. package/dist/fast-deep-equal.d.ts.map +1 -1
  77. package/dist/fast-deep-equal.js.map +1 -1
  78. package/dist/misc.d.ts.map +1 -1
  79. package/dist/misc.js +1 -1
  80. package/dist/misc.js.map +1 -1
  81. package/dist/mod.d.ts +1 -1
  82. package/dist/mod.d.ts.map +1 -1
  83. package/dist/mod.js +19 -19
  84. package/dist/mod.js.map +1 -1
  85. package/dist/node/mod.d.ts +9 -40
  86. package/dist/node/mod.d.ts.map +1 -1
  87. package/dist/node/mod.js +9 -41
  88. package/dist/node/mod.js.map +1 -1
  89. package/dist/object/index.js +1 -1
  90. package/dist/object/stringify-object.d.ts.map +1 -1
  91. package/dist/object/stringify-object.test.js +1 -1
  92. package/dist/promise.d.ts.map +1 -1
  93. package/dist/qr.d.ts.map +1 -1
  94. package/dist/set.d.ts.map +1 -1
  95. package/dist/string.d.ts.map +1 -1
  96. package/package.json +36 -36
  97. package/src/NoopTracer.test.ts +16 -0
  98. package/src/browser/Opfs/Opfs.ts +4 -4
  99. package/src/effect/Debug.ts +6 -22
  100. package/src/effect/Effect.test.ts +1 -1
  101. package/src/effect/Effect.ts +3 -3
  102. package/src/effect/RpcClient.ts +77 -63
  103. package/src/effect/Schema/index.ts +2 -2
  104. package/src/effect/WebChannel/WebChannel.ts +1 -2
  105. package/src/effect/WebSocket.test.ts +1 -1
  106. package/src/effect/WebSocket.ts +1 -1
  107. package/src/effect/mod.ts +12 -10
  108. package/src/fast-deep-equal.ts +4 -4
  109. package/src/misc.ts +1 -1
  110. package/src/mod.ts +5 -5
  111. package/src/node/mod.ts +8 -40
package/dist/node/mod.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as http from 'node:http';
2
2
  import { NodeFileSystem } from '@effect/platform-node';
3
3
  import { Effect, FileSystem, Layer, Option } from 'effect';
4
- import { OtelTracer, Tracer, UnknownError } from "../effect/mod.js";
5
- import { makeNoopTracer } from "../NoopTracer.js";
6
- export * as Cli from 'effect/unstable/cli';
7
- export * as SocketServer from 'effect/unstable/socket/SocketServer';
4
+ import { OtelTracer, Tracer, UnknownError } from '../effect/mod.js';
5
+ import { makeNoopTracer } from '../NoopTracer.js';
6
+ export * as Cli from 'effect/cli';
7
+ export * as SocketServer from 'effect/socket/SocketServer';
8
8
  export * as PlatformNode from '@effect/platform-node';
9
9
  // Enable debug logging for OpenTelemetry
10
10
  // otel.diag.setLogger(new otel.DiagConsoleLogger(), otel.DiagLogLevel.ERROR)
@@ -35,47 +35,15 @@ export const OtelLiveDummy = Layer.suspend(() => {
35
35
  const TracingLive = OtelTracer.layerWithoutOtelTracer.pipe(Layer.provideMerge(OtelTracerLive));
36
36
  return TracingLive;
37
37
  });
38
+ export { NodeFileSystem };
38
39
  /**
39
- * Compatibility layer for the old Effect v3 @parcel/watcher backend.
40
- *
41
- * Effect v4 removed `@effect/platform-node/NodeFileSystem/ParcelWatcher`; its
42
- * NodeFileSystem layer now performs recursive watching through Node's native
43
- * `fs.watch(path, { recursive: true })` fallback. This layer deliberately
44
- * registers no custom backend so existing `NodeRecursiveWatchLayer` consumers
45
- * continue to compile while the v4 NodeFileSystem implementation handles watch
46
- * events.
47
- *
48
- * This layer alone does NOT provide FileSystem - it only provides the watch backend.
49
- *
50
- * IMPORTANT: Layer ordering matters! When composing with NodeFileSystem.layer, use
51
- * `NodeFileSystemWithWatch` instead, or ensure WatchBackend is available when FileSystem
52
- * is constructed by using `Layer.provideMerge`:
53
- *
54
- * ```ts
55
- * // ✅ CORRECT: Use the pre-composed layer
56
- * Effect.provide(NodeFileSystemWithWatch)
57
- *
58
- * // ✅ CORRECT: Manual composition with Layer.provideMerge
59
- * const layer = PlatformNode.NodeFileSystem.layer.pipe(Layer.provideMerge(NodeRecursiveWatchLayer))
60
- * Effect.provide(layer)
61
- *
62
- * // ❌ WRONG: Chained Effect.provide - WatchBackend won't be used!
63
- * Effect.provide(NodeRecursiveWatchLayer).pipe(Effect.provide(PlatformNode.NodeFileSystem.layer))
64
- * ```
65
- *
66
- * @see https://github.com/Effect-TS/effect/issues/5913
40
+ * Effect 4 uses Node's native recursive watcher when no custom watch backend
41
+ * registers for the requested path. Keep the public Effect 3 compatibility
42
+ * layer while deliberately deferring to that native implementation.
67
43
  */
68
44
  export const NodeRecursiveWatchLayer = Layer.succeed(FileSystem.WatchBackend, FileSystem.WatchBackend.of({
69
45
  register: () => Option.none(),
70
46
  }));
71
- /**
72
- * Pre-composed layer providing FileSystem with recursive file watching.
73
- * This is the recommended way to get a FileSystem that supports recursive watching.
74
- *
75
- * Use this layer when you need to watch files recursively (e.g., watching nested directories).
76
- * Effect v4's NodeFileSystem uses Node.js's native recursive `fs.watch` support
77
- * instead of the removed ParcelWatcher backend from Effect v3.
78
- */
79
- export { NodeFileSystem } from '@effect/platform-node';
47
+ /** FileSystem layer retaining the public recursive-watch composition API. */
80
48
  export const NodeFileSystemWithWatch = NodeFileSystem.layer.pipe(Layer.provideMerge(NodeRecursiveWatchLayer));
81
49
  //# sourceMappingURL=mod.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../src/node/mod.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../src/node/mod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE1D,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,KAAK,GAAG,MAAM,YAAY,CAAA;AACjC,OAAO,KAAK,YAAY,MAAM,4BAA4B,CAAA;AAC1D,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AAErD,yCAAyC;AACzC,6EAA6E;AAE7E,6EAA6E;AAE7E,MAAM,CAAC,MAAM,WAAW,GAAwC,MAAM,CAAC,QAAQ,CAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE;IACnH,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;IAElC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,KAAK,EAAE,CAAA;IAChB,CAAC,CAAC,CAAA;IAEF,4CAA4C;IAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE;QACpB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAA;QAEhC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;YACzB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC9C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/F,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,wDAAwD;IACxD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC3B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACxG,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,aAAa,GAAuC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;IAClF,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,cAAc,EAAE,CAAC,CAAA;IAE7E,MAAM,WAAW,GAAG,UAAU,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAA;IAE9F,OAAO,WAAW,CAAA;AACpB,CAAC,CAAC,CAAA;AAEF,OAAO,EAAE,cAAc,EAAE,CAAA;AAEzB;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAyC,KAAK,CAAC,OAAO,CACxF,UAAU,CAAC,YAAY,EACvB,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;IACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;CAC9B,CAAC,CACH,CAAA;AAED,6EAA6E;AAC7E,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC,CAAA"}
@@ -1,2 +1,2 @@
1
- export * from "./stringify-object.js";
1
+ export * from './stringify-object.js';
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stringify-object.d.ts","sourceRoot":"","sources":["../../src/object/stringify-object.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,EAAE,eAAW,KAAG,MAmB1D,CAAA"}
1
+ {"version":3,"file":"stringify-object.d.ts","sourceRoot":"","sources":["../../src/object/stringify-object.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,QAAS,MAAM,sBAAgB,MAmB1D,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import { stringifyObject } from "./stringify-object.js";
2
+ import { stringifyObject } from './stringify-object.js';
3
3
  describe('stringifyObject', () => {
4
4
  it('stringifies a flat object', () => {
5
5
  const obj = { a: 1, b: 'test', c: true };
@@ -1 +1 @@
1
- {"version":3,"file":"promise.d.ts","sourceRoot":"","sources":["../src/promise.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,6CACpE,CAAA;AAE3B,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,GAAG,EACzC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACvB,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,KACjD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAG7B,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,CAAC,EAAE,GAAG,EAC3C,KAAK,CAAC,EAAE,EACR,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,EACvD,QAAQ,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,KACxC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAI7B,CAAA;AAED,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,GAAG,EACzC,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,EAC5C,WAAW,MAAM,KAChB,OAAO,CAAC,GAAG,EAAE,CAgBf,CAAA"}
1
+ {"version":3,"file":"promise.d.ts","sourceRoot":"","sources":["../src/promise.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,6CACpE,CAAA;AAE3B,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,GAAG,QACnC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAClB,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,KACjD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAG7B,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,CAAC,EAAE,GAAG,OACtC,CAAC,EAAE,YACE,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,UAC/C,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,KACxC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAI7B,CAAA;AAED,eAAO,MAAM,cAAc,GAAU,CAAC,EAAE,GAAG,OACpC,CAAC,EAAE,OACH,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,aACjC,MAAM,KAChB,OAAO,CAAC,GAAG,EAAE,CAgBf,CAAA"}
package/dist/qr.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../src/qr.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAEhD,MAAM,MAAM,sBAAsB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAE1D,MAAM,MAAM,sBAAsB,GAAG;IACnC,oBAAoB,CAAC,EAAE,sBAAsB,CAAA;IAC7C,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gDAAgD;IAChD,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oFAAoF;IACpF,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,UAAU,sBAAsB,KAAG,IAmFhF,CAAA"}
1
+ {"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../src/qr.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAEhD,MAAM,MAAM,sBAAsB,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAE1D,MAAM,MAAM,sBAAsB,GAAG;IACnC,oBAAoB,CAAC,EAAE,sBAAsB,CAAA;IAC7C,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gDAAgD;IAChD,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oFAAoF;IACpF,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,eAAe,SAAU,MAAM,YAAY,sBAAsB,KAAG,IAmFhF,CAAA"}
package/dist/set.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../src/set.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,WASjD,CAAA"}
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../src/set.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,WASjD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,EAAE,GAAG,MAAM,EAAE,aAAU,KAAG,MAI7C,CAAA"}
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,eAAO,MAAM,MAAM,QAAS,MAAM,KAAK,MAAM,oBAAe,MAI7C,CAAA"}
package/package.json CHANGED
@@ -1,22 +1,23 @@
1
1
  {
2
- "name": "@livestore/utils",
3
- "version": "0.5.0-dev.0",
4
- "license": "Apache-2.0",
5
- "repository": {
6
- "type": "git",
7
- "url": "git+https://github.com/livestorejs/livestore.git"
2
+ "$genie": {
3
+ "source": "package.json.genie.ts",
4
+ "warning": "DO NOT EDIT - changes will be overwritten",
5
+ "workspaceClosureDirs": [
6
+ "packages/@livestore/utils"
7
+ ]
8
8
  },
9
- "files": [
10
- "dist",
11
- "package.json",
12
- "src"
13
- ],
9
+ "name": "@livestore/utils",
10
+ "version": "0.5.0",
14
11
  "type": "module",
15
12
  "sideEffects": [
16
13
  "./src/global.ts",
17
14
  "./dist/global.js"
18
15
  ],
19
- "react-native": "./dist/index.js",
16
+ "license": "Apache-2.0",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/livestorejs/livestore.git"
20
+ },
20
21
  "exports": {
21
22
  ".": {
22
23
  "types": "./dist/mod.d.ts",
@@ -53,23 +54,25 @@
53
54
  "default": "./dist/bun/mod.js"
54
55
  }
55
56
  },
56
- "publishConfig": {
57
- "access": "public"
58
- },
57
+ "files": [
58
+ "dist",
59
+ "package.json",
60
+ "src"
61
+ ],
59
62
  "dependencies": {
60
- "@effect/platform-node": "4.0.0-rc.111",
63
+ "@effect/platform-node": "4.0.3",
61
64
  "@standard-schema/spec": "1.1.0",
62
65
  "nanoid": "5.0.9",
63
66
  "pretty-bytes": "7.0.1",
64
67
  "qrcode-generator": "2.0.4"
65
68
  },
66
69
  "devDependencies": {
67
- "@effect/opentelemetry": "4.0.0-rc.111",
68
- "@effect/platform-browser": "4.0.0-rc.111",
69
- "@effect/platform-bun": "4.0.0-rc.111",
70
- "@effect/platform-node": "4.0.0-rc.111",
71
- "@effect/platform-node-shared": "4.0.0-rc.111",
72
- "@effect/vitest": "4.0.0-rc.111",
70
+ "@effect/opentelemetry": "4.0.3",
71
+ "@effect/platform-browser": "4.0.3",
72
+ "@effect/platform-bun": "4.0.3",
73
+ "@effect/platform-node": "4.0.3",
74
+ "@effect/platform-node-shared": "4.0.3",
75
+ "@effect/vitest": "4.0.3",
73
76
  "@opentelemetry/api": "1.9.0",
74
77
  "@opentelemetry/resources": "2.2.0",
75
78
  "@standard-schema/spec": "1.1.0",
@@ -77,30 +80,27 @@
77
80
  "@types/jsdom": "21.1.7",
78
81
  "@types/node": "25.3.3",
79
82
  "@types/web": "0.0.264",
80
- "effect": "4.0.0-rc.111",
83
+ "effect": "4.0.3",
81
84
  "esbuild": "0.28.0",
82
85
  "jsdom": "26.1.0",
83
86
  "vitest": "4.1.9"
84
87
  },
85
88
  "peerDependencies": {
86
- "@effect/opentelemetry": "^4.0.0-rc.111",
87
- "@effect/platform-browser": "^4.0.0-rc.111",
88
- "@effect/platform-bun": "^4.0.0-rc.111",
89
- "@effect/platform-node": "^4.0.0-rc.111",
90
- "@effect/platform-node-shared": "^4.0.0-rc.111",
91
- "@effect/vitest": "^4.0.0-rc.111",
89
+ "@effect/opentelemetry": "^4.0.3",
90
+ "@effect/platform-browser": "^4.0.3",
91
+ "@effect/platform-bun": "^4.0.3",
92
+ "@effect/platform-node": "^4.0.3",
93
+ "@effect/platform-node-shared": "^4.0.3",
94
+ "@effect/vitest": "^4.0.3",
92
95
  "@opentelemetry/api": "^1.9.0",
93
96
  "@opentelemetry/resources": "^2.2.0",
94
97
  "@standard-schema/spec": "^1.1.0",
95
- "effect": "^4.0.0-rc.111"
98
+ "effect": "^4.0.3"
96
99
  },
97
- "$genie": {
98
- "source": "package.json.genie.ts",
99
- "warning": "DO NOT EDIT - changes will be overwritten",
100
- "workspaceClosureDirs": [
101
- "packages/@livestore/utils"
102
- ]
100
+ "publishConfig": {
101
+ "access": "public"
103
102
  },
103
+ "react-native": "./dist/index.js",
104
104
  "scripts": {
105
105
  "test": "vitest"
106
106
  }
@@ -1,6 +1,9 @@
1
1
  import { INVALID_SPAN_CONTEXT, isSpanContextValid, ROOT_CONTEXT } from '@opentelemetry/api'
2
+ import { Effect, FileSystem, type Layer } from 'effect'
2
3
  import { describe, expect, it } from 'vitest'
3
4
 
5
+ import { NodeFileSystemWithWatch, NodeRecursiveWatchLayer } from '@livestore/utils/node'
6
+
4
7
  import { makeNoopSpan, makeNoopTracer } from './NoopTracer.ts'
5
8
 
6
9
  describe('NoopTracer', () => {
@@ -18,3 +21,16 @@ describe('NoopTracer', () => {
18
21
  expect(tracer.startActiveSpan('four arguments', {}, ROOT_CONTEXT, () => 'four')).toBe('four')
19
22
  })
20
23
  })
24
+
25
+ describe('@livestore/utils/node recursive watch compatibility', () => {
26
+ it('keeps the public layers type-compatible and runnable', async () => {
27
+ const watchLayer: Layer.Layer<FileSystem.WatchBackend> = NodeRecursiveWatchLayer
28
+ const fileSystemLayer: Layer.Layer<FileSystem.FileSystem> = NodeFileSystemWithWatch
29
+
30
+ const watchBackend = await Effect.runPromise(FileSystem.WatchBackend.pipe(Effect.provide(watchLayer)))
31
+ const fileSystem = await Effect.runPromise(FileSystem.FileSystem.pipe(Effect.provide(fileSystemLayer)))
32
+
33
+ expect(typeof watchBackend.register).toBe('function')
34
+ expect(typeof fileSystem.watch).toBe('function')
35
+ })
36
+ })
@@ -308,7 +308,7 @@ export const layer = Layer.succeed(
308
308
  Effect.tryPromise({
309
309
  try: () => stream.close(),
310
310
  catch: (u) => WebError.classifyWebError(u, [WebError.TypeError]),
311
- }).pipe(Effect.catchCause(() => Effect.void)),
311
+ }).pipe(Effect.ignoreCause),
312
312
  ),
313
313
  appendToFile: (handle: FileSystemFileHandle, data: FileSystemWriteChunkType) =>
314
314
  Effect.acquireUseRelease(
@@ -346,7 +346,7 @@ export const layer = Layer.succeed(
346
346
  Effect.tryPromise({
347
347
  try: () => stream.close(),
348
348
  catch: (u) => WebError.classifyWebError(u, [WebError.TypeError]),
349
- }).pipe(Effect.catchCause(() => Effect.void)),
349
+ }).pipe(Effect.ignoreCause),
350
350
  ),
351
351
  truncateFile: (handle: FileSystemFileHandle, size: number) =>
352
352
  Effect.acquireUseRelease(
@@ -370,7 +370,7 @@ export const layer = Layer.succeed(
370
370
  Effect.tryPromise({
371
371
  try: () => stream.close(),
372
372
  catch: (u) => WebError.classifyWebError(u, [WebError.TypeError]),
373
- }).pipe(Effect.catchCause(() => Effect.void)),
373
+ }).pipe(Effect.ignoreCause),
374
374
  ),
375
375
  createSyncAccessHandle: (handle: FileSystemFileHandle) =>
376
376
  Effect.acquireRelease(
@@ -440,7 +440,7 @@ export const layerNoop = Layer.succeed(
440
440
  getDirectoryHandle: () => Effect.fail(notFoundError),
441
441
  removeEntry: () => Effect.fail(notFoundError),
442
442
  values: () => Stream.fail(notFoundError),
443
- resolve: () => Effect.succeed(Option.none()),
443
+ resolve: () => Effect.succeedNone,
444
444
  getFile: () => Effect.fail(notFoundError),
445
445
  writeFile: () => Effect.fail(notFoundError),
446
446
  appendToFile: () => Effect.fail(notFoundError),
@@ -194,24 +194,12 @@ const ensureTracerPatched = (tracer: Tracer.Tracer) => {
194
194
  }
195
195
  }
196
196
 
197
- interface ScopeImpl extends Scope.Scope {
198
- readonly state:
199
- | {
200
- readonly _tag: 'Open'
201
- readonly finalizers: Map<{}, (exit: Exit.Exit<unknown, unknown>) => Effect.Effect<unknown>>
202
- }
203
- | {
204
- readonly _tag: 'Closed'
205
- readonly exit: Exit.Exit<unknown, unknown>
206
- }
207
- }
208
-
209
197
  const knownScopes = new Map<
210
- ScopeImpl,
198
+ Scope.Scope,
211
199
  { id: number; allocationFiber: Fiber.Fiber<any, any> | undefined; allocationSpan: Tracer.AnySpan | undefined }
212
200
  >()
213
201
  let lastScopeId = 0
214
- const ensureScopePatched = (scope: ScopeImpl, allocationFiber: Fiber.Fiber<any, any> | undefined) => {
202
+ const ensureScopePatched = (scope: Scope.Scope, allocationFiber: Fiber.Fiber<any, any> | undefined) => {
215
203
  if (scope.state._tag === 'Closed') return
216
204
  if (knownScopes.has(scope) === true) return
217
205
  const id = lastScopeId++
@@ -232,7 +220,7 @@ const ensureScopePatched = (scope: ScopeImpl, allocationFiber: Fiber.Fiber<any,
232
220
  } else {
233
221
  cleanupScopes()
234
222
  }
235
- const allocationSpan = allocationFiber?.currentSpan
223
+ const allocationSpan = allocationFiber?.cache.span
236
224
  knownScopes.set(scope, { id, allocationFiber, allocationSpan })
237
225
  }
238
226
  const cleanupScopes = () => {
@@ -247,8 +235,7 @@ const ensureFiberPatched = (fiber: Fiber.Fiber<any, any>) => {
247
235
  ensureTracerPatched(fiber.getRef(Tracer.Tracer))
248
236
  // patch scope
249
237
  const currentScope = Context.getOrElse(fiber.context, Scope.Scope, () => undefined)
250
- // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- casting Scope to ScopeImpl; internal Effect type not publicly exported
251
- if (currentScope !== undefined) ensureScopePatched(currentScope as any as ScopeImpl, undefined)
238
+ if (currentScope !== undefined) ensureScopePatched(currentScope, undefined)
252
239
  // patch fiber
253
240
  if (knownFibers.has(fiber) === true) return
254
241
  knownFibers.add(fiber)
@@ -296,8 +283,7 @@ export const attachSlowDebugInstrumentation = (options: {
296
283
  console.log('onEvent', event)
297
284
  switch (event._tag) {
298
285
  case 'ScopeAllocated':
299
- // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- casting Scope to ScopeImpl; internal Effect type not publicly exported
300
- ensureScopePatched(event.scope as any as ScopeImpl, _globalThis['~effect/Fiber/currentFiber'])
286
+ ensureScopePatched(event.scope, _globalThis['~effect/Fiber/currentFiber'])
301
287
  break
302
288
  case 'FiberAllocated':
303
289
  ensureFiberPatched(event.fiber)
@@ -377,9 +363,7 @@ const renderSpanNode = (graph: Graph.Graph<GraphNodeInfo, void, 'directed'>, nod
377
363
  const durationStr = duration !== undefined ? ` ${duration}` : ''
378
364
 
379
365
  const fiberIds = Array.from(knownFibers)
380
- .filter(
381
- (fiber) => fiber.currentSpan?.spanId === info.span.spanId && fiber.currentSpan?.traceId === info.span.traceId,
382
- )
366
+ .filter((fiber) => fiber.cache.span?.spanId === info.span.spanId && fiber.cache.span?.traceId === info.span.traceId)
383
367
  .map((fiber) => `#${fiber.id}`)
384
368
  .join(', ')
385
369
  const runningOnFibers = fiberIds.length > 0 ? ` [fibers ${fiberIds}]` : ''
@@ -67,7 +67,7 @@ describe('trySyncOrPromiseOrEffect', () => {
67
67
  Effect.gen(function* () {
68
68
  const thrown = new Error('throwing then getter')
69
69
  const thenable = {
70
- // oxlint-disable-next-line eslint-plugin-unicorn(no-thenable) -- intentionally exercises Promise-like classification
70
+ // oxlint-disable-next-line unicorn/no-thenable -- intentionally exercises Promise-like classification
71
71
  get then(): PromiseLike<never>['then'] {
72
72
  throw thrown
73
73
  },
@@ -129,7 +129,7 @@ export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.
129
129
  export const dieDebugger = (msg: string, ...args: ReadonlyArray<unknown>): Effect.Effect<never> =>
130
130
  Effect.suspend(() => {
131
131
  if (isDevEnv() === true) {
132
- // oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint during development
132
+ // oxlint-disable-next-line no-debugger -- intentional breakpoint during development
133
133
  debugger
134
134
  void args // Keeps the variable in scope so it's inspectable when the debugger pauses
135
135
  }
@@ -150,7 +150,7 @@ export const orDieDebugger = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Eff
150
150
  // Keep the debugger hook so that `debugger` runs only when the wrapped effect actually fails, not while building the wrapper.
151
151
  Effect.suspend(() => {
152
152
  if (isDevEnv() === true) {
153
- // oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint for impossible states during development
153
+ // oxlint-disable-next-line no-debugger -- intentional breakpoint for impossible states during development
154
154
  debugger
155
155
  }
156
156
  return Effect.die(error)
@@ -342,7 +342,7 @@ export const withPerformanceMeasure =
342
342
 
343
343
  const getSpanTrace = () => {
344
344
  const fiber = Fiber.getCurrent()
345
- if (fiber === undefined || fiber.currentSpan === undefined) {
345
+ if (fiber === undefined || fiber.cache.span === undefined) {
346
346
  return 'No current fiber'
347
347
  }
348
348
 
@@ -1,10 +1,10 @@
1
- export * from 'effect/unstable/rpc/RpcClient'
1
+ export * from 'effect/rpc/RpcClient'
2
2
 
3
3
  import { Cause, Deferred, Effect, Function, Latch, Layer, References, Result, Schedule, type Scope } from 'effect'
4
- import { RpcClient, RpcClientError, RpcSerialization } from 'effect/unstable/rpc'
5
- import { Protocol } from 'effect/unstable/rpc/RpcClient'
6
- import { constPing, type FromServerEncoded } from 'effect/unstable/rpc/RpcMessage'
7
- import { Socket } from 'effect/unstable/socket'
4
+ import { RpcClient, RpcClientError, RpcSerialization } from 'effect/rpc'
5
+ import { Protocol } from 'effect/rpc/RpcClient'
6
+ import { constPing, type FromServerEncoded } from 'effect/rpc/RpcMessage'
7
+ import { Socket } from 'effect/socket'
8
8
 
9
9
  import * as SubscriptionRef from './SubscriptionRef.ts'
10
10
 
@@ -35,81 +35,94 @@ export const makeProtocolSocketWithIsConnected = (options: {
35
35
  const serialization = yield* RpcSerialization.RpcSerialization
36
36
  const requestClientMap = new Map<string | number, number>()
37
37
 
38
- const write = yield* socket.writer
38
+ const writer = yield* socket.writer
39
39
  let parser = serialization.makeUnsafe()
40
40
 
41
- const pinger = yield* makePinger(write(parser.encode(constPing)!), options?.pingSchedule)
41
+ const pinger = yield* makePinger(
42
+ Effect.suspend(() => {
43
+ const encoded = parser.encode(constPing)
44
+ return encoded === undefined ? Effect.void : writer.write(encoded)
45
+ }),
46
+ options?.pingSchedule,
47
+ )
42
48
  let currentError: RpcClientError.RpcClientError | undefined
43
49
 
44
50
  const markConnected = SubscriptionRef.set(options.isConnected, true)
45
51
  const broadcast = (response: FromServerEncoded) =>
46
52
  Effect.forEach(clientIds, (clientId) => writeResponse(clientId, response))
47
53
 
54
+ const processData = (message: Uint8Array | string): Effect.Effect<void> => {
55
+ try {
56
+ const responses = parser.decode(message) as Array<FromServerEncoded>
57
+ if (responses.length === 0) return Effect.void
58
+ let i = 0
59
+ return Effect.whileLoop({
60
+ while: () => i < responses.length,
61
+ body: () => {
62
+ const response = responses[i++]!
63
+ pinger.reset()
64
+ if (response._tag === 'Pong') {
65
+ pinger.onPong()
66
+ return markConnected
67
+ }
68
+ if ('requestId' in response) {
69
+ const clientId = requestClientMap.get(response.requestId)
70
+ if (clientId !== undefined) {
71
+ if (response._tag === 'Exit') {
72
+ requestClientMap.delete(response.requestId)
73
+ }
74
+ return markConnected.pipe(Effect.andThen(writeResponse(clientId, response)))
75
+ }
76
+ }
77
+ return markConnected.pipe(Effect.andThen(broadcast(response)))
78
+ },
79
+ step: Function.constVoid,
80
+ })
81
+ } catch (defect) {
82
+ return broadcast({
83
+ _tag: 'ClientProtocolError',
84
+ error: new RpcClientError.RpcClientError({
85
+ reason: new RpcClientError.RpcClientDefect({
86
+ message: 'Error decoding message',
87
+ cause: defect,
88
+ }),
89
+ }),
90
+ })
91
+ }
92
+ }
93
+
48
94
  yield* Effect.suspend(() => {
49
95
  // We rely on the heartbeat watchdog while streaming arbitrarily long payloads.
50
96
  // Reset the timer as soon as _any_ frame arrives so that large batches which
51
97
  // don't contain explicit `Pong` messages don't trigger the open-timeout defect.
52
98
  // (The actual pong handler still calls `onPong()` to resolve manual pings.)
53
- // CHANGED: don't reset parser on every message
54
- // parser = serialization.makeUnsafe()
55
- currentError = undefined
99
+ parser = serialization.makeUnsafe()
56
100
  pinger.reset()
57
- return socket
58
- .runRaw((message) => {
59
- try {
60
- const responses = parser.decode(message) as Array<FromServerEncoded>
61
- if (responses.length === 0) return
62
- let i = 0
63
- return Effect.whileLoop({
64
- while: () => i < responses.length,
65
- body: () => {
66
- const response = responses[i++]!
67
- // Keep extending the watchdog for each data frame to avoid
68
- // disconnecting mid-stream when the server is busy sending batches.
69
- pinger.reset()
70
- if (response._tag === 'Pong') {
71
- pinger.onPong()
72
- return markConnected
73
- }
74
- if ('requestId' in response) {
75
- const clientId = requestClientMap.get(response.requestId)
76
- if (clientId !== undefined) {
77
- if (response._tag === 'Exit') {
78
- requestClientMap.delete(response.requestId)
79
- }
80
- return markConnected.pipe(Effect.andThen(writeResponse(clientId, response)))
81
- }
82
- }
83
- return markConnected.pipe(Effect.andThen(broadcast(response)))
84
- },
85
- step: Function.constVoid,
86
- })
87
- } catch (defect) {
88
- return broadcast({
89
- _tag: 'ClientProtocolError',
90
- error: new RpcClientError.RpcClientError({
91
- reason: new RpcClientError.RpcClientDefect({
92
- message: 'Error decoding message',
93
- cause: defect,
94
- }),
95
- }),
96
- })
101
+ return Effect.gen(function* () {
102
+ const { pull } = yield* socket.reader
103
+ currentError = undefined
104
+ while (true) {
105
+ const frames = yield* pull
106
+ for (const frame of frames) {
107
+ // Keep extending the watchdog for each data frame to avoid disconnecting mid-stream.
108
+ yield* processData(frame)
97
109
  }
98
- })
99
- .pipe(
100
- Effect.raceFirst(
101
- Effect.flatMap(pinger.timeout, () =>
102
- Effect.fail(
103
- new Socket.SocketError({
104
- reason: new Socket.SocketOpenError({
105
- kind: 'Timeout',
106
- cause: new Error('ping timeout'),
107
- }),
110
+ }
111
+ }).pipe(
112
+ Effect.scoped,
113
+ Effect.raceFirst(
114
+ Effect.flatMap(pinger.timeout, () =>
115
+ Effect.fail(
116
+ new Socket.SocketError({
117
+ reason: new Socket.SocketOpenError({
118
+ kind: 'Timeout',
119
+ cause: new Error('ping timeout'),
108
120
  }),
109
- ),
121
+ }),
110
122
  ),
111
123
  ),
112
- )
124
+ ),
125
+ )
113
126
  }).pipe(
114
127
  Effect.flatMap(() =>
115
128
  Effect.fail(
@@ -173,10 +186,11 @@ export const makeProtocolSocketWithIsConnected = (options: {
173
186
  const encoded = parser.encode(request)
174
187
  if (encoded === undefined) return Effect.void
175
188
 
176
- return Effect.orDie(write(encoded))
189
+ return Effect.orDie(writer.write(encoded))
177
190
  },
178
191
  supportsAck: true,
179
192
  supportsTransferables: false,
193
+ codecFor: serialization.codecFor,
180
194
  pinger,
181
195
  }
182
196
  }),
@@ -12,7 +12,7 @@ import {
12
12
  SchemaTransformation,
13
13
  Struct,
14
14
  } from 'effect'
15
- import { Transferable } from 'effect/unstable/workers'
15
+ import { Transferable } from 'effect/workers'
16
16
 
17
17
  import { shouldNeverHappen } from '../../misc.ts'
18
18
 
@@ -89,7 +89,7 @@ export const headOrElse: {
89
89
  array.pipe(
90
90
  Schema.decodeTo(
91
91
  Schema.toType(array.value),
92
- SchemaTransformation.transformOrFail({
92
+ SchemaTransformation.transformEffect({
93
93
  decode: (array) =>
94
94
  Array.isReadonlyArrayNonEmpty(array) === true
95
95
  ? Effect.succeed(Array.headNonEmpty(array))
@@ -378,8 +378,7 @@ export const toOpenChannel = <MsgListen, MsgSend>(
378
378
  const deferred = yield* Deferred.make<void>()
379
379
  pendingPingDeferredRef.current = { deferred, requestId }
380
380
  yield* Deferred.await(deferred).pipe(
381
- Effect.timeout(timeout),
382
- Effect.catchTag('TimeoutError', () => channel.shutdown),
381
+ Effect.timeoutOrElse({ duration: timeout, orElse: () => channel.shutdown }),
383
382
  )
384
383
  }
385
384
  }).pipe(Effect.withSpan(`WebChannel:heartbeat`), Effect.forkScoped)
@@ -1,6 +1,6 @@
1
1
  import * as Vitest from '@effect/vitest'
2
2
  import { Effect, Exit } from 'effect'
3
- import { FetchHttpClient } from 'effect/unstable/http'
3
+ import { FetchHttpClient } from 'effect/http'
4
4
 
5
5
  import { makeWebSocket } from './WebSocket.ts'
6
6
 
@@ -1,6 +1,6 @@
1
1
  import type { Schedule, Scope } from 'effect'
2
2
  import { Effect, Exit, identity, Schema } from 'effect'
3
- import { HttpClient } from 'effect/unstable/http'
3
+ import { HttpClient } from 'effect/http'
4
4
 
5
5
  export class WebSocketError extends Schema.TaggedError<WebSocketError>('~@livestore/utils/WebSocketError')(
6
6
  'WebSocketError',