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.
- package/README.md +2 -2
- package/evm.schema.json +44 -34
- package/fuel.schema.json +32 -21
- package/index.d.ts +4 -1
- package/index.js +1 -0
- package/package.json +7 -6
- package/src/Batch.res.mjs +1 -1
- package/src/Benchmark.res +394 -0
- package/src/Benchmark.res.mjs +398 -0
- package/src/ChainFetcher.res +459 -0
- package/src/ChainFetcher.res.mjs +281 -0
- package/src/ChainManager.res +179 -0
- package/src/ChainManager.res.mjs +139 -0
- package/src/Config.res +15 -1
- package/src/Config.res.mjs +28 -5
- package/src/Ecosystem.res +9 -124
- package/src/Ecosystem.res.mjs +19 -160
- package/src/Env.res +0 -1
- package/src/Env.res.mjs +0 -3
- package/src/Envio.gen.ts +9 -1
- package/src/Envio.res +12 -9
- package/src/EventProcessing.res +476 -0
- package/src/EventProcessing.res.mjs +341 -0
- package/src/FetchState.res +54 -29
- package/src/FetchState.res.mjs +62 -35
- package/src/GlobalState.res +1169 -0
- package/src/GlobalState.res.mjs +1196 -0
- package/src/Internal.res +43 -1
- package/src/LoadLayer.res +444 -0
- package/src/LoadLayer.res.mjs +296 -0
- package/src/LoadLayer.resi +32 -0
- package/src/Prometheus.res +8 -8
- package/src/Prometheus.res.mjs +10 -10
- package/src/ReorgDetection.res +6 -10
- package/src/ReorgDetection.res.mjs +6 -6
- package/src/Types.ts +1 -1
- package/src/UserContext.res +356 -0
- package/src/UserContext.res.mjs +238 -0
- package/src/Utils.res +15 -0
- package/src/Utils.res.mjs +18 -0
- package/src/bindings/ClickHouse.res +31 -1
- package/src/bindings/ClickHouse.res.mjs +27 -1
- package/src/bindings/DateFns.res +71 -0
- package/src/bindings/DateFns.res.mjs +22 -0
- package/src/bindings/Ethers.res +27 -63
- package/src/bindings/Ethers.res.mjs +18 -65
- package/src/sources/Evm.res +87 -0
- package/src/sources/Evm.res.mjs +105 -0
- package/src/sources/EvmChain.res +95 -0
- package/src/sources/EvmChain.res.mjs +61 -0
- package/src/sources/Fuel.res +19 -34
- package/src/sources/Fuel.res.mjs +34 -16
- package/src/sources/FuelSDK.res +37 -0
- package/src/sources/FuelSDK.res.mjs +29 -0
- package/src/sources/HyperFuel.res +2 -2
- package/src/sources/HyperFuel.resi +1 -1
- package/src/sources/HyperFuelClient.res +2 -2
- package/src/sources/HyperFuelSource.res +8 -8
- package/src/sources/HyperFuelSource.res.mjs +5 -5
- package/src/sources/HyperSyncHeightStream.res +28 -110
- package/src/sources/HyperSyncHeightStream.res.mjs +30 -63
- package/src/sources/HyperSyncSource.res +16 -18
- package/src/sources/HyperSyncSource.res.mjs +25 -25
- package/src/sources/Rpc.res +43 -0
- package/src/sources/Rpc.res.mjs +31 -0
- package/src/sources/RpcSource.res +13 -8
- package/src/sources/RpcSource.res.mjs +12 -7
- package/src/sources/Source.res +3 -2
- package/src/sources/SourceManager.res +183 -108
- package/src/sources/SourceManager.res.mjs +162 -99
- package/src/sources/SourceManager.resi +4 -5
- package/src/sources/Svm.res +59 -0
- package/src/sources/Svm.res.mjs +79 -0
- 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
|
|