envio 3.14.0-subgraph → 3.14.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.
Files changed (63) hide show
  1. package/evm.schema.json +1 -1
  2. package/package.json +6 -6
  3. package/src/Config.res +0 -9
  4. package/src/Config.res.mjs +2 -6
  5. package/src/Core.res +0 -21
  6. package/src/Core.res.mjs +0 -17
  7. package/src/EventProcessing.res +6 -6
  8. package/src/EventProcessing.res.mjs +6 -8
  9. package/src/HandlerLoader.res +22 -48
  10. package/src/HandlerLoader.res.mjs +15 -41
  11. package/src/HandlerTypeCheck.res +207 -0
  12. package/src/HandlerTypeCheck.res.mjs +262 -0
  13. package/src/LoadLayer.res +7 -39
  14. package/src/LoadLayer.res.mjs +38 -65
  15. package/src/LoadLayer.resi +0 -28
  16. package/src/PgStorage.res +5 -24
  17. package/src/PgStorage.res.mjs +1 -18
  18. package/src/UserContext.res +62 -377
  19. package/src/UserContext.res.mjs +39 -297
  20. package/src/bindings/NodeJs.res +31 -0
  21. package/src/bindings/NodeJs.res.mjs +3 -0
  22. package/src/db/Table.res +0 -10
  23. package/src/db/Table.res.mjs +11 -22
  24. package/src/sources/EvmRpcClient.res +2 -0
  25. package/src/sources/RpcSource.res +17 -4
  26. package/src/sources/RpcSource.res.mjs +23 -5
  27. package/src/sources/SourceManager.res +63 -40
  28. package/src/sources/SourceManager.res.mjs +32 -20
  29. package/src/HandlerTypeCheck.mjs +0 -14
  30. package/src/HandlerTypeCheckWorker.mjs +0 -68
  31. package/src/SyncWrites.res +0 -86
  32. package/src/SyncWrites.res.mjs +0 -85
  33. package/src/subgraph/abi-types.ts +0 -63
  34. package/src/subgraph/assemblyscript.ts +0 -85
  35. package/src/subgraph/blocks.ts +0 -183
  36. package/src/subgraph/calls.ts +0 -149
  37. package/src/subgraph/conformance.ts +0 -83
  38. package/src/subgraph/errors.ts +0 -96
  39. package/src/subgraph/graph-cli-worker.mjs +0 -26
  40. package/src/subgraph/graph-cli.ts +0 -190
  41. package/src/subgraph/graph-ts-enums.ts +0 -28
  42. package/src/subgraph/graph-ts-types/VERSION +0 -2
  43. package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
  44. package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
  45. package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
  46. package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
  47. package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
  48. package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
  49. package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
  50. package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
  51. package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
  52. package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
  53. package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
  54. package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
  55. package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
  56. package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
  57. package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
  58. package/src/subgraph/graph-ts-types/index.d.ts +0 -102
  59. package/src/subgraph/graph-ts.ts +0 -2285
  60. package/src/subgraph/hosts.ts +0 -158
  61. package/src/subgraph/rpc.ts +0 -65
  62. package/src/subgraph/runtime.ts +0 -595
  63. package/src/subgraph/scope.ts +0 -68
@@ -1,83 +1,19 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Utils from "./Utils.res.mjs";
4
- import * as ChainId from "./ChainId.res.mjs";
5
4
  import * as Logging from "./Logging.res.mjs";
6
5
  import * as Internal from "./Internal.res.mjs";
7
6
  import * as Ecosystem from "./Ecosystem.res.mjs";
8
7
  import * as LoadLayer from "./LoadLayer.res.mjs";
9
- import * as SyncWrites from "./SyncWrites.res.mjs";
10
8
  import * as EntityFilter from "./db/EntityFilter.res.mjs";
9
+ import * as IndexerState from "./IndexerState.res.mjs";
11
10
  import * as ErrorHandling from "./ErrorHandling.res.mjs";
12
11
  import * as InMemoryStore from "./InMemoryStore.res.mjs";
13
12
  import * as InMemoryTable from "./InMemoryTable.res.mjs";
14
13
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
15
14
  import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
16
- import * as Stdlib_Promise from "@rescript/runtime/lib/es6/Stdlib_Promise.js";
17
15
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
18
16
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
19
- import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
20
-
21
- let Suspend = /* @__PURE__ */Primitive_exceptions.create("UserContext.Suspend");
22
-
23
- function isSuspend(exn) {
24
- return exn.RE_EXN_ID === Suspend;
25
- }
26
-
27
- function makeSyncState() {
28
- return {
29
- status: "Active",
30
- pending: undefined,
31
- memo: undefined,
32
- writes: undefined
33
- };
34
- }
35
-
36
- function getPending(sync) {
37
- let pending = sync.pending;
38
- if (pending !== undefined) {
39
- return pending;
40
- }
41
- let pending$1 = [];
42
- sync.pending = pending$1;
43
- return pending$1;
44
- }
45
-
46
- function getMemo(sync) {
47
- let memo = sync.memo;
48
- if (memo !== undefined) {
49
- return memo;
50
- }
51
- let memo$1 = {};
52
- sync.memo = memo$1;
53
- return memo$1;
54
- }
55
-
56
- function checkStatusOrThrow(params, access) {
57
- let exn = params.sync.status;
58
- if (typeof exn !== "object") {
59
- if (exn === "Active") {
60
- return;
61
- } else {
62
- return ErrorHandling.mkLogAndRaise(Ecosystem.getItemLogger(params.item, params.config.ecosystem), undefined, new Error(`Impossible to access ` + access + ` after the handler is resolved. Make sure you didn't miss an await in the handler.`));
63
- }
64
- }
65
- throw exn._0;
66
- }
67
-
68
- function scheduleAndSuspend(params, promise) {
69
- getPending(params.sync).push(promise);
70
- params.sync.status = {
71
- TAG: "Aborted",
72
- _0: {
73
- RE_EXN_ID: Suspend
74
- }
75
- };
76
- throw {
77
- RE_EXN_ID: Suspend,
78
- Error: new Error()
79
- };
80
- }
81
17
 
82
18
  let paramsByThis = new WeakMap();
83
19
 
@@ -111,71 +47,29 @@ var EffectContext = function(params, chainId, effectName, defaultShouldCache, ca
111
47
  EffectContext.prototype = effectContextPrototype;
112
48
  ;
113
49
 
114
- function prepareEffectCall(params, effect, input, caller) {
115
- let isCrossChain = effect => Stdlib_Option.getOr(effect.crossChain, params.config.defaultCrossChain);
116
- let scope = isCrossChain(effect) ? "crossChain" : Internal.getItemChainId(params.item);
117
- if (caller !== undefined && isCrossChain(caller) && !isCrossChain(effect)) {
118
- Stdlib_JsError.throwWithMessage(`The cross-chain effect "` + caller.name + `" cannot call the chain-scoped effect "` + effect.name + `", because a cross-chain effect isn't tied to a single chain. Make "` + effect.name + `" cross-chain (\`crossChain: true\`), or make "` + caller.name + `" chain-scoped (\`crossChain: false\`).`);
119
- }
120
- let tmp;
121
- tmp = scope === "crossChain" ? undefined : Primitive_option.some(scope);
122
- let effectContext = new EffectContext(params, tmp, effect.name, effect.defaultShouldCache, (nested, nestedInput) => callEffectAsync(params, nested, nestedInput, effect));
123
- let effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
124
- let effectArgs_chainId = Internal.getItemChainId(params.item);
125
- let effectArgs_checkpointId = params.checkpointId;
126
- let effectArgs = {
127
- input: input,
128
- context: effectContext,
129
- cacheKey: effectArgs_cacheKey,
130
- chainId: effectArgs_chainId,
131
- checkpointId: effectArgs_checkpointId
132
- };
133
- return [
134
- scope,
135
- effectArgs
136
- ];
137
- }
138
-
139
- function callEffectAsync(params, effect, input, caller) {
140
- let match = prepareEffectCall(params, effect, input, caller);
141
- return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, match[1], match[0], params.indexerState, params.isPreload, params.item, params.config.ecosystem);
142
- }
143
-
144
50
  function initEffect(params) {
145
- return (effect, input) => {
146
- checkStatusOrThrow(params, "context.effect");
147
- return callEffectAsync(params, effect, input, undefined);
148
- };
149
- }
150
-
151
- function effectMemoKey(effect, scope, cacheKey) {
152
- if (scope === "crossChain") {
153
- return effect.name + `.` + cacheKey;
154
- } else {
155
- return effect.name + `.` + ChainId.toString(scope) + `.` + cacheKey;
156
- }
157
- }
158
-
159
- function initEffectSync(params) {
160
- return (effect, input) => {
161
- checkStatusOrThrow(params, "context.effectSync");
162
- let match = prepareEffectCall(params, effect, input, undefined);
163
- let effectArgs = match[1];
164
- let scope = match[0];
165
- let memo = getMemo(params.sync);
166
- let memoKey = effectMemoKey(effect, scope, effectArgs.cacheKey);
167
- let output = memo[memoKey];
168
- if (output !== undefined) {
169
- return Primitive_option.valFromOption(output);
170
- }
171
- let inMemTable = InMemoryStore.getEffectInMemTable(params.indexerState, effect, scope);
172
- if (!InMemoryStore.hasEffectOutput(inMemTable, effectArgs.cacheKey)) {
173
- return scheduleAndSuspend(params, LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, scope, params.indexerState, params.isPreload, params.item, params.config.ecosystem));
51
+ let handlerChainId = Internal.getItemChainId(params.item);
52
+ let isCrossChain = effect => Stdlib_Option.getOr(effect.crossChain, params.config.defaultCrossChain);
53
+ let makeCaller = caller => ((effect, input) => {
54
+ let scope = isCrossChain(effect) ? "crossChain" : handlerChainId;
55
+ if (caller !== undefined && isCrossChain(caller) && !isCrossChain(effect)) {
56
+ Stdlib_JsError.throwWithMessage(`The cross-chain effect "` + caller.name + `" cannot call the chain-scoped effect "` + effect.name + `", because a cross-chain effect isn't tied to a single chain. Make "` + effect.name + `" cross-chain (\`crossChain: true\`), or make "` + caller.name + `" chain-scoped (\`crossChain: false\`).`);
174
57
  }
175
- let output$1 = InMemoryStore.getEffectOutputUnsafe(inMemTable, effectArgs.cacheKey);
176
- memo[memoKey] = output$1;
177
- return output$1;
178
- };
58
+ let tmp;
59
+ tmp = scope === "crossChain" ? undefined : Primitive_option.some(scope);
60
+ let effectContext = new EffectContext(params, tmp, effect.name, effect.defaultShouldCache, makeCaller(effect));
61
+ let effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
62
+ let effectArgs_checkpointId = params.checkpointId;
63
+ let effectArgs = {
64
+ input: input,
65
+ context: effectContext,
66
+ cacheKey: effectArgs_cacheKey,
67
+ chainId: handlerChainId,
68
+ checkpointId: effectArgs_checkpointId
69
+ };
70
+ return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, scope, params.indexerState, params.isPreload, params.item, params.config.ecosystem);
71
+ });
72
+ return makeCaller(undefined);
179
73
  }
180
74
 
181
75
  function entityScope(params) {
@@ -198,88 +92,26 @@ function throwClickHouseReadOnly(entityConfig, op) {
198
92
  return Stdlib_JsError.throwWithMessage(`context.` + entityConfig.name + `.` + op + `() is unavailable: ClickHouse storage is currently write-only. Follow Envio releases to be notified when ClickHouse supports both reads and writes from handlers.`);
199
93
  }
200
94
 
201
- function writeChange(params, change) {
202
- let scope = entityScope(params);
203
- let writes = params.sync.writes;
204
- if (writes !== undefined) {
205
- return SyncWrites.record(writes, params.entityConfig, scope, change);
206
- } else {
207
- return SyncWrites.write(params.indexerState, params.entityConfig, scope, change);
208
- }
209
- }
210
-
211
- function getRoundWrite(params, entityId) {
212
- let writes = params.sync.writes;
213
- if (writes !== undefined) {
214
- return SyncWrites.getById(writes, params.entityConfig, entityId);
215
- }
216
- }
217
-
218
- function getSyncHandler(params, entityId) {
219
- let entity = getRoundWrite(params, entityId);
220
- if (entity !== undefined) {
221
- return Primitive_option.valFromOption(entity);
222
- }
223
- let entity$1 = LoadLayer.getByIdInMemory(params.entityConfig, entityScope(params), params.indexerState, entityId);
224
- if (entity$1 !== undefined) {
225
- return Primitive_option.valFromOption(entity$1);
226
- } else {
227
- return scheduleAndSuspend(params, LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, entityScope(params), params.indexerState, params.isPreload, params.item, params.config.ecosystem, entityId));
228
- }
229
- }
230
-
231
- function getWhereSyncHandler(params, filter) {
232
- let entityConfig = params.entityConfig;
233
- let filter$1 = EntityFilter.parseOrThrow(filter, entityConfig.name, entityConfig.table);
234
- let entities = LoadLayer.getByFilterInMemory(entityConfig, entityScope(params), params.indexerState, filter$1);
235
- if (entities === undefined) {
236
- return scheduleAndSuspend(params, LoadLayer.loadByParsedFilter(params.loadManager, params.persistence, entityConfig, entityScope(params), params.indexerState, params.isPreload, params.item, params.config.ecosystem, filter$1));
237
- }
238
- let writes = params.sync.writes;
239
- if (writes !== undefined) {
240
- return SyncWrites.overlayFilter(writes, entities, entityConfig, filter$1);
241
- } else {
242
- return entities;
243
- }
244
- }
245
-
246
- function getInBlockSyncHandler(params, entityId) {
247
- let entity = getRoundWrite(params, entityId);
248
- if (entity !== undefined) {
249
- return Primitive_option.valFromOption(entity);
250
- }
251
- let inMemTable = InMemoryStore.getInMemTable(params.indexerState, params.entityConfig, entityScope(params));
252
- let change = inMemTable.latestEntityChangeById[entityId];
253
- if (change !== undefined && change.checkpointId === params.checkpointId) {
254
- return InMemoryTable.Entity.mapChangeToEntity(change);
255
- }
256
- }
257
-
258
95
  let entityTraps_get = (params, prop) => {
259
- checkStatusOrThrow(params, `context.` + params.entityConfig.name + `.` + prop);
260
96
  let isClickHouseOnly = !params.entityConfig.storage.postgres;
261
- let set = params.isPreload ? noopSet : entity => {
262
- checkStatusOrThrow(params, `context.` + params.entityConfig.name + `.set`);
263
- writeChange(params, {
264
- type: "SET",
265
- entityId: entity.id,
266
- entity: entity,
267
- checkpointId: params.checkpointId
268
- });
269
- };
97
+ let scope = entityScope(params);
98
+ let committedCheckpointId = IndexerState.committedCheckpointIdFor(params.indexerState, scope);
99
+ let set = params.isPreload ? noopSet : entity => InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.indexerState, params.entityConfig, scope), committedCheckpointId, {
100
+ type: "SET",
101
+ entityId: entity.id,
102
+ entity: entity,
103
+ checkpointId: params.checkpointId
104
+ });
270
105
  switch (prop) {
271
106
  case "deleteUnsafe" :
272
107
  if (params.isPreload) {
273
108
  return noopDeleteUnsafe;
274
109
  } else {
275
- return entityId => {
276
- checkStatusOrThrow(params, `context.` + params.entityConfig.name + `.deleteUnsafe`);
277
- writeChange(params, {
278
- type: "DELETE",
279
- entityId: entityId,
280
- checkpointId: params.checkpointId
281
- });
282
- };
110
+ return entityId => InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.indexerState, params.entityConfig, scope), committedCheckpointId, {
111
+ type: "DELETE",
112
+ entityId: entityId,
113
+ checkpointId: params.checkpointId
114
+ });
283
115
  }
284
116
  case "get" :
285
117
  if (isClickHouseOnly) {
@@ -287,8 +119,6 @@ let entityTraps_get = (params, prop) => {
287
119
  } else {
288
120
  return entityId => LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, entityScope(params), params.indexerState, params.isPreload, params.item, params.config.ecosystem, entityId);
289
121
  }
290
- case "getInBlockSync" :
291
- return entityId => getInBlockSyncHandler(params, entityId);
292
122
  case "getOrCreate" :
293
123
  if (isClickHouseOnly) {
294
124
  return _entity => throwClickHouseReadOnly(params.entityConfig, "getOrCreate");
@@ -314,16 +144,12 @@ let entityTraps_get = (params, prop) => {
314
144
  }
315
145
  });
316
146
  }
317
- case "getSync" :
318
- return entityId => getSyncHandler(params, entityId);
319
147
  case "getWhere" :
320
148
  if (isClickHouseOnly) {
321
149
  return _filter => throwClickHouseReadOnly(params.entityConfig, "getWhere");
322
150
  } else {
323
151
  return filter => getWhereHandler(params, filter);
324
152
  }
325
- case "getWhereSync" :
326
- return filter => getWhereSyncHandler(params, filter);
327
153
  case "set" :
328
154
  return set;
329
155
  default:
@@ -335,78 +161,16 @@ let entityTraps = {
335
161
  get: entityTraps_get
336
162
  };
337
163
 
338
- async function runSyncRound(params, fn, round) {
339
- if (round > 10000) {
340
- Stdlib_JsError.throwWithMessage(`The handler suspended on a synchronous read too many times: gave up after ` + (10000).toString() + ` rounds. This usually means the code isn't deterministic across reruns.`);
341
- }
342
- params.sync.status = "Active";
343
- params.sync.pending = undefined;
344
- let writes = SyncWrites.make();
345
- params.sync.writes = writes;
346
- let suspended;
347
- let exit = 0;
348
- let val;
349
- try {
350
- val = fn();
351
- exit = 1;
352
- } catch (raw_exn) {
353
- let exn = Primitive_exceptions.internalToException(raw_exn);
354
- params.sync.writes = undefined;
355
- if (exn.RE_EXN_ID === Suspend) {
356
- suspended = true;
357
- } else {
358
- let pending = params.sync.pending;
359
- if (pending !== undefined) {
360
- params.sync.pending = undefined;
361
- pending.forEach(promise => {
362
- Utils.$$Promise.silentCatch(promise);
363
- });
364
- }
365
- throw exn;
366
- }
367
- }
368
- if (exit === 1) {
369
- params.sync.writes = undefined;
370
- let match = params.sync.status;
371
- if (typeof match !== "object") {
372
- if (match === "Active") {
373
- SyncWrites.commit(writes, params.indexerState);
374
- suspended = false;
375
- } else {
376
- SyncWrites.commit(writes, params.indexerState);
377
- suspended = false;
378
- }
379
- } else {
380
- suspended = true;
381
- }
382
- }
383
- if (!suspended) {
384
- return;
385
- }
386
- let pending$1 = Stdlib_Option.getOr(params.sync.pending, []);
387
- params.sync.pending = undefined;
388
- let errors = [];
389
- await Promise.all(pending$1.map(promise => Stdlib_Promise.$$catch(promise, exn => {
390
- errors.push(exn);
391
- return Promise.resolve();
392
- })));
393
- let exn$1 = errors[0];
394
- if (exn$1 !== undefined) {
395
- throw exn$1;
396
- }
397
- return await runSyncRound(params, fn, round + 1 | 0);
398
- }
399
-
400
164
  let handlerTraps_get = (params, prop) => {
401
- checkStatusOrThrow(params, `context.` + prop);
165
+ if (params.isResolved) {
166
+ ErrorHandling.mkLogAndRaise(Ecosystem.getItemLogger(params.item, params.config.ecosystem), undefined, new Error(`Impossible to access context.` + prop + ` after the handler is resolved. Make sure you didn't miss an await in the handler.`));
167
+ }
402
168
  switch (prop) {
403
169
  case "chain" :
404
170
  let chainId = Internal.getItemChainId(params.item);
405
171
  return params.chains[chainId];
406
172
  case "effect" :
407
173
  return initEffect(params);
408
- case "effectSync" :
409
- return initEffectSync(params);
410
174
  case "isPreload" :
411
175
  return params.isPreload;
412
176
  case "log" :
@@ -415,8 +179,6 @@ let handlerTraps_get = (params, prop) => {
415
179
  } else {
416
180
  return Ecosystem.getItemUserLogger(params.item, params.config.ecosystem);
417
181
  }
418
- case "runSync" :
419
- return fn => runSyncRound(params, fn, 1);
420
182
  default:
421
183
  let entityConfig = params.config.userEntitiesByName[prop];
422
184
  if (entityConfig !== undefined) {
@@ -429,7 +191,7 @@ let handlerTraps_get = (params, prop) => {
429
191
  isPreload: params.isPreload,
430
192
  chains: params.chains,
431
193
  config: params.config,
432
- sync: params.sync,
194
+ isResolved: params.isResolved,
433
195
  entityConfig: entityConfig
434
196
  }, entityTraps);
435
197
  } else {
@@ -446,36 +208,16 @@ function getHandlerContext(params) {
446
208
  return new Proxy(params, handlerTraps);
447
209
  }
448
210
 
449
- let maxSyncRounds = 10000;
450
-
451
211
  export {
452
- Suspend,
453
- isSuspend,
454
- makeSyncState,
455
- getPending,
456
- getMemo,
457
- checkStatusOrThrow,
458
- scheduleAndSuspend,
459
212
  paramsByThis,
460
213
  effectContextPrototype,
461
- prepareEffectCall,
462
- callEffectAsync,
463
214
  initEffect,
464
- effectMemoKey,
465
- initEffectSync,
466
215
  entityScope,
467
216
  getWhereHandler,
468
217
  noopSet,
469
218
  noopDeleteUnsafe,
470
219
  throwClickHouseReadOnly,
471
- writeChange,
472
- getRoundWrite,
473
- getSyncHandler,
474
- getWhereSyncHandler,
475
- getInBlockSyncHandler,
476
220
  entityTraps,
477
- maxSyncRounds,
478
- runSyncRound,
479
221
  handlerTraps,
480
222
  getHandlerContext,
481
223
  }
@@ -39,6 +39,15 @@ module Util = {
39
39
  @module("util") external inspect: ('a, inspectOptions) => string = "inspect"
40
40
 
41
41
  let inspectObj = a => inspect(a, {showHidden: false, depth: Null, colors: true})
42
+
43
+ @module("util") external stripVTControlCharacters: string => string = "stripVTControlCharacters"
44
+ }
45
+
46
+ module Module = {
47
+ type require
48
+
49
+ @module("module") external createRequire: string => require = "createRequire"
50
+ @send external resolve: (require, string) => string = "resolve"
42
51
  }
43
52
 
44
53
  module Process = {
@@ -165,6 +174,23 @@ module ChildProcess = {
165
174
  @module("child_process")
166
175
  external execWithOptions: (string, execOptions, callback) => unit = "exec"
167
176
 
177
+ type execFileOptions = {
178
+ cwd?: string,
179
+ timeout?: int,
180
+ maxBuffer?: float,
181
+ }
182
+
183
+ // `killed` is set when the timeout stopped the child.
184
+ type execFileError = {killed: bool}
185
+
186
+ @module("child_process")
187
+ external execFile: (
188
+ string,
189
+ array<string>,
190
+ execFileOptions,
191
+ (Null.t<execFileError>, string, string) => unit,
192
+ ) => unit = "execFile"
193
+
168
194
  // One of a child's stdio slots, present only for a slot the parent asked to
169
195
  // pipe rather than inherit.
170
196
  module Stream = {
@@ -225,6 +251,8 @@ module Path = {
225
251
 
226
252
  @module("path") external join: (t, string) => t = "join"
227
253
  @module("path") external dirname: string => t = "dirname"
254
+ @module("path") external relative: (string, string) => string = "relative"
255
+ @module("path") external isAbsolute: string => bool = "isAbsolute"
228
256
 
229
257
  external toString: t => string = "%identity"
230
258
 
@@ -275,6 +303,9 @@ module Fs = {
275
303
  mode?: int,
276
304
  }
277
305
 
306
+ @module("fs") external existsSync: string => bool = "existsSync"
307
+ @module("fs") external readFileSync: (string, @as("utf8") _) => string = "readFileSync"
308
+
278
309
  module Promises = {
279
310
  @module("fs") @scope("promises")
280
311
  external writeFile: (
@@ -16,6 +16,8 @@ let Util$1 = {
16
16
  inspectObj: inspectObj
17
17
  };
18
18
 
19
+ let Module = {};
20
+
19
21
  let Process = {};
20
22
 
21
23
  let empty = globalThis.Buffer.alloc(0);
@@ -59,6 +61,7 @@ let Fs = {
59
61
 
60
62
  export {
61
63
  Util$1 as Util,
64
+ Module,
62
65
  Process,
63
66
  Buffer,
64
67
  V8,
package/src/db/Table.res CHANGED
@@ -454,7 +454,6 @@ type sqlParams<'entity> = {
454
454
  quotedNonPrimaryFieldNames: array<string>,
455
455
  arrayFieldTypes: array<string>,
456
456
  byteaColumnIndexes: array<int>,
457
- booleanArrayColumnIndexes: array<int>,
458
457
  hasArrayField: bool,
459
458
  }
460
459
 
@@ -465,10 +464,6 @@ let toSqlParams = (table: table, ~schema, ~pgSchema, ~chainIdMode: ChainId.mode=
465
464
  // Positions of the bytea columns among the unnest parameters, which the
466
465
  // caller binds as array literals (see `Utils.Bytes.toPgArrayLiteral`).
467
466
  let byteaColumnIndexes = []
468
- // postgres binds a JS array of booleans as a single `boolean`, whatever the
469
- // column (https://github.com/porsager/postgres/issues/471), so the VALUES
470
- // insert binds these columns as integer arrays and casts them back.
471
- let booleanArrayColumnIndexes = []
472
467
  let hasArrayField = ref(false)
473
468
 
474
469
  let dbSchema: S.t<dict<unknown>> = S.schema(s =>
@@ -504,10 +499,6 @@ let toSqlParams = (table: table, ~schema, ~pgSchema, ~chainIdMode: ChainId.mode=
504
499
  | None => throw(NonExistingTableField(location))
505
500
  }
506
501
  switch field {
507
- | Field({isArray: true, fieldType: Boolean}) => {
508
- hasArrayField := true
509
- booleanArrayColumnIndexes->Array.push(arrayFieldTypes->Array.length)->ignore
510
- }
511
502
  | Field({isArray: true}) => hasArrayField := true
512
503
  | Field({fieldType: Bytea}) =>
513
504
  byteaColumnIndexes->Array.push(arrayFieldTypes->Array.length)->ignore
@@ -563,7 +554,6 @@ let toSqlParams = (table: table, ~schema, ~pgSchema, ~chainIdMode: ChainId.mode=
563
554
  quotedNonPrimaryFieldNames,
564
555
  arrayFieldTypes,
565
556
  byteaColumnIndexes,
566
- booleanArrayColumnIndexes,
567
557
  hasArrayField: hasArrayField.contents,
568
558
  }
569
559
  }
@@ -384,7 +384,6 @@ function toSqlParams(table, schema, pgSchema, chainIdModeOpt) {
384
384
  let quotedNonPrimaryFieldNames = [];
385
385
  let arrayFieldTypes = [];
386
386
  let byteaColumnIndexes = [];
387
- let booleanArrayColumnIndexes = [];
388
387
  let hasArrayField = {
389
388
  contents: false
390
389
  };
@@ -442,20 +441,11 @@ function toSqlParams(table, schema, pgSchema, chainIdModeOpt) {
442
441
  }
443
442
  if (field$1.TAG === "Field") {
444
443
  let match = field$1._0;
445
- let match$1 = match.fieldType;
446
- let exit = 0;
447
- if (typeof match$1 !== "object" && match$1 === "Boolean") {
448
- if (match.isArray) {
449
- hasArrayField.contents = true;
450
- booleanArrayColumnIndexes.push(arrayFieldTypes.length);
451
- }
444
+ if (match.isArray) {
445
+ hasArrayField.contents = true;
452
446
  } else {
453
- exit = 1;
454
- }
455
- if (exit === 1) {
456
- if (match.isArray) {
457
- hasArrayField.contents = true;
458
- } else if (typeof match$1 !== "object" && match$1 === "Bytea") {
447
+ let tmp = match.fieldType;
448
+ if (typeof tmp !== "object" && tmp === "Bytea") {
459
449
  byteaColumnIndexes.push(arrayFieldTypes.length);
460
450
  }
461
451
  }
@@ -469,20 +459,20 @@ function toSqlParams(table, schema, pgSchema, chainIdModeOpt) {
469
459
  quotedNonPrimaryFieldNames.push(quotedDbName);
470
460
  }
471
461
  }
472
- let tmp;
462
+ let tmp$1;
473
463
  if (field$1.TAG === "Field") {
474
464
  let f = field$1._0;
475
465
  let pgFieldType = getPgFieldType(f.fieldType, pgSchema, true, false, f.isNullable, chainIdMode);
476
- let match$2 = f.fieldType;
477
- tmp = typeof match$2 !== "object" ? (
478
- match$2 === "Boolean" ? "INTEGER" + `[]::` + pgFieldType : pgFieldType
466
+ let match$1 = f.fieldType;
467
+ tmp$1 = typeof match$1 !== "object" ? (
468
+ match$1 === "Boolean" ? "INTEGER" + `[]::` + pgFieldType : pgFieldType
479
469
  ) : (
480
- match$2.type === "Enum" ? "TEXT" + `[]::` + pgFieldType : pgFieldType
470
+ match$1.type === "Enum" ? "TEXT" + `[]::` + pgFieldType : pgFieldType
481
471
  );
482
472
  } else {
483
- tmp = "TEXT[]";
473
+ tmp$1 = "TEXT[]";
484
474
  }
485
- arrayFieldTypes.push(tmp);
475
+ arrayFieldTypes.push(tmp$1);
486
476
  dict[location] = s.m(coerceSchema(param.schema));
487
477
  });
488
478
  return dict;
@@ -493,7 +483,6 @@ function toSqlParams(table, schema, pgSchema, chainIdModeOpt) {
493
483
  quotedNonPrimaryFieldNames: quotedNonPrimaryFieldNames,
494
484
  arrayFieldTypes: arrayFieldTypes,
495
485
  byteaColumnIndexes: byteaColumnIndexes,
496
- booleanArrayColumnIndexes: booleanArrayColumnIndexes,
497
486
  hasArrayField: hasArrayField.contents
498
487
  };
499
488
  }
@@ -28,6 +28,7 @@ type pageOutcome =
28
28
  | @as("SuggestedToBlock") SuggestedToBlock
29
29
  | @as("Backoff") Backoff
30
30
  | @as("FieldSelection") FieldSelection
31
+ | @as("BehindHead") BehindHead
31
32
 
32
33
  type nextPageResult = {
33
34
  kind: pageOutcome,
@@ -45,6 +46,7 @@ type nextPageResult = {
45
46
  // alongside it is empty.
46
47
  type blockHashResult = {
47
48
  message: option<string>,
49
+ behindHeadBlock: option<int>,
48
50
  requestStats: array<Source.requestStat>,
49
51
  }
50
52
 
@@ -99,7 +99,8 @@ let make = (
99
99
 
100
100
  // The cause travels as a real error so it reaches the logs the way every
101
101
  // other source's does. Absent where the message is the whole story.
102
- let exn = result.providerMessage->Option.map(message => JsError.make(message)->JsExn.anyToExnInternal)
102
+ let exn =
103
+ result.providerMessage->Option.map(message => JsError.make(message)->JsExn.anyToExnInternal)
103
104
 
104
105
  let failedGettingItems = (decision): exn => Source.GetItemsError(
105
106
  FailedGettingItems({
@@ -134,6 +135,16 @@ let make = (
134
135
  }),
135
136
  ),
136
137
  )
138
+ | BehindHead =>
139
+ throw(
140
+ Source.SourceBehindHead({
141
+ blockNumber: switch result.blockNumber {
142
+ | Some(blockNumber) => blockNumber
143
+ | None => missing("blockNumber")
144
+ },
145
+ requestStats: result.requestStats,
146
+ }),
147
+ )
137
148
  | SuggestedToBlock =>
138
149
  throw(
139
150
  failedGettingItems(
@@ -185,9 +196,11 @@ let make = (
185
196
  let getBlockHashes = async (~blockNumbers, ~logger as _) => {
186
197
  let (result, pageBlockStore) = await rpcClient.getBlockHashes(blockNumbers)
187
198
  {
188
- Source.result: switch result.message {
189
- | None => Ok(pageBlockStore)
190
- | Some(message) => Error(JsError.make(message)->JsExn.anyToExnInternal)
199
+ Source.result: switch (result.message, result.behindHeadBlock) {
200
+ | (None, _) => Ok(pageBlockStore)
201
+ | (Some(_), Some(blockNumber)) =>
202
+ Error(Source.SourceBehindHead({blockNumber, requestStats: result.requestStats}))
203
+ | (Some(message), None) => Error(JsError.make(message)->JsExn.anyToExnInternal)
191
204
  },
192
205
  requestStats: result.requestStats,
193
206
  }