envio 3.0.0-alpha.2 → 3.0.0-alpha.20

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 (175) hide show
  1. package/README.md +164 -30
  2. package/bin.mjs +49 -0
  3. package/evm.schema.json +79 -169
  4. package/fuel.schema.json +50 -21
  5. package/index.d.ts +497 -1
  6. package/index.js +4 -0
  7. package/package.json +42 -31
  8. package/rescript.json +4 -1
  9. package/src/Batch.res +11 -8
  10. package/src/Batch.res.mjs +11 -9
  11. package/src/ChainFetcher.res +531 -0
  12. package/src/ChainFetcher.res.mjs +339 -0
  13. package/src/ChainManager.res +190 -0
  14. package/src/ChainManager.res.mjs +166 -0
  15. package/src/Change.res +3 -3
  16. package/src/Config.gen.ts +19 -0
  17. package/src/Config.res +737 -22
  18. package/src/Config.res.mjs +703 -26
  19. package/src/{Indexer.res → Ctx.res} +1 -1
  20. package/src/Ecosystem.res +9 -124
  21. package/src/Ecosystem.res.mjs +19 -160
  22. package/src/Env.res +30 -74
  23. package/src/Env.res.mjs +25 -87
  24. package/src/Envio.gen.ts +3 -1
  25. package/src/Envio.res +20 -9
  26. package/src/EventProcessing.res +469 -0
  27. package/src/EventProcessing.res.mjs +337 -0
  28. package/src/EvmTypes.gen.ts +6 -0
  29. package/src/EvmTypes.res +1 -0
  30. package/src/FetchState.res +1256 -639
  31. package/src/FetchState.res.mjs +1135 -612
  32. package/src/GlobalState.res +1190 -0
  33. package/src/GlobalState.res.mjs +1183 -0
  34. package/src/GlobalStateManager.res +68 -0
  35. package/src/GlobalStateManager.res.mjs +75 -0
  36. package/src/GlobalStateManager.resi +7 -0
  37. package/src/HandlerLoader.res +89 -0
  38. package/src/HandlerLoader.res.mjs +79 -0
  39. package/src/HandlerRegister.res +357 -0
  40. package/src/HandlerRegister.res.mjs +299 -0
  41. package/src/{EventRegister.resi → HandlerRegister.resi} +13 -13
  42. package/src/Hasura.res +111 -175
  43. package/src/Hasura.res.mjs +88 -150
  44. package/src/InMemoryStore.res +1 -1
  45. package/src/InMemoryStore.res.mjs +3 -3
  46. package/src/InMemoryTable.res +1 -1
  47. package/src/InMemoryTable.res.mjs +1 -1
  48. package/src/Internal.gen.ts +4 -0
  49. package/src/Internal.res +230 -12
  50. package/src/Internal.res.mjs +115 -1
  51. package/src/LoadLayer.res +444 -0
  52. package/src/LoadLayer.res.mjs +296 -0
  53. package/src/LoadLayer.resi +32 -0
  54. package/src/LogSelection.res +33 -27
  55. package/src/LogSelection.res.mjs +6 -0
  56. package/src/Logging.res +21 -7
  57. package/src/Logging.res.mjs +16 -8
  58. package/src/Main.res +377 -0
  59. package/src/Main.res.mjs +339 -0
  60. package/src/Persistence.res +7 -21
  61. package/src/Persistence.res.mjs +3 -3
  62. package/src/PgStorage.gen.ts +10 -0
  63. package/src/PgStorage.res +116 -69
  64. package/src/PgStorage.res.d.mts +5 -0
  65. package/src/PgStorage.res.mjs +93 -50
  66. package/src/Prometheus.res +294 -224
  67. package/src/Prometheus.res.mjs +353 -340
  68. package/src/ReorgDetection.res +6 -10
  69. package/src/ReorgDetection.res.mjs +6 -6
  70. package/src/SafeCheckpointTracking.res +4 -4
  71. package/src/SafeCheckpointTracking.res.mjs +2 -2
  72. package/src/Sink.res +4 -2
  73. package/src/Sink.res.mjs +2 -1
  74. package/src/TableIndices.res +0 -1
  75. package/src/TestIndexer.res +692 -0
  76. package/src/TestIndexer.res.mjs +527 -0
  77. package/src/TestIndexerProxyStorage.res +205 -0
  78. package/src/TestIndexerProxyStorage.res.mjs +151 -0
  79. package/src/TopicFilter.res +1 -1
  80. package/src/Types.ts +1 -1
  81. package/src/UserContext.res +424 -0
  82. package/src/UserContext.res.mjs +279 -0
  83. package/src/Utils.res +97 -26
  84. package/src/Utils.res.mjs +91 -44
  85. package/src/bindings/BigInt.res +10 -0
  86. package/src/bindings/BigInt.res.mjs +15 -0
  87. package/src/bindings/ClickHouse.res +120 -23
  88. package/src/bindings/ClickHouse.res.mjs +118 -28
  89. package/src/bindings/DateFns.res +74 -0
  90. package/src/bindings/DateFns.res.mjs +22 -0
  91. package/src/bindings/EventSource.res +8 -1
  92. package/src/bindings/EventSource.res.mjs +8 -1
  93. package/src/bindings/Express.res +1 -0
  94. package/src/bindings/Hrtime.res +14 -1
  95. package/src/bindings/Hrtime.res.mjs +22 -2
  96. package/src/bindings/Hrtime.resi +4 -0
  97. package/src/bindings/Lodash.res +0 -1
  98. package/src/bindings/NodeJs.res +49 -3
  99. package/src/bindings/NodeJs.res.mjs +11 -3
  100. package/src/bindings/Pino.res +24 -10
  101. package/src/bindings/Pino.res.mjs +14 -8
  102. package/src/bindings/Postgres.gen.ts +8 -0
  103. package/src/bindings/Postgres.res +5 -1
  104. package/src/bindings/Postgres.res.d.mts +5 -0
  105. package/src/bindings/PromClient.res +0 -10
  106. package/src/bindings/PromClient.res.mjs +0 -3
  107. package/src/bindings/Vitest.res +142 -0
  108. package/src/bindings/Vitest.res.mjs +9 -0
  109. package/src/bindings/WebSocket.res +27 -0
  110. package/src/bindings/WebSocket.res.mjs +2 -0
  111. package/src/bindings/Yargs.res +8 -0
  112. package/src/bindings/Yargs.res.mjs +2 -0
  113. package/src/db/EntityHistory.res +7 -7
  114. package/src/db/EntityHistory.res.mjs +9 -9
  115. package/src/db/InternalTable.res +59 -111
  116. package/src/db/InternalTable.res.mjs +73 -104
  117. package/src/db/Table.res +27 -8
  118. package/src/db/Table.res.mjs +25 -14
  119. package/src/sources/Evm.res +84 -0
  120. package/src/sources/Evm.res.mjs +105 -0
  121. package/src/sources/EvmChain.res +94 -0
  122. package/src/sources/EvmChain.res.mjs +60 -0
  123. package/src/sources/Fuel.res +19 -34
  124. package/src/sources/Fuel.res.mjs +34 -16
  125. package/src/sources/FuelSDK.res +38 -0
  126. package/src/sources/FuelSDK.res.mjs +29 -0
  127. package/src/sources/HyperFuel.res +2 -2
  128. package/src/sources/HyperFuel.resi +1 -1
  129. package/src/sources/HyperFuelClient.res +2 -2
  130. package/src/sources/HyperFuelSource.res +33 -13
  131. package/src/sources/HyperFuelSource.res.mjs +24 -16
  132. package/src/sources/HyperSync.res +36 -6
  133. package/src/sources/HyperSync.res.mjs +9 -7
  134. package/src/sources/HyperSync.resi +4 -0
  135. package/src/sources/HyperSyncClient.res +1 -1
  136. package/src/sources/HyperSyncHeightStream.res +47 -116
  137. package/src/sources/HyperSyncHeightStream.res.mjs +46 -73
  138. package/src/sources/HyperSyncSource.res +118 -139
  139. package/src/sources/HyperSyncSource.res.mjs +104 -121
  140. package/src/sources/Rpc.res +86 -14
  141. package/src/sources/Rpc.res.mjs +101 -9
  142. package/src/sources/RpcSource.res +621 -364
  143. package/src/sources/RpcSource.res.mjs +843 -410
  144. package/src/sources/RpcWebSocketHeightStream.res +181 -0
  145. package/src/sources/RpcWebSocketHeightStream.res.mjs +196 -0
  146. package/src/sources/Source.res +7 -5
  147. package/src/sources/SourceManager.res +325 -225
  148. package/src/sources/SourceManager.res.mjs +314 -171
  149. package/src/sources/SourceManager.resi +17 -6
  150. package/src/sources/Svm.res +81 -0
  151. package/src/sources/Svm.res.mjs +90 -0
  152. package/src/tui/Tui.res +247 -0
  153. package/src/tui/Tui.res.mjs +337 -0
  154. package/src/tui/bindings/Ink.res +371 -0
  155. package/src/tui/bindings/Ink.res.mjs +72 -0
  156. package/src/tui/bindings/Style.res +123 -0
  157. package/src/tui/bindings/Style.res.mjs +2 -0
  158. package/src/tui/components/BufferedProgressBar.res +40 -0
  159. package/src/tui/components/BufferedProgressBar.res.mjs +57 -0
  160. package/src/tui/components/CustomHooks.res +122 -0
  161. package/src/tui/components/CustomHooks.res.mjs +179 -0
  162. package/src/tui/components/Messages.res +41 -0
  163. package/src/tui/components/Messages.res.mjs +75 -0
  164. package/src/tui/components/SyncETA.res +174 -0
  165. package/src/tui/components/SyncETA.res.mjs +263 -0
  166. package/src/tui/components/TuiData.res +47 -0
  167. package/src/tui/components/TuiData.res.mjs +34 -0
  168. package/svm.schema.json +112 -0
  169. package/bin.js +0 -48
  170. package/src/EventRegister.res +0 -241
  171. package/src/EventRegister.res.mjs +0 -240
  172. package/src/bindings/Ethers.gen.ts +0 -14
  173. package/src/bindings/Ethers.res +0 -204
  174. package/src/bindings/Ethers.res.mjs +0 -130
  175. /package/src/{Indexer.res.mjs → Ctx.res.mjs} +0 -0
@@ -0,0 +1,424 @@
1
+ let codegenHelpMessage = `Rerun 'pnpm dev' to update generated code after schema.graphql changes.`
2
+
3
+ type contextParams = {
4
+ item: Internal.item,
5
+ checkpointId: Internal.checkpointId,
6
+ inMemoryStore: InMemoryStore.t,
7
+ loadManager: LoadManager.t,
8
+ persistence: Persistence.t,
9
+ isPreload: bool,
10
+ shouldSaveHistory: bool,
11
+ chains: Internal.chains,
12
+ config: Config.t,
13
+ mutable isResolved: bool,
14
+ }
15
+
16
+ // We don't want to expose the params to the user
17
+ // so instead of storing _params on the context object,
18
+ // we use an external WeakMap
19
+ let paramsByThis: Utils.WeakMap.t<unknown, contextParams> = Utils.WeakMap.make()
20
+
21
+ let effectContextPrototype = %raw(`Object.create(null)`)
22
+ Utils.Object.defineProperty(
23
+ effectContextPrototype,
24
+ "log",
25
+ {
26
+ get: () => {
27
+ (paramsByThis->Utils.WeakMap.unsafeGet(%raw(`this`))).item->Logging.getUserLogger
28
+ },
29
+ },
30
+ )
31
+ %%raw(`
32
+ var EffectContext = function(params, defaultShouldCache, callEffect) {
33
+ paramsByThis.set(this, params);
34
+ this.effect = callEffect;
35
+ this.cache = defaultShouldCache;
36
+ };
37
+ EffectContext.prototype = effectContextPrototype;
38
+ `)
39
+
40
+ @new
41
+ external makeEffectContext: (
42
+ contextParams,
43
+ ~defaultShouldCache: bool,
44
+ ~callEffect: (Internal.effect, Internal.effectInput) => promise<Internal.effectOutput>,
45
+ ) => Internal.effectContext = "EffectContext"
46
+
47
+ let initEffect = (params: contextParams) => {
48
+ let rec callEffect = (effect: Internal.effect, input: Internal.effectInput) => {
49
+ let effectContext = makeEffectContext(
50
+ params,
51
+ ~defaultShouldCache=effect.defaultShouldCache,
52
+ ~callEffect,
53
+ )
54
+ let effectArgs: Internal.effectArgs = {
55
+ input,
56
+ context: effectContext,
57
+ cacheKey: input->S.reverseConvertOrThrow(effect.input)->Utils.Hash.makeOrThrow,
58
+ }
59
+ LoadLayer.loadEffect(
60
+ ~loadManager=params.loadManager,
61
+ ~persistence=params.persistence,
62
+ ~effect,
63
+ ~effectArgs,
64
+ ~inMemoryStore=params.inMemoryStore,
65
+ ~shouldGroup=params.isPreload,
66
+ ~item=params.item,
67
+ )
68
+ }
69
+ callEffect
70
+ }
71
+
72
+ type entityContextParams = {
73
+ ...contextParams,
74
+ entityConfig: Internal.entityConfig,
75
+ }
76
+
77
+ let getWhereHandler = (params: entityContextParams, filter: Js.Dict.t<Js.Dict.t<unknown>>) => {
78
+ let entityConfig = params.entityConfig
79
+ let filterKeys = filter->Js.Dict.keys
80
+
81
+ if filterKeys->Array.length === 0 {
82
+ Js.Exn.raiseError(
83
+ `Empty filter passed to context.${entityConfig.name}.getWhere(). Please provide a filter like { fieldName: { _eq: value } }.`,
84
+ )
85
+ }
86
+ if filterKeys->Array.length > 1 {
87
+ Js.Exn.raiseError(
88
+ `Multiple filter fields passed to context.${entityConfig.name}.getWhere(). Currently only one filter field per call is supported. Received fields: ${filterKeys->Js.Array2.joinWith(
89
+ ", ",
90
+ )}.`,
91
+ )
92
+ }
93
+
94
+ let dbFieldName = filterKeys->Js.Array2.unsafe_get(0)
95
+ let operatorObj = filter->Js.Dict.unsafeGet(dbFieldName)
96
+ let operatorKeys = operatorObj->Js.Dict.keys
97
+
98
+ if operatorKeys->Array.length === 0 {
99
+ Js.Exn.raiseError(
100
+ `Empty operator passed to context.${entityConfig.name}.getWhere({ ${dbFieldName}: {} }). Please provide an operator like { _eq: value }, { _gt: value }, { _lt: value }, { _gte: value }, { _lte: value }, or { _in: [values] }.`,
101
+ )
102
+ }
103
+ if operatorKeys->Array.length > 1 {
104
+ Js.Exn.raiseError(
105
+ `Multiple operators passed to context.${entityConfig.name}.getWhere({ ${dbFieldName}: ... }). Currently only one operator per filter field is supported. Received operators: ${operatorKeys->Js.Array2.joinWith(
106
+ ", ",
107
+ )}.`,
108
+ )
109
+ }
110
+
111
+ let operatorKey = operatorKeys->Js.Array2.unsafe_get(0)
112
+
113
+ let fieldSchema = switch entityConfig.table->Table.getFieldByDbName(dbFieldName) {
114
+ | None =>
115
+ Js.Exn.raiseError(
116
+ `Invalid field "${dbFieldName}" in context.${entityConfig.name}.getWhere(). The field doesn't exist. ${codegenHelpMessage}`,
117
+ )
118
+ | Some(DerivedFrom(_)) =>
119
+ Js.Exn.raiseError(
120
+ `The field "${dbFieldName}" on entity "${entityConfig.name}" is a derived field and cannot be used in getWhere(). Use the source entity's indexed field instead.`,
121
+ )
122
+ | Some(Field({isIndex: false, linkedEntity: None})) =>
123
+ Js.Exn.raiseError(
124
+ `The field "${dbFieldName}" on entity "${entityConfig.name}" does not have an index. To use it in getWhere(), add the @index directive in your schema.graphql:\n\n ${dbFieldName}: ... @index\n\nThen run 'pnpm envio codegen' to regenerate.`,
125
+ )
126
+ | Some(Field({fieldSchema})) => fieldSchema
127
+ }
128
+
129
+ if operatorKey === "_in" {
130
+ let fieldValues =
131
+ operatorObj
132
+ ->Js.Dict.unsafeGet(operatorKey)
133
+ ->(Utils.magic: unknown => array<unknown>)
134
+
135
+ fieldValues
136
+ ->Js.Array2.map(fieldValue =>
137
+ LoadLayer.loadByField(
138
+ ~loadManager=params.loadManager,
139
+ ~persistence=params.persistence,
140
+ ~operator=Eq,
141
+ ~entityConfig,
142
+ ~fieldName=dbFieldName,
143
+ ~fieldValueSchema=fieldSchema,
144
+ ~inMemoryStore=params.inMemoryStore,
145
+ ~shouldGroup=params.isPreload,
146
+ ~item=params.item,
147
+ ~fieldValue,
148
+ )
149
+ )
150
+ ->Promise.all
151
+ ->Promise.thenResolve(results => results->Belt.Array.concatMany)
152
+ } else if operatorKey === "_gte" || operatorKey === "_lte" {
153
+ // _gte and _lte are composed from Eq + Gt/Lt
154
+ let rangeOperator: TableIndices.Operator.t = operatorKey === "_gte" ? Gt : Lt
155
+ let fieldValue = operatorObj->Js.Dict.unsafeGet(operatorKey)
156
+
157
+ let loadWithOperator = operator =>
158
+ LoadLayer.loadByField(
159
+ ~loadManager=params.loadManager,
160
+ ~persistence=params.persistence,
161
+ ~operator,
162
+ ~entityConfig,
163
+ ~fieldName=dbFieldName,
164
+ ~fieldValueSchema=fieldSchema,
165
+ ~inMemoryStore=params.inMemoryStore,
166
+ ~shouldGroup=params.isPreload,
167
+ ~item=params.item,
168
+ ~fieldValue,
169
+ )
170
+
171
+ [loadWithOperator(Eq), loadWithOperator(rangeOperator)]
172
+ ->Promise.all
173
+ ->Promise.thenResolve(results => results->Belt.Array.concatMany)
174
+ } else {
175
+ let operator: TableIndices.Operator.t = switch operatorKey {
176
+ | "_eq" => Eq
177
+ | "_gt" => Gt
178
+ | "_lt" => Lt
179
+ | _ =>
180
+ Js.Exn.raiseError(
181
+ `Invalid operator "${operatorKey}" in context.${entityConfig.name}.getWhere({ ${dbFieldName}: { ${operatorKey}: ... } }). Valid operators are _eq, _gt, _lt, _gte, _lte, _in.`,
182
+ )
183
+ }
184
+
185
+ let fieldValue = operatorObj->Js.Dict.unsafeGet(operatorKey)
186
+
187
+ LoadLayer.loadByField(
188
+ ~loadManager=params.loadManager,
189
+ ~persistence=params.persistence,
190
+ ~operator,
191
+ ~entityConfig,
192
+ ~fieldName=dbFieldName,
193
+ ~fieldValueSchema=fieldSchema,
194
+ ~inMemoryStore=params.inMemoryStore,
195
+ ~shouldGroup=params.isPreload,
196
+ ~item=params.item,
197
+ ~fieldValue,
198
+ )
199
+ }
200
+ }
201
+
202
+ let noopSet = (_entity: Internal.entity) => ()
203
+ let noopDeleteUnsafe = (_entityId: string) => ()
204
+
205
+ let entityTraps: Utils.Proxy.traps<entityContextParams> = {
206
+ get: (~target as params, ~prop: unknown) => {
207
+ let prop = prop->(Utils.magic: unknown => string)
208
+
209
+ let set = params.isPreload
210
+ ? noopSet
211
+ : (entity: Internal.entity) => {
212
+ params.inMemoryStore
213
+ ->InMemoryStore.getInMemTable(~entityConfig=params.entityConfig)
214
+ ->InMemoryTable.Entity.set(
215
+ Set({
216
+ entityId: entity.id,
217
+ checkpointId: params.checkpointId,
218
+ entity,
219
+ }),
220
+ ~shouldSaveHistory=params.shouldSaveHistory,
221
+ )
222
+ }
223
+
224
+ switch prop {
225
+ | "get" =>
226
+ (
227
+ entityId =>
228
+ LoadLayer.loadById(
229
+ ~loadManager=params.loadManager,
230
+ ~persistence=params.persistence,
231
+ ~entityConfig=params.entityConfig,
232
+ ~inMemoryStore=params.inMemoryStore,
233
+ ~shouldGroup=params.isPreload,
234
+ ~item=params.item,
235
+ ~entityId,
236
+ )
237
+ )->(Utils.magic: (string => promise<option<Internal.entity>>) => unknown)
238
+ | "getWhere" =>
239
+ (
240
+ filter =>
241
+ getWhereHandler(params, filter->(Utils.magic: unknown => Js.Dict.t<Js.Dict.t<unknown>>))
242
+ )->(Utils.magic: (unknown => promise<array<Internal.entity>>) => unknown)
243
+ | "getOrThrow" =>
244
+ (
245
+ (entityId, ~message=?) =>
246
+ LoadLayer.loadById(
247
+ ~loadManager=params.loadManager,
248
+ ~persistence=params.persistence,
249
+ ~entityConfig=params.entityConfig,
250
+ ~inMemoryStore=params.inMemoryStore,
251
+ ~shouldGroup=params.isPreload,
252
+ ~item=params.item,
253
+ ~entityId,
254
+ )->Promise.thenResolve(entity => {
255
+ switch entity {
256
+ | Some(entity) => entity
257
+ | None =>
258
+ Js.Exn.raiseError(
259
+ message->Belt.Option.getWithDefault(
260
+ `Entity '${params.entityConfig.name}' with ID '${entityId}' is expected to exist.`,
261
+ ),
262
+ )
263
+ }
264
+ })
265
+ )->(Utils.magic: ((string, ~message: string=?) => promise<Internal.entity>) => unknown)
266
+ | "getOrCreate" =>
267
+ (
268
+ (entity: Internal.entity) =>
269
+ LoadLayer.loadById(
270
+ ~loadManager=params.loadManager,
271
+ ~persistence=params.persistence,
272
+ ~entityConfig=params.entityConfig,
273
+ ~inMemoryStore=params.inMemoryStore,
274
+ ~shouldGroup=params.isPreload,
275
+ ~item=params.item,
276
+ ~entityId=entity.id,
277
+ )->Promise.thenResolve(storageEntity => {
278
+ switch storageEntity {
279
+ | Some(entity) => entity
280
+ | None => {
281
+ set(entity)
282
+ entity
283
+ }
284
+ }
285
+ })
286
+ )->(Utils.magic: (Internal.entity => promise<Internal.entity>) => unknown)
287
+ | "set" => set->(Utils.magic: (Internal.entity => unit) => unknown)
288
+ | "deleteUnsafe" =>
289
+ if params.isPreload {
290
+ noopDeleteUnsafe
291
+ } else {
292
+ entityId => {
293
+ params.inMemoryStore
294
+ ->InMemoryStore.getInMemTable(~entityConfig=params.entityConfig)
295
+ ->InMemoryTable.Entity.set(
296
+ Delete({
297
+ entityId,
298
+ checkpointId: params.checkpointId,
299
+ }),
300
+ ~shouldSaveHistory=params.shouldSaveHistory,
301
+ )
302
+ }
303
+ }->(Utils.magic: (string => unit) => unknown)
304
+ | _ => Js.Exn.raiseError(`Invalid context.${params.entityConfig.name}.${prop} operation.`)
305
+ }
306
+ },
307
+ }
308
+
309
+ let handlerTraps: Utils.Proxy.traps<contextParams> = {
310
+ get: (~target as params, ~prop: unknown) => {
311
+ let prop = prop->(Utils.magic: unknown => string)
312
+ if params.isResolved {
313
+ Utils.Error.make(
314
+ `Impossible to access context.${prop} after the handler is resolved. Make sure you didn't miss an await in the handler.`,
315
+ )->ErrorHandling.mkLogAndRaise(~logger=params.item->Logging.getItemLogger)
316
+ }
317
+ switch prop {
318
+ | "log" =>
319
+ (params.isPreload ? Logging.noopLogger : params.item->Logging.getUserLogger)->(
320
+ Utils.magic: Envio.logger => unknown
321
+ )
322
+
323
+ | "effect" =>
324
+ initEffect((params :> contextParams))->(
325
+ Utils.magic: (
326
+ (Internal.effect, Internal.effectInput) => promise<Internal.effectOutput>
327
+ ) => unknown
328
+ )
329
+
330
+ | "isPreload" => params.isPreload->(Utils.magic: bool => unknown)
331
+ | "chain" =>
332
+ let chainId = params.item->Internal.getItemChainId
333
+ params.chains
334
+ ->Utils.Dict.dangerouslyGetByIntNonOption(chainId)
335
+ ->(Utils.magic: option<Internal.chainInfo> => unknown)
336
+ | _ =>
337
+ switch params.config.userEntitiesByName->Utils.Dict.dangerouslyGetNonOption(prop) {
338
+ | Some(entityConfig) =>
339
+ {
340
+ item: params.item,
341
+ isPreload: params.isPreload,
342
+ inMemoryStore: params.inMemoryStore,
343
+ loadManager: params.loadManager,
344
+ persistence: params.persistence,
345
+ shouldSaveHistory: params.shouldSaveHistory,
346
+ checkpointId: params.checkpointId,
347
+ chains: params.chains,
348
+ isResolved: params.isResolved,
349
+ config: params.config,
350
+ entityConfig,
351
+ }
352
+ ->Utils.Proxy.make(entityTraps)
353
+ ->(Utils.magic: entityContextParams => unknown)
354
+ | None =>
355
+ Js.Exn.raiseError(`Invalid context access by '${prop}' property. ${codegenHelpMessage}`)
356
+ }
357
+ }
358
+ },
359
+ }
360
+
361
+ let getHandlerContext = (params: contextParams): Internal.handlerContext => {
362
+ params->Utils.Proxy.make(handlerTraps)->(Utils.magic: contextParams => Internal.handlerContext)
363
+ }
364
+
365
+ // Contract register context creation
366
+ type contractRegisterParams = {
367
+ item: Internal.item,
368
+ onRegister: (~item: Internal.item, ~contractAddress: Address.t, ~contractName: string) => unit,
369
+ config: Config.t,
370
+ mutable isResolved: bool,
371
+ }
372
+
373
+ let contractRegisterTraps: Utils.Proxy.traps<contractRegisterParams> = {
374
+ get: (~target as params, ~prop: unknown) => {
375
+ let prop = prop->(Utils.magic: unknown => string)
376
+ if params.isResolved {
377
+ Utils.Error.make(
378
+ `Impossible to access context.${prop} after the contract register is resolved. Make sure you didn't miss an await in the handler.`,
379
+ )->ErrorHandling.mkLogAndRaise(~logger=params.item->Logging.getItemLogger)
380
+ }
381
+ switch prop {
382
+ | "log" => params.item->Logging.getUserLogger->(Utils.magic: Envio.logger => unknown)
383
+ | _ =>
384
+ // Use the pre-built mapping for efficient lookup
385
+ switch params.config.addContractNameToContractNameMapping->Utils.Dict.dangerouslyGetNonOption(
386
+ prop,
387
+ ) {
388
+ | Some(contractName) => {
389
+ let addFunction = (contractAddress: Address.t) => {
390
+ let validatedAddress = if params.config.ecosystem.name === Evm {
391
+ // The value is passed from the user-land,
392
+ // so we need to validate and checksum/lowercase the address.
393
+ if params.config.lowercaseAddresses {
394
+ contractAddress->Address.Evm.fromAddressLowercaseOrThrow
395
+ } else {
396
+ contractAddress->Address.Evm.fromAddressOrThrow
397
+ }
398
+ } else {
399
+ // TODO: Ideally we should do the same for other ecosystems
400
+ contractAddress
401
+ }
402
+
403
+ params.onRegister(~item=params.item, ~contractAddress=validatedAddress, ~contractName)
404
+ }
405
+
406
+ addFunction->(Utils.magic: (Address.t => unit) => unknown)
407
+ }
408
+ | None =>
409
+ Js.Exn.raiseError(`Invalid context access by '${prop}' property. ${codegenHelpMessage}`)
410
+ }
411
+ }
412
+ },
413
+ }
414
+
415
+ let getContractRegisterContext = (params: contractRegisterParams) => {
416
+ params
417
+ ->Utils.Proxy.make(contractRegisterTraps)
418
+ ->(Utils.magic: contractRegisterParams => Internal.contractRegisterContext)
419
+ }
420
+
421
+ let getContractRegisterArgs = (params: contractRegisterParams): Internal.contractRegisterArgs => {
422
+ event: (params.item->Internal.castUnsafeEventItem).event,
423
+ context: getContractRegisterContext(params),
424
+ }
@@ -0,0 +1,279 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Table from "./db/Table.res.mjs";
4
+ import * as Utils from "./Utils.res.mjs";
5
+ import * as Js_exn from "rescript/lib/es6/js_exn.js";
6
+ import * as Address from "./Address.res.mjs";
7
+ import * as Logging from "./Logging.res.mjs";
8
+ import * as Internal from "./Internal.res.mjs";
9
+ import * as LoadLayer from "./LoadLayer.res.mjs";
10
+ import * as Belt_Array from "rescript/lib/es6/belt_Array.js";
11
+ import * as Belt_Option from "rescript/lib/es6/belt_Option.js";
12
+ import * as ErrorHandling from "./ErrorHandling.res.mjs";
13
+ import * as InMemoryStore from "./InMemoryStore.res.mjs";
14
+ import * as InMemoryTable from "./InMemoryTable.res.mjs";
15
+ import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
16
+
17
+ var codegenHelpMessage = "Rerun 'pnpm dev' to update generated code after schema.graphql changes.";
18
+
19
+ var paramsByThis = new WeakMap();
20
+
21
+ var effectContextPrototype = (Object.create(null));
22
+
23
+ Object.defineProperty(effectContextPrototype, "log", {
24
+ get: (function () {
25
+ return Logging.getUserLogger(paramsByThis.get(this).item);
26
+ })
27
+ });
28
+
29
+ var EffectContext = function(params, defaultShouldCache, callEffect) {
30
+ paramsByThis.set(this, params);
31
+ this.effect = callEffect;
32
+ this.cache = defaultShouldCache;
33
+ };
34
+ EffectContext.prototype = effectContextPrototype;
35
+ ;
36
+
37
+ function initEffect(params) {
38
+ var callEffect = function (effect, input) {
39
+ var effectContext = new EffectContext(params, effect.defaultShouldCache, callEffect);
40
+ var effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
41
+ var effectArgs = {
42
+ input: input,
43
+ context: effectContext,
44
+ cacheKey: effectArgs_cacheKey
45
+ };
46
+ return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, params.inMemoryStore, params.isPreload, params.item);
47
+ };
48
+ return callEffect;
49
+ }
50
+
51
+ function getWhereHandler(params, filter) {
52
+ var entityConfig = params.entityConfig;
53
+ var filterKeys = Object.keys(filter);
54
+ if (filterKeys.length === 0) {
55
+ Js_exn.raiseError("Empty filter passed to context." + entityConfig.name + ".getWhere(). Please provide a filter like { fieldName: { _eq: value } }.");
56
+ }
57
+ if (filterKeys.length > 1) {
58
+ Js_exn.raiseError("Multiple filter fields passed to context." + entityConfig.name + ".getWhere(). Currently only one filter field per call is supported. Received fields: " + filterKeys.join(", ") + ".");
59
+ }
60
+ var dbFieldName = filterKeys[0];
61
+ var operatorObj = filter[dbFieldName];
62
+ var operatorKeys = Object.keys(operatorObj);
63
+ if (operatorKeys.length === 0) {
64
+ Js_exn.raiseError("Empty operator passed to context." + entityConfig.name + ".getWhere({ " + dbFieldName + ": {} }). Please provide an operator like { _eq: value }, { _gt: value }, { _lt: value }, { _gte: value }, { _lte: value }, or { _in: [values] }.");
65
+ }
66
+ if (operatorKeys.length > 1) {
67
+ Js_exn.raiseError("Multiple operators passed to context." + entityConfig.name + ".getWhere({ " + dbFieldName + ": ... }). Currently only one operator per filter field is supported. Received operators: " + operatorKeys.join(", ") + ".");
68
+ }
69
+ var operatorKey = operatorKeys[0];
70
+ var match = Table.getFieldByDbName(entityConfig.table, dbFieldName);
71
+ var fieldSchema;
72
+ if (match !== undefined) {
73
+ if (match.TAG === "Field") {
74
+ var match$1 = match._0;
75
+ fieldSchema = match$1.isIndex || match$1.linkedEntity !== undefined ? match$1.fieldSchema : Js_exn.raiseError("The field \"" + dbFieldName + "\" on entity \"" + entityConfig.name + "\" does not have an index. To use it in getWhere(), add the @index directive in your schema.graphql:\n\n " + dbFieldName + ": ... @index\n\nThen run 'pnpm envio codegen' to regenerate.");
76
+ } else {
77
+ fieldSchema = Js_exn.raiseError("The field \"" + dbFieldName + "\" on entity \"" + entityConfig.name + "\" is a derived field and cannot be used in getWhere(). Use the source entity's indexed field instead.");
78
+ }
79
+ } else {
80
+ fieldSchema = Js_exn.raiseError("Invalid field \"" + dbFieldName + "\" in context." + entityConfig.name + ".getWhere(). The field doesn't exist. " + codegenHelpMessage);
81
+ }
82
+ if (operatorKey === "_in") {
83
+ var fieldValues = operatorObj[operatorKey];
84
+ return Promise.all(fieldValues.map(function (fieldValue) {
85
+ return LoadLayer.loadByField(params.loadManager, params.persistence, "Eq", entityConfig, params.inMemoryStore, dbFieldName, fieldSchema, params.isPreload, params.item, fieldValue);
86
+ })).then(Belt_Array.concatMany);
87
+ }
88
+ if (operatorKey === "_gte" || operatorKey === "_lte") {
89
+ var rangeOperator = operatorKey === "_gte" ? "Gt" : "Lt";
90
+ var fieldValue = operatorObj[operatorKey];
91
+ var loadWithOperator = function (operator) {
92
+ return LoadLayer.loadByField(params.loadManager, params.persistence, operator, entityConfig, params.inMemoryStore, dbFieldName, fieldSchema, params.isPreload, params.item, fieldValue);
93
+ };
94
+ return Promise.all([
95
+ loadWithOperator("Eq"),
96
+ loadWithOperator(rangeOperator)
97
+ ]).then(Belt_Array.concatMany);
98
+ }
99
+ var operator;
100
+ switch (operatorKey) {
101
+ case "_eq" :
102
+ operator = "Eq";
103
+ break;
104
+ case "_gt" :
105
+ operator = "Gt";
106
+ break;
107
+ case "_lt" :
108
+ operator = "Lt";
109
+ break;
110
+ default:
111
+ operator = Js_exn.raiseError("Invalid operator \"" + operatorKey + "\" in context." + entityConfig.name + ".getWhere({ " + dbFieldName + ": { " + operatorKey + ": ... } }). Valid operators are _eq, _gt, _lt, _gte, _lte, _in.");
112
+ }
113
+ var fieldValue$1 = operatorObj[operatorKey];
114
+ return LoadLayer.loadByField(params.loadManager, params.persistence, operator, entityConfig, params.inMemoryStore, dbFieldName, fieldSchema, params.isPreload, params.item, fieldValue$1);
115
+ }
116
+
117
+ function noopSet(_entity) {
118
+
119
+ }
120
+
121
+ function noopDeleteUnsafe(_entityId) {
122
+
123
+ }
124
+
125
+ var entityTraps = {
126
+ get: (function (params, prop) {
127
+ var set = params.isPreload ? noopSet : (function (entity) {
128
+ InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), {
129
+ type: "SET",
130
+ entityId: entity.id,
131
+ entity: entity,
132
+ checkpointId: params.checkpointId
133
+ }, params.shouldSaveHistory, undefined);
134
+ });
135
+ switch (prop) {
136
+ case "deleteUnsafe" :
137
+ if (params.isPreload) {
138
+ return noopDeleteUnsafe;
139
+ } else {
140
+ return function (entityId) {
141
+ InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), {
142
+ type: "DELETE",
143
+ entityId: entityId,
144
+ checkpointId: params.checkpointId
145
+ }, params.shouldSaveHistory, undefined);
146
+ };
147
+ }
148
+ case "get" :
149
+ return function (entityId) {
150
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId);
151
+ };
152
+ case "getOrCreate" :
153
+ return function (entity) {
154
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entity.id).then(function (storageEntity) {
155
+ if (storageEntity !== undefined) {
156
+ return storageEntity;
157
+ } else {
158
+ set(entity);
159
+ return entity;
160
+ }
161
+ });
162
+ };
163
+ case "getOrThrow" :
164
+ return function (entityId, message) {
165
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId).then(function (entity) {
166
+ if (entity !== undefined) {
167
+ return entity;
168
+ } else {
169
+ return Js_exn.raiseError(Belt_Option.getWithDefault(message, "Entity '" + params.entityConfig.name + "' with ID '" + entityId + "' is expected to exist."));
170
+ }
171
+ });
172
+ };
173
+ case "getWhere" :
174
+ return function (filter) {
175
+ return getWhereHandler(params, filter);
176
+ };
177
+ case "set" :
178
+ return set;
179
+ default:
180
+ return Js_exn.raiseError("Invalid context." + params.entityConfig.name + "." + prop + " operation.");
181
+ }
182
+ })
183
+ };
184
+
185
+ var handlerTraps = {
186
+ get: (function (params, prop) {
187
+ if (params.isResolved) {
188
+ ErrorHandling.mkLogAndRaise(Logging.getItemLogger(params.item), undefined, new Error("Impossible to access context." + prop + " after the handler is resolved. Make sure you didn't miss an await in the handler."));
189
+ }
190
+ switch (prop) {
191
+ case "chain" :
192
+ var chainId = Internal.getItemChainId(params.item);
193
+ return params.chains[chainId];
194
+ case "effect" :
195
+ return initEffect(params);
196
+ case "isPreload" :
197
+ return params.isPreload;
198
+ case "log" :
199
+ if (params.isPreload) {
200
+ return Logging.noopLogger;
201
+ } else {
202
+ return Logging.getUserLogger(params.item);
203
+ }
204
+ default:
205
+ var entityConfig = params.config.userEntitiesByName[prop];
206
+ if (entityConfig !== undefined) {
207
+ return new Proxy({
208
+ item: params.item,
209
+ checkpointId: params.checkpointId,
210
+ inMemoryStore: params.inMemoryStore,
211
+ loadManager: params.loadManager,
212
+ persistence: params.persistence,
213
+ isPreload: params.isPreload,
214
+ shouldSaveHistory: params.shouldSaveHistory,
215
+ chains: params.chains,
216
+ config: params.config,
217
+ isResolved: params.isResolved,
218
+ entityConfig: entityConfig
219
+ }, entityTraps);
220
+ } else {
221
+ return Js_exn.raiseError("Invalid context access by '" + prop + "' property. " + codegenHelpMessage);
222
+ }
223
+ }
224
+ })
225
+ };
226
+
227
+ function getHandlerContext(params) {
228
+ return new Proxy(params, handlerTraps);
229
+ }
230
+
231
+ var contractRegisterTraps = {
232
+ get: (function (params, prop) {
233
+ if (params.isResolved) {
234
+ ErrorHandling.mkLogAndRaise(Logging.getItemLogger(params.item), undefined, new Error("Impossible to access context." + prop + " after the contract register is resolved. Make sure you didn't miss an await in the handler."));
235
+ }
236
+ if (prop === "log") {
237
+ return Logging.getUserLogger(params.item);
238
+ }
239
+ var contractName = params.config.addContractNameToContractNameMapping[prop];
240
+ if (contractName !== undefined) {
241
+ return function (contractAddress) {
242
+ var validatedAddress = params.config.ecosystem.name === "evm" ? (
243
+ params.config.lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(contractAddress) : Address.Evm.fromAddressOrThrow(contractAddress)
244
+ ) : contractAddress;
245
+ params.onRegister(params.item, validatedAddress, contractName);
246
+ };
247
+ } else {
248
+ return Js_exn.raiseError("Invalid context access by '" + prop + "' property. " + codegenHelpMessage);
249
+ }
250
+ })
251
+ };
252
+
253
+ function getContractRegisterContext(params) {
254
+ return new Proxy(params, contractRegisterTraps);
255
+ }
256
+
257
+ function getContractRegisterArgs(params) {
258
+ return {
259
+ event: params.item.event,
260
+ context: new Proxy(params, contractRegisterTraps)
261
+ };
262
+ }
263
+
264
+ export {
265
+ codegenHelpMessage ,
266
+ paramsByThis ,
267
+ effectContextPrototype ,
268
+ initEffect ,
269
+ getWhereHandler ,
270
+ noopSet ,
271
+ noopDeleteUnsafe ,
272
+ entityTraps ,
273
+ handlerTraps ,
274
+ getHandlerContext ,
275
+ contractRegisterTraps ,
276
+ getContractRegisterContext ,
277
+ getContractRegisterArgs ,
278
+ }
279
+ /* paramsByThis Not a pure module */