Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "indexer: add hooks support to vcr and plugins:init hook",
"packageName": "@apibara/indexer",
"email": "jadejajaipal5@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "plugin-drizzle: add useTestDrizzleStorage and use `plugin:init` hook",
"packageName": "@apibara/plugin-drizzle",
"email": "jadejajaipal5@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "plugin-mongo: use `plugin:init` hook",
"packageName": "@apibara/plugin-mongo",
"email": "jadejajaipal5@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "plugin-sqlite: use `plugin:init` hook",
"packageName": "@apibara/plugin-sqlite",
"email": "jadejajaipal5@gmail.com",
"dependentChangeType": "patch"
}
5 changes: 5 additions & 0 deletions examples/cli-drizzle/indexers/1-evm.indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export default function (runtimeConfig: ApibaraRuntimeConfig) {
},
],
},
hooks: {
"run:before": () => {
console.log("run:before hook called from indexer");
},
},
plugins: [
drizzleStorage({
db: database,
Expand Down
21 changes: 19 additions & 2 deletions examples/cli-drizzle/test/ethereum.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createVcr } from "apibara/testing";

import createIndexer from "@/indexers/1-evm.indexer";
import { ethereumUsdcTransfers } from "@/lib/schema";
import { useTestDrizzleStorage } from "@apibara/plugin-drizzle";
import { getTestDatabase } from "@apibara/plugin-drizzle/testing";
import { describe, expect, it } from "vitest";

Expand All @@ -15,8 +16,20 @@ describe("Ethereum USDC Transfers indexer", () => {
});

const testResult = await vcr.run("ethereum-usdc-transfers", indexer, {
fromBlock: 10_000_000n,
toBlock: 10_000_005n,
range: {
fromBlock: 10_000_000n,
toBlock: 10_000_005n,
},
hooks: {
"run:before": async () => {
console.log("run:before hook called from test function");
const db = useTestDrizzleStorage();
await db.insert(ethereumUsdcTransfers).values({
number: 1,
hash: "0x0000000000000000000000000000000000000000000000000000000000000000",
});
},
},
});

const database = getTestDatabase(testResult);
Expand All @@ -25,6 +38,10 @@ describe("Ethereum USDC Transfers indexer", () => {

expect(rows.map(({ _id, ...rest }) => rest)).toMatchInlineSnapshot(`
[
{
"hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"number": 1,
},
{
"hash": "0xfc80de5a3b766eece5c5a7f7858a9d537a8fefa8186c71fa7766a2bae939b816",
"number": 10000001,
Expand Down
3 changes: 1 addition & 2 deletions examples/cli-drizzle/test/starknet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ describe("Starknet USDC Transfers indexer", () => {
});

const testResult = await vcr.run("starknet-usdc-transfers", indexer, {
fromBlock: 800_000n,
toBlock: 800_005n,
range: { fromBlock: 800_000n, toBlock: 800_005n },
});

const database = getTestDatabase(testResult);
Expand Down
3 changes: 3 additions & 0 deletions packages/indexer/src/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export type UseMiddlewareFunction = (
) => void;

export interface IndexerHooks<TFilter, TBlock> {
"plugins:init": () => void;
"run:before": () => void;
"run:after": () => void;
"connect:before": ({
Expand Down Expand Up @@ -230,6 +231,8 @@ export async function run<TFilter, TBlock>(
context.debug = true;
}

await indexer.hooks.callHook("plugins:init");

const middleware = await registerMiddleware(indexer);

const indexerMetrics = createIndexerMetrics();
Expand Down
2 changes: 1 addition & 1 deletion packages/indexer/src/plugins/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function internalContext<TFilter, TBlock, TTxnParams>(
values: Record<string, unknown>,
) {
return defineIndexerPlugin<TFilter, TBlock>((indexer) => {
indexer.hooks.hook("run:before", () => {
indexer.hooks.hook("plugins:init", () => {
try {
const ctx = useIndexerContext();
ctx[INTERNAL_CONTEXT_PROPERTY] = {
Expand Down
2 changes: 1 addition & 1 deletion packages/indexer/src/plugins/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function logger<TFilter, TBlock, TTxnParams>({
logger,
}: { logger?: ConsolaReporter } = {}) {
return defineIndexerPlugin<TFilter, TBlock>((indexer) => {
indexer.hooks.hook("run:before", () => {
indexer.hooks.hook("plugins:init", () => {
const ctx = useIndexerContext();

if (logger) {
Expand Down
21 changes: 17 additions & 4 deletions packages/indexer/src/testing/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { createAuthenticatedClient } from "@apibara/protocol";
import ci from "ci-info";
import { type NestedHooks, mergeHooks } from "hookable";
import { useIndexerContext } from "../context";
import { type IndexerWithStreamConfig, createIndexer } from "../indexer";
import {
type IndexerHooks,
type IndexerWithStreamConfig,
createIndexer,
} from "../indexer";
import { type InternalContext, internalContext } from "../plugins/context";
import { logger } from "../plugins/logger";
import type { CassetteOptions, VcrConfig } from "../vcr/config";
Expand All @@ -18,19 +23,27 @@ export function createVcr() {
async run<TFilter, TBlock>(
cassetteName: string,
indexerConfig: IndexerWithStreamConfig<TFilter, TBlock>,
range: { fromBlock: bigint; toBlock: bigint },
config: {
range: { fromBlock: bigint; toBlock: bigint };
hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;
},
) {
const vcrConfig: VcrConfig = {
cassetteDir: "cassettes",
};

indexerConfig.hooks = mergeHooks(
indexerConfig.hooks ?? {},
config.hooks ?? {},
);

const cassetteOptions: CassetteOptions = {
name: cassetteName,
startingCursor: {
orderKey: range.fromBlock,
orderKey: config.range.fromBlock,
},
endingCursor: {
orderKey: range.toBlock,
orderKey: config.range.toBlock,
},
};

Expand Down
19 changes: 18 additions & 1 deletion packages/plugin-drizzle/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,23 @@ export function useDrizzleStorage<
return context[DRIZZLE_PROPERTY];
}

export function useTestDrizzleStorage<
TQueryResult extends PgQueryResultHKT,
TFullSchema extends Record<string, unknown> = Record<string, never>,
TSchema extends
TablesRelationalConfig = ExtractTablesWithRelations<TFullSchema>,
>(): PgDatabase<TQueryResult, TFullSchema, TSchema> {
const context = useIndexerContext();

if (!context[DRIZZLE_STORAGE_DB_PROPERTY]) {
throw new DrizzleStorageError(
"drizzle storage db is not available. Did you register the plugin?",
);
}

return context[DRIZZLE_STORAGE_DB_PROPERTY];
}

export interface DrizzleStorageOptions<
TQueryResult extends PgQueryResultHKT,
TFullSchema extends Record<string, unknown> = Record<string, never>,
Expand Down Expand Up @@ -191,7 +208,7 @@ export function drizzleStorage<
}
}

indexer.hooks.hook("run:before", async () => {
indexer.hooks.hook("plugins:init", async () => {
const internalContext = useInternalContext();
const context = useIndexerContext();
const logger = useLogger();
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-mongo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function mongoStorage<TFilter, TBlock>({
const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true";
let prevFinality: DataFinality | undefined;

indexer.hooks.hook("run:before", async () => {
indexer.hooks.hook("plugins:init", async () => {
const { indexerName } = useInternalContext();
indexerId = generateIndexerId(indexerName, identifier);
const logger = useLogger();
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-sqlite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function sqliteStorage<TFilter, TBlock>({
let prevFinality: DataFinality | undefined;
const alwaysReindex = process.env["APIBARA_ALWAYS_REINDEX"] === "true";

indexer.hooks.hook("run:before", async () => {
indexer.hooks.hook("plugins:init", async () => {
const { indexerName: indexerFileName, availableIndexers } =
useInternalContext();

Expand Down