liminal 0.17.13 → 0.17.15

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 (94) hide show
  1. package/Actor.ts +12 -13
  2. package/ActorTransport.ts +6 -4
  3. package/Audition.ts +87 -40
  4. package/CHANGELOG.md +16 -0
  5. package/Client.ts +260 -134
  6. package/ClientDirectory.ts +50 -36
  7. package/ClientHandleEncoders.ts +15 -0
  8. package/Fn.ts +55 -0
  9. package/Method.ts +11 -21
  10. package/Protocol.ts +44 -36
  11. package/Reducer.ts +22 -0
  12. package/Tracing.ts +37 -0
  13. package/browser/BrowserActorNamespace.ts +65 -30
  14. package/dist/Actor.d.ts +1 -1
  15. package/dist/Actor.js +6 -6
  16. package/dist/Actor.js.map +1 -1
  17. package/dist/ActorTransport.d.ts +5 -4
  18. package/dist/Audition.d.ts +16 -9
  19. package/dist/Audition.js +25 -9
  20. package/dist/Audition.js.map +1 -1
  21. package/dist/Client.d.ts +21 -14
  22. package/dist/Client.js +147 -100
  23. package/dist/Client.js.map +1 -1
  24. package/dist/ClientDirectory.d.ts +14 -6
  25. package/dist/ClientDirectory.js +25 -22
  26. package/dist/ClientDirectory.js.map +1 -1
  27. package/dist/ClientHandleEncoders.d.ts +7 -0
  28. package/dist/ClientHandleEncoders.js +2 -0
  29. package/dist/ClientHandleEncoders.js.map +1 -0
  30. package/dist/Fn.d.ts +16 -0
  31. package/dist/Fn.js +2 -0
  32. package/dist/Fn.js.map +1 -0
  33. package/dist/Method.d.ts +9 -14
  34. package/dist/Method.js +0 -1
  35. package/dist/Method.js.map +1 -1
  36. package/dist/Protocol.d.ts +19 -22
  37. package/dist/Protocol.js +20 -15
  38. package/dist/Protocol.js.map +1 -1
  39. package/dist/Reducer.d.ts +11 -0
  40. package/dist/Reducer.js +2 -0
  41. package/dist/Reducer.js.map +1 -0
  42. package/dist/Tracing.d.ts +37 -0
  43. package/dist/Tracing.js +29 -0
  44. package/dist/Tracing.js.map +1 -0
  45. package/dist/browser/BrowserActorNamespace.d.ts +5 -5
  46. package/dist/browser/BrowserActorNamespace.js +41 -20
  47. package/dist/browser/BrowserActorNamespace.js.map +1 -1
  48. package/dist/errors.d.ts +0 -4
  49. package/dist/errors.js.map +1 -1
  50. package/dist/experimental/TaggedTemplateFunction.js +1 -1
  51. package/dist/experimental/TaggedTemplateFunction.js.map +1 -1
  52. package/dist/index.d.ts +3 -3
  53. package/dist/index.js +3 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/package.json +16 -21
  56. package/dist/tsconfig.tsbuildinfo +1 -1
  57. package/dist/workerd/ActorHandle.d.ts +9 -0
  58. package/dist/workerd/ActorHandle.js +4 -0
  59. package/dist/workerd/ActorHandle.js.map +1 -0
  60. package/dist/workerd/WorkerdActorNamespace.d.ts +18 -18
  61. package/dist/workerd/WorkerdActorNamespace.js +43 -141
  62. package/dist/workerd/WorkerdActorNamespace.js.map +1 -1
  63. package/dist/workerd/WorkerdActorRuntime.d.ts +19 -0
  64. package/dist/workerd/WorkerdActorRuntime.js +204 -0
  65. package/dist/workerd/WorkerdActorRuntime.js.map +1 -0
  66. package/dist/workerd/index.d.ts +2 -0
  67. package/dist/workerd/index.js +2 -0
  68. package/dist/workerd/index.js.map +1 -1
  69. package/errors.ts +0 -6
  70. package/experimental/TaggedTemplateFunction.ts +1 -1
  71. package/index.ts +3 -3
  72. package/package.json +10 -25
  73. package/tsconfig.json +1 -1
  74. package/vitest.config.ts +7 -0
  75. package/workerd/ActorHandle.ts +29 -0
  76. package/workerd/WorkerdActorNamespace.ts +86 -273
  77. package/workerd/WorkerdActorRuntime.ts +422 -0
  78. package/workerd/index.ts +2 -0
  79. package/Accumulator.ts +0 -103
  80. package/F.ts +0 -10
  81. package/_diagnostic.ts +0 -3
  82. package/_util/Mutex.ts +0 -13
  83. package/dist/Accumulator.d.ts +0 -22
  84. package/dist/Accumulator.js +0 -37
  85. package/dist/Accumulator.js.map +0 -1
  86. package/dist/F.d.ts +0 -4
  87. package/dist/F.js +0 -2
  88. package/dist/F.js.map +0 -1
  89. package/dist/_diagnostic.d.ts +0 -4
  90. package/dist/_diagnostic.js +0 -3
  91. package/dist/_diagnostic.js.map +0 -1
  92. package/dist/_util/Mutex.d.ts +0 -7
  93. package/dist/_util/Mutex.js +0 -9
  94. package/dist/_util/Mutex.js.map +0 -1
package/Actor.ts CHANGED
@@ -1,14 +1,13 @@
1
1
  import { Context, Schema as S, Effect } from "effect"
2
+ import * as Spanner from "liminal-util/Spanner"
2
3
 
3
4
  import type { TopFromString } from "./_util/schema.ts"
4
5
  import type * as ActorClient from "./Client.ts"
5
6
  import type { ClientHandle, Sender } from "./ClientHandle.ts"
6
-
7
- import { diagnostic } from "./_diagnostic.ts"
8
7
  import * as Method from "./Method.ts"
9
8
  import { type ProtocolDefinition } from "./Protocol.ts"
10
9
 
11
- const { span } = diagnostic("Actor")
10
+ const span = Spanner.make(import.meta.url)
12
11
 
13
12
  export const TypeId = "~liminal/Actor" as const
14
13
 
@@ -58,10 +57,10 @@ export interface Actor<
58
57
 
59
58
  readonly others: Sender<ActorSelf, D>
60
59
 
61
- readonly handler: <K extends keyof D["methods"], R>(
60
+ readonly handler: <K extends keyof D["external"], R>(
62
61
  tag: K,
63
- f: Method.Handler<D["methods"][K], R>,
64
- ) => Method.Handler<D["methods"][K], R>
62
+ f: Method.Handler<D["external"][K], R>,
63
+ ) => Method.Handler<D["external"][K], R>
65
64
  }
66
65
 
67
66
  export const Service =
@@ -85,11 +84,11 @@ export const Service =
85
84
  Effect.flatMap(({ clients }) =>
86
85
  Effect.forEach(clients, (client) => client.send(key, payload), { concurrency: "unbounded" }),
87
86
  ),
88
- span("all.send"),
87
+ span("send-all"),
89
88
  ),
90
89
  disconnect: tag.asEffect().pipe(
91
90
  Effect.flatMap(({ clients }) => Effect.forEach(clients, ({ disconnect }) => disconnect)),
92
- span("all.disconnect"),
91
+ span("disconnect-all"),
93
92
  ),
94
93
  }
95
94
 
@@ -101,17 +100,17 @@ export const Service =
101
100
  (client) => (client === currentClient ? Effect.void : client.send(key, payload)),
102
101
  { concurrency: "unbounded" },
103
102
  )
104
- }, span("others.send")),
103
+ }, span("send-others")),
105
104
  disconnect: Effect.gen(function* () {
106
105
  const { clients, currentClient } = yield* tag
107
106
  yield* Effect.forEach(clients, (client) => (client === currentClient ? Effect.void : client.disconnect))
108
- }).pipe(span("others.disconnect")),
107
+ }).pipe(span("disconnect-others")),
109
108
  }
110
109
 
111
- const handler = <K extends keyof D["methods"], R>(
110
+ const handler = <K extends keyof D["external"], R>(
112
111
  _tag: K,
113
- f: Method.Handler<D["methods"][K], R>,
114
- ): Method.Handler<D["methods"][K], R> => f
112
+ f: Method.Handler<D["external"][K], R>,
113
+ ): Method.Handler<D["external"][K], R> => f
115
114
 
116
115
  return Object.assign(tag, {
117
116
  [TypeId]: TypeId,
package/ActorTransport.ts CHANGED
@@ -2,16 +2,18 @@ import { Effect, Schema as S } from "effect"
2
2
 
3
3
  import type { Protocol, ProtocolDefinition } from "./Protocol.ts"
4
4
 
5
- export interface ActorTransport<Raw, AttachmentFields extends S.Struct.Fields, D extends ProtocolDefinition> {
5
+ export interface ActorTransport<Key, Client, AttachmentFields extends S.Struct.Fields, D extends ProtocolDefinition> {
6
+ readonly key: (client: Client) => Key
7
+
6
8
  readonly send: (
7
- transport: Raw,
9
+ client: Client,
8
10
  event: Protocol<D>["Event"]["Type"],
9
11
  ) => Effect.Effect<void, S.SchemaError, Protocol<D>["Event"]["EncodingServices"]>
10
12
 
11
- readonly close: (transport: Raw) => Effect.Effect<void>
13
+ readonly close: (client: Client) => Effect.Effect<void>
12
14
 
13
15
  readonly snapshot: (
14
- transport: Raw,
16
+ client: Client,
15
17
  attachments: S.Struct<AttachmentFields>["Type"],
16
18
  ) => Effect.Effect<void, S.SchemaError, S.Struct<AttachmentFields>["EncodingServices"]>
17
19
  }
package/Audition.ts CHANGED
@@ -1,80 +1,126 @@
1
- import { Schema as S, Pipeable, Stream, Effect, Function } from "effect"
1
+ import { Schema as S, Pipeable, Stream, Effect, Function, Types } from "effect"
2
2
 
3
- import type { F } from "./F.ts"
4
- import type { ProtocolDefinition } from "./Protocol.ts"
5
-
6
- import { diagnostic } from "./_diagnostic.ts"
7
3
  import * as Client from "./Client.ts"
8
4
  import { type ClientError, AuditionError } from "./errors.ts"
9
-
10
- const { debug, span } = diagnostic("Audition")
5
+ import type { Fn } from "./Fn.ts"
6
+ import type { Methods } from "./Method.ts"
7
+ import type { ProtocolDefinition } from "./Protocol.ts"
11
8
 
12
9
  const TypeId = "~liminal/Audition" as const
13
10
 
14
- export interface Audition<ClientSelf, D extends ProtocolDefinition> extends Pipeable.Pipeable {
11
+ export interface Audition<AuditionSelf, State extends S.Union<ReadonlyArray<S.Top>>, External extends Methods, Event>
12
+ extends Pipeable.Pipeable {
15
13
  readonly [TypeId]: typeof TypeId
16
14
 
17
- readonly events: Stream.Stream<
18
- ReturnType<typeof S.TaggedUnion<D["events"]>>["Type"],
19
- ClientError | S.SchemaError,
20
- ClientSelf
21
- >
15
+ readonly state: Stream.Stream<State["Type"], ClientError | S.SchemaError, AuditionSelf | State["DecodingServices"]>
16
+
17
+ readonly fn: Fn<AuditionSelf, External>
22
18
 
23
- readonly f: F<ClientSelf, D>
19
+ readonly events: Stream.Stream<Event, ClientError | S.SchemaError, AuditionSelf>
24
20
  }
25
21
 
26
- export const empty: Audition<never, never> = {
22
+ type MergeMethods<T extends Methods, U extends Methods> = [keyof T] extends [never]
23
+ ? U
24
+ : { [K in keyof T & keyof U]: Types.Equals<T[K], U[K]> extends true ? T[K] : never }
25
+
26
+ type MergeState<State, D extends ProtocolDefinition> = [State] extends [never]
27
+ ? S.Union<[S.Struct<D["state"]>]>
28
+ : State extends S.Union<ReadonlyArray<S.Top>>
29
+ ? S.Union<[...State["members"], S.Struct<D["state"]>]>
30
+ : never
31
+
32
+ export const empty: Audition<never, never, {}, never> = {
27
33
  [TypeId]: TypeId,
28
34
  pipe() {
29
35
  return Pipeable.pipeArguments(this, arguments)
30
36
  },
37
+ state: Stream.fail(new AuditionError()),
38
+ fn: () => () => new AuditionError().asEffect(),
31
39
  events: Stream.fail(new AuditionError()),
32
- f: () => () => new AuditionError().asEffect(),
33
40
  }
34
41
 
42
+ export const cycleOn =
43
+ <Event>(predicate: (event: Event) => boolean) =>
44
+ <AuditionSelf, State extends S.Union<ReadonlyArray<S.Top>>, External extends Methods>(
45
+ audition: Audition<AuditionSelf, State, External, Event>,
46
+ ): Audition<AuditionSelf, State, External, Event> => {
47
+ const events = audition.events.pipe(Stream.takeUntil(predicate), Stream.forever)
48
+ const state = audition.state.pipe(Stream.forever)
49
+
50
+ return {
51
+ [TypeId]: TypeId,
52
+ pipe() {
53
+ return Pipeable.pipeArguments(this, arguments)
54
+ },
55
+ events,
56
+ fn: audition.fn,
57
+ state,
58
+ }
59
+ }
60
+
35
61
  export const add: {
36
62
  <ClientSelf, ClientId extends string, ClientD extends ProtocolDefinition>(
37
63
  client: Client.Client<ClientSelf, ClientId, ClientD>,
38
- ): <AuditionSelf, AuditionD extends ProtocolDefinition>(
39
- audition: Audition<AuditionSelf, AuditionD>,
40
- ) => Audition<AuditionSelf | ClientSelf, ProtocolDefinition.Merge<AuditionD, ClientD>>
64
+ ): <AuditionSelf, State extends S.Union<ReadonlyArray<S.Top>> | never, External extends Methods, Event>(
65
+ audition: Audition<AuditionSelf, State, External, Event>,
66
+ ) => Audition<
67
+ AuditionSelf | ClientSelf,
68
+ MergeState<State, ClientD>,
69
+ MergeMethods<External, ClientD["external"]>,
70
+ Event | ReturnType<typeof S.TaggedUnion<ClientD["events"]>>["Type"]
71
+ >
41
72
  <
42
- AuditionClientSelf,
43
- AuditionD extends ProtocolDefinition,
73
+ AuditionSelf,
74
+ State extends S.Union<ReadonlyArray<S.Top>> | never,
75
+ External extends Methods,
76
+ Event,
44
77
  ClientSelf,
45
78
  ClientId extends string,
46
79
  ClientD extends ProtocolDefinition,
47
80
  >(
48
- audition: Audition<AuditionClientSelf, AuditionD>,
81
+ audition: Audition<AuditionSelf, State, External, Event>,
49
82
  client: Client.Client<ClientSelf, ClientId, ClientD>,
50
- ): Audition<AuditionClientSelf | ClientSelf, ProtocolDefinition.Merge<AuditionD, ClientD>>
83
+ ): Audition<
84
+ AuditionSelf | ClientSelf,
85
+ MergeState<State, ClientD>,
86
+ MergeMethods<External, ClientD["external"]>,
87
+ Event | ReturnType<typeof S.TaggedUnion<ClientD["events"]>>["Type"]
88
+ >
51
89
  } = Function.dual(
52
90
  2,
53
91
  <
54
92
  AuditionSelf,
55
- AuditionD extends ProtocolDefinition,
93
+ State extends S.Union<ReadonlyArray<S.Top>>,
94
+ External extends Methods,
95
+ Event,
56
96
  ClientSelf,
57
97
  ClientId extends string,
58
98
  ClientD extends ProtocolDefinition,
59
99
  >(
60
- audition: Audition<AuditionSelf, AuditionD>,
100
+ audition: Audition<AuditionSelf, State, External, Event>,
61
101
  client: Client.Client<ClientSelf, ClientId, ClientD>,
62
- ): Audition<AuditionSelf | ClientSelf, ProtocolDefinition.Merge<AuditionD, ClientD>> => {
63
- const f: F<AuditionSelf | ClientSelf, ProtocolDefinition.Merge<AuditionD, ClientD>> = (method) => (payload) =>
64
- audition
65
- .f(method)(payload)
66
- .pipe(
67
- Effect.catchTag("AuditionError", () => client.f(method)(payload)),
68
- span("f"),
69
- )
102
+ ): Audition<
103
+ AuditionSelf | ClientSelf,
104
+ MergeState<State, ClientD>,
105
+ MergeMethods<External, ClientD["external"]>,
106
+ Event | ReturnType<typeof S.TaggedUnion<ClientD["events"]>>["Type"]
107
+ > => {
108
+ const fn = ((method: string, ...f: [any]) =>
109
+ Effect.fnUntraced(
110
+ function* (payload: any) {
111
+ return yield* audition
112
+ .fn(method)(payload)
113
+ .pipe(Effect.catchTag("AuditionError", () => client.fn(method)(payload)))
114
+ },
115
+ ...f,
116
+ )) as Fn<AuditionSelf | ClientSelf, MergeMethods<External, ClientD["external"]>>
70
117
 
71
118
  const events = audition.events.pipe(
72
- Stream.catchTag("AuditionError", () =>
73
- Effect.succeed(client.events).pipe(
74
- Effect.tap(() => debug("AuditionStaged", { client: client.key })),
75
- Stream.unwrap,
76
- ),
77
- ),
119
+ Stream.catchTag("AuditionError", () => Effect.succeed(client.events).pipe(Stream.unwrap)),
120
+ )
121
+
122
+ const state = audition.state.pipe(
123
+ Stream.catchTag("AuditionError", () => Effect.succeed(client.state).pipe(Stream.unwrap)),
78
124
  )
79
125
 
80
126
  return {
@@ -83,7 +129,8 @@ export const add: {
83
129
  return Pipeable.pipeArguments(this, arguments)
84
130
  },
85
131
  events,
86
- f,
132
+ fn,
133
+ state,
87
134
  }
88
135
  },
89
136
  )
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # liminal
2
2
 
3
+ ## 0.17.15
4
+
5
+ ### Patch Changes
6
+
7
+ - ab30d60: Move accumulator api directly into client and implement internal actor method bindings.
8
+ - Updated dependencies [ab30d60]
9
+ - effect-workerd@0.0.5
10
+
11
+ ## 0.17.14
12
+
13
+ ### Patch Changes
14
+
15
+ - d082441: Actor now inherits from DurableObject. Effect updated to beta 57.
16
+ - Updated dependencies [d082441]
17
+ - effect-workerd@0.0.4
18
+
3
19
  ## 0.17.13
4
20
 
5
21
  ### Patch Changes