@secondlayer/subgraphs 4.4.1 → 5.0.0
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/README.md +13 -21
- package/dist/{src/index.d.ts → index.d.ts} +59 -189
- package/dist/index.js +2151 -0
- package/dist/index.js.map +24 -0
- package/dist/{src/runtime → runtime}/emitter.d.ts +1 -1
- package/dist/{src/runtime → runtime}/emitter.js +8 -12
- package/dist/{src/runtime → runtime}/emitter.js.map +3 -3
- package/dist/{src/runtime → runtime}/replay.d.ts +1 -1
- package/dist/{src/runtime → runtime}/replay.js +342 -683
- package/dist/{src/runtime → runtime}/replay.js.map +5 -5
- package/dist/{src/schema → schema}/index.d.ts +10 -69
- package/dist/{src/schema → schema}/index.js +188 -281
- package/dist/schema/index.js.map +13 -0
- package/dist/{src/testing → testing}/index.d.ts +65 -115
- package/dist/{src/testing → testing}/index.js +554 -968
- package/dist/testing/index.js.map +21 -0
- package/dist/{src/types.d.ts → types.d.ts} +10 -66
- package/dist/{src/validate.d.ts → validate.d.ts} +11 -69
- package/dist/{src/validate.js → validate.js} +18 -98
- package/dist/validate.js.map +10 -0
- package/package.json +18 -26
- package/dist/src/index.js +0 -6081
- package/dist/src/index.js.map +0 -44
- package/dist/src/runtime/block-processor.d.ts +0 -559
- package/dist/src/runtime/block-processor.js +0 -3810
- package/dist/src/runtime/block-processor.js.map +0 -31
- package/dist/src/runtime/catchup.d.ts +0 -473
- package/dist/src/runtime/catchup.js +0 -4228
- package/dist/src/runtime/catchup.js.map +0 -35
- package/dist/src/runtime/clarity.d.ts +0 -15
- package/dist/src/runtime/clarity.js +0 -41
- package/dist/src/runtime/clarity.js.map +0 -10
- package/dist/src/runtime/context.d.ts +0 -325
- package/dist/src/runtime/context.js +0 -936
- package/dist/src/runtime/context.js.map +0 -13
- package/dist/src/runtime/processor.d.ts +0 -11
- package/dist/src/runtime/processor.js +0 -5372
- package/dist/src/runtime/processor.js.map +0 -40
- package/dist/src/runtime/reindex.d.ts +0 -539
- package/dist/src/runtime/reindex.js +0 -4802
- package/dist/src/runtime/reindex.js.map +0 -37
- package/dist/src/runtime/reorg.d.ts +0 -432
- package/dist/src/runtime/reorg.js +0 -4355
- package/dist/src/runtime/reorg.js.map +0 -36
- package/dist/src/runtime/runner.d.ts +0 -719
- package/dist/src/runtime/runner.js +0 -1332
- package/dist/src/runtime/runner.js.map +0 -16
- package/dist/src/runtime/source-matcher.d.ts +0 -304
- package/dist/src/runtime/source-matcher.js +0 -335
- package/dist/src/runtime/source-matcher.js.map +0 -10
- package/dist/src/runtime/stats.d.ts +0 -23
- package/dist/src/runtime/stats.js +0 -71
- package/dist/src/runtime/stats.js.map +0 -10
- package/dist/src/schema/index.js.map +0 -13
- package/dist/src/service.d.ts +0 -0
- package/dist/src/service.js +0 -5398
- package/dist/src/service.js.map +0 -41
- package/dist/src/testing/index.js.map +0 -22
- package/dist/src/triggers/index.d.ts +0 -381
- package/dist/src/triggers/index.js +0 -31
- package/dist/src/triggers/index.js.map +0 -10
- package/dist/src/validate.js.map +0 -10
- /package/dist/{src/types.js → types.js} +0 -0
- /package/dist/{src/types.js.map → types.js.map} +0 -0
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decode a hex-encoded Clarity value to a JS object.
|
|
3
|
-
* Returns original value on failure.
|
|
4
|
-
*/
|
|
5
|
-
declare function decodeClarityValue(hex: string): unknown;
|
|
6
|
-
/**
|
|
7
|
-
* Recursively decode all hex-encoded Clarity values in an object.
|
|
8
|
-
* Any string starting with "0x" and longer than 10 chars is attempted.
|
|
9
|
-
*/
|
|
10
|
-
declare function decodeEventData(data: unknown): unknown;
|
|
11
|
-
/**
|
|
12
|
-
* Decode function args array (hex-encoded Clarity values).
|
|
13
|
-
*/
|
|
14
|
-
declare function decodeFunctionArgs(args: string[]): unknown[];
|
|
15
|
-
export { decodeFunctionArgs, decodeEventData, decodeClarityValue };
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
// src/runtime/clarity.ts
|
|
5
|
-
import { cvToValue, deserializeCV } from "@secondlayer/stacks/clarity";
|
|
6
|
-
function decodeClarityValue(hex) {
|
|
7
|
-
try {
|
|
8
|
-
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
9
|
-
const cv = deserializeCV(cleanHex);
|
|
10
|
-
return cvToValue(cv);
|
|
11
|
-
} catch {
|
|
12
|
-
return hex;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function decodeEventData(data) {
|
|
16
|
-
if (typeof data === "string" && data.startsWith("0x") && data.length > 10) {
|
|
17
|
-
return decodeClarityValue(data);
|
|
18
|
-
}
|
|
19
|
-
if (Array.isArray(data)) {
|
|
20
|
-
return data.map(decodeEventData);
|
|
21
|
-
}
|
|
22
|
-
if (typeof data === "object" && data !== null) {
|
|
23
|
-
const decoded = {};
|
|
24
|
-
for (const [key, value] of Object.entries(data)) {
|
|
25
|
-
decoded[key] = decodeEventData(value);
|
|
26
|
-
}
|
|
27
|
-
return decoded;
|
|
28
|
-
}
|
|
29
|
-
return data;
|
|
30
|
-
}
|
|
31
|
-
function decodeFunctionArgs(args) {
|
|
32
|
-
return args.map(decodeClarityValue);
|
|
33
|
-
}
|
|
34
|
-
export {
|
|
35
|
-
decodeFunctionArgs,
|
|
36
|
-
decodeEventData,
|
|
37
|
-
decodeClarityValue
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
//# debugId=27ED3AEA8666AA8C64756E2164756E21
|
|
41
|
-
//# sourceMappingURL=clarity.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/runtime/clarity.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { cvToValue, deserializeCV } from \"@secondlayer/stacks/clarity\";\n\n/**\n * Decode a hex-encoded Clarity value to a JS object.\n * Returns original value on failure.\n */\nexport function decodeClarityValue(hex: string): unknown {\n\ttry {\n\t\tconst cleanHex = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n\t\tconst cv = deserializeCV(cleanHex);\n\t\treturn cvToValue(cv);\n\t} catch {\n\t\treturn hex;\n\t}\n}\n\n/**\n * Recursively decode all hex-encoded Clarity values in an object.\n * Any string starting with \"0x\" and longer than 10 chars is attempted.\n */\nexport function decodeEventData(data: unknown): unknown {\n\tif (typeof data === \"string\" && data.startsWith(\"0x\") && data.length > 10) {\n\t\treturn decodeClarityValue(data);\n\t}\n\n\tif (Array.isArray(data)) {\n\t\treturn data.map(decodeEventData);\n\t}\n\n\tif (typeof data === \"object\" && data !== null) {\n\t\tconst decoded: Record<string, unknown> = {};\n\t\tfor (const [key, value] of Object.entries(data)) {\n\t\t\tdecoded[key] = decodeEventData(value);\n\t\t}\n\t\treturn decoded;\n\t}\n\n\treturn data;\n}\n\n/**\n * Decode function args array (hex-encoded Clarity values).\n */\nexport function decodeFunctionArgs(args: string[]): unknown[] {\n\treturn args.map(decodeClarityValue);\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;;AAAA;AAMO,SAAS,kBAAkB,CAAC,KAAsB;AAAA,EACxD,IAAI;AAAA,IACH,MAAM,WAAW,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI;AAAA,IACvD,MAAM,KAAK,cAAc,QAAQ;AAAA,IACjC,OAAO,UAAU,EAAE;AAAA,IAClB,MAAM;AAAA,IACP,OAAO;AAAA;AAAA;AAQF,SAAS,eAAe,CAAC,MAAwB;AAAA,EACvD,IAAI,OAAO,SAAS,YAAY,KAAK,WAAW,IAAI,KAAK,KAAK,SAAS,IAAI;AAAA,IAC1E,OAAO,mBAAmB,IAAI;AAAA,EAC/B;AAAA,EAEA,IAAI,MAAM,QAAQ,IAAI,GAAG;AAAA,IACxB,OAAO,KAAK,IAAI,eAAe;AAAA,EAChC;AAAA,EAEA,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAAA,IAC9C,MAAM,UAAmC,CAAC;AAAA,IAC1C,YAAY,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG;AAAA,MAChD,QAAQ,OAAO,gBAAgB,KAAK;AAAA,IACrC;AAAA,IACA,OAAO;AAAA,EACR;AAAA,EAEA,OAAO;AAAA;AAMD,SAAS,kBAAkB,CAAC,MAA2B;AAAA,EAC7D,OAAO,KAAK,IAAI,kBAAkB;AAAA;",
|
|
8
|
-
"debugId": "27ED3AEA8666AA8C64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
import { UnwrapResponse } from "@secondlayer/stacks/actions";
|
|
2
|
-
import { AbiContract, ExtractFunctionArgs, ExtractFunctionOutput, ExtractReadOnlyFunctions, ToCamelCase } from "@secondlayer/stacks/clarity";
|
|
3
|
-
/**
|
|
4
|
-
* How long a read stays valid.
|
|
5
|
-
*
|
|
6
|
-
* - `per-block` (default): pinned to the block being processed, cached under
|
|
7
|
-
* its `index_block_hash`. Sound for any read-only function — reindexing the
|
|
8
|
-
* same block always returns the same value, and a reorg-replaced block has a
|
|
9
|
-
* different id so it can't inherit the orphaned answer.
|
|
10
|
-
* - `contract-constant`: the caller asserts the value cannot change for this
|
|
11
|
-
* contract and these args (SIP-010 `get-decimals`/`get-symbol`), so it is
|
|
12
|
-
* resolved ONCE instead of once per block. This is the mode that makes a
|
|
13
|
-
* backfill affordable — under `per-block` every block is a distinct key and
|
|
14
|
-
* therefore a distinct RPC. Declaring it on a value that does change pins the
|
|
15
|
-
* first answer forever, so it is opt-in and never inferred.
|
|
16
|
-
*/
|
|
17
|
-
type ChainReadCacheMode = "per-block" | "contract-constant";
|
|
18
|
-
type ChainReadOptions = {
|
|
19
|
-
cache?: ChainReadCacheMode
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* The chain-read surface, fully typed by an ABI.
|
|
23
|
-
*
|
|
24
|
-
* Shaped like `getContract` from `@secondlayer/stacks` — the same ABI in, the
|
|
25
|
-
* same camelCased read methods out — minus `call`/`buildCall`: a handler
|
|
26
|
-
* indexes the chain, it never writes to it.
|
|
27
|
-
*
|
|
28
|
-
* Reached through {@link readContractAt} rather than off `ctx.client`
|
|
29
|
-
* directly: an ABI-generic method living on the context interface makes every
|
|
30
|
-
* structural comparison of a subgraph definition instantiate it, which exceeds
|
|
31
|
-
* TS's depth budget. At a call site the ABI is already concrete and it costs
|
|
32
|
-
* nothing.
|
|
33
|
-
*/
|
|
34
|
-
interface ChainReadClient {
|
|
35
|
-
/**
|
|
36
|
-
* Read-only methods of a contract, evaluated against the exact block being
|
|
37
|
-
* processed.
|
|
38
|
-
*
|
|
39
|
-
* Every call is pinned to the block's `index_block_hash`, so a handler is a
|
|
40
|
-
* pure function of its block: reindexing a range produces byte-identical
|
|
41
|
-
* rows. Reading at the node's tip instead would make the same reindex
|
|
42
|
-
* return different values — that is the corruption this refuses to allow,
|
|
43
|
-
* so a block whose id was never persisted throws rather than falling back.
|
|
44
|
-
*
|
|
45
|
-
* Results are memoized in Postgres, so a value is fetched once per block
|
|
46
|
-
* rather than once per event (or once per contract with
|
|
47
|
-
* `cache: "contract-constant"`).
|
|
48
|
-
*/
|
|
49
|
-
contract<const C extends AbiContract>(contractId: string, abi: C, options?: ChainReadOptions): {
|
|
50
|
-
read: ChainReadMethods<C>
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* True for a structural empty mapped type (`{}`) and for codegen's
|
|
55
|
-
* `Record<string, never>`. `keyof Record<string, never>` is `string`, so the
|
|
56
|
-
* first check alone is not enough. Local copy of the `getContract` helper —
|
|
57
|
-
* importing `ContractInstance<C>["read"]` would re-enter the codegen-brand
|
|
58
|
-
* conditional this type exists to avoid.
|
|
59
|
-
*/
|
|
60
|
-
type IsEmptyArgs<A> = [keyof A & string] extends [never] ? true : Record<string, never> extends A ? true : false;
|
|
61
|
-
type ChainReadMethod<
|
|
62
|
-
A,
|
|
63
|
-
R
|
|
64
|
-
> = IsEmptyArgs<A> extends true ? (args?: A) => R : (args: A) => R;
|
|
65
|
-
/**
|
|
66
|
-
* The camelCased read methods of an ABI. Spelled out rather than reused from
|
|
67
|
-
* `ContractInstance<C>["read"]`: that type is a conditional over the codegen
|
|
68
|
-
* brand, and evaluating it wherever a subgraph definition is structurally
|
|
69
|
-
* compared pushes TS past its instantiation depth.
|
|
70
|
-
*/
|
|
71
|
-
type ChainReadMethods<C extends AbiContract> = { [N in ExtractReadOnlyFunctions<C> as ToCamelCase<N>] : ChainReadMethod<ExtractFunctionArgs<C, N>, Promise<UnwrapResponse<ExtractFunctionOutput<C, N>>>> };
|
|
72
|
-
/** Supported column types for subgraph schemas */
|
|
73
|
-
type ColumnType = "text" | "uint" | "int" | "principal" | "boolean" | "timestamp" | "jsonb";
|
|
74
|
-
/** Column definition in a subgraph table */
|
|
75
|
-
interface SubgraphColumn {
|
|
76
|
-
type: ColumnType;
|
|
77
|
-
nullable?: boolean;
|
|
78
|
-
indexed?: boolean;
|
|
79
|
-
search?: boolean;
|
|
80
|
-
default?: string | number | boolean;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* A foreign-key relation to another table in the same subgraph. Drives DDL FK
|
|
84
|
-
* constraints and ORM codegen (`@relation` in Prisma, `relations()` in Drizzle)
|
|
85
|
-
* so generated clients get typed joins. The referenced columns must form a
|
|
86
|
-
* `uniqueKeys` entry on the target table.
|
|
87
|
-
*/
|
|
88
|
-
interface SubgraphRelation {
|
|
89
|
-
/** Relation field name on this table's generated model (e.g. "pool"). */
|
|
90
|
-
name: string;
|
|
91
|
-
/** Target table name in this subgraph. */
|
|
92
|
-
references: string;
|
|
93
|
-
/** Local column(s) holding the foreign key. */
|
|
94
|
-
fields: string[];
|
|
95
|
-
/** Target column(s) the fields point at (a uniqueKeys entry on the target). */
|
|
96
|
-
referencedColumns: string[];
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Table definition within a subgraph schema.
|
|
100
|
-
*
|
|
101
|
-
* The array fields are `readonly` so a schema literal can be hoisted out of
|
|
102
|
-
* the `defineSubgraph()` call with `as const` (or {@link defineSchema}) and
|
|
103
|
-
* still typecheck — `as const` produces `readonly [readonly ["holder"]]`,
|
|
104
|
-
* which a mutable `string[][]` rejects. Without that, extracting a helper
|
|
105
|
-
* that takes `ctx` meant losing the entire typed surface, which is why the
|
|
106
|
-
* shipped starter reached for `ctx: any`.
|
|
107
|
-
*/
|
|
108
|
-
interface SubgraphTable {
|
|
109
|
-
columns: Record<string, SubgraphColumn>;
|
|
110
|
-
/** Composite indexes (each entry is an array of column names) */
|
|
111
|
-
indexes?: readonly (readonly string[])[];
|
|
112
|
-
/** Unique key constraints (each entry is an array of column names). Required for upsert. */
|
|
113
|
-
uniqueKeys?: readonly (readonly string[])[];
|
|
114
|
-
/** Foreign-key relations to other tables (for typed ORM joins). */
|
|
115
|
-
relations?: readonly SubgraphRelation[];
|
|
116
|
-
}
|
|
117
|
-
/** Subgraph schema — maps table names to table definitions */
|
|
118
|
-
type SubgraphSchema = Record<string, SubgraphTable>;
|
|
119
|
-
/** Scalar types that can appear as row values */
|
|
120
|
-
type RowValue = string | number | bigint | boolean | null | undefined | Record<string, unknown> | unknown[];
|
|
121
|
-
/** Value or computed function that receives existing row */
|
|
122
|
-
type ComputedValue = RowValue | ((existing: Record<string, unknown> | null) => unknown);
|
|
123
|
-
import { Database as Database2 } from "@secondlayer/shared/db";
|
|
124
|
-
import { Kysely as Kysely2, Transaction } from "kysely";
|
|
125
|
-
type AnyDb = Kysely2<Database2> | Transaction<Database2>;
|
|
126
|
-
/** Reorg journal entries older than this many blocks are prunable — far past
|
|
127
|
-
* Stacks finality (observed reorg depth is single digits). */
|
|
128
|
-
declare const JOURNAL_RETENTION_BLOCKS = 300;
|
|
129
|
-
interface WriteOp {
|
|
130
|
-
kind: "insert" | "update" | "delete" | "increment";
|
|
131
|
-
table: string;
|
|
132
|
-
data: Record<string, unknown>;
|
|
133
|
-
/** For update: SET clause. For increment: column → signed delta. */
|
|
134
|
-
set?: Record<string, unknown>;
|
|
135
|
-
}
|
|
136
|
-
interface FlushWrite {
|
|
137
|
-
op: "insert" | "update" | "delete";
|
|
138
|
-
table: string;
|
|
139
|
-
/** Full row data (for inserts) or where+set merged (for updates). Bigints stringified. */
|
|
140
|
-
row: Record<string, unknown>;
|
|
141
|
-
/** Stable identifier for dedup — `{blockHeight, txId, rowIndex}` */
|
|
142
|
-
pk: {
|
|
143
|
-
blockHeight: number
|
|
144
|
-
txId: string
|
|
145
|
-
rowIndex: number
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
interface FlushManifest {
|
|
149
|
-
count: number;
|
|
150
|
-
writes: FlushWrite[];
|
|
151
|
-
}
|
|
152
|
-
interface BlockMeta {
|
|
153
|
-
height: number;
|
|
154
|
-
hash: string;
|
|
155
|
-
timestamp: number;
|
|
156
|
-
burnBlockHeight: number;
|
|
157
|
-
/**
|
|
158
|
-
* Nakamoto StacksBlockId — the identifier `?tip=` accepts, and the only way
|
|
159
|
-
* to pin a read-only call to THIS block. Null on rows ingested before it
|
|
160
|
-
* was persisted; `ctx.client.readOnly` refuses to run rather than silently
|
|
161
|
-
* reading at the node's tip.
|
|
162
|
-
*/
|
|
163
|
-
indexBlockHash?: string | null;
|
|
164
|
-
}
|
|
165
|
-
interface TxMeta2 {
|
|
166
|
-
txId: string;
|
|
167
|
-
sender: string;
|
|
168
|
-
type: string;
|
|
169
|
-
status: string;
|
|
170
|
-
contractId?: string | null;
|
|
171
|
-
functionName?: string | null;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Runtime context passed to subgraph handlers.
|
|
175
|
-
* Batches writes and flushes them atomically at the end of a block.
|
|
176
|
-
*
|
|
177
|
-
* Row reads (findOne/findMany) are read-your-writes: they overlay the pending
|
|
178
|
-
* ops queue on the DB state, so a handler observes every write queued earlier
|
|
179
|
-
* in the same block. Without this, accumulator patterns (balance = f(existing))
|
|
180
|
-
* silently lose all but the last same-block delta per row (fix-f040 B1).
|
|
181
|
-
* Aggregate reads (count/sum/min/max) remain pre-flush DB state.
|
|
182
|
-
*/
|
|
183
|
-
declare class SubgraphContext2 {
|
|
184
|
-
readonly block: BlockMeta;
|
|
185
|
-
private _tx;
|
|
186
|
-
private readonly db;
|
|
187
|
-
private readonly pgSchemaName;
|
|
188
|
-
private readonly subgraphSchema;
|
|
189
|
-
/** Pending writes for this block. `protected` so the in-memory test
|
|
190
|
-
* context (`@secondlayer/subgraphs/testing`) can materialize them through
|
|
191
|
-
* the SAME overlay this class uses — never a second implementation. */
|
|
192
|
-
protected readonly ops: WriteOp[];
|
|
193
|
-
/**
|
|
194
|
-
* Record pre-images of keyed mutations into the schema's `_journal` so a
|
|
195
|
-
* reorg can restore prior row states (fix-f040 B2). Enabled on the live
|
|
196
|
-
* path only — deep reindex/backfill heights are past finality, and the
|
|
197
|
-
* journal would just be churn the pruner deletes.
|
|
198
|
-
*/
|
|
199
|
-
private readonly journal;
|
|
200
|
-
/** Memoized per block; see the `client` getter. */
|
|
201
|
-
protected _client?: ChainReadClient;
|
|
202
|
-
constructor(db: AnyDb, pgSchemaName: string, subgraphSchema: SubgraphSchema, block: BlockMeta, tx: TxMeta2, journal?: boolean);
|
|
203
|
-
/**
|
|
204
|
-
* Chain reads pinned to THIS block. Lazily built so a handler that never
|
|
205
|
-
* reads never touches the node config, and so the in-memory test context
|
|
206
|
-
* can override it without a node.
|
|
207
|
-
*/
|
|
208
|
-
get client(): ChainReadClient;
|
|
209
|
-
get tx(): TxMeta2;
|
|
210
|
-
/** Update the current transaction context (used by runner between events) */
|
|
211
|
-
setTx(tx: TxMeta2): void;
|
|
212
|
-
insert(table: string, row: Record<string, unknown>): void;
|
|
213
|
-
update(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
|
|
214
|
-
upsert(table: string, key: Record<string, unknown>, row: Record<string, unknown>): void;
|
|
215
|
-
delete(table: string, where: Record<string, unknown>): void;
|
|
216
|
-
/**
|
|
217
|
-
* Atomic counter update — the blessed accumulator primitive. Compiles to
|
|
218
|
-
* `INSERT ... ON CONFLICT (key) DO UPDATE SET col = COALESCE(t.col,0) + delta`,
|
|
219
|
-
* so deltas commute: same-block, replayed-in-order, and concurrent updates
|
|
220
|
-
* all land correctly without read-modify-write. Missing row inserts the
|
|
221
|
-
* delta as the initial value. Requires a uniqueKeys constraint matching
|
|
222
|
-
* `key`; deltas may be negative.
|
|
223
|
-
*/
|
|
224
|
-
increment(table: string, key: Record<string, unknown>, deltas: Record<string, bigint | number>): void;
|
|
225
|
-
/** Current length of the pending-ops queue. Pair with {@link rollbackTo}. */
|
|
226
|
-
opsCheckpoint(): number;
|
|
227
|
-
/**
|
|
228
|
-
* Discard ops queued after a checkpoint. The runner wraps each handler
|
|
229
|
-
* invocation so a thrown handler contributes nothing — without this, a
|
|
230
|
-
* transfer handler that debited then threw flushes a one-sided debit
|
|
231
|
-
* (fix-f040 B6).
|
|
232
|
-
*/
|
|
233
|
-
rollbackTo(checkpoint: number): void;
|
|
234
|
-
/** Partial update — sets only specified fields, preserves everything else */
|
|
235
|
-
patch(table: string, where: Record<string, unknown>, set: Record<string, unknown>): void;
|
|
236
|
-
/**
|
|
237
|
-
* Find-then-merge-or-insert. Values can be functions: (existing) => newValue.
|
|
238
|
-
* Async because it reads existing row first.
|
|
239
|
-
*/
|
|
240
|
-
patchOrInsert(table: string, key: Record<string, unknown>, row: Record<string, ComputedValue>): Promise<void>;
|
|
241
|
-
/** Format a bigint amount with decimal places */
|
|
242
|
-
formatUnits(value: bigint, decimals: number): string;
|
|
243
|
-
/**
|
|
244
|
-
* Committed rows matching `where`, BEFORE the pending-ops overlay. The one
|
|
245
|
-
* seam a different backing store replaces (the in-memory test context);
|
|
246
|
-
* everything above it — validation, overlay, op queueing, flush semantics
|
|
247
|
-
* — stays here so the two can't diverge.
|
|
248
|
-
*/
|
|
249
|
-
protected readRows(table: string, where: Record<string, unknown>, limit?: number): Promise<Record<string, unknown>[]>;
|
|
250
|
-
findOne(table: string, where: Record<string, unknown>): Promise<Record<string, unknown> | null>;
|
|
251
|
-
findMany(table: string, where: Record<string, unknown>): Promise<Record<string, unknown>[]>;
|
|
252
|
-
/**
|
|
253
|
-
* Replay pending ops for `table` over a single DB-read result so reads
|
|
254
|
-
* observe earlier same-block writes. Mirrors flush semantics: upserts
|
|
255
|
-
* merge non-key/non-meta columns, increments add deltas, updates/deletes
|
|
256
|
-
* apply by where-match. Overlaid rows synthesized from pending inserts
|
|
257
|
-
* lack DB-generated columns (_id, _created_at).
|
|
258
|
-
*/
|
|
259
|
-
protected overlayOne(table: string, where: Record<string, unknown>, dbRow: Record<string, unknown> | null): Record<string, unknown> | null;
|
|
260
|
-
protected overlayMany(table: string, where: Record<string, unknown>, dbRows: Record<string, unknown>[]): Record<string, unknown>[];
|
|
261
|
-
/** Apply one pending op to a candidate row state (null = row absent). */
|
|
262
|
-
protected applyOpToRow(op: WriteOp, row: Record<string, unknown> | null, where: Record<string, unknown>): Record<string, unknown> | null;
|
|
263
|
-
count(table: string, where?: Record<string, unknown>): Promise<number>;
|
|
264
|
-
sum(table: string, column: string, where?: Record<string, unknown>): Promise<bigint>;
|
|
265
|
-
min(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
|
|
266
|
-
max(table: string, column: string, where?: Record<string, unknown>): Promise<bigint | null>;
|
|
267
|
-
countDistinct(table: string, column: string, where?: Record<string, unknown>): Promise<number>;
|
|
268
|
-
/** Coerce string values from Postgres back to BigInt for uint/int columns */
|
|
269
|
-
private coerceRow;
|
|
270
|
-
/** Number of pending write operations */
|
|
271
|
-
get pendingOps(): number;
|
|
272
|
-
/**
|
|
273
|
-
* Execute all batched writes in a single transaction.
|
|
274
|
-
* Auto-populates _block_height, _tx_id, _created_at on inserts.
|
|
275
|
-
*
|
|
276
|
-
* Returns a {@link FlushManifest} describing every write so downstream
|
|
277
|
-
* consumers (webhook emitter) can fan out outbox rows atomically
|
|
278
|
-
* with the flush itself.
|
|
279
|
-
*/
|
|
280
|
-
flush(): Promise<FlushManifest>;
|
|
281
|
-
/**
|
|
282
|
-
* Run a built statement list on an open transaction.
|
|
283
|
-
*
|
|
284
|
-
* Plain statements run in order. An increment runs UPDATE-first and then,
|
|
285
|
-
* ONLY if that matched nothing, the guarded INSERT — and if the INSERT also
|
|
286
|
-
* wrote nothing, the UPDATE again.
|
|
287
|
-
*
|
|
288
|
-
* That last step is the whole point. Under READ COMMITTED, two block
|
|
289
|
-
* transactions flushing the same key while the row is absent both see
|
|
290
|
-
* `UPDATE → 0 rows`; the first commits its INSERT, and the second's
|
|
291
|
-
* `WHERE NOT EXISTS` then sees that committed row and inserts nothing. No
|
|
292
|
-
* error, no constraint violation — the second delta was simply dropped.
|
|
293
|
-
* Re-running the UPDATE takes a fresh snapshot that DOES see the winner's
|
|
294
|
-
* row and applies the delta onto it.
|
|
295
|
-
*
|
|
296
|
-
* It cannot double-apply: the retry is reached only when the first UPDATE
|
|
297
|
-
* matched no row AND the INSERT wrote no row, so the delta has not been
|
|
298
|
-
* applied by either.
|
|
299
|
-
*/
|
|
300
|
-
private execStatements;
|
|
301
|
-
/** Prepare a single insert row, returning its data, columns, upsert key for batching. */
|
|
302
|
-
private prepareInsert;
|
|
303
|
-
/**
|
|
304
|
-
* Lazily create `_journal` for schemas deployed before it existed. Cached
|
|
305
|
-
* per process only once CONFIRMED present (to_regclass) — a CREATE issued
|
|
306
|
-
* inside a block tx could roll back with it, so self-created tables are
|
|
307
|
-
* re-verified on the next flush instead of trusted.
|
|
308
|
-
*/
|
|
309
|
-
private ensureJournalTable;
|
|
310
|
-
/** SQL type of a user column (for casting journal key VALUES), if known. */
|
|
311
|
-
private columnSqlType;
|
|
312
|
-
/**
|
|
313
|
-
* Journal pre-images for a keyed batch: one `_journal` row per key with the
|
|
314
|
-
* row's current state (`prev_row`), or NULL when the key doesn't exist yet
|
|
315
|
-
* (the mutation will create it — a revert deletes it). Emitted BEFORE the
|
|
316
|
-
* mutation statement, same transaction.
|
|
317
|
-
*/
|
|
318
|
-
private journalCaptureSQL;
|
|
319
|
-
/** Journal pre-images of rows a where-clause mutation will touch, keyed by `_id`. */
|
|
320
|
-
private journalCaptureByWhereSQL;
|
|
321
|
-
/** Build SQL statements from write ops, batching compatible INSERTs. */
|
|
322
|
-
private buildStatements;
|
|
323
|
-
private validateTable;
|
|
324
|
-
}
|
|
325
|
-
export { TxMeta2 as TxMeta, SubgraphContext2 as SubgraphContext, JOURNAL_RETENTION_BLOCKS, FlushWrite, FlushManifest, BlockMeta };
|