envio 3.0.0-alpha.2 → 3.0.0-alpha.4

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 (74) hide show
  1. package/README.md +2 -2
  2. package/evm.schema.json +44 -34
  3. package/fuel.schema.json +32 -21
  4. package/index.d.ts +4 -1
  5. package/index.js +1 -0
  6. package/package.json +7 -6
  7. package/src/Batch.res.mjs +1 -1
  8. package/src/Benchmark.res +394 -0
  9. package/src/Benchmark.res.mjs +398 -0
  10. package/src/ChainFetcher.res +459 -0
  11. package/src/ChainFetcher.res.mjs +281 -0
  12. package/src/ChainManager.res +179 -0
  13. package/src/ChainManager.res.mjs +139 -0
  14. package/src/Config.res +15 -1
  15. package/src/Config.res.mjs +28 -5
  16. package/src/Ecosystem.res +9 -124
  17. package/src/Ecosystem.res.mjs +19 -160
  18. package/src/Env.res +0 -1
  19. package/src/Env.res.mjs +0 -3
  20. package/src/Envio.gen.ts +9 -1
  21. package/src/Envio.res +12 -9
  22. package/src/EventProcessing.res +476 -0
  23. package/src/EventProcessing.res.mjs +341 -0
  24. package/src/FetchState.res +54 -29
  25. package/src/FetchState.res.mjs +62 -35
  26. package/src/GlobalState.res +1169 -0
  27. package/src/GlobalState.res.mjs +1196 -0
  28. package/src/Internal.res +43 -1
  29. package/src/LoadLayer.res +444 -0
  30. package/src/LoadLayer.res.mjs +296 -0
  31. package/src/LoadLayer.resi +32 -0
  32. package/src/Prometheus.res +8 -8
  33. package/src/Prometheus.res.mjs +10 -10
  34. package/src/ReorgDetection.res +6 -10
  35. package/src/ReorgDetection.res.mjs +6 -6
  36. package/src/Types.ts +1 -1
  37. package/src/UserContext.res +356 -0
  38. package/src/UserContext.res.mjs +238 -0
  39. package/src/Utils.res +15 -0
  40. package/src/Utils.res.mjs +18 -0
  41. package/src/bindings/ClickHouse.res +31 -1
  42. package/src/bindings/ClickHouse.res.mjs +27 -1
  43. package/src/bindings/DateFns.res +71 -0
  44. package/src/bindings/DateFns.res.mjs +22 -0
  45. package/src/bindings/Ethers.res +27 -63
  46. package/src/bindings/Ethers.res.mjs +18 -65
  47. package/src/sources/Evm.res +87 -0
  48. package/src/sources/Evm.res.mjs +105 -0
  49. package/src/sources/EvmChain.res +95 -0
  50. package/src/sources/EvmChain.res.mjs +61 -0
  51. package/src/sources/Fuel.res +19 -34
  52. package/src/sources/Fuel.res.mjs +34 -16
  53. package/src/sources/FuelSDK.res +37 -0
  54. package/src/sources/FuelSDK.res.mjs +29 -0
  55. package/src/sources/HyperFuel.res +2 -2
  56. package/src/sources/HyperFuel.resi +1 -1
  57. package/src/sources/HyperFuelClient.res +2 -2
  58. package/src/sources/HyperFuelSource.res +8 -8
  59. package/src/sources/HyperFuelSource.res.mjs +5 -5
  60. package/src/sources/HyperSyncHeightStream.res +28 -110
  61. package/src/sources/HyperSyncHeightStream.res.mjs +30 -63
  62. package/src/sources/HyperSyncSource.res +16 -18
  63. package/src/sources/HyperSyncSource.res.mjs +25 -25
  64. package/src/sources/Rpc.res +43 -0
  65. package/src/sources/Rpc.res.mjs +31 -0
  66. package/src/sources/RpcSource.res +13 -8
  67. package/src/sources/RpcSource.res.mjs +12 -7
  68. package/src/sources/Source.res +3 -2
  69. package/src/sources/SourceManager.res +183 -108
  70. package/src/sources/SourceManager.res.mjs +162 -99
  71. package/src/sources/SourceManager.resi +4 -5
  72. package/src/sources/Svm.res +59 -0
  73. package/src/sources/Svm.res.mjs +79 -0
  74. package/src/bindings/Ethers.gen.ts +0 -14
@@ -0,0 +1,356 @@
1
+ let codegenHelpMessage = `Rerun 'pnpm dev' to update generated code after schema.graphql changes.`
2
+
3
+ type contextParams = {
4
+ item: Internal.item,
5
+ checkpointId: float,
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 getWhereTraps: Utils.Proxy.traps<entityContextParams> = {
78
+ get: (~target as params, ~prop: unknown) => {
79
+ let entityConfig = params.entityConfig
80
+ if prop->Js.typeof !== "string" {
81
+ Js.Exn.raiseError(
82
+ `Invalid context.${entityConfig.name}.getWhere access by a non-string property.`,
83
+ )
84
+ } else {
85
+ let dbFieldName = prop->(Utils.magic: unknown => string)
86
+ switch entityConfig.table->Table.getFieldByDbName(dbFieldName) {
87
+ | None =>
88
+ Js.Exn.raiseError(
89
+ `Invalid context.${entityConfig.name}.getWhere.${dbFieldName} - the field doesn't exist. ${codegenHelpMessage}`,
90
+ )
91
+ | Some(field) =>
92
+ let fieldValueSchema = switch field {
93
+ | Field({fieldSchema}) => fieldSchema
94
+ | DerivedFrom(_) => S.string->S.toUnknown
95
+ }
96
+ {
97
+ Envio.eq: fieldValue =>
98
+ LoadLayer.loadByField(
99
+ ~loadManager=params.loadManager,
100
+ ~persistence=params.persistence,
101
+ ~operator=Eq,
102
+ ~entityConfig,
103
+ ~fieldName=dbFieldName,
104
+ ~fieldValueSchema,
105
+ ~inMemoryStore=params.inMemoryStore,
106
+ ~shouldGroup=params.isPreload,
107
+ ~item=params.item,
108
+ ~fieldValue,
109
+ ),
110
+ gt: fieldValue =>
111
+ LoadLayer.loadByField(
112
+ ~loadManager=params.loadManager,
113
+ ~persistence=params.persistence,
114
+ ~operator=Gt,
115
+ ~entityConfig,
116
+ ~fieldName=dbFieldName,
117
+ ~fieldValueSchema,
118
+ ~inMemoryStore=params.inMemoryStore,
119
+ ~shouldGroup=params.isPreload,
120
+ ~item=params.item,
121
+ ~fieldValue,
122
+ ),
123
+ lt: fieldValue =>
124
+ LoadLayer.loadByField(
125
+ ~loadManager=params.loadManager,
126
+ ~persistence=params.persistence,
127
+ ~operator=Lt,
128
+ ~entityConfig,
129
+ ~fieldName=dbFieldName,
130
+ ~fieldValueSchema,
131
+ ~inMemoryStore=params.inMemoryStore,
132
+ ~shouldGroup=params.isPreload,
133
+ ~item=params.item,
134
+ ~fieldValue,
135
+ ),
136
+ }->Utils.magic
137
+ }
138
+ }
139
+ },
140
+ }
141
+
142
+ let noopSet = (_entity: Internal.entity) => ()
143
+ let noopDeleteUnsafe = (_entityId: string) => ()
144
+
145
+ let entityTraps: Utils.Proxy.traps<entityContextParams> = {
146
+ get: (~target as params, ~prop: unknown) => {
147
+ let prop = prop->(Utils.magic: unknown => string)
148
+
149
+ let set = params.isPreload
150
+ ? noopSet
151
+ : (entity: Internal.entity) => {
152
+ params.inMemoryStore
153
+ ->InMemoryStore.getInMemTable(~entityConfig=params.entityConfig)
154
+ ->InMemoryTable.Entity.set(
155
+ Set({
156
+ entityId: entity.id,
157
+ checkpointId: params.checkpointId,
158
+ entity,
159
+ }),
160
+ ~shouldSaveHistory=params.shouldSaveHistory,
161
+ )
162
+ }
163
+
164
+ switch prop {
165
+ | "get" =>
166
+ (
167
+ entityId =>
168
+ LoadLayer.loadById(
169
+ ~loadManager=params.loadManager,
170
+ ~persistence=params.persistence,
171
+ ~entityConfig=params.entityConfig,
172
+ ~inMemoryStore=params.inMemoryStore,
173
+ ~shouldGroup=params.isPreload,
174
+ ~item=params.item,
175
+ ~entityId,
176
+ )
177
+ )->Utils.magic
178
+ | "getWhere" => params->Utils.Proxy.make(getWhereTraps)->Utils.magic
179
+ | "getOrThrow" =>
180
+ (
181
+ (entityId, ~message=?) =>
182
+ LoadLayer.loadById(
183
+ ~loadManager=params.loadManager,
184
+ ~persistence=params.persistence,
185
+ ~entityConfig=params.entityConfig,
186
+ ~inMemoryStore=params.inMemoryStore,
187
+ ~shouldGroup=params.isPreload,
188
+ ~item=params.item,
189
+ ~entityId,
190
+ )->Promise.thenResolve(entity => {
191
+ switch entity {
192
+ | Some(entity) => entity
193
+ | None =>
194
+ Js.Exn.raiseError(
195
+ message->Belt.Option.getWithDefault(
196
+ `Entity '${params.entityConfig.name}' with ID '${entityId}' is expected to exist.`,
197
+ ),
198
+ )
199
+ }
200
+ })
201
+ )->Utils.magic
202
+ | "getOrCreate" =>
203
+ (
204
+ (entity: Internal.entity) =>
205
+ LoadLayer.loadById(
206
+ ~loadManager=params.loadManager,
207
+ ~persistence=params.persistence,
208
+ ~entityConfig=params.entityConfig,
209
+ ~inMemoryStore=params.inMemoryStore,
210
+ ~shouldGroup=params.isPreload,
211
+ ~item=params.item,
212
+ ~entityId=entity.id,
213
+ )->Promise.thenResolve(storageEntity => {
214
+ switch storageEntity {
215
+ | Some(entity) => entity
216
+ | None => {
217
+ set(entity)
218
+ entity
219
+ }
220
+ }
221
+ })
222
+ )->Utils.magic
223
+ | "set" => set->Utils.magic
224
+ | "deleteUnsafe" =>
225
+ if params.isPreload {
226
+ noopDeleteUnsafe
227
+ } else {
228
+ entityId => {
229
+ params.inMemoryStore
230
+ ->InMemoryStore.getInMemTable(~entityConfig=params.entityConfig)
231
+ ->InMemoryTable.Entity.set(
232
+ Delete({
233
+ entityId,
234
+ checkpointId: params.checkpointId,
235
+ }),
236
+ ~shouldSaveHistory=params.shouldSaveHistory,
237
+ )
238
+ }
239
+ }->Utils.magic
240
+ | _ => Js.Exn.raiseError(`Invalid context.${params.entityConfig.name}.${prop} operation.`)
241
+ }
242
+ },
243
+ }
244
+
245
+ let handlerTraps: Utils.Proxy.traps<contextParams> = {
246
+ get: (~target as params, ~prop: unknown) => {
247
+ let prop = prop->(Utils.magic: unknown => string)
248
+ if params.isResolved {
249
+ Utils.Error.make(
250
+ `Impossible to access context.${prop} after the handler is resolved. Make sure you didn't miss an await in the handler.`,
251
+ )->ErrorHandling.mkLogAndRaise(~logger=params.item->Logging.getItemLogger)
252
+ }
253
+ switch prop {
254
+ | "log" =>
255
+ (params.isPreload ? Logging.noopLogger : params.item->Logging.getUserLogger)->Utils.magic
256
+ | "effect" =>
257
+ initEffect((params :> contextParams))->(
258
+ Utils.magic: (
259
+ (Internal.effect, Internal.effectInput) => promise<Internal.effectOutput>
260
+ ) => unknown
261
+ )
262
+
263
+ | "isPreload" => params.isPreload->Utils.magic
264
+ | "chains" => params.chains->Utils.magic
265
+ | "chain" =>
266
+ let chainId = params.item->Internal.getItemChainId
267
+ params.chains->Utils.Dict.dangerouslyGetByIntNonOption(chainId)->Utils.magic
268
+ | _ =>
269
+ switch params.config.userEntitiesByName->Utils.Dict.dangerouslyGetNonOption(prop) {
270
+ | Some(entityConfig) =>
271
+ {
272
+ item: params.item,
273
+ isPreload: params.isPreload,
274
+ inMemoryStore: params.inMemoryStore,
275
+ loadManager: params.loadManager,
276
+ persistence: params.persistence,
277
+ shouldSaveHistory: params.shouldSaveHistory,
278
+ checkpointId: params.checkpointId,
279
+ chains: params.chains,
280
+ isResolved: params.isResolved,
281
+ config: params.config,
282
+ entityConfig,
283
+ }
284
+ ->Utils.Proxy.make(entityTraps)
285
+ ->Utils.magic
286
+ | None =>
287
+ Js.Exn.raiseError(`Invalid context access by '${prop}' property. ${codegenHelpMessage}`)
288
+ }
289
+ }
290
+ },
291
+ }
292
+
293
+ let getHandlerContext = (params: contextParams): Internal.handlerContext => {
294
+ params->Utils.Proxy.make(handlerTraps)->Utils.magic
295
+ }
296
+
297
+ // Contract register context creation
298
+ type contractRegisterParams = {
299
+ item: Internal.item,
300
+ onRegister: (~item: Internal.item, ~contractAddress: Address.t, ~contractName: string) => unit,
301
+ config: Config.t,
302
+ mutable isResolved: bool,
303
+ }
304
+
305
+ let contractRegisterTraps: Utils.Proxy.traps<contractRegisterParams> = {
306
+ get: (~target as params, ~prop: unknown) => {
307
+ let prop = prop->(Utils.magic: unknown => string)
308
+ if params.isResolved {
309
+ Utils.Error.make(
310
+ `Impossible to access context.${prop} after the contract register is resolved. Make sure you didn't miss an await in the handler.`,
311
+ )->ErrorHandling.mkLogAndRaise(~logger=params.item->Logging.getItemLogger)
312
+ }
313
+ switch prop {
314
+ | "log" => params.item->Logging.getUserLogger->Utils.magic
315
+ | _ =>
316
+ // Use the pre-built mapping for efficient lookup
317
+ switch params.config.addContractNameToContractNameMapping->Utils.Dict.dangerouslyGetNonOption(
318
+ prop,
319
+ ) {
320
+ | Some(contractName) => {
321
+ let addFunction = (contractAddress: Address.t) => {
322
+ let validatedAddress = if params.config.ecosystem.name === Evm {
323
+ // The value is passed from the user-land,
324
+ // so we need to validate and checksum/lowercase the address.
325
+ if params.config.lowercaseAddresses {
326
+ contractAddress->Address.Evm.fromAddressLowercaseOrThrow
327
+ } else {
328
+ contractAddress->Address.Evm.fromAddressOrThrow
329
+ }
330
+ } else {
331
+ // TODO: Ideally we should do the same for other ecosystems
332
+ contractAddress
333
+ }
334
+
335
+ params.onRegister(~item=params.item, ~contractAddress=validatedAddress, ~contractName)
336
+ }
337
+
338
+ addFunction->Utils.magic
339
+ }
340
+ | None =>
341
+ Js.Exn.raiseError(`Invalid context access by '${prop}' property. ${codegenHelpMessage}`)
342
+ }
343
+ }
344
+ },
345
+ }
346
+
347
+ let getContractRegisterContext = (params: contractRegisterParams) => {
348
+ params
349
+ ->Utils.Proxy.make(contractRegisterTraps)
350
+ ->Utils.magic
351
+ }
352
+
353
+ let getContractRegisterArgs = (params: contractRegisterParams): Internal.contractRegisterArgs => {
354
+ event: (params.item->Internal.castUnsafeEventItem).event,
355
+ context: getContractRegisterContext(params),
356
+ }
@@ -0,0 +1,238 @@
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_Option from "rescript/lib/es6/belt_Option.js";
11
+ import * as ErrorHandling from "./ErrorHandling.res.mjs";
12
+ import * as InMemoryStore from "./InMemoryStore.res.mjs";
13
+ import * as InMemoryTable from "./InMemoryTable.res.mjs";
14
+ import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
15
+
16
+ var codegenHelpMessage = "Rerun 'pnpm dev' to update generated code after schema.graphql changes.";
17
+
18
+ var paramsByThis = new WeakMap();
19
+
20
+ var effectContextPrototype = (Object.create(null));
21
+
22
+ Object.defineProperty(effectContextPrototype, "log", {
23
+ get: (function () {
24
+ return Logging.getUserLogger(paramsByThis.get(this).item);
25
+ })
26
+ });
27
+
28
+ var EffectContext = function(params, defaultShouldCache, callEffect) {
29
+ paramsByThis.set(this, params);
30
+ this.effect = callEffect;
31
+ this.cache = defaultShouldCache;
32
+ };
33
+ EffectContext.prototype = effectContextPrototype;
34
+ ;
35
+
36
+ function initEffect(params) {
37
+ var callEffect = function (effect, input) {
38
+ var effectContext = new EffectContext(params, effect.defaultShouldCache, callEffect);
39
+ var effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
40
+ var effectArgs = {
41
+ input: input,
42
+ context: effectContext,
43
+ cacheKey: effectArgs_cacheKey
44
+ };
45
+ return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, params.inMemoryStore, params.isPreload, params.item);
46
+ };
47
+ return callEffect;
48
+ }
49
+
50
+ var getWhereTraps = {
51
+ get: (function (params, prop) {
52
+ var entityConfig = params.entityConfig;
53
+ if (typeof prop !== "string") {
54
+ return Js_exn.raiseError("Invalid context." + entityConfig.name + ".getWhere access by a non-string property.");
55
+ }
56
+ var field = Table.getFieldByDbName(entityConfig.table, prop);
57
+ if (field === undefined) {
58
+ return Js_exn.raiseError("Invalid context." + entityConfig.name + ".getWhere." + prop + " - the field doesn't exist. " + codegenHelpMessage);
59
+ }
60
+ var fieldValueSchema;
61
+ fieldValueSchema = field.TAG === "Field" ? field._0.fieldSchema : S$RescriptSchema.string;
62
+ return {
63
+ eq: (function (fieldValue) {
64
+ return LoadLayer.loadByField(params.loadManager, params.persistence, "Eq", entityConfig, params.inMemoryStore, prop, fieldValueSchema, params.isPreload, params.item, fieldValue);
65
+ }),
66
+ gt: (function (fieldValue) {
67
+ return LoadLayer.loadByField(params.loadManager, params.persistence, "Gt", entityConfig, params.inMemoryStore, prop, fieldValueSchema, params.isPreload, params.item, fieldValue);
68
+ }),
69
+ lt: (function (fieldValue) {
70
+ return LoadLayer.loadByField(params.loadManager, params.persistence, "Lt", entityConfig, params.inMemoryStore, prop, fieldValueSchema, params.isPreload, params.item, fieldValue);
71
+ })
72
+ };
73
+ })
74
+ };
75
+
76
+ function noopSet(_entity) {
77
+
78
+ }
79
+
80
+ function noopDeleteUnsafe(_entityId) {
81
+
82
+ }
83
+
84
+ var entityTraps = {
85
+ get: (function (params, prop) {
86
+ var set = params.isPreload ? noopSet : (function (entity) {
87
+ InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), {
88
+ type: "SET",
89
+ entityId: entity.id,
90
+ entity: entity,
91
+ checkpointId: params.checkpointId
92
+ }, params.shouldSaveHistory, undefined);
93
+ });
94
+ switch (prop) {
95
+ case "deleteUnsafe" :
96
+ if (params.isPreload) {
97
+ return noopDeleteUnsafe;
98
+ } else {
99
+ return function (entityId) {
100
+ InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), {
101
+ type: "DELETE",
102
+ entityId: entityId,
103
+ checkpointId: params.checkpointId
104
+ }, params.shouldSaveHistory, undefined);
105
+ };
106
+ }
107
+ case "get" :
108
+ return function (entityId) {
109
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId);
110
+ };
111
+ case "getOrCreate" :
112
+ return function (entity) {
113
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entity.id).then(function (storageEntity) {
114
+ if (storageEntity !== undefined) {
115
+ return storageEntity;
116
+ } else {
117
+ set(entity);
118
+ return entity;
119
+ }
120
+ });
121
+ };
122
+ case "getOrThrow" :
123
+ return function (entityId, message) {
124
+ return LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId).then(function (entity) {
125
+ if (entity !== undefined) {
126
+ return entity;
127
+ } else {
128
+ return Js_exn.raiseError(Belt_Option.getWithDefault(message, "Entity '" + params.entityConfig.name + "' with ID '" + entityId + "' is expected to exist."));
129
+ }
130
+ });
131
+ };
132
+ case "getWhere" :
133
+ return new Proxy(params, getWhereTraps);
134
+ case "set" :
135
+ return set;
136
+ default:
137
+ return Js_exn.raiseError("Invalid context." + params.entityConfig.name + "." + prop + " operation.");
138
+ }
139
+ })
140
+ };
141
+
142
+ var handlerTraps = {
143
+ get: (function (params, prop) {
144
+ if (params.isResolved) {
145
+ 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."));
146
+ }
147
+ switch (prop) {
148
+ case "chain" :
149
+ var chainId = Internal.getItemChainId(params.item);
150
+ return params.chains[chainId];
151
+ case "chains" :
152
+ return params.chains;
153
+ case "effect" :
154
+ return initEffect(params);
155
+ case "isPreload" :
156
+ return params.isPreload;
157
+ case "log" :
158
+ if (params.isPreload) {
159
+ return Logging.noopLogger;
160
+ } else {
161
+ return Logging.getUserLogger(params.item);
162
+ }
163
+ default:
164
+ var entityConfig = params.config.userEntitiesByName[prop];
165
+ if (entityConfig !== undefined) {
166
+ return new Proxy({
167
+ item: params.item,
168
+ checkpointId: params.checkpointId,
169
+ inMemoryStore: params.inMemoryStore,
170
+ loadManager: params.loadManager,
171
+ persistence: params.persistence,
172
+ isPreload: params.isPreload,
173
+ shouldSaveHistory: params.shouldSaveHistory,
174
+ chains: params.chains,
175
+ config: params.config,
176
+ isResolved: params.isResolved,
177
+ entityConfig: entityConfig
178
+ }, entityTraps);
179
+ } else {
180
+ return Js_exn.raiseError("Invalid context access by '" + prop + "' property. " + codegenHelpMessage);
181
+ }
182
+ }
183
+ })
184
+ };
185
+
186
+ function getHandlerContext(params) {
187
+ return new Proxy(params, handlerTraps);
188
+ }
189
+
190
+ var contractRegisterTraps = {
191
+ get: (function (params, prop) {
192
+ if (params.isResolved) {
193
+ 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."));
194
+ }
195
+ if (prop === "log") {
196
+ return Logging.getUserLogger(params.item);
197
+ }
198
+ var contractName = params.config.addContractNameToContractNameMapping[prop];
199
+ if (contractName !== undefined) {
200
+ return function (contractAddress) {
201
+ var validatedAddress = params.config.ecosystem.name === "evm" ? (
202
+ params.config.lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(contractAddress) : Address.Evm.fromAddressOrThrow(contractAddress)
203
+ ) : contractAddress;
204
+ params.onRegister(params.item, validatedAddress, contractName);
205
+ };
206
+ } else {
207
+ return Js_exn.raiseError("Invalid context access by '" + prop + "' property. " + codegenHelpMessage);
208
+ }
209
+ })
210
+ };
211
+
212
+ function getContractRegisterContext(params) {
213
+ return new Proxy(params, contractRegisterTraps);
214
+ }
215
+
216
+ function getContractRegisterArgs(params) {
217
+ return {
218
+ event: params.item.event,
219
+ context: new Proxy(params, contractRegisterTraps)
220
+ };
221
+ }
222
+
223
+ export {
224
+ codegenHelpMessage ,
225
+ paramsByThis ,
226
+ effectContextPrototype ,
227
+ initEffect ,
228
+ getWhereTraps ,
229
+ noopSet ,
230
+ noopDeleteUnsafe ,
231
+ entityTraps ,
232
+ handlerTraps ,
233
+ getHandlerContext ,
234
+ contractRegisterTraps ,
235
+ getContractRegisterContext ,
236
+ getContractRegisterArgs ,
237
+ }
238
+ /* paramsByThis Not a pure module */
package/src/Utils.res CHANGED
@@ -175,6 +175,15 @@ module Dict = {
175
175
  }
176
176
  `)
177
177
 
178
+ let unsafeDeleteUndefinedFieldsInPlace: 'a => unit = %raw(`(dict) => {
179
+ for (var key in dict) {
180
+ if (dict[key] === undefined) {
181
+ delete dict[key];
182
+ }
183
+ }
184
+ }
185
+ `)
186
+
178
187
  let updateImmutable: (
179
188
  dict<'a>,
180
189
  string,
@@ -472,6 +481,12 @@ module Schema = {
472
481
  ->(magic: S.t<Js.Json.t> => S.t<Js.Date.t>)
473
482
  ->S.preprocess(_ => {serializer: date => date->magic->Js.Date.toISOString})
474
483
 
484
+ // ClickHouse expects timestamps as numbers (milliseconds), not ISO strings
485
+ let clickHouseDate =
486
+ S.json(~validate=false)
487
+ ->(magic: S.t<Js.Json.t> => S.t<Js.Date.t>)
488
+ ->S.preprocess(_ => {serializer: date => date->magic->Js.Date.getTime})
489
+
475
490
  // When trying to serialize data to Json pg type, it will fail with
476
491
  // PostgresError: column "params" is of type json but expression is of type boolean
477
492
  // If there's bool or null on the root level. It works fine as object field values.
package/src/Utils.res.mjs CHANGED
@@ -151,6 +151,14 @@ var deleteInPlace = ((dict, key) => {
151
151
  delete dict[key];
152
152
  });
153
153
 
154
+ var unsafeDeleteUndefinedFieldsInPlace = ((dict) => {
155
+ for (var key in dict) {
156
+ if (dict[key] === undefined) {
157
+ delete dict[key];
158
+ }
159
+ }
160
+ });
161
+
154
162
  var updateImmutable = ((dict, key, value) => ({...dict, [key]: value}));
155
163
 
156
164
  var shallowCopy = ((dict) => ({...dict}));
@@ -172,6 +180,7 @@ var Dict = {
172
180
  size: size,
173
181
  isEmpty: isEmpty,
174
182
  deleteInPlace: deleteInPlace,
183
+ unsafeDeleteUndefinedFieldsInPlace: unsafeDeleteUndefinedFieldsInPlace,
175
184
  updateImmutable: updateImmutable,
176
185
  shallowCopy: shallowCopy,
177
186
  incrementByInt: incrementByInt
@@ -449,6 +458,14 @@ var dbDate = S$RescriptSchema.preprocess(S$RescriptSchema.json(false), (function
449
458
  };
450
459
  }));
451
460
 
461
+ var clickHouseDate = S$RescriptSchema.preprocess(S$RescriptSchema.json(false), (function (param) {
462
+ return {
463
+ s: (function (date) {
464
+ return date.getTime();
465
+ })
466
+ };
467
+ }));
468
+
452
469
  function coerceToJsonPgType(schema) {
453
470
  return S$RescriptSchema.preprocess(schema, (function (s) {
454
471
  var match = s.schema.t;
@@ -485,6 +502,7 @@ var Schema = {
485
502
  getNonOptionalFieldNames: getNonOptionalFieldNames,
486
503
  getCapitalizedFieldNames: getCapitalizedFieldNames,
487
504
  dbDate: dbDate,
505
+ clickHouseDate: clickHouseDate,
488
506
  coerceToJsonPgType: coerceToJsonPgType
489
507
  };
490
508