envio 3.15.0 → 3.16.0

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 (99) hide show
  1. package/README.md +40 -34
  2. package/evm.schema.json +11 -2
  3. package/fuel.schema.json +10 -1
  4. package/index.d.ts +6 -0
  5. package/licenses/README.md +1 -1
  6. package/package.json +8 -8
  7. package/src/Batch.res.mjs +5 -5
  8. package/src/BatchProcessing.res +1 -0
  9. package/src/BatchProcessing.res.mjs +1 -0
  10. package/src/ChainState.res +48 -7
  11. package/src/ChainState.res.mjs +27 -11
  12. package/src/Clock.res +57 -0
  13. package/src/Clock.res.mjs +72 -0
  14. package/src/Config.res +10 -3
  15. package/src/Config.res.mjs +4 -2
  16. package/src/Core.res +4 -40
  17. package/src/EffectState.res +10 -2
  18. package/src/EffectState.res.mjs +8 -4
  19. package/src/EffectState.resi +3 -1
  20. package/src/EntityId.res +2 -7
  21. package/src/EntityId.res.mjs +1 -8
  22. package/src/EntityTables.res +4 -1
  23. package/src/EntityTables.res.mjs +1 -1
  24. package/src/FetchState.res +157 -69
  25. package/src/FetchState.res.mjs +144 -49
  26. package/src/FinalizeBackfill.res +2 -4
  27. package/src/FinalizeBackfill.res.mjs +3 -4
  28. package/src/InMemoryTable.res +17 -16
  29. package/src/InMemoryTable.res.mjs +14 -15
  30. package/src/IndexerState.res +28 -4
  31. package/src/IndexerState.res.mjs +19 -6
  32. package/src/IndexerState.resi +4 -0
  33. package/src/Internal.res +0 -49
  34. package/src/Internal.res.mjs +1 -80
  35. package/src/LoadLayer.res +14 -8
  36. package/src/LoadLayer.res.mjs +8 -6
  37. package/src/Main.res.mjs +1 -1
  38. package/src/Persistence.res +3 -23
  39. package/src/Persistence.res.mjs +3 -3
  40. package/src/Rollback.res +0 -1
  41. package/src/Rollback.res.mjs +1 -1
  42. package/src/SafeCheckpointTracking.res +4 -4
  43. package/src/SafeCheckpointTracking.res.mjs +1 -1
  44. package/src/StagedRows.res +106 -0
  45. package/src/StagedRows.res.mjs +102 -0
  46. package/src/Staging.res +32 -14
  47. package/src/Staging.res.mjs +17 -20
  48. package/src/Storage.res +277 -948
  49. package/src/Storage.res.mjs +215 -707
  50. package/src/Supervisor.res +75 -56
  51. package/src/Supervisor.res.mjs +55 -26
  52. package/src/TestIndexer.res +22 -27
  53. package/src/TestIndexer.res.mjs +20 -17
  54. package/src/Throttler.res +15 -8
  55. package/src/Throttler.res.mjs +9 -6
  56. package/src/Throttler.resi +1 -1
  57. package/src/Utils.res +0 -6
  58. package/src/Utils.res.mjs +0 -5
  59. package/src/Writing.res +0 -1
  60. package/src/Writing.res.mjs +1 -1
  61. package/src/bindings/ClickHouse.res +0 -322
  62. package/src/bindings/ClickHouse.res.mjs +0 -338
  63. package/src/bindings/StorageClient.res +107 -174
  64. package/src/bindings/StorageClient.res.mjs +19 -8
  65. package/src/bindings/Vitest.res +0 -26
  66. package/src/bindings/Vitest.res.mjs +0 -3
  67. package/src/db/Table.res +24 -150
  68. package/src/db/Table.res.mjs +38 -272
  69. package/src/sources/ChainSources.res +2 -0
  70. package/src/sources/ChainSources.res.mjs +2 -2
  71. package/src/sources/EvmChain.res +3 -0
  72. package/src/sources/EvmChain.res.mjs +4 -2
  73. package/src/sources/EvmHyperSyncSource.res +2 -2
  74. package/src/sources/EvmHyperSyncSource.res.mjs +1 -1
  75. package/src/sources/EvmRpcClient.res +13 -3
  76. package/src/sources/EvmRpcClient.res.mjs +4 -3
  77. package/src/sources/EvmRpcWs.res +4 -3
  78. package/src/sources/EvmRpcWs.res.mjs +2 -2
  79. package/src/sources/HeightFeed.res +31 -10
  80. package/src/sources/HeightFeed.res.mjs +10 -6
  81. package/src/sources/HeightStream.res +32 -17
  82. package/src/sources/HeightStream.res.mjs +10 -10
  83. package/src/sources/HyperSyncSSE.res +4 -6
  84. package/src/sources/HyperSyncSSE.res.mjs +2 -2
  85. package/src/sources/RpcSource.res +10 -1
  86. package/src/sources/RpcSource.res.mjs +4 -3
  87. package/src/sources/Source.res +3 -0
  88. package/src/sources/SourceManager.res +84 -77
  89. package/src/sources/SourceManager.res.mjs +17 -20
  90. package/src/sources/SourceManager.resi +3 -4
  91. package/src/sources/StartBlockResolver.res +1 -0
  92. package/src/sources/StartBlockResolver.res.mjs +3 -2
  93. package/src/sources/SvmHyperSyncSource.res +2 -2
  94. package/src/sources/SvmHyperSyncSource.res.mjs +1 -1
  95. package/svm.schema.json +11 -2
  96. package/src/PgWriting.res +0 -36
  97. package/src/PgWriting.res.mjs +0 -34
  98. package/src/db/IndexDefinition.res +0 -47
  99. package/src/db/IndexDefinition.res.mjs +0 -67
@@ -0,0 +1,106 @@
1
+ // Values as the addon declares each staged field has to arrive, compiled once
2
+ // per layout and written into a stage.
3
+
4
+ @send external getTime: unknown => float = "getTime"
5
+ @send external toFixed: unknown => string = "toFixed"
6
+ @val @scope("Array") external isArray: unknown => bool = "isArray"
7
+
8
+ // A list element as its JSON: the encoding a scalar of its type would take,
9
+ // except that a boolean stays one and bytes become their values.
10
+ %%private(
11
+ let elementOf = (encoding: Staging.encoding, ~column): (unknown => unknown) =>
12
+ switch encoding {
13
+ | Number =>
14
+ value =>
15
+ value->Staging.toNumber->Staging.finiteOrThrow(~column)->(Utils.magic: float => unknown)
16
+ | Date => value => value->getTime->(Utils.magic: float => unknown)
17
+ | Digits => value => value->Staging.stringOf->(Utils.magic: string => unknown)
18
+ | Decimal => value => value->toFixed->(Utils.magic: string => unknown)
19
+ | Document => value => value->Sql.canonicalDocument->(Utils.magic: string => unknown)
20
+ | Bytes =>
21
+ value =>
22
+ value
23
+ ->(Utils.magic: unknown => Array.arrayLike<int>)
24
+ ->Array.fromArrayLike
25
+ ->(Utils.magic: array<int> => unknown)
26
+ | Bool | Text | List => value => value
27
+ }
28
+ )
29
+
30
+ %%private(
31
+ let rec mapList = (value: unknown, element: unknown => unknown): unknown =>
32
+ if value->isArray {
33
+ value
34
+ ->(Utils.magic: unknown => array<unknown>)
35
+ ->Array.map(item => item->mapList(element))
36
+ ->(Utils.magic: array<unknown> => unknown)
37
+ } else if value === %raw(`undefined`) || value === %raw(`null`) {
38
+ %raw(`null`)
39
+ } else {
40
+ element(value)
41
+ }
42
+ )
43
+
44
+ // What a present value becomes before it is written to its slot.
45
+ %%private(
46
+ let encoderOf = ({name, encoding, element}: Staging.stagedField): (unknown => unknown) =>
47
+ switch encoding {
48
+ | Bool =>
49
+ value => (value->(Utils.magic: unknown => bool) ? 1. : 0.)->(Utils.magic: float => unknown)
50
+ | Date => value => value->getTime->(Utils.magic: float => unknown)
51
+ | Decimal => value => value->toFixed->(Utils.magic: string => unknown)
52
+ | Document => value => value->Sql.canonicalDocument->(Utils.magic: string => unknown)
53
+ | List =>
54
+ let encode = elementOf(element, ~column=name)
55
+ // A document can be a list itself, so a list of them is one level deep.
56
+ let mapList = switch element {
57
+ | Document =>
58
+ (value, encode) =>
59
+ value
60
+ ->(Utils.magic: unknown => array<unknown>)
61
+ ->Array.map(item => item->Staging.isAbsent ? %raw(`null`) : encode(item))
62
+ ->(Utils.magic: array<unknown> => unknown)
63
+ | _ => mapList
64
+ }
65
+ value =>
66
+ value
67
+ ->mapList(encode)
68
+ ->(Utils.magic: unknown => JSON.t)
69
+ ->JSON.stringify
70
+ ->Utils.replaceLoneSurrogateEscapes
71
+ ->(Utils.magic: string => unknown)
72
+ | Number | Text | Digits | Bytes => value => value
73
+ }
74
+ )
75
+
76
+ // A layout's fields compiled once: the slot each takes and how a value of it
77
+ // is written there.
78
+ type writer = {field: Staging.stagedField, encode: unknown => unknown}
79
+
80
+ let writersOf = (fields: array<Staging.stagedField>) =>
81
+ fields->Array.map(field => {field, encode: encoderOf(field)})
82
+
83
+ let columnsOf = (writers: array<writer>): array<Staging.column> =>
84
+ writers->Array.map(({field}) => {
85
+ Staging.name: field.name,
86
+ kind: field.encoding->Staging.kindOf,
87
+ isNullable: field.isNullable,
88
+ })
89
+
90
+ // JSON `null` is a document of its own, which a column that can't be NULL
91
+ // stores as one. Left out, the value is no document and is refused like any
92
+ // other.
93
+ let writeField = (stage, ~writers: array<writer>, ~column, ~row, value: unknown) => {
94
+ let {field, encode} = writers->Array.getUnsafe(column)
95
+ if value->Staging.isAbsent {
96
+ stage->Staging.writeValue(
97
+ ~column,
98
+ ~row,
99
+ field.encoding === Staging.Document && !field.isNullable && value === %raw(`null`)
100
+ ? "null"->(Utils.magic: string => unknown)
101
+ : value,
102
+ )
103
+ } else {
104
+ stage->Staging.writeValue(~column, ~row, encode(value))
105
+ }
106
+ }
@@ -0,0 +1,102 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Sql from "./db/Sql.res.mjs";
4
+ import * as Utils from "./Utils.res.mjs";
5
+ import * as Staging from "./Staging.res.mjs";
6
+
7
+ function elementOf(encoding, column) {
8
+ switch (encoding) {
9
+ case "Number" :
10
+ return value => Staging.finiteOrThrow(Number(value), column);
11
+ case "Date" :
12
+ return value => value.getTime();
13
+ case "Digits" :
14
+ return value => String(value);
15
+ case "Decimal" :
16
+ return value => value.toFixed();
17
+ case "Document" :
18
+ return Sql.canonicalDocument;
19
+ case "Bytes" :
20
+ return value => Array.from(value);
21
+ default:
22
+ return value => value;
23
+ }
24
+ }
25
+
26
+ function mapList(value, element) {
27
+ if (Array.isArray(value)) {
28
+ return value.map(item => mapList(item, element));
29
+ } else if (value === undefined || value === null) {
30
+ return null;
31
+ } else {
32
+ return element(value);
33
+ }
34
+ }
35
+
36
+ function encoderOf(param) {
37
+ let element = param.element;
38
+ switch (param.encoding) {
39
+ case "Bool" :
40
+ return value => {
41
+ if (value) {
42
+ return 1;
43
+ } else {
44
+ return 0;
45
+ }
46
+ };
47
+ case "Date" :
48
+ return value => value.getTime();
49
+ case "Decimal" :
50
+ return value => value.toFixed();
51
+ case "Document" :
52
+ return Sql.canonicalDocument;
53
+ case "List" :
54
+ let encode = elementOf(element, param.name);
55
+ let mapList$1;
56
+ mapList$1 = element === "Document" ? (value, encode) => value.map(item => {
57
+ if (Staging.isAbsent(item)) {
58
+ return null;
59
+ } else {
60
+ return encode(item);
61
+ }
62
+ }) : mapList;
63
+ return value => Utils.replaceLoneSurrogateEscapes(JSON.stringify(mapList$1(value, encode)));
64
+ default:
65
+ return value => value;
66
+ }
67
+ }
68
+
69
+ function writersOf(fields) {
70
+ return fields.map(field => ({
71
+ field: field,
72
+ encode: encoderOf(field)
73
+ }));
74
+ }
75
+
76
+ function columnsOf(writers) {
77
+ return writers.map(param => {
78
+ let field = param.field;
79
+ return {
80
+ name: field.name,
81
+ kind: Staging.kindOf(field.encoding),
82
+ isNullable: field.isNullable
83
+ };
84
+ });
85
+ }
86
+
87
+ function writeField(stage, writers, column, row, value) {
88
+ let match = writers[column];
89
+ let field = match.field;
90
+ if (Staging.isAbsent(value)) {
91
+ return Staging.writeValue(stage, column, row, field.encoding === "Document" && !field.isNullable && value === null ? "null" : value);
92
+ } else {
93
+ return Staging.writeValue(stage, column, row, match.encode(value));
94
+ }
95
+ }
96
+
97
+ export {
98
+ writersOf,
99
+ columnsOf,
100
+ writeField,
101
+ }
102
+ /* Sql Not a pure module */
package/src/Staging.res CHANGED
@@ -10,16 +10,6 @@ type kind =
10
10
  | @as(3) Text
11
11
  | @as(4) Bytes
12
12
 
13
- let kindOfOrdinal = ordinal =>
14
- switch ordinal {
15
- | 0 => F64
16
- | 1 => U64
17
- | 2 => I64
18
- | 3 => Text
19
- | 4 => Bytes
20
- | unknown => JsError.throwWithMessage(`Unknown staged column kind ${unknown->Int.toString}`)
21
- }
22
-
23
13
  // The replacer closes over nothing but the column's name, so it is built once
24
14
  // with the column rather than once per column per batch.
25
15
  type column = {name: string, kind: kind, isNullable: bool, replacer?: JSON.replacer}
@@ -28,7 +18,7 @@ type begun = {handle: int, buffers: array<ArrayBuffer.t>}
28
18
 
29
19
  // What the addon exposes, so this module stays free of the storage's own API.
30
20
  type arena = {
31
- beginStage: (~table: int, ~rows: int) => begun,
21
+ beginStage: (~rows: int) => begun,
32
22
  growStage: (~handle: int, ~column: int, ~needed: int, ~stale: ArrayBuffer.t) => ArrayBuffer.t,
33
23
  commitStage: (~handle: int, ~buffers: array<ArrayBuffer.t>) => unit,
34
24
  abortStage: (~handle: int, ~buffers: array<ArrayBuffer.t>) => unit,
@@ -79,8 +69,8 @@ type t = {
79
69
  builders: array<builder>,
80
70
  }
81
71
 
82
- let begin = (arena, ~table, ~rows, ~columns: array<column>) => {
83
- let {handle, buffers} = arena.beginStage(~table, ~rows)
72
+ let begin = (arena, ~rows, ~columns: array<column>) => {
73
+ let {handle, buffers} = arena.beginStage(~rows)
84
74
  let slot = ref(0)
85
75
  let take = () => {
86
76
  let buffer = buffers->Array.getUnsafe(slot.contents)
@@ -275,7 +265,7 @@ let toText = (value: unknown, ~replacer=?) =>
275
265
  }
276
266
  )
277
267
 
278
- %%private(let isAbsent = (value: unknown) => value === %raw(`undefined`) || value === %raw(`null`))
268
+ let isAbsent = (value: unknown) => value === %raw(`undefined`) || value === %raw(`null`)
279
269
 
280
270
  // Writes one value of a row the handler set. `undefined`/`null` marks the row's
281
271
  // null bit, which a column that accepts NULL stores as such — and which one that
@@ -317,3 +307,31 @@ let commit = stage => {
317
307
  }
318
308
 
319
309
  let abort = stage => stage.arena.abortStage(~handle=stage.handle, ~buffers=stage.buffers)
310
+
311
+ // How a staged value has to arrive, as the addon declares it for every field:
312
+ // `storage::schema::Encoding`.
313
+ type encoding =
314
+ | Number
315
+ | Bool
316
+ | Date
317
+ | Text
318
+ | Digits
319
+ | Decimal
320
+ | Document
321
+ | Bytes
322
+ | List
323
+
324
+ type stagedField = {
325
+ name: string,
326
+ encoding: encoding,
327
+ // What a list's elements are encoded as; the field's own for a scalar.
328
+ element: encoding,
329
+ isNullable: bool,
330
+ }
331
+
332
+ let kindOf = (encoding: encoding) =>
333
+ switch encoding {
334
+ | Number | Bool | Date => F64
335
+ | Text | Digits | Decimal | Document | List => Text
336
+ | Bytes => Bytes
337
+ }
@@ -4,27 +4,10 @@ import * as Utils from "./Utils.res.mjs";
4
4
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
5
5
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
6
6
 
7
- function kindOfOrdinal(ordinal) {
8
- switch (ordinal) {
9
- case 0 :
10
- return 0;
11
- case 1 :
12
- return 1;
13
- case 2 :
14
- return 2;
15
- case 3 :
16
- return 3;
17
- case 4 :
18
- return 4;
19
- default:
20
- return Stdlib_JsError.throwWithMessage(`Unknown staged column kind ` + ordinal.toString());
21
- }
22
- }
23
-
24
7
  let encoder = new TextEncoder();
25
8
 
26
- function begin(arena, table, rows, columns) {
27
- let match = arena.beginStage(table, rows);
9
+ function begin(arena, rows, columns) {
10
+ let match = arena.beginStage(rows);
28
11
  let buffers = match.buffers;
29
12
  let slot = {
30
13
  contents: 0
@@ -249,15 +232,29 @@ function abort(stage) {
249
232
  stage.arena.abortStage(stage.handle, stage.buffers);
250
233
  }
251
234
 
235
+ function kindOf(encoding) {
236
+ switch (encoding) {
237
+ case "Number" :
238
+ case "Bool" :
239
+ case "Date" :
240
+ return 0;
241
+ case "Bytes" :
242
+ return 4;
243
+ default:
244
+ return 3;
245
+ }
246
+ }
247
+
252
248
  export {
253
- kindOfOrdinal,
254
249
  begin,
255
250
  finiteOrThrow,
256
251
  toText,
252
+ isAbsent,
257
253
  writeValue,
258
254
  writeDeletedValue,
259
255
  columnCount,
260
256
  commit,
261
257
  abort,
258
+ kindOf,
262
259
  }
263
260
  /* encoder Not a pure module */