envio 3.5.0-alpha.1 → 3.5.0-alpha.3

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/index.d.ts +10 -6
  2. package/package.json +6 -6
  3. package/src/BatchProcessing.res +27 -0
  4. package/src/BatchProcessing.res.mjs +12 -0
  5. package/src/ChainFetching.res +5 -5
  6. package/src/ChainFetching.res.mjs +3 -4
  7. package/src/ChainState.res +48 -25
  8. package/src/ChainState.res.mjs +23 -29
  9. package/src/ChainState.resi +2 -6
  10. package/src/Change.res +3 -3
  11. package/src/Config.res +2 -6
  12. package/src/Config.res.mjs +2 -12
  13. package/src/Core.res +3 -0
  14. package/src/CrossChainState.res +33 -10
  15. package/src/CrossChainState.res.mjs +21 -6
  16. package/src/CrossChainState.resi +3 -0
  17. package/src/EntityId.res +15 -0
  18. package/src/EntityId.res.mjs +9 -0
  19. package/src/EventConfigBuilder.res +1 -58
  20. package/src/EventConfigBuilder.res.mjs +1 -33
  21. package/src/FetchState.res +510 -460
  22. package/src/FetchState.res.mjs +413 -428
  23. package/src/FinalizeBackfill.res +34 -0
  24. package/src/FinalizeBackfill.res.mjs +26 -0
  25. package/src/HandlerRegister.res +45 -0
  26. package/src/HandlerRegister.res.mjs +43 -0
  27. package/src/InMemoryStore.res +11 -4
  28. package/src/InMemoryTable.res +26 -24
  29. package/src/InMemoryTable.res.mjs +19 -18
  30. package/src/IndexerState.res +71 -2
  31. package/src/IndexerState.res.mjs +67 -3
  32. package/src/IndexerState.resi +5 -0
  33. package/src/Internal.res +17 -8
  34. package/src/LoadLayer.res +9 -1
  35. package/src/LoadLayer.res.mjs +1 -0
  36. package/src/LogSelection.res +2 -1
  37. package/src/Metrics.res +37 -6
  38. package/src/Metrics.res.mjs +5 -1
  39. package/src/Persistence.res +12 -1
  40. package/src/PgStorage.res +411 -57
  41. package/src/PgStorage.res.mjs +262 -41
  42. package/src/SimulateItems.res +2 -2
  43. package/src/TestIndexer.res +9 -5
  44. package/src/TestIndexer.res.mjs +5 -2
  45. package/src/UserContext.res +3 -3
  46. package/src/Writing.res +12 -2
  47. package/src/Writing.res.mjs +13 -2
  48. package/src/bindings/ClickHouse.res +5 -3
  49. package/src/bindings/ClickHouse.res.mjs +2 -5
  50. package/src/bindings/Vitest.res +22 -1
  51. package/src/bindings/Vitest.res.mjs +15 -0
  52. package/src/db/EntityFilter.res +0 -4
  53. package/src/db/EntityFilter.res.mjs +1 -8
  54. package/src/db/EntityHistory.res +16 -7
  55. package/src/db/EntityHistory.res.mjs +7 -6
  56. package/src/db/IndexRegistry.res +219 -0
  57. package/src/db/IndexRegistry.res.mjs +195 -0
  58. package/src/db/InternalTable.res +7 -0
  59. package/src/db/InternalTable.res.mjs +7 -0
  60. package/src/db/Table.res +53 -22
  61. package/src/db/Table.res.mjs +56 -18
  62. package/src/sources/AddressSet.res +48 -0
  63. package/src/sources/AddressSet.res.mjs +11 -0
  64. package/src/sources/AddressStore.res +152 -0
  65. package/src/sources/AddressStore.res.mjs +97 -0
  66. package/src/sources/EvmChain.res +3 -0
  67. package/src/sources/EvmChain.res.mjs +4 -2
  68. package/src/sources/EvmHyperSyncSource.res +6 -3
  69. package/src/sources/EvmHyperSyncSource.res.mjs +3 -3
  70. package/src/sources/EvmRpcClient.res +6 -3
  71. package/src/sources/EvmRpcClient.res.mjs +3 -3
  72. package/src/sources/FuelHyperSync.res +4 -3
  73. package/src/sources/FuelHyperSync.res.mjs +3 -3
  74. package/src/sources/FuelHyperSync.resi +2 -1
  75. package/src/sources/FuelHyperSyncClient.res +12 -6
  76. package/src/sources/FuelHyperSyncClient.res.mjs +2 -2
  77. package/src/sources/FuelHyperSyncSource.res +7 -4
  78. package/src/sources/FuelHyperSyncSource.res.mjs +3 -3
  79. package/src/sources/HyperSync.res +6 -4
  80. package/src/sources/HyperSync.res.mjs +2 -3
  81. package/src/sources/HyperSync.resi +1 -1
  82. package/src/sources/HyperSyncClient.res +18 -9
  83. package/src/sources/HyperSyncClient.res.mjs +4 -4
  84. package/src/sources/RpcSource.res +15 -10
  85. package/src/sources/RpcSource.res.mjs +3 -4
  86. package/src/sources/SimulateSource.res +26 -11
  87. package/src/sources/SimulateSource.res.mjs +13 -5
  88. package/src/sources/Source.res +4 -2
  89. package/src/sources/SourceManager.res +2 -3
  90. package/src/sources/SourceManager.res.mjs +2 -3
  91. package/src/sources/Svm.res +1 -2
  92. package/src/sources/Svm.res.mjs +1 -1
  93. package/src/sources/SvmHyperSyncClient.res +12 -3
  94. package/src/sources/SvmHyperSyncClient.res.mjs +2 -2
  95. package/src/sources/SvmHyperSyncSource.res +10 -5
  96. package/src/sources/SvmHyperSyncSource.res.mjs +5 -4
  97. package/src/IndexingAddresses.res +0 -151
  98. package/src/IndexingAddresses.res.mjs +0 -130
  99. package/src/IndexingAddresses.resi +0 -39
@@ -0,0 +1,195 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Utils from "../Utils.res.mjs";
4
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
5
+ import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
6
+ import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
7
+
8
+ function fromIndexFields(indexFields) {
9
+ return indexFields.map(param => ({
10
+ name: param.fieldName,
11
+ direction: param.direction
12
+ }));
13
+ }
14
+
15
+ function makeKey(tableName, columns, method) {
16
+ return tableName + `|` + method + `|` + columns.map(param => {
17
+ let name = param.name;
18
+ if (param.direction === "Asc") {
19
+ return name;
20
+ } else {
21
+ return name + " DESC";
22
+ }
23
+ }).join(",");
24
+ }
25
+
26
+ let catalogRowsSchema = S$RescriptSchema.array(S$RescriptSchema.object(s => ({
27
+ tableName: s.f("tableName", S$RescriptSchema.string),
28
+ indexName: s.f("indexName", S$RescriptSchema.string),
29
+ method: s.f("method", S$RescriptSchema.string),
30
+ isValid: s.f("isValid", S$RescriptSchema.int),
31
+ isPlain: s.f("isPlain", S$RescriptSchema.int),
32
+ columns: s.f("columns", S$RescriptSchema.array(S$RescriptSchema.string)),
33
+ directions: s.f("directions", S$RescriptSchema.array(S$RescriptSchema.string))
34
+ })));
35
+
36
+ function makeCatalogQuery(pgSchema) {
37
+ return `SELECT
38
+ t.relname AS "tableName",
39
+ i.relname AS "indexName",
40
+ am.amname AS "method",
41
+ CASE WHEN ix.indisvalid AND ix.indisready THEN 1 ELSE 0 END AS "isValid",
42
+ CASE
43
+ WHEN ix.indisunique OR ix.indpred IS NOT NULL OR ix.indexprs IS NOT NULL THEN 0
44
+ ELSE 1
45
+ END AS "isPlain",
46
+ array_agg(
47
+ CASE WHEN k.attnum = 0
48
+ THEN pg_get_indexdef(ix.indexrelid, k.ord::int, true)
49
+ ELSE a.attname
50
+ END ORDER BY k.ord
51
+ ) AS "columns",
52
+ array_agg(
53
+ CASE WHEN (ix.indoption[k.ord - 1] & 1) = 1 THEN 'DESC' ELSE 'ASC' END ORDER BY k.ord
54
+ ) AS "directions"
55
+ FROM pg_index ix
56
+ JOIN pg_class i ON i.oid = ix.indexrelid
57
+ JOIN pg_class t ON t.oid = ix.indrelid
58
+ JOIN pg_namespace n ON n.oid = t.relnamespace
59
+ JOIN pg_am am ON am.oid = i.relam
60
+ JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS k(attnum, ord) ON k.ord <= ix.indnkeyatts
61
+ LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum
62
+ WHERE n.nspname = '` + pgSchema + `'
63
+ GROUP BY t.relname, i.relname, am.amname, ix.indisvalid, ix.indisready,
64
+ ix.indisunique, ix.indpred, ix.indexprs;`;
65
+ }
66
+
67
+ function make() {
68
+ return {
69
+ keys: new Set(),
70
+ invalidByName: {},
71
+ inflight: {},
72
+ tableQueue: {}
73
+ };
74
+ }
75
+
76
+ function has(registry, key) {
77
+ return registry.keys.has(key);
78
+ }
79
+
80
+ function add(registry, key) {
81
+ registry.keys.add(key);
82
+ }
83
+
84
+ function size(registry) {
85
+ return registry.keys.size;
86
+ }
87
+
88
+ function toArray(registry) {
89
+ return Array.from(registry.keys).toSorted(Primitive_string.compare);
90
+ }
91
+
92
+ function getInvalid(registry, name) {
93
+ return registry.invalidByName[name];
94
+ }
95
+
96
+ function clearInvalidName(registry, name) {
97
+ Utils.Dict.deleteInPlace(registry.invalidByName, name);
98
+ }
99
+
100
+ function reload(registry, rows) {
101
+ registry.keys.clear();
102
+ Object.keys(registry.invalidByName).forEach(name => Utils.Dict.deleteInPlace(registry.invalidByName, name));
103
+ let invalidIndexNames = [];
104
+ rows.forEach(row => {
105
+ let key = makeKey(row.tableName, row.columns.map((name, idx) => {
106
+ let match = row.directions[idx];
107
+ let tmp;
108
+ tmp = match === "DESC" ? "Desc" : "Asc";
109
+ return {
110
+ name: name,
111
+ direction: tmp
112
+ };
113
+ }), row.method);
114
+ if (row.isValid === 0) {
115
+ invalidIndexNames.push(row.indexName);
116
+ registry.invalidByName[row.indexName] = {
117
+ key: key,
118
+ isRepairable: row.isPlain === 1
119
+ };
120
+ return;
121
+ } else {
122
+ return add(registry, key);
123
+ }
124
+ });
125
+ return invalidIndexNames;
126
+ }
127
+
128
+ function ensure(registry, key, tableName, build) {
129
+ if (registry.keys.has(key)) {
130
+ return Promise.resolve();
131
+ }
132
+ let promise = registry.inflight[key];
133
+ if (promise !== undefined) {
134
+ return promise;
135
+ }
136
+ let tail = registry.tableQueue[tableName];
137
+ let tail$1 = tail !== undefined ? tail : Promise.resolve();
138
+ let promise$1 = tail$1.then(() => {
139
+ if (registry.keys.has(key)) {
140
+ return Promise.resolve();
141
+ } else {
142
+ return build();
143
+ }
144
+ }).then(() => add(registry, key));
145
+ registry.inflight[key] = promise$1;
146
+ registry.tableQueue[tableName] = Utils.$$Promise.silentCatch(promise$1);
147
+ return promise$1.finally(() => Utils.Dict.deleteInPlace(registry.inflight, key));
148
+ }
149
+
150
+ function truncateIndexName(description) {
151
+ if (description.length > 63) {
152
+ return description.slice(0, 63);
153
+ } else {
154
+ return description;
155
+ }
156
+ }
157
+
158
+ function validateIndexNamesOrThrow(descriptions) {
159
+ let byName = {};
160
+ descriptions.forEach(description => {
161
+ let name = truncateIndexName(description);
162
+ let existing = byName[name];
163
+ if (existing !== undefined && existing !== description) {
164
+ return Stdlib_JsError.throwWithMessage(`Index names "` + existing + `" and "` + description + `" both truncate to "` + name + `" at PostgreSQL's ` + (63).toString() + `-character identifier limit. Rename a field or an entity so the generated index names stay distinct.`);
165
+ } else {
166
+ byName[name] = description;
167
+ return;
168
+ }
169
+ });
170
+ }
171
+
172
+ let btree = "btree";
173
+
174
+ let pgMaxIdentifierLength = 63;
175
+
176
+ export {
177
+ btree,
178
+ fromIndexFields,
179
+ makeKey,
180
+ catalogRowsSchema,
181
+ makeCatalogQuery,
182
+ make,
183
+ has,
184
+ add,
185
+ size,
186
+ toArray,
187
+ getInvalid,
188
+ clearInvalidName,
189
+ reload,
190
+ ensure,
191
+ pgMaxIdentifierLength,
192
+ truncateIndexName,
193
+ validateIndexNamesOrThrow,
194
+ }
195
+ /* catalogRowsSchema Not a pure module */
@@ -164,6 +164,13 @@ SET ${setClauses->Array.joinUnsafe(",\n ")}
164
164
  WHERE "${(#id: field :> string)}" = $1;`
165
165
  }
166
166
 
167
+ // Written in the same transaction as the deferred schema indexes, so a chain
168
+ // is never reported ready without the indexes the schema promises.
169
+ let makeSetReadyAtQuery = (~pgSchema) =>
170
+ `UPDATE "${pgSchema}"."${table.tableName}"
171
+ SET "${(#ready_at: field :> string)}" = $1
172
+ WHERE "${(#id: field :> string)}" = ANY($2::int[]);`
173
+
167
174
  type rawInitialState = {
168
175
  id: int,
169
176
  startBlock: int,
@@ -101,6 +101,12 @@ SET ` + setClauses.join(",\n ") + `
101
101
  WHERE "` + "id" + `" = $1;`;
102
102
  }
103
103
 
104
+ function makeSetReadyAtQuery(pgSchema) {
105
+ return `UPDATE "` + pgSchema + `"."` + table.tableName + `"
106
+ SET "` + "ready_at" + `" = $1
107
+ WHERE "` + "id" + `" = ANY($2::int[]);`;
108
+ }
109
+
104
110
  function makeGetInitialStateQuery(pgSchema) {
105
111
  return `SELECT "` + "id" + `" as "id",
106
112
  "` + "start_block" + `" as "startBlock",
@@ -213,6 +219,7 @@ let Chains = {
213
219
  makeInitialValuesQuery: makeInitialValuesQuery,
214
220
  metaFields: metaFields,
215
221
  makeMetaFieldsUpdateQuery: makeMetaFieldsUpdateQuery,
222
+ makeSetReadyAtQuery: makeSetReadyAtQuery,
216
223
  makeGetInitialStateQuery: makeGetInitialStateQuery,
217
224
  makeGetIndexingAddressesQuery: makeGetIndexingAddressesQuery,
218
225
  getInitialState: getInitialState,
package/src/db/Table.res CHANGED
@@ -31,7 +31,6 @@ type fieldType =
31
31
  | Json
32
32
  | Date
33
33
  | Enum({config: enumConfig<enum>})
34
- | Entity({name: string})
35
34
 
36
35
  type field = {
37
36
  fieldName: string,
@@ -168,7 +167,6 @@ let getPgFieldType = (
168
167
  | Date =>
169
168
  (isNullable ? Postgres.TimestampWithTimezoneNull : Postgres.TimestampWithTimezone :> string)
170
169
  | Enum({config}) => `"${pgSchema}".${config.name}`
171
- | Entity(_) => (Postgres.Text :> string) // FIXME: Will it work correctly if id is not a text column?
172
170
  }
173
171
 
174
172
  // Workaround for Hasura bug https://github.com/enviodev/hyperindex/issues/788
@@ -192,14 +190,14 @@ type compositeIndexField = {
192
190
  type table = {
193
191
  tableName: string,
194
192
  fields: array<fieldOrDerived>,
195
- compositeIndices: array<array<compositeIndexField>>,
193
+ compositeIndexes: array<array<compositeIndexField>>,
196
194
  description: option<string>,
197
195
  }
198
196
 
199
- let mkTable = (tableName, ~compositeIndices=[], ~fields, ~description=?) => {
197
+ let mkTable = (tableName, ~compositeIndexes=[], ~fields, ~description=?) => {
200
198
  tableName,
201
199
  fields,
202
- compositeIndices,
200
+ compositeIndexes,
203
201
  description,
204
202
  }
205
203
 
@@ -248,6 +246,40 @@ let getDerivedFromFields = table =>
248
246
  let getFieldByName = (table, fieldName) =>
249
247
  table.fields->Array.find(field => field->getUserDefinedFieldName === fieldName)
250
248
 
249
+ exception NoIdField(string)
250
+
251
+ // The `id` primary-key field. Its type drives both the id column and every
252
+ // foreign key that references the entity, so id-typed SQL (delete-by-id,
253
+ // history backfill) reads the column type and value schema from here.
254
+ let getIdFieldOrThrow = (table): field =>
255
+ switch table->getFieldByName(idFieldName) {
256
+ | Some(Field(field)) => field
257
+ | _ => throw(NoIdField(table.tableName))
258
+ }
259
+
260
+ let getIdPgFieldType = (table, ~pgSchema) =>
261
+ getPgFieldType(
262
+ ~fieldType=(table->getIdFieldOrThrow).fieldType,
263
+ ~pgSchema,
264
+ ~isArray=false,
265
+ ~isNumericArrayAsText=false,
266
+ ~isNullable=false,
267
+ )
268
+
269
+ // Schema for a single id value, typed opaquely so id-generic code can serialize
270
+ // ids regardless of the underlying scalar.
271
+ let getIdSchema = (table): S.t<EntityId.t> =>
272
+ (table->getIdFieldOrThrow).fieldSchema->(Utils.magic: S.t<unknown> => S.t<EntityId.t>)
273
+
274
+ // Serializes an array of ids to the JSON form the SQL layer binds. The array
275
+ // schema is memoized per table so its serializer compiles once, not on every
276
+ // (high-frequency) delete/history write.
277
+ let idsArraySchema: table => S.t<array<EntityId.t>> = Utils.WeakMap.memoize(table =>
278
+ S.array(table->getIdSchema)
279
+ )
280
+ let encodeIdsToJson = (table, ids: array<EntityId.t>): JSON.t =>
281
+ ids->S.reverseConvertToJsonOrThrow(table->idsArraySchema)
282
+
251
283
  // TODO: Test whether it should be passed via args and match the column type
252
284
 
253
285
  let getFieldByApiName = (table, apiFieldName) =>
@@ -297,13 +329,12 @@ let makeRowsSchema = (table, ~rowFieldName) =>
297
329
  S.array(
298
330
  S.object(s => {
299
331
  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
- },
332
+ table.fields->Array.forEach(field =>
333
+ switch field {
334
+ | Field(field) =>
335
+ dict->Dict.set(field->getApiFieldName, s.field(field->rowFieldName, field.fieldSchema))
336
+ | DerivedFrom(_) => ()
337
+ }
307
338
  )
308
339
  dict
309
340
  })->(Utils.magic: S.t<dict<unknown>> => S.t<unknown>),
@@ -324,11 +355,11 @@ let pgRowsSchema: table => S.t<array<unknown>> = Utils.WeakMap.memoize(table =>
324
355
  exception NonExistingTableField(string)
325
356
 
326
357
  /*
327
- Gets all composite indicies (whether they are single indices or not)
358
+ Gets all composite indexes (whether they are single indexes or not)
328
359
  And maps the fields defined to their actual db name (some have _id suffix)
329
360
  */
330
- let getUnfilteredCompositeIndicesUnsafe = (table): array<array<compositeIndexField>> => {
331
- table.compositeIndices->Array.map(compositeIndex =>
361
+ let getUnfilteredCompositeIndexesUnsafe = (table): array<array<compositeIndexField>> => {
362
+ table.compositeIndexes->Array.map(compositeIndex =>
332
363
  compositeIndex->Array.map(indexField => {
333
364
  let dbFieldName = switch table->getFieldByName(indexField.fieldName) {
334
365
  | Some(field) => field->getPgFieldName
@@ -438,10 +469,10 @@ let toSqlParams = (table: table, ~schema, ~pgSchema) => {
438
469
  }
439
470
 
440
471
  /*
441
- Gets all single indicies
472
+ Gets all single indexes
442
473
  And maps the fields defined to their actual db name (some have _id suffix)
443
474
  */
444
- let getSingleIndices = (table): array<string> => {
475
+ let getSingleIndexes = (table): array<string> => {
445
476
  let indexFields = table.fields->Array.filterMap(field =>
446
477
  switch field {
447
478
  | Field(field) if field.isIndex => Some(field->getPgDbFieldName)
@@ -450,8 +481,8 @@ let getSingleIndices = (table): array<string> => {
450
481
  )
451
482
 
452
483
  table
453
- ->getUnfilteredCompositeIndicesUnsafe
454
- //get all composite indices with only 1 field defined
484
+ ->getUnfilteredCompositeIndexesUnsafe
485
+ //get all composite indexes with only 1 field defined
455
486
  //this is still a single index
456
487
  ->Array.filterMap(cidx =>
457
488
  switch cidx {
@@ -467,11 +498,11 @@ let getSingleIndices = (table): array<string> => {
467
498
  }
468
499
 
469
500
  /*
470
- Gets all composite indicies
501
+ Gets all composite indexes
471
502
  And maps the fields defined to their actual db name (some have _id suffix)
472
503
  */
473
- let getCompositeIndices = (table): array<array<compositeIndexField>> => {
504
+ let getCompositeIndexes = (table): array<array<compositeIndexField>> => {
474
505
  table
475
- ->getUnfilteredCompositeIndicesUnsafe
506
+ ->getUnfilteredCompositeIndexesUnsafe
476
507
  ->Array.filter(ind => ind->Array.length > 1)
477
508
  }
@@ -94,6 +94,8 @@ function getPgFieldName(fieldOrDerived) {
94
94
  }
95
95
  }
96
96
 
97
+ let idFieldName = "id";
98
+
97
99
  function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNullable) {
98
100
  let columnType;
99
101
  if (typeof fieldType !== "object") {
@@ -142,9 +144,6 @@ function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNu
142
144
  case "Enum" :
143
145
  columnType = `"` + pgSchema + `".` + fieldType.config.name;
144
146
  break;
145
- case "Entity" :
146
- columnType = "TEXT";
147
- break;
148
147
  }
149
148
  }
150
149
  let isNumericAsText = isArray && isNumericArrayAsText;
@@ -154,12 +153,12 @@ function getPgFieldType(fieldType, pgSchema, isArray, isNumericArrayAsText, isNu
154
153
  );
155
154
  }
156
155
 
157
- function mkTable(tableName, compositeIndicesOpt, fields, description) {
158
- let compositeIndices = compositeIndicesOpt !== undefined ? compositeIndicesOpt : [];
156
+ function mkTable(tableName, compositeIndexesOpt, fields, description) {
157
+ let compositeIndexes = compositeIndexesOpt !== undefined ? compositeIndexesOpt : [];
159
158
  return {
160
159
  tableName: tableName,
161
160
  fields: fields,
162
- compositeIndices: compositeIndices,
161
+ compositeIndexes: compositeIndexes,
163
162
  description: description
164
163
  };
165
164
  }
@@ -226,6 +225,41 @@ function getFieldByName(table, fieldName) {
226
225
  return table.fields.find(field => getUserDefinedFieldName(field) === fieldName);
227
226
  }
228
227
 
228
+ let NoIdField = /* @__PURE__ */Primitive_exceptions.create("Table.NoIdField");
229
+
230
+ function getIdFieldOrThrow(table) {
231
+ let match = getFieldByName(table, idFieldName);
232
+ if (match !== undefined) {
233
+ if (match.TAG === "Field") {
234
+ return match._0;
235
+ }
236
+ throw {
237
+ RE_EXN_ID: NoIdField,
238
+ _1: table.tableName,
239
+ Error: new Error()
240
+ };
241
+ }
242
+ throw {
243
+ RE_EXN_ID: NoIdField,
244
+ _1: table.tableName,
245
+ Error: new Error()
246
+ };
247
+ }
248
+
249
+ function getIdPgFieldType(table, pgSchema) {
250
+ return getPgFieldType(getIdFieldOrThrow(table).fieldType, pgSchema, false, false, false);
251
+ }
252
+
253
+ function getIdSchema(table) {
254
+ return getIdFieldOrThrow(table).fieldSchema;
255
+ }
256
+
257
+ let idsArraySchema = Utils.$$WeakMap.memoize(table => S$RescriptSchema.array(getIdFieldOrThrow(table).fieldSchema));
258
+
259
+ function encodeIdsToJson(table, ids) {
260
+ return S$RescriptSchema.reverseConvertToJsonOrThrow(ids, idsArraySchema(table));
261
+ }
262
+
229
263
  function getFieldByApiName(table, apiFieldName) {
230
264
  return table.fields.find(field => {
231
265
  let tmp;
@@ -270,8 +304,8 @@ let pgRowsSchema = Utils.$$WeakMap.memoize(table => makeRowsSchema(table, getPgD
270
304
 
271
305
  let NonExistingTableField = /* @__PURE__ */Primitive_exceptions.create("Table.NonExistingTableField");
272
306
 
273
- function getUnfilteredCompositeIndicesUnsafe(table) {
274
- return table.compositeIndices.map(compositeIndex => compositeIndex.map(indexField => {
307
+ function getUnfilteredCompositeIndexesUnsafe(table) {
308
+ return table.compositeIndexes.map(compositeIndex => compositeIndex.map(indexField => {
275
309
  let field = getFieldByName(table, indexField.fieldName);
276
310
  let dbFieldName;
277
311
  if (field !== undefined) {
@@ -385,7 +419,7 @@ function toSqlParams(table, schema, pgSchema) {
385
419
  };
386
420
  }
387
421
 
388
- function getSingleIndices(table) {
422
+ function getSingleIndexes(table) {
389
423
  let indexFields = Stdlib_Array.filterMap(table.fields, field => {
390
424
  if (field.TAG !== "Field") {
391
425
  return;
@@ -395,7 +429,7 @@ function getSingleIndices(table) {
395
429
  return getPgDbFieldName(field$1);
396
430
  }
397
431
  });
398
- return Array.from(new Set(Stdlib_Array.filterMap(getUnfilteredCompositeIndicesUnsafe(table), cidx => {
432
+ return Array.from(new Set(Stdlib_Array.filterMap(getUnfilteredCompositeIndexesUnsafe(table), cidx => {
399
433
  if (cidx.length !== 1) {
400
434
  return;
401
435
  }
@@ -404,12 +438,10 @@ function getSingleIndices(table) {
404
438
  }).concat([indexFields]).flat())).toSorted(Primitive_string.compare);
405
439
  }
406
440
 
407
- function getCompositeIndices(table) {
408
- return getUnfilteredCompositeIndicesUnsafe(table).filter(ind => ind.length > 1);
441
+ function getCompositeIndexes(table) {
442
+ return getUnfilteredCompositeIndexesUnsafe(table).filter(ind => ind.length > 1);
409
443
  }
410
444
 
411
- let idFieldName = "id";
412
-
413
445
  export {
414
446
  makeEnumConfig,
415
447
  mkField,
@@ -429,15 +461,21 @@ export {
429
461
  getLinkedEntityFields,
430
462
  getDerivedFromFields,
431
463
  getFieldByName,
464
+ NoIdField,
465
+ getIdFieldOrThrow,
466
+ getIdPgFieldType,
467
+ getIdSchema,
468
+ idsArraySchema,
469
+ encodeIdsToJson,
432
470
  getFieldByApiName,
433
471
  queryFields,
434
472
  makeRowsSchema,
435
473
  rowsSchema,
436
474
  pgRowsSchema,
437
475
  NonExistingTableField,
438
- getUnfilteredCompositeIndicesUnsafe,
476
+ getUnfilteredCompositeIndexesUnsafe,
439
477
  toSqlParams,
440
- getSingleIndices,
441
- getCompositeIndices,
478
+ getSingleIndexes,
479
+ getCompositeIndexes,
442
480
  }
443
- /* queryFields Not a pure module */
481
+ /* idsArraySchema Not a pure module */
@@ -0,0 +1,48 @@
1
+ // Binding to the Rust `AddressSet` napi class: an immutable, ordered snapshot
2
+ // of some of a chain's indexed addresses, handed to a fetch-state partition
3
+ // instead of a JS address array. Sets are ordered by
4
+ // `(effectiveStartBlock, address)`, so the same addresses always produce the
5
+ // same set however they were registered or restored. Everything a query derives
6
+ // from one (padded topics, the routing owner index, per-contract counts) is
7
+ // built once inside Rust and shared by every query the partition makes.
8
+ type t
9
+
10
+ type startBlockGroup = {startBlock: int, count: int}
11
+
12
+ @send external size: t => int = "size"
13
+
14
+ // Live addresses of one contract, derived once per set inside Rust — so the
15
+ // fetch state can size and split partitions without ever walking the addresses.
16
+ @send external countFor: (t, string) => int = "countFor"
17
+
18
+ // The chain-wide address gate, reachable through any set of the store. Not set
19
+ // membership: the simulate source has no native query boundary, so it applies
20
+ // the same gate every real source applies while routing.
21
+ @send external has: (t, Address.t, string, int) => bool = "has"
22
+
23
+ @send external contractNames: t => array<string> = "contractNames"
24
+
25
+ // Distinct effective start blocks in this set, ascending — how partition
26
+ // creation decides where one partition ends and the next begins.
27
+ @send external startBlockGroups: t => array<startBlockGroup> = "startBlockGroups"
28
+
29
+ @send external slice: (t, ~offset: int, ~limit: option<int>) => t = "slice"
30
+
31
+ // Keeps only the named contracts' addresses, in set order.
32
+ @send external filterByContracts: (t, array<string>) => t = "filterByContracts"
33
+
34
+ // Drops addresses registered after the target block, and any the store has
35
+ // tombstoned since this set was built.
36
+ @send external filterByRegistrationBlock: (t, int) => t = "filterByRegistrationBlock"
37
+
38
+ // Union with another set of the same store, keeping set order; duplicates
39
+ // collapse.
40
+ @send external merge: (t, t) => t = "merge"
41
+
42
+ // Canonical address strings in set order. Not on a query path — queries read
43
+ // the set's cached slices inside Rust.
44
+ @send external addresses: t => array<Address.t> = "addresses"
45
+
46
+ @send external entries: t => array<Internal.indexingContract> = "entries"
47
+
48
+ let isEmpty = (set: t) => set->size === 0
@@ -0,0 +1,11 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ function isEmpty(set) {
5
+ return set.size() === 0;
6
+ }
7
+
8
+ export {
9
+ isEmpty,
10
+ }
11
+ /* No side effect */