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
@@ -0,0 +1,207 @@
1
+ type result =
2
+ | Passed
3
+ | TypeErrors(string)
4
+ | Skipped(string)
5
+
6
+ let timeoutSeconds = 30
7
+
8
+ // tsc's pretty output reads the same from TypeScript 5 to 7: a diagnostic
9
+ // starts unindented with its location, its code frame and related locations
10
+ // follow indented, and `--listFiles` prints the program's files after the
11
+ // last one, before the closing summary.
12
+ let fileDiagnostic = /^(.+):\d+:\d+ - error TS(\d+): /
13
+ let globalDiagnostic = /^error TS(\d+): /
14
+ let summary = /^Found \d+ errors?\b/
15
+ let thrownError = /^\w*Error: /
16
+
17
+ let lines = output => output->String.replaceAll("\r\n", "\n")->String.split("\n")
18
+
19
+ let rec findUp = (directory, name) => {
20
+ let candidate = NodeJs.Path.resolve([directory, name])->NodeJs.Path.toString
21
+ if NodeJs.Fs.existsSync(candidate) {
22
+ Some(candidate)
23
+ } else {
24
+ let parent = NodeJs.Path.dirname(directory)->NodeJs.Path.toString
25
+ parent === directory ? None : findUp(parent, name)
26
+ }
27
+ }
28
+
29
+ // The `tsc` the project's own scripts run. TypeScript 7 has no JavaScript API
30
+ // to call instead, only this command.
31
+ let resolveTsc = (~cwd) =>
32
+ try {
33
+ let manifest =
34
+ NodeJs.Module.createRequire(
35
+ NodeJs.Path.resolve([cwd, "package.json"])->NodeJs.Path.toString,
36
+ )->NodeJs.Module.resolve("typescript/package.json")
37
+ let bin = switch NodeJs.Fs.readFileSync(manifest)->JSON.parseOrThrow {
38
+ | JSON.Object(fields) =>
39
+ switch fields->Dict.get("bin") {
40
+ | Some(JSON.String(bin)) => Some(bin)
41
+ | Some(JSON.Object(bins)) =>
42
+ switch bins->Dict.get("tsc") {
43
+ | Some(JSON.String(bin)) => Some(bin)
44
+ | _ => None
45
+ }
46
+ | _ => None
47
+ }
48
+ | _ => None
49
+ }
50
+ bin->Option.map(bin =>
51
+ NodeJs.Path.resolve([
52
+ NodeJs.Path.dirname(manifest)->NodeJs.Path.toString,
53
+ bin,
54
+ ])->NodeJs.Path.toString
55
+ )
56
+ } catch {
57
+ | _ => None
58
+ }
59
+
60
+ type run = {error: option<NodeJs.ChildProcess.execFileError>, output: string}
61
+
62
+ let runTsc = (~tsc, ~cwd, args) =>
63
+ Promise.make((resolve, _) =>
64
+ NodeJs.ChildProcess.execFile(
65
+ NodeJs.Process.process->NodeJs.Process.execPath,
66
+ [tsc]->Array.concat(args),
67
+ {cwd, timeout: timeoutSeconds * 1000, maxBuffer: Float.Constants.positiveInfinity},
68
+ (error, stdout, stderr) =>
69
+ resolve({
70
+ error: error->Null.toOption,
71
+ output: NodeJs.Util.stripVTControlCharacters(stdout ++ stderr),
72
+ }),
73
+ )
74
+ )
75
+
76
+ type diagnostic = {file: option<string>, code: int, lines: array<string>}
77
+
78
+ // tsc type-checks nothing after a syntax error, an options error or a global
79
+ // error, and an options error is reported at its line in tsconfig.json.
80
+ let canStopTypeChecking = ({file, code}) =>
81
+ file->Option.isNone || code < 2000 || (code >= 5000 && code < 7000)
82
+
83
+ // Paths compare relative to the project, which on Windows also ignores the
84
+ // case of a drive letter tsc may print differently.
85
+ let parse = (output, ~cwd) => {
86
+ let relative = file =>
87
+ NodeJs.Path.relative(cwd, NodeJs.Path.resolve([cwd, file])->NodeJs.Path.toString)
88
+ let diagnostics = []
89
+ let programFiles = Utils.Set.make()
90
+ let current = ref(None)
91
+ let start = (~file, ~code, line) => {
92
+ let diagnostic = {
93
+ file,
94
+ code: code->Int.fromString->Option.getOr(0),
95
+ lines: [line],
96
+ }
97
+ diagnostics->Array.push(diagnostic)
98
+ current := Some(diagnostic)
99
+ }
100
+ output
101
+ ->lines
102
+ ->Array.forEach(line =>
103
+ switch (
104
+ fileDiagnostic->RegExp.exec(line)->Option.map(RegExp.Result.matches),
105
+ globalDiagnostic->RegExp.exec(line)->Option.map(RegExp.Result.matches),
106
+ ) {
107
+ | (Some([Some(file), Some(code)]), _) => start(~file=Some(relative(file)), ~code, line)
108
+ | (_, Some([Some(code)])) => start(~file=None, ~code, line)
109
+ | _ if NodeJs.Path.isAbsolute(line) =>
110
+ programFiles->Utils.Set.add(relative(line))->ignore
111
+ current := None
112
+ | _ if summary->RegExp.test(line) => current := None
113
+ | _ => current.contents->Option.forEach(diagnostic => diagnostic.lines->Array.push(line))
114
+ }
115
+ )
116
+ (diagnostics, programFiles)
117
+ }
118
+
119
+ // Exit codes say nothing here: TypeScript 5 and 6 exit with 2 on type errors,
120
+ // 7 with 1, and 1 is also how its launcher fails when the native compiler
121
+ // isn't installed.
122
+ let failure = ({error, output}) =>
123
+ switch error {
124
+ | Some({killed: true}) =>
125
+ `Skipped the handler type check: tsc didn't finish within ${timeoutSeconds->Int.toString} seconds.`
126
+ | _ =>
127
+ let reason =
128
+ output
129
+ ->lines
130
+ ->Array.find(line => thrownError->RegExp.test(line))
131
+ ->Option.getOr(output->String.trim)
132
+ `Skipped the handler type check: tsc failed to run:\n\n${reason}`
133
+ }
134
+
135
+ let check = async (~cwd, ~files) => {
136
+ // The ReScript compiler checks a ReScript project's handlers, so it has no
137
+ // reason to set up TypeScript, and the warning would only be noise there.
138
+ // `rescript.json` at the root is what makes codegen treat it as ReScript.
139
+ let skip = warning =>
140
+ NodeJs.Fs.existsSync(NodeJs.Path.resolve([cwd, "rescript.json"])->NodeJs.Path.toString)
141
+ ? Passed
142
+ : Skipped(warning)
143
+
144
+ switch (resolveTsc(~cwd), findUp(cwd, "tsconfig.json")) {
145
+ | (None, _) =>
146
+ skip(
147
+ "Skipped the handler type check: typescript isn't installed. Add it to devDependencies to type-check handlers on start.",
148
+ )
149
+ | (_, None) =>
150
+ skip(
151
+ "Skipped the handler type check: no tsconfig.json found. Add one, like the one envio init creates, to type-check handlers on start.",
152
+ )
153
+ | (Some(tsc), Some(tsconfig)) =>
154
+ // The project's own `tsc --noEmit`, minus the build info it would write.
155
+ // `explainFiles` would replace the listed files' absolute paths with
156
+ // relative ones and the reasons each is included.
157
+ let run = await runTsc(
158
+ ~tsc,
159
+ ~cwd,
160
+ [
161
+ "--project",
162
+ tsconfig,
163
+ "--noEmit",
164
+ "--incremental",
165
+ "false",
166
+ "--composite",
167
+ "false",
168
+ "--listFiles",
169
+ "--explainFiles",
170
+ "false",
171
+ "--pretty",
172
+ ],
173
+ )
174
+ let (diagnostics, programFiles) = run.output->parse(~cwd)
175
+ let report = diagnostics =>
176
+ diagnostics
177
+ ->Array.map(({lines}) => lines->Array.join("\n")->String.trimEnd)
178
+ ->Array.join("\n\n")
179
+ let handlers = files->Array.map(file => NodeJs.Path.relative(cwd, file))
180
+ let isHandler = ({file}) => file->Option.mapOr(false, file => handlers->Array.includes(file))
181
+ let errors = diagnostics->Array.filter(isHandler)
182
+ let stopping =
183
+ diagnostics->Array.filter(diagnostic =>
184
+ !isHandler(diagnostic) && canStopTypeChecking(diagnostic)
185
+ )
186
+ let unchecked = handlers->Array.filter(file => !(programFiles->Utils.Set.has(file)))
187
+ if run.error->Option.isSome && diagnostics->Array.length === 0 {
188
+ Skipped(failure(run))
189
+ } else if errors->Array.length > 0 {
190
+ TypeErrors(report(errors))
191
+ } else if stopping->Array.length > 0 {
192
+ let reason = report(stopping)
193
+ Skipped(
194
+ `Skipped the handler type check: tsc can't check the handlers until these errors are fixed:\n\n${reason}`,
195
+ )
196
+ } else if unchecked->Array.length > 0 {
197
+ let names = unchecked->Array.join(", ")
198
+ let tsconfig = NodeJs.Path.relative(cwd, tsconfig)
199
+ let pronoun = unchecked->Array.length === 1 ? "it" : "them"
200
+ Skipped(
201
+ `Skipped the handler type check: ${tsconfig} doesn't include ${names}. Add ${pronoun} to "include" to type-check ${pronoun} on start.`,
202
+ )
203
+ } else {
204
+ Passed
205
+ }
206
+ }
207
+ }
@@ -0,0 +1,262 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Fs from "fs";
4
+ import * as Path from "path";
5
+ import * as Util from "util";
6
+ import * as Module from "module";
7
+ import * as Process from "process";
8
+ import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
9
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
10
+ import * as Child_process from "child_process";
11
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
12
+
13
+ let fileDiagnostic = /^(.+):\d+:\d+ - error TS(\d+): /;
14
+
15
+ let globalDiagnostic = /^error TS(\d+): /;
16
+
17
+ let summary = /^Found \d+ errors?\b/;
18
+
19
+ let thrownError = /^\w*Error: /;
20
+
21
+ function lines(output) {
22
+ return output.replaceAll("\r\n", "\n").split("\n");
23
+ }
24
+
25
+ function findUp(_directory, name) {
26
+ while (true) {
27
+ let directory = _directory;
28
+ let candidate = Path.resolve(directory, name);
29
+ if (Fs.existsSync(candidate)) {
30
+ return candidate;
31
+ }
32
+ let parent = Path.dirname(directory);
33
+ if (parent === directory) {
34
+ return;
35
+ }
36
+ _directory = parent;
37
+ continue;
38
+ };
39
+ }
40
+
41
+ function resolveTsc(cwd) {
42
+ try {
43
+ let manifest = Module.createRequire(Path.resolve(cwd, "package.json")).resolve("typescript/package.json");
44
+ let fields = JSON.parse(Fs.readFileSync(manifest, "utf8"));
45
+ let bin;
46
+ if (typeof fields === "object" && fields !== null && !Array.isArray(fields)) {
47
+ let match = fields["bin"];
48
+ if (match !== undefined && !(match === null || Array.isArray(match))) {
49
+ switch (typeof match) {
50
+ case "string" :
51
+ bin = match;
52
+ break;
53
+ case "object" :
54
+ let match$1 = match["tsc"];
55
+ bin = typeof match$1 === "string" ? match$1 : undefined;
56
+ break;
57
+ default:
58
+ bin = undefined;
59
+ }
60
+ } else {
61
+ bin = undefined;
62
+ }
63
+ } else {
64
+ bin = undefined;
65
+ }
66
+ return Stdlib_Option.map(bin, bin => Path.resolve(Path.dirname(manifest), bin));
67
+ } catch (exn) {
68
+ return;
69
+ }
70
+ }
71
+
72
+ function runTsc(tsc, cwd, args) {
73
+ return new Promise((resolve, param) => {
74
+ Child_process.execFile(Process.execPath, [tsc].concat(args), {
75
+ cwd: cwd,
76
+ timeout: 30000,
77
+ maxBuffer: Number.POSITIVE_INFINITY
78
+ }, (error, stdout, stderr) => resolve({
79
+ error: error === null ? undefined : Primitive_option.some(error),
80
+ output: Util.stripVTControlCharacters(stdout + stderr)
81
+ }));
82
+ });
83
+ }
84
+
85
+ function canStopTypeChecking(param) {
86
+ let code = param.code;
87
+ if (Stdlib_Option.isNone(param.file) || code < 2000) {
88
+ return true;
89
+ } else if (code >= 5000) {
90
+ return code < 7000;
91
+ } else {
92
+ return false;
93
+ }
94
+ }
95
+
96
+ function parse(output, cwd) {
97
+ let relative = file => Path.relative(cwd, Path.resolve(cwd, file));
98
+ let diagnostics = [];
99
+ let programFiles = new Set();
100
+ let current = {
101
+ contents: undefined
102
+ };
103
+ let start = (file, code, line) => {
104
+ let diagnostic_code = Stdlib_Option.getOr(Stdlib_Int.fromString(code, undefined), 0);
105
+ let diagnostic_lines = [line];
106
+ let diagnostic = {
107
+ file: file,
108
+ code: diagnostic_code,
109
+ lines: diagnostic_lines
110
+ };
111
+ diagnostics.push(diagnostic);
112
+ current.contents = diagnostic;
113
+ };
114
+ lines(output).forEach(line => {
115
+ let match = Stdlib_Option.map(Primitive_option.fromNullable(fileDiagnostic.exec(line)), prim => prim.slice(1));
116
+ let match$1 = Stdlib_Option.map(Primitive_option.fromNullable(globalDiagnostic.exec(line)), prim => prim.slice(1));
117
+ let exit = 0;
118
+ if (match !== undefined && match.length === 2) {
119
+ let file = match[0];
120
+ if (file !== undefined) {
121
+ let code = match[1];
122
+ if (code !== undefined) {
123
+ return start(relative(file), code, line);
124
+ }
125
+ exit = 2;
126
+ } else {
127
+ exit = 2;
128
+ }
129
+ } else {
130
+ exit = 2;
131
+ }
132
+ if (exit === 2 && match$1 !== undefined && match$1.length === 1) {
133
+ let code$1 = match$1[0];
134
+ if (code$1 !== undefined) {
135
+ return start(undefined, code$1, line);
136
+ }
137
+ }
138
+ if (Path.isAbsolute(line)) {
139
+ programFiles.add(relative(line));
140
+ current.contents = undefined;
141
+ return;
142
+ } else if (summary.test(line)) {
143
+ current.contents = undefined;
144
+ return;
145
+ } else {
146
+ return Stdlib_Option.forEach(current.contents, diagnostic => {
147
+ diagnostic.lines.push(line);
148
+ });
149
+ }
150
+ });
151
+ return [
152
+ diagnostics,
153
+ programFiles
154
+ ];
155
+ }
156
+
157
+ function failure(param) {
158
+ let output = param.output;
159
+ let error = param.error;
160
+ if (error !== undefined && error.killed) {
161
+ return `Skipped the handler type check: tsc didn't finish within ` + (30).toString() + ` seconds.`;
162
+ }
163
+ let reason = Stdlib_Option.getOr(lines(output).find(line => thrownError.test(line)), output.trim());
164
+ return `Skipped the handler type check: tsc failed to run:\n\n` + reason;
165
+ }
166
+
167
+ async function check(cwd, files) {
168
+ let skip = warning => {
169
+ if (Fs.existsSync(Path.resolve(cwd, "rescript.json"))) {
170
+ return "Passed";
171
+ } else {
172
+ return {
173
+ TAG: "Skipped",
174
+ _0: warning
175
+ };
176
+ }
177
+ };
178
+ let match = resolveTsc(cwd);
179
+ let match$1 = findUp(cwd, "tsconfig.json");
180
+ if (match === undefined) {
181
+ return skip("Skipped the handler type check: typescript isn't installed. Add it to devDependencies to type-check handlers on start.");
182
+ }
183
+ if (match$1 === undefined) {
184
+ return skip("Skipped the handler type check: no tsconfig.json found. Add one, like the one envio init creates, to type-check handlers on start.");
185
+ }
186
+ let run = await runTsc(match, cwd, [
187
+ "--project",
188
+ match$1,
189
+ "--noEmit",
190
+ "--incremental",
191
+ "false",
192
+ "--composite",
193
+ "false",
194
+ "--listFiles",
195
+ "--explainFiles",
196
+ "false",
197
+ "--pretty"
198
+ ]);
199
+ let match$2 = parse(run.output, cwd);
200
+ let programFiles = match$2[1];
201
+ let diagnostics = match$2[0];
202
+ let report = diagnostics => diagnostics.map(param => param.lines.join("\n").trimEnd()).join("\n\n");
203
+ let handlers = files.map(file => Path.relative(cwd, file));
204
+ let isHandler = param => Stdlib_Option.mapOr(param.file, false, file => handlers.includes(file));
205
+ let errors = diagnostics.filter(isHandler);
206
+ let stopping = diagnostics.filter(diagnostic => {
207
+ if (isHandler(diagnostic)) {
208
+ return false;
209
+ } else {
210
+ return canStopTypeChecking(diagnostic);
211
+ }
212
+ });
213
+ let unchecked = handlers.filter(file => !programFiles.has(file));
214
+ if (Stdlib_Option.isSome(run.error) && diagnostics.length === 0) {
215
+ return {
216
+ TAG: "Skipped",
217
+ _0: failure(run)
218
+ };
219
+ }
220
+ if (errors.length !== 0) {
221
+ return {
222
+ TAG: "TypeErrors",
223
+ _0: report(errors)
224
+ };
225
+ }
226
+ if (stopping.length !== 0) {
227
+ let reason = report(stopping);
228
+ return {
229
+ TAG: "Skipped",
230
+ _0: `Skipped the handler type check: tsc can't check the handlers until these errors are fixed:\n\n` + reason
231
+ };
232
+ }
233
+ if (unchecked.length === 0) {
234
+ return "Passed";
235
+ }
236
+ let names = unchecked.join(", ");
237
+ let tsconfig = Path.relative(cwd, match$1);
238
+ let pronoun = unchecked.length === 1 ? "it" : "them";
239
+ return {
240
+ TAG: "Skipped",
241
+ _0: `Skipped the handler type check: ` + tsconfig + ` doesn't include ` + names + `. Add ` + pronoun + ` to "include" to type-check ` + pronoun + ` on start.`
242
+ };
243
+ }
244
+
245
+ let timeoutSeconds = 30;
246
+
247
+ export {
248
+ timeoutSeconds,
249
+ fileDiagnostic,
250
+ globalDiagnostic,
251
+ summary,
252
+ thrownError,
253
+ lines,
254
+ findUp,
255
+ resolveTsc,
256
+ runTsc,
257
+ canStopTypeChecking,
258
+ parse,
259
+ failure,
260
+ check,
261
+ }
262
+ /* fs Not a pure module */
package/src/LoadLayer.res CHANGED
@@ -332,44 +332,6 @@ let loadEffect = (
332
332
  )
333
333
  }
334
334
 
335
- // Keying an _in walks every value, so it's computed once and handed on rather
336
- // than recomputed by each reader. Before answering "not in memory", the rows
337
- // already loaded for other filters are checked: they may cover this one.
338
- let indexFilter = (inMemTable, ~filter, ~table) => {
339
- let filterKey = filter->EntityFilter.toString(~table)
340
- if !(inMemTable->InMemoryTable.Entity.hasIndex)(filterKey) {
341
- inMemTable->InMemoryTable.Entity.tryIndexFromLoadedValues(~filter, ~table)
342
- }
343
- filterKey
344
- }
345
-
346
- // A recorded absence is an answer too: `Some(None)` means the entity is known
347
- // not to exist, so no load is needed to say so.
348
- let getByIdInMemory = (
349
- ~entityConfig: Internal.entityConfig,
350
- ~scope,
351
- ~indexerState,
352
- ~entityId: string,
353
- ) => {
354
- let inMemTable = indexerState->InMemoryStore.getInMemTable(~entityConfig, ~scope)
355
- inMemTable.latestEntityChangeById->Dict.has(entityId)
356
- ? Some((inMemTable->InMemoryTable.Entity.getUnsafe)(entityId))
357
- : None
358
- }
359
-
360
- let getByFilterInMemory = (
361
- ~entityConfig: Internal.entityConfig,
362
- ~scope,
363
- ~indexerState,
364
- ~filter: EntityFilter.t,
365
- ) => {
366
- let inMemTable = indexerState->InMemoryStore.getInMemTable(~entityConfig, ~scope)
367
- let filterKey = inMemTable->indexFilter(~filter, ~table=entityConfig.table)
368
- (inMemTable->InMemoryTable.Entity.hasIndex)(filterKey)
369
- ? Some((inMemTable->InMemoryTable.Entity.getUnsafeOnIndex)(filterKey))
370
- : None
371
- }
372
-
373
335
  let loadByParsedFilter = (
374
336
  ~loadManager,
375
337
  ~persistence: Persistence.t,
@@ -463,7 +425,13 @@ let loadByParsedFilter = (
463
425
  )
464
426
  }
465
427
 
466
- let filterKey = inMemTable->indexFilter(~filter, ~table=entityConfig.table)
428
+ // Keying an _in walks every value, so it's computed once here and handed to
429
+ // the load manager rather than recomputed by the hasher.
430
+ let filterKey = filter->EntityFilter.toString(~table=entityConfig.table)
431
+
432
+ if !(inMemTable->InMemoryTable.Entity.hasIndex)(filterKey) {
433
+ inMemTable->InMemoryTable.Entity.tryIndexFromLoadedValues(~filter, ~table=entityConfig.table)
434
+ }
467
435
 
468
436
  loadManager->LoadManager.call(
469
437
  ~key,
@@ -15,7 +15,6 @@ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
15
15
  import * as ErrorHandling from "./ErrorHandling.res.mjs";
16
16
  import * as InMemoryStore from "./InMemoryStore.res.mjs";
17
17
  import * as InMemoryTable from "./InMemoryTable.res.mjs";
18
- import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
19
18
  import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
20
19
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
21
20
 
@@ -183,69 +182,46 @@ function loadEffect(loadManager, persistence, effect, effectArgs, scope, indexer
183
182
  return LoadManager.call(loadManager, effectArgs, key, load, args => args.cacheKey, shouldGroup, hash => InMemoryStore.hasEffectOutput(inMemTable, hash), hash => InMemoryStore.getEffectOutputUnsafe(inMemTable, hash));
184
183
  }
185
184
 
186
- function indexFilter(inMemTable, filter, table) {
187
- let filterKey = EntityFilter.toString(filter, table);
188
- if (!InMemoryTable.Entity.hasIndex(inMemTable)(filterKey)) {
189
- InMemoryTable.Entity.tryIndexFromLoadedValues(inMemTable, filter, table);
190
- }
191
- return filterKey;
192
- }
193
-
194
- function getByIdInMemory(entityConfig, scope, indexerState, entityId) {
195
- let inMemTable = InMemoryStore.getInMemTable(indexerState, entityConfig, scope);
196
- if (entityId in inMemTable.latestEntityChangeById) {
197
- return Primitive_option.some(InMemoryTable.Entity.getUnsafe(inMemTable)(entityId));
198
- }
199
- }
200
-
201
- function getByFilterInMemory(entityConfig, scope, indexerState, filter) {
202
- let inMemTable = InMemoryStore.getInMemTable(indexerState, entityConfig, scope);
203
- let filterKey = indexFilter(inMemTable, filter, entityConfig.table);
204
- if (InMemoryTable.Entity.hasIndex(inMemTable)(filterKey)) {
205
- return InMemoryTable.Entity.getUnsafeOnIndex(inMemTable)(filterKey);
206
- }
207
- }
208
-
209
- function loadByParsedFilter(loadManager, persistence, entityConfig, scope, indexerState, shouldGroup, item, ecosystem, filter) {
210
- let key = EntityFilter.toOperationKey(filter, entityConfig.name) + scopeKeySuffix(scope);
211
- let inMemTable = InMemoryStore.getInMemTable(indexerState, entityConfig, scope);
212
- let load = async (filters, param) => {
213
- let storage = Persistence.getInitializedStorageOrThrow(persistence);
214
- let timerRef = IndexerState.startStorageLoad(indexerState, storage.name, key);
215
- let size = {
216
- contents: 0
217
- };
218
- filters.forEach(filter => InMemoryTable.Entity.addEmptyIndex(inMemTable, filter, entityConfig.table));
219
- await storage.ensureQueryIndexes(entityConfig, scope, filters);
220
- let queries = EntityFilter.merge(filters);
221
- await Promise.all(queries.map(async filter => {
222
- try {
223
- let entities = await storage.loadOrThrow(EntityFilter.scoped(filter, entityConfig.table, scope), entityConfig.table);
224
- let committedCheckpointId = IndexerState.committedCheckpointIdFor(indexerState, scope);
225
- entities.forEach(entity => InMemoryTable.Entity.initValue(inMemTable, committedCheckpointId, entity.id, entity));
226
- InMemoryTable.Entity.recordLoadedValues(inMemTable, filter, entityConfig.table);
227
- size.contents = size.contents + entities.length | 0;
228
- return;
229
- } catch (raw_exn) {
230
- let exn = Primitive_exceptions.internalToException(raw_exn);
231
- if (exn.RE_EXN_ID === Persistence.StorageError) {
232
- return ErrorHandling.mkLogAndRaise(Logging.createChildFrom(Ecosystem.getItemLogger(item, ecosystem), {
233
- operation: key,
234
- params: EntityFilter.getParams(filter)
235
- }), exn.message, exn.reason);
236
- }
237
- throw exn;
238
- }
239
- }));
240
- return IndexerState.endStorageLoad(indexerState, timerRef, storage.name, key, Stdlib_Array.reduce(queries, 0, (acc, query) => acc + EntityFilter.valuesCount(query) | 0), size.contents);
241
- };
242
- let filterKey = indexFilter(inMemTable, filter, entityConfig.table);
243
- return LoadManager.call(loadManager, filter, key, load, param => filterKey, shouldGroup, InMemoryTable.Entity.hasIndex(inMemTable), InMemoryTable.Entity.getUnsafeOnIndex(inMemTable));
244
- }
245
-
246
185
  function loadByFilter(loadManager, persistence, entityConfig, scope, indexerState, shouldGroup, item, ecosystem, filter) {
247
186
  try {
248
- return loadByParsedFilter(loadManager, persistence, entityConfig, scope, indexerState, shouldGroup, item, ecosystem, EntityFilter.parseOrThrow(filter, entityConfig.name, entityConfig.table));
187
+ let filter$1 = EntityFilter.parseOrThrow(filter, entityConfig.name, entityConfig.table);
188
+ let key = EntityFilter.toOperationKey(filter$1, entityConfig.name) + scopeKeySuffix(scope);
189
+ let inMemTable = InMemoryStore.getInMemTable(indexerState, entityConfig, scope);
190
+ let load = async (filters, param) => {
191
+ let storage = Persistence.getInitializedStorageOrThrow(persistence);
192
+ let timerRef = IndexerState.startStorageLoad(indexerState, storage.name, key);
193
+ let size = {
194
+ contents: 0
195
+ };
196
+ filters.forEach(filter => InMemoryTable.Entity.addEmptyIndex(inMemTable, filter, entityConfig.table));
197
+ await storage.ensureQueryIndexes(entityConfig, scope, filters);
198
+ let queries = EntityFilter.merge(filters);
199
+ await Promise.all(queries.map(async filter => {
200
+ try {
201
+ let entities = await storage.loadOrThrow(EntityFilter.scoped(filter, entityConfig.table, scope), entityConfig.table);
202
+ let committedCheckpointId = IndexerState.committedCheckpointIdFor(indexerState, scope);
203
+ entities.forEach(entity => InMemoryTable.Entity.initValue(inMemTable, committedCheckpointId, entity.id, entity));
204
+ InMemoryTable.Entity.recordLoadedValues(inMemTable, filter, entityConfig.table);
205
+ size.contents = size.contents + entities.length | 0;
206
+ return;
207
+ } catch (raw_exn) {
208
+ let exn = Primitive_exceptions.internalToException(raw_exn);
209
+ if (exn.RE_EXN_ID === Persistence.StorageError) {
210
+ return ErrorHandling.mkLogAndRaise(Logging.createChildFrom(Ecosystem.getItemLogger(item, ecosystem), {
211
+ operation: key,
212
+ params: EntityFilter.getParams(filter)
213
+ }), exn.message, exn.reason);
214
+ }
215
+ throw exn;
216
+ }
217
+ }));
218
+ return IndexerState.endStorageLoad(indexerState, timerRef, storage.name, key, Stdlib_Array.reduce(queries, 0, (acc, query) => acc + EntityFilter.valuesCount(query) | 0), size.contents);
219
+ };
220
+ let filterKey = EntityFilter.toString(filter$1, entityConfig.table);
221
+ if (!InMemoryTable.Entity.hasIndex(inMemTable)(filterKey)) {
222
+ InMemoryTable.Entity.tryIndexFromLoadedValues(inMemTable, filter$1, entityConfig.table);
223
+ }
224
+ return LoadManager.call(loadManager, filter$1, key, load, param => filterKey, shouldGroup, InMemoryTable.Entity.hasIndex(inMemTable), InMemoryTable.Entity.getUnsafeOnIndex(inMemTable));
249
225
  } catch (raw_exn) {
250
226
  let exn = Primitive_exceptions.internalToException(raw_exn);
251
227
  return Promise.reject(Utils.prettifyExn(exn));
@@ -255,9 +231,6 @@ function loadByFilter(loadManager, persistence, entityConfig, scope, indexerStat
255
231
  export {
256
232
  loadById,
257
233
  loadByFilter,
258
- loadByParsedFilter,
259
- getByIdInMemory,
260
- getByFilterInMemory,
261
234
  loadEffect,
262
235
  }
263
236
  /* Utils Not a pure module */
@@ -22,34 +22,6 @@ let loadByFilter: (
22
22
  ~filter: dict<dict<unknown>>,
23
23
  ) => promise<array<Internal.entity>>
24
24
 
25
- let loadByParsedFilter: (
26
- ~loadManager: LoadManager.t,
27
- ~persistence: Persistence.t,
28
- ~entityConfig: Internal.entityConfig,
29
- ~scope: Internal.chainScope,
30
- ~indexerState: IndexerState.t,
31
- ~shouldGroup: bool,
32
- ~item: Internal.item,
33
- ~ecosystem: Ecosystem.t,
34
- ~filter: EntityFilter.t,
35
- ) => promise<array<Internal.entity>>
36
-
37
- // What a get or getWhere answers without a load, or None when it would need
38
- // one. The sync context reads through these and suspends on None.
39
- let getByIdInMemory: (
40
- ~entityConfig: Internal.entityConfig,
41
- ~scope: Internal.chainScope,
42
- ~indexerState: IndexerState.t,
43
- ~entityId: string,
44
- ) => option<option<Internal.entity>>
45
-
46
- let getByFilterInMemory: (
47
- ~entityConfig: Internal.entityConfig,
48
- ~scope: Internal.chainScope,
49
- ~indexerState: IndexerState.t,
50
- ~filter: EntityFilter.t,
51
- ) => option<array<Internal.entity>>
52
-
53
25
  let loadEffect: (
54
26
  ~loadManager: LoadManager.t,
55
27
  ~persistence: Persistence.t,