@secondlayer/subgraphs 0.11.1 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/index.js +67 -26
- package/dist/src/index.js.map +4 -4
- package/dist/src/runtime/block-processor.js +36 -21
- package/dist/src/runtime/block-processor.js.map +3 -3
- package/dist/src/runtime/catchup.js +36 -21
- package/dist/src/runtime/catchup.js.map +3 -3
- package/dist/src/runtime/context.js +36 -21
- package/dist/src/runtime/context.js.map +3 -3
- package/dist/src/runtime/processor.js +77 -28
- package/dist/src/runtime/processor.js.map +5 -5
- package/dist/src/runtime/reindex.js +36 -21
- package/dist/src/runtime/reindex.js.map +3 -3
- package/dist/src/runtime/reorg.d.ts +2 -1
- package/dist/src/runtime/reorg.js +37 -22
- package/dist/src/runtime/reorg.js.map +4 -4
- package/dist/src/schema/index.js +32 -6
- package/dist/src/schema/index.js.map +3 -3
- package/dist/src/service.js +77 -28
- package/dist/src/service.js.map +5 -5
- package/package.json +2 -2
package/dist/src/index.js
CHANGED
|
@@ -102,7 +102,11 @@ class SubgraphContext {
|
|
|
102
102
|
}
|
|
103
103
|
insert(table, row) {
|
|
104
104
|
this.validateTable(table);
|
|
105
|
-
this.ops.push({
|
|
105
|
+
this.ops.push({
|
|
106
|
+
kind: "insert",
|
|
107
|
+
table,
|
|
108
|
+
data: { ...row, _block_height: this.block.height, _tx_id: this._tx.txId }
|
|
109
|
+
});
|
|
106
110
|
}
|
|
107
111
|
update(table, where, set) {
|
|
108
112
|
this.validateTable(table);
|
|
@@ -111,13 +115,16 @@ class SubgraphContext {
|
|
|
111
115
|
upsert(table, key, row) {
|
|
112
116
|
this.validateTable(table);
|
|
113
117
|
const tableDef = this.subgraphSchema[table];
|
|
118
|
+
if (!tableDef)
|
|
119
|
+
return;
|
|
114
120
|
const keyColumns = Object.keys(key);
|
|
115
121
|
const hasUniqueConstraint = tableDef.uniqueKeys?.some((uk) => uk.length === keyColumns.length && uk.every((c) => keyColumns.includes(c)));
|
|
122
|
+
const meta = { _block_height: this.block.height, _tx_id: this._tx.txId };
|
|
116
123
|
if (hasUniqueConstraint) {
|
|
117
124
|
this.ops.push({
|
|
118
125
|
kind: "insert",
|
|
119
126
|
table,
|
|
120
|
-
data: { ...key, ...row, _upsert_keys: keyColumns }
|
|
127
|
+
data: { ...key, ...row, ...meta, _upsert_keys: keyColumns }
|
|
121
128
|
});
|
|
122
129
|
} else {
|
|
123
130
|
logger.warn("upsert called without matching uniqueKeys constraint, using fallback", {
|
|
@@ -130,6 +137,7 @@ class SubgraphContext {
|
|
|
130
137
|
data: {
|
|
131
138
|
...key,
|
|
132
139
|
...row,
|
|
140
|
+
...meta,
|
|
133
141
|
_upsert_fallback_keys: keyColumns,
|
|
134
142
|
_upsert_fallback_set: row
|
|
135
143
|
}
|
|
@@ -249,11 +257,13 @@ class SubgraphContext {
|
|
|
249
257
|
prepareInsert(op) {
|
|
250
258
|
const upsertKeys = op.data._upsert_keys;
|
|
251
259
|
const data = { ...op.data };
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
data._block_height
|
|
256
|
-
|
|
260
|
+
data._upsert_keys = undefined;
|
|
261
|
+
data._upsert_fallback_keys = undefined;
|
|
262
|
+
data._upsert_fallback_set = undefined;
|
|
263
|
+
if (!data._block_height)
|
|
264
|
+
data._block_height = this.block.height;
|
|
265
|
+
if (!data._tx_id)
|
|
266
|
+
data._tx_id = this._tx.txId;
|
|
257
267
|
data._created_at = "NOW()";
|
|
258
268
|
const cols = Object.keys(data);
|
|
259
269
|
cols.forEach(validateColumnName);
|
|
@@ -268,11 +278,13 @@ class SubgraphContext {
|
|
|
268
278
|
const flushInsertBatch = () => {
|
|
269
279
|
if (!currentBatch)
|
|
270
280
|
return;
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
281
|
+
const batch = currentBatch;
|
|
282
|
+
const qualifiedTable = `"${this.pgSchemaName}"."${batch.table}"`;
|
|
283
|
+
const colList = batch.cols.map((c) => `"${c}"`).join(", ");
|
|
284
|
+
let rows = batch.rows;
|
|
285
|
+
if (batch.upsertKeys && batch.upsertKeys.length > 0) {
|
|
286
|
+
const uKeys = batch.upsertKeys;
|
|
287
|
+
const keyIndices = uKeys.map((k) => batch.cols.indexOf(k));
|
|
276
288
|
const seen = new Map;
|
|
277
289
|
for (let i = 0;i < rows.length; i++) {
|
|
278
290
|
const key = keyIndices.map((ki) => rows[i][ki]).join("\x00");
|
|
@@ -284,13 +296,14 @@ class SubgraphContext {
|
|
|
284
296
|
}
|
|
285
297
|
const valuesList = rows.map((r) => `(${r.join(", ")})`).join(", ");
|
|
286
298
|
let stmt = `INSERT INTO ${qualifiedTable} (${colList}) VALUES ${valuesList}`;
|
|
287
|
-
if (
|
|
288
|
-
const
|
|
299
|
+
if (batch.upsertKeys && batch.upsertKeys.length > 0) {
|
|
300
|
+
const batchKeys = batch.upsertKeys;
|
|
301
|
+
const updateCols = batch.cols.filter((c) => !batchKeys.includes(c) && !c.startsWith("_"));
|
|
289
302
|
if (updateCols.length > 0) {
|
|
290
303
|
const setClauses = updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`);
|
|
291
|
-
stmt += ` ON CONFLICT (${
|
|
304
|
+
stmt += ` ON CONFLICT (${batchKeys.map((k) => `"${k}"`).join(", ")}) DO UPDATE SET ${setClauses.join(", ")}`;
|
|
292
305
|
} else {
|
|
293
|
-
stmt += ` ON CONFLICT (${
|
|
306
|
+
stmt += ` ON CONFLICT (${batchKeys.map((k) => `"${k}"`).join(", ")}) DO NOTHING`;
|
|
294
307
|
}
|
|
295
308
|
}
|
|
296
309
|
statements.push(stmt);
|
|
@@ -311,8 +324,9 @@ class SubgraphContext {
|
|
|
311
324
|
} else {
|
|
312
325
|
flushInsertBatch();
|
|
313
326
|
if (op.kind === "update") {
|
|
314
|
-
const setEntries = Object.entries(op.set);
|
|
315
|
-
|
|
327
|
+
const setEntries = Object.entries(op.set ?? {});
|
|
328
|
+
for (const [k] of setEntries)
|
|
329
|
+
validateColumnName(k);
|
|
316
330
|
const setClauses = setEntries.map(([k, v]) => `"${k}" = ${escapeLiteral(v)}`);
|
|
317
331
|
const { clause } = buildWhereClause(op.data);
|
|
318
332
|
statements.push(`UPDATE ${qualifiedTable} SET ${setClauses.join(", ")} WHERE ${clause}`);
|
|
@@ -339,14 +353,15 @@ function escapeLiteral(value) {
|
|
|
339
353
|
if (typeof value === "boolean")
|
|
340
354
|
return value ? "TRUE" : "FALSE";
|
|
341
355
|
if (typeof value === "object")
|
|
342
|
-
return `'${JSON.stringify(value).replace(/'/g, "''")}'::jsonb`;
|
|
356
|
+
return `'${JSON.stringify(value, (_k, v) => typeof v === "bigint" ? v.toString() : v).replace(/'/g, "''")}'::jsonb`;
|
|
343
357
|
return `'${String(value).replace(/'/g, "''")}'`;
|
|
344
358
|
}
|
|
345
359
|
function buildWhereClause(where) {
|
|
346
360
|
const entries = Object.entries(where);
|
|
347
361
|
if (entries.length === 0)
|
|
348
362
|
return { clause: "TRUE", values: [] };
|
|
349
|
-
|
|
363
|
+
for (const [k] of entries)
|
|
364
|
+
validateColumnName(k);
|
|
350
365
|
const parts = entries.map(([k, v]) => `"${k}" = ${escapeLiteral(v)}`);
|
|
351
366
|
return { clause: parts.join(" AND "), values: [] };
|
|
352
367
|
}
|
|
@@ -1600,7 +1615,8 @@ function diffSchema(existing, incoming) {
|
|
|
1600
1615
|
changed: [...incomingKeys].filter((k) => {
|
|
1601
1616
|
if (!existingKeys.has(k))
|
|
1602
1617
|
return false;
|
|
1603
|
-
|
|
1618
|
+
const sortedStringify = (o) => JSON.stringify(o, Object.keys(o).sort());
|
|
1619
|
+
return sortedStringify(existingCols[k]) !== sortedStringify(incomingCols[k]);
|
|
1604
1620
|
})
|
|
1605
1621
|
};
|
|
1606
1622
|
}
|
|
@@ -1658,7 +1674,11 @@ async function deploySchema(db, def, handlerPath, opts) {
|
|
|
1658
1674
|
if (existing.schema_hash === hash && !opts?.forceReindex) {
|
|
1659
1675
|
const { updateSubgraphHandlerPath } = await import("@secondlayer/shared/db/queries/subgraphs");
|
|
1660
1676
|
await updateSubgraphHandlerPath(db, def.name, handlerPath);
|
|
1661
|
-
return {
|
|
1677
|
+
return {
|
|
1678
|
+
action: "unchanged",
|
|
1679
|
+
subgraphId: existing.id,
|
|
1680
|
+
version: existing.version
|
|
1681
|
+
};
|
|
1662
1682
|
}
|
|
1663
1683
|
if (existing.schema_hash === hash && opts?.forceReindex) {
|
|
1664
1684
|
await sql3.raw(`DROP SCHEMA IF EXISTS "${schemaName}" CASCADE`).execute(db);
|
|
@@ -1683,10 +1703,17 @@ async function deploySchema(db, def, handlerPath, opts) {
|
|
|
1683
1703
|
addedColumns: Object.fromEntries(Object.entries(diff.tables).filter(([, c]) => c.added.length > 0).map(([t, c]) => [t, c.added])),
|
|
1684
1704
|
breakingChanges: reasons
|
|
1685
1705
|
};
|
|
1686
|
-
return {
|
|
1706
|
+
return {
|
|
1707
|
+
action: "reindexed",
|
|
1708
|
+
subgraphId: sg3.id,
|
|
1709
|
+
version: newVersion,
|
|
1710
|
+
diff: deployDiff2
|
|
1711
|
+
};
|
|
1687
1712
|
}
|
|
1688
1713
|
for (const tableName of diff.addedTables) {
|
|
1689
1714
|
const tableDef = def.schema[tableName];
|
|
1715
|
+
if (!tableDef)
|
|
1716
|
+
continue;
|
|
1690
1717
|
const qualifiedName = `${schemaName}.${tableName}`;
|
|
1691
1718
|
const colDefs = [
|
|
1692
1719
|
"_id BIGSERIAL PRIMARY KEY",
|
|
@@ -1696,7 +1723,10 @@ async function deploySchema(db, def, handlerPath, opts) {
|
|
|
1696
1723
|
];
|
|
1697
1724
|
for (const [colName, col] of Object.entries(tableDef.columns)) {
|
|
1698
1725
|
const nullable = col.nullable ? "" : " NOT NULL";
|
|
1699
|
-
|
|
1726
|
+
const sqlType = TYPE_MAP[col.type];
|
|
1727
|
+
if (!sqlType)
|
|
1728
|
+
continue;
|
|
1729
|
+
colDefs.push(`${colName} ${sqlType}${nullable}`);
|
|
1700
1730
|
}
|
|
1701
1731
|
await sql3.raw(`CREATE TABLE IF NOT EXISTS ${qualifiedName} (
|
|
1702
1732
|
${colDefs.join(`,
|
|
@@ -1718,9 +1748,15 @@ async function deploySchema(db, def, handlerPath, opts) {
|
|
|
1718
1748
|
continue;
|
|
1719
1749
|
const qualifiedName = `${schemaName}.${tableName}`;
|
|
1720
1750
|
const tableDef = def.schema[tableName];
|
|
1751
|
+
if (!tableDef)
|
|
1752
|
+
continue;
|
|
1721
1753
|
for (const colName of colDiff.added) {
|
|
1722
1754
|
const col = tableDef.columns[colName];
|
|
1755
|
+
if (!col)
|
|
1756
|
+
continue;
|
|
1723
1757
|
const sqlType = TYPE_MAP[col.type];
|
|
1758
|
+
if (!sqlType)
|
|
1759
|
+
continue;
|
|
1724
1760
|
const nullable = col.nullable ? "" : ` NOT NULL DEFAULT ${getDefault(col.type)}`;
|
|
1725
1761
|
await sql3.raw(`ALTER TABLE ${qualifiedName} ADD COLUMN ${colName} ${sqlType}${nullable}`).execute(db);
|
|
1726
1762
|
if (col.indexed) {
|
|
@@ -1743,7 +1779,12 @@ async function deploySchema(db, def, handlerPath, opts) {
|
|
|
1743
1779
|
addedColumns: addedCols,
|
|
1744
1780
|
breakingChanges: []
|
|
1745
1781
|
};
|
|
1746
|
-
return {
|
|
1782
|
+
return {
|
|
1783
|
+
action: "updated",
|
|
1784
|
+
subgraphId: sg2.id,
|
|
1785
|
+
version: newVersion,
|
|
1786
|
+
diff: deployDiff
|
|
1787
|
+
};
|
|
1747
1788
|
}
|
|
1748
1789
|
}
|
|
1749
1790
|
for (const stmt of statements) {
|
|
@@ -1782,5 +1823,5 @@ export {
|
|
|
1782
1823
|
backfillSubgraph
|
|
1783
1824
|
};
|
|
1784
1825
|
|
|
1785
|
-
//# debugId=
|
|
1826
|
+
//# debugId=BDEFBE84CC1D9E3564756E2164756E21
|
|
1786
1827
|
//# sourceMappingURL=index.js.map
|