effect 4.0.0-beta.44 → 4.0.0-beta.46

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 (151) hide show
  1. package/dist/Equal.d.ts.map +1 -1
  2. package/dist/Equal.js +16 -0
  3. package/dist/Equal.js.map +1 -1
  4. package/dist/Hash.js +1 -1
  5. package/dist/Hash.js.map +1 -1
  6. package/dist/Semaphore.d.ts +1 -1
  7. package/dist/Semaphore.d.ts.map +1 -1
  8. package/dist/Semaphore.js +1 -3
  9. package/dist/Semaphore.js.map +1 -1
  10. package/dist/unstable/ai/McpServer.d.ts.map +1 -1
  11. package/dist/unstable/ai/McpServer.js +24 -21
  12. package/dist/unstable/ai/McpServer.js.map +1 -1
  13. package/dist/unstable/eventlog/Event.d.ts +0 -6
  14. package/dist/unstable/eventlog/Event.d.ts.map +1 -1
  15. package/dist/unstable/eventlog/Event.js +0 -5
  16. package/dist/unstable/eventlog/Event.js.map +1 -1
  17. package/dist/unstable/eventlog/EventGroup.d.ts +0 -2
  18. package/dist/unstable/eventlog/EventGroup.d.ts.map +1 -1
  19. package/dist/unstable/eventlog/EventGroup.js +0 -2
  20. package/dist/unstable/eventlog/EventGroup.js.map +1 -1
  21. package/dist/unstable/eventlog/EventJournal.d.ts +22 -5
  22. package/dist/unstable/eventlog/EventJournal.d.ts.map +1 -1
  23. package/dist/unstable/eventlog/EventJournal.js +126 -67
  24. package/dist/unstable/eventlog/EventJournal.js.map +1 -1
  25. package/dist/unstable/eventlog/EventLog.d.ts +88 -34
  26. package/dist/unstable/eventlog/EventLog.d.ts.map +1 -1
  27. package/dist/unstable/eventlog/EventLog.js +215 -141
  28. package/dist/unstable/eventlog/EventLog.js.map +1 -1
  29. package/dist/unstable/eventlog/EventLogEncryption.d.ts +9 -7
  30. package/dist/unstable/eventlog/EventLogEncryption.d.ts.map +1 -1
  31. package/dist/unstable/eventlog/EventLogEncryption.js +13 -15
  32. package/dist/unstable/eventlog/EventLogEncryption.js.map +1 -1
  33. package/dist/unstable/eventlog/EventLogMessage.d.ts +228 -0
  34. package/dist/unstable/eventlog/EventLogMessage.d.ts.map +1 -0
  35. package/dist/unstable/eventlog/EventLogMessage.js +214 -0
  36. package/dist/unstable/eventlog/EventLogMessage.js.map +1 -0
  37. package/dist/unstable/eventlog/EventLogRemote.d.ts +109 -194
  38. package/dist/unstable/eventlog/EventLogRemote.d.ts.map +1 -1
  39. package/dist/unstable/eventlog/EventLogRemote.js +165 -320
  40. package/dist/unstable/eventlog/EventLogRemote.js.map +1 -1
  41. package/dist/unstable/eventlog/EventLogServer.d.ts +25 -47
  42. package/dist/unstable/eventlog/EventLogServer.d.ts.map +1 -1
  43. package/dist/unstable/eventlog/EventLogServer.js +127 -198
  44. package/dist/unstable/eventlog/EventLogServer.js.map +1 -1
  45. package/dist/unstable/eventlog/EventLogServerEncrypted.d.ts +60 -0
  46. package/dist/unstable/eventlog/EventLogServerEncrypted.d.ts.map +1 -0
  47. package/dist/unstable/eventlog/EventLogServerEncrypted.js +166 -0
  48. package/dist/unstable/eventlog/EventLogServerEncrypted.js.map +1 -0
  49. package/dist/unstable/eventlog/EventLogServerUnencrypted.d.ts +183 -0
  50. package/dist/unstable/eventlog/EventLogServerUnencrypted.d.ts.map +1 -0
  51. package/dist/unstable/eventlog/EventLogServerUnencrypted.js +461 -0
  52. package/dist/unstable/eventlog/EventLogServerUnencrypted.js.map +1 -0
  53. package/dist/unstable/eventlog/EventLogSessionAuth.d.ts +117 -0
  54. package/dist/unstable/eventlog/EventLogSessionAuth.d.ts.map +1 -0
  55. package/dist/unstable/eventlog/EventLogSessionAuth.js +284 -0
  56. package/dist/unstable/eventlog/EventLogSessionAuth.js.map +1 -0
  57. package/dist/unstable/eventlog/{SqlEventLogJournal.d.ts → SqlEventJournal.d.ts} +2 -2
  58. package/dist/unstable/eventlog/SqlEventJournal.d.ts.map +1 -0
  59. package/dist/unstable/eventlog/{SqlEventLogJournal.js → SqlEventJournal.js} +20 -14
  60. package/dist/unstable/eventlog/SqlEventJournal.js.map +1 -0
  61. package/dist/unstable/eventlog/{SqlEventLogServer.d.ts → SqlEventLogServerEncrypted.d.ts} +5 -5
  62. package/dist/unstable/eventlog/SqlEventLogServerEncrypted.d.ts.map +1 -0
  63. package/dist/unstable/eventlog/{SqlEventLogServer.js → SqlEventLogServerEncrypted.js} +65 -24
  64. package/dist/unstable/eventlog/SqlEventLogServerEncrypted.js.map +1 -0
  65. package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.d.ts +25 -0
  66. package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.d.ts.map +1 -0
  67. package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js +354 -0
  68. package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js.map +1 -0
  69. package/dist/unstable/eventlog/index.d.ts +22 -2
  70. package/dist/unstable/eventlog/index.d.ts.map +1 -1
  71. package/dist/unstable/eventlog/index.js +22 -2
  72. package/dist/unstable/eventlog/index.js.map +1 -1
  73. package/dist/unstable/eventlog/internal/identityRootSecretDerivation.d.ts +2 -0
  74. package/dist/unstable/eventlog/internal/identityRootSecretDerivation.d.ts.map +1 -0
  75. package/dist/unstable/eventlog/internal/identityRootSecretDerivation.js +89 -0
  76. package/dist/unstable/eventlog/internal/identityRootSecretDerivation.js.map +1 -0
  77. package/dist/unstable/reactivity/AtomHttpApi.d.ts +1 -2
  78. package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
  79. package/dist/unstable/reactivity/AtomHttpApi.js +2 -2
  80. package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
  81. package/dist/unstable/reactivity/AtomRpc.d.ts +1 -2
  82. package/dist/unstable/reactivity/AtomRpc.d.ts.map +1 -1
  83. package/dist/unstable/reactivity/AtomRpc.js +3 -3
  84. package/dist/unstable/reactivity/AtomRpc.js.map +1 -1
  85. package/dist/unstable/rpc/Rpc.d.ts +25 -4
  86. package/dist/unstable/rpc/Rpc.d.ts.map +1 -1
  87. package/dist/unstable/rpc/Rpc.js +26 -0
  88. package/dist/unstable/rpc/Rpc.js.map +1 -1
  89. package/dist/unstable/rpc/RpcClient.d.ts +3 -13
  90. package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
  91. package/dist/unstable/rpc/RpcClient.js +47 -23
  92. package/dist/unstable/rpc/RpcClient.js.map +1 -1
  93. package/dist/unstable/rpc/RpcGroup.d.ts +1 -1
  94. package/dist/unstable/rpc/RpcGroup.d.ts.map +1 -1
  95. package/dist/unstable/rpc/RpcMiddleware.d.ts +2 -2
  96. package/dist/unstable/rpc/RpcMiddleware.d.ts.map +1 -1
  97. package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
  98. package/dist/unstable/rpc/RpcServer.js +3 -2
  99. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  100. package/dist/unstable/rpc/Utils.d.ts +6 -0
  101. package/dist/unstable/rpc/Utils.d.ts.map +1 -1
  102. package/dist/unstable/rpc/Utils.js +44 -0
  103. package/dist/unstable/rpc/Utils.js.map +1 -1
  104. package/dist/unstable/schema/Model.d.ts +2 -2
  105. package/dist/unstable/schema/Model.d.ts.map +1 -1
  106. package/dist/unstable/schema/Model.js +2 -4
  107. package/dist/unstable/schema/Model.js.map +1 -1
  108. package/dist/unstable/schema/VariantSchema.d.ts +1 -1
  109. package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
  110. package/dist/unstable/schema/VariantSchema.js +1 -12
  111. package/dist/unstable/schema/VariantSchema.js.map +1 -1
  112. package/dist/unstable/workers/Transferable.d.ts +1 -1
  113. package/dist/unstable/workers/Transferable.d.ts.map +1 -1
  114. package/dist/unstable/workers/Transferable.js +1 -1
  115. package/dist/unstable/workers/Transferable.js.map +1 -1
  116. package/package.json +1 -1
  117. package/src/Equal.ts +17 -0
  118. package/src/Hash.ts +2 -2
  119. package/src/Semaphore.ts +2 -4
  120. package/src/unstable/ai/McpServer.ts +24 -22
  121. package/src/unstable/eventlog/Event.ts +0 -8
  122. package/src/unstable/eventlog/EventGroup.ts +0 -4
  123. package/src/unstable/eventlog/EventJournal.ts +144 -76
  124. package/src/unstable/eventlog/EventLog.ts +342 -221
  125. package/src/unstable/eventlog/EventLogEncryption.ts +16 -30
  126. package/src/unstable/eventlog/EventLogMessage.ts +277 -0
  127. package/src/unstable/eventlog/EventLogRemote.ts +261 -408
  128. package/src/unstable/eventlog/EventLogServer.ts +182 -274
  129. package/src/unstable/eventlog/EventLogServerEncrypted.ts +206 -0
  130. package/src/unstable/eventlog/EventLogServerUnencrypted.ts +749 -0
  131. package/src/unstable/eventlog/EventLogSessionAuth.ts +437 -0
  132. package/src/unstable/eventlog/{SqlEventLogJournal.ts → SqlEventJournal.ts} +26 -18
  133. package/src/unstable/eventlog/{SqlEventLogServer.ts → SqlEventLogServerEncrypted.ts} +102 -40
  134. package/src/unstable/eventlog/SqlEventLogServerUnencrypted.ts +500 -0
  135. package/src/unstable/eventlog/index.ts +27 -2
  136. package/src/unstable/eventlog/internal/identityRootSecretDerivation.ts +153 -0
  137. package/src/unstable/reactivity/AtomHttpApi.ts +23 -8
  138. package/src/unstable/reactivity/AtomRpc.ts +16 -5
  139. package/src/unstable/rpc/Rpc.ts +42 -4
  140. package/src/unstable/rpc/RpcClient.ts +59 -24
  141. package/src/unstable/rpc/RpcGroup.ts +1 -1
  142. package/src/unstable/rpc/RpcMiddleware.ts +2 -2
  143. package/src/unstable/rpc/RpcServer.ts +5 -3
  144. package/src/unstable/rpc/Utils.ts +59 -0
  145. package/src/unstable/schema/Model.ts +4 -6
  146. package/src/unstable/schema/VariantSchema.ts +4 -17
  147. package/src/unstable/workers/Transferable.ts +9 -11
  148. package/dist/unstable/eventlog/SqlEventLogJournal.d.ts.map +0 -1
  149. package/dist/unstable/eventlog/SqlEventLogJournal.js.map +0 -1
  150. package/dist/unstable/eventlog/SqlEventLogServer.d.ts.map +0 -1
  151. package/dist/unstable/eventlog/SqlEventLogServer.js.map +0 -1
@@ -1,304 +1,212 @@
1
1
  /**
2
2
  * @since 4.0.0
3
3
  */
4
- import * as Uuid from "uuid"
5
- import type * as Cause from "../../Cause.ts"
4
+ import type { NonEmptyReadonlyArray } from "../../Array.ts"
5
+ import * as Arr from "../../Array.ts"
6
+ import * as Cache from "../../Cache.ts"
6
7
  import * as Context from "../../Context.ts"
8
+ import * as Data from "../../Data.ts"
7
9
  import * as Effect from "../../Effect.ts"
8
- import * as FiberMap from "../../FiberMap.ts"
10
+ import * as Equal from "../../Equal.ts"
11
+ import * as Hash from "../../Hash.ts"
9
12
  import * as Layer from "../../Layer.ts"
10
- import * as PubSub from "../../PubSub.ts"
11
- import * as Queue from "../../Queue.ts"
12
- import * as RcMap from "../../RcMap.ts"
13
- import * as Schema from "../../Schema.ts"
14
- import type * as Scope from "../../Scope.ts"
15
- import type * as HttpServerError from "../http/HttpServerError.ts"
16
- import * as HttpServerRequest from "../http/HttpServerRequest.ts"
17
- import * as HttpServerResponse from "../http/HttpServerResponse.ts"
18
- import type * as Socket from "../socket/Socket.ts"
19
- import { EntryId, makeRemoteIdUnsafe, type RemoteId } from "./EventJournal.ts"
20
- import type { EncryptedRemoteEntry } from "./EventLogEncryption.ts"
13
+ import * as Option from "../../Option.ts"
14
+ import * as Redacted from "../../Redacted.ts"
15
+ import * as Stream from "../../Stream.ts"
16
+ import type * as Rpc from "../rpc/Rpc.ts"
17
+ import type * as RpcGroup from "../rpc/RpcGroup.ts"
18
+ import type { RemoteId } from "./EventJournal.ts"
19
+ import * as EventLog from "./EventLog.ts"
21
20
  import {
22
- Ack,
23
- Changes,
24
21
  ChunkedMessage,
25
- decodeRequest,
26
- encodeResponse,
27
- Hello,
28
- Pong,
29
- type ProtocolRequest,
30
- type ProtocolResponse
31
- } from "./EventLogRemote.ts"
22
+ EventLogAuthentication,
23
+ EventLogProtocolError,
24
+ EventLogRemoteRpcs,
25
+ HelloResponse,
26
+ SingleMessage,
27
+ type StoreId
28
+ } from "./EventLogMessage.ts"
29
+ import * as EventLogSessionAuth from "./EventLogSessionAuth.ts"
32
30
 
33
- const constChunkSize = 512_000
31
+ /**
32
+ * @since 4.0.0
33
+ * @category Layers
34
+ */
35
+ export const layerAuthMiddleware: Layer.Layer<
36
+ EventLogAuthentication
37
+ > = Layer.succeed(EventLogAuthentication, (effect, { client, rpc }) => {
38
+ const identity = Context.getOrUndefined(client.annotations, EventLog.Identity)
39
+ if (identity) return Effect.provideService(effect, EventLog.Identity, identity)
40
+ return Effect.fail(
41
+ new EventLogProtocolError({
42
+ requestTag: rpc._tag,
43
+ publicKey: undefined,
44
+ code: "Forbidden",
45
+ message: "Unauthenticated request"
46
+ })
47
+ )
48
+ })
34
49
 
35
50
  /**
36
51
  * @since 4.0.0
37
- * @category constructors
52
+ * @category Layers
38
53
  */
39
- export const makeHandler: Effect.Effect<
40
- (socket: Socket.Socket) => Effect.Effect<void, Socket.SocketError>,
41
- never,
42
- Storage
43
- > = Effect.gen(function*() {
44
- const storage = yield* Storage
45
- const remoteId = yield* storage.getId
46
- let chunkId = 0
54
+ export const layerRpcHandlers = (options: {
55
+ readonly remoteId: RemoteId
56
+ readonly getOrCreateSessionAuthBinding: (
57
+ publicKey: string,
58
+ signingPublicKey: Uint8Array<ArrayBuffer>
59
+ ) => Effect.Effect<Uint8Array<ArrayBuffer>>
60
+ readonly onWrite: (
61
+ data: Uint8Array<ArrayBuffer>
62
+ ) => Effect.Effect<void, EventLogProtocolError>
63
+ readonly changes: (options: {
64
+ readonly publicKey: string
65
+ readonly storeId: StoreId
66
+ readonly startSequence: number
67
+ }) => Stream.Stream<Uint8Array<ArrayBuffer>, unknown>
68
+ }): Layer.Layer<
69
+ Rpc.ToHandler<RpcGroup.Rpcs<typeof EventLogRemoteRpcs>> | EventLogAuthentication
70
+ > =>
71
+ EventLogRemoteRpcs.toLayer(Effect.gen(function*() {
72
+ const clientChallenges = yield* Cache.make({
73
+ lookup: (_clientId: number) => Effect.orDie(EventLogSessionAuth.makeSessionAuthChallenge),
74
+ capacity: Number.MAX_SAFE_INTEGER,
75
+ timeToLive: EventLogSessionAuth.SessionAuthChallengeTimeToLiveMillis
76
+ })
77
+ let chunkedIdCounter = 0
47
78
 
48
- return Effect.fnUntraced(
49
- function*(socket: Socket.Socket) {
50
- const subscriptions = yield* FiberMap.make<string>()
51
- const writeRaw = yield* socket.writer
52
- const chunks = new Map<
53
- number,
54
- {
55
- readonly parts: Array<Uint8Array>
56
- count: number
57
- bytes: number
58
- }
59
- >()
60
- let latestSequence = -1
79
+ const persistedSigningPublicKeys = yield* Cache.make({
80
+ lookup: (key: SessionAuthCacheKey) =>
81
+ options.getOrCreateSessionAuthBinding(key.publicKey, key.signingPublicKey).pipe(
82
+ Effect.catchCause((_) =>
83
+ Effect.fail(
84
+ new EventLogProtocolError({
85
+ requestTag: "Authenticate",
86
+ publicKey: key.publicKey,
87
+ code: "Forbidden",
88
+ message: "Session auth binding lookup failed"
89
+ })
90
+ )
91
+ )
92
+ ),
93
+ capacity: 4096
94
+ })
61
95
 
62
- const write = Effect.fnUntraced(function*(response: Schema.Schema.Type<typeof ProtocolResponse>) {
63
- const data = yield* encodeResponse(response)
64
- if (response._tag !== "Changes" || data.byteLength <= constChunkSize) {
65
- return yield* writeRaw(data)
66
- }
67
- const id = chunkId++
68
- for (const part of ChunkedMessage.split(id, data)) {
69
- yield* writeRaw(yield* encodeResponse(part))
96
+ return EventLogRemoteRpcs.of({
97
+ "EventLog.Hello": Effect.fnUntraced(function*(_, { client }) {
98
+ const challenge = yield* Cache.get(clientChallenges, client.id)
99
+ return new HelloResponse({
100
+ remoteId: options.remoteId,
101
+ challenge
102
+ })
103
+ }),
104
+ "EventLog.Authenticate": Effect.fnUntraced(function*(request, { client }) {
105
+ const challenge = Option.getOrNull(yield* Cache.getOption(clientChallenges, client.id))
106
+ if (!challenge) {
107
+ return new EventLogProtocolError({
108
+ requestTag: "Authenticate",
109
+ publicKey: request.publicKey,
110
+ code: "Forbidden",
111
+ message: "Session auth challenge has expired"
112
+ })
70
113
  }
71
- })
114
+ yield* Cache.invalidate(clientChallenges, client.id)
115
+ const signingPublicKey = yield* Cache.get(
116
+ persistedSigningPublicKeys,
117
+ new SessionAuthCacheKey({
118
+ publicKey: request.publicKey,
119
+ signingPublicKey: request.signingPublicKey
120
+ })
121
+ )
122
+ const verified = yield* EventLogSessionAuth.verifySessionAuthenticateRequest({
123
+ remoteId: options.remoteId,
124
+ challenge,
125
+ publicKey: request.publicKey,
126
+ signingPublicKey,
127
+ signature: request.signature,
128
+ algorithm: request.algorithm
129
+ }).pipe(
130
+ Effect.catch(() => Effect.succeed(false))
131
+ )
72
132
 
73
- yield* Effect.forkChild(Effect.orDie(write(new Hello({ remoteId }))))
133
+ if (!verified) {
134
+ return yield* new EventLogProtocolError({
135
+ requestTag: "Authenticate",
136
+ publicKey: request.publicKey,
137
+ code: "Forbidden",
138
+ message: "Session auth signature verification failed"
139
+ })
140
+ }
74
141
 
75
- const handleRequest = (request: Schema.Schema.Type<typeof ProtocolRequest>): Effect.Effect<void> => {
76
- switch (request._tag) {
77
- case "Ping": {
78
- return Effect.orDie(write(new Pong({ id: request.id })))
79
- }
80
- case "WriteEntries": {
81
- if (request.encryptedEntries.length === 0) {
82
- return Effect.orDie(
83
- write(
84
- new Ack({
85
- id: request.id,
86
- sequenceNumbers: []
87
- })
88
- )
89
- )
142
+ client
143
+ .annotate(EventLog.Identity, {
144
+ publicKey: request.publicKey,
145
+ privateKey: constEmptyPrivateKey
146
+ })
147
+ .annotate(ChunkedMessageState, new Map())
148
+ }),
149
+ "EventLog.WriteSingle": Effect.fnUntraced(function*(request) {
150
+ yield* options.onWrite(request.data)
151
+ }),
152
+ "EventLog.WriteChunked": Effect.fnUntraced(function*(request, { client }) {
153
+ const state = Context.get(client.annotations, ChunkedMessageState)
154
+ const data = ChunkedMessage.join(state, request)
155
+ if (!data) return
156
+ yield* options.onWrite(data)
157
+ }),
158
+ "EventLog.Changes": (request) =>
159
+ options.changes({
160
+ publicKey: request.publicKey,
161
+ storeId: request.storeId,
162
+ startSequence: request.startSequence
163
+ }).pipe(
164
+ Stream.mapArray(Arr.flatMap((data): NonEmptyReadonlyArray<SingleMessage | ChunkedMessage> => {
165
+ if (data.byteLength <= ChunkedMessage.chunkSize) {
166
+ return [new SingleMessage({ data })]
90
167
  }
91
- return Effect.gen(function*() {
92
- const entries = request.encryptedEntries.map(({ encryptedEntry, entryId }) =>
93
- new PersistedEntry({
94
- entryId,
95
- iv: request.iv,
96
- encryptedEntry
97
- })
98
- )
99
- const encrypted = yield* storage.write(request.publicKey, entries)
100
- latestSequence = encrypted[encrypted.length - 1].sequence
101
- return yield* Effect.orDie(
102
- write(
103
- new Ack({
104
- id: request.id,
105
- sequenceNumbers: encrypted.map((entry) => entry.sequence)
106
- })
107
- )
108
- )
109
- })
110
- }
111
- case "RequestChanges": {
112
- return Effect.gen(function*() {
113
- const changes = yield* storage.changes(request.publicKey, request.startSequence)
114
- return yield* Queue.takeAll(changes).pipe(
115
- Effect.flatMap((entries) => {
116
- const latestEntries: Array<EncryptedRemoteEntry> = []
117
- for (const entry of entries) {
118
- if (entry.sequence <= latestSequence) continue
119
- latestEntries.push(entry)
120
- latestSequence = entry.sequence
121
- }
122
- if (latestEntries.length === 0) return Effect.void
123
- return Effect.orDie(
124
- write(
125
- new Changes({
126
- publicKey: request.publicKey,
127
- entries: latestEntries
128
- })
129
- )
130
- )
131
- }),
132
- Effect.forever
133
- )
134
- }).pipe(
135
- Effect.scoped,
136
- FiberMap.run(subscriptions, request.publicKey)
168
+ return ChunkedMessage.split(chunkedIdCounter++, data)
169
+ })),
170
+ Stream.catchCause((_) =>
171
+ Stream.fail(
172
+ new EventLogProtocolError({
173
+ requestTag: "Changes",
174
+ publicKey: request.publicKey,
175
+ code: "InternalServerError",
176
+ message: "Decoding failure"
177
+ })
137
178
  )
138
- }
139
- case "StopChanges": {
140
- return FiberMap.remove(subscriptions, request.publicKey)
141
- }
142
- case "ChunkedMessage": {
143
- const data = ChunkedMessage.join(chunks, request)
144
- if (!data) return Effect.void
145
- return Effect.flatMap(Effect.orDie(decodeRequest(data)), handleRequest)
146
- }
147
- }
148
- }
149
-
150
- yield* socket.run((data) => Effect.flatMap(Effect.orDie(decodeRequest(data)), handleRequest)).pipe(
151
- Effect.catchCause((cause) => Effect.logDebug(cause))
152
- )
153
- },
154
- Effect.scoped,
155
- Effect.annotateLogs({
156
- module: "EventLogServer"
179
+ )
180
+ )
157
181
  })
182
+ })).pipe(
183
+ Layer.merge(layerAuthMiddleware)
158
184
  )
159
- })
160
185
 
161
186
  /**
162
187
  * @since 4.0.0
163
- * @category websockets
188
+ * @category ChunkedMessage state
164
189
  */
165
- export const makeHandlerHttp: Effect.Effect<
166
- Effect.Effect<
167
- HttpServerResponse.HttpServerResponse,
168
- HttpServerError.HttpServerError | Socket.SocketError,
169
- HttpServerRequest.HttpServerRequest | Scope.Scope
170
- >,
171
- never,
172
- Storage
173
- > = Effect.gen(function*() {
174
- const handler = yield* makeHandler
175
-
176
- // @effect-diagnostics-next-line returnEffectInGen:off
177
- return Effect.gen(function*() {
178
- const request = yield* HttpServerRequest.HttpServerRequest
179
- const socket = yield* request.upgrade
180
- yield* handler(socket)
181
- return HttpServerResponse.empty()
182
- }).pipe(Effect.annotateLogs({
183
- module: "EventLogServer"
184
- }))
185
- })
190
+ export class ChunkedMessageState extends Context.Reference<
191
+ Map<number, {
192
+ readonly parts: Array<Uint8Array>
193
+ count: number
194
+ bytes: number
195
+ }>
196
+ >("effect/eventlog/EventLogServer/ChunkedMessageState", {
197
+ defaultValue: () => new Map()
198
+ }) {}
186
199
 
187
- /**
188
- * @since 4.0.0
189
- * @category storage
190
- */
191
- export class PersistedEntry extends Schema.Class<PersistedEntry>(
192
- "effect/eventlog/EventLogServer/PersistedEntry"
193
- )({
194
- entryId: EntryId,
195
- iv: Schema.Uint8Array,
196
- encryptedEntry: Schema.Uint8Array
197
- }) {
198
- /**
199
- * @since 4.0.0
200
- */
201
- get entryIdString(): string {
202
- return Uuid.stringify(this.entryId)
200
+ class SessionAuthCacheKey extends Data.Class<{
201
+ readonly publicKey: string
202
+ readonly signingPublicKey: Uint8Array<ArrayBuffer>
203
+ }> {
204
+ [Equal.symbol](that: SessionAuthCacheKey) {
205
+ return this.publicKey === that.publicKey
203
206
  }
204
- }
205
-
206
- /**
207
- * @since 4.0.0
208
- * @category storage
209
- */
210
- export class Storage extends Context.Service<Storage, {
211
- readonly getId: Effect.Effect<RemoteId>
212
- readonly write: (
213
- publicKey: string,
214
- entries: ReadonlyArray<PersistedEntry>
215
- ) => Effect.Effect<ReadonlyArray<EncryptedRemoteEntry>>
216
- readonly entries: (
217
- publicKey: string,
218
- startSequence: number
219
- ) => Effect.Effect<ReadonlyArray<EncryptedRemoteEntry>>
220
- readonly changes: (
221
- publicKey: string,
222
- startSequence: number
223
- ) => Effect.Effect<Queue.Dequeue<EncryptedRemoteEntry, Cause.Done>, never, Scope.Scope>
224
- }>()("effect/eventlog/EventLogServer/Storage") {}
225
-
226
- /**
227
- * @since 4.0.0
228
- * @category storage
229
- */
230
- export const makeStorageMemory: Effect.Effect<Storage["Service"], never, Scope.Scope> = Effect.gen(function*() {
231
- const knownIds = new Map<string, number>()
232
- const journals = new Map<string, Array<EncryptedRemoteEntry>>()
233
- const remoteId = makeRemoteIdUnsafe()
234
- const ensureJournal = (publicKey: string) => {
235
- let journal = journals.get(publicKey)
236
- if (journal) return journal
237
- journal = []
238
- journals.set(publicKey, journal)
239
- return journal
207
+ [Hash.symbol]() {
208
+ return Hash.string(this.publicKey)
240
209
  }
241
- const pubsubs = yield* RcMap.make({
242
- lookup: (_publicKey: string) =>
243
- Effect.acquireRelease(
244
- PubSub.unbounded<EncryptedRemoteEntry>(),
245
- PubSub.shutdown
246
- ),
247
- idleTimeToLive: 60000
248
- })
249
-
250
- return Storage.of({
251
- getId: Effect.succeed(remoteId),
252
- write: (publicKey, entries) =>
253
- Effect.gen(function*() {
254
- const active = yield* RcMap.keys(pubsubs)
255
- let pubsub: PubSub.PubSub<EncryptedRemoteEntry> | undefined
256
- for (const key of active) {
257
- if (key === publicKey) {
258
- pubsub = yield* RcMap.get(pubsubs, publicKey)
259
- break
260
- }
261
- }
262
- const journal = ensureJournal(publicKey)
263
- const encryptedEntries: Array<EncryptedRemoteEntry> = []
264
- for (const entry of entries) {
265
- const idString = entry.entryIdString
266
- if (knownIds.has(idString)) continue
267
- const encrypted: EncryptedRemoteEntry = {
268
- sequence: journal.length,
269
- entryId: entry.entryId,
270
- iv: entry.iv,
271
- encryptedEntry: entry.encryptedEntry
272
- }
273
- encryptedEntries.push(encrypted)
274
- knownIds.set(idString, encrypted.sequence)
275
- journal.push(encrypted)
276
- if (pubsub) {
277
- yield* PubSub.publish(pubsub, encrypted)
278
- }
279
- }
280
- return encryptedEntries
281
- }).pipe(Effect.scoped),
282
- entries: (publicKey, startSequence) => Effect.sync(() => ensureJournal(publicKey).slice(startSequence)),
283
- changes: (publicKey, startSequence) =>
284
- Effect.gen(function*() {
285
- const queue = yield* Queue.make<EncryptedRemoteEntry>()
286
- const pubsub = yield* RcMap.get(pubsubs, publicKey)
287
- const subscription = yield* PubSub.subscribe(pubsub)
288
- yield* Queue.offerAll(queue, ensureJournal(publicKey).slice(startSequence))
289
- yield* PubSub.takeAll(subscription).pipe(
290
- Effect.flatMap((chunk) => Queue.offerAll(queue, chunk)),
291
- Effect.forever,
292
- Effect.forkScoped
293
- )
294
- yield* Effect.addFinalizer(() => Queue.shutdown(queue))
295
- return Queue.asDequeue(queue)
296
- })
297
- })
298
- })
210
+ }
299
211
 
300
- /**
301
- * @since 4.0.0
302
- * @category storage
303
- */
304
- export const layerStorageMemory: Layer.Layer<Storage> = Layer.effect(Storage)(makeStorageMemory)
212
+ const constEmptyPrivateKey = Redacted.make(new Uint8Array(32))