@livestore/utils 0.3.0-dev.4 → 0.3.0-dev.41
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/Deferred.d.ts.map +1 -1
- package/dist/base64.d.ts.map +1 -1
- package/dist/bun/mod.d.ts +5 -0
- package/dist/bun/mod.d.ts.map +1 -0
- package/dist/bun/mod.js +9 -0
- package/dist/bun/mod.js.map +1 -0
- package/dist/cuid/cuid.browser.d.ts.map +1 -1
- package/dist/cuid/cuid.node.d.ts.map +1 -1
- package/dist/effect/BucketQueue.d.ts +15 -2
- package/dist/effect/BucketQueue.d.ts.map +1 -1
- package/dist/effect/BucketQueue.js +24 -6
- package/dist/effect/BucketQueue.js.map +1 -1
- package/dist/effect/Effect.d.ts +4 -2
- package/dist/effect/Effect.d.ts.map +1 -1
- package/dist/effect/Effect.js +21 -18
- package/dist/effect/Effect.js.map +1 -1
- package/dist/effect/Logger.d.ts +2 -0
- package/dist/effect/Logger.d.ts.map +1 -1
- package/dist/effect/Logger.js +16 -1
- package/dist/effect/Logger.js.map +1 -1
- package/dist/effect/Scheduler.d.ts.map +1 -1
- package/dist/effect/Schema/debug-diff.d.ts.map +1 -1
- package/dist/effect/Schema/index.d.ts +3 -0
- package/dist/effect/Schema/index.d.ts.map +1 -1
- package/dist/effect/Schema/index.js +19 -0
- package/dist/effect/Schema/index.js.map +1 -1
- package/dist/effect/Schema/msgpack.d.ts +1 -1
- package/dist/effect/Schema/msgpack.d.ts.map +1 -1
- package/dist/effect/ServiceContext.d.ts.map +1 -1
- package/dist/effect/Stream.d.ts.map +1 -1
- package/dist/effect/Subscribable.d.ts +76 -0
- package/dist/effect/Subscribable.d.ts.map +1 -0
- package/dist/effect/Subscribable.js +80 -0
- package/dist/effect/Subscribable.js.map +1 -0
- package/dist/effect/TaskTracing.d.ts.map +1 -1
- package/dist/effect/{WebChannel.d.ts → WebChannel/WebChannel.d.ts} +29 -16
- package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -0
- package/dist/effect/WebChannel/WebChannel.js +264 -0
- package/dist/effect/WebChannel/WebChannel.js.map +1 -0
- package/dist/effect/WebChannel/WebChannel.test.d.ts +2 -0
- package/dist/effect/WebChannel/WebChannel.test.d.ts.map +1 -0
- package/dist/effect/WebChannel/WebChannel.test.js +62 -0
- package/dist/effect/WebChannel/WebChannel.test.js.map +1 -0
- package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts +5 -6
- package/dist/effect/WebChannel/broadcastChannelWithAck.d.ts.map +1 -1
- package/dist/effect/WebChannel/broadcastChannelWithAck.js +12 -9
- package/dist/effect/WebChannel/broadcastChannelWithAck.js.map +1 -1
- package/dist/effect/WebChannel/common.d.ts +16 -1
- package/dist/effect/WebChannel/common.d.ts.map +1 -1
- package/dist/effect/WebChannel/common.js +19 -1
- package/dist/effect/WebChannel/common.js.map +1 -1
- package/dist/effect/WebChannel/mod.d.ts +4 -0
- package/dist/effect/WebChannel/mod.d.ts.map +1 -0
- package/dist/effect/WebChannel/mod.js +4 -0
- package/dist/effect/WebChannel/mod.js.map +1 -0
- package/dist/effect/WebLock.d.ts.map +1 -1
- package/dist/effect/WebSocket.d.ts +3 -2
- package/dist/effect/WebSocket.d.ts.map +1 -1
- package/dist/effect/WebSocket.js +45 -19
- package/dist/effect/WebSocket.js.map +1 -1
- package/dist/effect/WebSocket.test.d.ts +2 -0
- package/dist/effect/WebSocket.test.d.ts.map +1 -0
- package/dist/effect/WebSocket.test.js +11 -0
- package/dist/effect/WebSocket.test.js.map +1 -0
- package/dist/effect/index.d.ts +6 -3
- package/dist/effect/index.d.ts.map +1 -1
- package/dist/effect/index.js +9 -5
- package/dist/effect/index.js.map +1 -1
- package/dist/env.d.ts +4 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +10 -0
- package/dist/env.js.map +1 -1
- package/dist/fast-deep-equal.d.ts.map +1 -1
- package/dist/guards.d.ts.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/misc.d.ts +1 -0
- package/dist/misc.d.ts.map +1 -1
- package/dist/misc.js +1 -0
- package/dist/misc.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts +0 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js +21 -11
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts +2 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.d.ts.map +1 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +39 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +1 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +75 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts.map +1 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js +62 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js.map +1 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts +2 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.d.ts.map +1 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +42 -0
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +1 -0
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts +1 -4
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js +1 -4
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +1 -1
- package/dist/node/mod.d.ts +4 -16
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +25 -69
- package/dist/node/mod.js.map +1 -1
- package/dist/object/index.d.ts.map +1 -1
- package/dist/object/omit.d.ts.map +1 -1
- package/dist/object/pick.d.ts.map +1 -1
- package/dist/promise.d.ts.map +1 -1
- package/dist/set.d.ts.map +1 -1
- package/dist/string.d.ts.map +1 -1
- package/dist/time.d.ts.map +1 -1
- package/package.json +59 -51
- package/src/bun/mod.ts +12 -0
- package/src/effect/BucketQueue.ts +33 -6
- package/src/effect/Effect.ts +33 -20
- package/src/effect/Logger.ts +23 -1
- package/src/effect/Schema/index.ts +27 -0
- package/src/effect/Subscribable.ts +155 -0
- package/src/effect/WebChannel/WebChannel.test.ts +106 -0
- package/src/effect/WebChannel/WebChannel.ts +438 -0
- package/src/effect/WebChannel/broadcastChannelWithAck.ts +86 -83
- package/src/effect/WebChannel/common.ts +49 -2
- package/src/effect/WebChannel/mod.ts +3 -0
- package/src/effect/WebSocket.test.ts +15 -0
- package/src/effect/WebSocket.ts +75 -36
- package/src/effect/index.ts +34 -2
- package/src/env.ts +15 -0
- package/src/index.ts +6 -2
- package/src/misc.ts +3 -0
- package/src/node/ChildProcessRunner/ChildProcessRunner.ts +40 -29
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +52 -0
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +65 -0
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +53 -0
- package/src/node/ChildProcessRunner/ChildProcessWorker.ts +3 -6
- package/src/node/mod.ts +32 -94
- package/dist/effect/WebChannel.d.ts.map +0 -1
- package/dist/effect/WebChannel.js +0 -162
- package/dist/effect/WebChannel.js.map +0 -1
- package/dist/nanoid/index.browser.d.ts +0 -2
- package/dist/nanoid/index.browser.d.ts.map +0 -1
- package/dist/nanoid/index.browser.js +0 -3
- package/dist/nanoid/index.browser.js.map +0 -1
- package/src/effect/WebChannel.ts +0 -290
- package/src/nanoid/index.browser.ts +0 -2
- package/tmp/effect-deferred-repro.ts +0 -29
- package/tmp/effect-semaphore-repro.ts +0 -93
- package/tsconfig.json +0 -10
package/dist/string.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,WAA+C,CAAA;AAC7F,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,WAA+C,CAAA;AAE7F,qEAAqE;AACrE,eAAO,MAAM,MAAM,GAAI,KAAK,MAAM,EAAE,GAAG,MAAM,EAAE,aAAU,KAAG,MAI7C,CAAA"}
|
package/dist/time.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../src/time.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,QAAY,CAAA;AAEnC,eAAO,MAAM,IAAI;;;;;;;CAOhB,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../src/time.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,QAAY,CAAA;AAEnC,eAAO,MAAM,IAAI;;;;;;;CAOhB,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,cAAc,GAAI,IAAI,MAAM,WAYxC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livestore/utils",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.41",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"sideEffects": [
|
|
5
6
|
"./dist/global.js"
|
|
6
7
|
],
|
|
7
|
-
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
@@ -13,12 +13,11 @@
|
|
|
13
13
|
"./cuid": {
|
|
14
14
|
"types": "./dist/cuid/cuid.node.d.ts",
|
|
15
15
|
"node": "./dist/cuid/cuid.node.js",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
16
|
+
"browser": "./dist/cuid/cuid.browser.js",
|
|
17
|
+
"react-native": "./dist/cuid/cuid.browser.js"
|
|
18
18
|
},
|
|
19
19
|
"./nanoid": {
|
|
20
20
|
"types": "./dist/nanoid/index.d.ts",
|
|
21
|
-
"react-native": "./dist/nanoid/index.browser.js",
|
|
22
21
|
"default": "./dist/nanoid/index.js"
|
|
23
22
|
},
|
|
24
23
|
"./effect": {
|
|
@@ -29,16 +28,11 @@
|
|
|
29
28
|
"types": "./dist/node/mod.d.ts",
|
|
30
29
|
"default": "./dist/node/mod.js"
|
|
31
30
|
},
|
|
32
|
-
"./
|
|
33
|
-
"types": "./dist/
|
|
34
|
-
"default": "./dist/
|
|
35
|
-
},
|
|
36
|
-
"./node-vitest-polyfill": {
|
|
37
|
-
"types": "./dist/node-vitest/polyfill.d.ts",
|
|
38
|
-
"default": "./dist/node-vitest/polyfill.js"
|
|
31
|
+
"./bun": {
|
|
32
|
+
"types": "./dist/bun/mod.d.ts",
|
|
33
|
+
"default": "./dist/bun/mod.js"
|
|
39
34
|
}
|
|
40
35
|
},
|
|
41
|
-
"react-native": "./dist/index.js",
|
|
42
36
|
"types": "./dist/index.d.ts",
|
|
43
37
|
"typesVersions": {
|
|
44
38
|
"*": {
|
|
@@ -54,55 +48,69 @@
|
|
|
54
48
|
"./node": [
|
|
55
49
|
"./dist/node/mod.d.ts"
|
|
56
50
|
],
|
|
57
|
-
"./
|
|
58
|
-
"./dist/
|
|
59
|
-
],
|
|
60
|
-
"./node-vitest-polyfill": [
|
|
61
|
-
"./dist/node-vitest/polyfill.d.ts"
|
|
51
|
+
"./bun": [
|
|
52
|
+
"./dist/bun/mod.d.ts"
|
|
62
53
|
]
|
|
63
54
|
}
|
|
64
55
|
},
|
|
65
56
|
"dependencies": {
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
},
|
|
71
|
-
"peerDependencies": {
|
|
72
|
-
"@effect/cli": "^0.50.2",
|
|
73
|
-
"@effect/experimental": "^0.36.1",
|
|
74
|
-
"@effect/opentelemetry": "^0.42.1",
|
|
75
|
-
"@effect/platform": "^0.72.1",
|
|
76
|
-
"@effect/platform-browser": "^0.51.1",
|
|
77
|
-
"@effect/platform-bun": "^0.52.1",
|
|
78
|
-
"@effect/platform-node": "^0.68.1",
|
|
79
|
-
"@effect/vitest": "^0.16.1",
|
|
80
|
-
"@opentelemetry/api": "^1.9.0",
|
|
81
|
-
"effect": "^3.11.7"
|
|
57
|
+
"@standard-schema/spec": "1.0.0",
|
|
58
|
+
"msgpackr": "1.11.2",
|
|
59
|
+
"nanoid": "5.1.3",
|
|
60
|
+
"pretty-bytes": "6.1.1"
|
|
82
61
|
},
|
|
83
62
|
"devDependencies": {
|
|
84
|
-
"@effect/cli": "^0.
|
|
85
|
-
"@effect/
|
|
86
|
-
"@effect/
|
|
87
|
-
"@effect/
|
|
88
|
-
"@effect/platform
|
|
89
|
-
"@effect/platform-
|
|
90
|
-
"@effect/platform-
|
|
91
|
-
"@effect/
|
|
63
|
+
"@effect/cli": "^0.59.15",
|
|
64
|
+
"@effect/cluster": "^0.30.3",
|
|
65
|
+
"@effect/experimental": "^0.44.15",
|
|
66
|
+
"@effect/opentelemetry": "^0.46.4",
|
|
67
|
+
"@effect/platform": "^0.80.15",
|
|
68
|
+
"@effect/platform-browser": "^0.60.6",
|
|
69
|
+
"@effect/platform-bun": "^0.61.3",
|
|
70
|
+
"@effect/platform-node": "^0.77.3",
|
|
71
|
+
"@effect/printer": "^0.42.15",
|
|
72
|
+
"@effect/printer-ansi": "^0.42.15",
|
|
73
|
+
"@effect/rpc": "^0.56.3",
|
|
74
|
+
"@effect/sql": "^0.33.15",
|
|
75
|
+
"@effect/typeclass": "^0.33.15",
|
|
76
|
+
"@effect/vitest": "^0.20.8",
|
|
92
77
|
"@opentelemetry/api": "^1.9.0",
|
|
93
|
-
"@opentelemetry/
|
|
94
|
-
"@
|
|
95
|
-
"@
|
|
96
|
-
"@
|
|
97
|
-
"@
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
78
|
+
"@opentelemetry/resources": "^2.0.0",
|
|
79
|
+
"@types/bun": "^1.2.4",
|
|
80
|
+
"@types/jsdom": "^21.1.7",
|
|
81
|
+
"@types/node": "^22.13.10",
|
|
82
|
+
"@types/web": "^0.0.203",
|
|
83
|
+
"effect": "^3.14.15",
|
|
84
|
+
"jsdom": "^26.0.0",
|
|
85
|
+
"vitest": "^3.1.1"
|
|
86
|
+
},
|
|
87
|
+
"files": [
|
|
88
|
+
"package.json",
|
|
89
|
+
"src",
|
|
90
|
+
"dist"
|
|
91
|
+
],
|
|
92
|
+
"peerDependencies": {
|
|
93
|
+
"@effect/cli": "~0.59.15",
|
|
94
|
+
"@effect/cluster": "~0.30.3",
|
|
95
|
+
"@effect/experimental": "~0.44.15",
|
|
96
|
+
"@effect/opentelemetry": "~0.46.4",
|
|
97
|
+
"@effect/platform": "~0.80.15",
|
|
98
|
+
"@effect/platform-browser": "~0.60.6",
|
|
99
|
+
"@effect/platform-bun": "~0.61.3",
|
|
100
|
+
"@effect/platform-node": "~0.77.3",
|
|
101
|
+
"@effect/printer": "~0.42.15",
|
|
102
|
+
"@effect/printer-ansi": "~0.42.15",
|
|
103
|
+
"@effect/rpc": "~0.56.3",
|
|
104
|
+
"@effect/sql": "~0.33.15",
|
|
105
|
+
"@effect/typeclass": "~0.33.15",
|
|
106
|
+
"@opentelemetry/api": "~1.9.0",
|
|
107
|
+
"@opentelemetry/resources": "~2.0.0",
|
|
108
|
+
"effect": "~3.14.15"
|
|
102
109
|
},
|
|
103
110
|
"publishConfig": {
|
|
104
111
|
"access": "public"
|
|
105
112
|
},
|
|
113
|
+
"react-native": "./dist/index.js",
|
|
106
114
|
"scripts": {
|
|
107
115
|
"test": "vitest"
|
|
108
116
|
}
|
package/src/bun/mod.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { $ } from 'bun'
|
|
2
|
+
import { Effect } from 'effect'
|
|
3
|
+
|
|
4
|
+
export * as PlatformBun from '@effect/platform-bun'
|
|
5
|
+
|
|
6
|
+
export const cmd = (_: string) =>
|
|
7
|
+
Effect.promise(() => {
|
|
8
|
+
console.log(`Running command: ${_}`)
|
|
9
|
+
return $`${{ raw: _ }}`
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
export { $ } from 'bun'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Array, STM, TRef } from 'effect'
|
|
1
|
+
import { Array, Effect, STM, TRef } from 'effect'
|
|
2
2
|
|
|
3
3
|
export type BucketQueue<A> = TRef.TRef<A[]>
|
|
4
4
|
|
|
@@ -7,16 +7,43 @@ export const make = <A>(): STM.STM<BucketQueue<A>> => TRef.make<A[]>([])
|
|
|
7
7
|
export const offerAll = <A>(self: BucketQueue<A>, elements: ReadonlyArray<A>) =>
|
|
8
8
|
TRef.update(self, (bucket) => Array.appendAll(bucket, elements))
|
|
9
9
|
|
|
10
|
+
export const replace = <A>(self: BucketQueue<A>, elements: ReadonlyArray<A>) => TRef.set(self, elements as A[])
|
|
11
|
+
|
|
10
12
|
export const clear = <A>(self: BucketQueue<A>) => TRef.set(self, [])
|
|
11
13
|
|
|
12
|
-
export const takeBetween = <A>(
|
|
14
|
+
export const takeBetween = <A>(
|
|
15
|
+
bucket: BucketQueue<A>,
|
|
16
|
+
min: number,
|
|
17
|
+
max: number,
|
|
18
|
+
): STM.STM<ReadonlyArray<A>, never, never> =>
|
|
13
19
|
STM.gen(function* () {
|
|
14
|
-
const
|
|
15
|
-
if (
|
|
20
|
+
const bucketValue = yield* TRef.get(bucket)
|
|
21
|
+
if (bucketValue.length < min) {
|
|
16
22
|
return yield* STM.retry
|
|
17
23
|
} else {
|
|
18
|
-
const elements =
|
|
19
|
-
yield* TRef.set(
|
|
24
|
+
const elements = bucketValue.splice(0, Math.min(max, bucketValue.length))
|
|
25
|
+
yield* TRef.set(bucket, bucketValue)
|
|
20
26
|
return elements
|
|
21
27
|
}
|
|
22
28
|
})
|
|
29
|
+
|
|
30
|
+
export const peekAll = <A>(bucket: BucketQueue<A>) => TRef.get(bucket)
|
|
31
|
+
|
|
32
|
+
/** Returns the elements up to the first element that matches the predicate, the rest is left in the queue
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const [elements, rest] = yield* BucketQueue.takeSplitWhere(bucket, (a) => a > 3)
|
|
37
|
+
* assert.deepStrictEqual(elements, [1, 2, 3])
|
|
38
|
+
* assert.deepStrictEqual(rest, [4, 5, 6])
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export const takeSplitWhere = <A>(bucket: BucketQueue<A>, predicate: (a: A) => boolean) =>
|
|
42
|
+
STM.gen(function* () {
|
|
43
|
+
const bucketValue = yield* TRef.get(bucket)
|
|
44
|
+
const [elements, rest] = Array.splitWhere(bucketValue, predicate)
|
|
45
|
+
yield* TRef.set(bucket, rest)
|
|
46
|
+
return elements
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
export const size = <A>(bucket: BucketQueue<A>) => TRef.get(bucket).pipe(Effect.map((_) => _.length))
|
package/src/effect/Effect.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as OtelTracer from '@effect/opentelemetry/Tracer'
|
|
2
|
-
import type { Context, Duration,
|
|
3
|
-
import { Cause, Deferred, Effect, Fiber, FiberRef, HashSet, Logger, pipe } from 'effect'
|
|
2
|
+
import type { Context, Duration, Stream } from 'effect'
|
|
3
|
+
import { Cause, Deferred, Effect, Fiber, FiberRef, HashSet, Logger, pipe, Scope } from 'effect'
|
|
4
4
|
import type { UnknownException } from 'effect/Cause'
|
|
5
5
|
import { log } from 'effect/Console'
|
|
6
6
|
import type { LazyArg } from 'effect/Function'
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { isPromise } from '../index.js'
|
|
9
9
|
import { UnknownError } from './Error.js'
|
|
10
10
|
|
|
11
11
|
export * from 'effect/Effect'
|
|
@@ -25,6 +25,18 @@ export * from 'effect/Effect'
|
|
|
25
25
|
// console.error(message, ...rest)
|
|
26
26
|
// })
|
|
27
27
|
|
|
28
|
+
/** Same as `Effect.scopeWith` but with a `CloseableScope` instead of a `Scope`. */
|
|
29
|
+
export const scopeWithCloseable = <R, E, A>(
|
|
30
|
+
fn: (scope: Scope.CloseableScope) => Effect.Effect<A, E, R | Scope.Scope>,
|
|
31
|
+
): Effect.Effect<A, E, R | Scope.Scope> =>
|
|
32
|
+
Effect.gen(function* () {
|
|
33
|
+
// const parentScope = yield* Scope.Scope
|
|
34
|
+
// const scope = yield* Scope.fork(parentScope, ExecutionStrategy.sequential)
|
|
35
|
+
const scope = yield* Scope.make()
|
|
36
|
+
yield* Effect.addFinalizer((exit) => Scope.close(scope, exit))
|
|
37
|
+
return yield* fn(scope).pipe(Scope.extend(scope))
|
|
38
|
+
})
|
|
39
|
+
|
|
28
40
|
export const tryAll = <Res>(
|
|
29
41
|
fn: () => Res,
|
|
30
42
|
): Res extends Effect.Effect<infer A, infer E, never>
|
|
@@ -42,17 +54,6 @@ export const tryAll = <Res>(
|
|
|
42
54
|
),
|
|
43
55
|
) as any
|
|
44
56
|
|
|
45
|
-
const getThreadName = () => {
|
|
46
|
-
// @ts-expect-error TODO fix types
|
|
47
|
-
const globalName = globalThis.name
|
|
48
|
-
return isNonEmptyString(globalName)
|
|
49
|
-
? globalName
|
|
50
|
-
: // eslint-disable-next-line unicorn/prefer-global-this
|
|
51
|
-
typeof window === 'object'
|
|
52
|
-
? 'Main Thread'
|
|
53
|
-
: 'unknown-thread'
|
|
54
|
-
}
|
|
55
|
-
|
|
56
57
|
export const acquireReleaseLog = (label: string) =>
|
|
57
58
|
Effect.acquireRelease(Effect.log(`${label} acquire`), (_, ex) => Effect.log(`${label} release`, ex))
|
|
58
59
|
|
|
@@ -76,9 +77,8 @@ export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.
|
|
|
76
77
|
Effect.catchTag('NoSuchElementException', (_) => Effect.succeed(undefined)),
|
|
77
78
|
)
|
|
78
79
|
|
|
79
|
-
const threadName = getThreadName()
|
|
80
80
|
const firstErrLine = cause.toString().split('\n')[0]
|
|
81
|
-
yield* Effect.logError(
|
|
81
|
+
yield* Effect.logError(firstErrLine, cause).pipe((_) =>
|
|
82
82
|
span === undefined
|
|
83
83
|
? _
|
|
84
84
|
: Effect.annotateLogs({ spanId: span.spanContext().spanId, traceId: span.spanContext().traceId })(_),
|
|
@@ -113,11 +113,11 @@ export const logWarnIfTakesLongerThan =
|
|
|
113
113
|
Effect.gen(function* () {
|
|
114
114
|
const runtime = yield* Effect.runtime<never>()
|
|
115
115
|
|
|
116
|
-
let
|
|
116
|
+
let tookLongerThanTimer = false
|
|
117
117
|
|
|
118
118
|
const timeoutFiber = Effect.sleep(duration).pipe(
|
|
119
119
|
Effect.tap(() => {
|
|
120
|
-
|
|
120
|
+
tookLongerThanTimer = true
|
|
121
121
|
// TODO include span info
|
|
122
122
|
return Effect.logWarning(`${label}: Took longer than ${duration}ms`)
|
|
123
123
|
}),
|
|
@@ -126,9 +126,22 @@ export const logWarnIfTakesLongerThan =
|
|
|
126
126
|
)
|
|
127
127
|
|
|
128
128
|
const start = Date.now()
|
|
129
|
-
const res = yield* eff.pipe(
|
|
129
|
+
const res = yield* eff.pipe(
|
|
130
|
+
Effect.exit,
|
|
131
|
+
Effect.onInterrupt(
|
|
132
|
+
Effect.fn(function* () {
|
|
133
|
+
const end = Date.now()
|
|
134
|
+
|
|
135
|
+
yield* Fiber.interrupt(timeoutFiber)
|
|
136
|
+
|
|
137
|
+
if (tookLongerThanTimer) {
|
|
138
|
+
yield* Effect.logWarning(`${label}: Interrupted after ${end - start}ms`)
|
|
139
|
+
}
|
|
140
|
+
}),
|
|
141
|
+
),
|
|
142
|
+
)
|
|
130
143
|
|
|
131
|
-
if (
|
|
144
|
+
if (tookLongerThanTimer) {
|
|
132
145
|
const end = Date.now()
|
|
133
146
|
yield* Effect.logWarning(`${label}: Actual duration: ${end - start}ms`)
|
|
134
147
|
}
|
package/src/effect/Logger.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Logger } from 'effect'
|
|
1
|
+
import { Cause, HashMap, Logger, LogLevel } from 'effect'
|
|
2
2
|
|
|
3
3
|
export * from 'effect/Logger'
|
|
4
4
|
|
|
@@ -14,4 +14,26 @@ export const prettyWithThread = (threadName: string) =>
|
|
|
14
14
|
Logger.prettyLogger({
|
|
15
15
|
formatDate: (date) => `${defaultDateFormat(date)} ${threadName}`,
|
|
16
16
|
}),
|
|
17
|
+
// consoleLogger(threadName),
|
|
17
18
|
)
|
|
19
|
+
|
|
20
|
+
export const consoleLogger = (threadName: string) =>
|
|
21
|
+
Logger.make(({ message, annotations, date, logLevel, cause }) => {
|
|
22
|
+
const consoleFn =
|
|
23
|
+
logLevel === LogLevel.Debug
|
|
24
|
+
? console.debug
|
|
25
|
+
: logLevel === LogLevel.Info
|
|
26
|
+
? console.info
|
|
27
|
+
: logLevel === LogLevel.Warning
|
|
28
|
+
? console.warn
|
|
29
|
+
: console.error
|
|
30
|
+
|
|
31
|
+
const annotationsObj = Object.fromEntries(HashMap.entries(annotations))
|
|
32
|
+
|
|
33
|
+
const messages = Array.isArray(message) ? message : [message]
|
|
34
|
+
if (Cause.isEmpty(cause) === false) {
|
|
35
|
+
messages.push(Cause.pretty(cause, { renderErrorCause: true }))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
consoleFn(`[${defaultDateFormat(date)} ${threadName}]`, ...messages, annotationsObj)
|
|
39
|
+
})
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Transferable } from '@effect/platform'
|
|
2
|
+
import type { SchemaAST } from 'effect'
|
|
2
3
|
import { Effect, Hash, ParseResult, Schema } from 'effect'
|
|
3
4
|
import type { ParseError } from 'effect/ParseResult'
|
|
4
5
|
import type { ParseOptions } from 'effect/SchemaAST'
|
|
5
6
|
|
|
7
|
+
import { shouldNeverHappen } from '../../index.js'
|
|
8
|
+
|
|
6
9
|
export * from 'effect/Schema'
|
|
7
10
|
export * from './debug-diff.js'
|
|
8
11
|
export * from './msgpack.js'
|
|
@@ -34,6 +37,30 @@ export const encodeWithTransferables =
|
|
|
34
37
|
return [encoded, collector.unsafeRead() as Transferable[]]
|
|
35
38
|
})
|
|
36
39
|
|
|
40
|
+
export const decodeSyncDebug: <A, I>(
|
|
41
|
+
schema: Schema.Schema<A, I, never>,
|
|
42
|
+
options?: SchemaAST.ParseOptions,
|
|
43
|
+
) => (i: I, overrideOptions?: SchemaAST.ParseOptions) => A = (schema, options) => (input, overrideOptions) => {
|
|
44
|
+
const res = Schema.decodeEither(schema, options)(input, overrideOptions)
|
|
45
|
+
if (res._tag === 'Left') {
|
|
46
|
+
return shouldNeverHappen(`decodeSyncDebug failed:`, res.left)
|
|
47
|
+
} else {
|
|
48
|
+
return res.right
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const encodeSyncDebug: <A, I>(
|
|
53
|
+
schema: Schema.Schema<A, I, never>,
|
|
54
|
+
options?: SchemaAST.ParseOptions,
|
|
55
|
+
) => (a: A, overrideOptions?: SchemaAST.ParseOptions) => I = (schema, options) => (input, overrideOptions) => {
|
|
56
|
+
const res = Schema.encodeEither(schema, options)(input, overrideOptions)
|
|
57
|
+
if (res._tag === 'Left') {
|
|
58
|
+
return shouldNeverHappen(`encodeSyncDebug failed:`, res.left)
|
|
59
|
+
} else {
|
|
60
|
+
return res.right
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
37
64
|
export const swap = <A, I, R>(schema: Schema.Schema<A, I, R>): Schema.Schema<I, A, R> =>
|
|
38
65
|
Schema.transformOrFail(Schema.typeSchema(schema), Schema.encodedSchema(schema), {
|
|
39
66
|
decode: ParseResult.encode(schema),
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Fork of effect/Subscribable.ts which makes Subscribable yieldable
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @since 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { SubscriptionRef } from 'effect'
|
|
8
|
+
import { Effect, Effectable, Readable, Stream } from 'effect'
|
|
9
|
+
import { dual } from 'effect/Function'
|
|
10
|
+
import { hasProperty } from 'effect/Predicate'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @since 2.0.0
|
|
14
|
+
* @category type ids
|
|
15
|
+
*/
|
|
16
|
+
export const TypeId: unique symbol = Symbol.for('effect/Subscribable')
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @since 2.0.0
|
|
20
|
+
* @category type ids
|
|
21
|
+
*/
|
|
22
|
+
export type TypeId = typeof TypeId
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @since 2.0.0
|
|
26
|
+
* @category models
|
|
27
|
+
*/
|
|
28
|
+
export interface Subscribable<A, E = never, R = never> extends Readable.Readable<A, E, R>, Effect.Effect<A, E, R> {
|
|
29
|
+
readonly [TypeId]: TypeId
|
|
30
|
+
readonly changes: Stream.Stream<A, E, R>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @since 2.0.0
|
|
35
|
+
* @category refinements
|
|
36
|
+
*/
|
|
37
|
+
export const isSubscribable = (u: unknown): u is Subscribable<unknown, unknown, unknown> => hasProperty(u, TypeId)
|
|
38
|
+
|
|
39
|
+
// const Proto: Omit<Subscribable<any>, 'get' | 'changes'> = {
|
|
40
|
+
// [Readable.TypeId]: Readable.TypeId,
|
|
41
|
+
// [TypeId]: TypeId,
|
|
42
|
+
// pipe() {
|
|
43
|
+
// return pipeArguments(this, arguments)
|
|
44
|
+
// },
|
|
45
|
+
// }
|
|
46
|
+
|
|
47
|
+
class SubscribableImpl<in out A> extends Effectable.Class<A> implements Subscribable<A> {
|
|
48
|
+
// @ts-expect-error type symbol
|
|
49
|
+
readonly [TypeId] = TypeId
|
|
50
|
+
// @ts-expect-error type symbol
|
|
51
|
+
readonly [Readable.TypeId] = Readable.TypeId
|
|
52
|
+
constructor(
|
|
53
|
+
readonly get: Effect.Effect<A>,
|
|
54
|
+
readonly changes: Stream.Stream<A>,
|
|
55
|
+
) {
|
|
56
|
+
super()
|
|
57
|
+
}
|
|
58
|
+
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
|
|
59
|
+
commit() {
|
|
60
|
+
return this.get
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @since 2.0.0
|
|
66
|
+
* @category constructors
|
|
67
|
+
*/
|
|
68
|
+
// export const make = <A, E, R>(options: {
|
|
69
|
+
// readonly get: Effect.Effect<A, E, R>
|
|
70
|
+
// readonly changes: Stream.Stream<A, E, R>
|
|
71
|
+
// }): Subscribable<A, E, R> => Object.assign(Object.create(Proto), options)
|
|
72
|
+
|
|
73
|
+
export const make = <A, E, R>(options: {
|
|
74
|
+
readonly get: Effect.Effect<A, E, R>
|
|
75
|
+
readonly changes: Stream.Stream<A, E, R>
|
|
76
|
+
}): Subscribable<A, E, R> => new SubscribableImpl(options.get as any, options.changes as any) as Subscribable<A, E, R>
|
|
77
|
+
|
|
78
|
+
export const fromSubscriptionRef = <A>(ref: SubscriptionRef.SubscriptionRef<A>): Subscribable<A> =>
|
|
79
|
+
make({
|
|
80
|
+
get: ref.get,
|
|
81
|
+
changes: ref.changes,
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @since 2.0.0
|
|
86
|
+
* @category combinators
|
|
87
|
+
*/
|
|
88
|
+
export const map: {
|
|
89
|
+
/**
|
|
90
|
+
* @since 2.0.0
|
|
91
|
+
* @category combinators
|
|
92
|
+
*/
|
|
93
|
+
<A, B>(f: (a: NoInfer<A>) => B): <E, R>(fa: Subscribable<A, E, R>) => Subscribable<B, E, R>
|
|
94
|
+
/**
|
|
95
|
+
* @since 2.0.0
|
|
96
|
+
* @category combinators
|
|
97
|
+
*/
|
|
98
|
+
<A, E, R, B>(self: Subscribable<A, E, R>, f: (a: NoInfer<A>) => B): Subscribable<B, E, R>
|
|
99
|
+
} = dual(
|
|
100
|
+
2,
|
|
101
|
+
<A, E, R, B>(self: Subscribable<A, E, R>, f: (a: NoInfer<A>) => B): Subscribable<B, E, R> =>
|
|
102
|
+
make({
|
|
103
|
+
get: Effect.map(self.get, f),
|
|
104
|
+
changes: Stream.map(self.changes, f),
|
|
105
|
+
}),
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @since 2.0.0
|
|
110
|
+
* @category combinators
|
|
111
|
+
*/
|
|
112
|
+
export const mapEffect: {
|
|
113
|
+
/**
|
|
114
|
+
* @since 2.0.0
|
|
115
|
+
* @category combinators
|
|
116
|
+
*/
|
|
117
|
+
<A, B, E2, R2>(
|
|
118
|
+
f: (a: NoInfer<A>) => Effect.Effect<B, E2, R2>,
|
|
119
|
+
): <E, R>(fa: Subscribable<A, E, R>) => Subscribable<B, E | E2, R | R2>
|
|
120
|
+
/**
|
|
121
|
+
* @since 2.0.0
|
|
122
|
+
* @category combinators
|
|
123
|
+
*/
|
|
124
|
+
<A, E, R, B, E2, R2>(
|
|
125
|
+
self: Subscribable<A, E, R>,
|
|
126
|
+
f: (a: NoInfer<A>) => Effect.Effect<B, E2, R2>,
|
|
127
|
+
): Subscribable<B, E | E2, R | R2>
|
|
128
|
+
} = dual(
|
|
129
|
+
2,
|
|
130
|
+
<A, E, R, B, E2, R2>(
|
|
131
|
+
self: Subscribable<A, E, R>,
|
|
132
|
+
f: (a: NoInfer<A>) => Effect.Effect<B, E2, R2>,
|
|
133
|
+
): Subscribable<B, E | E2, R | R2> =>
|
|
134
|
+
make({
|
|
135
|
+
get: Effect.flatMap(self.get, f),
|
|
136
|
+
changes: Stream.mapEffect(self.changes, f),
|
|
137
|
+
}),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @since 2.0.0
|
|
142
|
+
* @category constructors
|
|
143
|
+
*/
|
|
144
|
+
export const unwrap = <A, E, R, E1, R1>(
|
|
145
|
+
effect: Effect.Effect<Subscribable<A, E, R>, E1, R1>,
|
|
146
|
+
): Subscribable<A, E | E1, R | R1> =>
|
|
147
|
+
make({
|
|
148
|
+
get: Effect.flatMap(effect, (s) => s.get),
|
|
149
|
+
changes: Stream.unwrap(Effect.map(effect, (s) => s.changes)),
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
export const never = make({
|
|
153
|
+
get: Effect.never,
|
|
154
|
+
changes: Stream.never,
|
|
155
|
+
})
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as Vitest from '@effect/vitest'
|
|
2
|
+
import { Effect, Schema, Stream } from 'effect'
|
|
3
|
+
import { JSDOM } from 'jsdom'
|
|
4
|
+
|
|
5
|
+
import * as WebChannel from './WebChannel.js'
|
|
6
|
+
|
|
7
|
+
Vitest.describe('WebChannel', () => {
|
|
8
|
+
Vitest.describe('windowChannel', () => {
|
|
9
|
+
Vitest.scopedLive('should work with 2 windows', () =>
|
|
10
|
+
Effect.gen(function* () {
|
|
11
|
+
const windowA = new JSDOM().window as unknown as globalThis.Window
|
|
12
|
+
const windowB = new JSDOM().window as unknown as globalThis.Window
|
|
13
|
+
|
|
14
|
+
const codeSideA = Effect.gen(function* () {
|
|
15
|
+
const channelToB = yield* WebChannel.windowChannel({
|
|
16
|
+
listenWindow: windowA,
|
|
17
|
+
sendWindow: windowB,
|
|
18
|
+
ids: { own: 'a', other: 'b' },
|
|
19
|
+
schema: Schema.Number,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const msgFromBFiber = yield* channelToB.listen.pipe(
|
|
23
|
+
Stream.flatten(),
|
|
24
|
+
Stream.runHead,
|
|
25
|
+
Effect.flatten,
|
|
26
|
+
Effect.fork,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
yield* channelToB.send(1)
|
|
30
|
+
|
|
31
|
+
Vitest.expect(yield* msgFromBFiber).toEqual(2)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const codeSideB = Effect.gen(function* () {
|
|
35
|
+
const channelToA = yield* WebChannel.windowChannel({
|
|
36
|
+
listenWindow: windowB,
|
|
37
|
+
sendWindow: windowA,
|
|
38
|
+
ids: { own: 'b', other: 'a' },
|
|
39
|
+
schema: Schema.Number,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const msgFromAFiber = yield* channelToA.listen.pipe(
|
|
43
|
+
Stream.flatten(),
|
|
44
|
+
Stream.runHead,
|
|
45
|
+
Effect.flatten,
|
|
46
|
+
Effect.fork,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
yield* channelToA.send(2)
|
|
50
|
+
|
|
51
|
+
Vitest.expect(yield* msgFromAFiber).toEqual(1)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
yield* Effect.all([codeSideA, codeSideB], { concurrency: 'unbounded' })
|
|
55
|
+
}),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
Vitest.scopedLive('should work with the same window', () =>
|
|
59
|
+
Effect.gen(function* () {
|
|
60
|
+
const window = new JSDOM().window as unknown as globalThis.Window
|
|
61
|
+
|
|
62
|
+
const codeSideA = Effect.gen(function* () {
|
|
63
|
+
const channelToB = yield* WebChannel.windowChannel({
|
|
64
|
+
listenWindow: window,
|
|
65
|
+
sendWindow: window,
|
|
66
|
+
ids: { own: 'a', other: 'b' },
|
|
67
|
+
schema: Schema.Number,
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const msgFromBFiber = yield* channelToB.listen.pipe(
|
|
71
|
+
Stream.flatten(),
|
|
72
|
+
Stream.runHead,
|
|
73
|
+
Effect.flatten,
|
|
74
|
+
Effect.fork,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
yield* channelToB.send(1)
|
|
78
|
+
|
|
79
|
+
Vitest.expect(yield* msgFromBFiber).toEqual(2)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const codeSideB = Effect.gen(function* () {
|
|
83
|
+
const channelToA = yield* WebChannel.windowChannel({
|
|
84
|
+
listenWindow: window,
|
|
85
|
+
sendWindow: window,
|
|
86
|
+
ids: { own: 'b', other: 'a' },
|
|
87
|
+
schema: Schema.Number,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const msgFromAFiber = yield* channelToA.listen.pipe(
|
|
91
|
+
Stream.flatten(),
|
|
92
|
+
Stream.runHead,
|
|
93
|
+
Effect.flatten,
|
|
94
|
+
Effect.fork,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
yield* channelToA.send(2)
|
|
98
|
+
|
|
99
|
+
Vitest.expect(yield* msgFromAFiber).toEqual(1)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
yield* Effect.all([codeSideA, codeSideB], { concurrency: 'unbounded' })
|
|
103
|
+
}),
|
|
104
|
+
)
|
|
105
|
+
})
|
|
106
|
+
})
|