Skip to content

Commit

Permalink
cli: add build command and refactor cli
Browse files Browse the repository at this point in the history
  • Loading branch information
jaipaljadeja committed Jul 29, 2024
1 parent 8ffcc82 commit 3d2625c
Show file tree
Hide file tree
Showing 28 changed files with 826 additions and 66 deletions.
19 changes: 19 additions & 0 deletions examples/cli/apibara.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineConfig } from "@apibara/cli";
import { defaultSink } from "@apibara/indexer";

export default defineConfig({
runtimeConfig: {
test: 123,
check: "something",
},
presets: {
dev: {
runtimeConfig: {
test: 999,
},
},
},
sink: {
default: () => defaultSink(),
},
});
36 changes: 36 additions & 0 deletions examples/cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "example-cli",
"version": "1.0.0",
"private": true,
"scripts": {
"cli:build": "jiti ./src/main.ts build --dir ./src",
"cli:prepare": "jiti ./src/main.ts prepare --dir ./src",
"cli:start": "jiti ./dist/main.mjs",
"typecheck": "tsc --noEmit",
"lint": "biome check .",
"lint:fix": "pnpm lint --write",
"format": "biome format . --write"
},
"dependencies": {
"@apibara/evm": "workspace:*",
"@apibara/indexer": "workspace:*",
"@apibara/protocol": "workspace:*",
"@apibara/cli": "workspace:*",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.52.0",
"@opentelemetry/resources": "^1.25.0",
"@opentelemetry/sdk-node": "^0.52.0",
"@opentelemetry/sdk-trace-base": "^1.25.0",
"@opentelemetry/semantic-conventions": "^1.25.0",
"better-sqlite3": "^11.1.2",
"citty": "^0.1.6",
"consola": "^3.2.3",
"csv-stringify": "^6.5.0",
"viem": "^2.12.4"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.11",
"@types/node": "^20.12.12",
"jiti": "^1.21.0"
}
}
93 changes: 93 additions & 0 deletions examples/cli/src/indexer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import assert from "node:assert";
import { EvmStream } from "@apibara/evm";
import { defineIndexer, useIndexerContext } from "@apibara/indexer";
import { trace } from "@opentelemetry/api";
import consola from "consola";
import { encodeEventTopics, parseAbi } from "viem";

const abi = parseAbi([
"event Transfer(address indexed from, address indexed to, uint256 value)",
]);

const tracer = trace.getTracer("evm-indexer-demo");

export function createIndexerConfig(streamUrl: string) {
return defineIndexer(EvmStream)({
streamUrl,
finality: "accepted",
startingCursor: {
orderKey: 560875n,
},
filter: {
logs: [
{
strict: true,
topics: encodeEventTopics({
abi,
eventName: "Transfer",
args: { from: null, to: null },
}) as `0x${string}`[],
},
],
},
async transform({ block: { header, logs, transactions } }) {
const ctx = useIndexerContext();
ctx.counter += 1;

if (!transactions || !header || !header.number) return [];

return tracer.startActiveSpan("parseLogs", (span) => {
const rows = logs.map((log) => {
assert(log.topics.length === 3, "Transfer event has 3 topics");

const { args } = tracer.startActiveSpan("decodeEventLog", (span) => {
// const decoded = decodeEventLog({
// abi,
// topics: log.topics as [`0x${string}`, ...`0x${string}`[]],
// data: log.data,
// eventName: "Transfer",
// });
const decoded = { args: { from: "0x0", to: "0x0", value: "0" } };

span.end();
return decoded;
});

return {
blockNumber: Number(header.number),
blockHash: header.hash,
logIndex: Number(log.logIndex),
fromAddress: args.from,
toAddress: args.to,
value: Number(args.value),
};
});

span.end();
return rows;
});
},
hooks: {
async "run:before"() {},
"handler:after"({ output }) {
for (const transfer of output) {
consola.debug(
"Transfer",
transfer.blockNumber,
transfer.logIndex,
transfer.fromAddress,
transfer.toAddress,
transfer.value.toString(),
);
}
},
"sink:write"({ data }) {
consola.info("Wrote", data.length, "transfers");
},
"sink:flush"() {
consola.debug("Flushing");
},
},
plugins: [],
});
}
9 changes: 9 additions & 0 deletions examples/cli/src/indexers/demo.indexer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createIndexer } from "@apibara/indexer";
import { createIndexerConfig } from "../indexer";

export default function demoIndexer(runtimeConfig: unknown) {
console.log("demoIndexer runtimeConfig", runtimeConfig);
return createIndexer(
createIndexerConfig("http://mainnet-v2.starknet.a5a.ch:7007"),
);
}
6 changes: 6 additions & 0 deletions examples/cli/src/indexers/test.indexer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createIndexer } from "@apibara/indexer";
import { createIndexerConfig } from "../indexer";

export default createIndexer(
createIndexerConfig("http://mainnet-v2.starknet.a5a.ch:7007"),
);
43 changes: 43 additions & 0 deletions examples/cli/src/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { Resource } from "@opentelemetry/resources";
import * as opentelemetry from "@opentelemetry/sdk-node";
import {
BatchSpanProcessor,
type SpanProcessor,
} from "@opentelemetry/sdk-trace-base";
import { SEMRESATTRS_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
import consola from "consola";

let spanProcessor: SpanProcessor | undefined;

const axiomApiKey = process.env.AXIOM_API_KEY;
const axiomDataset = process.env.AXIOM_DATASET ?? "evm-indexer-demo";
if (axiomApiKey) {
const exporter = new OTLPTraceExporter({
url: "https://api.axiom.co/v1/traces",
headers: {
Authorization: `Bearer ${axiomApiKey}`,
"X-Axiom-Dataset": axiomDataset,
},
});
spanProcessor = new BatchSpanProcessor(exporter);
consola.info("Sending traces to Axiom", axiomDataset);
}

const resource = new Resource({
[SEMRESATTRS_SERVICE_NAME]: "evm-indexer",
});

const sdk = new opentelemetry.NodeSDK(
spanProcessor
? {
spanProcessor,
resource,
}
: {
resource,
},
);

consola.info("Starting OpenTelemetry SDK");
sdk.start();
4 changes: 4 additions & 0 deletions examples/cli/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { mainCli } from "@apibara/cli";
import { runMain } from "citty";

runMain(mainCli);
11 changes: 11 additions & 0 deletions examples/cli/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"declarationDir": "dist",
"noEmit": false,
"rootDir": "src",
"types": ["node"]
},
"include": ["src/"]
}
13 changes: 0 additions & 13 deletions packages/cli/apibara.config.ts

This file was deleted.

9 changes: 8 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,36 @@
}
},
"scripts": {
"prepare": "jiti ./src/main.ts prepare",
"build": "unbuild",
"lint": "biome check .",
"typecheck": "tsc --noEmit",
"lint:fix": "pnpm lint --write",
"format": "biome format . --write"
},
"devDependencies": {
"@types/fs-extra": "^11.0.4",
"@types/node": "^20.14.0",
"jiti": "^1.21.0",
"unbuild": "^2.0.0",
"vitest": "^1.6.0"
},
"dependencies": {
"@apibara/indexer": "workspace:*",
"@rollup/plugin-commonjs": "^26.0.1",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"c12": "^1.11.1",
"chokidar": "^3.6.0",
"citty": "^0.1.6",
"consola": "^3.2.3",
"defu": "^6.1.4",
"fs-extra": "^11.2.0",
"hookable": "^5.5.3",
"klona": "^2.0.6",
"pathe": "^1.1.2",
"rollup": "^4.18.1",
"tslib": "^2.6.3",
"untyped": "^1.4.2"
}
}
12 changes: 11 additions & 1 deletion packages/cli/src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { defineCommand } from "citty";
import { resolve } from "pathe";
import { createApibara } from "../apibara";
import { commonArgs } from "../common";
import { build } from "../core/build/build";
import { prepare } from "../core/build/prepare";

export default defineCommand({
meta: {
Expand All @@ -10,6 +14,12 @@ export default defineCommand({
...commonArgs,
},
async run({ args }) {
// TODO
const rootDir = resolve((args.dir || args._dir || ".") as string);
const apibara = await createApibara({
rootDir,
});
await prepare(apibara);
await build(apibara);
await apibara.close();
},
});
3 changes: 2 additions & 1 deletion packages/cli/src/commands/prepare.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { defineCommand } from "citty";
import { resolve } from "pathe";
import { createApibara } from "../apibara";
import { writeTypes } from "../build/types";
import { commonArgs } from "../common";
import { writeTypes } from "../core/build/types";

export default defineCommand({
meta: {
Expand All @@ -13,6 +13,7 @@ export default defineCommand({
...commonArgs,
},
async run({ args }) {
console.log("prepare", args);
const rootDir = resolve((args.dir || ".") as string);
const apibara = await createApibara({ rootDir });
await writeTypes(apibara);
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/config/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { defaultSink } from "@apibara/indexer";
import { defineConfig } from ".";
import { defineConfig } from "../config";

export const ApibaraDefaults = defineConfig({
dev: false,
rootDir: ".",
outputDir: "./dist",
runtimeConfig: {},
sink: {
default: defaultSink(),
default: () => defaultSink(),
},
hooks: {},
});
7 changes: 5 additions & 2 deletions packages/cli/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import type { DeepPartial } from "../types";
import type { ApibaraConfig } from "../types/config";

export function defineConfig<
// biome-ignore lint/complexity/noBannedTypes: <explanation>
T extends Record<string, Partial<ApibaraConfig<T>>> = {},
>(config: ApibaraConfig<T>): ApibaraConfig<T> {
T extends Record<string, DeepPartial<ApibaraConfig<T, R>>> = {},
// biome-ignore lint/complexity/noBannedTypes: <explanation>
R extends Record<string, unknown> = {},
>(config: ApibaraConfig<T, R>): ApibaraConfig<T, R> {
return config;
}
4 changes: 3 additions & 1 deletion packages/cli/src/config/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ async function _loadUserConfig(
? watchConfig<ApibaraConfig>
: loadConfig<ApibaraConfig>)({
name: "apibara",
cwd: configOverrides.rootDir,
// path from where apibara.config.ts is loaded
// defautl is "." path
// cwd: configOverrides.rootDir,
overrides: {
...configOverrides,
},
Expand Down
11 changes: 5 additions & 6 deletions packages/cli/src/config/resolvers/preset.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import defu from "defu";
import type { ApibaraOptions } from "../../types/config";

export async function presetResolver(options: ApibaraOptions) {
const updateOptions = {
...options,
...(options.preset ? options.presets?.[options.preset] : {}),
};

Object.assign(options, updateOptions);
if (options.preset && options.presets?.[options.preset]) {
const new_options = defu(options.presets[options.preset], options);
Object.assign(options, new_options);
}
}
8 changes: 8 additions & 0 deletions packages/cli/src/core/build/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { getRollupConfig } from "../../rollup/config";
import type { Apibara } from "../../types/apibara";
import { buildProduction } from "./prod";

export async function build(apibara: Apibara) {
const rollupConfig = getRollupConfig(apibara);
return await buildProduction(apibara, rollupConfig);
}
Loading

0 comments on commit 3d2625c

Please sign in to comment.