envio 3.1.2 → 3.2.1
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/evm.schema.json +83 -11
- package/fuel.schema.json +83 -11
- package/index.d.ts +184 -3
- package/package.json +6 -6
- package/src/Batch.res +2 -2
- package/src/ChainFetcher.res +27 -3
- package/src/ChainFetcher.res.mjs +17 -3
- package/src/ChainManager.res +163 -0
- package/src/ChainManager.res.mjs +136 -0
- package/src/Config.res +213 -30
- package/src/Config.res.mjs +102 -41
- package/src/Core.res +16 -10
- package/src/Ecosystem.res +0 -3
- package/src/Env.res +2 -2
- package/src/Env.res.mjs +2 -2
- package/src/Envio.res +101 -2
- package/src/Envio.res.mjs +2 -3
- package/src/EventConfigBuilder.res +87 -0
- package/src/EventConfigBuilder.res.mjs +53 -0
- package/src/EventUtils.res +2 -2
- package/src/FetchState.res +63 -67
- package/src/FetchState.res.mjs +44 -42
- package/src/GlobalState.res +219 -363
- package/src/GlobalState.res.mjs +314 -491
- package/src/GlobalStateManager.res +49 -59
- package/src/GlobalStateManager.res.mjs +5 -4
- package/src/GlobalStateManager.resi +1 -1
- package/src/HandlerLoader.res +18 -2
- package/src/HandlerLoader.res.mjs +16 -34
- package/src/HandlerRegister.res +9 -9
- package/src/HandlerRegister.res.mjs +9 -9
- package/src/Hasura.res +102 -32
- package/src/Hasura.res.mjs +88 -34
- package/src/InMemoryStore.res +10 -1
- package/src/InMemoryStore.res.mjs +4 -1
- package/src/InMemoryTable.res +83 -136
- package/src/InMemoryTable.res.mjs +57 -86
- package/src/Internal.res +70 -5
- package/src/Internal.res.mjs +2 -8
- package/src/LazyLoader.res +2 -2
- package/src/LazyLoader.res.mjs +3 -3
- package/src/LoadLayer.res +47 -60
- package/src/LoadLayer.res.mjs +28 -50
- package/src/LoadLayer.resi +2 -5
- package/src/LogSelection.res +90 -21
- package/src/LogSelection.res.mjs +72 -21
- package/src/Logging.res +1 -1
- package/src/Main.res +61 -2
- package/src/Main.res.mjs +37 -1
- package/src/Persistence.res +3 -16
- package/src/PgStorage.res +125 -114
- package/src/PgStorage.res.mjs +112 -95
- package/src/Ports.res +5 -0
- package/src/Ports.res.mjs +9 -0
- package/src/Prometheus.res +3 -3
- package/src/Prometheus.res.mjs +4 -4
- package/src/ReorgDetection.res +4 -4
- package/src/ReorgDetection.res.mjs +4 -5
- package/src/SafeCheckpointTracking.res +16 -16
- package/src/SafeCheckpointTracking.res.mjs +2 -2
- package/src/SimulateItems.res +10 -14
- package/src/SimulateItems.res.mjs +5 -2
- package/src/Sink.res +1 -1
- package/src/Sink.res.mjs +1 -2
- package/src/SvmTypes.res +9 -0
- package/src/SvmTypes.res.mjs +14 -0
- package/src/TestIndexer.res +35 -68
- package/src/TestIndexer.res.mjs +17 -48
- package/src/TestIndexerProxyStorage.res +23 -23
- package/src/TestIndexerProxyStorage.res.mjs +12 -15
- package/src/Throttler.res +2 -2
- package/src/Time.res +2 -2
- package/src/Time.res.mjs +2 -2
- package/src/UserContext.res +19 -118
- package/src/UserContext.res.mjs +10 -66
- package/src/Utils.res +15 -15
- package/src/Utils.res.mjs +7 -8
- package/src/adapters/MarkBatchProcessedAdapter.res +5 -0
- package/src/adapters/MarkBatchProcessedAdapter.res.mjs +14 -0
- package/src/bindings/BigDecimal.res +1 -1
- package/src/bindings/BigDecimal.res.mjs +2 -2
- package/src/bindings/ClickHouse.res +8 -6
- package/src/bindings/ClickHouse.res.mjs +5 -5
- package/src/bindings/Hrtime.res +1 -1
- package/src/bindings/Pino.res +2 -2
- package/src/bindings/Pino.res.mjs +3 -4
- package/src/db/EntityFilter.res +410 -0
- package/src/db/EntityFilter.res.mjs +424 -0
- package/src/db/EntityHistory.res +1 -1
- package/src/db/EntityHistory.res.mjs +1 -1
- package/src/db/InternalTable.res +10 -10
- package/src/db/InternalTable.res.mjs +41 -45
- package/src/db/Schema.res +2 -2
- package/src/db/Schema.res.mjs +3 -3
- package/src/db/Table.res +106 -22
- package/src/db/Table.res.mjs +84 -35
- package/src/sources/EventRouter.res +67 -2
- package/src/sources/EventRouter.res.mjs +45 -3
- package/src/sources/Evm.res +0 -7
- package/src/sources/Evm.res.mjs +0 -15
- package/src/sources/EvmChain.res +1 -1
- package/src/sources/EvmChain.res.mjs +1 -2
- package/src/sources/EvmRpcClient.res +42 -0
- package/src/sources/EvmRpcClient.res.mjs +64 -0
- package/src/sources/Fuel.res +0 -7
- package/src/sources/Fuel.res.mjs +0 -15
- package/src/sources/HyperFuelSource.res +5 -4
- package/src/sources/HyperFuelSource.res.mjs +2 -2
- package/src/sources/HyperSyncClient.res +9 -5
- package/src/sources/HyperSyncClient.res.mjs +2 -2
- package/src/sources/HyperSyncHeightStream.res +2 -2
- package/src/sources/HyperSyncHeightStream.res.mjs +2 -2
- package/src/sources/HyperSyncSource.res +12 -11
- package/src/sources/HyperSyncSource.res.mjs +6 -6
- package/src/sources/Rpc.res +1 -5
- package/src/sources/Rpc.res.mjs +1 -9
- package/src/sources/RpcSource.res +57 -21
- package/src/sources/RpcSource.res.mjs +47 -20
- package/src/sources/RpcWebSocketHeightStream.res +1 -1
- package/src/sources/SourceManager.res +3 -2
- package/src/sources/SourceManager.res.mjs +1 -1
- package/src/sources/Svm.res +3 -10
- package/src/sources/Svm.res.mjs +4 -18
- package/src/sources/SvmHyperSyncClient.res +265 -0
- package/src/sources/SvmHyperSyncClient.res.mjs +28 -0
- package/src/sources/SvmHyperSyncSource.res +638 -0
- package/src/sources/SvmHyperSyncSource.res.mjs +557 -0
- package/src/tui/Tui.res +9 -2
- package/src/tui/Tui.res.mjs +18 -3
- package/src/tui/components/BufferedProgressBar.res +2 -2
- package/src/tui/components/TuiData.res +3 -0
- package/svm.schema.json +523 -14
- package/src/TableIndices.res +0 -115
- package/src/TableIndices.res.mjs +0 -144
package/src/db/Schema.res
CHANGED
|
@@ -6,11 +6,11 @@ let make = (tables: array<Table.table>) => {
|
|
|
6
6
|
|
|
7
7
|
exception UndefinedEntity(Table.derivedFromField)
|
|
8
8
|
exception UndefinedFieldInEntity(Table.derivedFromField)
|
|
9
|
-
let
|
|
9
|
+
let getDerivedFromPgFieldName = (schema: t, derivedFromField: Table.derivedFromField) =>
|
|
10
10
|
switch schema->Utils.Dict.dangerouslyGetNonOption(derivedFromField.derivedFromEntity) {
|
|
11
11
|
| Some(entity) =>
|
|
12
12
|
switch entity->Table.getFieldByName(derivedFromField.derivedFromField) {
|
|
13
|
-
| Some(field) => field->Table.
|
|
13
|
+
| Some(field) => field->Table.getPgFieldName->Ok
|
|
14
14
|
| None => Error(UndefinedFieldInEntity(derivedFromField)) //Unexpected, schema should be parsed on codegen
|
|
15
15
|
}
|
|
16
16
|
| None => Error(UndefinedEntity(derivedFromField)) //Unexpected, schema should be parsed on codegen
|
package/src/db/Schema.res.mjs
CHANGED
|
@@ -14,7 +14,7 @@ let UndefinedEntity = /* @__PURE__ */Primitive_exceptions.create("Schema.Undefin
|
|
|
14
14
|
|
|
15
15
|
let UndefinedFieldInEntity = /* @__PURE__ */Primitive_exceptions.create("Schema.UndefinedFieldInEntity");
|
|
16
16
|
|
|
17
|
-
function
|
|
17
|
+
function getDerivedFromPgFieldName(schema, derivedFromField) {
|
|
18
18
|
let entity = schema[derivedFromField.derivedFromEntity];
|
|
19
19
|
if (entity === undefined) {
|
|
20
20
|
return {
|
|
@@ -29,7 +29,7 @@ function getDerivedFromFieldName(schema, derivedFromField) {
|
|
|
29
29
|
if (field !== undefined) {
|
|
30
30
|
return {
|
|
31
31
|
TAG: "Ok",
|
|
32
|
-
_0: Table.
|
|
32
|
+
_0: Table.getPgFieldName(field)
|
|
33
33
|
};
|
|
34
34
|
} else {
|
|
35
35
|
return {
|
|
@@ -46,6 +46,6 @@ export {
|
|
|
46
46
|
make,
|
|
47
47
|
UndefinedEntity,
|
|
48
48
|
UndefinedFieldInEntity,
|
|
49
|
-
|
|
49
|
+
getDerivedFromPgFieldName,
|
|
50
50
|
}
|
|
51
51
|
/* Table Not a pure module */
|
package/src/db/Table.res
CHANGED
|
@@ -44,6 +44,11 @@ type field = {
|
|
|
44
44
|
linkedEntity: option<string>,
|
|
45
45
|
defaultValue: option<string>,
|
|
46
46
|
description: option<string>,
|
|
47
|
+
// Override the column name per storage backend (eg when `column_name_format:
|
|
48
|
+
// snake_case` is configured), while the API keeps using fieldName. The
|
|
49
|
+
// backends can be configured with different formats, so each gets its own override.
|
|
50
|
+
postgresDbName: option<string>,
|
|
51
|
+
clickhouseDbName: option<string>,
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
type derivedFromField = {
|
|
@@ -66,6 +71,8 @@ let mkField = (
|
|
|
66
71
|
~isIndex=false,
|
|
67
72
|
~linkedEntity=?,
|
|
68
73
|
~description=?,
|
|
74
|
+
~postgresDbName=?,
|
|
75
|
+
~clickhouseDbName=?,
|
|
69
76
|
) =>
|
|
70
77
|
{
|
|
71
78
|
fieldName,
|
|
@@ -78,6 +85,8 @@ let mkField = (
|
|
|
78
85
|
linkedEntity,
|
|
79
86
|
defaultValue: default,
|
|
80
87
|
description,
|
|
88
|
+
postgresDbName,
|
|
89
|
+
clickhouseDbName,
|
|
81
90
|
}->Field
|
|
82
91
|
|
|
83
92
|
let mkDerivedFromField = (fieldName, ~derivedFromEntity, ~derivedFromField, ~description=?) =>
|
|
@@ -96,12 +105,29 @@ let getUserDefinedFieldName = fieldOrDerived =>
|
|
|
96
105
|
|
|
97
106
|
let isLinkedEntityField = field => field.linkedEntity->Option.isSome
|
|
98
107
|
|
|
99
|
-
|
|
108
|
+
// The field name exposed to the user-facing APIs (entity records, getWhere,
|
|
109
|
+
// Hasura GraphQL). Entity references get an `_id` suffix since the column
|
|
110
|
+
// stores the referenced entity id.
|
|
111
|
+
let getApiFieldName = field =>
|
|
100
112
|
field->isLinkedEntityField ? field.fieldName ++ "_id" : field.fieldName
|
|
101
113
|
|
|
102
|
-
|
|
114
|
+
// The actual column name in the storage. Matches the API field name unless
|
|
115
|
+
// the storage is configured with a different column naming.
|
|
116
|
+
let getPgDbFieldName = field =>
|
|
117
|
+
switch field.postgresDbName {
|
|
118
|
+
| Some(dbName) => dbName
|
|
119
|
+
| None => field->getApiFieldName
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let getClickHouseDbFieldName = field =>
|
|
123
|
+
switch field.clickhouseDbName {
|
|
124
|
+
| Some(dbName) => dbName
|
|
125
|
+
| None => field->getApiFieldName
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let getPgFieldName = fieldOrDerived =>
|
|
103
129
|
switch fieldOrDerived {
|
|
104
|
-
| Field(field) => field->
|
|
130
|
+
| Field(field) => field->getPgDbFieldName
|
|
105
131
|
| DerivedFrom({fieldName}) => fieldName
|
|
106
132
|
}
|
|
107
133
|
|
|
@@ -177,10 +203,10 @@ let mkTable = (tableName, ~compositeIndices=[], ~fields, ~description=?) => {
|
|
|
177
203
|
description,
|
|
178
204
|
}
|
|
179
205
|
|
|
180
|
-
let
|
|
206
|
+
let getPgPrimaryKeyFieldNames = table =>
|
|
181
207
|
table.fields->Array.filterMap(field =>
|
|
182
208
|
switch field {
|
|
183
|
-
| Field({isPrimaryKey: true
|
|
209
|
+
| Field({isPrimaryKey: true} as field) => Some(field->getPgDbFieldName)
|
|
184
210
|
| _ => None
|
|
185
211
|
}
|
|
186
212
|
)
|
|
@@ -193,10 +219,6 @@ let getFields = table =>
|
|
|
193
219
|
}
|
|
194
220
|
)
|
|
195
221
|
|
|
196
|
-
let getFieldNames = table => {
|
|
197
|
-
table->getFields->Array.map(getDbFieldName)
|
|
198
|
-
}
|
|
199
|
-
|
|
200
222
|
let getNonDefaultFields = table =>
|
|
201
223
|
table.fields->Array.filterMap(field =>
|
|
202
224
|
switch field {
|
|
@@ -223,23 +245,82 @@ let getDerivedFromFields = table =>
|
|
|
223
245
|
}
|
|
224
246
|
)
|
|
225
247
|
|
|
226
|
-
let getNonDefaultFieldNames = table => {
|
|
227
|
-
table->getNonDefaultFields->Array.map(getDbFieldName)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
248
|
let getFieldByName = (table, fieldName) =>
|
|
231
249
|
table.fields->Array.find(field => field->getUserDefinedFieldName === fieldName)
|
|
232
250
|
|
|
233
251
|
// TODO: Test whether it should be passed via args and match the column type
|
|
234
252
|
|
|
235
|
-
let
|
|
253
|
+
let getFieldByApiName = (table, apiFieldName) =>
|
|
236
254
|
table.fields->Array.find(field =>
|
|
237
255
|
switch field {
|
|
238
|
-
| Field(f) => f->
|
|
256
|
+
| Field(f) => f->getApiFieldName
|
|
239
257
|
| DerivedFrom({fieldName}) => fieldName
|
|
240
|
-
} ===
|
|
258
|
+
} === apiFieldName
|
|
241
259
|
)
|
|
242
260
|
|
|
261
|
+
// Both schema instances are created once per field: rescript-schema compiles
|
|
262
|
+
// and caches operations on the schema instance, so building S.array(fieldSchema)
|
|
263
|
+
// per query would recompile the serializer on every call.
|
|
264
|
+
type queryField = {
|
|
265
|
+
fieldSchema: S.t<unknown>,
|
|
266
|
+
// Serializes the values array of an "in" filter
|
|
267
|
+
arrayFieldSchema: S.t<unknown>,
|
|
268
|
+
// The Postgres column referenced in load SQL, which only differs from the
|
|
269
|
+
// API field name keying this entry when column renaming is configured.
|
|
270
|
+
// Loads are served by Postgres only (ClickHouse is a write-only sink), so
|
|
271
|
+
// no ClickHouse counterpart is needed here.
|
|
272
|
+
pgDbFieldName: string,
|
|
273
|
+
}
|
|
274
|
+
let queryFields: table => dict<queryField> = Utils.WeakMap.memoize(table => {
|
|
275
|
+
let dict = Dict.make()
|
|
276
|
+
table.fields->Array.forEach(field =>
|
|
277
|
+
switch field {
|
|
278
|
+
| Field(field) =>
|
|
279
|
+
dict->Dict.set(
|
|
280
|
+
field->getApiFieldName,
|
|
281
|
+
{
|
|
282
|
+
fieldSchema: field.fieldSchema,
|
|
283
|
+
arrayFieldSchema: S.array(field.fieldSchema)->S.toUnknown,
|
|
284
|
+
pgDbFieldName: field->getPgDbFieldName,
|
|
285
|
+
},
|
|
286
|
+
)
|
|
287
|
+
| DerivedFrom(_) => ()
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
dict
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
// Parses rows into entity objects keyed by API field names (the camelCase
|
|
294
|
+
// record field names are type-level only), reading each value from the
|
|
295
|
+
// row key produced by ~rowFieldName.
|
|
296
|
+
let makeRowsSchema = (table, ~rowFieldName) =>
|
|
297
|
+
S.array(
|
|
298
|
+
S.object(s => {
|
|
299
|
+
let dict = Dict.make()
|
|
300
|
+
table.fields->Array.forEach(
|
|
301
|
+
field =>
|
|
302
|
+
switch field {
|
|
303
|
+
| Field(field) =>
|
|
304
|
+
dict->Dict.set(field->getApiFieldName, s.field(field->rowFieldName, field.fieldSchema))
|
|
305
|
+
| DerivedFrom(_) => ()
|
|
306
|
+
},
|
|
307
|
+
)
|
|
308
|
+
dict
|
|
309
|
+
})->(Utils.magic: S.t<dict<unknown>> => S.t<unknown>),
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
let rowsSchema: table => S.t<array<unknown>> = Utils.WeakMap.memoize(table =>
|
|
313
|
+
table->makeRowsSchema(~rowFieldName=getApiFieldName)
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
// Rows loaded from Postgres are keyed by the possibly renamed column names.
|
|
317
|
+
// Lives here rather than in PgStorage because InMemoryStore also parses
|
|
318
|
+
// Postgres rollback rows and can't depend on PgStorage without a module
|
|
319
|
+
// cycle.
|
|
320
|
+
let pgRowsSchema: table => S.t<array<unknown>> = Utils.WeakMap.memoize(table =>
|
|
321
|
+
table->makeRowsSchema(~rowFieldName=getPgDbFieldName)
|
|
322
|
+
)
|
|
323
|
+
|
|
243
324
|
exception NonExistingTableField(string)
|
|
244
325
|
|
|
245
326
|
/*
|
|
@@ -250,7 +331,7 @@ let getUnfilteredCompositeIndicesUnsafe = (table): array<array<compositeIndexFie
|
|
|
250
331
|
table.compositeIndices->Array.map(compositeIndex =>
|
|
251
332
|
compositeIndex->Array.map(indexField => {
|
|
252
333
|
let dbFieldName = switch table->getFieldByName(indexField.fieldName) {
|
|
253
|
-
| Some(field) => field->
|
|
334
|
+
| Some(field) => field->getPgFieldName
|
|
254
335
|
| None => throw(NonExistingTableField(indexField.fieldName)) //Unexpected should be validated in schema parser
|
|
255
336
|
}
|
|
256
337
|
{fieldName: dbFieldName, direction: indexField.direction}
|
|
@@ -276,7 +357,7 @@ let toSqlParams = (table: table, ~schema, ~pgSchema) => {
|
|
|
276
357
|
switch schema->S.classify {
|
|
277
358
|
| Object({items}) =>
|
|
278
359
|
let dict = Dict.make()
|
|
279
|
-
items->
|
|
360
|
+
items->Array.forEach(({location, schema}) => {
|
|
280
361
|
let rec coerceSchema = schema =>
|
|
281
362
|
switch schema->S.classify {
|
|
282
363
|
| BigInt => Utils.BigInt.schema->S.toUnknown
|
|
@@ -300,18 +381,21 @@ let toSqlParams = (table: table, ~schema, ~pgSchema) => {
|
|
|
300
381
|
| _ => schema
|
|
301
382
|
}
|
|
302
383
|
|
|
303
|
-
let field = switch table->
|
|
384
|
+
let field = switch table->getFieldByApiName(location) {
|
|
304
385
|
| Some(field) => field
|
|
305
386
|
| None => throw(NonExistingTableField(location))
|
|
306
387
|
}
|
|
307
388
|
|
|
389
|
+
// Schema locations use API field names, while the SQL references
|
|
390
|
+
// columns by their possibly renamed db names.
|
|
391
|
+
let quotedDbName = `"${field->getPgFieldName}"`
|
|
308
392
|
quotedFieldNames
|
|
309
|
-
->Array.push(
|
|
393
|
+
->Array.push(quotedDbName)
|
|
310
394
|
->ignore
|
|
311
395
|
switch field {
|
|
312
396
|
| Field({isPrimaryKey: false}) =>
|
|
313
397
|
quotedNonPrimaryFieldNames
|
|
314
|
-
->Array.push(
|
|
398
|
+
->Array.push(quotedDbName)
|
|
315
399
|
->ignore
|
|
316
400
|
| _ => ()
|
|
317
401
|
}
|
|
@@ -360,7 +444,7 @@ And maps the fields defined to their actual db name (some have _id suffix)
|
|
|
360
444
|
let getSingleIndices = (table): array<string> => {
|
|
361
445
|
let indexFields = table.fields->Array.filterMap(field =>
|
|
362
446
|
switch field {
|
|
363
|
-
| Field(field) if field.isIndex => Some(field->
|
|
447
|
+
| Field(field) if field.isIndex => Some(field->getPgDbFieldName)
|
|
364
448
|
| _ => None
|
|
365
449
|
}
|
|
366
450
|
)
|
package/src/db/Table.res.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Utils from "../Utils.res.mjs";
|
|
4
|
-
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
5
4
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
6
5
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
6
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
@@ -17,7 +16,7 @@ function makeEnumConfig(name, variants) {
|
|
|
17
16
|
};
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
function mkField(fieldName, fieldType, fieldSchema, $$default, isArrayOpt, isNullableOpt, isPrimaryKeyOpt, isIndexOpt, linkedEntity, description) {
|
|
19
|
+
function mkField(fieldName, fieldType, fieldSchema, $$default, isArrayOpt, isNullableOpt, isPrimaryKeyOpt, isIndexOpt, linkedEntity, description, postgresDbName, clickhouseDbName) {
|
|
21
20
|
let isArray = isArrayOpt !== undefined ? isArrayOpt : false;
|
|
22
21
|
let isNullable = isNullableOpt !== undefined ? isNullableOpt : false;
|
|
23
22
|
let isPrimaryKey = isPrimaryKeyOpt !== undefined ? isPrimaryKeyOpt : false;
|
|
@@ -34,7 +33,9 @@ function mkField(fieldName, fieldType, fieldSchema, $$default, isArrayOpt, isNul
|
|
|
34
33
|
isIndex: isIndex,
|
|
35
34
|
linkedEntity: linkedEntity,
|
|
36
35
|
defaultValue: $$default,
|
|
37
|
-
description: description
|
|
36
|
+
description: description,
|
|
37
|
+
postgresDbName: postgresDbName,
|
|
38
|
+
clickhouseDbName: clickhouseDbName
|
|
38
39
|
}
|
|
39
40
|
};
|
|
40
41
|
}
|
|
@@ -59,7 +60,7 @@ function isLinkedEntityField(field) {
|
|
|
59
60
|
return Stdlib_Option.isSome(field.linkedEntity);
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
function
|
|
63
|
+
function getApiFieldName(field) {
|
|
63
64
|
if (Stdlib_Option.isSome(field.linkedEntity)) {
|
|
64
65
|
return field.fieldName + "_id";
|
|
65
66
|
} else {
|
|
@@ -67,9 +68,27 @@ function getDbFieldName(field) {
|
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
function
|
|
71
|
+
function getPgDbFieldName(field) {
|
|
72
|
+
let dbName = field.postgresDbName;
|
|
73
|
+
if (dbName !== undefined) {
|
|
74
|
+
return dbName;
|
|
75
|
+
} else {
|
|
76
|
+
return getApiFieldName(field);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function getClickHouseDbFieldName(field) {
|
|
81
|
+
let dbName = field.clickhouseDbName;
|
|
82
|
+
if (dbName !== undefined) {
|
|
83
|
+
return dbName;
|
|
84
|
+
} else {
|
|
85
|
+
return getApiFieldName(field);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getPgFieldName(fieldOrDerived) {
|
|
71
90
|
if (fieldOrDerived.TAG === "Field") {
|
|
72
|
-
return
|
|
91
|
+
return getPgDbFieldName(fieldOrDerived._0);
|
|
73
92
|
} else {
|
|
74
93
|
return fieldOrDerived._0.fieldName;
|
|
75
94
|
}
|
|
@@ -145,14 +164,14 @@ function mkTable(tableName, compositeIndicesOpt, fields, description) {
|
|
|
145
164
|
};
|
|
146
165
|
}
|
|
147
166
|
|
|
148
|
-
function
|
|
167
|
+
function getPgPrimaryKeyFieldNames(table) {
|
|
149
168
|
return Stdlib_Array.filterMap(table.fields, field => {
|
|
150
169
|
if (field.TAG !== "Field") {
|
|
151
170
|
return;
|
|
152
171
|
}
|
|
153
|
-
let
|
|
154
|
-
if (
|
|
155
|
-
return
|
|
172
|
+
let field$1 = field._0;
|
|
173
|
+
if (field$1.isPrimaryKey) {
|
|
174
|
+
return getPgDbFieldName(field$1);
|
|
156
175
|
}
|
|
157
176
|
});
|
|
158
177
|
}
|
|
@@ -165,10 +184,6 @@ function getFields(table) {
|
|
|
165
184
|
});
|
|
166
185
|
}
|
|
167
186
|
|
|
168
|
-
function getFieldNames(table) {
|
|
169
|
-
return getFields(table).map(getDbFieldName);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
187
|
function getNonDefaultFields(table) {
|
|
173
188
|
return Stdlib_Array.filterMap(table.fields, field => {
|
|
174
189
|
if (field.TAG !== "Field") {
|
|
@@ -207,22 +222,52 @@ function getDerivedFromFields(table) {
|
|
|
207
222
|
});
|
|
208
223
|
}
|
|
209
224
|
|
|
210
|
-
function getNonDefaultFieldNames(table) {
|
|
211
|
-
return getNonDefaultFields(table).map(getDbFieldName);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
225
|
function getFieldByName(table, fieldName) {
|
|
215
226
|
return table.fields.find(field => getUserDefinedFieldName(field) === fieldName);
|
|
216
227
|
}
|
|
217
228
|
|
|
218
|
-
function
|
|
229
|
+
function getFieldByApiName(table, apiFieldName) {
|
|
219
230
|
return table.fields.find(field => {
|
|
220
231
|
let tmp;
|
|
221
|
-
tmp = field.TAG === "Field" ?
|
|
222
|
-
return tmp ===
|
|
232
|
+
tmp = field.TAG === "Field" ? getApiFieldName(field._0) : field._0.fieldName;
|
|
233
|
+
return tmp === apiFieldName;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let queryFields = Utils.$$WeakMap.memoize(table => {
|
|
238
|
+
let dict = {};
|
|
239
|
+
table.fields.forEach(field => {
|
|
240
|
+
if (field.TAG !== "Field") {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
let field$1 = field._0;
|
|
244
|
+
dict[getApiFieldName(field$1)] = {
|
|
245
|
+
fieldSchema: field$1.fieldSchema,
|
|
246
|
+
arrayFieldSchema: S$RescriptSchema.array(field$1.fieldSchema),
|
|
247
|
+
pgDbFieldName: getPgDbFieldName(field$1)
|
|
248
|
+
};
|
|
223
249
|
});
|
|
250
|
+
return dict;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
function makeRowsSchema(table, rowFieldName) {
|
|
254
|
+
return S$RescriptSchema.array(S$RescriptSchema.object(s => {
|
|
255
|
+
let dict = {};
|
|
256
|
+
table.fields.forEach(field => {
|
|
257
|
+
if (field.TAG !== "Field") {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
let field$1 = field._0;
|
|
261
|
+
dict[getApiFieldName(field$1)] = s.f(rowFieldName(field$1), field$1.fieldSchema);
|
|
262
|
+
});
|
|
263
|
+
return dict;
|
|
264
|
+
}));
|
|
224
265
|
}
|
|
225
266
|
|
|
267
|
+
let rowsSchema = Utils.$$WeakMap.memoize(table => makeRowsSchema(table, getApiFieldName));
|
|
268
|
+
|
|
269
|
+
let pgRowsSchema = Utils.$$WeakMap.memoize(table => makeRowsSchema(table, getPgDbFieldName));
|
|
270
|
+
|
|
226
271
|
let NonExistingTableField = /* @__PURE__ */Primitive_exceptions.create("Table.NonExistingTableField");
|
|
227
272
|
|
|
228
273
|
function getUnfilteredCompositeIndicesUnsafe(table) {
|
|
@@ -230,7 +275,7 @@ function getUnfilteredCompositeIndicesUnsafe(table) {
|
|
|
230
275
|
let field = getFieldByName(table, indexField.fieldName);
|
|
231
276
|
let dbFieldName;
|
|
232
277
|
if (field !== undefined) {
|
|
233
|
-
dbFieldName =
|
|
278
|
+
dbFieldName = getPgFieldName(field);
|
|
234
279
|
} else {
|
|
235
280
|
throw {
|
|
236
281
|
RE_EXN_ID: NonExistingTableField,
|
|
@@ -261,8 +306,7 @@ function toSqlParams(table, schema, pgSchema) {
|
|
|
261
306
|
return Stdlib_JsError.throwWithMessage("Failed creating db schema. Expected an object schema for table");
|
|
262
307
|
}
|
|
263
308
|
let dict = {};
|
|
264
|
-
|
|
265
|
-
let inlinedLocation = param.inlinedLocation;
|
|
309
|
+
match.items.forEach(param => {
|
|
266
310
|
let location = param.location;
|
|
267
311
|
let coerceSchema = schema => {
|
|
268
312
|
let child = schema.t;
|
|
@@ -294,7 +338,7 @@ function toSqlParams(table, schema, pgSchema) {
|
|
|
294
338
|
}
|
|
295
339
|
}
|
|
296
340
|
};
|
|
297
|
-
let field =
|
|
341
|
+
let field = getFieldByApiName(table, location);
|
|
298
342
|
let field$1;
|
|
299
343
|
if (field !== undefined) {
|
|
300
344
|
field$1 = field;
|
|
@@ -305,12 +349,13 @@ function toSqlParams(table, schema, pgSchema) {
|
|
|
305
349
|
Error: new Error()
|
|
306
350
|
};
|
|
307
351
|
}
|
|
308
|
-
|
|
352
|
+
let quotedDbName = `"` + getPgFieldName(field$1) + `"`;
|
|
353
|
+
quotedFieldNames.push(quotedDbName);
|
|
309
354
|
if (field$1.TAG === "Field") {
|
|
310
355
|
if (field$1._0.isPrimaryKey) {
|
|
311
356
|
|
|
312
357
|
} else {
|
|
313
|
-
quotedNonPrimaryFieldNames.push(
|
|
358
|
+
quotedNonPrimaryFieldNames.push(quotedDbName);
|
|
314
359
|
}
|
|
315
360
|
}
|
|
316
361
|
let tmp;
|
|
@@ -347,7 +392,7 @@ function getSingleIndices(table) {
|
|
|
347
392
|
}
|
|
348
393
|
let field$1 = field._0;
|
|
349
394
|
if (field$1.isIndex) {
|
|
350
|
-
return
|
|
395
|
+
return getPgDbFieldName(field$1);
|
|
351
396
|
}
|
|
352
397
|
});
|
|
353
398
|
return Array.from(new Set(Stdlib_Array.filterMap(getUnfilteredCompositeIndicesUnsafe(table), cidx => {
|
|
@@ -371,24 +416,28 @@ export {
|
|
|
371
416
|
mkDerivedFromField,
|
|
372
417
|
getUserDefinedFieldName,
|
|
373
418
|
isLinkedEntityField,
|
|
374
|
-
|
|
375
|
-
|
|
419
|
+
getApiFieldName,
|
|
420
|
+
getPgDbFieldName,
|
|
421
|
+
getClickHouseDbFieldName,
|
|
422
|
+
getPgFieldName,
|
|
376
423
|
idFieldName,
|
|
377
424
|
getPgFieldType,
|
|
378
425
|
mkTable,
|
|
379
|
-
|
|
426
|
+
getPgPrimaryKeyFieldNames,
|
|
380
427
|
getFields,
|
|
381
|
-
getFieldNames,
|
|
382
428
|
getNonDefaultFields,
|
|
383
429
|
getLinkedEntityFields,
|
|
384
430
|
getDerivedFromFields,
|
|
385
|
-
getNonDefaultFieldNames,
|
|
386
431
|
getFieldByName,
|
|
387
|
-
|
|
432
|
+
getFieldByApiName,
|
|
433
|
+
queryFields,
|
|
434
|
+
makeRowsSchema,
|
|
435
|
+
rowsSchema,
|
|
436
|
+
pgRowsSchema,
|
|
388
437
|
NonExistingTableField,
|
|
389
438
|
getUnfilteredCompositeIndicesUnsafe,
|
|
390
439
|
toSqlParams,
|
|
391
440
|
getSingleIndices,
|
|
392
441
|
getCompositeIndices,
|
|
393
442
|
}
|
|
394
|
-
/*
|
|
443
|
+
/* queryFields Not a pure module */
|
|
@@ -97,14 +97,14 @@ let get = (router: t<'a>, ~tag, ~contractAddress, ~blockNumber, ~indexingAddress
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
let getEvmEventId = (~sighash, ~topicCount) => {
|
|
100
|
-
sighash ++ "_" ++ topicCount->
|
|
100
|
+
sighash ++ "_" ++ topicCount->Int.toString
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
let fromEvmEventModsOrThrow = (events: array<Internal.evmEventConfig>, ~chain): t<
|
|
104
104
|
Internal.evmEventConfig,
|
|
105
105
|
> => {
|
|
106
106
|
let router = empty()
|
|
107
|
-
events->
|
|
107
|
+
events->Array.forEach(config => {
|
|
108
108
|
router->addOrThrow(
|
|
109
109
|
config.id,
|
|
110
110
|
config,
|
|
@@ -116,3 +116,68 @@ let fromEvmEventModsOrThrow = (events: array<Internal.evmEventConfig>, ~chain):
|
|
|
116
116
|
})
|
|
117
117
|
router
|
|
118
118
|
}
|
|
119
|
+
|
|
120
|
+
/** Dispatch key for SVM instructions. `None` matches any instruction in the
|
|
121
|
+
program (lowest priority). */
|
|
122
|
+
let getSvmEventId = (~programId: SvmTypes.Pubkey.t, ~discriminator: option<string>) =>
|
|
123
|
+
switch discriminator {
|
|
124
|
+
| None => programId->SvmTypes.Pubkey.toString ++ "_none"
|
|
125
|
+
| Some(d) => programId->SvmTypes.Pubkey.toString ++ "_" ++ d
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Discriminator byte-lengths declared by a program, sorted descending. The
|
|
129
|
+
source uses this to probe `(programId, dN)` keys longest-first when routing
|
|
130
|
+
a returned instruction to a handler — matching the locked Q1 answer. */
|
|
131
|
+
type svmProgramOrdering = {
|
|
132
|
+
programId: SvmTypes.Pubkey.t,
|
|
133
|
+
/** Byte lengths in descending order, deduplicated. Includes `0` only when
|
|
134
|
+
a handler is registered with no discriminator (program-wide match). */
|
|
135
|
+
byteLengthsDesc: array<int>,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let fromSvmEventConfigsOrThrow = (events: array<Internal.svmInstructionEventConfig>, ~chain): (
|
|
139
|
+
t<Internal.svmInstructionEventConfig>,
|
|
140
|
+
array<svmProgramOrdering>,
|
|
141
|
+
) => {
|
|
142
|
+
let router = empty()
|
|
143
|
+
events->Array.forEach(config => {
|
|
144
|
+
// The router tag must include the programId so two programs declaring the
|
|
145
|
+
// same discriminator coexist. The source-side lookup uses the same shape
|
|
146
|
+
// via `getSvmEventId(~programId, ~discriminator)`.
|
|
147
|
+
let routerTag = getSvmEventId(~programId=config.programId, ~discriminator=config.discriminator)
|
|
148
|
+
router->addOrThrow(
|
|
149
|
+
routerTag,
|
|
150
|
+
config,
|
|
151
|
+
~contractName=config.contractName,
|
|
152
|
+
~eventName=config.name,
|
|
153
|
+
~chain,
|
|
154
|
+
~isWildcard=config.isWildcard,
|
|
155
|
+
)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// Per-program list of declared discriminator byte lengths, sorted desc.
|
|
159
|
+
let byProgram: dict<Utils.Set.t<int>> = Dict.make()
|
|
160
|
+
events->Array.forEach(config => {
|
|
161
|
+
let key = config.programId->SvmTypes.Pubkey.toString
|
|
162
|
+
let set = switch byProgram->Utils.Dict.dangerouslyGetNonOption(key) {
|
|
163
|
+
| Some(s) => s
|
|
164
|
+
| None =>
|
|
165
|
+
let s = Utils.Set.make()
|
|
166
|
+
byProgram->Dict.set(key, s)
|
|
167
|
+
s
|
|
168
|
+
}
|
|
169
|
+
let _ = set->Utils.Set.add(config.discriminatorByteLen)
|
|
170
|
+
})
|
|
171
|
+
let ordering =
|
|
172
|
+
byProgram
|
|
173
|
+
->Dict.toArray
|
|
174
|
+
->Array.map(((programIdString, lens)) => {
|
|
175
|
+
let sorted = lens->Utils.Set.toArray->Array.toSorted((a, b) => (b - a)->Int.toFloat)
|
|
176
|
+
{
|
|
177
|
+
programId: programIdString->SvmTypes.Pubkey.fromStringUnsafe,
|
|
178
|
+
byteLengthsDesc: sorted,
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
(router, ordering)
|
|
183
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as ChainMap from "../ChainMap.res.mjs";
|
|
4
|
-
import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
|
|
5
4
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
5
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
7
6
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
@@ -102,15 +101,56 @@ function get$1(router, tag, contractAddress, blockNumber, indexingAddresses) {
|
|
|
102
101
|
}
|
|
103
102
|
|
|
104
103
|
function getEvmEventId(sighash, topicCount) {
|
|
105
|
-
return sighash + "_" +
|
|
104
|
+
return sighash + "_" + topicCount.toString();
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
function fromEvmEventModsOrThrow(events, chain) {
|
|
109
108
|
let router = {};
|
|
110
|
-
|
|
109
|
+
events.forEach(config => addOrThrow$1(router, config.id, config, config.contractName, config.isWildcard, config.name, chain));
|
|
111
110
|
return router;
|
|
112
111
|
}
|
|
113
112
|
|
|
113
|
+
function getSvmEventId(programId, discriminator) {
|
|
114
|
+
if (discriminator !== undefined) {
|
|
115
|
+
return programId + "_" + discriminator;
|
|
116
|
+
} else {
|
|
117
|
+
return programId + "_none";
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function fromSvmEventConfigsOrThrow(events, chain) {
|
|
122
|
+
let router = {};
|
|
123
|
+
events.forEach(config => {
|
|
124
|
+
let routerTag = getSvmEventId(config.programId, config.discriminator);
|
|
125
|
+
addOrThrow$1(router, routerTag, config, config.contractName, config.isWildcard, config.name, chain);
|
|
126
|
+
});
|
|
127
|
+
let byProgram = {};
|
|
128
|
+
events.forEach(config => {
|
|
129
|
+
let key = config.programId;
|
|
130
|
+
let s = byProgram[key];
|
|
131
|
+
let set;
|
|
132
|
+
if (s !== undefined) {
|
|
133
|
+
set = Primitive_option.valFromOption(s);
|
|
134
|
+
} else {
|
|
135
|
+
let s$1 = new Set();
|
|
136
|
+
byProgram[key] = s$1;
|
|
137
|
+
set = s$1;
|
|
138
|
+
}
|
|
139
|
+
set.add(config.discriminatorByteLen);
|
|
140
|
+
});
|
|
141
|
+
let ordering = Object.entries(byProgram).map(param => {
|
|
142
|
+
let sorted = Array.from(param[1]).toSorted((a, b) => b - a | 0);
|
|
143
|
+
return {
|
|
144
|
+
programId: param[0],
|
|
145
|
+
byteLengthsDesc: sorted
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
return [
|
|
149
|
+
router,
|
|
150
|
+
ordering
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
|
|
114
154
|
export {
|
|
115
155
|
EventDuplicate,
|
|
116
156
|
WildcardCollision,
|
|
@@ -120,5 +160,7 @@ export {
|
|
|
120
160
|
get$1 as get,
|
|
121
161
|
getEvmEventId,
|
|
122
162
|
fromEvmEventModsOrThrow,
|
|
163
|
+
getSvmEventId,
|
|
164
|
+
fromSvmEventConfigsOrThrow,
|
|
123
165
|
}
|
|
124
166
|
/* ChainMap Not a pure module */
|
package/src/sources/Evm.res
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
@get external getNumber: Internal.eventBlock => int = "number"
|
|
2
|
-
@get external getTimestamp: Internal.eventBlock => int = "timestamp"
|
|
3
|
-
@get external getId: Internal.eventBlock => string = "hash"
|
|
4
|
-
|
|
5
1
|
let cleanUpRawEventFieldsInPlace: JSON.t => unit = %raw(`fields => {
|
|
6
2
|
delete fields.hash
|
|
7
3
|
delete fields.number
|
|
@@ -77,9 +73,6 @@ let ecosystem: Ecosystem.t = {
|
|
|
77
73
|
blockNumberName: "number",
|
|
78
74
|
blockTimestampName: "timestamp",
|
|
79
75
|
blockHashName: "hash",
|
|
80
|
-
getNumber,
|
|
81
|
-
getTimestamp,
|
|
82
|
-
getId,
|
|
83
76
|
cleanUpRawEventFieldsInPlace,
|
|
84
77
|
onBlockMethodName: "onBlock",
|
|
85
78
|
// EVM filter shape: `{block: {number: {_gte?, _lte?, _every?}}}`.
|