@livestore/utils 0.4.0-dev.1 → 0.4.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo.json +1 -1
- package/dist/NoopTracer.d.ts.map +1 -1
- package/dist/NoopTracer.js +1 -0
- package/dist/NoopTracer.js.map +1 -1
- package/dist/effect/Effect.d.ts +9 -3
- package/dist/effect/Effect.d.ts.map +1 -1
- package/dist/effect/Effect.js +4 -2
- package/dist/effect/Effect.js.map +1 -1
- package/dist/effect/Error.d.ts +1 -1
- package/dist/effect/Error.js.map +1 -1
- package/dist/effect/Logger.d.ts +4 -1
- package/dist/effect/Logger.d.ts.map +1 -1
- package/dist/effect/Logger.js +12 -3
- package/dist/effect/Logger.js.map +1 -1
- package/dist/effect/OtelTracer.d.ts +5 -0
- package/dist/effect/OtelTracer.d.ts.map +1 -0
- package/dist/effect/OtelTracer.js +8 -0
- package/dist/effect/OtelTracer.js.map +1 -0
- package/dist/effect/RpcClient.d.ts +32 -0
- package/dist/effect/RpcClient.d.ts.map +1 -0
- package/dist/effect/RpcClient.js +149 -0
- package/dist/effect/RpcClient.js.map +1 -0
- package/dist/effect/Schema/index.d.ts +2 -2
- package/dist/effect/Schema/index.d.ts.map +1 -1
- package/dist/effect/Schema/index.js +12 -2
- package/dist/effect/Schema/index.js.map +1 -1
- package/dist/effect/Stream.d.ts +73 -2
- package/dist/effect/Stream.d.ts.map +1 -1
- package/dist/effect/Stream.js +68 -1
- package/dist/effect/Stream.js.map +1 -1
- package/dist/effect/Stream.test.d.ts +2 -0
- package/dist/effect/Stream.test.d.ts.map +1 -0
- package/dist/effect/Stream.test.js +84 -0
- package/dist/effect/Stream.test.js.map +1 -0
- package/dist/effect/SubscriptionRef.d.ts +2 -2
- package/dist/effect/SubscriptionRef.d.ts.map +1 -1
- package/dist/effect/SubscriptionRef.js +6 -1
- package/dist/effect/SubscriptionRef.js.map +1 -1
- package/dist/effect/WebChannel/common.d.ts +1 -1
- package/dist/effect/WebChannel/common.d.ts.map +1 -1
- package/dist/effect/WebSocket.js +1 -1
- package/dist/effect/WebSocket.js.map +1 -1
- package/dist/effect/index.d.ts +17 -11
- package/dist/effect/index.d.ts.map +1 -1
- package/dist/effect/index.js +20 -15
- package/dist/effect/index.js.map +1 -1
- package/dist/global.d.ts +1 -0
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js.map +1 -1
- package/dist/misc.js +1 -1
- package/dist/misc.js.map +1 -1
- package/dist/mod.d.ts +2 -0
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +4 -0
- package/dist/mod.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js +66 -10
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +177 -3
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +10 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js +7 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +13 -3
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts +16 -0
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js +98 -2
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +1 -1
- package/dist/node/mod.d.ts +7 -1
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +10 -2
- package/dist/node/mod.js.map +1 -1
- package/package.json +42 -41
- package/src/NoopTracer.ts +1 -0
- package/src/effect/Effect.ts +31 -4
- package/src/effect/Error.ts +1 -1
- package/src/effect/Logger.ts +14 -4
- package/src/effect/OtelTracer.ts +11 -0
- package/src/effect/RpcClient.ts +212 -0
- package/src/effect/Schema/index.ts +17 -3
- package/src/effect/Stream.test.ts +127 -0
- package/src/effect/Stream.ts +111 -2
- package/src/effect/SubscriptionRef.ts +14 -2
- package/src/effect/WebChannel/common.ts +1 -1
- package/src/effect/WebSocket.ts +1 -1
- package/src/effect/index.ts +40 -14
- package/src/global.ts +1 -0
- package/src/misc.ts +1 -1
- package/src/mod.ts +9 -0
- package/src/node/ChildProcessRunner/ChildProcessRunner.ts +71 -10
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +258 -3
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +14 -1
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +16 -3
- package/src/node/ChildProcessRunner/ChildProcessWorker.ts +111 -3
- package/src/node/mod.ts +12 -5
- package/dist/effect/Schema/msgpack.d.ts +0 -3
- package/dist/effect/Schema/msgpack.d.ts.map +0 -1
- package/dist/effect/Schema/msgpack.js +0 -7
- package/dist/effect/Schema/msgpack.js.map +0 -1
- package/src/effect/Schema/msgpack.ts +0 -8
package/dist/node/mod.d.ts
CHANGED
|
@@ -5,6 +5,12 @@ export * as SocketServer from '@effect/platform/SocketServer';
|
|
|
5
5
|
export * as PlatformNode from '@effect/platform-node';
|
|
6
6
|
export * as ChildProcessRunner from './ChildProcessRunner/ChildProcessRunner.ts';
|
|
7
7
|
export * as ChildProcessWorker from './ChildProcessRunner/ChildProcessWorker.ts';
|
|
8
|
-
export declare const getFreePort: Effect.Effect<number, UnknownError
|
|
8
|
+
export declare const getFreePort: Effect.Effect<number, UnknownError>;
|
|
9
9
|
export declare const OtelLiveDummy: Layer.Layer<OtelTracer.OtelTracer>;
|
|
10
|
+
/**
|
|
11
|
+
* Layer that enables recursive file watching by combining the Node filesystem implementation with
|
|
12
|
+
* the Parcel-based watch backend. Mirrored from Effect’s platform-node Parcel watcher layer:
|
|
13
|
+
* https://github.com/Effect-TS/effect/blob/main/packages/platform-node/src/NodeFileSystem/ParcelWatcher.ts
|
|
14
|
+
*/
|
|
15
|
+
export declare const NodeRecursiveWatchLayer: Layer.Layer<import("@effect/platform/FileSystem").FileSystem | import("@effect/platform/FileSystem").WatchBackend, never, never>;
|
|
10
16
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/node/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/node/mod.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/node/mod.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAG7D,OAAO,KAAK,GAAG,MAAM,aAAa,CAAA;AAClC,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAA;AAC7D,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AAErD,OAAO,KAAK,kBAAkB,MAAM,4CAA4C,CAAA;AAChF,OAAO,KAAK,kBAAkB,MAAM,4CAA4C,CAAA;AAOhF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAuB1D,CAAA;AAEF,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAQ3D,CAAA;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,kIAAwE,CAAA"}
|
package/dist/node/mod.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as http from 'node:http';
|
|
2
|
+
import * as PlatformNode from '@effect/platform-node';
|
|
3
|
+
import { layer as ParcelWatcherLayer } from '@effect/platform-node/NodeFileSystem/ParcelWatcher';
|
|
2
4
|
import { Effect, Layer } from 'effect';
|
|
3
5
|
import { OtelTracer, UnknownError } from "../effect/index.js";
|
|
4
6
|
import { makeNoopTracer } from "../NoopTracer.js";
|
|
@@ -27,8 +29,8 @@ export const getFreePort = Effect.async((cb, signal) => {
|
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
// Error handling in case the server encounters an error
|
|
30
|
-
server.on('error', (
|
|
31
|
-
server.close(() => cb(Effect.fail(new UnknownError({ cause:
|
|
32
|
+
server.on('error', (cause) => {
|
|
33
|
+
server.close(() => cb(Effect.fail(new UnknownError({ cause, payload: 'Failed to get a free port' }))));
|
|
32
34
|
});
|
|
33
35
|
});
|
|
34
36
|
export const OtelLiveDummy = Layer.suspend(() => {
|
|
@@ -36,4 +38,10 @@ export const OtelLiveDummy = Layer.suspend(() => {
|
|
|
36
38
|
const TracingLive = Layer.unwrapEffect(Effect.map(OtelTracer.make, Layer.setTracer)).pipe(Layer.provideMerge(OtelTracerLive));
|
|
37
39
|
return TracingLive;
|
|
38
40
|
});
|
|
41
|
+
/**
|
|
42
|
+
* Layer that enables recursive file watching by combining the Node filesystem implementation with
|
|
43
|
+
* the Parcel-based watch backend. Mirrored from Effect’s platform-node Parcel watcher layer:
|
|
44
|
+
* https://github.com/Effect-TS/effect/blob/main/packages/platform-node/src/NodeFileSystem/ParcelWatcher.ts
|
|
45
|
+
*/
|
|
46
|
+
export const NodeRecursiveWatchLayer = Layer.mergeAll(PlatformNode.NodeFileSystem.layer, ParcelWatcherLayer);
|
|
39
47
|
//# sourceMappingURL=mod.js.map
|
package/dist/node/mod.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.js","sourceRoot":"","sources":["../../src/node/mod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"mod.js","sourceRoot":"","sources":["../../src/node/mod.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,KAAK,IAAI,kBAAkB,EAAE,MAAM,oDAAoD,CAAA;AAChG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,KAAK,GAAG,MAAM,aAAa,CAAA;AAClC,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAA;AAC7D,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AAErD,OAAO,KAAK,kBAAkB,MAAM,4CAA4C,CAAA;AAChF,OAAO,KAAK,kBAAkB,MAAM,4CAA4C,CAAA;AAEhF,yCAAyC;AACzC,6EAA6E;AAE7E,6EAA6E;AAE7E,MAAM,CAAC,MAAM,WAAW,GAAwC,MAAM,CAAC,KAAK,CAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE;IAChH,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,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC3C,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,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CACvF,KAAK,CAAC,YAAY,CAAC,cAAc,CAAC,CACnC,CAAA;IAED,OAAO,WAAW,CAAA;AACpB,CAAC,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/utils",
|
|
3
|
-
"version": "0.4.0-dev.
|
|
3
|
+
"version": "0.4.0-dev.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
6
|
-
"./src/global.ts"
|
|
6
|
+
"./src/global.ts",
|
|
7
|
+
"./dist/global.js"
|
|
7
8
|
],
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
@@ -34,33 +35,35 @@
|
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
38
|
+
"@effect/platform-node": "0.98.0",
|
|
37
39
|
"@standard-schema/spec": "1.0.0",
|
|
38
|
-
"msgpackr": "1.11.5",
|
|
39
40
|
"nanoid": "5.1.5",
|
|
40
|
-
"pretty-bytes": "7.0.
|
|
41
|
+
"pretty-bytes": "7.0.1"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@effect/
|
|
44
|
-
"@effect/
|
|
45
|
-
"@effect/
|
|
46
|
-
"@effect/
|
|
47
|
-
"@effect/
|
|
48
|
-
"@effect/platform
|
|
49
|
-
"@effect/platform-
|
|
50
|
-
"@effect/platform-
|
|
51
|
-
"@effect/
|
|
52
|
-
"@effect/printer
|
|
53
|
-
"@effect/
|
|
54
|
-
"@effect/
|
|
55
|
-
"@effect/
|
|
56
|
-
"@effect/
|
|
57
|
-
"@
|
|
44
|
+
"@effect/ai": "^0.29.0",
|
|
45
|
+
"@effect/cli": "^0.71.0",
|
|
46
|
+
"@effect/cluster": "^0.50.0",
|
|
47
|
+
"@effect/experimental": "^0.56.0",
|
|
48
|
+
"@effect/opentelemetry": "0.58.0",
|
|
49
|
+
"@effect/platform": "^0.92.0",
|
|
50
|
+
"@effect/platform-browser": "^0.72.0",
|
|
51
|
+
"@effect/platform-bun": "^0.81.0",
|
|
52
|
+
"@effect/platform-node": "^0.98.0",
|
|
53
|
+
"@effect/printer": "^0.46.0",
|
|
54
|
+
"@effect/printer-ansi": "^0.46.0",
|
|
55
|
+
"@effect/rpc": "^0.71.0",
|
|
56
|
+
"@effect/sql": "^0.46.0",
|
|
57
|
+
"@effect/typeclass": "^0.37.0",
|
|
58
|
+
"@effect/vitest": "^0.26.0",
|
|
59
|
+
"@effect/workflow": "^0.11.0",
|
|
60
|
+
"@opentelemetry/api": "1.9.0",
|
|
58
61
|
"@opentelemetry/resources": "^2.0.1",
|
|
59
|
-
"@types/bun": "^1.2.
|
|
62
|
+
"@types/bun": "^1.2.21",
|
|
60
63
|
"@types/jsdom": "^21.1.7",
|
|
61
|
-
"@types/node": "24.2
|
|
62
|
-
"@types/web": "^0.0.
|
|
63
|
-
"effect": "
|
|
64
|
+
"@types/node": "24.5.2",
|
|
65
|
+
"@types/web": "^0.0.264",
|
|
66
|
+
"effect": "3.18.0",
|
|
64
67
|
"jsdom": "^26.1.0",
|
|
65
68
|
"vitest": "3.2.4"
|
|
66
69
|
},
|
|
@@ -71,28 +74,26 @@
|
|
|
71
74
|
],
|
|
72
75
|
"license": "Apache-2.0",
|
|
73
76
|
"peerDependencies": {
|
|
74
|
-
"@effect/
|
|
75
|
-
"@effect/
|
|
76
|
-
"@effect/
|
|
77
|
-
"@effect/
|
|
78
|
-
"@effect/
|
|
79
|
-
"@effect/platform
|
|
80
|
-
"@effect/platform-
|
|
81
|
-
"@effect/platform-
|
|
82
|
-
"@effect/
|
|
83
|
-
"@effect/printer
|
|
84
|
-
"@effect/
|
|
85
|
-
"@effect/
|
|
86
|
-
"@effect/
|
|
77
|
+
"@effect/ai": "^0.29.0",
|
|
78
|
+
"@effect/cli": "^0.71.0",
|
|
79
|
+
"@effect/cluster": "^0.50.0",
|
|
80
|
+
"@effect/experimental": "^0.56.0",
|
|
81
|
+
"@effect/opentelemetry": "^0.58.0",
|
|
82
|
+
"@effect/platform": "^0.92.0",
|
|
83
|
+
"@effect/platform-browser": "^0.72.0",
|
|
84
|
+
"@effect/platform-bun": "^0.81.0",
|
|
85
|
+
"@effect/platform-node": "^0.98.0",
|
|
86
|
+
"@effect/printer": "^0.46.0",
|
|
87
|
+
"@effect/printer-ansi": "^0.46.0",
|
|
88
|
+
"@effect/rpc": "^0.71.0",
|
|
89
|
+
"@effect/sql": "^0.46.0",
|
|
90
|
+
"@effect/typeclass": "^0.37.0",
|
|
87
91
|
"@opentelemetry/api": "^1.9.0",
|
|
88
92
|
"@opentelemetry/resources": "^2.0.1",
|
|
89
|
-
"effect": "^3.
|
|
93
|
+
"effect": "^3.18.0"
|
|
90
94
|
},
|
|
91
95
|
"publishConfig": {
|
|
92
|
-
"access": "public"
|
|
93
|
-
"sideEffects": [
|
|
94
|
-
"./dist/global.js"
|
|
95
|
-
]
|
|
96
|
+
"access": "public"
|
|
96
97
|
},
|
|
97
98
|
"react-native": "./dist/index.js",
|
|
98
99
|
"scripts": {
|
package/src/NoopTracer.ts
CHANGED
package/src/effect/Effect.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import * as OtelTracer from '@effect/opentelemetry/Tracer'
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
Cause,
|
|
4
|
+
type Context,
|
|
5
|
+
Deferred,
|
|
6
|
+
Duration,
|
|
7
|
+
Effect,
|
|
8
|
+
Fiber,
|
|
9
|
+
FiberRef,
|
|
10
|
+
HashSet,
|
|
11
|
+
Logger,
|
|
12
|
+
pipe,
|
|
13
|
+
Scope,
|
|
14
|
+
type Stream,
|
|
15
|
+
} from 'effect'
|
|
4
16
|
import type { UnknownException } from 'effect/Cause'
|
|
5
17
|
import { log } from 'effect/Console'
|
|
6
|
-
import type
|
|
18
|
+
import { dual, type LazyArg } from 'effect/Function'
|
|
19
|
+
import type { Predicate, Refinement } from 'effect/Predicate'
|
|
7
20
|
|
|
8
21
|
import { isPromise } from '../mod.ts'
|
|
9
22
|
import { UnknownError } from './Error.ts'
|
|
@@ -94,6 +107,20 @@ export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.
|
|
|
94
107
|
}),
|
|
95
108
|
)
|
|
96
109
|
|
|
110
|
+
export const ignoreIf: {
|
|
111
|
+
<E, EB extends E>(
|
|
112
|
+
refinement: Refinement<NoInfer<E>, EB>,
|
|
113
|
+
): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, Exclude<E, EB>, R>
|
|
114
|
+
<E>(predicate: Predicate<NoInfer<E>>): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, E, R>
|
|
115
|
+
<A, E, R, EB extends E>(
|
|
116
|
+
self: Effect.Effect<A, E, R>,
|
|
117
|
+
refinement: Refinement<E, EB>,
|
|
118
|
+
): Effect.Effect<void, Exclude<E, EB>, R>
|
|
119
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, predicate: Predicate<E>): Effect.Effect<void, E, R>
|
|
120
|
+
} = dual(2, <A, E, R>(self: Effect.Effect<A, E, R>, predicate: Predicate<E>) =>
|
|
121
|
+
self.pipe(Effect.catchIf(predicate, () => Effect.void)),
|
|
122
|
+
)
|
|
123
|
+
|
|
97
124
|
export const eventListener = <TEvent = unknown>(
|
|
98
125
|
target: Stream.EventListener<TEvent>,
|
|
99
126
|
type: string,
|
|
@@ -166,7 +193,7 @@ export const logDuration =
|
|
|
166
193
|
const start = Date.now()
|
|
167
194
|
const res = yield* eff
|
|
168
195
|
const end = Date.now()
|
|
169
|
-
yield* Effect.log(`${label}: ${end - start}
|
|
196
|
+
yield* Effect.log(`${label}: ${Duration.format(end - start)}`)
|
|
170
197
|
return res
|
|
171
198
|
})
|
|
172
199
|
|
package/src/effect/Error.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schema } from 'effect'
|
|
2
2
|
|
|
3
|
-
export class UnknownError extends Schema.TaggedError<
|
|
3
|
+
export class UnknownError extends Schema.TaggedError<UnknownError>()('UnknownError', {
|
|
4
4
|
cause: Schema.Any,
|
|
5
5
|
payload: Schema.optional(Schema.Any),
|
|
6
6
|
}) {}
|
package/src/effect/Logger.ts
CHANGED
|
@@ -8,20 +8,24 @@ const defaultDateFormat = (date: Date): string =>
|
|
|
8
8
|
.toString()
|
|
9
9
|
.padStart(2, '0')}.${date.getMilliseconds().toString().padStart(3, '0')}`
|
|
10
10
|
|
|
11
|
-
export const prettyWithThread = (threadName: string) =>
|
|
11
|
+
export const prettyWithThread = (threadName: string, options: { mode?: 'tty' | 'browser' } = {}) =>
|
|
12
12
|
Logger.replace(
|
|
13
13
|
Logger.defaultLogger,
|
|
14
14
|
Logger.prettyLogger({
|
|
15
15
|
formatDate: (date) => `${defaultDateFormat(date)} ${threadName}`,
|
|
16
|
+
mode: options.mode,
|
|
16
17
|
}),
|
|
17
|
-
// consoleLogger(threadName),
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
export const consoleLogger = (threadName: string) =>
|
|
21
21
|
Logger.make(({ message, annotations, date, logLevel, cause }) => {
|
|
22
|
+
const isCloudflareWorker = typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers'
|
|
22
23
|
const consoleFn =
|
|
23
24
|
logLevel === LogLevel.Debug
|
|
24
|
-
? console.debug
|
|
25
|
+
? // Cloudflare Workers doesn't support console.debug 🤷
|
|
26
|
+
isCloudflareWorker
|
|
27
|
+
? console.log
|
|
28
|
+
: console.debug
|
|
25
29
|
: logLevel === LogLevel.Info
|
|
26
30
|
? console.info
|
|
27
31
|
: logLevel === LogLevel.Warning
|
|
@@ -35,5 +39,11 @@ export const consoleLogger = (threadName: string) =>
|
|
|
35
39
|
messages.push(Cause.pretty(cause, { renderErrorCause: true }))
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
if (Object.keys(annotationsObj).length > 0) {
|
|
43
|
+
messages.push(annotationsObj)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
consoleFn(`[${defaultDateFormat(date)} ${threadName}]`, ...messages)
|
|
39
47
|
})
|
|
48
|
+
|
|
49
|
+
export const consoleWithThread = (threadName: string) => Logger.replace(Logger.defaultLogger, consoleLogger(threadName))
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { makeExternalSpan } from '@effect/opentelemetry/Tracer'
|
|
2
|
+
import type { Link as OtelSpanLink } from '@opentelemetry/api'
|
|
3
|
+
import type { SpanLink as EffectSpanLink } from 'effect/Tracer'
|
|
4
|
+
|
|
5
|
+
export * from '@effect/opentelemetry/Tracer'
|
|
6
|
+
|
|
7
|
+
export const makeSpanLink = (otelSpanLink: OtelSpanLink): EffectSpanLink => ({
|
|
8
|
+
_tag: 'SpanLink',
|
|
9
|
+
span: makeExternalSpan(otelSpanLink.context),
|
|
10
|
+
attributes: otelSpanLink.attributes ?? {},
|
|
11
|
+
})
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
export * from '@effect/rpc/RpcClient'
|
|
2
|
+
|
|
3
|
+
import { Socket } from '@effect/platform'
|
|
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 { Cause, Deferred, Effect, Layer, Option, Schedule, type Scope } from 'effect'
|
|
8
|
+
import { constVoid, identity } from 'effect/Function'
|
|
9
|
+
import * as SubscriptionRef from './SubscriptionRef.ts'
|
|
10
|
+
|
|
11
|
+
// This is based on `makeProtocolSocket` / `layerProtocolSocket` from `@effect/rpc` in order to:
|
|
12
|
+
// - Add a `isConnected` subscription ref to track the connection state
|
|
13
|
+
// - Add a ping schedule to the socket
|
|
14
|
+
// - Add a retry schedule to the socket
|
|
15
|
+
|
|
16
|
+
export const layerProtocolSocketWithIsConnected = (options: {
|
|
17
|
+
readonly url: string
|
|
18
|
+
readonly retryTransientErrors?: Schedule.Schedule<unknown> | undefined
|
|
19
|
+
readonly isConnected: SubscriptionRef.SubscriptionRef<boolean>
|
|
20
|
+
readonly pingSchedule?: Schedule.Schedule<unknown> | undefined
|
|
21
|
+
}): Layer.Layer<Protocol, never, RpcSerialization.RpcSerialization | Socket.Socket> =>
|
|
22
|
+
Layer.scoped(Protocol, makeProtocolSocketWithIsConnected(options))
|
|
23
|
+
|
|
24
|
+
export const makeProtocolSocketWithIsConnected = (options: {
|
|
25
|
+
readonly url: string
|
|
26
|
+
readonly retryTransientErrors?: Schedule.Schedule<unknown> | undefined
|
|
27
|
+
// CHANGED: add isConnected subscription ref
|
|
28
|
+
readonly isConnected: SubscriptionRef.SubscriptionRef<boolean>
|
|
29
|
+
// CHANGED: add ping schedule
|
|
30
|
+
readonly pingSchedule?: Schedule.Schedule<unknown> | undefined
|
|
31
|
+
}): Effect.Effect<Protocol['Type'], never, Scope.Scope | RpcSerialization.RpcSerialization | Socket.Socket> =>
|
|
32
|
+
Protocol.make(
|
|
33
|
+
Effect.fnUntraced(function* (writeResponse) {
|
|
34
|
+
const socket = yield* Socket.Socket
|
|
35
|
+
const serialization = yield* RpcSerialization.RpcSerialization
|
|
36
|
+
|
|
37
|
+
const write = yield* socket.writer
|
|
38
|
+
const parser = serialization.unsafeMake()
|
|
39
|
+
|
|
40
|
+
const pinger = yield* makePinger(write(parser.encode(constPing)!), options?.pingSchedule)
|
|
41
|
+
|
|
42
|
+
yield* Effect.suspend(() => {
|
|
43
|
+
// We rely on the heartbeat watchdog while streaming arbitrarily long payloads.
|
|
44
|
+
// Reset the timer as soon as _any_ frame arrives so that large batches which
|
|
45
|
+
// don't contain explicit `Pong` messages don't trigger the open-timeout defect.
|
|
46
|
+
// (The actual pong handler still calls `onPong()` to resolve manual pings.)
|
|
47
|
+
// CHANGED: don't reset parser on every message
|
|
48
|
+
// parser = serialization.unsafeMake()
|
|
49
|
+
pinger.reset()
|
|
50
|
+
return socket
|
|
51
|
+
.runRaw((message) => {
|
|
52
|
+
try {
|
|
53
|
+
const responses = parser.decode(message) as Array<FromServerEncoded>
|
|
54
|
+
if (responses.length === 0) return
|
|
55
|
+
let i = 0
|
|
56
|
+
return Effect.whileLoop({
|
|
57
|
+
while: () => i < responses.length,
|
|
58
|
+
body: () => {
|
|
59
|
+
const response = responses[i++]!
|
|
60
|
+
// Keep extending the watchdog for each data frame to avoid
|
|
61
|
+
// disconnecting mid-stream when the server is busy sending batches.
|
|
62
|
+
pinger.reset()
|
|
63
|
+
if (response._tag === 'Pong') {
|
|
64
|
+
pinger.onPong()
|
|
65
|
+
}
|
|
66
|
+
return writeResponse(response).pipe(
|
|
67
|
+
// CHANGED: set isConnected to true on pong
|
|
68
|
+
Effect.tap(
|
|
69
|
+
Effect.fn(function* () {
|
|
70
|
+
if (options?.isConnected !== undefined) {
|
|
71
|
+
yield* SubscriptionRef.set(options.isConnected, true)
|
|
72
|
+
}
|
|
73
|
+
}),
|
|
74
|
+
),
|
|
75
|
+
)
|
|
76
|
+
},
|
|
77
|
+
step: constVoid,
|
|
78
|
+
})
|
|
79
|
+
} catch (defect) {
|
|
80
|
+
return writeResponse({
|
|
81
|
+
_tag: 'ClientProtocolError',
|
|
82
|
+
error: new RpcClientError.RpcClientError({
|
|
83
|
+
reason: 'Protocol',
|
|
84
|
+
message: 'Error decoding message',
|
|
85
|
+
cause: Cause.fail(defect),
|
|
86
|
+
}),
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
.pipe(
|
|
91
|
+
Effect.raceFirst(
|
|
92
|
+
Effect.zipRight(
|
|
93
|
+
pinger.timeout,
|
|
94
|
+
Effect.fail(
|
|
95
|
+
new Socket.SocketGenericError({
|
|
96
|
+
reason: 'OpenTimeout',
|
|
97
|
+
cause: new Error('ping timeout'),
|
|
98
|
+
}),
|
|
99
|
+
),
|
|
100
|
+
),
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
}).pipe(
|
|
104
|
+
Effect.zipRight(
|
|
105
|
+
Effect.fail(
|
|
106
|
+
new Socket.SocketCloseError({
|
|
107
|
+
reason: 'Close',
|
|
108
|
+
code: 1000,
|
|
109
|
+
closeReason: 'Closing connection',
|
|
110
|
+
}),
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
Effect.tapErrorCause(
|
|
114
|
+
Effect.fn(function* (cause) {
|
|
115
|
+
// CHANGED: set isConnected to false on error
|
|
116
|
+
if (options?.isConnected !== undefined) {
|
|
117
|
+
yield* SubscriptionRef.set(options.isConnected, false)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const error = Cause.failureOption(cause)
|
|
121
|
+
if (
|
|
122
|
+
options?.retryTransientErrors &&
|
|
123
|
+
Option.isSome(error) &&
|
|
124
|
+
(error.value.reason === 'Open' || error.value.reason === 'OpenTimeout')
|
|
125
|
+
) {
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
// yield* Effect.logError('Error in socket', cause)
|
|
129
|
+
return yield* writeResponse({
|
|
130
|
+
_tag: 'ClientProtocolError',
|
|
131
|
+
error: new RpcClientError.RpcClientError({
|
|
132
|
+
reason: 'Protocol',
|
|
133
|
+
message: 'Error in socket',
|
|
134
|
+
cause: Cause.squash(cause),
|
|
135
|
+
}),
|
|
136
|
+
})
|
|
137
|
+
}),
|
|
138
|
+
),
|
|
139
|
+
// CHANGED: make configurable via schedule
|
|
140
|
+
options?.retryTransientErrors ? Effect.retry(options.retryTransientErrors) : identity,
|
|
141
|
+
Effect.annotateLogs({
|
|
142
|
+
module: 'RpcClient',
|
|
143
|
+
method: 'makeProtocolSocket',
|
|
144
|
+
}),
|
|
145
|
+
Effect.interruptible,
|
|
146
|
+
Effect.ignore, // Errors are already handled
|
|
147
|
+
Effect.provide(Layer.setUnhandledErrorLogLevel(Option.none())),
|
|
148
|
+
Effect.forkScoped,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
send: (request) => {
|
|
153
|
+
const encoded = parser.encode(request)
|
|
154
|
+
if (encoded === undefined) return Effect.void
|
|
155
|
+
|
|
156
|
+
return Effect.orDie(write(encoded))
|
|
157
|
+
},
|
|
158
|
+
supportsAck: true,
|
|
159
|
+
supportsTransferables: false,
|
|
160
|
+
pinger,
|
|
161
|
+
}
|
|
162
|
+
}),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
export const SocketPinger = Effect.map(RpcClient.Protocol, (protocol) => (protocol as any).pinger as SocketPinger)
|
|
166
|
+
|
|
167
|
+
export type SocketPinger = Effect.Effect.Success<ReturnType<typeof makePinger>>
|
|
168
|
+
|
|
169
|
+
const makePinger = Effect.fnUntraced(function* <A, E, R>(
|
|
170
|
+
writePing: Effect.Effect<A, E, R>,
|
|
171
|
+
pingSchedule: Schedule.Schedule<unknown> = Schedule.spaced(10000).pipe(Schedule.addDelay(() => 5000)),
|
|
172
|
+
) {
|
|
173
|
+
// CHANGED: add manual ping deferreds
|
|
174
|
+
const manualPingDeferreds = new Set<Deferred.Deferred<void, never>>()
|
|
175
|
+
|
|
176
|
+
let recievedPong = true
|
|
177
|
+
const latch = Effect.unsafeMakeLatch()
|
|
178
|
+
const reset = () => {
|
|
179
|
+
recievedPong = true
|
|
180
|
+
latch.unsafeClose()
|
|
181
|
+
}
|
|
182
|
+
const onPong = () => {
|
|
183
|
+
recievedPong = true
|
|
184
|
+
// CHANGED: mark all manual ping deferreds as done
|
|
185
|
+
for (const deferred of manualPingDeferreds) {
|
|
186
|
+
Deferred.unsafeDone(deferred, Effect.void)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
yield* Effect.suspend(() => {
|
|
190
|
+
// Starting new ping
|
|
191
|
+
if (!recievedPong) return latch.open
|
|
192
|
+
recievedPong = false
|
|
193
|
+
return writePing
|
|
194
|
+
}).pipe(
|
|
195
|
+
// CHANGED: make configurable via schedule
|
|
196
|
+
Effect.schedule(pingSchedule),
|
|
197
|
+
Effect.ignore,
|
|
198
|
+
Effect.forever,
|
|
199
|
+
Effect.interruptible,
|
|
200
|
+
Effect.forkScoped,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
// CHANGED: add manual ping
|
|
204
|
+
const ping = Effect.gen(function* () {
|
|
205
|
+
const deferred = yield* Deferred.make<void, never>()
|
|
206
|
+
manualPingDeferreds.add(deferred)
|
|
207
|
+
yield* deferred
|
|
208
|
+
manualPingDeferreds.delete(deferred)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
return { timeout: latch.await, reset, onPong, ping } as const
|
|
212
|
+
})
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Transferable } from '@effect/platform'
|
|
2
|
-
import type { SchemaAST } from 'effect'
|
|
3
2
|
import { Effect, Hash, ParseResult, Schema } from 'effect'
|
|
4
3
|
import type { ParseError } from 'effect/ParseResult'
|
|
5
4
|
import type { ParseOptions } from 'effect/SchemaAST'
|
|
5
|
+
import * as SchemaAST from 'effect/SchemaAST'
|
|
6
6
|
|
|
7
7
|
import { shouldNeverHappen } from '../../mod.ts'
|
|
8
8
|
|
|
9
9
|
export * from 'effect/Schema'
|
|
10
10
|
export * from './debug-diff.ts'
|
|
11
|
-
export * from './msgpack.ts'
|
|
12
11
|
|
|
13
12
|
// NOTE this is a temporary workaround until Effect schema has a better way to hash schemas
|
|
14
13
|
// https://github.com/Effect-TS/effect/issues/2719
|
|
@@ -24,6 +23,21 @@ export const hash = (schema: Schema.Schema<any>) => {
|
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
25
|
|
|
26
|
+
const resolveStructAst = (ast: SchemaAST.AST): SchemaAST.AST => {
|
|
27
|
+
if (SchemaAST.isTransformation(ast)) {
|
|
28
|
+
return resolveStructAst(ast.from)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return ast
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const getResolvedPropertySignatures = (
|
|
35
|
+
schema: Schema.Schema.AnyNoContext,
|
|
36
|
+
): ReadonlyArray<SchemaAST.PropertySignature> => {
|
|
37
|
+
const resolvedAst = resolveStructAst(schema.ast)
|
|
38
|
+
return SchemaAST.getPropertySignatures(resolvedAst)
|
|
39
|
+
}
|
|
40
|
+
|
|
27
41
|
export const encodeWithTransferables =
|
|
28
42
|
<A, I, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions | undefined) =>
|
|
29
43
|
(a: A, overrideOptions?: ParseOptions | undefined): Effect.Effect<[I, Transferable[]], ParseError, R> =>
|
|
@@ -82,4 +96,4 @@ export const JsonValue: Schema.Schema<JsonValue> = Schema.Union(
|
|
|
82
96
|
Schema.Null,
|
|
83
97
|
Schema.Array(Schema.suspend(() => JsonValue)),
|
|
84
98
|
Schema.Record({ key: Schema.String, value: Schema.suspend(() => JsonValue) }),
|
|
85
|
-
).annotations({
|
|
99
|
+
).annotations({ identifier: 'JsonValue' })
|