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,85 +0,0 @@
1
- /**
2
- * The runtime half of `packages/cli/src/subgraph/assemblyscript.rs`, which
3
- * rewrites every arithmetic and comparison operator in a mapping into a call
4
- * on `OPERATORS_HELPER`, every `changetype<Foo>(x)` into one to `RETAG_HELPER`,
5
- * and exports each handler's event class as `EVENT_CLASSES_EXPORT`. The names
6
- * are shared with that file.
7
- */
8
-
9
- export const OPERATORS_HELPER = "__envio_op";
10
- export const RETAG_HELPER = "__envio_retag";
11
- export const EVENT_CLASSES_EXPORT = "__envio_event_classes";
12
-
13
- /**
14
- * AssemblyScript divides two integers as integers; this truncates only when
15
- * both operands really are integers and otherwise divides as before — an `f64`
16
- * divides as a float in AssemblyScript too.
17
- */
18
- export function integerDivision(a: unknown, b: unknown): unknown {
19
- const left = typeof a === "object" && a !== null ? (a as any).valueOf() : a;
20
- const right = typeof b === "object" && b !== null ? (b as any).valueOf() : b;
21
-
22
- const integral = (v: unknown) =>
23
- typeof v === "bigint" || (typeof v === "number" && Number.isInteger(v));
24
- if (integral(left) && integral(right)) {
25
- // Only i64 / i64 stays 64-bit; anything narrower is an i32 in AssemblyScript
26
- // and must come back as a number, or the bigint spreads through every
27
- // arithmetic that follows.
28
- if (typeof left === "bigint" && typeof right === "bigint") {
29
- return left / right;
30
- }
31
- return Math.trunc(Number(left) / Number(right));
32
- }
33
- return (left as number) / (right as number);
34
- }
35
-
36
- /** The graph-ts operator overload `value` declares under `method`, if any. */
37
- function overload(value: unknown, method: string): Function | undefined {
38
- if (!isObject(value)) return undefined;
39
- const fn = (value as Record<string, unknown>)[method];
40
- return typeof fn === "function" ? fn : undefined;
41
- }
42
-
43
- function isObject(value: unknown): boolean {
44
- return value !== null && typeof value === "object";
45
- }
46
-
47
- // Both operands are objects wherever AssemblyScript picks the overload — it
48
- // doesn't compile `BigInt < i32` — so a primitive on either side is left to
49
- // JavaScript, which reads the object through `valueOf`.
50
- const binary =
51
- (method: string, fallback: (a: any, b: any) => unknown) =>
52
- (a: unknown, b: unknown): unknown => {
53
- const declared = isObject(b) ? overload(a, method) : undefined;
54
- return declared ? declared.call(a, b) : fallback(a, b);
55
- };
56
-
57
- // Against null AssemblyScript compares the reference, overload or not.
58
- const equals = (a: unknown, b: unknown): boolean => {
59
- const declared = isObject(b) ? overload(a, "equals") : undefined;
60
- return declared ? (declared.call(a, b) as boolean) : a == b;
61
- };
62
-
63
- /**
64
- * graph-ts overloads the arithmetic and comparison operators on `BigInt`,
65
- * `BigDecimal` and `ByteArray`, and AssemblyScript calls the overload: a
66
- * JavaScript operator would coerce them, or compare their identity — so
67
- * `address == ZERO_ADDRESS` would always be false.
68
- */
69
- export const operators = {
70
- add: binary("plus", (a, b) => a + b),
71
- sub: binary("minus", (a, b) => a - b),
72
- mul: binary("times", (a, b) => a * b),
73
- div: binary("div", integerDivision),
74
- rem: binary("mod", (a, b) => a % b),
75
- eq: equals,
76
- ne: (a: unknown, b: unknown) => !equals(a, b),
77
- lt: binary("lt", (a, b) => a < b),
78
- le: binary("le", (a, b) => a <= b),
79
- gt: binary("gt", (a, b) => a > b),
80
- ge: binary("ge", (a, b) => a >= b),
81
- neg: (a: unknown) => {
82
- const declared = overload(a, "neg");
83
- return declared ? declared.call(a) : -(a as number);
84
- },
85
- };
@@ -1,183 +0,0 @@
1
- /**
2
- * A block handler's `block.timestamp`.
3
- *
4
- * envio hands a block handler only the block number, so the timestamp has to be
5
- * fetched. Every handler invocation in a batch asks within the same microtask,
6
- * so the requests are collected and answered by a HyperSync range query per
7
- * cluster of nearby blocks rather than one round trip per block. An RPC endpoint, if one is configured,
8
- * is the fallback for whatever HyperSync couldn't answer.
9
- */
10
-
11
- import { rpcClient } from "./rpc.ts";
12
-
13
- const API_TOKEN_ENV_VAR = "ENVIO_API_TOKEN";
14
-
15
- const hypersyncUrl = (chainId: number) => `https://${chainId}.hypersync.xyz/query`;
16
-
17
- type Waiter = {
18
- resolve: (timestamp: bigint) => void;
19
- reject: (error: unknown) => void;
20
- };
21
-
22
- /** Blocks asked for since the last flush, by chain then block number. */
23
- let pending = new Map<number, Map<number, Waiter[]>>();
24
- let flushScheduled = false;
25
-
26
- let rpcUrls: string[] = [];
27
-
28
- export function configureBlockTimestamps(urls: string[]) {
29
- rpcUrls = urls;
30
- pending = new Map();
31
- flushScheduled = false;
32
- }
33
-
34
- export function requestBlockTimestamp(chainId: number, blockNumber: number): Promise<bigint> {
35
- return new Promise((resolve, reject) => {
36
- let blocks = pending.get(chainId);
37
- if (!blocks) {
38
- blocks = new Map();
39
- pending.set(chainId, blocks);
40
- }
41
- const waiters = blocks.get(blockNumber);
42
- if (waiters) {
43
- waiters.push({ resolve, reject });
44
- } else {
45
- blocks.set(blockNumber, [{ resolve, reject }]);
46
- }
47
-
48
- if (!flushScheduled) {
49
- flushScheduled = true;
50
- queueMicrotask(() => {
51
- flushScheduled = false;
52
- const collected = pending;
53
- pending = new Map();
54
- for (const [chain, blocksForChain] of collected) {
55
- void answer(chain, blocksForChain);
56
- }
57
- });
58
- }
59
- });
60
- }
61
-
62
- /**
63
- * Gaps narrower than one response's worth of headers are fetched through
64
- * rather than split: a polling handler every few blocks is one query, one
65
- * every 100,000 is one tiny query per block.
66
- */
67
- const CLUSTER_GAP = 10_000;
68
-
69
- /** The requested blocks as `[from, to]` ranges, in order. */
70
- function clusters(blockNumbers: number[]): [number, number][] {
71
- const sorted = [...blockNumbers].sort((a, b) => a - b);
72
- const ranges: [number, number][] = [];
73
- for (const blockNumber of sorted) {
74
- const last = ranges[ranges.length - 1];
75
- if (last && blockNumber - last[1] <= CLUSTER_GAP) last[1] = blockNumber;
76
- else ranges.push([blockNumber, blockNumber]);
77
- }
78
- return ranges;
79
- }
80
-
81
- async function answer(chainId: number, blocks: Map<number, Waiter[]>) {
82
- let timestamps = new Map<number, bigint>();
83
-
84
- try {
85
- const fetched = await Promise.all(
86
- clusters([...blocks.keys()]).map(([from, to]) => fromHyperSync(chainId, from, to)),
87
- );
88
- timestamps = new Map(fetched.flatMap((cluster) => [...cluster]));
89
- } catch (error) {
90
- if (rpcUrls.length === 0) {
91
- const message = error instanceof Error ? error.message : String(error);
92
- for (const waiters of blocks.values()) {
93
- for (const waiter of waiters) {
94
- waiter.reject(
95
- new Error(
96
- `Envio Subgraph couldn't read a block timestamp from HyperSync: ${message}\n` +
97
- `Set ${API_TOKEN_ENV_VAR} in .env or the environment — create one at\n` +
98
- `https://envio.dev/app/api-tokens — or set ENVIO_SUBGRAPH_RPC to fall back to RPC.`,
99
- ),
100
- );
101
- }
102
- }
103
- return;
104
- }
105
- }
106
-
107
- for (const [blockNumber, waiters] of blocks) {
108
- const known = timestamps.get(blockNumber);
109
- if (known !== undefined) {
110
- for (const waiter of waiters) waiter.resolve(known);
111
- continue;
112
- }
113
- try {
114
- const timestamp = await fromRpc(blockNumber);
115
- for (const waiter of waiters) waiter.resolve(timestamp);
116
- } catch (error) {
117
- for (const waiter of waiters) waiter.reject(error);
118
- }
119
- }
120
- }
121
-
122
- type HyperSyncResponse = {
123
- data: { blocks?: { number: number; timestamp: string }[] }[];
124
- next_block: number;
125
- };
126
-
127
- async function fromHyperSync(
128
- chainId: number,
129
- fromBlock: number,
130
- toBlock: number,
131
- ): Promise<Map<number, bigint>> {
132
- const token = process.env[API_TOKEN_ENV_VAR];
133
- const timestamps = new Map<number, bigint>();
134
-
135
- let cursor = fromBlock;
136
- // HyperSync answers as much of the range as one response holds and points at
137
- // where to resume, so a wide range takes more than one round trip.
138
- while (cursor <= toBlock) {
139
- const response = await fetch(hypersyncUrl(chainId), {
140
- method: "POST",
141
- headers: {
142
- "content-type": "application/json",
143
- ...(token ? { authorization: `Bearer ${token}` } : {}),
144
- },
145
- body: JSON.stringify({
146
- from_block: cursor,
147
- to_block: toBlock + 1,
148
- include_all_blocks: true,
149
- field_selection: { block: ["number", "timestamp"] },
150
- }),
151
- });
152
-
153
- if (!response.ok) {
154
- throw new Error(`HyperSync returned ${response.status} ${await response.text()}`);
155
- }
156
-
157
- const body = (await response.json()) as HyperSyncResponse;
158
- for (const page of body.data ?? []) {
159
- for (const block of page.blocks ?? []) {
160
- timestamps.set(block.number, BigInt(block.timestamp));
161
- }
162
- }
163
-
164
- if (!body.next_block || body.next_block <= cursor) {
165
- break;
166
- }
167
- cursor = body.next_block;
168
- }
169
-
170
- return timestamps;
171
- }
172
-
173
- async function fromRpc(blockNumber: number): Promise<bigint> {
174
- if (rpcUrls.length === 0) {
175
- throw new Error(
176
- `Envio Subgraph couldn't read the timestamp of block ${blockNumber}: HyperSync didn't\n` +
177
- `return it, and no RPC fallback is configured. Set ENVIO_SUBGRAPH_RPC in .env or the\n` +
178
- `environment.`,
179
- );
180
- }
181
- const block = await rpcClient(rpcUrls).getBlock({ blockNumber: BigInt(blockNumber) });
182
- return block.timestamp;
183
- }
@@ -1,149 +0,0 @@
1
- /**
2
- * `Contract.bind(x).foo()` -> an envio effect over viem.
3
- *
4
- * graph-node evaluates a mapping's contract calls against the block the event
5
- * came from, so the block number is part of the effect's input — and therefore
6
- * of its cache key, which is what makes a cached call safe to reuse.
7
- */
8
-
9
- import { decodeFunctionResult, encodeFunctionData, parseAbiParameters, type Abi } from "viem";
10
- import * as Sury from "rescript-schema";
11
- import { createEffect } from "../Envio.res.mjs";
12
- import { missingRpcMessage } from "./errors.ts";
13
- import { rpcClient } from "./rpc.ts";
14
- import { parseSignature } from "./abi-types.ts";
15
-
16
- export function abiItemFor(signature: string): Abi {
17
- const { name, inputs, outputs } = parseSignature(signature);
18
- return [
19
- {
20
- type: "function",
21
- name,
22
- stateMutability: "view",
23
- inputs: inputs.trim() === "" ? [] : [...parseAbiParameters(inputs)],
24
- outputs: outputs.trim() === "" ? [] : [...parseAbiParameters(outputs)],
25
- },
26
- ] as Abi;
27
- }
28
-
29
- /**
30
- * A revert is data: the mapping's `try_` sees `{reverted: true}`. A transport
31
- * failure is not — it throws as the handler error so envio retries, and a flaky
32
- * RPC never fabricates reverted data.
33
- */
34
- export function isRevert(error: unknown): boolean {
35
- const parts: string[] = [];
36
- let current: any = error;
37
- for (let depth = 0; current && depth < 10; depth++) {
38
- parts.push(current.name, current.shortMessage, current.details, current.message);
39
- current = current.cause;
40
- }
41
- const text = parts.filter(Boolean).join(" | ");
42
-
43
- if (/revert|ContractFunctionZeroDataError|invalid opcode|out of gas/i.test(text)) {
44
- return true;
45
- }
46
- return false;
47
- }
48
-
49
- export type CallInput = {
50
- chainId: number;
51
- address: string;
52
- signature: string;
53
- args: unknown[];
54
- blockNumber: number;
55
- };
56
-
57
- export type CallOutput = {
58
- reverted: boolean;
59
- values: unknown[] | null;
60
- };
61
-
62
- /**
63
- * BigInt and Bytes cross the effect boundary through Sury, which needs a
64
- * serialisable shape — so the call is described in plain JSON and the graph-ts
65
- * values are converted on both sides by the shim.
66
- */
67
- export function makeCallEffect(rpcUrls: string[]) {
68
- return createEffect(
69
- {
70
- name: "envio_subgraph_eth_call",
71
- // Both sides travel as JSON text: the cache key is then the exact call
72
- // description, and the cached row is readable.
73
- input: Sury.string,
74
- output: Sury.string,
75
- rateLimit: false,
76
- cache: true,
77
- crossChain: false,
78
- },
79
- async ({ input: encoded }: { input: string }) => {
80
- const input = JSON.parse(encoded) as CallInput;
81
- if (rpcUrls.length === 0) {
82
- throw new Error(missingRpcMessage(input.signature));
83
- }
84
- const abi = abiItemFor(input.signature);
85
- const { name } = parseSignature(input.signature);
86
- const data = encodeFunctionData({
87
- abi,
88
- functionName: name,
89
- args: input.args.map(decodeArg),
90
- });
91
-
92
- let result;
93
- try {
94
- result = await rpcClient(rpcUrls).call({
95
- to: input.address as `0x${string}`,
96
- data,
97
- blockNumber: BigInt(input.blockNumber),
98
- });
99
- } catch (error) {
100
- if (isRevert(error)) {
101
- return JSON.stringify({ reverted: true, values: null });
102
- }
103
- throw error;
104
- }
105
-
106
- try {
107
- const decoded = decodeFunctionResult({
108
- abi,
109
- functionName: name,
110
- data: (result.data ?? "0x") as `0x${string}`,
111
- });
112
- // graph-ts returns one `ethereum.Value` per ABI output. A single
113
- // tuple/struct is therefore `[tuple]`, not the flattened fields —
114
- // generated bindings call `result[0].toTuple()`.
115
- const outputs = (abi[0] as { outputs?: unknown[] }).outputs ?? [];
116
- const values = outputs.length === 1 ? [decoded] : Array.isArray(decoded) ? decoded : [decoded];
117
- return JSON.stringify({ reverted: false, values: values.map(encodeArg) });
118
- } catch {
119
- // Output the declared signature can't decode counts as a failed call,
120
- // which is what lets a mapping retry through a different ABI — the
121
- // bytes32-vs-string ERC20 name is the case every token subgraph hits.
122
- return JSON.stringify({ reverted: true, values: null });
123
- }
124
- },
125
- );
126
- }
127
-
128
- /** Effect inputs/outputs travel as strings, tagged so the type survives. */
129
- export function encodeArg(value: unknown): string {
130
- if (typeof value === "bigint") return `i:${value.toString()}`;
131
- if (typeof value === "boolean") return `b:${value ? "1" : "0"}`;
132
- if (Array.isArray(value)) return `a:${JSON.stringify(value.map(encodeArg))}`;
133
- return `s:${String(value)}`;
134
- }
135
-
136
- export function decodeArg(value: string): unknown {
137
- const tag = value.slice(0, 2);
138
- const body = value.slice(2);
139
- switch (tag) {
140
- case "i:":
141
- return BigInt(body);
142
- case "b:":
143
- return body === "1";
144
- case "a:":
145
- return (JSON.parse(body) as string[]).map(decodeArg);
146
- default:
147
- return body;
148
- }
149
- }
@@ -1,83 +0,0 @@
1
- /**
2
- * The shim, checked against the types a subgraph developer codes against.
3
- *
4
- * A subgraph's mappings are type-checked by `asc` against
5
- * `@graphprotocol/graph-ts`, and then run by this shim. Nothing else makes the
6
- * two agree, so a gap shows up as green types and a runtime error — the worst
7
- * feedback loop there is. This file closes it.
8
- *
9
- * The declarations come from the real package (see
10
- * `scripts/generate-graph-ts-types.mjs`). Every export is walked, and within
11
- * each class and namespace every static and every instance member, so a gap is
12
- * named down to the member — `ethereum.Value.fromAddress` — rather than hidden
13
- * behind a suppression covering a whole namespace. This file is type-checked,
14
- * never run.
15
- */
16
-
17
- import type * as GraphTs from "./graph-ts-types/index.js";
18
- import type * as Shim from "./graph-ts.ts";
19
-
20
- /** A class's statics: a mapped type drops the construct signature. */
21
- type Statics<T> = { [K in keyof T as K extends "prototype" ? never : K]: T[K] };
22
-
23
- type Agrees<Real, Ours, Path extends string> = [Ours] extends [Real] ? never : Path;
24
-
25
- /**
26
- * Deep enough to reach `ethereum.Value.fromAddress`, and no deeper: a member
27
- * past that is compared whole, which still catches any disagreement inside it.
28
- */
29
- type Member<Real, Ours, Path extends string, Depth extends unknown[]> = Depth["length"] extends 2
30
- ? Agrees<Real, Ours, Path>
31
- : // `any` would take every branch below at once.
32
- 0 extends 1 & Real
33
- ? Agrees<Real, Ours, Path>
34
- : // Bracketed so a union — an enum, `boolean` — is compared whole.
35
- [Real] extends [(...args: any) => any]
36
- ? Agrees<Real, Ours, Path>
37
- : // A class, even one whose constructor is protected.
38
- [Real] extends [{ prototype: infer RealInstance }]
39
- ? [Ours] extends [{ prototype: infer OursInstance }]
40
- ?
41
- | Gaps<Statics<Real>, Statics<Ours>, `${Path}.`, [...Depth, unknown]>
42
- | Gaps<RealInstance, OursInstance, `${Path}#`, [...Depth, unknown]>
43
- : Path
44
- : [Real] extends [object]
45
- ? Gaps<Real, Ours, `${Path}.`, [...Depth, unknown]>
46
- : Agrees<Real, Ours, Path>;
47
-
48
- /** Where `Ours` lacks or disagrees with `Real`, by path. */
49
- type Gaps<Real, Ours, Path extends string, Depth extends unknown[] = []> = {
50
- [K in keyof Real & string]-?: K extends keyof Ours
51
- ? Member<Real[K], Ours[K], `${Path}${K}`, Depth>
52
- : `${Path}${K}`;
53
- }[keyof Real & string];
54
-
55
- type Found = Gaps<typeof GraphTs, typeof Shim, "">;
56
-
57
- /** Every gap the shim knows it has, and why. */
58
- type KnownGap =
59
- // Chains envio doesn't index in subgraph mode.
60
- | "cosmos"
61
- | "near"
62
- | "starknet"
63
- | "Felt"
64
- | "arweave.Block"
65
- | "arweave.ProofOfAccess"
66
- | "arweave.Tag"
67
- | "arweave.Transaction"
68
- | "arweave.TransactionWithBlockPtr"
69
- // Refused at runtime: a YAML parser isn't shipped with the shim.
70
- | `yaml.${string}`
71
- | `YAMLValue${string}`
72
- | `YAMLTaggedValue${string}`
73
- // graph-ts declares `CallResult._value` private, which no other declaration
74
- // can match; the shim's is structurally the same.
75
- | "ethereum.CallResult.fromValue"
76
- | "ethereum.SmartContract#tryCall";
77
-
78
- /** A known gap no longer found, whose entry should go. */
79
- type Closed<Gap> = Gap extends unknown ? ([Extract<Found, Gap>] extends [never] ? Gap : never) : never;
80
-
81
- // Keyed so a failure lists each path as a missing property.
82
- export const unlisted: Record<Exclude<Found, KnownGap>, "a gap KnownGap doesn't list"> = {};
83
- export const closed: Record<Closed<KnownGap>, "a KnownGap entry that no longer applies"> = {};
@@ -1,96 +0,0 @@
1
- const ISSUES_URL = "https://github.com/enviodev/hyperindex/issues";
2
-
3
- /**
4
- * Subgraph mode ships under its own npm dist-tag (see `publish.yml`), so
5
- * `envio@latest` would move a project off it.
6
- */
7
- const UPGRADE_COMMAND = "pnpm add -D envio@subgraph";
8
-
9
- /** A feature we recognise and deliberately don't implement. */
10
- export function unsupported(feature: string, location: string): Error {
11
- return new Error(
12
- `Envio Subgraph doesn't support ${feature} yet.\n` +
13
- ` Found in ${location}.\n` +
14
- `First, make sure you're on the newest Envio Subgraph release — support may have landed:\n` +
15
- ` ${UPGRADE_COMMAND}\n` +
16
- `If you're up to date and need this feature, please open an issue (existing\n` +
17
- `issues welcome a 👍 — demand drives prioritization):\n ${ISSUES_URL}`,
18
- );
19
- }
20
-
21
- /** Something we don't recognise at all: newer than us, or a typo. */
22
- export function unknown(thing: string, location: string): Error {
23
- return new Error(
24
- `Envio Subgraph doesn't know ${thing}.\n` +
25
- ` Found in ${location}.\n` +
26
- `This may be a feature newer than this envio version understands, or a typo.\n` +
27
- `First, make sure you're on the newest Envio Subgraph release:\n` +
28
- ` ${UPGRADE_COMMAND}\n` +
29
- `If you're up to date and this is a real subgraph feature, please open an\n` +
30
- `issue so we can add it: ${ISSUES_URL}`,
31
- );
32
- }
33
-
34
- const RPC_ENV_VAR = "ENVIO_SUBGRAPH_RPC";
35
-
36
- /** §6b: contract calls need an endpoint HyperSync and HyperRPC don't serve. */
37
- export function missingRpcMessage(callSite: string): string {
38
- return (
39
- `This subgraph performs contract calls (${callSite}), which need an\n` +
40
- `RPC endpoint — HyperSync and HyperRPC serve logs and blocks, not eth_call.\n` +
41
- `Set one in .env or the environment:\n` +
42
- ` ${RPC_ENV_VAR}=https://...\n` +
43
- `Advanced (matches envio's rpc config; single entry or array):\n` +
44
- ` ${RPC_ENV_VAR}={"url":"https://...","for":"fallback","headers":{...}}`
45
- );
46
- }
47
-
48
- /**
49
- * Names a trap must answer for rather than refuse. AS-compiled mappings never
50
- * feature-detect, so nothing legitimate reaches these — but `console.log`,
51
- * `await` and `JSON.stringify` do, and they must not explode.
52
- */
53
- const PASSTHROUGH = new Set([
54
- "then",
55
- "toJSON",
56
- "constructor",
57
- "valueOf",
58
- "toString",
59
- "inspect",
60
- "nodeType",
61
- "$$typeof",
62
- "@@__IMMUTABLE_ITERABLE__@@",
63
- ]);
64
-
65
- function isPassthrough(prop: PropertyKey): boolean {
66
- return typeof prop === "symbol" || PASSTHROUGH.has(prop as string);
67
- }
68
-
69
- export const PROTOTYPE_PASSTHROUGH = PASSTHROUGH;
70
-
71
- /**
72
- * Full Proxy for a graph-ts namespace object. Future graph-ts APIs are
73
- * unenumerable, so only a `get` trap can catch them; these are cold paths, so
74
- * the trap cost doesn't matter.
75
- */
76
- export function strictNamespace<T extends object>(name: string, target: T): T {
77
- return new Proxy(target, {
78
- get(target, prop, receiver) {
79
- if (prop in target || isPassthrough(prop)) {
80
- return Reflect.get(target, prop, receiver);
81
- }
82
- throw unknown(`the graph-ts API ${name}.${String(prop)}`, `a mapping handler`);
83
- },
84
- });
85
- }
86
-
87
- /** A known-but-refused field: enumerable, so a plain throwing getter is enough. */
88
- export function refusedGetter(object: object, prop: string, feature: string, location: string) {
89
- Object.defineProperty(object, prop, {
90
- enumerable: true,
91
- configurable: true,
92
- get() {
93
- throw unsupported(feature, location);
94
- },
95
- });
96
- }
@@ -1,26 +0,0 @@
1
- // Runs one graph-cli command, as its own bin would, on the thread
2
- // `graph-cli.ts` sized for it. Plain JavaScript: the TypeScript loader envio
3
- // registers doesn't reach worker threads.
4
- import { parentPort, workerData } from "node:worker_threads";
5
- import path from "node:path";
6
- import { pathToFileURL } from "node:url";
7
-
8
- const { packageDir, command, argv } = workerData;
9
-
10
- let ok = true;
11
- try {
12
- const { default: Command } = await import(
13
- pathToFileURL(path.join(packageDir, "dist", "commands", `${command}.js`)).href
14
- );
15
- await Command.run(argv, packageDir);
16
- // A generation failure is reported through the exit code, not a throw.
17
- ok = process.exitCode === undefined || process.exitCode === 0;
18
- } catch (error) {
19
- // oclif ends a successful command early by throwing an exit of 0.
20
- if (error?.oclif?.exit !== 0) {
21
- console.error(error?.message ?? error);
22
- ok = false;
23
- }
24
- }
25
- process.exitCode = 0;
26
- parentPort.postMessage(ok);