From da02a5b5cba5468857e35f0c391064082ea6cd8b Mon Sep 17 00:00:00 2001 From: loothero Date: Tue, 10 Mar 2026 18:00:24 -0700 Subject: [PATCH] fix: backport drizzle plugin patch to eliminate per-block DDL overhead Pins Apibara dependencies to concrete versions and applies the @apibara/plugin-drizzle patch from next branch that: - Registers reorg triggers once (guarded flag) instead of every block - Uses PostgreSQL session variable for order_key instead of trigger args - Removes post-transaction trigger teardown - Splits invalidation into dedicated transaction to prevent reorg corruption Co-Authored-By: Claude Opus 4.6 --- indexer/Dockerfile | 2 + indexer/package.json | 15 +- ...pibara__plugin-drizzle@2.1.0-beta.55.patch | 440 ++++++++++++++++++ indexer/pnpm-lock.yaml | 86 ++-- 4 files changed, 506 insertions(+), 37 deletions(-) create mode 100644 indexer/patches/@apibara__plugin-drizzle@2.1.0-beta.55.patch diff --git a/indexer/Dockerfile b/indexer/Dockerfile index 23c78bf4..4c7e9d21 100644 --- a/indexer/Dockerfile +++ b/indexer/Dockerfile @@ -9,6 +9,7 @@ WORKDIR /app # Install dependencies COPY package.json pnpm-lock.yaml ./ +COPY patches ./patches RUN corepack enable && \ corepack prepare pnpm@10.0.0 --activate && \ pnpm install --frozen-lockfile @@ -30,6 +31,7 @@ RUN addgroup -g 1001 -S nodejs && \ # Install production dependencies + tsx for status check script COPY package.json pnpm-lock.yaml ./ +COPY patches ./patches RUN corepack enable && \ corepack prepare pnpm@10.0.0 --activate && \ pnpm install --prod --frozen-lockfile && \ diff --git a/indexer/package.json b/indexer/package.json index f75fb34d..7a9a0981 100644 --- a/indexer/package.json +++ b/indexer/package.json @@ -27,11 +27,11 @@ "license": "MIT", "description": "Savage Summit Dojo event indexer using Apibara with PostgreSQL persistence", "dependencies": { - "@apibara/indexer": "next", - "@apibara/plugin-drizzle": "next", - "@apibara/protocol": "next", - "@apibara/starknet": "next", - "apibara": "next", + "@apibara/indexer": "2.1.0-beta.56", + "@apibara/plugin-drizzle": "2.1.0-beta.55", + "@apibara/protocol": "2.1.0-beta.56", + "@apibara/starknet": "2.1.0-beta.56", + "apibara": "2.1.0-beta.55", "drizzle-orm": "^0.38.0", "pg": "^8.13.0", "starknet": "^7.1.0" @@ -49,5 +49,10 @@ "typescript": "^5.7.0", "typescript-eslint": "^8.55.0", "vitest": "^3.1.1" + }, + "pnpm": { + "patchedDependencies": { + "@apibara/plugin-drizzle@2.1.0-beta.55": "patches/@apibara__plugin-drizzle@2.1.0-beta.55.patch" + } } } diff --git a/indexer/patches/@apibara__plugin-drizzle@2.1.0-beta.55.patch b/indexer/patches/@apibara__plugin-drizzle@2.1.0-beta.55.patch new file mode 100644 index 00000000..660d1a15 --- /dev/null +++ b/indexer/patches/@apibara__plugin-drizzle@2.1.0-beta.55.patch @@ -0,0 +1,440 @@ +diff --git a/dist/index.cjs b/dist/index.cjs +index 4926b17a6418da810dff724625b8c4a846944b47..7ff74d6813f8ce058c6bb207a97bf0b6ec45da15 100644 +--- a/dist/index.cjs ++++ b/dist/index.cjs +@@ -410,11 +410,18 @@ async function initializeReorgRollbackTable(tx, indexerId) { + DECLARE + table_name TEXT := TG_ARGV[0]::TEXT; + id_col TEXT := TG_ARGV[1]::TEXT; +- order_key INTEGER := TG_ARGV[2]::INTEGER; +- indexer_id TEXT := TG_ARGV[3]::TEXT; ++ order_key_text TEXT := current_setting('${constants.SCHEMA_NAME}.reorg_order_key', true); ++ order_key INTEGER; ++ indexer_id TEXT := TG_ARGV[2]::TEXT; + new_id_value TEXT := row_to_json(NEW.*)->>id_col; + old_id_value TEXT := row_to_json(OLD.*)->>id_col; + BEGIN ++ IF order_key_text IS NULL THEN ++ RETURN NULL; ++ END IF; ++ ++ order_key := order_key_text::INTEGER; ++ + IF (TG_OP = 'DELETE') THEN + INSERT INTO ${constants.SCHEMA_NAME}.${ROLLBACK_TABLE_NAME}(op, table_name, cursor, row_id, row_value, indexer_id) + SELECT 'D', table_name, order_key, old_id_value, row_to_json(OLD.*), indexer_id; +@@ -439,7 +446,7 @@ async function initializeReorgRollbackTable(tx, indexerId) { + ); + } + } +-async function registerTriggers(tx, tables, endCursor, idColumnMap, indexerId) { ++async function registerTriggers(tx, tables, idColumnMap, indexerId) { + try { + for (const table of tables) { + const tableIdColumn = getIdColumnForTable(table, idColumnMap); +@@ -450,10 +457,11 @@ async function registerTriggers(tx, tables, endCursor, idColumnMap, indexerId) { + ); + await tx.execute( + drizzleOrm.sql.raw(` ++ DROP TRIGGER IF EXISTS ${getReorgTriggerName(table, indexerId)} ON ${table}; + CREATE CONSTRAINT TRIGGER ${getReorgTriggerName(table, indexerId)} + AFTER INSERT OR UPDATE OR DELETE ON ${table} + DEFERRABLE INITIALLY DEFERRED +- FOR EACH ROW EXECUTE FUNCTION ${constants.SCHEMA_NAME}.reorg_checkpoint('${table}', '${tableIdColumn}', ${Number(endCursor.orderKey)}, '${indexerId}'); ++ FOR EACH ROW EXECUTE FUNCTION ${constants.SCHEMA_NAME}.reorg_checkpoint('${table}', '${tableIdColumn}', '${indexerId}'); + `) + ); + } +@@ -463,6 +471,19 @@ async function registerTriggers(tx, tables, endCursor, idColumnMap, indexerId) { + }); + } + } ++async function setReorgOrderKey(tx, endCursor) { ++ try { ++ await tx.execute( ++ drizzleOrm.sql.raw( ++ `SELECT set_config('${constants.SCHEMA_NAME}.reorg_order_key', '${Number(endCursor.orderKey)}', true);` ++ ) ++ ); ++ } catch (error) { ++ throw new DrizzleStorageError("Failed to set reorg order key", { ++ cause: error ++ }); ++ } ++} + async function removeTriggers(db, tables, indexerId) { + try { + for (const table of tables) { +@@ -653,6 +674,7 @@ function drizzleStorage({ + let indexerId = ""; + const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true"; + let prevFinality; ++ let reorgTriggersRegistered = false; + const schema = _schema ?? db._.schema ?? {}; + const idColumnMap = { + "*": typeof idColumn === "string" ? idColumn : "id", +@@ -813,23 +835,35 @@ function drizzleStorage({ + indexer$1.hooks.hook("handler:middleware", async ({ use }) => { + use(async (context, next) => { + try { ++ let registeredTriggersInTxn = false; + const { endCursor, finality, cursor } = context; + if (!endCursor) { + throw new DrizzleStorageError("End Cursor is undefined"); + } ++ if (prevFinality === "pending") { ++ await withTransaction(db, async (tx) => { ++ // Invalidate in a dedicated transaction so rollback writes are ++ // never captured with the current block's reorg_order_key. ++ // TRADEOFF: If the replacement transaction (below) fails after this ++ // commits, readers see state with the tip removed until process restart. ++ // Apibara does not retry handler errors, so recovery depends on Railway's ++ // ALWAYS restart policy re-indexing from the last checkpoint. ++ await invalidate(tx, cursor, idColumnMap, indexerId); ++ }); ++ } + await withTransaction(db, async (tx) => { + context[constants.DRIZZLE_PROPERTY] = { db: tx }; +- if (prevFinality === "pending") { +- await invalidate(tx, cursor, idColumnMap, indexerId); +- } + if (finality !== "finalized") { +- await registerTriggers( +- tx, +- tableNames, +- endCursor, +- idColumnMap, +- indexerId +- ); ++ if (!reorgTriggersRegistered) { ++ await registerTriggers( ++ tx, ++ tableNames, ++ idColumnMap, ++ indexerId ++ ); ++ registeredTriggersInTxn = true; ++ } ++ await setReorgOrderKey(tx, endCursor); + } + await next(); + delete context[constants.DRIZZLE_PROPERTY]; +@@ -842,11 +876,10 @@ function drizzleStorage({ + } + prevFinality = finality; + }); +- if (finality !== "finalized") { +- await removeTriggers(db, tableNames, indexerId); ++ if (registeredTriggersInTxn) { ++ reorgTriggersRegistered = true; + } + } catch (error) { +- await removeTriggers(db, tableNames, indexerId); + throw error; + } + }); +diff --git a/dist/index.mjs b/dist/index.mjs +index 1bdf312081394c65988b248952fef093ec89e812..e26e503c70b7a9f87dd9620d27dacaf686bf69d4 100644 +--- a/dist/index.mjs ++++ b/dist/index.mjs +@@ -408,11 +408,18 @@ async function initializeReorgRollbackTable(tx, indexerId) { + DECLARE + table_name TEXT := TG_ARGV[0]::TEXT; + id_col TEXT := TG_ARGV[1]::TEXT; +- order_key INTEGER := TG_ARGV[2]::INTEGER; +- indexer_id TEXT := TG_ARGV[3]::TEXT; ++ order_key_text TEXT := current_setting('${SCHEMA_NAME}.reorg_order_key', true); ++ order_key INTEGER; ++ indexer_id TEXT := TG_ARGV[2]::TEXT; + new_id_value TEXT := row_to_json(NEW.*)->>id_col; + old_id_value TEXT := row_to_json(OLD.*)->>id_col; + BEGIN ++ IF order_key_text IS NULL THEN ++ RETURN NULL; ++ END IF; ++ ++ order_key := order_key_text::INTEGER; ++ + IF (TG_OP = 'DELETE') THEN + INSERT INTO ${SCHEMA_NAME}.${ROLLBACK_TABLE_NAME}(op, table_name, cursor, row_id, row_value, indexer_id) + SELECT 'D', table_name, order_key, old_id_value, row_to_json(OLD.*), indexer_id; +@@ -437,7 +444,7 @@ async function initializeReorgRollbackTable(tx, indexerId) { + ); + } + } +-async function registerTriggers(tx, tables, endCursor, idColumnMap, indexerId) { ++async function registerTriggers(tx, tables, idColumnMap, indexerId) { + try { + for (const table of tables) { + const tableIdColumn = getIdColumnForTable(table, idColumnMap); +@@ -448,10 +455,11 @@ async function registerTriggers(tx, tables, endCursor, idColumnMap, indexerId) { + ); + await tx.execute( + sql.raw(` ++ DROP TRIGGER IF EXISTS ${getReorgTriggerName(table, indexerId)} ON ${table}; + CREATE CONSTRAINT TRIGGER ${getReorgTriggerName(table, indexerId)} + AFTER INSERT OR UPDATE OR DELETE ON ${table} + DEFERRABLE INITIALLY DEFERRED +- FOR EACH ROW EXECUTE FUNCTION ${SCHEMA_NAME}.reorg_checkpoint('${table}', '${tableIdColumn}', ${Number(endCursor.orderKey)}, '${indexerId}'); ++ FOR EACH ROW EXECUTE FUNCTION ${SCHEMA_NAME}.reorg_checkpoint('${table}', '${tableIdColumn}', '${indexerId}'); + `) + ); + } +@@ -461,6 +469,19 @@ async function registerTriggers(tx, tables, endCursor, idColumnMap, indexerId) { + }); + } + } ++async function setReorgOrderKey(tx, endCursor) { ++ try { ++ await tx.execute( ++ sql.raw( ++ `SELECT set_config('${SCHEMA_NAME}.reorg_order_key', '${Number(endCursor.orderKey)}', true);` ++ ) ++ ); ++ } catch (error) { ++ throw new DrizzleStorageError("Failed to set reorg order key", { ++ cause: error ++ }); ++ } ++} + async function removeTriggers(db, tables, indexerId) { + try { + for (const table of tables) { +@@ -651,6 +672,7 @@ function drizzleStorage({ + let indexerId = ""; + const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true"; + let prevFinality; ++ let reorgTriggersRegistered = false; + const schema = _schema ?? db._.schema ?? {}; + const idColumnMap = { + "*": typeof idColumn === "string" ? idColumn : "id", +@@ -811,23 +833,35 @@ function drizzleStorage({ + indexer.hooks.hook("handler:middleware", async ({ use }) => { + use(async (context, next) => { + try { ++ let registeredTriggersInTxn = false; + const { endCursor, finality, cursor } = context; + if (!endCursor) { + throw new DrizzleStorageError("End Cursor is undefined"); + } ++ if (prevFinality === "pending") { ++ await withTransaction(db, async (tx) => { ++ // Invalidate in a dedicated transaction so rollback writes are ++ // never captured with the current block's reorg_order_key. ++ // TRADEOFF: If the replacement transaction (below) fails after this ++ // commits, readers see state with the tip removed until process restart. ++ // Apibara does not retry handler errors, so recovery depends on Railway's ++ // ALWAYS restart policy re-indexing from the last checkpoint. ++ await invalidate(tx, cursor, idColumnMap, indexerId); ++ }); ++ } + await withTransaction(db, async (tx) => { + context[DRIZZLE_PROPERTY] = { db: tx }; +- if (prevFinality === "pending") { +- await invalidate(tx, cursor, idColumnMap, indexerId); +- } + if (finality !== "finalized") { +- await registerTriggers( +- tx, +- tableNames, +- endCursor, +- idColumnMap, +- indexerId +- ); ++ if (!reorgTriggersRegistered) { ++ await registerTriggers( ++ tx, ++ tableNames, ++ idColumnMap, ++ indexerId ++ ); ++ registeredTriggersInTxn = true; ++ } ++ await setReorgOrderKey(tx, endCursor); + } + await next(); + delete context[DRIZZLE_PROPERTY]; +@@ -840,11 +874,10 @@ function drizzleStorage({ + } + prevFinality = finality; + }); +- if (finality !== "finalized") { +- await removeTriggers(db, tableNames, indexerId); ++ if (registeredTriggersInTxn) { ++ reorgTriggersRegistered = true; + } + } catch (error) { +- await removeTriggers(db, tableNames, indexerId); + throw error; + } + }); +diff --git a/src/index.ts b/src/index.ts +index 3761cf45d3ce34a37ebfb2a012804e161d4589d6..f79d046e77ee4bb42e08685cab95f15a37acf1f6 100644 +--- a/src/index.ts ++++ b/src/index.ts +@@ -31,7 +31,7 @@ import { + initializeReorgRollbackTable, + invalidate, + registerTriggers, +- removeTriggers, ++ setReorgOrderKey, + } from "./storage"; + import { + DrizzleStorageError, +@@ -186,6 +186,7 @@ export function drizzleStorage< + let indexerId = ""; + const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true"; + let prevFinality: DataFinality | undefined; ++ let reorgTriggersRegistered = false; + const schema: TSchema = (_schema as TSchema) ?? db._.schema ?? {}; + const idColumnMap: IdColumnMap = { + "*": typeof idColumn === "string" ? idColumn : "id", +@@ -402,6 +403,7 @@ export function drizzleStorage< + indexer.hooks.hook("handler:middleware", async ({ use }) => { + use(async (context, next) => { + try { ++ let registeredTriggersInTxn = false; + const { endCursor, finality, cursor } = context as { + cursor: Cursor; + endCursor: Cursor; +@@ -412,6 +414,18 @@ export function drizzleStorage< + throw new DrizzleStorageError("End Cursor is undefined"); + } + ++ if (prevFinality === "pending") { ++ await withTransaction(db, async (tx) => { ++ // Invalidate in a dedicated transaction so rollback writes are ++ // never captured with the current block's reorg_order_key. ++ // TRADEOFF: If the replacement transaction (below) fails after this ++ // commits, readers see state with the tip removed until process restart. ++ // Apibara does not retry handler errors, so recovery depends on Railway's ++ // ALWAYS restart policy re-indexing from the last checkpoint. ++ await invalidate(tx, cursor, idColumnMap, indexerId); ++ }); ++ } ++ + await withTransaction(db, async (tx) => { + context[DRIZZLE_PROPERTY] = { db: tx } as DrizzleStorage< + TQueryResult, +@@ -419,19 +433,17 @@ export function drizzleStorage< + TSchema + >; + +- if (prevFinality === "pending") { +- // invalidate if previous block's finality was "pending" +- await invalidate(tx, cursor, idColumnMap, indexerId); +- } +- + if (finality !== "finalized") { +- await registerTriggers( +- tx, +- tableNames, +- endCursor, +- idColumnMap, +- indexerId, +- ); ++ if (!reorgTriggersRegistered) { ++ await registerTriggers( ++ tx, ++ tableNames, ++ idColumnMap, ++ indexerId, ++ ); ++ registeredTriggersInTxn = true; ++ } ++ await setReorgOrderKey(tx, endCursor); + } + + await next(); +@@ -448,13 +460,11 @@ export function drizzleStorage< + prevFinality = finality; + }); + +- if (finality !== "finalized") { +- // remove trigger outside of the transaction or it won't be triggered. +- await removeTriggers(db, tableNames, indexerId); ++ if (registeredTriggersInTxn) { ++ // Mark registration only after the transaction commits successfully. ++ reorgTriggersRegistered = true; + } + } catch (error) { +- await removeTriggers(db, tableNames, indexerId); +- + throw error; + } + }); +diff --git a/src/storage.ts b/src/storage.ts +index 1d6e951c860ee24afcd0511fa032cb5d9c99a0e3..bfe1a7d137d444bc2a7812a9fd41739ea8bcaf40 100644 +--- a/src/storage.ts ++++ b/src/storage.ts +@@ -91,11 +91,18 @@ export async function initializeReorgRollbackTable< + DECLARE + table_name TEXT := TG_ARGV[0]::TEXT; + id_col TEXT := TG_ARGV[1]::TEXT; +- order_key INTEGER := TG_ARGV[2]::INTEGER; +- indexer_id TEXT := TG_ARGV[3]::TEXT; ++ order_key_text TEXT := current_setting('${SCHEMA_NAME}.reorg_order_key', true); ++ order_key INTEGER; ++ indexer_id TEXT := TG_ARGV[2]::TEXT; + new_id_value TEXT := row_to_json(NEW.*)->>id_col; + old_id_value TEXT := row_to_json(OLD.*)->>id_col; + BEGIN ++ IF order_key_text IS NULL THEN ++ RETURN NULL; ++ END IF; ++ ++ order_key := order_key_text::INTEGER; ++ + IF (TG_OP = 'DELETE') THEN + INSERT INTO ${SCHEMA_NAME}.${ROLLBACK_TABLE_NAME}(op, table_name, cursor, row_id, row_value, indexer_id) + SELECT 'D', table_name, order_key, old_id_value, row_to_json(OLD.*), indexer_id; +@@ -129,7 +136,6 @@ export async function registerTriggers< + >( + tx: PgTransaction, + tables: string[], +- endCursor: Cursor, + idColumnMap: IdColumnMap, + indexerId: string, + ) { +@@ -145,10 +151,11 @@ export async function registerTriggers< + ); + await tx.execute( + sql.raw(` ++ DROP TRIGGER IF EXISTS ${getReorgTriggerName(table, indexerId)} ON ${table}; + CREATE CONSTRAINT TRIGGER ${getReorgTriggerName(table, indexerId)} + AFTER INSERT OR UPDATE OR DELETE ON ${table} + DEFERRABLE INITIALLY DEFERRED +- FOR EACH ROW EXECUTE FUNCTION ${SCHEMA_NAME}.reorg_checkpoint('${table}', '${tableIdColumn}', ${Number(endCursor.orderKey)}, '${indexerId}'); ++ FOR EACH ROW EXECUTE FUNCTION ${SCHEMA_NAME}.reorg_checkpoint('${table}', '${tableIdColumn}', '${indexerId}'); + `), + ); + } +@@ -159,6 +166,28 @@ export async function registerTriggers< + } + } + ++export async function setReorgOrderKey< ++ TQueryResult extends PgQueryResultHKT, ++ TFullSchema extends Record = Record, ++ TSchema extends ++ TablesRelationalConfig = ExtractTablesWithRelations, ++>( ++ tx: PgTransaction, ++ endCursor: Cursor, ++) { ++ try { ++ await tx.execute( ++ sql.raw( ++ `SELECT set_config('${SCHEMA_NAME}.reorg_order_key', '${Number(endCursor.orderKey)}', true);`, ++ ), ++ ); ++ } catch (error) { ++ throw new DrizzleStorageError("Failed to set reorg order key", { ++ cause: error, ++ }); ++ } ++} ++ + export async function removeTriggers< + TQueryResult extends PgQueryResultHKT, + TFullSchema extends Record = Record, diff --git a/indexer/pnpm-lock.yaml b/indexer/pnpm-lock.yaml index d22f4d57..8b966322 100644 --- a/indexer/pnpm-lock.yaml +++ b/indexer/pnpm-lock.yaml @@ -4,25 +4,30 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + '@apibara/plugin-drizzle@2.1.0-beta.55': + hash: 75ca36241d9ec34fefe74972b6217bd01a2770b9bf07d0ac0fa79af614d10965 + path: patches/@apibara__plugin-drizzle@2.1.0-beta.55.patch + importers: .: dependencies: '@apibara/indexer': - specifier: next - version: 2.1.0-beta.54(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) + specifier: 2.1.0-beta.56 + version: 2.1.0-beta.56(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) '@apibara/plugin-drizzle': - specifier: next - version: 2.1.0-beta.53(drizzle-orm@0.38.4(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.18.0))(pg@8.18.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) + specifier: 2.1.0-beta.55 + version: 2.1.0-beta.55(patch_hash=75ca36241d9ec34fefe74972b6217bd01a2770b9bf07d0ac0fa79af614d10965)(drizzle-orm@0.38.4(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.18.0))(pg@8.18.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) '@apibara/protocol': - specifier: next - version: 2.1.0-beta.54(typescript@5.9.3) + specifier: 2.1.0-beta.56 + version: 2.1.0-beta.56(typescript@5.9.3) '@apibara/starknet': - specifier: next - version: 2.1.0-beta.54(typescript@5.9.3) + specifier: 2.1.0-beta.56 + version: 2.1.0-beta.56(typescript@5.9.3) apibara: - specifier: next - version: 2.1.0-beta.53(magicast@0.3.5)(rollup@4.57.1)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) + specifier: 2.1.0-beta.55 + version: 2.1.0-beta.55(magicast@0.3.5)(rollup@4.57.1)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) drizzle-orm: specifier: ^0.38.0 version: 0.38.4(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.18.0) @@ -79,13 +84,13 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@apibara/indexer@2.1.0-beta.54': - resolution: {integrity: sha512-UBrQP1/4IF8gHACbRWKwNYoIWaC7nNNdc3XcH8ucKaeGZe8ufxeyj4kYvEEq1el8viEaf/CD0JL4LhnnK5L1Hg==} + '@apibara/indexer@2.1.0-beta.56': + resolution: {integrity: sha512-i8o6RC0rCNCxComFtZowpcnThLblFn8Z+6Wf2aqZShJd/AG+CrkNwmvtdOnyrK2sZ/+y7fICKopZjnbtmhB1HA==} peerDependencies: vitest: ^1.6.0 - '@apibara/plugin-drizzle@2.1.0-beta.53': - resolution: {integrity: sha512-LxaPjhRonHjYNB/ifm84KXmdaZUnpgEdJpRUBfx2XlYafKegINpz+azGY3EuwVmmZP64ej6xyZG9bKzBEm9NbA==} + '@apibara/plugin-drizzle@2.1.0-beta.55': + resolution: {integrity: sha512-DDgg6qpOQGRgt48KGCG8bUkSdhm4hmjhpZP1iApC4YAOHeCRezWNUVKQ8hQphXd5jdWudy1oLnSxYvFkYdoxiA==} peerDependencies: '@electric-sql/pglite': '>=0.2.0' drizzle-orm: <1 @@ -96,11 +101,11 @@ packages: pg: optional: true - '@apibara/protocol@2.1.0-beta.54': - resolution: {integrity: sha512-rOCLV44Mz/mKCP6DtSRxdqOrBgC90Ev+5apMzO/0S/cQoqfd1ZhKU3Sc3qsR4+Id+MFkH9mzgIlcg2czyXW2BA==} + '@apibara/protocol@2.1.0-beta.56': + resolution: {integrity: sha512-TerNSio5rIy/3Cx3nj3OJNa/Ndzj4tcxVfsaDAoS+oU6cpPRxl1dIaiLwXQPrlMY4+pQQ8JlTQPjQhmiw4XRhg==} - '@apibara/starknet@2.1.0-beta.54': - resolution: {integrity: sha512-SW725WqTrgAASrx+XsPS3VKG3XJOIoIdERyBWZBnrBCZEXzeL2pOfgA3TvRboP0WyCxlgy93t5pWA9Kvf86VkA==} + '@apibara/starknet@2.1.0-beta.56': + resolution: {integrity: sha512-CtwI+iqFrDYBRzH/AoOCggZhgp4tpIug9sfDz+pHhoXySgbH+pN0mt4px03ICmPtb6rrSsYozVBtGoNT+zRlzA==} '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} @@ -820,21 +825,25 @@ packages: resolution: {integrity: sha512-bYyZLXzJ2boZ7CdUuCSAaTcWkVKcBUOL+B86zv+tRyrtk4BIpHF+L+vOg5uPD/PHwrIglxAno5MN4NnpkUj5fQ==} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-beta.3': resolution: {integrity: sha512-t/jaaFrCSvwX2075jRfa2bwAcsuTtY1/sIT4XqsDg2MVxWQtaUyBx5Mi0pqZKTjdOPnL+f/zoUC9dxT2lUpNmw==} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-x64-gnu@1.0.0-beta.3': resolution: {integrity: sha512-EeDNLPU0Xw8ByRWxNLO30AF0fKYkdb/6rH5G073NFBDkj7ggYR/CvsNBjtDeCJ7+I6JG4xUjete2+VeV+GQjiA==} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-beta.3': resolution: {integrity: sha512-iTcAj8FKac3nyQhvFuqKt6Xqu9YNDbe1ew6US2OSN4g3zwfujgylaRCitEG+Uzd7AZfSVVLAfqrxKMa36Sj9Mg==} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-wasm32-wasi@1.0.0-beta.3': resolution: {integrity: sha512-sYgbsbyspvVZ2zplqsTxjf2N3e8UQGQnSsN5u4bMX461gY5vAsjUiA4nf1/ztDBMHWT79lF2QNx4csjnjSxMlA==} @@ -917,66 +926,79 @@ packages: resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.57.1': resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.57.1': resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.57.1': resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.57.1': resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.57.1': resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.57.1': resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.57.1': resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.57.1': resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.57.1': resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.57.1': resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.57.1': resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.57.1': resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.57.1': resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} @@ -1225,8 +1247,8 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - apibara@2.1.0-beta.53: - resolution: {integrity: sha512-rcgGRA2glUe2p0bIkQv2vNK2pExMR2Rh4d6mDgVbNRDU7aiDAtucbtLe9L/cSjGlUOnT/BCv3P4Z2U/cStNhng==} + apibara@2.1.0-beta.55: + resolution: {integrity: sha512-N2ck7DmJZPYm+Rol3m/iXMqmmcJQi8c5spcpLlI8uZ60TTVmZU4q7ccc4pPdatCIzr7pWXlxn86KRnixeJJhgw==} hasBin: true argparse@2.0.1: @@ -2485,9 +2507,9 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@apibara/indexer@2.1.0-beta.54(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0))': + '@apibara/indexer@2.1.0-beta.56(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0))': dependencies: - '@apibara/protocol': 2.1.0-beta.54(typescript@5.9.3) + '@apibara/protocol': 2.1.0-beta.56(typescript@5.9.3) '@opentelemetry/api': 1.9.0 ci-info: 4.4.0 consola: 3.4.2 @@ -2502,10 +2524,10 @@ snapshots: - utf-8-validate - zod - '@apibara/plugin-drizzle@2.1.0-beta.53(drizzle-orm@0.38.4(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.18.0))(pg@8.18.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0))': + '@apibara/plugin-drizzle@2.1.0-beta.55(patch_hash=75ca36241d9ec34fefe74972b6217bd01a2770b9bf07d0ac0fa79af614d10965)(drizzle-orm@0.38.4(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.18.0))(pg@8.18.0)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0))': dependencies: - '@apibara/indexer': 2.1.0-beta.54(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) - '@apibara/protocol': 2.1.0-beta.54(typescript@5.9.3) + '@apibara/indexer': 2.1.0-beta.56(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) + '@apibara/protocol': 2.1.0-beta.56(typescript@5.9.3) drizzle-orm: 0.38.4(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(pg@8.18.0) postgres-range: 1.1.4 optionalDependencies: @@ -2517,7 +2539,7 @@ snapshots: - vitest - zod - '@apibara/protocol@2.1.0-beta.54(typescript@5.9.3)': + '@apibara/protocol@2.1.0-beta.56(typescript@5.9.3)': dependencies: consola: 3.4.2 long: 5.3.2 @@ -2531,9 +2553,9 @@ snapshots: - utf-8-validate - zod - '@apibara/starknet@2.1.0-beta.54(typescript@5.9.3)': + '@apibara/starknet@2.1.0-beta.56(typescript@5.9.3)': dependencies: - '@apibara/protocol': 2.1.0-beta.54(typescript@5.9.3) + '@apibara/protocol': 2.1.0-beta.56(typescript@5.9.3) '@scure/starknet': 1.1.2 abi-wan-kanabi: 2.2.4 long: 5.3.2 @@ -3198,7 +3220,7 @@ snapshots: '@scure/bip32@1.7.0': dependencies: - '@noble/curves': 1.9.1 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 @@ -3463,10 +3485,10 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 - apibara@2.1.0-beta.53(magicast@0.3.5)(rollup@4.57.1)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)): + apibara@2.1.0-beta.55(magicast@0.3.5)(rollup@4.57.1)(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)): dependencies: - '@apibara/indexer': 2.1.0-beta.54(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) - '@apibara/protocol': 2.1.0-beta.54(typescript@5.9.3) + '@apibara/indexer': 2.1.0-beta.56(typescript@5.9.3)(vitest@3.2.4(@types/node@22.19.11)(jiti@2.6.1)(tsx@4.21.0)) + '@apibara/protocol': 2.1.0-beta.56(typescript@5.9.3) '@rollup/plugin-replace': 6.0.3(rollup@4.57.1) '@rollup/plugin-virtual': 3.0.2(rollup@4.57.1) c12: 1.11.2(magicast@0.3.5)