@livestore/utils 0.0.54-dev.21 → 0.0.54-dev.23

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 (47) hide show
  1. package/dist/.tsbuildinfo.json +1 -1
  2. package/dist/effect/Effect.d.ts +6 -5
  3. package/dist/effect/Effect.d.ts.map +1 -1
  4. package/dist/effect/Effect.js +40 -13
  5. package/dist/effect/Effect.js.map +1 -1
  6. package/dist/effect/Schema.d.ts +11 -1
  7. package/dist/effect/Schema.d.ts.map +1 -1
  8. package/dist/effect/Schema.js +31 -1
  9. package/dist/effect/Schema.js.map +1 -1
  10. package/dist/effect/Stream.d.ts +2 -0
  11. package/dist/effect/Stream.d.ts.map +1 -1
  12. package/dist/effect/Stream.js +11 -1
  13. package/dist/effect/Stream.js.map +1 -1
  14. package/dist/effect/SubscriptionRef.d.ts +8 -3
  15. package/dist/effect/SubscriptionRef.d.ts.map +1 -1
  16. package/dist/effect/SubscriptionRef.js +2 -2
  17. package/dist/effect/SubscriptionRef.js.map +1 -1
  18. package/dist/effect/WebLock.d.ts +5 -1
  19. package/dist/effect/WebLock.d.ts.map +1 -1
  20. package/dist/effect/WebLock.js +26 -6
  21. package/dist/effect/WebLock.js.map +1 -1
  22. package/dist/effect/index.d.ts +3 -2
  23. package/dist/effect/index.d.ts.map +1 -1
  24. package/dist/effect/index.js +3 -2
  25. package/dist/effect/index.js.map +1 -1
  26. package/dist/effect/port-platform-runner.d.ts +5 -0
  27. package/dist/effect/port-platform-runner.d.ts.map +1 -0
  28. package/dist/effect/port-platform-runner.js +54 -0
  29. package/dist/effect/port-platform-runner.js.map +1 -0
  30. package/dist/index.d.ts +3 -3
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +6 -16
  33. package/dist/index.js.map +1 -1
  34. package/dist/misc.d.ts +2 -0
  35. package/dist/misc.d.ts.map +1 -0
  36. package/dist/misc.js +13 -0
  37. package/dist/misc.js.map +1 -0
  38. package/package.json +14 -14
  39. package/src/effect/Effect.ts +60 -19
  40. package/src/effect/Schema.ts +43 -2
  41. package/src/effect/Stream.ts +37 -1
  42. package/src/effect/SubscriptionRef.ts +22 -7
  43. package/src/effect/WebLock.ts +41 -13
  44. package/src/effect/index.ts +4 -0
  45. package/src/effect/port-platform-runner.ts +73 -0
  46. package/src/index.ts +8 -18
  47. package/src/misc.ts +12 -0
package/dist/index.js CHANGED
@@ -7,8 +7,10 @@ export * from './NoopTracer.js';
7
7
  export * from './set.js';
8
8
  export * from './browser.js';
9
9
  export * from './Deferred.js';
10
+ export * from './misc.js';
10
11
  export * as base64 from './base64.js';
11
12
  export { default as prettyBytes } from 'pretty-bytes';
13
+ import { objectToString } from './misc.js';
12
14
  export * as dateFns from 'date-fns';
13
15
  export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
14
16
  export const ref = (val) => ({ current: val });
@@ -43,21 +45,6 @@ export const recRemoveUndefinedValues = (val) => {
43
45
  };
44
46
  export const debugDeepCopy = (val) => JSON.parse(JSON.stringify(val));
45
47
  export const prop = (key) => (obj) => obj[key];
46
- export const objectToString = (error) => {
47
- const stack = error.stack;
48
- const str = error.toString();
49
- const stackStr = stack ? `\n${stack}` : '';
50
- if (str !== '[object Object]')
51
- return str + stackStr;
52
- try {
53
- return JSON.stringify({ ...error, stack }, null, 2);
54
- }
55
- catch (e) {
56
- console.log(error);
57
- return 'Error while printing error: ' + e;
58
- }
59
- };
60
- export const errorToString = objectToString;
61
48
  export const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
62
49
  export const isReadonlyArray = (value) => Array.isArray(value);
63
50
  /**
@@ -170,7 +157,10 @@ export const memoizeByRef = (fn) => {
170
157
  return result;
171
158
  });
172
159
  };
173
- export const isNonEmptyString = (str) => str === undefined || str === null || str === '';
160
+ export const isNonEmptyString = (str) => {
161
+ return typeof str === 'string' && str.length > 0;
162
+ };
174
163
  export const isPromise = (value) => typeof value?.then === 'function';
175
164
  export const isIterable = (value) => typeof value?.[Symbol.iterator] === 'function';
165
+ export { objectToString as errorToString } from './misc.js';
176
166
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/misc.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const objectToString: (error: any) => string;
2
+ //# sourceMappingURL=misc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../src/misc.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,UAAW,GAAG,KAAG,MAW3C,CAAA"}
package/dist/misc.js ADDED
@@ -0,0 +1,13 @@
1
+ export const objectToString = (error) => {
2
+ const str = error?.toString();
3
+ if (str !== '[object Object]')
4
+ return str;
5
+ try {
6
+ return JSON.stringify(error, null, 2);
7
+ }
8
+ catch (e) {
9
+ console.log(error);
10
+ return 'Error while printing error: ' + e;
11
+ }
12
+ };
13
+ //# sourceMappingURL=misc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"misc.js","sourceRoot":"","sources":["../src/misc.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAU,EAAU,EAAE;IACnD,MAAM,GAAG,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAA;IAC7B,IAAI,GAAG,KAAK,iBAAiB;QAAE,OAAO,GAAG,CAAA;IAEzC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACvC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAElB,OAAO,8BAA8B,GAAG,CAAC,CAAA;IAC3C,CAAC;AACH,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/utils",
3
- "version": "0.0.54-dev.21",
3
+ "version": "0.0.54-dev.23",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -35,27 +35,27 @@
35
35
  "date-fns": "^3.6.0",
36
36
  "otel-websocket-exporter": "^0.0.29",
37
37
  "pretty-bytes": "^6.1.1",
38
- "effect-db-schema": "0.0.54-dev.21"
38
+ "effect-db-schema": "0.0.54-dev.23"
39
39
  },
40
40
  "peerDependencies": {
41
- "@effect/experimental": "^0.16.24",
42
- "@effect/opentelemetry": "^0.34.17",
43
- "@effect/platform": "^0.57.0",
44
- "@effect/platform-browser": "^0.36.0",
45
- "@effect/schema": "^0.67.22",
41
+ "@effect/experimental": "^0.18.1",
42
+ "@effect/opentelemetry": "^0.34.36",
43
+ "@effect/platform": "^0.58.27",
44
+ "@effect/platform-browser": "^0.37.27",
45
+ "@effect/schema": "^0.68.23",
46
46
  "@opentelemetry/api": "^1.9.0",
47
- "effect": "^3.3.1"
47
+ "effect": "^3.5.3"
48
48
  },
49
49
  "devDependencies": {
50
- "@effect/experimental": "0.16.26",
51
- "@effect/opentelemetry": "0.34.19",
52
- "@effect/platform": "0.57.1",
53
- "@effect/platform-browser": "0.36.1",
54
- "@effect/schema": "0.67.23",
50
+ "@effect/experimental": "0.18.1",
51
+ "@effect/opentelemetry": "0.34.36",
52
+ "@effect/platform": "0.58.27",
53
+ "@effect/platform-browser": "0.37.27",
54
+ "@effect/schema": "0.68.23",
55
55
  "@opentelemetry/api": "^1.9.0",
56
56
  "@types/node": "^20.12.11",
57
57
  "@types/web": "^0.0.149",
58
- "effect": "3.3.2"
58
+ "effect": "3.5.3"
59
59
  },
60
60
  "publishConfig": {
61
61
  "access": "public"
@@ -1,5 +1,6 @@
1
- import type { Context, Duration } from 'effect'
2
- import { Cause, Deferred, Effect, pipe } from 'effect'
1
+ import type { Context, Duration, Scope } from 'effect'
2
+ import { Cause, Deferred, Effect, Fiber, pipe } from 'effect'
3
+ import { log } from 'effect/Console'
3
4
  import type { LazyArg } from 'effect/Function'
4
5
 
5
6
  import { isNonEmptyString } from '../index.js'
@@ -7,34 +8,73 @@ import { UnknownError } from './Error.js'
7
8
 
8
9
  export * from 'effect/Effect'
9
10
 
10
- export const log = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
11
- Effect.sync(() => {
12
- console.log(message, ...rest)
13
- })
11
+ // export const log = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
12
+ // Effect.sync(() => {
13
+ // console.log(message, ...rest)
14
+ // })
14
15
 
15
- export const logWarn = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
16
- Effect.sync(() => {
17
- console.warn(message, ...rest)
18
- })
16
+ // export const logWarn = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
17
+ // Effect.sync(() => {
18
+ // console.warn(message, ...rest)
19
+ // })
19
20
 
20
- export const logError = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
21
- Effect.sync(() => {
22
- console.error(message, ...rest)
23
- })
21
+ // export const logError = <A>(message: A, ...rest: any[]): Effect.Effect<void> =>
22
+ // Effect.sync(() => {
23
+ // console.error(message, ...rest)
24
+ // })
25
+
26
+ const getThreadName = () =>
27
+ isNonEmptyString(self.name) ? self.name : typeof window === 'object' ? 'Browser Main Thread' : 'unknown-thread'
24
28
 
25
29
  /** Logs both on errors and defects */
26
30
  export const tapCauseLogPretty = <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
27
31
  Effect.tapErrorCause(eff, (err) => {
28
32
  if (Cause.isInterruptedOnly(err)) {
33
+ // console.log('interrupted', Cause.pretty(err), err)
29
34
  return Effect.void
30
35
  }
31
36
 
32
- const threadName =
33
- typeof window === 'undefined' ? 'NodeJS Main Thread' : isNonEmptyString(self.name) ? self.name : 'unknown-thread'
37
+ const threadName = getThreadName()
34
38
 
35
- return logError(`Error on ${threadName}`, Cause.pretty(err))
39
+ // const prettyError = (err as any).error ? (err as any).error.toString() : Cause.pretty(err)
40
+ // const prettyError = Cause.pretty(err)
41
+
42
+ // return Effect.logError(`Error on ${threadName}:`, prettyError)
43
+ const firstErrLine = err.toString().split('\n')[0]
44
+ return Effect.logError(`Error on ${threadName}: ${firstErrLine}`, err)
36
45
  })
37
46
 
47
+ export const logWarnIfTakesLongerThan =
48
+ ({ label, duration }: { label: string; duration: Duration.DurationInput }) =>
49
+ <R, E, A>(eff: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
50
+ Effect.gen(function* () {
51
+ const runtime = yield* Effect.runtime<never>()
52
+
53
+ let timedOut = false
54
+
55
+ const timeoutFiber = Effect.sleep(duration).pipe(
56
+ Effect.tap(() => {
57
+ timedOut = true
58
+ // TODO include span info
59
+ return Effect.logWarning(`${label}: Took longer than ${duration}ms`)
60
+ }),
61
+ Effect.provide(runtime),
62
+ Effect.runFork,
63
+ )
64
+
65
+ const start = Date.now()
66
+ const res = yield* eff
67
+
68
+ if (timedOut) {
69
+ const end = Date.now()
70
+ yield* Effect.logWarning(`${label}: Actual duration: ${end - start}ms`)
71
+ }
72
+
73
+ yield* Fiber.interrupt(timeoutFiber)
74
+
75
+ return res
76
+ })
77
+
38
78
  export const tapSync =
39
79
  <A>(tapFn: (a: A) => unknown) =>
40
80
  <R, E>(eff: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
@@ -62,14 +102,15 @@ export const timeoutDieMsg =
62
102
 
63
103
  export const toForkedDeferred = <R, E, A>(
64
104
  eff: Effect.Effect<A, E, R>,
65
- ): Effect.Effect<Deferred.Deferred<A, E>, never, R> =>
105
+ ): Effect.Effect<Deferred.Deferred<A, E>, never, R | Scope.Scope> =>
66
106
  pipe(
67
107
  Deferred.make<A, E>(),
68
108
  Effect.tap((deferred) =>
69
109
  pipe(
70
110
  Effect.exit(eff),
71
111
  Effect.flatMap((ex) => Deferred.done(deferred, ex)),
72
- Effect.forkDaemon,
112
+ tapCauseLogPretty,
113
+ Effect.forkScoped,
73
114
  ),
74
115
  ),
75
116
  )
@@ -1,5 +1,10 @@
1
- import type { Schema } from '@effect/schema'
2
- import { Hash } from 'effect'
1
+ import { Transferable } from '@effect/platform'
2
+ import { Schema } from '@effect/schema'
3
+ import type { ParseOptions } from '@effect/schema/AST'
4
+ import type { ParseError } from '@effect/schema/ParseResult'
5
+ import { Effect, Hash } from 'effect'
6
+
7
+ import { objectToString } from '../misc.js'
3
8
 
4
9
  export * from '@effect/schema/Schema'
5
10
 
@@ -16,3 +21,39 @@ export const hash = (schema: Schema.Schema<any>) => {
16
21
  return Hash.hash(schema.ast.toString())
17
22
  }
18
23
  }
24
+
25
+ const errorStructSchema = Schema.Struct({
26
+ message: Schema.String,
27
+ stack: Schema.optional(Schema.String),
28
+ })
29
+
30
+ export class AnyError extends Schema.transform(errorStructSchema, Schema.Any, {
31
+ decode: (errorStruct) => {
32
+ const { message, stack } = errorStruct
33
+ const previousLimit = Error.stackTraceLimit
34
+ Error.stackTraceLimit = 0
35
+ // eslint-disable-next-line unicorn/error-message
36
+ const error = new Error('')
37
+ Error.stackTraceLimit = previousLimit
38
+ error.message = message
39
+ error.stack = stack
40
+ return error
41
+ },
42
+ encode: (anyError) => ({
43
+ message: objectToString(anyError).replace(/^Error: /, ''),
44
+ stack: anyError.stack,
45
+ }),
46
+ }) {}
47
+
48
+ export const encodeWithTransferables =
49
+ <A, I, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions | undefined) =>
50
+ (a: A, overrideOptions?: ParseOptions | undefined): Effect.Effect<[I, Transferable[]], ParseError, R> =>
51
+ Effect.gen(function* () {
52
+ const collector = yield* Transferable.makeCollector
53
+
54
+ const encoded: I = yield* Schema.encode(schema, options)(a, overrideOptions).pipe(
55
+ Effect.provideService(Transferable.Collector, collector),
56
+ )
57
+
58
+ return [encoded, collector.unsafeRead() as Transferable[]]
59
+ })
@@ -1,7 +1,7 @@
1
1
  export * from 'effect/Stream'
2
2
 
3
3
  import type { Chunk } from 'effect'
4
- import { Effect, pipe, Stream } from 'effect'
4
+ import { Effect, Option, pipe, Ref, Stream } from 'effect'
5
5
 
6
6
  export const tapLog = <R, E, A>(stream: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>
7
7
  tapChunk<never, never, A, void>(Effect.forEach((_) => Effect.succeed(console.log(_))))(stream)
@@ -20,3 +20,39 @@ export const tapChunk =
20
20
  Effect.map(() => chunks),
21
21
  ),
22
22
  )
23
+
24
+ const isIdentity = <A>(a1: A, a2: A): boolean => a1 === a2
25
+
26
+ export const skipRepeated =
27
+ <A>(isEqual: (prevEl: A, newEl: A) => boolean = isIdentity) =>
28
+ <R, E>(stream: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>
29
+ skipRepeated_(stream, isEqual)
30
+
31
+ export const skipRepeated_ = <R, E, A>(
32
+ stream: Stream.Stream<A, E, R>,
33
+ isEqual: (prevEl: A, newEl: A) => boolean = isIdentity,
34
+ ): Stream.Stream<A, E, R> =>
35
+ pipe(
36
+ Ref.make<Option.Option<A>>(Option.none()),
37
+ Stream.fromEffect,
38
+ Stream.flatMap((ref) =>
39
+ pipe(
40
+ stream,
41
+ Stream.filterEffect((el) =>
42
+ pipe(
43
+ Ref.get(ref),
44
+ Effect.flatMap((prevEl) => {
45
+ if (prevEl._tag === 'None' || isEqual(prevEl.value, el) === false) {
46
+ return pipe(
47
+ Ref.set(ref, Option.some(el)),
48
+ Effect.map(() => true),
49
+ )
50
+ } else {
51
+ return Effect.succeed(false)
52
+ }
53
+ }),
54
+ ),
55
+ ),
56
+ ),
57
+ ),
58
+ )
@@ -1,15 +1,30 @@
1
- import type { Effect } from 'effect'
2
- import { pipe, Stream, SubscriptionRef } from 'effect'
1
+ import { Chunk, Effect, pipe, Stream, SubscriptionRef } from 'effect'
3
2
  import { dual } from 'effect/Function'
3
+ import type { Predicate, Refinement } from 'effect/Predicate'
4
4
 
5
5
  export * from 'effect/SubscriptionRef'
6
6
 
7
7
  export const changeStreamIncludingCurrent = <A>(sref: SubscriptionRef.SubscriptionRef<A>) =>
8
8
  pipe(Stream.fromEffect(SubscriptionRef.get(sref)), Stream.concat(sref.changes))
9
9
 
10
- export const waitUntil = dual<
11
- <A>(predicate: (a: A) => boolean) => (sref: SubscriptionRef.SubscriptionRef<A>) => Effect.Effect<void>,
12
- <A>(sref: SubscriptionRef.SubscriptionRef<A>, predicate: (a: A) => boolean) => Effect.Effect<void>
13
- >(2, <A>(sref: SubscriptionRef.SubscriptionRef<A>, predicate: (a: A) => boolean) =>
14
- pipe(changeStreamIncludingCurrent(sref), Stream.filter(predicate), Stream.take(1), Stream.runDrain),
10
+ export const waitUntil: {
11
+ <A, B extends A>(
12
+ refinement: Refinement<NoInfer<A>, B>,
13
+ ): (sref: SubscriptionRef.SubscriptionRef<A>) => Effect.Effect<B, never, never>
14
+ <A, B extends A>(
15
+ predicate: Predicate<B>,
16
+ ): (sref: SubscriptionRef.SubscriptionRef<A>) => Effect.Effect<A, never, never>
17
+ <A, B extends A>(
18
+ sref: SubscriptionRef.SubscriptionRef<A>,
19
+ refinement: Refinement<NoInfer<A>, B>,
20
+ ): Effect.Effect<B, never, never>
21
+ <A, B extends A>(sref: SubscriptionRef.SubscriptionRef<A>, predicate: Predicate<B>): Effect.Effect<A, never, never>
22
+ } = dual(2, <A>(sref: SubscriptionRef.SubscriptionRef<A>, predicate: (a: A) => boolean) =>
23
+ pipe(
24
+ changeStreamIncludingCurrent(sref),
25
+ Stream.filter(predicate),
26
+ Stream.take(1),
27
+ Stream.runCollect,
28
+ Effect.map(Chunk.unsafeHead),
29
+ ),
15
30
  )
@@ -3,18 +3,36 @@ import { Deferred, Effect, Runtime } from 'effect'
3
3
 
4
4
  // See https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API
5
5
  export const withLock =
6
- (lockName: string, options?: Omit<LockOptions, 'signal'>) =>
7
- <Ctx, E, A>(eff: Effect.Effect<A, E, Ctx>): Effect.Effect<A | void, E, Ctx> =>
6
+ <E2>({
7
+ lockName,
8
+ onTaken,
9
+ options,
10
+ }: {
11
+ lockName: string
12
+ onTaken?: Effect.Effect<void, E2>
13
+ options?: Omit<LockOptions, 'signal'>
14
+ }) =>
15
+ <Ctx, E, A>(eff: Effect.Effect<A, E, Ctx>): Effect.Effect<A | void, E | E2, Ctx> =>
8
16
  Effect.gen(function* ($) {
9
17
  const runtime = yield* $(Effect.runtime<Ctx>())
10
18
 
11
19
  const exit = yield* $(
12
- Effect.tryPromise<Exit.Exit<A, E>, E>({
20
+ Effect.tryPromise<Exit.Exit<A, E>, E | E2>({
13
21
  try: (signal) => {
22
+ if (signal.aborted) return 'aborted' as never
23
+
14
24
  // NOTE The 'signal' and 'ifAvailable' options cannot be used together.
15
25
  const requestOptions = options?.ifAvailable === true ? options : { ...options, signal }
16
26
  return navigator.locks.request(lockName, requestOptions, async (lock) => {
17
- if (lock === null) return
27
+ if (lock === null) {
28
+ if (onTaken) {
29
+ const exit = await Runtime.runPromiseExit(runtime)(onTaken)
30
+ if (exit._tag === 'Failure') {
31
+ return exit
32
+ }
33
+ }
34
+ return
35
+ }
18
36
 
19
37
  // TODO also propagate Effect interruption to the execution
20
38
  return Runtime.runPromiseExit(runtime)(eff)
@@ -33,25 +51,35 @@ export const withLock =
33
51
 
34
52
  export const waitForDeferredLock = (deferred: Deferred.Deferred<void>, lockName: string) =>
35
53
  Effect.async<void>((cb, signal) => {
36
- navigator.locks.request(lockName, { signal, mode: 'exclusive', ifAvailable: false }, async (_lock) => {
37
- // immediately continuing calling Effect since we have the lock
38
- cb(Effect.void)
54
+ if (signal.aborted) return
39
55
 
40
- // the code below is still running
56
+ navigator.locks
57
+ .request(lockName, { signal, mode: 'exclusive', ifAvailable: false }, (_lock) => {
58
+ // immediately continuing calling Effect since we have the lock
59
+ cb(Effect.void)
41
60
 
42
- // holding lock until deferred is resolved
43
- await Effect.runPromise(Deferred.await(deferred))
44
- })
61
+ // the code below is still running
62
+
63
+ // holding lock until deferred is resolved
64
+ return Effect.runPromise(Deferred.await(deferred))
65
+ })
66
+ .catch((error) => {
67
+ if (error.code === 20 && error.message === 'signal is aborted without reason') {
68
+ // Given signal interruption is handled via Effect, we can ignore this case
69
+ } else {
70
+ throw error
71
+ }
72
+ })
45
73
  })
46
74
 
47
75
  export const tryGetDeferredLock = (deferred: Deferred.Deferred<void>, lockName: string) =>
48
76
  Effect.async<boolean>((cb) => {
49
- navigator.locks.request(lockName, { mode: 'exclusive', ifAvailable: true }, async (lock) => {
77
+ navigator.locks.request(lockName, { mode: 'exclusive', ifAvailable: true }, (lock) => {
50
78
  cb(Effect.succeed(lock !== null))
51
79
 
52
80
  // the code below is still running
53
81
 
54
82
  // holding lock until deferred is resolved
55
- await Effect.runPromise(Deferred.await(deferred))
83
+ return Effect.runPromise(Deferred.await(deferred))
56
84
  })
57
85
  })
@@ -36,6 +36,8 @@ export {
36
36
  HashSet,
37
37
  MutableHashSet,
38
38
  Option,
39
+ LogLevel,
40
+ Logger,
39
41
  Layer,
40
42
  STM,
41
43
  TRef,
@@ -55,6 +57,7 @@ export {
55
57
  TreeFormatter,
56
58
  AST as SchemaAST,
57
59
  Pretty as SchemaPretty,
60
+ Equivalence as SchemaEquivalence,
58
61
  Serializable,
59
62
  JSONSchema,
60
63
  ParseResult,
@@ -64,6 +67,7 @@ export * as OtelTracer from '@effect/opentelemetry/Tracer'
64
67
 
65
68
  export { Transferable, FileSystem, Worker, WorkerError, WorkerRunner, Terminal, HttpServer } from '@effect/platform'
66
69
  export { BrowserWorker, BrowserWorkerRunner } from '@effect/platform-browser'
70
+ export * as PortPlatformRunner from './port-platform-runner.js'
67
71
 
68
72
  export * as Effect from './Effect.js'
69
73
  export * as Schedule from './Schedule.js'
@@ -0,0 +1,73 @@
1
+ import { WorkerError } from '@effect/platform/WorkerError'
2
+ import * as Runner from '@effect/platform/WorkerRunner'
3
+ import { Deferred } from 'effect'
4
+ import * as Cause from 'effect/Cause'
5
+ import * as Effect from 'effect/Effect'
6
+ import * as Layer from 'effect/Layer'
7
+ import * as Queue from 'effect/Queue'
8
+ import * as Schedule from 'effect/Schedule'
9
+
10
+ const platformRunnerImpl = (port: MessagePort) =>
11
+ Runner.PlatformRunner.of({
12
+ [Runner.PlatformRunnerTypeId]: Runner.PlatformRunnerTypeId,
13
+ start: <I, O>(shutdown: Effect.Effect<void>) => {
14
+ return Effect.gen(function* () {
15
+ const queue = yield* Queue.unbounded<readonly [portId: number, message: I]>()
16
+
17
+ const latch = yield* Deferred.make<void>()
18
+
19
+ yield* Effect.async<never, WorkerError>((resume) => {
20
+ const onMessage = (msg: MessageEvent<Runner.BackingRunner.Message<I>>) => {
21
+ const message = msg.data
22
+ if (message[0] === 0) {
23
+ queue.unsafeOffer([0, message[1]])
24
+ } else {
25
+ Effect.runFork(shutdown)
26
+ }
27
+ }
28
+
29
+ const onError = (error: any) => {
30
+ resume(new WorkerError({ reason: 'decode', error }))
31
+ }
32
+
33
+ port.addEventListener('message', onMessage)
34
+ port.addEventListener('messageerror', onError)
35
+ port.addEventListener('error', onError)
36
+
37
+ Deferred.unsafeDone(latch, Effect.void)
38
+
39
+ return Effect.sync(() => {
40
+ port.removeEventListener('message', onMessage as any)
41
+ port.removeEventListener('error', onError as any)
42
+ })
43
+ }).pipe(
44
+ Effect.tapErrorCause((cause) => (Cause.isInterruptedOnly(cause) ? Effect.void : Effect.logDebug(cause))),
45
+ Effect.retry(Schedule.forever),
46
+ Effect.annotateLogs({
47
+ package: '@livestore/utils/effect',
48
+ module: 'PortPlatformRunner',
49
+ }),
50
+ Effect.interruptible,
51
+ Effect.forkScoped,
52
+ )
53
+
54
+ yield* Deferred.await(latch)
55
+
56
+ port.start()
57
+
58
+ const send = (_portId: number, message: O, transfers?: ReadonlyArray<unknown>) =>
59
+ Effect.try({
60
+ try: () => port.postMessage([1, message], transfers as any),
61
+ catch: (error) => new WorkerError({ reason: 'send', error }),
62
+ }).pipe(Effect.catchTag('WorkerError', Effect.orDie))
63
+
64
+ // ready
65
+ port.postMessage([0])
66
+
67
+ return { queue, send }
68
+ })
69
+ },
70
+ })
71
+
72
+ /** @internal */
73
+ export const layer = (port: MessagePort) => Layer.succeed(Runner.PlatformRunner, platformRunnerImpl(port))
package/src/index.ts CHANGED
@@ -7,11 +7,14 @@ export * from './NoopTracer.js'
7
7
  export * from './set.js'
8
8
  export * from './browser.js'
9
9
  export * from './Deferred.js'
10
+ export * from './misc.js'
10
11
  export * as base64 from './base64.js'
11
12
  export { default as prettyBytes } from 'pretty-bytes'
12
13
 
13
14
  import type * as otel from '@opentelemetry/api'
14
15
 
16
+ import { objectToString } from './misc.js'
17
+
15
18
  export * as dateFns from 'date-fns'
16
19
 
17
20
  export type Prettify<T> = T extends infer U ? { [K in keyof U]: Prettify<U[K]> } : never
@@ -72,23 +75,6 @@ export const prop =
72
75
  (obj: T): T[K] =>
73
76
  obj[key]
74
77
 
75
- export const objectToString = (error: any): string => {
76
- const stack = error.stack
77
- const str = error.toString()
78
- const stackStr = stack ? `\n${stack}` : ''
79
- if (str !== '[object Object]') return str + stackStr
80
-
81
- try {
82
- return JSON.stringify({ ...error, stack }, null, 2)
83
- } catch (e: any) {
84
- console.log(error)
85
-
86
- return 'Error while printing error: ' + e
87
- }
88
- }
89
-
90
- export const errorToString = objectToString
91
-
92
78
  export const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1)
93
79
 
94
80
  export const isReadonlyArray = <I, T>(value: ReadonlyArray<I> | T): value is ReadonlyArray<I> => Array.isArray(value)
@@ -236,8 +222,12 @@ export const memoizeByRef = <T extends (arg: any) => any>(fn: T): T => {
236
222
  }) as any
237
223
  }
238
224
 
239
- export const isNonEmptyString = (str: string | undefined | null) => str === undefined || str === null || str === ''
225
+ export const isNonEmptyString = (str: string | undefined | null): str is string => {
226
+ return typeof str === 'string' && str.length > 0
227
+ }
240
228
 
241
229
  export const isPromise = (value: any): value is Promise<unknown> => typeof value?.then === 'function'
242
230
 
243
231
  export const isIterable = <T>(value: any): value is Iterable<T> => typeof value?.[Symbol.iterator] === 'function'
232
+
233
+ export { objectToString as errorToString } from './misc.js'
package/src/misc.ts ADDED
@@ -0,0 +1,12 @@
1
+ export const objectToString = (error: any): string => {
2
+ const str = error?.toString()
3
+ if (str !== '[object Object]') return str
4
+
5
+ try {
6
+ return JSON.stringify(error, null, 2)
7
+ } catch (e: any) {
8
+ console.log(error)
9
+
10
+ return 'Error while printing error: ' + e
11
+ }
12
+ }