liminal 0.17.14 → 0.17.16

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 (126) hide show
  1. package/Actor.ts +22 -34
  2. package/ActorHandle.ts +34 -0
  3. package/ActorNamespace.ts +188 -0
  4. package/ActorRuntime.ts +449 -0
  5. package/ActorTransport.ts +8 -6
  6. package/Audition.ts +87 -40
  7. package/BrowserActorNamespace.ts +257 -0
  8. package/CHANGELOG.md +17 -0
  9. package/Client.ts +374 -197
  10. package/ClientDirectory.ts +71 -49
  11. package/ClientHandle.ts +9 -7
  12. package/ClientHandleEncoders.ts +15 -0
  13. package/Fn.ts +94 -0
  14. package/Method.ts +11 -21
  15. package/Protocol.ts +44 -36
  16. package/Reducer.ts +22 -0
  17. package/Tracing.ts +45 -0
  18. package/dist/Actor.d.ts +3 -5
  19. package/dist/Actor.js +5 -9
  20. package/dist/Actor.js.map +1 -1
  21. package/dist/ActorHandle.d.ts +12 -0
  22. package/dist/ActorHandle.js +4 -0
  23. package/dist/ActorHandle.js.map +1 -0
  24. package/dist/ActorNamespace.d.ts +25 -0
  25. package/dist/ActorNamespace.js +60 -0
  26. package/dist/ActorNamespace.js.map +1 -0
  27. package/dist/ActorRuntime.d.ts +20 -0
  28. package/dist/ActorRuntime.js +210 -0
  29. package/dist/ActorRuntime.js.map +1 -0
  30. package/dist/ActorTransport.d.ts +5 -4
  31. package/dist/Audition.d.ts +16 -9
  32. package/dist/Audition.js +25 -9
  33. package/dist/Audition.js.map +1 -1
  34. package/dist/BrowserActorNamespace.d.ts +39 -0
  35. package/dist/BrowserActorNamespace.js +134 -0
  36. package/dist/BrowserActorNamespace.js.map +1 -0
  37. package/dist/Client.d.ts +26 -16
  38. package/dist/Client.js +186 -109
  39. package/dist/Client.js.map +1 -1
  40. package/dist/ClientDirectory.d.ts +15 -7
  41. package/dist/ClientDirectory.js +32 -23
  42. package/dist/ClientDirectory.js.map +1 -1
  43. package/dist/ClientHandle.d.ts +5 -4
  44. package/dist/ClientHandleEncoders.d.ts +7 -0
  45. package/dist/ClientHandleEncoders.js +2 -0
  46. package/dist/ClientHandleEncoders.js.map +1 -0
  47. package/dist/Fn.d.ts +24 -0
  48. package/dist/Fn.js +2 -0
  49. package/dist/Fn.js.map +1 -0
  50. package/dist/Method.d.ts +9 -14
  51. package/dist/Method.js +0 -1
  52. package/dist/Method.js.map +1 -1
  53. package/dist/Protocol.d.ts +19 -22
  54. package/dist/Protocol.js +20 -15
  55. package/dist/Protocol.js.map +1 -1
  56. package/dist/Reducer.d.ts +11 -0
  57. package/dist/Reducer.js +2 -0
  58. package/dist/Reducer.js.map +1 -0
  59. package/dist/Tracing.d.ts +37 -0
  60. package/dist/Tracing.js +33 -0
  61. package/dist/Tracing.js.map +1 -0
  62. package/dist/errors.d.ts +0 -4
  63. package/dist/errors.js.map +1 -1
  64. package/dist/experimental/L/append.js +1 -1
  65. package/dist/experimental/L/append.js.map +1 -1
  66. package/dist/experimental/L/history.js +1 -1
  67. package/dist/experimental/L/history.js.map +1 -1
  68. package/dist/experimental/TaggedTemplateFunction.js +1 -1
  69. package/dist/experimental/TaggedTemplateFunction.js.map +1 -1
  70. package/dist/index.common.d.ts +12 -0
  71. package/dist/index.common.js +13 -0
  72. package/dist/index.common.js.map +1 -0
  73. package/dist/index.d.ts +4 -11
  74. package/dist/index.js +4 -11
  75. package/dist/index.js.map +1 -1
  76. package/dist/index.non-workerd.d.ts +1 -0
  77. package/dist/index.non-workerd.js +2 -0
  78. package/dist/index.non-workerd.js.map +1 -0
  79. package/dist/package.json +20 -19
  80. package/dist/tsconfig.tsbuildinfo +1 -1
  81. package/errors.ts +0 -6
  82. package/experimental/L/append.ts +1 -1
  83. package/experimental/L/history.ts +1 -1
  84. package/experimental/TaggedTemplateFunction.ts +1 -1
  85. package/index.common.ts +12 -0
  86. package/index.non-workerd.ts +1 -0
  87. package/index.ts +4 -11
  88. package/package.json +11 -23
  89. package/tsconfig.json +1 -1
  90. package/vitest.config.ts +7 -0
  91. package/Accumulator.ts +0 -103
  92. package/F.ts +0 -10
  93. package/_diagnostic.ts +0 -3
  94. package/_util/Mutex.ts +0 -13
  95. package/_util/schema.ts +0 -7
  96. package/browser/BrowserActorNamespace.ts +0 -213
  97. package/browser/index.ts +0 -1
  98. package/dist/Accumulator.d.ts +0 -22
  99. package/dist/Accumulator.js +0 -37
  100. package/dist/Accumulator.js.map +0 -1
  101. package/dist/F.d.ts +0 -4
  102. package/dist/F.js +0 -2
  103. package/dist/F.js.map +0 -1
  104. package/dist/_diagnostic.d.ts +0 -4
  105. package/dist/_diagnostic.js +0 -3
  106. package/dist/_diagnostic.js.map +0 -1
  107. package/dist/_util/Mutex.d.ts +0 -7
  108. package/dist/_util/Mutex.js +0 -9
  109. package/dist/_util/Mutex.js.map +0 -1
  110. package/dist/_util/schema.d.ts +0 -4
  111. package/dist/_util/schema.js +0 -5
  112. package/dist/_util/schema.js.map +0 -1
  113. package/dist/browser/BrowserActorNamespace.d.ts +0 -16
  114. package/dist/browser/BrowserActorNamespace.js +0 -112
  115. package/dist/browser/BrowserActorNamespace.js.map +0 -1
  116. package/dist/browser/index.d.ts +0 -1
  117. package/dist/browser/index.js +0 -2
  118. package/dist/browser/index.js.map +0 -1
  119. package/dist/workerd/WorkerdActorNamespace.d.ts +0 -25
  120. package/dist/workerd/WorkerdActorNamespace.js +0 -146
  121. package/dist/workerd/WorkerdActorNamespace.js.map +0 -1
  122. package/dist/workerd/index.d.ts +0 -1
  123. package/dist/workerd/index.js +0 -2
  124. package/dist/workerd/index.js.map +0 -1
  125. package/workerd/WorkerdActorNamespace.ts +0 -362
  126. package/workerd/index.ts +0 -1
@@ -18,7 +18,7 @@ export const raw = Effect.fnUntraced(function* <Substitutions extends Array<unkn
18
18
  ): Effect.fn.Return<string, ExtractE<Substitutions[number]>, ExtractR<Substitutions[number]>> {
19
19
  return String.raw(
20
20
  template,
21
- ...(yield* Effect.all(substitutions.map((v) => (Effect.isEffect(v) ? v : Effect.succeed(v)))) as Effect.Effect<
21
+ ...(yield* Effect.forEach(substitutions, (v) => (Effect.isEffect(v) ? v : Effect.succeed(v))) as Effect.Effect<
22
22
  Array<string>,
23
23
  ExtractE<Substitutions[number]>,
24
24
  ExtractR<Substitutions[number]>
@@ -0,0 +1,12 @@
1
+ export * as Actor from "./Actor.ts"
2
+ export * as Audition from "./Audition.ts"
3
+ export * as Client from "./Client.ts"
4
+ export * as ClientDirectory from "./ClientDirectory.ts"
5
+ export * as ClientHandle from "./ClientHandle.ts"
6
+ export * as Protocol from "./Protocol.ts"
7
+ export * from "./ActorTransport.ts"
8
+ export * from "./Fn.ts"
9
+ export * from "./Method.ts"
10
+ export * from "./Reducer.ts"
11
+ export * from "./errors.ts"
12
+ export * as BrowserActorNamespace from "./BrowserActorNamespace.ts"
@@ -0,0 +1 @@
1
+ export * from "./index.common.ts"
package/index.ts CHANGED
@@ -1,11 +1,4 @@
1
- export * as Accumulator from "./Accumulator.ts"
2
- export * as Actor from "./Actor.ts"
3
- export * as Audition from "./Audition.ts"
4
- export * as Client from "./Client.ts"
5
- export * as ClientDirectory from "./ClientDirectory.ts"
6
- export * as ClientHandle from "./ClientHandle.ts"
7
- export * as Method from "./Method.ts"
8
- export * as Protocol from "./Protocol.ts"
9
- export * from "./ActorTransport.ts"
10
- export * from "./F.ts"
11
- export * from "./errors.ts"
1
+ export * from "./index.common.ts"
2
+ export * as ActorNamespace from "./ActorNamespace.ts"
3
+ export * as ActorRuntime from "./ActorRuntime.ts"
4
+ export * from "./ActorHandle.ts"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liminal",
3
- "version": "0.17.14",
3
+ "version": "0.17.16",
4
4
  "description": "Effect x Actors",
5
5
  "bugs": {
6
6
  "url": "https://github.com/crosshatch/liminal/issues"
@@ -15,33 +15,21 @@
15
15
  "sideEffects": false,
16
16
  "exports": {
17
17
  ".": {
18
- "types": "./index.ts",
18
+ "workerd": "./dist/index.js",
19
+ "browser": "./dist/index.non-workerd.js",
20
+ "node": "./dist/index.non-workerd.js",
19
21
  "default": "./dist/index.js"
20
22
  },
21
- "./*": {
22
- "types": "./*.ts",
23
- "default": "./dist/*.js"
24
- },
25
- "./browser": {
26
- "types": "./browser/index.ts",
27
- "default": "./dist/browser/index.js"
28
- },
29
- "./experimental": {
30
- "types": "./experimental/index.ts",
31
- "default": "./dist/experimental/index.js"
32
- },
33
- "./workerd": {
34
- "types": "./workerd/index.ts",
35
- "default": "./dist/workerd/index.js"
36
- },
23
+ "./*": "./dist/*.js",
24
+ "./experimental": "./dist/experimental/index.js",
37
25
  "./package.json": "./package.json"
38
26
  },
39
27
  "peerDependencies": {
40
28
  "@cloudflare/workers-types": "^4.20260414.1",
41
- "@effect/platform-browser": "4.0.0-beta.57",
42
- "@effect/sql-d1": "4.0.0-beta.57",
43
- "effect": "4.0.0-beta.57",
44
- "effect-workerd": "0.0.4",
45
- "liminal-util": "0.0.9"
29
+ "@effect/platform-browser": "4.0.0-beta.83",
30
+ "@effect/sql-d1": "4.0.0-beta.83",
31
+ "effect": "4.0.0-beta.83",
32
+ "liminal-util": "0.0.10",
33
+ "effect-workerd": "0.0.6"
46
34
  }
47
35
  }
package/tsconfig.json CHANGED
@@ -6,6 +6,6 @@
6
6
  "types": ["@cloudflare/workers-types"]
7
7
  },
8
8
  "include": [".", "package.json"],
9
- "exclude": ["dist"],
9
+ "exclude": ["dist", "vitest.config.ts"],
10
10
  "references": [{ "path": "../effect-workerd" }, { "path": "../liminal-util" }]
11
11
  }
@@ -0,0 +1,7 @@
1
+ import { mergeConfig, type ViteUserConfig } from "vitest/config"
2
+
3
+ import config from "../konfik/vitest.ts"
4
+
5
+ export default mergeConfig(config, {
6
+ test: { name: "liminal" },
7
+ } satisfies ViteUserConfig)
package/Accumulator.ts DELETED
@@ -1,103 +0,0 @@
1
- import { Deferred, Types, Option, Ref, PubSub, Stream, Effect, Context, Layer, Semaphore } from "effect"
2
-
3
- import { diagnostic } from "./_diagnostic.ts"
4
-
5
- const { debug } = diagnostic("Accumulator")
6
-
7
- const TypeId = "~liminal/Accumulator" as const
8
-
9
- export interface Service<State> {
10
- readonly ref: Ref.Ref<State>
11
-
12
- readonly pubsub: PubSub.PubSub<State>
13
- }
14
-
15
- export interface AccumulatorLayerConfig<Item, E, R, State, E2, R2, E3, R3> {
16
- readonly source: Stream.Stream<Item, E, R>
17
-
18
- readonly reduce: (item: Item) => (state: State) => Effect.Effect<State, E2, R2>
19
-
20
- readonly initial: (item: Item) => Effect.Effect<Option.Option<State>, E3, R3>
21
- }
22
-
23
- export type Reduce<State, Item, K extends Types.Tags<Item> = Types.Tags<Item>, E = never, R = never> = (
24
- item: Types.ExtractTag<Item, K>,
25
- ) => (accumulator: State) => Effect.Effect<State, E, R>
26
-
27
- export interface Accumulator<Self, Id extends string, State> extends Context.Service<Self, Service<State>> {
28
- new (_: never): Context.ServiceClass.Shape<Id, Service<State>>
29
-
30
- readonly [TypeId]: typeof TypeId
31
-
32
- readonly get: Effect.Effect<State, never, Self>
33
-
34
- readonly stream: Stream.Stream<State, never, Self>
35
-
36
- readonly reducer: <Item>() => <K extends Types.Tags<Item>, E, R>(
37
- _tag: K,
38
- f: Reduce<State, Item, K, E, R>,
39
- ) => Reduce<State, Item, K, E, R>
40
-
41
- readonly layer: <Item, E, R, E2, R2, E3, R3>(
42
- config: AccumulatorLayerConfig<Item, E, R, State, E2, R2, E3, R3>,
43
- ) => Layer.Layer<Self, E | E2 | E3, R | R2 | R3>
44
- }
45
-
46
- export const Service =
47
- <Self, State>() =>
48
- <Id extends string>(id: Id): Accumulator<Self, Id, State> => {
49
- const tag = Context.Service<Self, Service<State>>()(id)
50
-
51
- const get = tag.asEffect().pipe(
52
- Effect.map(({ ref }) => ref),
53
- Effect.flatMap(Ref.get),
54
- )
55
-
56
- const stream = tag.asEffect().pipe(
57
- Effect.map(({ pubsub }) => Stream.fromPubSub(pubsub)),
58
- Stream.unwrap,
59
- )
60
-
61
- const reducer =
62
- <Item>() =>
63
- <K extends Types.Tags<Item>, E, R>(_tag: K, f: Reduce<State, Item, K, E, R>): Reduce<State, Item, K, E, R> =>
64
- f
65
-
66
- const layer = <Item, E, R, E2, R2, E3, R3>({
67
- source,
68
- initial,
69
- reduce,
70
- }: AccumulatorLayerConfig<Item, E, R, State, E2, R2, E3, R3>): Layer.Layer<Self, E | E2 | E3, R | R2 | R3> =>
71
- Effect.gen(function* () {
72
- const semaphore = yield* Semaphore.make(1)
73
- const deferred = yield* Deferred.make<State>()
74
- const pubsub = yield* PubSub.unbounded<State>({ replay: 1 })
75
- yield* source.pipe(
76
- Stream.runForEach(
77
- Effect.fn(function* (item) {
78
- if (!(yield* Deferred.isDone(deferred))) {
79
- const match = yield* initial(item)
80
- if (Option.isSome(match)) {
81
- const { value } = match
82
- yield* Deferred.succeed(deferred, value)
83
- yield* debug("InitializedState", { state: value })
84
- }
85
- return
86
- }
87
- const current = yield* Ref.get(ref)
88
- const reduced = yield* reduce(item)(current)
89
- yield* Ref.set(ref, reduced)
90
- yield* PubSub.publish(pubsub, reduced)
91
- yield* debug("ReducedState", { item, previous: current, current: reduced })
92
- }, semaphore.withPermits(1)),
93
- ),
94
- Effect.forkScoped,
95
- )
96
- const initial_ = yield* Deferred.await(deferred)
97
- const ref = yield* Ref.make(initial_)
98
- yield* PubSub.publish(pubsub, initial_)
99
- return { ref, pubsub }
100
- }).pipe(Layer.effect(tag))
101
-
102
- return Object.assign(tag, { [TypeId]: TypeId, get, stream, reducer, layer })
103
- }
package/F.ts DELETED
@@ -1,10 +0,0 @@
1
- import { Effect } from "effect"
2
-
3
- import type { FError } from "./errors.ts"
4
- import type { ProtocolDefinition } from "./Protocol.ts"
5
-
6
- export type F<Self, D extends ProtocolDefinition> = <Method extends keyof D["methods"]>(
7
- method: Method,
8
- ) => (
9
- payload: D["methods"][Method]["payload"]["Type"],
10
- ) => Effect.Effect<D["methods"][Method]["success"]["Type"], FError<D>, Self>
package/_diagnostic.ts DELETED
@@ -1,3 +0,0 @@
1
- import { factory } from "liminal-util/Diagnostic"
2
-
3
- export const diagnostic = factory("liminal")
package/_util/Mutex.ts DELETED
@@ -1,13 +0,0 @@
1
- import { Context, Effect, Layer, Semaphore } from "effect"
2
-
3
- export class Mutex extends Context.Service<
4
- Mutex,
5
- <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
6
- >()("liminal/Mutex") {}
7
-
8
- export const layer = Effect.gen(function* () {
9
- const mutex = yield* Semaphore.make(1)
10
- return mutex.withPermits(1)
11
- }).pipe(Layer.effect(Mutex))
12
-
13
- export const task = <A, E, R>(effect: Effect.Effect<A, E, R>) => Mutex.asEffect().pipe(Effect.flatMap((f) => f(effect)))
package/_util/schema.ts DELETED
@@ -1,7 +0,0 @@
1
- import { Schema as S, flow } from "effect"
2
-
3
- export type TopFromString = S.Codec<any, string, any, any>
4
-
5
- const toJsonStringCodec = flow(S.toCodecJson, S.fromJsonString)
6
- export const encodeJsonString = flow(toJsonStringCodec, S.encodeEffect)
7
- export const decodeJsonString = flow(toJsonStringCodec, S.decodeUnknownEffect)
@@ -1,213 +0,0 @@
1
- import { BrowserWorkerRunner } from "@effect/platform-browser"
2
- import { Cause, Effect, Exit, Layer, Option, Ref, Schema as S, Scope, Semaphore, Stream } from "effect"
3
- import { WorkerRunner } from "effect/unstable/workers"
4
- import { logCause } from "liminal-util/logCause"
5
-
6
- import type { TopFromString } from "../_util/schema.ts"
7
- import type { Actor } from "../Actor.ts"
8
- import type { ActorTransport } from "../ActorTransport.ts"
9
- import type { ClientHandle } from "../ClientHandle.ts"
10
- import type { ProtocolDefinition } from "../Protocol.ts"
11
-
12
- import { diagnostic } from "../_diagnostic.ts"
13
- import * as ClientDirectory from "../ClientDirectory.ts"
14
- import * as Method from "../Method.ts"
15
-
16
- const { debug, span } = diagnostic("browser.BrowserActorNamespace")
17
-
18
- export interface Introduction<Name extends TopFromString, AttachmentFields extends S.Struct.Fields> {
19
- readonly port: MessagePort
20
- readonly name: Name["Type"]
21
- readonly attachments: S.Struct<AttachmentFields>["Type"]
22
- }
23
-
24
- export const make = Effect.fnUntraced(function* <
25
- ActorSelf,
26
- ActorId extends string,
27
- Name extends TopFromString,
28
- AttachmentFields extends S.Struct.Fields,
29
- ClientSelf,
30
- ClientId extends string,
31
- D extends ProtocolDefinition,
32
- const Handlers extends Method.Handlers<D["methods"], any>,
33
- A,
34
- E,
35
- R,
36
- IntroductionE,
37
- IntroductionR,
38
- >({
39
- actor,
40
- handlers,
41
- onConnect,
42
- introductions,
43
- }: {
44
- readonly actor: Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>
45
- readonly handlers: Handlers
46
- readonly onConnect: Effect.Effect<A, E, R>
47
- readonly introductions: Stream.Stream<Introduction<Name, AttachmentFields>, IntroductionE, IntroductionR>
48
- }) {
49
- const {
50
- definition: {
51
- client: {
52
- protocol: { Client: ClientM, Actor },
53
- key: expected,
54
- },
55
- name: Name,
56
- },
57
- } = actor
58
-
59
- const validateClientMessage = S.decodeUnknownEffect(S.toType(ClientM))
60
- const encodeName = S.encodeEffect(Name)
61
-
62
- interface Entry {
63
- readonly directory: ClientDirectory.ClientDirectory<MessagePort, ActorSelf, AttachmentFields, D>
64
- readonly mutex: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
65
- }
66
-
67
- const entries: Record<string, Entry> = {}
68
- const runners = new Map<MessagePort, WorkerRunner.WorkerRunner<typeof Actor.Type, typeof ClientM.Type>>()
69
-
70
- const transport: ActorTransport<MessagePort, AttachmentFields, D> = {
71
- send: (port, event) => runners.get(port)?.send(0, event) ?? Effect.void,
72
- close: () => Effect.void,
73
- snapshot: () => Effect.void,
74
- }
75
-
76
- const useEntries = yield* Semaphore.make(1).pipe(Effect.map((v) => v.withPermits(1)))
77
-
78
- const getEntry = Effect.fnUntraced(function* (key: string) {
79
- const existing = entries[key]
80
- if (existing) return existing
81
- const directory = ClientDirectory.make(actor, transport)
82
- const semaphore = yield* Semaphore.make(1)
83
- const fresh = {
84
- directory,
85
- mutex: semaphore.withPermits(1),
86
- }
87
- entries[key] = fresh
88
- return fresh
89
- }, useEntries)
90
-
91
- const outerScope = yield* Scope.Scope
92
-
93
- yield* introductions.pipe(
94
- Stream.runForEach(
95
- Effect.fnUntraced(function* ({ name, port, attachments }) {
96
- yield* debug("IntroductionReceived", { name })
97
-
98
- const stateRef = yield* Ref.make<
99
- Option.Option<{
100
- readonly key: string
101
- readonly entry: Entry
102
- readonly currentClient: ClientHandle<ActorSelf, AttachmentFields, D>
103
- readonly ActorLive: Layer.Layer<ActorSelf>
104
- }>
105
- >(Option.none())
106
-
107
- const scope = yield* Scope.fork(outerScope, "sequential")
108
- const closeScope = Scope.close(scope, Exit.void)
109
-
110
- const backing = yield* BrowserWorkerRunner.make(port).start<typeof Actor.Type, typeof ClientM.Type>()
111
- runners.set(port, backing)
112
-
113
- yield* Scope.addFinalizer(
114
- scope,
115
- Effect.gen(function* () {
116
- runners.delete(port)
117
- const state = yield* Ref.get(stateRef)
118
- if (Option.isSome(state)) {
119
- const {
120
- key,
121
- entry: { directory },
122
- } = state.value
123
- yield* directory.unregister(port)
124
- if (directory.handles.size === 0) {
125
- delete entries[key]
126
- }
127
- }
128
- }).pipe(useEntries),
129
- )
130
-
131
- yield* backing
132
- .run(
133
- Effect.fnUntraced(function* (_portId, raw) {
134
- const state = yield* Ref.get(stateRef)
135
- yield* Effect.gen(function* () {
136
- const message = yield* validateClientMessage(raw)
137
- yield* debug("MessageReceived", { message })
138
- if (Option.isNone(state)) {
139
- if (message._tag !== "Audition.Payload") {
140
- return yield* Effect.die(undefined)
141
- }
142
- const { client: actual } = message
143
- if (actual !== expected) {
144
- yield* backing.send(0, {
145
- _tag: "Audition.Failure",
146
- expected,
147
- actual,
148
- })
149
- return yield* closeScope
150
- }
151
- const key = yield* encodeName(name)
152
- const entry = yield* getEntry(key)
153
- const currentClient = Object.assign(yield* entry.directory.register(port, attachments), {
154
- disconnect: closeScope,
155
- })
156
- const ActorLive = Layer.succeed(actor, {
157
- name,
158
- clients: entry.directory.handles,
159
- currentClient,
160
- })
161
- yield* Ref.set(stateRef, Option.some({ key, entry, currentClient, ActorLive }))
162
- yield* backing.send(0, { _tag: "Audition.Success" })
163
- return yield* onConnect.pipe(entry.mutex, Effect.scoped, span("onConnect"), Effect.provide(ActorLive))
164
- }
165
- const { entry, ActorLive } = state.value
166
- if (message._tag === "Audition.Payload") {
167
- return yield* Effect.die(undefined)
168
- }
169
- if (message._tag === "Disconnect") {
170
- return yield* closeScope
171
- }
172
- const { id, payload } = message
173
- const { _tag, value } = payload as never
174
- yield* (
175
- handlers as Method.Handlers<
176
- D["methods"],
177
- Handlers[keyof Handlers] extends (v: never) => Effect.Effect<any, any, infer R> ? R : never
178
- >
179
- )[_tag]!(value).pipe(
180
- Effect.match({
181
- onSuccess: (value) => ({
182
- _tag: "F.Success" as const,
183
- id,
184
- success: { _tag, value } as never,
185
- }),
186
- onFailure: (value) => ({
187
- _tag: "F.Failure" as const,
188
- id,
189
- failure: { _tag, value } as never,
190
- }),
191
- }),
192
- Effect.andThen((v) => backing.send(0, v)),
193
- span("handler", { attributes: { _tag } }),
194
- Effect.scoped,
195
- Effect.provide(ActorLive),
196
- entry.mutex,
197
- )
198
- })
199
- }, span("message")),
200
- )
201
- .pipe(
202
- Effect.andThen(closeScope),
203
- Effect.catchCause((cause) =>
204
- Cause.hasInterruptsOnly(cause) ? Effect.void : logCause(cause).pipe(Effect.andThen(closeScope)),
205
- ),
206
- Effect.forkScoped,
207
- Scope.provide(scope),
208
- )
209
- }),
210
- ),
211
- Effect.tapCause(logCause),
212
- )
213
- }, span("make"))
package/browser/index.ts DELETED
@@ -1 +0,0 @@
1
- export * as BrowserActorNamespace from "./BrowserActorNamespace.ts"
@@ -1,22 +0,0 @@
1
- import { Types, Option, Ref, PubSub, Stream, Effect, Context, Layer } from "effect";
2
- declare const TypeId: "~liminal/Accumulator";
3
- export interface Service<State> {
4
- readonly ref: Ref.Ref<State>;
5
- readonly pubsub: PubSub.PubSub<State>;
6
- }
7
- export interface AccumulatorLayerConfig<Item, E, R, State, E2, R2, E3, R3> {
8
- readonly source: Stream.Stream<Item, E, R>;
9
- readonly reduce: (item: Item) => (state: State) => Effect.Effect<State, E2, R2>;
10
- readonly initial: (item: Item) => Effect.Effect<Option.Option<State>, E3, R3>;
11
- }
12
- export type Reduce<State, Item, K extends Types.Tags<Item> = Types.Tags<Item>, E = never, R = never> = (item: Types.ExtractTag<Item, K>) => (accumulator: State) => Effect.Effect<State, E, R>;
13
- export interface Accumulator<Self, Id extends string, State> extends Context.Service<Self, Service<State>> {
14
- new (_: never): Context.ServiceClass.Shape<Id, Service<State>>;
15
- readonly [TypeId]: typeof TypeId;
16
- readonly get: Effect.Effect<State, never, Self>;
17
- readonly stream: Stream.Stream<State, never, Self>;
18
- readonly reducer: <Item>() => <K extends Types.Tags<Item>, E, R>(_tag: K, f: Reduce<State, Item, K, E, R>) => Reduce<State, Item, K, E, R>;
19
- readonly layer: <Item, E, R, E2, R2, E3, R3>(config: AccumulatorLayerConfig<Item, E, R, State, E2, R2, E3, R3>) => Layer.Layer<Self, E | E2 | E3, R | R2 | R3>;
20
- }
21
- export declare const Service: <Self, State>() => <Id extends string>(id: Id) => Accumulator<Self, Id, State>;
22
- export {};
@@ -1,37 +0,0 @@
1
- import { Deferred, Types, Option, Ref, PubSub, Stream, Effect, Context, Layer, Semaphore } from "effect";
2
- import { diagnostic } from "./_diagnostic.js";
3
- const { debug } = diagnostic("Accumulator");
4
- const TypeId = "~liminal/Accumulator";
5
- export const Service = () => (id) => {
6
- const tag = Context.Service()(id);
7
- const get = tag.asEffect().pipe(Effect.map(({ ref }) => ref), Effect.flatMap(Ref.get));
8
- const stream = tag.asEffect().pipe(Effect.map(({ pubsub }) => Stream.fromPubSub(pubsub)), Stream.unwrap);
9
- const reducer = () => (_tag, f) => f;
10
- const layer = ({ source, initial, reduce, }) => Effect.gen(function* () {
11
- const semaphore = yield* Semaphore.make(1);
12
- const deferred = yield* Deferred.make();
13
- const pubsub = yield* PubSub.unbounded({ replay: 1 });
14
- yield* source.pipe(Stream.runForEach(Effect.fn(function* (item) {
15
- if (!(yield* Deferred.isDone(deferred))) {
16
- const match = yield* initial(item);
17
- if (Option.isSome(match)) {
18
- const { value } = match;
19
- yield* Deferred.succeed(deferred, value);
20
- yield* debug("InitializedState", { state: value });
21
- }
22
- return;
23
- }
24
- const current = yield* Ref.get(ref);
25
- const reduced = yield* reduce(item)(current);
26
- yield* Ref.set(ref, reduced);
27
- yield* PubSub.publish(pubsub, reduced);
28
- yield* debug("ReducedState", { item, previous: current, current: reduced });
29
- }, semaphore.withPermits(1))), Effect.forkScoped);
30
- const initial_ = yield* Deferred.await(deferred);
31
- const ref = yield* Ref.make(initial_);
32
- yield* PubSub.publish(pubsub, initial_);
33
- return { ref, pubsub };
34
- }).pipe(Layer.effect(tag));
35
- return Object.assign(tag, { [TypeId]: TypeId, get, stream, reducer, layer });
36
- };
37
- //# sourceMappingURL=Accumulator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Accumulator.js","sourceRoot":"","sources":["../Accumulator.ts"],"names":[],"mappings":"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"}
package/dist/F.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import { Effect } from "effect";
2
- import type { FError } from "./errors.ts";
3
- import type { ProtocolDefinition } from "./Protocol.ts";
4
- export type F<Self, D extends ProtocolDefinition> = <Method extends keyof D["methods"]>(method: Method) => (payload: D["methods"][Method]["payload"]["Type"]) => Effect.Effect<D["methods"][Method]["success"]["Type"], FError<D>, Self>;
package/dist/F.js DELETED
@@ -1,2 +0,0 @@
1
- import { Effect } from "effect";
2
- //# sourceMappingURL=F.js.map
package/dist/F.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"F.js","sourceRoot":"","sources":["../F.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA"}
@@ -1,4 +0,0 @@
1
- export declare const diagnostic: (module: string) => {
2
- debug: (event: string, annotations?: Record<string, unknown>) => import("effect/Effect").Effect<void, never, never>;
3
- span: (operation: string, options?: import("effect/Tracer").SpanOptions | undefined) => <A, E, R>(effect: import("effect/Effect").Effect<A, E, R>) => import("effect/Effect").Effect<A, E, Exclude<R, import("effect/Tracer").ParentSpan>>;
4
- };
@@ -1,3 +0,0 @@
1
- import { factory } from "liminal-util/Diagnostic";
2
- export const diagnostic = factory("liminal");
3
- //# sourceMappingURL=_diagnostic.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_diagnostic.js","sourceRoot":"","sources":["../_diagnostic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAEjD,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA"}
@@ -1,7 +0,0 @@
1
- import { Context, Effect, Layer } from "effect";
2
- declare const Mutex_base: Context.ServiceClass<Mutex, "liminal/Mutex", <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>>;
3
- export declare class Mutex extends Mutex_base {
4
- }
5
- export declare const layer: Layer.Layer<Mutex, never, never>;
6
- export declare const task: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R | Mutex>;
7
- export {};
@@ -1,9 +0,0 @@
1
- import { Context, Effect, Layer, Semaphore } from "effect";
2
- export class Mutex extends Context.Service()("liminal/Mutex") {
3
- }
4
- export const layer = Effect.gen(function* () {
5
- const mutex = yield* Semaphore.make(1);
6
- return mutex.withPermits(1);
7
- }).pipe(Layer.effect(Mutex));
8
- export const task = (effect) => Mutex.asEffect().pipe(Effect.flatMap((f) => f(effect)));
9
- //# sourceMappingURL=Mutex.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Mutex.js","sourceRoot":"","sources":["../../_util/Mutex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAE1D,MAAM,OAAO,KAAM,SAAQ,OAAO,CAAC,OAAO,EAGvC,CAAC,eAAe,CAAC;CAAG;AAEvB,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtC,OAAO,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;AAC7B,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;AAE5B,MAAM,CAAC,MAAM,IAAI,GAAG,CAAU,MAA8B,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA"}
@@ -1,4 +0,0 @@
1
- import { Schema as S } from "effect";
2
- export type TopFromString = S.Codec<any, string, any, any>;
3
- export declare const encodeJsonString: <T, E, RD, RE>(schema: S.Codec<T, E, RD, RE>) => (input: T, options?: import("effect/SchemaAST").ParseOptions) => import("effect/Effect").Effect<string, S.SchemaError, RE>;
4
- export declare const decodeJsonString: <T, E, RD, RE>(schema: S.Codec<T, E, RD, RE>) => (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => import("effect/Effect").Effect<T, S.SchemaError, RD>;
@@ -1,5 +0,0 @@
1
- import { Schema as S, flow } from "effect";
2
- const toJsonStringCodec = flow(S.toCodecJson, S.fromJsonString);
3
- export const encodeJsonString = flow(toJsonStringCodec, S.encodeEffect);
4
- export const decodeJsonString = flow(toJsonStringCodec, S.decodeUnknownEffect);
5
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../_util/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAI1C,MAAM,iBAAiB,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,cAAc,CAAC,CAAA;AAC/D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAA"}
@@ -1,16 +0,0 @@
1
- import { Effect, Schema as S, Scope, Stream } from "effect";
2
- import type { TopFromString } from "../_util/schema.ts";
3
- import type { Actor } from "../Actor.ts";
4
- import type { ProtocolDefinition } from "../Protocol.ts";
5
- import * as Method from "../Method.ts";
6
- export interface Introduction<Name extends TopFromString, AttachmentFields extends S.Struct.Fields> {
7
- readonly port: MessagePort;
8
- readonly name: Name["Type"];
9
- readonly attachments: S.Struct<AttachmentFields>["Type"];
10
- }
11
- export declare const make: <ActorSelf, ActorId extends string, Name extends TopFromString, AttachmentFields extends S.Struct.Fields, ClientSelf, ClientId extends string, D extends ProtocolDefinition, const Handlers extends Method.Handlers<D["methods"], any>, A, E, R, IntroductionE, IntroductionR>(args_0: {
12
- readonly actor: Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>;
13
- readonly handlers: Handlers;
14
- readonly onConnect: Effect.Effect<A, E, R>;
15
- readonly introductions: Stream.Stream<Introduction<Name, AttachmentFields>, IntroductionE, IntroductionR>;
16
- }) => Effect.Effect<void, IntroductionE | import("effect/unstable/workers/WorkerError").WorkerError, Scope.Scope | Exclude<IntroductionR, import("effect/Tracer").ParentSpan> | Exclude<Exclude<Exclude<S.Struct.EncodingServices<AttachmentFields>, import("effect/Tracer").ParentSpan>, Scope.Scope>, import("effect/Tracer").ParentSpan> | Exclude<Exclude<Exclude<Name["EncodingServices"], import("effect/Tracer").ParentSpan>, Scope.Scope>, import("effect/Tracer").ParentSpan> | Exclude<Exclude<Exclude<Exclude<Exclude<Exclude<R, Scope.Scope>, import("effect/Tracer").ParentSpan>, ActorSelf>, import("effect/Tracer").ParentSpan>, Scope.Scope>, import("effect/Tracer").ParentSpan> | Exclude<Exclude<Exclude<Exclude<Exclude<Exclude<Handlers[keyof Handlers] extends (v: never) => Effect.Effect<any, any, infer R_1> ? R_1 : never, import("effect/Tracer").ParentSpan>, Scope.Scope>, ActorSelf>, import("effect/Tracer").ParentSpan>, Scope.Scope>, import("effect/Tracer").ParentSpan>>;