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.
- package/evm.schema.json +1 -1
- package/package.json +6 -6
- package/src/Config.res +0 -9
- package/src/Config.res.mjs +2 -6
- package/src/Core.res +0 -21
- package/src/Core.res.mjs +0 -17
- package/src/EventProcessing.res +6 -6
- package/src/EventProcessing.res.mjs +6 -8
- package/src/HandlerLoader.res +22 -48
- package/src/HandlerLoader.res.mjs +15 -41
- package/src/HandlerTypeCheck.res +207 -0
- package/src/HandlerTypeCheck.res.mjs +262 -0
- package/src/LoadLayer.res +7 -39
- package/src/LoadLayer.res.mjs +38 -65
- package/src/LoadLayer.resi +0 -28
- package/src/PgStorage.res +5 -24
- package/src/PgStorage.res.mjs +1 -18
- package/src/UserContext.res +62 -377
- package/src/UserContext.res.mjs +39 -297
- package/src/bindings/NodeJs.res +31 -0
- package/src/bindings/NodeJs.res.mjs +3 -0
- package/src/db/Table.res +0 -10
- package/src/db/Table.res.mjs +11 -22
- package/src/sources/EvmRpcClient.res +2 -0
- package/src/sources/RpcSource.res +17 -4
- package/src/sources/RpcSource.res.mjs +23 -5
- package/src/sources/SourceManager.res +63 -40
- package/src/sources/SourceManager.res.mjs +32 -20
- package/src/HandlerTypeCheck.mjs +0 -14
- package/src/HandlerTypeCheckWorker.mjs +0 -68
- package/src/SyncWrites.res +0 -86
- package/src/SyncWrites.res.mjs +0 -85
- package/src/subgraph/abi-types.ts +0 -63
- package/src/subgraph/assemblyscript.ts +0 -85
- package/src/subgraph/blocks.ts +0 -183
- package/src/subgraph/calls.ts +0 -149
- package/src/subgraph/conformance.ts +0 -83
- package/src/subgraph/errors.ts +0 -96
- package/src/subgraph/graph-cli-worker.mjs +0 -26
- package/src/subgraph/graph-cli.ts +0 -190
- package/src/subgraph/graph-ts-enums.ts +0 -28
- package/src/subgraph/graph-ts-types/VERSION +0 -2
- package/src/subgraph/graph-ts-types/chain/arweave.d.ts +0 -70
- package/src/subgraph/graph-ts-types/chain/cosmos.d.ts +0 -327
- package/src/subgraph/graph-ts-types/chain/ethereum.d.ts +0 -233
- package/src/subgraph/graph-ts-types/chain/near.d.ts +0 -253
- package/src/subgraph/graph-ts-types/chain/starknet.d.ts +0 -32
- package/src/subgraph/graph-ts-types/common/collections.d.ts +0 -136
- package/src/subgraph/graph-ts-types/common/conversion.d.ts +0 -11
- package/src/subgraph/graph-ts-types/common/datasource.d.ts +0 -30
- package/src/subgraph/graph-ts-types/common/eager-offset.d.ts +0 -0
- package/src/subgraph/graph-ts-types/common/json.d.ts +0 -17
- package/src/subgraph/graph-ts-types/common/numbers.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/value.d.ts +0 -120
- package/src/subgraph/graph-ts-types/common/yaml.d.ts +0 -90
- package/src/subgraph/graph-ts-types/global/global.d.ts +0 -194
- package/src/subgraph/graph-ts-types/helper-functions.d.ts +0 -22
- package/src/subgraph/graph-ts-types/index.d.ts +0 -102
- package/src/subgraph/graph-ts.ts +0 -2285
- package/src/subgraph/hosts.ts +0 -158
- package/src/subgraph/rpc.ts +0 -65
- package/src/subgraph/runtime.ts +0 -595
- 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
|
-
|
|
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,
|
package/src/LoadLayer.res.mjs
CHANGED
|
@@ -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
|
-
|
|
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 */
|
package/src/LoadLayer.resi
CHANGED
|
@@ -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,
|