@effect-atom/atom 0.1.1 → 0.1.3

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/src/AtomRpc.ts ADDED
@@ -0,0 +1,198 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ import * as Reactivity from "@effect/experimental/Reactivity"
5
+ import * as Headers from "@effect/platform/Headers"
6
+ import type * as Rpc from "@effect/rpc/Rpc"
7
+ import * as RpcClient from "@effect/rpc/RpcClient"
8
+ import type { RpcClientError } from "@effect/rpc/RpcClientError"
9
+ import type * as RpcGroup from "@effect/rpc/RpcGroup"
10
+ import type { RequestId } from "@effect/rpc/RpcMessage"
11
+ import * as RpcSchema from "@effect/rpc/RpcSchema"
12
+ import * as Data from "effect/Data"
13
+ import * as Effect from "effect/Effect"
14
+ import * as Equal from "effect/Equal"
15
+ import { pipe } from "effect/Function"
16
+ import * as Hash from "effect/Hash"
17
+ import type { ReadonlyRecord } from "effect/Record"
18
+ import * as Stream from "effect/Stream"
19
+ import * as Atom from "./Atom.js"
20
+ import type * as Result from "./Result.js"
21
+
22
+ /**
23
+ * @since 1.0.0
24
+ * @category Models
25
+ */
26
+ export interface AtomRpcClient<Rpcs extends Rpc.Any, E> {
27
+ readonly client: Atom.Atom<
28
+ Result.Result<RpcClient.RpcClient.Flat<Rpcs, RpcClientError>, E>
29
+ >
30
+
31
+ readonly mutation: <Tag extends Rpc.Tag<Rpcs>>(
32
+ arg: Tag
33
+ ) => Rpc.ExtractTag<Rpcs, Tag> extends Rpc.Rpc<
34
+ infer _Tag,
35
+ infer _Payload,
36
+ infer _Success,
37
+ infer _Error,
38
+ infer _Middleware
39
+ > ? [_Success] extends [RpcSchema.Stream<infer _A, infer _E>] ? never
40
+ : Atom.AtomResultFn<
41
+ {
42
+ readonly payload: Rpc.PayloadConstructor<Rpc.ExtractTag<Rpcs, Tag>>
43
+ readonly reactivityKeys?:
44
+ | ReadonlyRecord<string, ReadonlyArray<unknown>>
45
+ | undefined
46
+ readonly headers?: Headers.Input | undefined
47
+ },
48
+ _Success["Type"],
49
+ _Error["Type"] | E | _Middleware["failure"]["Type"]
50
+ >
51
+ : never
52
+
53
+ readonly query: <Tag extends Rpc.Tag<Rpcs>>(
54
+ tag: Tag,
55
+ payload: Rpc.PayloadConstructor<Rpc.ExtractTag<Rpcs, Tag>>,
56
+ options?: {
57
+ readonly headers?: Headers.Input | undefined
58
+ readonly reactivityKeys?:
59
+ | ReadonlyArray<unknown>
60
+ | ReadonlyRecord<string, ReadonlyArray<unknown>>
61
+ | undefined
62
+ }
63
+ ) => Rpc.ExtractTag<Rpcs, Tag> extends Rpc.Rpc<
64
+ infer _Tag,
65
+ infer _Payload,
66
+ infer _Success,
67
+ infer _Error,
68
+ infer _Middleware
69
+ > ? [_Success] extends [RpcSchema.Stream<infer _A, infer _E>] ? Atom.Writable<
70
+ Atom.PullResult<
71
+ _A,
72
+ _E | _Error["Type"] | E | _Middleware["failure"]["Type"]
73
+ >,
74
+ void
75
+ >
76
+ : Atom.Atom<
77
+ Result.Result<
78
+ _Success["Type"],
79
+ _Error["Type"] | E | _Middleware["failure"]["Type"]
80
+ >
81
+ >
82
+ : never
83
+ }
84
+
85
+ /**
86
+ * @since 1.0.0
87
+ * @category Constructors
88
+ */
89
+ export const make = <Rpcs extends Rpc.Any, ER>(
90
+ group: RpcGroup.RpcGroup<Rpcs>,
91
+ options: {
92
+ readonly runtime: Atom.AtomRuntime<
93
+ RpcClient.Protocol | Rpc.MiddlewareClient<Rpcs> | Rpc.Context<Rpcs>,
94
+ ER
95
+ >
96
+ readonly spanPrefix?: string | undefined
97
+ readonly spanAttributes?: Record<string, unknown> | undefined
98
+ readonly generateRequestId?: (() => RequestId) | undefined
99
+ readonly disableTracing?: boolean | undefined
100
+ }
101
+ ): AtomRpcClient<Rpcs, ER> => {
102
+ const client = options.runtime.atom(
103
+ RpcClient.make(group, {
104
+ ...options,
105
+ flatten: true
106
+ })
107
+ )
108
+
109
+ const mutation = Atom.family(<Tag extends Rpc.Tag<Rpcs>>(tag: Tag) =>
110
+ options.runtime.fn<{
111
+ readonly payload: Rpc.PayloadConstructor<Rpc.ExtractTag<Rpcs, Tag>>
112
+ readonly reactivityKeys?:
113
+ | ReadonlyArray<unknown>
114
+ | ReadonlyRecord<string, ReadonlyArray<unknown>>
115
+ | undefined
116
+ readonly headers?: Headers.Input | undefined
117
+ }>()(
118
+ Effect.fnUntraced(function*({ headers, payload, reactivityKeys }, get) {
119
+ const c = yield* get.result(client)
120
+ const effect = c(tag, payload, { headers } as any)
121
+ return yield* reactivityKeys
122
+ ? Reactivity.mutation(effect, reactivityKeys)
123
+ : effect
124
+ })
125
+ )
126
+ )
127
+
128
+ const queryFamily = Atom.family(({ headers, payload, reactivityKeys, tag }: QueryKey) => {
129
+ const rpc = group.requests.get(tag)! as any as Rpc.AnyWithProps
130
+ const atom = RpcSchema.isStreamSchema(rpc.successSchema)
131
+ ? Atom.pull((get) =>
132
+ get.result(client).pipe(
133
+ Effect.map((client) => client(tag, payload, { headers } as any)),
134
+ Stream.unwrap
135
+ )
136
+ )
137
+ : Atom.make((get) =>
138
+ get
139
+ .result(client)
140
+ .pipe(
141
+ Effect.flatMap((client) => client(tag, payload, { headers } as any))
142
+ )
143
+ )
144
+ return reactivityKeys ? options.runtime.factory.withReactivity(reactivityKeys)(atom) : atom
145
+ })
146
+
147
+ const query = <Tag extends Rpc.Tag<Rpcs>>(
148
+ tag: Tag,
149
+ payload: Rpc.PayloadConstructor<Rpc.ExtractTag<Rpcs, Tag>>,
150
+ options?: {
151
+ readonly headers?: Headers.Input | undefined
152
+ readonly reactivityKeys?: ReadonlyArray<unknown> | undefined
153
+ }
154
+ ) =>
155
+ queryFamily(
156
+ new QueryKey({
157
+ tag,
158
+ payload: Data.struct(payload),
159
+ headers: options?.headers
160
+ ? Data.unsafeStruct(Headers.fromInput(options.headers))
161
+ : undefined,
162
+ reactivityKeys: options?.reactivityKeys
163
+ ? Data.array(options.reactivityKeys)
164
+ : undefined
165
+ })
166
+ )
167
+
168
+ return {
169
+ client,
170
+ mutation,
171
+ query
172
+ } as any
173
+ }
174
+
175
+ class QueryKey extends Data.Class<{
176
+ tag: string
177
+ payload: any
178
+ headers?: Headers.Headers | undefined
179
+ reactivityKeys?: ReadonlyArray<unknown> | undefined
180
+ }> {
181
+ [Equal.symbol](that: QueryKey) {
182
+ return (
183
+ this.tag === that.tag &&
184
+ Equal.equals(this.payload, that.payload) &&
185
+ Equal.equals(this.headers, that.headers) &&
186
+ Equal.equals(this.reactivityKeys, that.reactivityKeys)
187
+ )
188
+ }
189
+ [Hash.symbol]() {
190
+ return pipe(
191
+ Hash.string(this.tag),
192
+ Hash.combine(Hash.hash(this.payload)),
193
+ Hash.combine(Hash.hash(this.headers)),
194
+ Hash.combine(Hash.hash(this.reactivityKeys)),
195
+ Hash.cached(this)
196
+ )
197
+ }
198
+ }
package/src/index.ts CHANGED
@@ -8,6 +8,11 @@ export * as Atom from "./Atom.js"
8
8
  */
9
9
  export * as AtomRef from "./AtomRef.js"
10
10
 
11
+ /**
12
+ * @since 1.0.0
13
+ */
14
+ export * as AtomRpc from "./AtomRpc.js"
15
+
11
16
  /**
12
17
  * @since 1.0.0
13
18
  */