From d146b17cb44fe7d507c22e321c170db6a11ffdd9 Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Thu, 18 Jul 2024 15:38:25 +0530 Subject: [PATCH 01/10] indexer: remove generic types from sink --- packages/indexer/src/indexer.test.ts | 6 +++--- packages/indexer/src/indexer.ts | 8 ++++---- packages/indexer/src/sink.ts | 22 ++++++++++++---------- packages/indexer/src/sinks/csv.ts | 17 +++++++++-------- packages/indexer/src/sinks/sqlite.test.ts | 4 ++-- packages/indexer/src/sinks/sqlite.ts | 21 ++++++++++----------- packages/indexer/src/testing/setup.ts | 2 +- packages/indexer/src/testing/vcr.ts | 10 +++++----- packages/indexer/src/vcr/replay.ts | 9 +++++---- 9 files changed, 51 insertions(+), 48 deletions(-) diff --git a/packages/indexer/src/indexer.test.ts b/packages/indexer/src/indexer.test.ts index 89f0da5..63cdab4 100644 --- a/packages/indexer/src/indexer.test.ts +++ b/packages/indexer/src/indexer.test.ts @@ -17,7 +17,7 @@ describe("Run Test", () => { return generateMockMessages(); }); - const sink = vcr(); + const sink = vcr(); await run(client, getMockIndexer(), sink); expect(sink.result).toMatchInlineSnapshot(` @@ -265,7 +265,7 @@ describe("Run Test", () => { return {}; }; - const sink = vcr(); + const sink = vcr(); await run(client, indexer, sink); @@ -442,7 +442,7 @@ describe("Run Test", () => { return {}; }; - const sink = vcr(); + const sink = vcr(); await expect(() => run(client, indexer, sink)).rejects.toThrowError( "this error should occurr!", diff --git a/packages/indexer/src/indexer.ts b/packages/indexer/src/indexer.ts index 51d7770..b71c255 100644 --- a/packages/indexer/src/indexer.ts +++ b/packages/indexer/src/indexer.ts @@ -19,7 +19,7 @@ import assert from "node:assert"; import { indexerAsyncContext } from "./context"; import { tracer } from "./otel"; import type { IndexerPlugin } from "./plugins"; -import { type Sink, defaultSink } from "./sink"; +import { type Sink, type SinkData, defaultSink } from "./sink"; export interface IndexerHooks { "run:before": () => void; @@ -123,7 +123,7 @@ export function createIndexer({ export async function run( client: Client, indexer: Indexer, - sinkArg?: Sink, + sinkArg?: Sink, ) { await indexerAsyncContext.callAsync({}, async () => { await indexer.hooks.callHook("run:before"); @@ -131,7 +131,7 @@ export async function run( const sink = sinkArg ?? defaultSink(); sink.hook("write", async ({ data }) => { - await indexer.hooks.callHook("sink:write", { data }); + await indexer.hooks.callHook("sink:write", { data: data as TRet[] }); }); sink.hook("flush", async ({ endCursor, finality }) => { await indexer.hooks.callHook("sink:flush", { endCursor, finality }); @@ -283,7 +283,7 @@ export async function run( if (output.length > 0) { await tracer.startActiveSpan("sink write", async (span) => { await sink.write({ - data: output, + data: output as SinkData[], cursor, endCursor, finality, diff --git a/packages/indexer/src/sink.ts b/packages/indexer/src/sink.ts index 3b77868..db8c73e 100644 --- a/packages/indexer/src/sink.ts +++ b/packages/indexer/src/sink.ts @@ -1,37 +1,39 @@ import type { Cursor, DataFinality } from "@apibara/protocol"; import { Hookable } from "hookable"; -export interface SinkEvents { - write({ data }: { data: TData[] }): void; +export type SinkData = Record; + +export interface SinkEvents { + write({ data }: { data: SinkData[] }): void; flush({ endCursor, finality, }: { endCursor?: Cursor; finality: DataFinality }): void; } -export type SinkWriteArgs = { - data: TData[]; +export type SinkWriteArgs = { + data: SinkData[]; cursor?: Cursor | undefined; endCursor?: Cursor | undefined; finality: DataFinality; }; -export abstract class Sink extends Hookable> { +export abstract class Sink extends Hookable { abstract write({ data, cursor, endCursor, finality, - }: SinkWriteArgs): Promise; + }: SinkWriteArgs): Promise; } -export class DefaultSink extends Sink { - async write({ data, endCursor, finality }: SinkWriteArgs) { +export class DefaultSink extends Sink { + async write({ data, endCursor, finality }: SinkWriteArgs) { await this.callHook("write", { data }); await this.callHook("flush", { endCursor, finality }); } } -export function defaultSink() { - return new DefaultSink(); +export function defaultSink() { + return new DefaultSink(); } diff --git a/packages/indexer/src/sinks/csv.ts b/packages/indexer/src/sinks/csv.ts index 4e2fa5e..1a9b33f 100644 --- a/packages/indexer/src/sinks/csv.ts +++ b/packages/indexer/src/sinks/csv.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import type { Cursor } from "@apibara/protocol"; import { type Options, type Stringifier, stringify } from "csv-stringify"; -import { Sink, type SinkWriteArgs } from "../sink"; +import { Sink, type SinkData, type SinkWriteArgs } from "../sink"; export type CsvArgs = { /** @@ -23,9 +23,7 @@ export type CsvSinkOptions = { cursorColumn?: string; }; -export class CsvSink< - TData extends Record, -> extends Sink { +export class CsvSink extends Sink { constructor( private _stringifier: Stringifier, private _config: CsvSinkOptions, @@ -33,7 +31,7 @@ export class CsvSink< super(); } - async write({ data, endCursor, finality }: SinkWriteArgs) { + async write({ data, endCursor, finality }: SinkWriteArgs) { await this.callHook("write", { data }); // adds a "_cursor" property if "cursorColumn" is not specified by user data = this.processCursorColumn(data, endCursor); @@ -43,7 +41,7 @@ export class CsvSink< await this.callHook("flush", { endCursor, finality }); } - private async insertToCSV(data: TData[]) { + private async insertToCSV(data: SinkData[]) { if (data.length === 0) return; return await new Promise((resolve, reject) => { @@ -60,7 +58,10 @@ export class CsvSink< }); } - private processCursorColumn(data: TData[], endCursor?: Cursor): TData[] { + private processCursorColumn( + data: SinkData[], + endCursor?: Cursor, + ): SinkData[] { const { cursorColumn } = this._config; if ( @@ -93,5 +94,5 @@ export const csv = >( const writeStream = fs.createWriteStream(filepath, { flags: "a" }); stringifier.pipe(writeStream); - return new CsvSink(stringifier, sinkOptions); + return new CsvSink(stringifier, sinkOptions); }; diff --git a/packages/indexer/src/sinks/sqlite.test.ts b/packages/indexer/src/sinks/sqlite.test.ts index 03d1c50..0a72db0 100644 --- a/packages/indexer/src/sinks/sqlite.test.ts +++ b/packages/indexer/src/sinks/sqlite.test.ts @@ -8,7 +8,7 @@ import { describe, expect, it } from "vitest"; import { run } from "../indexer"; import {} from "../plugins/persistence"; import { generateMockMessages } from "../testing"; -import { type MockRet, getMockIndexer } from "../testing/indexer"; +import { getMockIndexer } from "../testing/indexer"; import { sqlite } from "./sqlite"; describe("Run Test", () => { @@ -29,7 +29,7 @@ describe("Run Test", () => { );`, ).run(); - const sink = sqlite({ + const sink = sqlite({ database: db, tableName: "test", }); diff --git a/packages/indexer/src/sinks/sqlite.ts b/packages/indexer/src/sinks/sqlite.ts index ac69a8b..9d9fff1 100644 --- a/packages/indexer/src/sinks/sqlite.ts +++ b/packages/indexer/src/sinks/sqlite.ts @@ -1,6 +1,6 @@ import type { Cursor } from "@apibara/protocol"; import type { Database as SqliteDatabase } from "better-sqlite3"; -import { Sink, type SinkWriteArgs } from "../sink"; +import { Sink, type SinkData, type SinkWriteArgs } from "../sink"; export type SqliteSinkOptions = { /** @@ -24,9 +24,7 @@ export type SqliteSinkOptions = { onConflict?: { on: string; update: string[] }; }; -export class SqliteSink< - TData extends Record, -> extends Sink { +export class SqliteSink extends Sink { private _config: Omit; private _db: SqliteDatabase; @@ -37,7 +35,7 @@ export class SqliteSink< this._db = database; } - async write({ data, endCursor, finality }: SinkWriteArgs) { + async write({ data, endCursor, finality }: SinkWriteArgs) { await this.callHook("write", { data }); data = this.processCursorColumn(data, endCursor); @@ -46,7 +44,7 @@ export class SqliteSink< await this.callHook("flush", { endCursor, finality }); } - private async insertJsonArray(data: TData[]) { + private async insertJsonArray(data: SinkData[]) { if (data.length === 0) return; // Get columns from the first row of the object array @@ -68,7 +66,10 @@ export class SqliteSink< this._db.prepare(statement).run(values); } - private processCursorColumn(data: TData[], endCursor?: Cursor): TData[] { + private processCursorColumn( + data: SinkData[], + endCursor?: Cursor, + ): SinkData[] { const { cursorColumn } = this._config; if ( @@ -104,8 +105,6 @@ export class SqliteSink< } } -export const sqlite = >( - args: SqliteSinkOptions, -) => { - return new SqliteSink(args); +export const sqlite = (args: SqliteSinkOptions) => { + return new SqliteSink(args); }; diff --git a/packages/indexer/src/testing/setup.ts b/packages/indexer/src/testing/setup.ts index 56aecf4..d0fe06c 100644 --- a/packages/indexer/src/testing/setup.ts +++ b/packages/indexer/src/testing/setup.ts @@ -19,7 +19,7 @@ export const test = viTest.extend({ type WithClientContext = { run: ( indexerArgs: Indexer, - ) => Promise>; + ) => Promise; }; async function withClient( diff --git a/packages/indexer/src/testing/vcr.ts b/packages/indexer/src/testing/vcr.ts index 48c212f..993cd6a 100644 --- a/packages/indexer/src/testing/vcr.ts +++ b/packages/indexer/src/testing/vcr.ts @@ -1,16 +1,16 @@ import { Sink, type SinkWriteArgs } from "../sink"; import type { VcrReplayResult } from "../vcr"; -export class VcrSink extends Sink { - public result: VcrReplayResult["outputs"] = []; +export class VcrSink extends Sink { + public result: VcrReplayResult["outputs"] = []; - async write({ data, endCursor, finality }: SinkWriteArgs) { + async write({ data, endCursor, finality }: SinkWriteArgs) { await this.callHook("write", { data }); this.result.push({ data, endCursor }); await this.callHook("flush", { endCursor, finality }); } } -export function vcr() { - return new VcrSink(); +export function vcr() { + return new VcrSink(); } diff --git a/packages/indexer/src/vcr/replay.ts b/packages/indexer/src/vcr/replay.ts index 55071e7..bb53815 100644 --- a/packages/indexer/src/vcr/replay.ts +++ b/packages/indexer/src/vcr/replay.ts @@ -4,6 +4,7 @@ import path from "node:path"; import type { Client, Cursor } from "@apibara/protocol"; import { MockClient } from "@apibara/protocol/testing"; import { type Indexer, run } from "../indexer"; +import type { SinkData } from "../sink"; import { vcr } from "../testing/vcr"; import { type CassetteDataType, deserialize } from "../vcr"; import type { VcrConfig } from "./config"; @@ -12,10 +13,10 @@ export async function replay( vcrConfig: VcrConfig, indexer: Indexer, cassetteName: string, -): Promise> { +): Promise { const client = loadCassette(vcrConfig, cassetteName); - const sink = vcr(); + const sink = vcr(); await run(client, indexer, sink); @@ -24,8 +25,8 @@ export async function replay( }; } -export type VcrReplayResult = { - outputs: Array<{ endCursor?: Cursor; data: TRet[] }>; +export type VcrReplayResult = { + outputs: Array<{ endCursor?: Cursor; data: SinkData[] }>; }; export function loadCassette( From 47706e6ec5fea9a3d02d7a292f6c6582e600f3c3 Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Fri, 19 Jul 2024 17:26:50 +0530 Subject: [PATCH 02/10] cli: add skeleton flow of cli --- packages/cli/README.md | 7 + packages/cli/package.json | 44 ++ packages/cli/src/apibara.ts | 29 ++ packages/cli/src/build/types.ts | 20 + packages/cli/src/commands/build.ts | 15 + packages/cli/src/commands/dev.ts | 15 + packages/cli/src/commands/prepare.ts | 20 + packages/cli/src/common.ts | 8 + packages/cli/src/config/defaults.ts | 5 + packages/cli/src/config/index.ts | 5 + packages/cli/src/config/loader.ts | 63 +++ .../src/config/resolvers/paths.resolver.ts | 6 + .../resolvers/runtime-config.resolver.ts | 5 + packages/cli/src/config/update.ts | 11 + packages/cli/src/index.ts | 1 + packages/cli/src/main.ts | 16 + packages/cli/src/types/_utils.ts | 4 + packages/cli/src/types/apibara.ts | 10 + packages/cli/src/types/config.ts | 51 +++ packages/cli/src/types/hooks.ts | 11 + packages/cli/src/types/presets.ts | 2 + packages/cli/src/types/rollup.ts | 8 + packages/cli/tsconfig.json | 11 + pnpm-lock.yaml | 379 +++++++++++------- 24 files changed, 598 insertions(+), 148 deletions(-) create mode 100644 packages/cli/README.md create mode 100644 packages/cli/package.json create mode 100644 packages/cli/src/apibara.ts create mode 100644 packages/cli/src/build/types.ts create mode 100644 packages/cli/src/commands/build.ts create mode 100644 packages/cli/src/commands/dev.ts create mode 100644 packages/cli/src/commands/prepare.ts create mode 100644 packages/cli/src/common.ts create mode 100644 packages/cli/src/config/defaults.ts create mode 100644 packages/cli/src/config/index.ts create mode 100644 packages/cli/src/config/loader.ts create mode 100644 packages/cli/src/config/resolvers/paths.resolver.ts create mode 100644 packages/cli/src/config/resolvers/runtime-config.resolver.ts create mode 100644 packages/cli/src/config/update.ts create mode 100644 packages/cli/src/index.ts create mode 100644 packages/cli/src/main.ts create mode 100644 packages/cli/src/types/_utils.ts create mode 100644 packages/cli/src/types/apibara.ts create mode 100644 packages/cli/src/types/config.ts create mode 100644 packages/cli/src/types/hooks.ts create mode 100644 packages/cli/src/types/presets.ts create mode 100644 packages/cli/src/types/rollup.ts create mode 100644 packages/cli/tsconfig.json diff --git a/packages/cli/README.md b/packages/cli/README.md new file mode 100644 index 0000000..75c419c --- /dev/null +++ b/packages/cli/README.md @@ -0,0 +1,7 @@ +# `@apibara/cli` + +TODO + +## Installation + +TODO diff --git a/packages/cli/package.json b/packages/cli/package.json new file mode 100644 index 0000000..bacd4c8 --- /dev/null +++ b/packages/cli/package.json @@ -0,0 +1,44 @@ +{ + "name": "@apibara/cli", + "version": "2.0.0", + "type": "module", + "source": "./src/index.ts", + "main": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, + "publishConfig": { + "files": ["dist", "src", "README.md"], + "main": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "default": "./dist/index.mjs" + } + } + }, + "scripts": { + "build": "unbuild", + "lint": "biome check .", + "typecheck": "tsc --noEmit", + "lint:fix": "pnpm lint --write", + "format": "biome format . --write" + }, + "devDependencies": { + "@types/node": "^20.14.0", + "unbuild": "^2.0.0", + "vitest": "^1.6.0" + }, + "dependencies": { + "@apibara/indexer": "workspace:*", + "c12": "^1.11.1", + "citty": "^0.1.6", + "hookable": "^5.5.3", + "klona": "^2.0.6", + "pathe": "^1.1.2", + "rollup": "^4.18.1", + "untyped": "^1.4.2" + } +} diff --git a/packages/cli/src/apibara.ts b/packages/cli/src/apibara.ts new file mode 100644 index 0000000..e0b4c71 --- /dev/null +++ b/packages/cli/src/apibara.ts @@ -0,0 +1,29 @@ +import { createHooks } from "hookable"; +import { loadOptions } from "./config/loader"; +import { updateApibaraConfig } from "./config/update"; +import type { Apibara } from "./types/apibara"; +import type { + ApibaraConfig, + ApibaraDynamicConfig, + LoadConfigOptions, +} from "./types/config"; + +export async function createApibara( + config: ApibaraConfig = {}, + opts: LoadConfigOptions = {}, +) { + const options = await loadOptions(config, opts); + + // create apibara context + const apibara: Apibara = { + options, + hooks: createHooks(), + close: async () => {}, + async updateConfig(config: ApibaraDynamicConfig) { + updateApibaraConfig(apibara, config); + }, + }; + + // TODO + return apibara; +} diff --git a/packages/cli/src/build/types.ts b/packages/cli/src/build/types.ts new file mode 100644 index 0000000..f29abc2 --- /dev/null +++ b/packages/cli/src/build/types.ts @@ -0,0 +1,20 @@ +import { type JSValue, generateTypes, resolveSchema } from "untyped"; +import type { Apibara } from "../types/apibara"; + +export async function writeTypes(apibara: Apibara) { + // TODO + generateTypes( + await resolveSchema( + Object.fromEntries( + Object.entries(apibara.options.runtimeConfig), + ) as Record, + ), + { + interfaceName: "ApibaraRuntimeConfig", + addExport: false, + addDefaults: false, + allowExtraKeys: false, + indentation: 2, + }, + ); +} diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts new file mode 100644 index 0000000..3fae247 --- /dev/null +++ b/packages/cli/src/commands/build.ts @@ -0,0 +1,15 @@ +import { defineCommand } from "citty"; +import { commonArgs } from "../common"; + +export default defineCommand({ + meta: { + name: "build", + description: "Build indexer", + }, + args: { + ...commonArgs, + }, + async run({ args }) { + // TODO + }, +}); diff --git a/packages/cli/src/commands/dev.ts b/packages/cli/src/commands/dev.ts new file mode 100644 index 0000000..d3d337b --- /dev/null +++ b/packages/cli/src/commands/dev.ts @@ -0,0 +1,15 @@ +import { defineCommand } from "citty"; +import { commonArgs } from "../common"; + +export default defineCommand({ + meta: { + name: "dev", + description: "Start the development server", + }, + args: { + ...commonArgs, + }, + async run({ args }) { + // TODO + }, +}); diff --git a/packages/cli/src/commands/prepare.ts b/packages/cli/src/commands/prepare.ts new file mode 100644 index 0000000..b6edc93 --- /dev/null +++ b/packages/cli/src/commands/prepare.ts @@ -0,0 +1,20 @@ +import { defineCommand } from "citty"; +import { resolve } from "pathe"; +import { createApibara } from "../apibara"; +import { writeTypes } from "../build/types"; +import { commonArgs } from "../common"; + +export default defineCommand({ + meta: { + name: "prepare", + description: "Generate types for the project", + }, + args: { + ...commonArgs, + }, + async run({ args }) { + const rootDir = resolve((args.dir || ".") as string); + const apibara = await createApibara({ rootDir }); + await writeTypes(apibara); + }, +}); diff --git a/packages/cli/src/common.ts b/packages/cli/src/common.ts new file mode 100644 index 0000000..d0793cf --- /dev/null +++ b/packages/cli/src/common.ts @@ -0,0 +1,8 @@ +import type { ArgsDef } from "citty"; + +export const commonArgs = { + dir: { + type: "string", + description: "project root directory", + }, +}; diff --git a/packages/cli/src/config/defaults.ts b/packages/cli/src/config/defaults.ts new file mode 100644 index 0000000..583f677 --- /dev/null +++ b/packages/cli/src/config/defaults.ts @@ -0,0 +1,5 @@ +import type { ApibaraConfig } from "../types/config"; + +export const ApibaraDefaults: ApibaraConfig = { + // TODO +}; diff --git a/packages/cli/src/config/index.ts b/packages/cli/src/config/index.ts new file mode 100644 index 0000000..9eb4b46 --- /dev/null +++ b/packages/cli/src/config/index.ts @@ -0,0 +1,5 @@ +import type { ApibaraConfig } from "../types/config"; + +export function defineConfig(config: ApibaraConfig): ApibaraConfig { + return config; +} diff --git a/packages/cli/src/config/loader.ts b/packages/cli/src/config/loader.ts new file mode 100644 index 0000000..8e696de --- /dev/null +++ b/packages/cli/src/config/loader.ts @@ -0,0 +1,63 @@ +import { loadConfig, watchConfig } from "c12"; +import { klona } from "klona/full"; +import type { + ApibaraConfig, + ApibaraOptions, + LoadConfigOptions, +} from "../types/config"; +import { ApibaraDefaults } from "./defaults"; +import { resolvePathOptions } from "./resolvers/paths.resolver"; +import { resolveRuntimeConfigOptions } from "./resolvers/runtime-config.resolver"; + +const configResolvers = [ + resolvePathOptions, + resolveRuntimeConfigOptions, +] as const; + +export async function loadOptions( + configOverrides: ApibaraConfig = {}, + opts: LoadConfigOptions = {}, +): Promise { + const options = await _loadUserConfig(configOverrides, opts); + for (const resolver of configResolvers) { + await resolver(options); + } + return options; +} + +async function _loadUserConfig( + configOverrides: ApibaraConfig = {}, + opts: LoadConfigOptions = {}, +): Promise { + let presetOverride = configOverrides.preset; + if (configOverrides.dev) { + presetOverride = "apibara-dev"; + } + + // biome-ignore lint: noParameterAssign + configOverrides = klona(configOverrides); + + const loadedConfig = await (opts.watch + ? watchConfig + : loadConfig)({ + name: "apibara", + cwd: configOverrides.rootDir, + overrides: { + ...configOverrides, + preset: presetOverride, + }, + defaults: ApibaraDefaults, + ...opts.c12, + }); + + const options = klona(loadedConfig.config) as ApibaraOptions; + + options._config = configOverrides; + options._c12 = loadedConfig; + + if (presetOverride) { + options.preset = presetOverride; + } + + return options; +} diff --git a/packages/cli/src/config/resolvers/paths.resolver.ts b/packages/cli/src/config/resolvers/paths.resolver.ts new file mode 100644 index 0000000..79f24e6 --- /dev/null +++ b/packages/cli/src/config/resolvers/paths.resolver.ts @@ -0,0 +1,6 @@ +import { resolve } from "pathe"; +import type { ApibaraOptions } from "../../types/config"; + +export async function resolvePathOptions(options: ApibaraOptions) { + options.rootDir = resolve(options.rootDir || "."); +} diff --git a/packages/cli/src/config/resolvers/runtime-config.resolver.ts b/packages/cli/src/config/resolvers/runtime-config.resolver.ts new file mode 100644 index 0000000..079d799 --- /dev/null +++ b/packages/cli/src/config/resolvers/runtime-config.resolver.ts @@ -0,0 +1,5 @@ +import type { ApibaraOptions } from "../../types/config"; + +export async function resolveRuntimeConfigOptions(options: ApibaraOptions) { + options.runtimeConfig = { ...options.runtimeConfig, default: "value" }; +} diff --git a/packages/cli/src/config/update.ts b/packages/cli/src/config/update.ts new file mode 100644 index 0000000..6017093 --- /dev/null +++ b/packages/cli/src/config/update.ts @@ -0,0 +1,11 @@ +import type { Apibara } from "../types/apibara"; +import type { ApibaraDynamicConfig } from "../types/config"; + +export async function updateApibaraConfig( + apibara: Apibara, + config: ApibaraDynamicConfig, +) { + // Do something + // await apibara.hooks.callHook("rollup:reload"); + // consola.success("Apibara config hot reloaded!"); +} diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts new file mode 100644 index 0000000..d66d2cd --- /dev/null +++ b/packages/cli/src/index.ts @@ -0,0 +1 @@ +export * from "./main"; diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts new file mode 100644 index 0000000..4b0c2ed --- /dev/null +++ b/packages/cli/src/main.ts @@ -0,0 +1,16 @@ +import { defineCommand, runMain } from "citty"; + +const main = defineCommand({ + meta: { + name: "apibara", + description: "Apibara CLI", + version: "2.0.0", + }, + subCommands: { + dev: () => import("./commands/dev").then((r) => r.default), + build: () => import("./commands/build").then((r) => r.default), + prepare: () => import("./commands/prepare").then((r) => r.default), + }, +}); + +runMain(main); diff --git a/packages/cli/src/types/_utils.ts b/packages/cli/src/types/_utils.ts new file mode 100644 index 0000000..353a532 --- /dev/null +++ b/packages/cli/src/types/_utils.ts @@ -0,0 +1,4 @@ +// biome-ignore lint/suspicious/noExplicitAny: +export type DeepPartial = T extends Record + ? { [P in keyof T]?: DeepPartial | T[P] } + : T; diff --git a/packages/cli/src/types/apibara.ts b/packages/cli/src/types/apibara.ts new file mode 100644 index 0000000..c3183d5 --- /dev/null +++ b/packages/cli/src/types/apibara.ts @@ -0,0 +1,10 @@ +import type { Hookable } from "hookable"; +import type { ApibaraDynamicConfig, ApibaraOptions } from "./config"; +import type { ApibaraHooks } from "./hooks"; + +export interface Apibara { + options: ApibaraOptions; + hooks: Hookable; + close: () => Promise; + updateConfig: (config: ApibaraDynamicConfig) => void | Promise; +} diff --git a/packages/cli/src/types/config.ts b/packages/cli/src/types/config.ts new file mode 100644 index 0000000..4fd15f8 --- /dev/null +++ b/packages/cli/src/types/config.ts @@ -0,0 +1,51 @@ +import type { Sink } from "@apibara/indexer"; +import type { ConfigWatcher, ResolvedConfig, WatchConfigOptions } from "c12"; +import type { DeepPartial } from "./_utils"; +import type { PresetName } from "./presets"; +import type { RollupConfig } from "./rollup"; + +/** + * Apibara Config type (apibara.config) + */ +export interface ApibaraConfig + extends DeepPartial> { + sink?: { + default: Sink; + [key: string]: Sink; + }; + dev?: boolean; + runtimeConfig?: RuntimeConfig; + presets?: { + [key: string]: Partial; + }; + preset?: string; +} + +export interface RuntimeConfig { + [key: string]: unknown; +} + +export type ApibaraDynamicConfig = Pick; + +/** + * Config loader options + */ +export interface LoadConfigOptions { + watch?: boolean; + c12?: WatchConfigOptions; +} + +export interface ApibaraOptions { + // Internal + _config: ApibaraConfig; + _c12: ResolvedConfig | ConfigWatcher; + // General + debug: boolean; + preset: PresetName; + runtimeConfig: RuntimeConfig; + rootDir: string; + outputDir: string; + // Dev + dev: boolean; + rollupConfig?: RollupConfig; +} diff --git a/packages/cli/src/types/hooks.ts b/packages/cli/src/types/hooks.ts new file mode 100644 index 0000000..bc03c15 --- /dev/null +++ b/packages/cli/src/types/hooks.ts @@ -0,0 +1,11 @@ +import type { Apibara } from "./apibara"; +import type { RollupConfig } from "./rollup"; + +export interface ApibaraHooks { + "rollup:before": (apibara: Apibara, rollupConfig: RollupConfig) => void; + compiled: (apibara: Apibara) => void; + "dev:reload": () => void; + "rollup:reload": () => void; + restart: () => void; + close: () => void; +} diff --git a/packages/cli/src/types/presets.ts b/packages/cli/src/types/presets.ts new file mode 100644 index 0000000..1ebe7e7 --- /dev/null +++ b/packages/cli/src/types/presets.ts @@ -0,0 +1,2 @@ +// TODO +export type PresetName = string; diff --git a/packages/cli/src/types/rollup.ts b/packages/cli/src/types/rollup.ts new file mode 100644 index 0000000..5430fc0 --- /dev/null +++ b/packages/cli/src/types/rollup.ts @@ -0,0 +1,8 @@ +import type { + InputOptions as RollupInputOptions, + OutputOptions as RollupOutputOptions, +} from "rollup"; + +export type RollupConfig = RollupInputOptions & { + output: RollupOutputOptions; +}; diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json new file mode 100644 index 0000000..9d05974 --- /dev/null +++ b/packages/cli/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": "dist", + "noEmit": false, + "rootDir": "src", + "types": ["node"] + }, + "include": ["src/"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index df16cbc..eca04bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -252,6 +252,43 @@ importers: specifier: ^1.6.0 version: 1.6.0(@types/node@20.14.0) + packages/cli: + dependencies: + '@apibara/indexer': + specifier: workspace:* + version: link:../indexer + c12: + specifier: ^1.11.1 + version: 1.11.1 + citty: + specifier: ^0.1.6 + version: 0.1.6 + hookable: + specifier: ^5.5.3 + version: 5.5.3 + klona: + specifier: ^2.0.6 + version: 2.0.6 + pathe: + specifier: ^1.1.2 + version: 1.1.2 + rollup: + specifier: ^4.18.1 + version: 4.18.1 + untyped: + specifier: ^1.4.2 + version: 1.4.2 + devDependencies: + '@types/node': + specifier: ^20.14.0 + version: 20.14.0 + unbuild: + specifier: ^2.0.0 + version: 2.0.0(typescript@5.4.5) + vitest: + specifier: ^1.6.0 + version: 1.6.0(@types/node@20.14.0) + packages/evm: dependencies: '@apibara/protocol': @@ -426,7 +463,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - dev: true /@babel/code-frame@7.24.2: resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} @@ -442,12 +478,10 @@ packages: dependencies: '@babel/highlight': 7.24.6 picocolors: 1.0.1 - dev: true /@babel/compat-data@7.24.6: resolution: {integrity: sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/core@7.24.6: resolution: {integrity: sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==} @@ -470,7 +504,6 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color - dev: true /@babel/generator@7.24.6: resolution: {integrity: sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==} @@ -480,7 +513,6 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - dev: true /@babel/helper-compilation-targets@7.24.6: resolution: {integrity: sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==} @@ -491,12 +523,10 @@ packages: browserslist: 4.23.0 lru-cache: 5.1.1 semver: 6.3.1 - dev: true /@babel/helper-environment-visitor@7.24.6: resolution: {integrity: sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-function-name@7.24.6: resolution: {integrity: sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==} @@ -504,21 +534,18 @@ packages: dependencies: '@babel/template': 7.24.6 '@babel/types': 7.24.6 - dev: true /@babel/helper-hoist-variables@7.24.6: resolution: {integrity: sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.6 - dev: true /@babel/helper-module-imports@7.24.6: resolution: {integrity: sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.6 - dev: true /@babel/helper-module-transforms@7.24.6(@babel/core@7.24.6): resolution: {integrity: sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==} @@ -532,26 +559,22 @@ packages: '@babel/helper-simple-access': 7.24.6 '@babel/helper-split-export-declaration': 7.24.6 '@babel/helper-validator-identifier': 7.24.6 - dev: true /@babel/helper-simple-access@7.24.6: resolution: {integrity: sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.6 - dev: true /@babel/helper-split-export-declaration@7.24.6: resolution: {integrity: sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.24.6 - dev: true /@babel/helper-string-parser@7.24.6: resolution: {integrity: sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} @@ -561,12 +584,10 @@ packages: /@babel/helper-validator-identifier@7.24.6: resolution: {integrity: sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-option@7.24.6: resolution: {integrity: sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/helpers@7.24.6: resolution: {integrity: sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==} @@ -574,7 +595,6 @@ packages: dependencies: '@babel/template': 7.24.6 '@babel/types': 7.24.6 - dev: true /@babel/highlight@7.24.2: resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} @@ -595,7 +615,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 picocolors: 1.0.1 - dev: true /@babel/parser@7.24.6: resolution: {integrity: sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==} @@ -603,7 +622,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.24.6 - dev: true /@babel/runtime@7.24.4: resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} @@ -615,7 +633,6 @@ packages: /@babel/standalone@7.24.6: resolution: {integrity: sha512-ch8nbtobUPLvSLKdG2s8pVAqS1zUc+mt7UE9k8/xpupvETbAFOaoqo0QcpgVD/f0xkMkbUnqedVY5eeVWOqtjw==} engines: {node: '>=6.9.0'} - dev: true /@babel/template@7.24.6: resolution: {integrity: sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==} @@ -624,7 +641,6 @@ packages: '@babel/code-frame': 7.24.6 '@babel/parser': 7.24.6 '@babel/types': 7.24.6 - dev: true /@babel/traverse@7.24.6: resolution: {integrity: sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==} @@ -642,7 +658,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/types@7.24.6: resolution: {integrity: sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==} @@ -651,7 +666,6 @@ packages: '@babel/helper-string-parser': 7.24.6 '@babel/helper-validator-identifier': 7.24.6 to-fast-properties: 2.0.0 - dev: true /@biomejs/biome@1.8.1: resolution: {integrity: sha512-fQXGfvq6DIXem12dGQCM2tNF+vsNHH1qs3C7WeOu75Pd0trduoTmoO7G4ntLJ2qDs5wuw981H+cxQhi1uHnAtA==} @@ -1539,17 +1553,14 @@ packages: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.25 - dev: true /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/set-array@1.2.1: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} @@ -1559,7 +1570,6 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /@manypkg/find-root@1.1.0: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -2004,132 +2014,116 @@ packages: rollup: 3.29.4 dev: true - /@rollup/rollup-android-arm-eabi@4.18.0: - resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} + /@rollup/rollup-android-arm-eabi@4.18.1: + resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==} cpu: [arm] os: [android] requiresBuild: true - dev: true optional: true - /@rollup/rollup-android-arm64@4.18.0: - resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} + /@rollup/rollup-android-arm64@4.18.1: + resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==} cpu: [arm64] os: [android] requiresBuild: true - dev: true optional: true - /@rollup/rollup-darwin-arm64@4.18.0: - resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} + /@rollup/rollup-darwin-arm64@4.18.1: + resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==} cpu: [arm64] os: [darwin] requiresBuild: true - dev: true optional: true - /@rollup/rollup-darwin-x64@4.18.0: - resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} + /@rollup/rollup-darwin-x64@4.18.1: + resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==} cpu: [x64] os: [darwin] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.18.0: - resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} + /@rollup/rollup-linux-arm-gnueabihf@4.18.1: + resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==} cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-arm-musleabihf@4.18.0: - resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} + /@rollup/rollup-linux-arm-musleabihf@4.18.1: + resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==} cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-arm64-gnu@4.18.0: - resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} + /@rollup/rollup-linux-arm64-gnu@4.18.1: + resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==} cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-arm64-musl@4.18.0: - resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} + /@rollup/rollup-linux-arm64-musl@4.18.1: + resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==} cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-powerpc64le-gnu@4.18.0: - resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} + /@rollup/rollup-linux-powerpc64le-gnu@4.18.1: + resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==} cpu: [ppc64] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-riscv64-gnu@4.18.0: - resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} + /@rollup/rollup-linux-riscv64-gnu@4.18.1: + resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==} cpu: [riscv64] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-s390x-gnu@4.18.0: - resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} + /@rollup/rollup-linux-s390x-gnu@4.18.1: + resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==} cpu: [s390x] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-x64-gnu@4.18.0: - resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} + /@rollup/rollup-linux-x64-gnu@4.18.1: + resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==} cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-linux-x64-musl@4.18.0: - resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} + /@rollup/rollup-linux-x64-musl@4.18.1: + resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==} cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true - /@rollup/rollup-win32-arm64-msvc@4.18.0: - resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} + /@rollup/rollup-win32-arm64-msvc@4.18.1: + resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==} cpu: [arm64] os: [win32] requiresBuild: true - dev: true optional: true - /@rollup/rollup-win32-ia32-msvc@4.18.0: - resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} + /@rollup/rollup-win32-ia32-msvc@4.18.1: + resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==} cpu: [ia32] os: [win32] requiresBuild: true - dev: true optional: true - /@rollup/rollup-win32-x64-msvc@4.18.0: - resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} + /@rollup/rollup-win32-x64-msvc@4.18.1: + resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==} cpu: [x64] os: [win32] requiresBuild: true - dev: true optional: true /@scure/base@1.1.5: @@ -2308,7 +2302,6 @@ packages: requiresBuild: true dependencies: color-convert: 1.9.3 - dev: true /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} @@ -2473,7 +2466,6 @@ packages: electron-to-chromium: 1.4.783 node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.0) - dev: true /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -2486,6 +2478,28 @@ packages: engines: {node: '>=6'} dev: true + /c12@1.11.1: + resolution: {integrity: sha512-KDU0TvSvVdaYcQKQ6iPHATGz/7p/KiVjPg4vQrB6Jg/wX9R0yl5RZxWm9IoZqaIHD2+6PZd81+KMGwRr/lRIUg==} + peerDependencies: + magicast: ^0.3.4 + peerDependenciesMeta: + magicast: + optional: true + dependencies: + chokidar: 3.6.0 + confbox: 0.1.7 + defu: 6.1.4 + dotenv: 16.4.5 + giget: 1.2.3 + jiti: 1.21.6 + mlly: 1.7.1 + ohash: 1.1.3 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + pkg-types: 1.1.1 + rc9: 2.1.2 + dev: false + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -2527,7 +2541,6 @@ packages: /caniuse-lite@1.0.30001621: resolution: {integrity: sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA==} - dev: true /chai@4.4.1: resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} @@ -2550,7 +2563,6 @@ packages: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: true /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -2593,6 +2605,11 @@ packages: /chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: false + /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -2633,7 +2650,6 @@ packages: requiresBuild: true dependencies: color-name: 1.1.3 - dev: true /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -2644,7 +2660,6 @@ packages: /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} requiresBuild: true - dev: true /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -2664,7 +2679,6 @@ packages: /confbox@0.1.7: resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} - dev: true /consola@3.2.3: resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} @@ -2672,7 +2686,6 @@ packages: /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} @@ -2689,7 +2702,6 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true /css-declaration-sorter@7.2.0(postcss@8.4.38): resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==} @@ -2931,7 +2943,10 @@ packages: /defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - dev: true + + /destr@2.0.3: + resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} + dev: false /detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} @@ -2981,6 +2996,11 @@ packages: domhandler: 5.0.3 dev: true + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: false + /dotenv@8.6.0: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} @@ -2992,7 +3012,6 @@ packages: /electron-to-chromium@1.4.783: resolution: {integrity: sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ==} - dev: true /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -3185,13 +3204,11 @@ packages: /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} - dev: true /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} requiresBuild: true - dev: true /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} @@ -3221,7 +3238,6 @@ packages: onetime: 6.0.0 signal-exit: 4.1.0 strip-final-newline: 3.0.0 - dev: true /expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} @@ -3336,6 +3352,13 @@ packages: universalify: 0.1.2 dev: true + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -3367,7 +3390,6 @@ packages: /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - dev: true /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} @@ -3391,7 +3413,6 @@ packages: /get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} - dev: true /get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} @@ -3402,6 +3423,20 @@ packages: get-intrinsic: 1.2.4 dev: true + /giget@1.2.3: + resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} + hasBin: true + dependencies: + citty: 0.1.6 + consola: 3.2.3 + defu: 6.1.4 + node-fetch-native: 1.6.4 + nypm: 0.3.9 + ohash: 1.1.3 + pathe: 1.1.2 + tar: 6.2.1 + dev: false + /github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -3426,7 +3461,6 @@ packages: /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - dev: true /globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} @@ -3497,7 +3531,6 @@ packages: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} requiresBuild: true - dev: true /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -3547,7 +3580,6 @@ packages: /human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - dev: true /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} @@ -3728,7 +3760,6 @@ packages: /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} @@ -3775,7 +3806,6 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true /isows@1.0.4(ws@8.13.0): resolution: {integrity: sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==} @@ -3787,12 +3817,15 @@ packages: /jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true - dev: true + + /jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + dev: false /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} requiresBuild: true - dev: true /js-tokens@9.0.0: resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} @@ -3810,7 +3843,6 @@ packages: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true - dev: true /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} @@ -3820,7 +3852,6 @@ packages: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - dev: true /jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -3932,7 +3963,6 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 - dev: true /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} @@ -3982,7 +4012,6 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -4000,7 +4029,6 @@ packages: /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - dev: true /mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} @@ -4030,6 +4058,26 @@ packages: /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: false + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: false + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: false + /mixme@0.5.10: resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} engines: {node: '>= 8.0.0'} @@ -4038,6 +4086,12 @@ packages: /mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + /mkdist@1.5.1(typescript@5.4.5): resolution: {integrity: sha512-lCu1spNiA52o7IaKgZnOjg28nNHwYqUDjBfXePXyUtzD7Xhe6rRTkGTalQ/ALfrZC/SrPw2+A/0qkeJ+fPDZtQ==} hasBin: true @@ -4078,7 +4132,15 @@ packages: pathe: 1.1.2 pkg-types: 1.1.1 ufo: 1.5.3 - dev: true + + /mlly@1.7.1: + resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.1.1 + ufo: 1.5.3 + dev: false /module-details-from-path@1.0.3: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} @@ -4087,7 +4149,6 @@ packages: /mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} - dev: true /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -4121,6 +4182,10 @@ packages: dependencies: semver: 7.6.0 + /node-fetch-native@1.6.4: + resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + dev: false + /node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -4135,7 +4200,6 @@ packages: /node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -4161,7 +4225,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: path-key: 4.0.0 - dev: true /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -4169,6 +4232,19 @@ packages: boolbase: 1.0.0 dev: true + /nypm@0.3.9: + resolution: {integrity: sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==} + engines: {node: ^14.16.0 || >=16.10.0} + hasBin: true + dependencies: + citty: 0.1.6 + consola: 3.2.3 + execa: 8.0.1 + pathe: 1.1.2 + pkg-types: 1.1.1 + ufo: 1.5.3 + dev: false + /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} dev: true @@ -4188,6 +4264,10 @@ packages: object-keys: 1.1.1 dev: true + /ohash@1.1.3: + resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + dev: false + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -4198,7 +4278,6 @@ packages: engines: {node: '>=12'} dependencies: mimic-fn: 4.0.0 - dev: true /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} @@ -4279,12 +4358,10 @@ packages: /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - dev: true /path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - dev: true /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -4301,19 +4378,21 @@ packages: /pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - dev: true /pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} dev: true + /perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true /picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - dev: true /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -4337,7 +4416,6 @@ packages: confbox: 0.1.7 mlly: 1.7.0 pathe: 1.1.2 - dev: true /possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} @@ -4766,6 +4844,13 @@ packages: engines: {node: '>=8'} dev: true + /rc9@2.1.2: + resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + dependencies: + defu: 6.1.4 + destr: 2.0.3 + dev: false + /rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -4904,31 +4989,30 @@ packages: fsevents: 2.3.3 dev: true - /rollup@4.18.0: - resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} + /rollup@4.18.1: + resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.18.0 - '@rollup/rollup-android-arm64': 4.18.0 - '@rollup/rollup-darwin-arm64': 4.18.0 - '@rollup/rollup-darwin-x64': 4.18.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 - '@rollup/rollup-linux-arm-musleabihf': 4.18.0 - '@rollup/rollup-linux-arm64-gnu': 4.18.0 - '@rollup/rollup-linux-arm64-musl': 4.18.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 - '@rollup/rollup-linux-riscv64-gnu': 4.18.0 - '@rollup/rollup-linux-s390x-gnu': 4.18.0 - '@rollup/rollup-linux-x64-gnu': 4.18.0 - '@rollup/rollup-linux-x64-musl': 4.18.0 - '@rollup/rollup-win32-arm64-msvc': 4.18.0 - '@rollup/rollup-win32-ia32-msvc': 4.18.0 - '@rollup/rollup-win32-x64-msvc': 4.18.0 + '@rollup/rollup-android-arm-eabi': 4.18.1 + '@rollup/rollup-android-arm64': 4.18.1 + '@rollup/rollup-darwin-arm64': 4.18.1 + '@rollup/rollup-darwin-x64': 4.18.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.1 + '@rollup/rollup-linux-arm-musleabihf': 4.18.1 + '@rollup/rollup-linux-arm64-gnu': 4.18.1 + '@rollup/rollup-linux-arm64-musl': 4.18.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.1 + '@rollup/rollup-linux-riscv64-gnu': 4.18.1 + '@rollup/rollup-linux-s390x-gnu': 4.18.1 + '@rollup/rollup-linux-x64-gnu': 4.18.1 + '@rollup/rollup-linux-x64-musl': 4.18.1 + '@rollup/rollup-win32-arm64-msvc': 4.18.1 + '@rollup/rollup-win32-ia32-msvc': 4.18.1 + '@rollup/rollup-win32-x64-msvc': 4.18.1 fsevents: 2.3.3 - dev: true /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -4964,7 +5048,6 @@ packages: /scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} - dev: true /semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} @@ -4974,7 +5057,6 @@ packages: /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - dev: true /semver@7.6.0: resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} @@ -5021,7 +5103,6 @@ packages: engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 - dev: true /shebang-regex@1.0.0: resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} @@ -5031,7 +5112,6 @@ packages: /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - dev: true /shimmer@1.2.1: resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} @@ -5058,7 +5138,6 @@ packages: /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - dev: true /simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} @@ -5209,7 +5288,6 @@ packages: /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - dev: true /strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} @@ -5245,7 +5323,6 @@ packages: requiresBuild: true dependencies: has-flag: 3.0.0 - dev: true /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} @@ -5290,6 +5367,18 @@ packages: inherits: 2.0.4 readable-stream: 3.6.2 + /tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: false + /term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -5319,7 +5408,6 @@ packages: /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - dev: true /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -5490,7 +5578,6 @@ packages: /ufo@1.5.3: resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} - dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} @@ -5591,7 +5678,6 @@ packages: scule: 1.3.0 transitivePeerDependencies: - supports-color - dev: true /update-browserslist-db@1.0.16(browserslist@4.23.0): resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} @@ -5602,7 +5688,6 @@ packages: browserslist: 4.23.0 escalade: 3.1.2 picocolors: 1.0.1 - dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -5776,7 +5861,7 @@ packages: '@types/node': 20.12.12 esbuild: 0.20.2 postcss: 8.4.38 - rollup: 4.18.0 + rollup: 4.18.1 optionalDependencies: fsevents: 2.3.3 dev: true @@ -5812,7 +5897,7 @@ packages: '@types/node': 20.12.13 esbuild: 0.20.2 postcss: 8.4.38 - rollup: 4.18.0 + rollup: 4.18.1 optionalDependencies: fsevents: 2.3.3 dev: true @@ -5848,7 +5933,7 @@ packages: '@types/node': 20.14.0 esbuild: 0.20.2 postcss: 8.4.38 - rollup: 4.18.0 + rollup: 4.18.1 optionalDependencies: fsevents: 2.3.3 dev: true @@ -6093,7 +6178,6 @@ packages: hasBin: true dependencies: isexe: 2.0.0 - dev: true /why-is-node-running@2.2.2: resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} @@ -6150,7 +6234,6 @@ packages: /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} From 8ffcc827ac65e03e538e1ed21013dad7fa251c8b Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Tue, 23 Jul 2024 13:54:41 +0530 Subject: [PATCH 03/10] cli: add preset override and useRuntimeConfig hook --- packages/cli/apibara.config.ts | 13 +++++ packages/cli/package.json | 4 ++ packages/cli/src/apibara.ts | 9 ++- packages/cli/src/build/types.ts | 7 ++- packages/cli/src/config/defaults.ts | 16 ++++-- packages/cli/src/config/index.ts | 5 +- packages/cli/src/config/loader.ts | 14 +---- .../src/config/resolvers/preset.resolver.ts | 10 ++++ .../resolvers/runtime-config.resolver.ts | 1 + packages/cli/src/hooks/useRuntimeConfig.ts | 3 + packages/cli/src/types/apibara.ts | 2 + packages/cli/src/types/config.ts | 57 ++++++++++++++----- pnpm-lock.yaml | 17 ++++-- 13 files changed, 119 insertions(+), 39 deletions(-) create mode 100644 packages/cli/apibara.config.ts create mode 100644 packages/cli/src/config/resolvers/preset.resolver.ts create mode 100644 packages/cli/src/hooks/useRuntimeConfig.ts diff --git a/packages/cli/apibara.config.ts b/packages/cli/apibara.config.ts new file mode 100644 index 0000000..e4949ec --- /dev/null +++ b/packages/cli/apibara.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "./src/config"; + +export default defineConfig({ + runtimeConfig: { + test: 123, + }, + presets: { + dev: { + dev: true, + }, + }, + preset: "dev", +}); diff --git a/packages/cli/package.json b/packages/cli/package.json index bacd4c8..50e90b4 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -20,6 +20,7 @@ } }, "scripts": { + "prepare": "jiti ./src/main.ts prepare", "build": "unbuild", "lint": "biome check .", "typecheck": "tsc --noEmit", @@ -28,13 +29,16 @@ }, "devDependencies": { "@types/node": "^20.14.0", + "jiti": "^1.21.0", "unbuild": "^2.0.0", "vitest": "^1.6.0" }, "dependencies": { "@apibara/indexer": "workspace:*", "c12": "^1.11.1", + "chokidar": "^3.6.0", "citty": "^0.1.6", + "consola": "^3.2.3", "hookable": "^5.5.3", "klona": "^2.0.6", "pathe": "^1.1.2", diff --git a/packages/cli/src/apibara.ts b/packages/cli/src/apibara.ts index e0b4c71..fab22ce 100644 --- a/packages/cli/src/apibara.ts +++ b/packages/cli/src/apibara.ts @@ -1,3 +1,4 @@ +import consola from "consola"; import { createHooks } from "hookable"; import { loadOptions } from "./config/loader"; import { updateApibaraConfig } from "./config/update"; @@ -11,19 +12,23 @@ import type { export async function createApibara( config: ApibaraConfig = {}, opts: LoadConfigOptions = {}, -) { +): Promise { + // load options const options = await loadOptions(config, opts); // create apibara context const apibara: Apibara = { options, hooks: createHooks(), - close: async () => {}, + close: () => apibara.hooks.callHook("close"), + logger: consola.withTag("apibara"), async updateConfig(config: ApibaraDynamicConfig) { updateApibaraConfig(apibara, config); }, }; + apibara.hooks.addHooks(apibara.options.hooks); + // TODO return apibara; } diff --git a/packages/cli/src/build/types.ts b/packages/cli/src/build/types.ts index f29abc2..0049e29 100644 --- a/packages/cli/src/build/types.ts +++ b/packages/cli/src/build/types.ts @@ -2,8 +2,8 @@ import { type JSValue, generateTypes, resolveSchema } from "untyped"; import type { Apibara } from "../types/apibara"; export async function writeTypes(apibara: Apibara) { - // TODO - generateTypes( + // TODO write to a file + const type = generateTypes( await resolveSchema( Object.fromEntries( Object.entries(apibara.options.runtimeConfig), @@ -17,4 +17,7 @@ export async function writeTypes(apibara: Apibara) { indentation: 2, }, ); + + console.log("apibara ---> ", apibara); + console.log("type ---> ", type); } diff --git a/packages/cli/src/config/defaults.ts b/packages/cli/src/config/defaults.ts index 583f677..99b199c 100644 --- a/packages/cli/src/config/defaults.ts +++ b/packages/cli/src/config/defaults.ts @@ -1,5 +1,13 @@ -import type { ApibaraConfig } from "../types/config"; +import { defaultSink } from "@apibara/indexer"; +import { defineConfig } from "."; -export const ApibaraDefaults: ApibaraConfig = { - // TODO -}; +export const ApibaraDefaults = defineConfig({ + dev: false, + rootDir: ".", + outputDir: "./dist", + runtimeConfig: {}, + sink: { + default: defaultSink(), + }, + hooks: {}, +}); diff --git a/packages/cli/src/config/index.ts b/packages/cli/src/config/index.ts index 9eb4b46..4164c96 100644 --- a/packages/cli/src/config/index.ts +++ b/packages/cli/src/config/index.ts @@ -1,5 +1,8 @@ import type { ApibaraConfig } from "../types/config"; -export function defineConfig(config: ApibaraConfig): ApibaraConfig { +export function defineConfig< + // biome-ignore lint/complexity/noBannedTypes: + T extends Record>> = {}, +>(config: ApibaraConfig): ApibaraConfig { return config; } diff --git a/packages/cli/src/config/loader.ts b/packages/cli/src/config/loader.ts index 8e696de..f954098 100644 --- a/packages/cli/src/config/loader.ts +++ b/packages/cli/src/config/loader.ts @@ -7,11 +7,13 @@ import type { } from "../types/config"; import { ApibaraDefaults } from "./defaults"; import { resolvePathOptions } from "./resolvers/paths.resolver"; +import { presetResolver } from "./resolvers/preset.resolver"; import { resolveRuntimeConfigOptions } from "./resolvers/runtime-config.resolver"; const configResolvers = [ resolvePathOptions, resolveRuntimeConfigOptions, + presetResolver, ] as const; export async function loadOptions( @@ -29,11 +31,6 @@ async function _loadUserConfig( configOverrides: ApibaraConfig = {}, opts: LoadConfigOptions = {}, ): Promise { - let presetOverride = configOverrides.preset; - if (configOverrides.dev) { - presetOverride = "apibara-dev"; - } - // biome-ignore lint: noParameterAssign configOverrides = klona(configOverrides); @@ -44,9 +41,8 @@ async function _loadUserConfig( cwd: configOverrides.rootDir, overrides: { ...configOverrides, - preset: presetOverride, }, - defaults: ApibaraDefaults, + defaults: { ...ApibaraDefaults }, ...opts.c12, }); @@ -55,9 +51,5 @@ async function _loadUserConfig( options._config = configOverrides; options._c12 = loadedConfig; - if (presetOverride) { - options.preset = presetOverride; - } - return options; } diff --git a/packages/cli/src/config/resolvers/preset.resolver.ts b/packages/cli/src/config/resolvers/preset.resolver.ts new file mode 100644 index 0000000..7d82356 --- /dev/null +++ b/packages/cli/src/config/resolvers/preset.resolver.ts @@ -0,0 +1,10 @@ +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); +} diff --git a/packages/cli/src/config/resolvers/runtime-config.resolver.ts b/packages/cli/src/config/resolvers/runtime-config.resolver.ts index 079d799..92bdf86 100644 --- a/packages/cli/src/config/resolvers/runtime-config.resolver.ts +++ b/packages/cli/src/config/resolvers/runtime-config.resolver.ts @@ -2,4 +2,5 @@ import type { ApibaraOptions } from "../../types/config"; export async function resolveRuntimeConfigOptions(options: ApibaraOptions) { options.runtimeConfig = { ...options.runtimeConfig, default: "value" }; + process.env.APIBARA_RUNTIME_CONFIG = JSON.stringify(options.runtimeConfig); } diff --git a/packages/cli/src/hooks/useRuntimeConfig.ts b/packages/cli/src/hooks/useRuntimeConfig.ts new file mode 100644 index 0000000..e0ed7f1 --- /dev/null +++ b/packages/cli/src/hooks/useRuntimeConfig.ts @@ -0,0 +1,3 @@ +export function useRuntimeConfig() { + return JSON.parse(process.env.APIBARA_RUNTIME_CONFIG || "{}"); +} diff --git a/packages/cli/src/types/apibara.ts b/packages/cli/src/types/apibara.ts index c3183d5..3dbe087 100644 --- a/packages/cli/src/types/apibara.ts +++ b/packages/cli/src/types/apibara.ts @@ -1,3 +1,4 @@ +import type { ConsolaInstance } from "consola"; import type { Hookable } from "hookable"; import type { ApibaraDynamicConfig, ApibaraOptions } from "./config"; import type { ApibaraHooks } from "./hooks"; @@ -5,6 +6,7 @@ import type { ApibaraHooks } from "./hooks"; export interface Apibara { options: ApibaraOptions; hooks: Hookable; + logger: ConsolaInstance; close: () => Promise; updateConfig: (config: ApibaraDynamicConfig) => void | Promise; } diff --git a/packages/cli/src/types/config.ts b/packages/cli/src/types/config.ts index 4fd15f8..e901b78 100644 --- a/packages/cli/src/types/config.ts +++ b/packages/cli/src/types/config.ts @@ -1,27 +1,35 @@ import type { Sink } from "@apibara/indexer"; -import type { ConfigWatcher, ResolvedConfig, WatchConfigOptions } from "c12"; +import type { + C12InputConfig, + ConfigWatcher, + ResolvedConfig, + WatchConfigOptions, +} from "c12"; +import type { WatchOptions } from "chokidar"; +import type { NestedHooks } from "hookable"; import type { DeepPartial } from "./_utils"; -import type { PresetName } from "./presets"; +import type { ApibaraHooks } from "./hooks"; import type { RollupConfig } from "./rollup"; /** * Apibara Config type (apibara.config) */ -export interface ApibaraConfig - extends DeepPartial> { +export interface ApibaraConfig< + // biome-ignore lint/complexity/noBannedTypes: + T extends Record>> = {}, +> extends DeepPartial, "preset" | "presets">>, + C12InputConfig { sink?: { default: Sink; [key: string]: Sink; }; dev?: boolean; - runtimeConfig?: RuntimeConfig; - presets?: { - [key: string]: Partial; - }; - preset?: string; + runtimeConfig?: ApibaraRuntimeConfig; + presets?: T; + preset?: keyof T; } -export interface RuntimeConfig { +export interface ApibaraRuntimeConfig { [key: string]: unknown; } @@ -35,17 +43,36 @@ export interface LoadConfigOptions { c12?: WatchConfigOptions; } -export interface ApibaraOptions { +export interface ApibaraOptions< + // biome-ignore lint/complexity/noBannedTypes: + T extends Record>> = {}, +> { // Internal - _config: ApibaraConfig; - _c12: ResolvedConfig | ConfigWatcher; + _config: ApibaraConfig; + _c12: ResolvedConfig> | ConfigWatcher>; + + // Sink + sink: { + default: Sink; + [key: string]: Sink; + }; + + // Presets + presets?: T; + preset?: keyof T; + // General debug: boolean; - preset: PresetName; - runtimeConfig: RuntimeConfig; + runtimeConfig: ApibaraRuntimeConfig; rootDir: string; outputDir: string; // Dev dev: boolean; + watchOptions: WatchOptions; + + // Hooks + hooks: NestedHooks; + // Rollup rollupConfig?: RollupConfig; + entry: string; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eca04bd..ca9b1a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -260,9 +260,15 @@ importers: c12: specifier: ^1.11.1 version: 1.11.1 + chokidar: + specifier: ^3.6.0 + version: 3.6.0 citty: specifier: ^0.1.6 version: 0.1.6 + consola: + specifier: ^3.2.3 + version: 3.2.3 hookable: specifier: ^5.5.3 version: 5.5.3 @@ -282,6 +288,9 @@ importers: '@types/node': specifier: ^20.14.0 version: 20.14.0 + jiti: + specifier: ^1.21.0 + version: 1.21.6 unbuild: specifier: ^2.0.0 version: 2.0.0(typescript@5.4.5) @@ -3817,11 +3826,11 @@ packages: /jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true + dev: true /jiti@1.21.6: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true - dev: false /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -4114,7 +4123,7 @@ packages: esbuild: 0.20.2 fs-extra: 11.2.0 globby: 14.0.1 - jiti: 1.21.0 + jiti: 1.21.6 mlly: 1.7.0 mri: 1.2.0 pathe: 1.1.2 @@ -5610,7 +5619,7 @@ packages: esbuild: 0.19.11 globby: 13.2.2 hookable: 5.5.3 - jiti: 1.21.0 + jiti: 1.21.6 magic-string: 0.30.10 mkdist: 1.5.1(typescript@5.4.5) mlly: 1.7.0 @@ -5673,7 +5682,7 @@ packages: '@babel/standalone': 7.24.6 '@babel/types': 7.24.6 defu: 6.1.4 - jiti: 1.21.0 + jiti: 1.21.6 mri: 1.2.0 scule: 1.3.0 transitivePeerDependencies: From 3d2625cabfa4ae48ecf8a8cfb9b89cce1555b935 Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Mon, 29 Jul 2024 15:29:50 +0530 Subject: [PATCH 04/10] cli: add build command and refactor cli --- examples/cli/apibara.config.ts | 19 ++ examples/cli/package.json | 36 ++ examples/cli/src/indexer.ts | 93 ++++++ examples/cli/src/indexers/demo.indexer.ts | 9 + examples/cli/src/indexers/test.indexer.ts | 6 + examples/cli/src/instrumentation.ts | 43 +++ examples/cli/src/main.ts | 4 + examples/cli/tsconfig.json | 11 + packages/cli/apibara.config.ts | 13 - packages/cli/package.json | 9 +- packages/cli/src/commands/build.ts | 12 +- packages/cli/src/commands/prepare.ts | 3 +- packages/cli/src/config/defaults.ts | 5 +- packages/cli/src/config/index.ts | 7 +- packages/cli/src/config/loader.ts | 4 +- .../src/config/resolvers/preset.resolver.ts | 11 +- packages/cli/src/core/build/build.ts | 8 + packages/cli/src/core/build/prepare.ts | 12 + packages/cli/src/core/build/prod.ts | 32 ++ packages/cli/src/{ => core}/build/types.ts | 2 +- packages/cli/src/hooks/index.ts | 1 + packages/cli/src/index.ts | 3 + packages/cli/src/main.ts | 8 +- packages/cli/src/rollup/config.ts | 183 ++++++++++ packages/cli/src/types/config.ts | 36 +- packages/cli/src/types/index.ts | 5 + packages/cli/src/types/presets.ts | 2 - pnpm-lock.yaml | 315 +++++++++++++++++- 28 files changed, 826 insertions(+), 66 deletions(-) create mode 100644 examples/cli/apibara.config.ts create mode 100644 examples/cli/package.json create mode 100644 examples/cli/src/indexer.ts create mode 100644 examples/cli/src/indexers/demo.indexer.ts create mode 100644 examples/cli/src/indexers/test.indexer.ts create mode 100644 examples/cli/src/instrumentation.ts create mode 100644 examples/cli/src/main.ts create mode 100644 examples/cli/tsconfig.json delete mode 100644 packages/cli/apibara.config.ts create mode 100644 packages/cli/src/core/build/build.ts create mode 100644 packages/cli/src/core/build/prepare.ts create mode 100644 packages/cli/src/core/build/prod.ts rename packages/cli/src/{ => core}/build/types.ts (91%) create mode 100644 packages/cli/src/hooks/index.ts mode change 100644 => 100755 packages/cli/src/main.ts create mode 100644 packages/cli/src/rollup/config.ts create mode 100644 packages/cli/src/types/index.ts delete mode 100644 packages/cli/src/types/presets.ts diff --git a/examples/cli/apibara.config.ts b/examples/cli/apibara.config.ts new file mode 100644 index 0000000..348c1df --- /dev/null +++ b/examples/cli/apibara.config.ts @@ -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(), + }, +}); diff --git a/examples/cli/package.json b/examples/cli/package.json new file mode 100644 index 0000000..96d4fcd --- /dev/null +++ b/examples/cli/package.json @@ -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" + } +} diff --git a/examples/cli/src/indexer.ts b/examples/cli/src/indexer.ts new file mode 100644 index 0000000..c28dddd --- /dev/null +++ b/examples/cli/src/indexer.ts @@ -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: [], + }); +} diff --git a/examples/cli/src/indexers/demo.indexer.ts b/examples/cli/src/indexers/demo.indexer.ts new file mode 100644 index 0000000..263a586 --- /dev/null +++ b/examples/cli/src/indexers/demo.indexer.ts @@ -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"), + ); +} diff --git a/examples/cli/src/indexers/test.indexer.ts b/examples/cli/src/indexers/test.indexer.ts new file mode 100644 index 0000000..277ae5b --- /dev/null +++ b/examples/cli/src/indexers/test.indexer.ts @@ -0,0 +1,6 @@ +import { createIndexer } from "@apibara/indexer"; +import { createIndexerConfig } from "../indexer"; + +export default createIndexer( + createIndexerConfig("http://mainnet-v2.starknet.a5a.ch:7007"), +); diff --git a/examples/cli/src/instrumentation.ts b/examples/cli/src/instrumentation.ts new file mode 100644 index 0000000..feeb160 --- /dev/null +++ b/examples/cli/src/instrumentation.ts @@ -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(); diff --git a/examples/cli/src/main.ts b/examples/cli/src/main.ts new file mode 100644 index 0000000..5614928 --- /dev/null +++ b/examples/cli/src/main.ts @@ -0,0 +1,4 @@ +import { mainCli } from "@apibara/cli"; +import { runMain } from "citty"; + +runMain(mainCli); diff --git a/examples/cli/tsconfig.json b/examples/cli/tsconfig.json new file mode 100644 index 0000000..9d05974 --- /dev/null +++ b/examples/cli/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": "dist", + "noEmit": false, + "rootDir": "src", + "types": ["node"] + }, + "include": ["src/"] +} diff --git a/packages/cli/apibara.config.ts b/packages/cli/apibara.config.ts deleted file mode 100644 index e4949ec..0000000 --- a/packages/cli/apibara.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from "./src/config"; - -export default defineConfig({ - runtimeConfig: { - test: 123, - }, - presets: { - dev: { - dev: true, - }, - }, - preset: "dev", -}); diff --git a/packages/cli/package.json b/packages/cli/package.json index 50e90b4..8f7cf8e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -20,7 +20,6 @@ } }, "scripts": { - "prepare": "jiti ./src/main.ts prepare", "build": "unbuild", "lint": "biome check .", "typecheck": "tsc --noEmit", @@ -28,6 +27,7 @@ "format": "biome format . --write" }, "devDependencies": { + "@types/fs-extra": "^11.0.4", "@types/node": "^20.14.0", "jiti": "^1.21.0", "unbuild": "^2.0.0", @@ -35,14 +35,21 @@ }, "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" } } diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts index 3fae247..ce189af 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/commands/build.ts @@ -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: { @@ -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(); }, }); diff --git a/packages/cli/src/commands/prepare.ts b/packages/cli/src/commands/prepare.ts index b6edc93..51ea497 100644 --- a/packages/cli/src/commands/prepare.ts +++ b/packages/cli/src/commands/prepare.ts @@ -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: { @@ -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); diff --git a/packages/cli/src/config/defaults.ts b/packages/cli/src/config/defaults.ts index 99b199c..4819d62 100644 --- a/packages/cli/src/config/defaults.ts +++ b/packages/cli/src/config/defaults.ts @@ -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: {}, }); diff --git a/packages/cli/src/config/index.ts b/packages/cli/src/config/index.ts index 4164c96..1677c14 100644 --- a/packages/cli/src/config/index.ts +++ b/packages/cli/src/config/index.ts @@ -1,8 +1,11 @@ +import type { DeepPartial } from "../types"; import type { ApibaraConfig } from "../types/config"; export function defineConfig< // biome-ignore lint/complexity/noBannedTypes: - T extends Record>> = {}, ->(config: ApibaraConfig): ApibaraConfig { + T extends Record>> = {}, + // biome-ignore lint/complexity/noBannedTypes: + R extends Record = {}, +>(config: ApibaraConfig): ApibaraConfig { return config; } diff --git a/packages/cli/src/config/loader.ts b/packages/cli/src/config/loader.ts index f954098..13b1ffe 100644 --- a/packages/cli/src/config/loader.ts +++ b/packages/cli/src/config/loader.ts @@ -38,7 +38,9 @@ async function _loadUserConfig( ? watchConfig : loadConfig)({ name: "apibara", - cwd: configOverrides.rootDir, + // path from where apibara.config.ts is loaded + // defautl is "." path + // cwd: configOverrides.rootDir, overrides: { ...configOverrides, }, diff --git a/packages/cli/src/config/resolvers/preset.resolver.ts b/packages/cli/src/config/resolvers/preset.resolver.ts index 7d82356..96a191a 100644 --- a/packages/cli/src/config/resolvers/preset.resolver.ts +++ b/packages/cli/src/config/resolvers/preset.resolver.ts @@ -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); + } } diff --git a/packages/cli/src/core/build/build.ts b/packages/cli/src/core/build/build.ts new file mode 100644 index 0000000..4d1ef98 --- /dev/null +++ b/packages/cli/src/core/build/build.ts @@ -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); +} diff --git a/packages/cli/src/core/build/prepare.ts b/packages/cli/src/core/build/prepare.ts new file mode 100644 index 0000000..f9c03c6 --- /dev/null +++ b/packages/cli/src/core/build/prepare.ts @@ -0,0 +1,12 @@ +import fsp from "node:fs/promises"; +import fse from "fs-extra"; +import type { Apibara } from "../../types/apibara"; + +export async function prepare(apibara: Apibara) { + await prepareDir(apibara.options.outputDir); +} + +async function prepareDir(dir: string) { + await fsp.mkdir(dir, { recursive: true }); + await fse.emptyDir(dir); +} diff --git a/packages/cli/src/core/build/prod.ts b/packages/cli/src/core/build/prod.ts new file mode 100644 index 0000000..7e4703a --- /dev/null +++ b/packages/cli/src/core/build/prod.ts @@ -0,0 +1,32 @@ +import { type OutputOptions, rollup } from "rollup"; +import type { Apibara } from "../../types/apibara"; +import type { RollupConfig } from "../../types/rollup"; + +export async function buildProduction( + apibara: Apibara, + rollupConfig: RollupConfig, +) { + try { + // Create a bundle + const bundle = await rollup(rollupConfig); + + // Generate output + if (Array.isArray(rollupConfig.output)) { + for (const outputOptions of rollupConfig.output) { + await bundle.write(outputOptions); + } + } else if (rollupConfig.output) { + await bundle.write(rollupConfig.output as OutputOptions); + } else { + throw new Error("No output options specified in Rollup config"); + } + + // Close the bundle + await bundle.close(); + + console.log("Build completed successfully!"); + } catch (error) { + console.error("Build failed:", error); + throw error; + } +} diff --git a/packages/cli/src/build/types.ts b/packages/cli/src/core/build/types.ts similarity index 91% rename from packages/cli/src/build/types.ts rename to packages/cli/src/core/build/types.ts index 0049e29..0f25bf0 100644 --- a/packages/cli/src/build/types.ts +++ b/packages/cli/src/core/build/types.ts @@ -1,5 +1,5 @@ import { type JSValue, generateTypes, resolveSchema } from "untyped"; -import type { Apibara } from "../types/apibara"; +import type { Apibara } from "../../types/apibara"; export async function writeTypes(apibara: Apibara) { // TODO write to a file diff --git a/packages/cli/src/hooks/index.ts b/packages/cli/src/hooks/index.ts new file mode 100644 index 0000000..3f315ee --- /dev/null +++ b/packages/cli/src/hooks/index.ts @@ -0,0 +1 @@ +export * from "./useRuntimeConfig"; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index d66d2cd..c838408 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1 +1,4 @@ export * from "./main"; +export * from "./types"; +export * from "./hooks"; +export * from "./config"; diff --git a/packages/cli/src/main.ts b/packages/cli/src/main.ts old mode 100644 new mode 100755 index 4b0c2ed..2735e9d --- a/packages/cli/src/main.ts +++ b/packages/cli/src/main.ts @@ -1,6 +1,6 @@ -import { defineCommand, runMain } from "citty"; +import { defineCommand } from "citty"; -const main = defineCommand({ +export const mainCli = defineCommand({ meta: { name: "apibara", description: "Apibara CLI", @@ -12,5 +12,5 @@ const main = defineCommand({ prepare: () => import("./commands/prepare").then((r) => r.default), }, }); - -runMain(main); +// TODO uncomment when we build the CLI +// runMain(mainCli); diff --git a/packages/cli/src/rollup/config.ts b/packages/cli/src/rollup/config.ts new file mode 100644 index 0000000..cd49ec1 --- /dev/null +++ b/packages/cli/src/rollup/config.ts @@ -0,0 +1,183 @@ +import { existsSync } from "node:fs"; +import { builtinModules } from "node:module"; +import commonjs from "@rollup/plugin-commonjs"; +import json from "@rollup/plugin-json"; +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import typescript from "@rollup/plugin-typescript"; +import { readdirSync } from "fs-extra"; +import { basename, join } from "pathe"; +import type { Apibara } from "../types/apibara"; +import type { RollupConfig } from "../types/rollup"; + +export const getRollupConfig = ( + apibara: Apibara, + dev = false, +): RollupConfig => { + const extensions: string[] = [ + ".ts", + ".mjs", + ".js", + ".json", + ".node", + ".tsx", + ".jsx", + ]; + + const indexerDir = join(apibara.options.rootDir, "indexers"); + const configPath = join("./apibara.config.ts"); + + // Check if the indexers directory and config file exist + if (!existsSync(indexerDir)) { + throw new Error(`Indexers directory not found: ${indexerDir}`); + } + if (!existsSync(configPath)) { + throw new Error(`Config file not found: ${configPath}`); + } + + // Check if the indexers directory exists and is not empty + let indexerFiles: string[] = []; + try { + indexerFiles = readdirSync(indexerDir).filter((file) => + file.endsWith(".indexer.ts"), + ); + if (indexerFiles.length === 0) { + console.warn(`No indexer files found in ${indexerDir}`); + } + } catch (error) { + console.error(`Error reading indexers directory: ${error}`); + } + + const indexerImports = indexerFiles + .map( + (file, index) => + `import indexer${index} from '${join(indexerDir, file)}';`, + ) + .join("\n"); + + // Generate main.ts content + const mainContent = ` +import { createClient } from "@apibara/protocol"; +import { run } from "@apibara/indexer"; +import { defineCommand, runMain } from "citty"; +import config from './${configPath}'; + +${indexerImports} + +const indexers = { + ${indexerFiles + .map( + (file, index) => `'${basename(file, ".indexer.ts")}': indexer${index},`, + ) + .join("\n ")} +}; + +const command = defineCommand({ + meta: { + name: "run-indexers", + description: "Run Apibara indexers", + }, + args: { + indexers: { + type: "string", + description: "Comma-separated list of indexers to run", + }, + preset: { + type: "string", + description: "Preset to use", + }, + sink: { + type: "string", + description: "Sink to use", + }, + }, + async run({ args }) { + const selectedIndexers = args.indexers ? args.indexers.split(',') : Object.keys(indexers); + const preset = args.preset || config.preset || 'default'; + const sinkName = args.sink || 'default'; + + // Apply preset + let runtimeConfig = { ...config.runtimeConfig }; + if (preset && config.presets && config.presets[preset]) { + runtimeConfig = { ...runtimeConfig, ...config.presets[preset].runtimeConfig }; + } + + // Get sink function + const sinkFunction = config.sink?.[sinkName]; + if (!sinkFunction) { + throw new Error(\`Sink \${sinkName} not found\`); + } + + await Promise.all(selectedIndexers.map(async (name) => { + if (!indexers[name]) { + console.error(\`Indexer \${name} not found\`); + return; + } + + const indexerFactory = indexers[name]; + const indexer = typeof indexerFactory === 'function' + ? await indexerFactory(runtimeConfig) + : indexerFactory; + + const client = createClient(indexer.streamConfig, indexer.options.streamUrl); + const sink = sinkFunction(); + + try { + console.log("Running Indexer: ", name); + await run(client, indexer, sink); + } catch (error) { + console.error(\`Error in indexer \${name}:\`, error); + } + })); + }, +}); + +runMain(command); +`; + + return { + input: { + main: "virtual:main.ts", + }, + output: { + dir: join(apibara.options.outputDir || "dist"), + format: "esm", + entryFileNames: "[name].mjs", + chunkFileNames: "chunks/[name]-[hash].mjs", + }, + plugins: [ + commonjs(), + json(), + typescript({ + tsconfig: join("./tsconfig.json"), + }), + nodeResolve({ + extensions, + preferBuiltins: true, + }), + { + name: "virtual", + resolveId(id) { + if (id === "virtual:main.ts") { + return id; + } + return null; + }, + load(id) { + if (id === "virtual:main.ts") { + return mainContent; + } + return null; + }, + }, + ], + external: [ + ...builtinModules, + "@apibara/indexer", + "@apibara/protocol", + "@apibara/evm", + "@apibara/starknet", + "@apibara/beaconchain", + "@apibara/cli", + ], + }; +}; diff --git a/packages/cli/src/types/config.ts b/packages/cli/src/types/config.ts index e901b78..ae195ea 100644 --- a/packages/cli/src/types/config.ts +++ b/packages/cli/src/types/config.ts @@ -16,23 +16,20 @@ import type { RollupConfig } from "./rollup"; */ export interface ApibaraConfig< // biome-ignore lint/complexity/noBannedTypes: - T extends Record>> = {}, -> extends DeepPartial, "preset" | "presets">>, - C12InputConfig { + T extends Record>> = {}, + // biome-ignore lint/complexity/noBannedTypes: + R extends Record = {}, +> extends DeepPartial, "preset" | "presets" | "dev">>, + C12InputConfig> { sink?: { - default: Sink; - [key: string]: Sink; + default: () => Sink; + [key: string]: () => Sink; }; - dev?: boolean; - runtimeConfig?: ApibaraRuntimeConfig; + runtimeConfig?: R; presets?: T; preset?: keyof T; } -export interface ApibaraRuntimeConfig { - [key: string]: unknown; -} - export type ApibaraDynamicConfig = Pick; /** @@ -45,16 +42,20 @@ export interface LoadConfigOptions { export interface ApibaraOptions< // biome-ignore lint/complexity/noBannedTypes: - T extends Record>> = {}, + T extends Record>> = {}, + // biome-ignore lint/complexity/noBannedTypes: + R extends Record = {}, > { // Internal - _config: ApibaraConfig; - _c12: ResolvedConfig> | ConfigWatcher>; + _config: ApibaraConfig; + _c12: + | ResolvedConfig> + | ConfigWatcher>; // Sink sink: { - default: Sink; - [key: string]: Sink; + default: () => Sink; + [key: string]: () => Sink; }; // Presets @@ -63,7 +64,7 @@ export interface ApibaraOptions< // General debug: boolean; - runtimeConfig: ApibaraRuntimeConfig; + runtimeConfig: R; rootDir: string; outputDir: string; // Dev @@ -75,4 +76,5 @@ export interface ApibaraOptions< // Rollup rollupConfig?: RollupConfig; entry: string; + minify: boolean; } diff --git a/packages/cli/src/types/index.ts b/packages/cli/src/types/index.ts new file mode 100644 index 0000000..a3ff743 --- /dev/null +++ b/packages/cli/src/types/index.ts @@ -0,0 +1,5 @@ +export * from "./apibara"; +export * from "./_utils"; +export * from "./config"; +export * from "./hooks"; +export * from "./rollup"; diff --git a/packages/cli/src/types/presets.ts b/packages/cli/src/types/presets.ts deleted file mode 100644 index 1ebe7e7..0000000 --- a/packages/cli/src/types/presets.ts +++ /dev/null @@ -1,2 +0,0 @@ -// TODO -export type PresetName = string; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ca9b1a2..65482a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,6 +49,64 @@ importers: specifier: ^1.21.0 version: 1.21.0 + examples/cli: + dependencies: + '@apibara/cli': + specifier: workspace:* + version: link:../../packages/cli + '@apibara/evm': + specifier: workspace:* + version: link:../../packages/evm + '@apibara/indexer': + specifier: workspace:* + version: link:../../packages/indexer + '@apibara/protocol': + specifier: workspace:* + version: link:../../packages/protocol + '@opentelemetry/api': + specifier: ^1.9.0 + version: 1.9.0 + '@opentelemetry/exporter-trace-otlp-proto': + specifier: ^0.52.0 + version: 0.52.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': + specifier: ^1.25.0 + version: 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-node': + specifier: ^0.52.0 + version: 0.52.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': + specifier: ^1.25.0 + version: 1.25.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': + specifier: ^1.25.0 + version: 1.25.0 + better-sqlite3: + specifier: ^11.1.2 + version: 11.1.2 + citty: + specifier: ^0.1.6 + version: 0.1.6 + consola: + specifier: ^3.2.3 + version: 3.2.3 + csv-stringify: + specifier: ^6.5.0 + version: 6.5.0 + viem: + specifier: ^2.12.4 + version: 2.13.8(typescript@5.4.5) + devDependencies: + '@types/better-sqlite3': + specifier: ^7.6.11 + version: 7.6.11 + '@types/node': + specifier: ^20.12.12 + version: 20.14.0 + jiti: + specifier: ^1.21.0 + version: 1.21.6 + examples/evm-client: dependencies: '@apibara/evm': @@ -257,6 +315,18 @@ importers: '@apibara/indexer': specifier: workspace:* version: link:../indexer + '@rollup/plugin-commonjs': + specifier: ^26.0.1 + version: 26.0.1(rollup@4.18.1) + '@rollup/plugin-json': + specifier: ^6.1.0 + version: 6.1.0(rollup@4.18.1) + '@rollup/plugin-node-resolve': + specifier: ^15.2.3 + version: 15.2.3(rollup@4.18.1) + '@rollup/plugin-typescript': + specifier: ^11.1.6 + version: 11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.4.5) c12: specifier: ^1.11.1 version: 1.11.1 @@ -269,6 +339,12 @@ importers: consola: specifier: ^3.2.3 version: 3.2.3 + defu: + specifier: ^6.1.4 + version: 6.1.4 + fs-extra: + specifier: ^11.2.0 + version: 11.2.0 hookable: specifier: ^5.5.3 version: 5.5.3 @@ -281,10 +357,16 @@ importers: rollup: specifier: ^4.18.1 version: 4.18.1 + tslib: + specifier: ^2.6.3 + version: 2.6.3 untyped: specifier: ^1.4.2 version: 1.4.2 devDependencies: + '@types/fs-extra': + specifier: ^11.0.4 + version: 11.0.4 '@types/node': specifier: ^20.14.0 version: 20.14.0 @@ -1548,6 +1630,18 @@ packages: yargs: 17.7.2 dev: false + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: false + /@jest/schemas@29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1889,6 +1983,13 @@ packages: engines: {node: '>=14'} dev: false + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: false + optional: true + /@protobufjs/aspromise@1.1.2: resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} dev: false @@ -1963,6 +2064,24 @@ packages: rollup: 3.29.4 dev: true + /@rollup/plugin-commonjs@26.0.1(rollup@4.18.1): + resolution: {integrity: sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 10.4.5 + is-reference: 1.2.1 + magic-string: 0.30.10 + rollup: 4.18.1 + dev: false + /@rollup/plugin-json@6.1.0(rollup@3.29.4): resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} engines: {node: '>=14.0.0'} @@ -1976,6 +2095,19 @@ packages: rollup: 3.29.4 dev: true + /@rollup/plugin-json@6.1.0(rollup@4.18.1): + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) + rollup: 4.18.1 + dev: false + /@rollup/plugin-node-resolve@15.2.3(rollup@3.29.4): resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} engines: {node: '>=14.0.0'} @@ -1994,6 +2126,24 @@ packages: rollup: 3.29.4 dev: true + /@rollup/plugin-node-resolve@15.2.3(rollup@4.18.1): + resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.8 + rollup: 4.18.1 + dev: false + /@rollup/plugin-replace@5.0.5(rollup@3.29.4): resolution: {integrity: sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==} engines: {node: '>=14.0.0'} @@ -2008,6 +2158,26 @@ packages: rollup: 3.29.4 dev: true + /@rollup/plugin-typescript@11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.4.5): + resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.18.1) + resolve: 1.22.8 + rollup: 4.18.1 + tslib: 2.6.3 + typescript: 5.4.5 + dev: false + /@rollup/pluginutils@5.1.0(rollup@3.29.4): resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} engines: {node: '>=14.0.0'} @@ -2023,6 +2193,21 @@ packages: rollup: 3.29.4 dev: true + /@rollup/pluginutils@5.1.0(rollup@4.18.1): + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 4.18.1 + dev: false + /@rollup/rollup-android-arm-eabi@4.18.1: resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==} cpu: [arm] @@ -2174,6 +2359,19 @@ packages: /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + /@types/fs-extra@11.0.4: + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 20.14.0 + dev: true + + /@types/jsonfile@6.1.4: + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + dependencies: + '@types/node': 20.14.0 + dev: true + /@types/long@5.0.0: resolution: {integrity: sha512-eQs9RsucA/LNjnMoJvWG/nXa7Pot/RbBzilF/QRIU/xRl+0ApxrSUFsV5lmf01SvSlqMzJ7Zwxe440wmz2SJGA==} deprecated: This is a stub types definition. long provides its own type definitions, so you do not need this installed. @@ -2212,7 +2410,6 @@ packages: /@types/resolve@1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - dev: true /@types/semver@7.5.8: resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -2305,6 +2502,11 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: false + /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -2323,6 +2525,11 @@ packages: engines: {node: '>=10'} dev: true + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: false + /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -2408,7 +2615,6 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -2452,7 +2658,6 @@ packages: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 - dev: true /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} @@ -2485,7 +2690,6 @@ packages: /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - dev: true /c12@1.11.1: resolution: {integrity: sha512-KDU0TvSvVdaYcQKQ6iPHATGz/7p/KiVjPg4vQrB6Jg/wX9R0yl5RZxWm9IoZqaIHD2+6PZd81+KMGwRr/lRIUg==} @@ -2684,7 +2888,6 @@ packages: /commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true /confbox@0.1.7: resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} @@ -2924,7 +3127,6 @@ packages: /deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - dev: true /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -3015,6 +3217,10 @@ packages: engines: {node: '>=10'} dev: true + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + /effect@3.2.6: resolution: {integrity: sha512-0DMjunl0BgBBcn0g5innUONI3fVz2BHLILUeemYivyStCXZl6G7rzMMiipjjFu+0oQ/FKinR+gwwAZEAvdabDw==} dev: false @@ -3025,6 +3231,10 @@ packages: /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: @@ -3227,7 +3437,6 @@ packages: /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true /estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -3327,6 +3536,14 @@ packages: is-callable: 1.2.7 dev: true + /foreground-child@3.2.1: + resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: false + /fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} dev: true @@ -3341,7 +3558,6 @@ packages: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - dev: true /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} @@ -3455,6 +3671,18 @@ packages: dependencies: is-glob: 4.0.3 + /glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + dependencies: + foreground-child: 3.2.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 1.11.1 + dev: false + /glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} @@ -3521,7 +3749,6 @@ packages: /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true /grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} @@ -3680,7 +3907,6 @@ packages: engines: {node: '>=6'} dependencies: builtin-modules: 3.3.0 - dev: true /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} @@ -3722,7 +3948,6 @@ packages: /is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - dev: true /is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} @@ -3749,7 +3974,6 @@ packages: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} dependencies: '@types/estree': 1.0.5 - dev: true /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} @@ -3823,6 +4047,14 @@ packages: dependencies: ws: 8.13.0 + /jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: false + /jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true @@ -3874,7 +4106,6 @@ packages: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - dev: true /kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} @@ -3961,6 +4192,10 @@ packages: get-func-name: 2.0.2 dev: true + /lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + dev: false + /lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} dependencies: @@ -4055,6 +4290,13 @@ packages: brace-expansion: 2.0.1 dev: true + /minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: false + /minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -4079,6 +4321,11 @@ packages: engines: {node: '>=8'} dev: false + /minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + dev: false + /minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} @@ -4349,6 +4596,10 @@ packages: engines: {node: '>=6'} dev: true + /package-json-from-dist@1.0.0: + resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + dev: false + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -4375,6 +4626,14 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + /path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + dev: false + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -5250,6 +5509,15 @@ packages: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: false + /string.prototype.trim@1.2.9: resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} engines: {node: '>= 0.4'} @@ -5289,6 +5557,13 @@ packages: dependencies: ansi-regex: 5.0.1 + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: false + /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -5437,6 +5712,10 @@ packages: resolution: {integrity: sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==} dev: false + /tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + dev: false + /tty-table@4.2.3: resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} engines: {node: '>=8.0.0'} @@ -5662,7 +5941,6 @@ packages: /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - dev: true /unplugin@1.10.1: resolution: {integrity: sha512-d6Mhq8RJeGA8UfKCu54Um4lFA0eSaRa3XxdAJg8tIdxbu1ubW0hBCZUL7yI2uGyYCRndvbK8FLHzqy2XKfeMsg==} @@ -6214,6 +6492,15 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: false + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} From f374a440d6d4d7e593064b6cd34b7321d486efa9 Mon Sep 17 00:00:00 2001 From: Francesco Ceccon Date: Mon, 29 Jul 2024 15:11:20 +0200 Subject: [PATCH 05/10] cli: isolate modules --- examples/cli/apibara.config.ts | 2 +- examples/cli/indexers/simple.indexer.ts | 30 ++++++ examples/cli/indexers/with-config.indexer.ts | 34 +++++++ examples/cli/package.json | 8 +- examples/cli/src/indexer.ts | 93 ------------------- examples/cli/src/indexers/demo.indexer.ts | 9 -- examples/cli/src/indexers/test.indexer.ts | 6 -- examples/cli/src/instrumentation.ts | 43 --------- examples/cli/src/main.ts | 4 - examples/cli/tsconfig.json | 12 ++- packages/cli/build.config.ts | 37 ++++++++ packages/cli/package.json | 47 ++++++---- packages/cli/src/{ => cli}/commands/build.ts | 7 +- packages/cli/src/{ => cli}/commands/dev.ts | 2 + .../cli/src/{ => cli}/commands/prepare.ts | 9 +- packages/cli/src/{ => cli}/common.ts | 0 packages/cli/src/{main.ts => cli/index.ts} | 6 +- packages/cli/src/config/defaults.ts | 12 --- packages/cli/src/config/index.ts | 4 +- packages/cli/src/{ => core}/apibara.ts | 4 +- packages/cli/src/core/build/build.ts | 4 +- packages/cli/src/core/build/prepare.ts | 2 +- packages/cli/src/core/config/defaults.ts | 12 +++ packages/cli/src/{ => core}/config/loader.ts | 22 ++--- .../config/resolvers/paths.resolver.ts | 2 +- .../config/resolvers/preset.resolver.ts | 2 +- .../resolvers/runtime-config.resolver.ts | 2 +- packages/cli/src/{ => core}/config/update.ts | 3 +- packages/cli/src/core/index.ts | 3 + packages/cli/src/index.ts | 4 - packages/cli/src/rollup/config.ts | 21 ++--- packages/cli/src/rollup/index.ts | 1 + packages/cli/tsconfig.json | 27 +++++- pnpm-lock.yaml | 6 +- 34 files changed, 234 insertions(+), 246 deletions(-) create mode 100644 examples/cli/indexers/simple.indexer.ts create mode 100644 examples/cli/indexers/with-config.indexer.ts delete mode 100644 examples/cli/src/indexer.ts delete mode 100644 examples/cli/src/indexers/demo.indexer.ts delete mode 100644 examples/cli/src/indexers/test.indexer.ts delete mode 100644 examples/cli/src/instrumentation.ts delete mode 100644 examples/cli/src/main.ts create mode 100644 packages/cli/build.config.ts rename packages/cli/src/{ => cli}/commands/build.ts (75%) rename packages/cli/src/{ => cli}/commands/dev.ts (81%) rename packages/cli/src/{ => cli}/commands/prepare.ts (70%) rename packages/cli/src/{ => cli}/common.ts (100%) rename packages/cli/src/{main.ts => cli/index.ts} (78%) delete mode 100644 packages/cli/src/config/defaults.ts rename packages/cli/src/{ => core}/apibara.ts (91%) create mode 100644 packages/cli/src/core/config/defaults.ts rename packages/cli/src/{ => core}/config/loader.ts (81%) rename packages/cli/src/{ => core}/config/resolvers/paths.resolver.ts (73%) rename packages/cli/src/{ => core}/config/resolvers/preset.resolver.ts (82%) rename packages/cli/src/{ => core}/config/resolvers/runtime-config.resolver.ts (80%) rename packages/cli/src/{ => core}/config/update.ts (67%) create mode 100644 packages/cli/src/core/index.ts delete mode 100644 packages/cli/src/index.ts create mode 100644 packages/cli/src/rollup/index.ts diff --git a/examples/cli/apibara.config.ts b/examples/cli/apibara.config.ts index 348c1df..d2f4d88 100644 --- a/examples/cli/apibara.config.ts +++ b/examples/cli/apibara.config.ts @@ -1,4 +1,4 @@ -import { defineConfig } from "@apibara/cli"; +import { defineConfig } from "apibara/config"; import { defaultSink } from "@apibara/indexer"; export default defineConfig({ diff --git a/examples/cli/indexers/simple.indexer.ts b/examples/cli/indexers/simple.indexer.ts new file mode 100644 index 0000000..8010c1d --- /dev/null +++ b/examples/cli/indexers/simple.indexer.ts @@ -0,0 +1,30 @@ +import { EvmStream } from "@apibara/evm"; +import { defineIndexer } from "@apibara/indexer"; +import { encodeEventTopics, parseAbi } from "viem"; + +const abi = parseAbi([ + "event Transfer(address indexed from, address indexed to, uint256 value)", +]); + +export default defineIndexer(EvmStream)({ + streamUrl: "https://sepolia.ethereum.a5a.ch", + finality: "accepted", + startingCursor: { + orderKey: 5_000_000n, + }, + filter: { + logs: [ + { + strict: true, + topics: encodeEventTopics({ + abi, + eventName: "Transfer", + args: { from: null, to: null }, + }) as `0x${string}`[], + }, + ], + }, + async transform({ block: { header } }) { + return [header]; + }, +}) diff --git a/examples/cli/indexers/with-config.indexer.ts b/examples/cli/indexers/with-config.indexer.ts new file mode 100644 index 0000000..7dc8777 --- /dev/null +++ b/examples/cli/indexers/with-config.indexer.ts @@ -0,0 +1,34 @@ +import { EvmStream } from "@apibara/evm"; +import { defineIndexer } from "@apibara/indexer"; +import { encodeEventTopics, parseAbi } from "viem"; + +const abi = parseAbi([ + "event Transfer(address indexed from, address indexed to, uint256 value)", +]); + +// TODO: `runtimeConfig` type should come from the generated types file +export default function indexer(runtimeConfig: unknown) { + console.log("runtimeConfig", runtimeConfig); + return defineIndexer(EvmStream)({ + streamUrl: "https://sepolia.ethereum.a5a.ch", + finality: "accepted", + startingCursor: { + orderKey: 5_000_000n, + }, + filter: { + logs: [ + { + strict: true, + topics: encodeEventTopics({ + abi, + eventName: "Transfer", + args: { from: null, to: null }, + }) as `0x${string}`[], + }, + ], + }, + async transform({ block: { header } }) { + return [header]; + }, + }) +} diff --git a/examples/cli/package.json b/examples/cli/package.json index 96d4fcd..43c7bdd 100644 --- a/examples/cli/package.json +++ b/examples/cli/package.json @@ -3,9 +3,7 @@ "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", + "build": "apibara build", "typecheck": "tsc --noEmit", "lint": "biome check .", "lint:fix": "pnpm lint --write", @@ -15,13 +13,13 @@ "@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", + "apibara": "workspace:*", "better-sqlite3": "^11.1.2", "citty": "^0.1.6", "consola": "^3.2.3", @@ -33,4 +31,4 @@ "@types/node": "^20.12.12", "jiti": "^1.21.0" } -} +} \ No newline at end of file diff --git a/examples/cli/src/indexer.ts b/examples/cli/src/indexer.ts deleted file mode 100644 index c28dddd..0000000 --- a/examples/cli/src/indexer.ts +++ /dev/null @@ -1,93 +0,0 @@ -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: [], - }); -} diff --git a/examples/cli/src/indexers/demo.indexer.ts b/examples/cli/src/indexers/demo.indexer.ts deleted file mode 100644 index 263a586..0000000 --- a/examples/cli/src/indexers/demo.indexer.ts +++ /dev/null @@ -1,9 +0,0 @@ -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"), - ); -} diff --git a/examples/cli/src/indexers/test.indexer.ts b/examples/cli/src/indexers/test.indexer.ts deleted file mode 100644 index 277ae5b..0000000 --- a/examples/cli/src/indexers/test.indexer.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createIndexer } from "@apibara/indexer"; -import { createIndexerConfig } from "../indexer"; - -export default createIndexer( - createIndexerConfig("http://mainnet-v2.starknet.a5a.ch:7007"), -); diff --git a/examples/cli/src/instrumentation.ts b/examples/cli/src/instrumentation.ts deleted file mode 100644 index feeb160..0000000 --- a/examples/cli/src/instrumentation.ts +++ /dev/null @@ -1,43 +0,0 @@ -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(); diff --git a/examples/cli/src/main.ts b/examples/cli/src/main.ts deleted file mode 100644 index 5614928..0000000 --- a/examples/cli/src/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { mainCli } from "@apibara/cli"; -import { runMain } from "citty"; - -runMain(mainCli); diff --git a/examples/cli/tsconfig.json b/examples/cli/tsconfig.json index 9d05974..0f2829f 100644 --- a/examples/cli/tsconfig.json +++ b/examples/cli/tsconfig.json @@ -4,8 +4,12 @@ "outDir": "dist", "declarationDir": "dist", "noEmit": false, - "rootDir": "src", - "types": ["node"] + "rootDir": ".", + "types": [ + "node" + ] }, - "include": ["src/"] -} + "include": [ + "indexers/" + ] +} \ No newline at end of file diff --git a/packages/cli/build.config.ts b/packages/cli/build.config.ts new file mode 100644 index 0000000..f87c7f6 --- /dev/null +++ b/packages/cli/build.config.ts @@ -0,0 +1,37 @@ +import { defineBuildConfig } from "unbuild"; +import { fileURLToPath } from "node:url"; +import { resolve } from "pathe"; + +const modules = [ + "cli", + "config", + "core", + "rollup", + "types", +]; + +const srcDir = fileURLToPath(new URL("src", import.meta.url)); + +export default defineBuildConfig({ + entries: [ + { input: "./src/cli/index.ts" }, + { input: "./src/config/index.ts" }, + { input: "./src/core/index.ts" }, + { input: "./src/rollup/index.ts" }, + ], + clean: true, + outDir: "./dist", + declaration: true, + alias: { + ...Object.fromEntries( + modules.map((module) => [ + `apibara/${module}`, + resolve(srcDir, `${module}/index.ts`), + ]) + ), + }, + externals: [ + ...modules.map((module) => `apibara/${module}`), + ], +}); + diff --git a/packages/cli/package.json b/packages/cli/package.json index 8f7cf8e..06e63e3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,24 +1,39 @@ { - "name": "@apibara/cli", + "name": "apibara", "version": "2.0.0", "type": "module", - "source": "./src/index.ts", - "main": "./src/index.ts", + "source": "./src/core/index.ts", + "main": "./dist/core/index.mjs", "exports": { - ".": "./src/index.ts" - }, - "publishConfig": { - "files": ["dist", "src", "README.md"], - "main": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "default": "./dist/index.mjs" - } + ".": { + "types": "./dist/core/index.d.ts", + "import": "./dist/core/index.mjs" + }, + "./cli": { + "types": "./dist/cli/index.d.ts", + "import": "./dist/cli/index.mjs" + }, + "./config": { + "types": "./dist/config/index.d.ts", + "import": "./dist/config/index.mjs" + }, + "./core": { + "types": "./dist/core/index.d.ts", + "import": "./dist/core/index.mjs" + }, + "./rollup": { + "types": "./dist/rollup/index.d.ts", + "import": "./dist/rollup/index.mjs" } }, + "bin": { + "apibara": "./dist/cli/index.mjs" + }, + "files": [ + "dist", + "src", + "README.md" + ], "scripts": { "build": "unbuild", "lint": "biome check .", @@ -52,4 +67,4 @@ "tslib": "^2.6.3", "untyped": "^1.4.2" } -} +} \ No newline at end of file diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/cli/commands/build.ts similarity index 75% rename from packages/cli/src/commands/build.ts rename to packages/cli/src/cli/commands/build.ts index ce189af..4ce5368 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/cli/commands/build.ts @@ -1,9 +1,8 @@ import { defineCommand } from "citty"; import { resolve } from "pathe"; -import { createApibara } from "../apibara"; +import { createApibara, build, prepare } from "apibara/core"; import { commonArgs } from "../common"; -import { build } from "../core/build/build"; -import { prepare } from "../core/build/prepare"; +import consola from "consola"; export default defineCommand({ meta: { @@ -14,10 +13,12 @@ export default defineCommand({ ...commonArgs, }, async run({ args }) { + consola.info("build", args); const rootDir = resolve((args.dir || args._dir || ".") as string); const apibara = await createApibara({ rootDir, }); + consola.info("apibara", apibara); await prepare(apibara); await build(apibara); await apibara.close(); diff --git a/packages/cli/src/commands/dev.ts b/packages/cli/src/cli/commands/dev.ts similarity index 81% rename from packages/cli/src/commands/dev.ts rename to packages/cli/src/cli/commands/dev.ts index d3d337b..8a00f62 100644 --- a/packages/cli/src/commands/dev.ts +++ b/packages/cli/src/cli/commands/dev.ts @@ -1,5 +1,6 @@ import { defineCommand } from "citty"; import { commonArgs } from "../common"; +import consola from "consola"; export default defineCommand({ meta: { @@ -11,5 +12,6 @@ export default defineCommand({ }, async run({ args }) { // TODO + consola.info("dev", args); }, }); diff --git a/packages/cli/src/commands/prepare.ts b/packages/cli/src/cli/commands/prepare.ts similarity index 70% rename from packages/cli/src/commands/prepare.ts rename to packages/cli/src/cli/commands/prepare.ts index 51ea497..ccfba1c 100644 --- a/packages/cli/src/commands/prepare.ts +++ b/packages/cli/src/cli/commands/prepare.ts @@ -1,8 +1,9 @@ +import consola from "consola"; import { defineCommand } from "citty"; import { resolve } from "pathe"; -import { createApibara } from "../apibara"; +// import { createApibara } from "../../apibara"; import { commonArgs } from "../common"; -import { writeTypes } from "../core/build/types"; +// import { writeTypes } from "../../core/build/types"; export default defineCommand({ meta: { @@ -13,9 +14,11 @@ export default defineCommand({ ...commonArgs, }, async run({ args }) { - console.log("prepare", args); const rootDir = resolve((args.dir || ".") as string); + consola.info("prepare", args); + /* const apibara = await createApibara({ rootDir }); await writeTypes(apibara); + */ }, }); diff --git a/packages/cli/src/common.ts b/packages/cli/src/cli/common.ts similarity index 100% rename from packages/cli/src/common.ts rename to packages/cli/src/cli/common.ts diff --git a/packages/cli/src/main.ts b/packages/cli/src/cli/index.ts similarity index 78% rename from packages/cli/src/main.ts rename to packages/cli/src/cli/index.ts index 2735e9d..c370cc1 100755 --- a/packages/cli/src/main.ts +++ b/packages/cli/src/cli/index.ts @@ -1,4 +1,4 @@ -import { defineCommand } from "citty"; +import { defineCommand, runMain } from "citty"; export const mainCli = defineCommand({ meta: { @@ -12,5 +12,5 @@ export const mainCli = defineCommand({ prepare: () => import("./commands/prepare").then((r) => r.default), }, }); -// TODO uncomment when we build the CLI -// runMain(mainCli); + +runMain(mainCli); diff --git a/packages/cli/src/config/defaults.ts b/packages/cli/src/config/defaults.ts deleted file mode 100644 index 4819d62..0000000 --- a/packages/cli/src/config/defaults.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defaultSink } from "@apibara/indexer"; -import { defineConfig } from "../config"; - -export const ApibaraDefaults = defineConfig({ - rootDir: ".", - outputDir: "./dist", - runtimeConfig: {}, - sink: { - default: () => defaultSink(), - }, - hooks: {}, -}); diff --git a/packages/cli/src/config/index.ts b/packages/cli/src/config/index.ts index 1677c14..dc4dd21 100644 --- a/packages/cli/src/config/index.ts +++ b/packages/cli/src/config/index.ts @@ -1,5 +1,4 @@ -import type { DeepPartial } from "../types"; -import type { ApibaraConfig } from "../types/config"; +import type { DeepPartial, ApibaraConfig } from "apibara/types"; export function defineConfig< // biome-ignore lint/complexity/noBannedTypes: @@ -9,3 +8,4 @@ export function defineConfig< >(config: ApibaraConfig): ApibaraConfig { return config; } + diff --git a/packages/cli/src/apibara.ts b/packages/cli/src/core/apibara.ts similarity index 91% rename from packages/cli/src/apibara.ts rename to packages/cli/src/core/apibara.ts index fab22ce..029b447 100644 --- a/packages/cli/src/apibara.ts +++ b/packages/cli/src/core/apibara.ts @@ -2,12 +2,12 @@ import consola from "consola"; import { createHooks } from "hookable"; import { loadOptions } from "./config/loader"; import { updateApibaraConfig } from "./config/update"; -import type { Apibara } from "./types/apibara"; import type { + Apibara, ApibaraConfig, ApibaraDynamicConfig, LoadConfigOptions, -} from "./types/config"; +} from "apibara/types"; export async function createApibara( config: ApibaraConfig = {}, diff --git a/packages/cli/src/core/build/build.ts b/packages/cli/src/core/build/build.ts index 4d1ef98..140ed5a 100644 --- a/packages/cli/src/core/build/build.ts +++ b/packages/cli/src/core/build/build.ts @@ -1,5 +1,5 @@ -import { getRollupConfig } from "../../rollup/config"; -import type { Apibara } from "../../types/apibara"; +import { getRollupConfig } from "apibara/rollup"; +import type { Apibara } from "apibara/types"; import { buildProduction } from "./prod"; export async function build(apibara: Apibara) { diff --git a/packages/cli/src/core/build/prepare.ts b/packages/cli/src/core/build/prepare.ts index f9c03c6..7306e6c 100644 --- a/packages/cli/src/core/build/prepare.ts +++ b/packages/cli/src/core/build/prepare.ts @@ -1,6 +1,6 @@ import fsp from "node:fs/promises"; import fse from "fs-extra"; -import type { Apibara } from "../../types/apibara"; +import type { Apibara } from "apibara/types"; export async function prepare(apibara: Apibara) { await prepareDir(apibara.options.outputDir); diff --git a/packages/cli/src/core/config/defaults.ts b/packages/cli/src/core/config/defaults.ts new file mode 100644 index 0000000..445deb4 --- /dev/null +++ b/packages/cli/src/core/config/defaults.ts @@ -0,0 +1,12 @@ +// import { defaultSink } from "@apibara/indexer"; +import { type ApibaraConfig } from "apibara/types"; + +export const ApibaraDefaults: ApibaraConfig = { + rootDir: ".", + outputDir: "./dist", + runtimeConfig: {}, + // sink: { + // // default: () => defaultSink(), + // }, + hooks: {}, +}; diff --git a/packages/cli/src/config/loader.ts b/packages/cli/src/core/config/loader.ts similarity index 81% rename from packages/cli/src/config/loader.ts rename to packages/cli/src/core/config/loader.ts index 13b1ffe..e20ec97 100644 --- a/packages/cli/src/config/loader.ts +++ b/packages/cli/src/core/config/loader.ts @@ -4,7 +4,7 @@ import type { ApibaraConfig, ApibaraOptions, LoadConfigOptions, -} from "../types/config"; +} from "apibara/types"; import { ApibaraDefaults } from "./defaults"; import { resolvePathOptions } from "./resolvers/paths.resolver"; import { presetResolver } from "./resolvers/preset.resolver"; @@ -37,16 +37,16 @@ async function _loadUserConfig( const loadedConfig = await (opts.watch ? watchConfig : loadConfig)({ - name: "apibara", - // path from where apibara.config.ts is loaded - // defautl is "." path - // cwd: configOverrides.rootDir, - overrides: { - ...configOverrides, - }, - defaults: { ...ApibaraDefaults }, - ...opts.c12, - }); + name: "apibara", + // path from where apibara.config.ts is loaded + // defautl is "." path + // cwd: configOverrides.rootDir, + overrides: { + ...configOverrides, + }, + defaults: { ...ApibaraDefaults }, + ...opts.c12, + }); const options = klona(loadedConfig.config) as ApibaraOptions; diff --git a/packages/cli/src/config/resolvers/paths.resolver.ts b/packages/cli/src/core/config/resolvers/paths.resolver.ts similarity index 73% rename from packages/cli/src/config/resolvers/paths.resolver.ts rename to packages/cli/src/core/config/resolvers/paths.resolver.ts index 79f24e6..ec59c70 100644 --- a/packages/cli/src/config/resolvers/paths.resolver.ts +++ b/packages/cli/src/core/config/resolvers/paths.resolver.ts @@ -1,5 +1,5 @@ import { resolve } from "pathe"; -import type { ApibaraOptions } from "../../types/config"; +import type { ApibaraOptions } from "apibara/types"; export async function resolvePathOptions(options: ApibaraOptions) { options.rootDir = resolve(options.rootDir || "."); diff --git a/packages/cli/src/config/resolvers/preset.resolver.ts b/packages/cli/src/core/config/resolvers/preset.resolver.ts similarity index 82% rename from packages/cli/src/config/resolvers/preset.resolver.ts rename to packages/cli/src/core/config/resolvers/preset.resolver.ts index 96a191a..372ce8f 100644 --- a/packages/cli/src/config/resolvers/preset.resolver.ts +++ b/packages/cli/src/core/config/resolvers/preset.resolver.ts @@ -1,5 +1,5 @@ import defu from "defu"; -import type { ApibaraOptions } from "../../types/config"; +import type { ApibaraOptions } from "apibara/types"; export async function presetResolver(options: ApibaraOptions) { if (options.preset && options.presets?.[options.preset]) { diff --git a/packages/cli/src/config/resolvers/runtime-config.resolver.ts b/packages/cli/src/core/config/resolvers/runtime-config.resolver.ts similarity index 80% rename from packages/cli/src/config/resolvers/runtime-config.resolver.ts rename to packages/cli/src/core/config/resolvers/runtime-config.resolver.ts index 92bdf86..45d7a57 100644 --- a/packages/cli/src/config/resolvers/runtime-config.resolver.ts +++ b/packages/cli/src/core/config/resolvers/runtime-config.resolver.ts @@ -1,4 +1,4 @@ -import type { ApibaraOptions } from "../../types/config"; +import type { ApibaraOptions } from "apibara/types"; export async function resolveRuntimeConfigOptions(options: ApibaraOptions) { options.runtimeConfig = { ...options.runtimeConfig, default: "value" }; diff --git a/packages/cli/src/config/update.ts b/packages/cli/src/core/config/update.ts similarity index 67% rename from packages/cli/src/config/update.ts rename to packages/cli/src/core/config/update.ts index 6017093..b87b102 100644 --- a/packages/cli/src/config/update.ts +++ b/packages/cli/src/core/config/update.ts @@ -1,5 +1,4 @@ -import type { Apibara } from "../types/apibara"; -import type { ApibaraDynamicConfig } from "../types/config"; +import type { Apibara, ApibaraDynamicConfig } from "apibara/types"; export async function updateApibaraConfig( apibara: Apibara, diff --git a/packages/cli/src/core/index.ts b/packages/cli/src/core/index.ts new file mode 100644 index 0000000..4a707e5 --- /dev/null +++ b/packages/cli/src/core/index.ts @@ -0,0 +1,3 @@ +export { createApibara } from "./apibara"; +export { build } from "./build/build"; +export { prepare } from "./build/prepare"; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts deleted file mode 100644 index c838408..0000000 --- a/packages/cli/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./main"; -export * from "./types"; -export * from "./hooks"; -export * from "./config"; diff --git a/packages/cli/src/rollup/config.ts b/packages/cli/src/rollup/config.ts index cd49ec1..e1bcc12 100644 --- a/packages/cli/src/rollup/config.ts +++ b/packages/cli/src/rollup/config.ts @@ -4,10 +4,9 @@ import commonjs from "@rollup/plugin-commonjs"; import json from "@rollup/plugin-json"; import { nodeResolve } from "@rollup/plugin-node-resolve"; import typescript from "@rollup/plugin-typescript"; -import { readdirSync } from "fs-extra"; +import fsExtra from "fs-extra"; import { basename, join } from "pathe"; -import type { Apibara } from "../types/apibara"; -import type { RollupConfig } from "../types/rollup"; +import type { Apibara, RollupConfig } from "apibara/types"; export const getRollupConfig = ( apibara: Apibara, @@ -37,7 +36,7 @@ export const getRollupConfig = ( // Check if the indexers directory exists and is not empty let indexerFiles: string[] = []; try { - indexerFiles = readdirSync(indexerDir).filter((file) => + indexerFiles = fsExtra.readdirSync(indexerDir).filter((file) => file.endsWith(".indexer.ts"), ); if (indexerFiles.length === 0) { @@ -65,10 +64,10 @@ ${indexerImports} const indexers = { ${indexerFiles - .map( - (file, index) => `'${basename(file, ".indexer.ts")}': indexer${index},`, - ) - .join("\n ")} + .map( + (file, index) => `'${basename(file, ".indexer.ts")}': indexer${index},`, + ) + .join("\n ")} }; const command = defineCommand({ @@ -114,13 +113,13 @@ const command = defineCommand({ } const indexerFactory = indexers[name]; - const indexer = typeof indexerFactory === 'function' - ? await indexerFactory(runtimeConfig) + const indexer = typeof indexerFactory === 'function' + ? await indexerFactory(runtimeConfig) : indexerFactory; const client = createClient(indexer.streamConfig, indexer.options.streamUrl); const sink = sinkFunction(); - + try { console.log("Running Indexer: ", name); await run(client, indexer, sink); diff --git a/packages/cli/src/rollup/index.ts b/packages/cli/src/rollup/index.ts new file mode 100644 index 0000000..5c62e04 --- /dev/null +++ b/packages/cli/src/rollup/index.ts @@ -0,0 +1 @@ +export * from "./config"; diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json index 9d05974..42d5044 100644 --- a/packages/cli/tsconfig.json +++ b/packages/cli/tsconfig.json @@ -5,7 +5,28 @@ "declarationDir": "dist", "noEmit": false, "rootDir": "src", - "types": ["node"] + "types": [ + "node" + ], + "paths": { + "apibara/cli": [ + "./src/cli" + ], + "apibara/config": [ + "./src/config" + ], + "apibara/core": [ + "./src/core" + ], + "apibara/rollup": [ + "./src/rollup" + ], + "apibara/types": [ + "./src/types" + ] + } }, - "include": ["src/"] -} + "include": [ + "src/" + ] +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65482a4..d3f127f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,9 +51,6 @@ importers: examples/cli: dependencies: - '@apibara/cli': - specifier: workspace:* - version: link:../../packages/cli '@apibara/evm': specifier: workspace:* version: link:../../packages/evm @@ -81,6 +78,9 @@ importers: '@opentelemetry/semantic-conventions': specifier: ^1.25.0 version: 1.25.0 + apibara: + specifier: workspace:* + version: link:../../packages/cli better-sqlite3: specifier: ^11.1.2 version: 11.1.2 From b0652bcfd0f2ff908771baefaf69d4514411ace2 Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Tue, 30 Jul 2024 20:59:55 +0530 Subject: [PATCH 06/10] cli: add prepare command --- .gitignore | 3 +- biome.json | 3 + examples/cli/apibara.config.ts | 2 +- examples/cli/indexers/simple.indexer.ts | 2 +- examples/cli/indexers/with-config.indexer.ts | 7 +- examples/cli/package.json | 6 +- examples/cli/tsconfig.json | 12 +- packages/cli/build.config.ts | 20 +-- packages/cli/package.json | 17 +- packages/cli/src/cli/commands/build.ts | 7 +- packages/cli/src/cli/commands/dev.ts | 4 +- packages/cli/src/cli/commands/prepare.ts | 8 +- packages/cli/src/config/index.ts | 3 +- packages/cli/src/core/apibara.ts | 8 +- packages/cli/src/core/build/prepare.ts | 4 +- packages/cli/src/core/build/prod.ts | 6 +- packages/cli/src/core/build/types.ts | 159 ++++++++++++++++-- packages/cli/src/core/config/defaults.ts | 17 +- packages/cli/src/core/config/loader.ts | 24 +-- .../core/config/resolvers/paths.resolver.ts | 2 +- .../core/config/resolvers/preset.resolver.ts | 2 +- packages/cli/src/core/index.ts | 1 + packages/cli/src/hooks/useRuntimeConfig.ts | 4 +- packages/cli/src/rollup/config.ts | 32 ++-- packages/cli/src/types/config.ts | 13 ++ packages/cli/src/types/index.ts | 1 + packages/cli/src/types/runtime.ts | 1 + packages/cli/tsconfig.json | 31 +--- pnpm-lock.yaml | 25 +-- 29 files changed, 286 insertions(+), 138 deletions(-) create mode 100644 packages/cli/src/types/runtime.ts diff --git a/.gitignore b/.gitignore index b178996..b83eb57 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules dist .turbo bun.lockb -.vscode \ No newline at end of file +.vscode +.apibara \ No newline at end of file diff --git a/biome.json b/biome.json index 1e7a95f..9629783 100644 --- a/biome.json +++ b/biome.json @@ -9,6 +9,9 @@ "recommended": true, "correctness": { "noUnusedImports": "error" + }, + "style": { + "noNonNullAssertion": "off" } } }, diff --git a/examples/cli/apibara.config.ts b/examples/cli/apibara.config.ts index d2f4d88..284df07 100644 --- a/examples/cli/apibara.config.ts +++ b/examples/cli/apibara.config.ts @@ -1,5 +1,5 @@ -import { defineConfig } from "apibara/config"; import { defaultSink } from "@apibara/indexer"; +import { defineConfig } from "apibara/config"; export default defineConfig({ runtimeConfig: { diff --git a/examples/cli/indexers/simple.indexer.ts b/examples/cli/indexers/simple.indexer.ts index 8010c1d..9101046 100644 --- a/examples/cli/indexers/simple.indexer.ts +++ b/examples/cli/indexers/simple.indexer.ts @@ -27,4 +27,4 @@ export default defineIndexer(EvmStream)({ async transform({ block: { header } }) { return [header]; }, -}) +}); diff --git a/examples/cli/indexers/with-config.indexer.ts b/examples/cli/indexers/with-config.indexer.ts index 7dc8777..f8305b6 100644 --- a/examples/cli/indexers/with-config.indexer.ts +++ b/examples/cli/indexers/with-config.indexer.ts @@ -1,14 +1,13 @@ import { EvmStream } from "@apibara/evm"; import { defineIndexer } from "@apibara/indexer"; +import type { ApibaraRuntimeConfig } from "apibara/types"; import { encodeEventTopics, parseAbi } from "viem"; const abi = parseAbi([ "event Transfer(address indexed from, address indexed to, uint256 value)", ]); -// TODO: `runtimeConfig` type should come from the generated types file -export default function indexer(runtimeConfig: unknown) { - console.log("runtimeConfig", runtimeConfig); +export default function indexer(runtimeConfig: ApibaraRuntimeConfig) { return defineIndexer(EvmStream)({ streamUrl: "https://sepolia.ethereum.a5a.ch", finality: "accepted", @@ -30,5 +29,5 @@ export default function indexer(runtimeConfig: unknown) { async transform({ block: { header } }) { return [header]; }, - }) + }); } diff --git a/examples/cli/package.json b/examples/cli/package.json index 43c7bdd..5567051 100644 --- a/examples/cli/package.json +++ b/examples/cli/package.json @@ -3,7 +3,9 @@ "version": "1.0.0", "private": true, "scripts": { - "build": "apibara build", + "apibara:build": "apibara build", + "apibara:start": "jiti ./dist/main.mjs", + "apibara:prepare": "apibara prepare", "typecheck": "tsc --noEmit", "lint": "biome check .", "lint:fix": "pnpm lint --write", @@ -31,4 +33,4 @@ "@types/node": "^20.12.12", "jiti": "^1.21.0" } -} \ No newline at end of file +} diff --git a/examples/cli/tsconfig.json b/examples/cli/tsconfig.json index 0f2829f..3ec03b8 100644 --- a/examples/cli/tsconfig.json +++ b/examples/cli/tsconfig.json @@ -1,15 +1,11 @@ { - "extends": "../../tsconfig.json", + "extends": ["../../tsconfig.json", "./.apibara/types/tsconfig.json"], "compilerOptions": { "outDir": "dist", "declarationDir": "dist", "noEmit": false, "rootDir": ".", - "types": [ - "node" - ] + "types": ["node"] }, - "include": [ - "indexers/" - ] -} \ No newline at end of file + "include": ["indexers/", "apibara.config.ts"] +} diff --git a/packages/cli/build.config.ts b/packages/cli/build.config.ts index f87c7f6..f90a4fb 100644 --- a/packages/cli/build.config.ts +++ b/packages/cli/build.config.ts @@ -1,15 +1,10 @@ -import { defineBuildConfig } from "unbuild"; import { fileURLToPath } from "node:url"; import { resolve } from "pathe"; +import { defineBuildConfig } from "unbuild"; -const modules = [ - "cli", - "config", - "core", - "rollup", - "types", -]; +const modules = ["cli", "config", "core", "rollup", "types", "hooks "]; +// @ts-ignore The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'. const srcDir = fileURLToPath(new URL("src", import.meta.url)); export default defineBuildConfig({ @@ -18,6 +13,8 @@ export default defineBuildConfig({ { input: "./src/config/index.ts" }, { input: "./src/core/index.ts" }, { input: "./src/rollup/index.ts" }, + { input: "./src/types/index.ts" }, + { input: "./src/hooks/index.ts" }, ], clean: true, outDir: "./dist", @@ -27,11 +24,8 @@ export default defineBuildConfig({ modules.map((module) => [ `apibara/${module}`, resolve(srcDir, `${module}/index.ts`), - ]) + ]), ), }, - externals: [ - ...modules.map((module) => `apibara/${module}`), - ], + externals: [...modules.map((module) => `apibara/${module}`)], }); - diff --git a/packages/cli/package.json b/packages/cli/package.json index 06e63e3..eb9ede5 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,16 +24,20 @@ "./rollup": { "types": "./dist/rollup/index.d.ts", "import": "./dist/rollup/index.mjs" + }, + "./types": { + "types": "./dist/types/index.d.ts", + "import": "./dist/types/index.mjs" + }, + "./hooks": { + "types": "./dist/hooks/index.d.ts", + "import": "./dist/hooks/index.mjs" } }, "bin": { "apibara": "./dist/cli/index.mjs" }, - "files": [ - "dist", - "src", - "README.md" - ], + "files": ["dist", "src", "README.md"], "scripts": { "build": "unbuild", "lint": "biome check .", @@ -63,8 +67,9 @@ "hookable": "^5.5.3", "klona": "^2.0.6", "pathe": "^1.1.2", + "pkg-types": "^1.1.3", "rollup": "^4.18.1", "tslib": "^2.6.3", "untyped": "^1.4.2" } -} \ No newline at end of file +} diff --git a/packages/cli/src/cli/commands/build.ts b/packages/cli/src/cli/commands/build.ts index 4ce5368..8aee0f0 100644 --- a/packages/cli/src/cli/commands/build.ts +++ b/packages/cli/src/cli/commands/build.ts @@ -1,8 +1,8 @@ +import { build, createApibara, prepare } from "apibara/core"; import { defineCommand } from "citty"; +import consola from "consola"; import { resolve } from "pathe"; -import { createApibara, build, prepare } from "apibara/core"; import { commonArgs } from "../common"; -import consola from "consola"; export default defineCommand({ meta: { @@ -13,12 +13,11 @@ export default defineCommand({ ...commonArgs, }, async run({ args }) { - consola.info("build", args); + consola.info("Building with args", args); const rootDir = resolve((args.dir || args._dir || ".") as string); const apibara = await createApibara({ rootDir, }); - consola.info("apibara", apibara); await prepare(apibara); await build(apibara); await apibara.close(); diff --git a/packages/cli/src/cli/commands/dev.ts b/packages/cli/src/cli/commands/dev.ts index 8a00f62..7561240 100644 --- a/packages/cli/src/cli/commands/dev.ts +++ b/packages/cli/src/cli/commands/dev.ts @@ -1,6 +1,6 @@ import { defineCommand } from "citty"; -import { commonArgs } from "../common"; import consola from "consola"; +import { commonArgs } from "../common"; export default defineCommand({ meta: { @@ -12,6 +12,6 @@ export default defineCommand({ }, async run({ args }) { // TODO - consola.info("dev", args); + consola.info("Not implemented!", args); }, }); diff --git a/packages/cli/src/cli/commands/prepare.ts b/packages/cli/src/cli/commands/prepare.ts index ccfba1c..5b81b00 100644 --- a/packages/cli/src/cli/commands/prepare.ts +++ b/packages/cli/src/cli/commands/prepare.ts @@ -1,5 +1,7 @@ -import consola from "consola"; +import { createApibara, writeTypes } from "apibara/core"; +import {} from "apibara/types"; import { defineCommand } from "citty"; +import consola from "consola"; import { resolve } from "pathe"; // import { createApibara } from "../../apibara"; import { commonArgs } from "../common"; @@ -14,11 +16,9 @@ export default defineCommand({ ...commonArgs, }, async run({ args }) { + consola.info("Prepairing \n\n"); const rootDir = resolve((args.dir || ".") as string); - consola.info("prepare", args); - /* const apibara = await createApibara({ rootDir }); await writeTypes(apibara); - */ }, }); diff --git a/packages/cli/src/config/index.ts b/packages/cli/src/config/index.ts index dc4dd21..8ff321d 100644 --- a/packages/cli/src/config/index.ts +++ b/packages/cli/src/config/index.ts @@ -1,4 +1,4 @@ -import type { DeepPartial, ApibaraConfig } from "apibara/types"; +import type { ApibaraConfig, DeepPartial } from "apibara/types"; export function defineConfig< // biome-ignore lint/complexity/noBannedTypes: @@ -8,4 +8,3 @@ export function defineConfig< >(config: ApibaraConfig): ApibaraConfig { return config; } - diff --git a/packages/cli/src/core/apibara.ts b/packages/cli/src/core/apibara.ts index 029b447..52bca23 100644 --- a/packages/cli/src/core/apibara.ts +++ b/packages/cli/src/core/apibara.ts @@ -1,13 +1,13 @@ -import consola from "consola"; -import { createHooks } from "hookable"; -import { loadOptions } from "./config/loader"; -import { updateApibaraConfig } from "./config/update"; import type { Apibara, ApibaraConfig, ApibaraDynamicConfig, LoadConfigOptions, } from "apibara/types"; +import consola from "consola"; +import { createHooks } from "hookable"; +import { loadOptions } from "./config/loader"; +import { updateApibaraConfig } from "./config/update"; export async function createApibara( config: ApibaraConfig = {}, diff --git a/packages/cli/src/core/build/prepare.ts b/packages/cli/src/core/build/prepare.ts index 7306e6c..782e394 100644 --- a/packages/cli/src/core/build/prepare.ts +++ b/packages/cli/src/core/build/prepare.ts @@ -1,8 +1,10 @@ import fsp from "node:fs/promises"; -import fse from "fs-extra"; import type { Apibara } from "apibara/types"; +import consola from "consola"; +import fse from "fs-extra"; export async function prepare(apibara: Apibara) { + consola.info("Cleaning output directory"); await prepareDir(apibara.options.outputDir); } diff --git a/packages/cli/src/core/build/prod.ts b/packages/cli/src/core/build/prod.ts index 7e4703a..2b05115 100644 --- a/packages/cli/src/core/build/prod.ts +++ b/packages/cli/src/core/build/prod.ts @@ -1,6 +1,6 @@ +import type { Apibara, RollupConfig } from "apibara/types"; +import consola from "consola"; import { type OutputOptions, rollup } from "rollup"; -import type { Apibara } from "../../types/apibara"; -import type { RollupConfig } from "../../types/rollup"; export async function buildProduction( apibara: Apibara, @@ -24,7 +24,7 @@ export async function buildProduction( // Close the bundle await bundle.close(); - console.log("Build completed successfully!"); + consola.success("Build completed successfully!"); } catch (error) { console.error("Build failed:", error); throw error; diff --git a/packages/cli/src/core/build/types.ts b/packages/cli/src/core/build/types.ts index 0f25bf0..667273b 100644 --- a/packages/cli/src/core/build/types.ts +++ b/packages/cli/src/core/build/types.ts @@ -1,23 +1,152 @@ +import fsp from "node:fs/promises"; +import type { Apibara } from "apibara/types"; +import consola from "consola"; +import defu from "defu"; +import { dirname, isAbsolute, join, relative, resolve } from "pathe"; +import type { TSConfig } from "pkg-types"; import { type JSValue, generateTypes, resolveSchema } from "untyped"; -import type { Apibara } from "../../types/apibara"; export async function writeTypes(apibara: Apibara) { - // TODO write to a file - const type = generateTypes( - await resolveSchema( - Object.fromEntries( - Object.entries(apibara.options.runtimeConfig), - ) as Record, - ), + const typesDir = resolve(apibara.options.buildDir, "types"); + + const config = [ + "// Generated by apibara", + ` +declare module "apibara/types" {`, + apibara.options.typescript.generateRuntimeConfigTypes + ? generateTypes( + await resolveSchema( + Object.fromEntries( + Object.entries(apibara.options.runtimeConfig), + ) as Record, + ), + { + interfaceName: "ApibaraRuntimeConfig", + addExport: false, + addDefaults: false, + allowExtraKeys: false, + indentation: 2, + }, + ) + : "", + "}", + // Makes this a module for augmentation purposes + "export type {}", + ]; + + const declarations = [ + // local apibara augmentations + '/// ', + ]; + + const buildFiles: { path: string; contents: string }[] = []; + + buildFiles.push({ + path: join(typesDir, "apibara-config.d.ts"), + contents: config.join("\n"), + }); + + buildFiles.push({ + path: join(typesDir, "apibara.d.ts"), + contents: declarations.join("\n"), + }); + + if (apibara.options.typescript.generateTsConfig) { + const tsConfigPath = resolve( + apibara.options.buildDir, + apibara.options.typescript.tsconfigPath, + ); + const tsconfigDir = dirname(tsConfigPath); + const tsConfig: TSConfig = defu(apibara.options.typescript.tsConfig, { + compilerOptions: { + forceConsistentCasingInFileNames: true, + strict: apibara.options.typescript.strict, + noEmit: true, + target: "ESNext", + module: "ESNext", + moduleResolution: "Bundler", + allowJs: true, + resolveJsonModule: true, + jsx: "preserve", + allowSyntheticDefaultImports: true, + jsxFactory: "h", + jsxFragmentFactory: "Fragment", + }, + include: [ + relativeWithDot(tsconfigDir, join(typesDir, "apibara.d.ts")).replace( + /^(?=[^.])/, + "./", + ), + ], + }); + + for (const alias in tsConfig.compilerOptions!.paths) { + const paths = tsConfig.compilerOptions!.paths[alias]; + tsConfig.compilerOptions!.paths[alias] = await Promise.all( + paths.map(async (path: string) => { + if (!isAbsolute(path)) { + return path; + } + const stats = await fsp + .stat(path) + .catch(() => null /* file does not exist */); + return relativeWithDot( + tsconfigDir, + stats?.isFile() + ? path.replace(/(?<=\w)\.\w+$/g, "") /* remove extension */ + : path, + ); + }), + ); + } + + tsConfig.include = [ + ...new Set( + tsConfig.include!.map((p) => + isAbsolute(p) ? relativeWithDot(tsconfigDir, p) : p, + ), + ), + ]; + if (tsConfig.exclude) { + tsConfig.exclude = [ + ...new Set( + tsConfig.exclude!.map((p) => + isAbsolute(p) ? relativeWithDot(tsconfigDir, p) : p, + ), + ), + ]; + } + + buildFiles.push({ + path: tsConfigPath, + contents: JSON.stringify(tsConfig, null, 2), + }); + } + + await Promise.all( + buildFiles.map(async (file) => { + const _file = resolve(apibara.options.buildDir, file.path); + await fsp.mkdir(dirname(_file), { recursive: true }); + await fsp.writeFile(_file, file.contents); + }), + ); + + consola.info( + "To leverage type hints within your project, create a tsconfig.json file that extends auto generated types.\n", + ); + consola.log.raw( { - interfaceName: "ApibaraRuntimeConfig", - addExport: false, - addDefaults: false, - allowExtraKeys: false, - indentation: 2, + extends: "./.apibara/types/tsconfig.json", }, + "\n\n", ); - console.log("apibara ---> ", apibara); - console.log("type ---> ", type); + consola.success("Preparation successful!\n\n"); +} + +const RELATIVE_RE = /^\.{1,2}\//; + +export function relativeWithDot(from: string, to: string) { + const rel = relative(from, to); + return RELATIVE_RE.test(rel) ? rel : `./${rel}`; } diff --git a/packages/cli/src/core/config/defaults.ts b/packages/cli/src/core/config/defaults.ts index 445deb4..c3a4526 100644 --- a/packages/cli/src/core/config/defaults.ts +++ b/packages/cli/src/core/config/defaults.ts @@ -1,12 +1,21 @@ // import { defaultSink } from "@apibara/indexer"; -import { type ApibaraConfig } from "apibara/types"; +import type { ApibaraConfig } from "apibara/types"; export const ApibaraDefaults: ApibaraConfig = { rootDir: ".", outputDir: "./dist", + runtimeConfig: {}, - // sink: { - // // default: () => defaultSink(), - // }, hooks: {}, + + buildDir: ".apibara", + + typescript: { + strict: false, + generateTsConfig: true, + generateRuntimeConfigTypes: true, + tsconfigPath: "types/tsconfig.json", + internalPaths: false, + tsConfig: {}, + }, }; diff --git a/packages/cli/src/core/config/loader.ts b/packages/cli/src/core/config/loader.ts index e20ec97..ac2b0de 100644 --- a/packages/cli/src/core/config/loader.ts +++ b/packages/cli/src/core/config/loader.ts @@ -1,10 +1,10 @@ -import { loadConfig, watchConfig } from "c12"; -import { klona } from "klona/full"; import type { ApibaraConfig, ApibaraOptions, LoadConfigOptions, } from "apibara/types"; +import { loadConfig, watchConfig } from "c12"; +import { klona } from "klona/full"; import { ApibaraDefaults } from "./defaults"; import { resolvePathOptions } from "./resolvers/paths.resolver"; import { presetResolver } from "./resolvers/preset.resolver"; @@ -37,16 +37,16 @@ async function _loadUserConfig( const loadedConfig = await (opts.watch ? watchConfig : loadConfig)({ - name: "apibara", - // path from where apibara.config.ts is loaded - // defautl is "." path - // cwd: configOverrides.rootDir, - overrides: { - ...configOverrides, - }, - defaults: { ...ApibaraDefaults }, - ...opts.c12, - }); + name: "apibara", + // path from where apibara.config.ts is loaded + // defautl is "." path + // cwd: configOverrides.rootDir, + overrides: { + ...configOverrides, + }, + defaults: { ...ApibaraDefaults }, + ...opts.c12, + }); const options = klona(loadedConfig.config) as ApibaraOptions; diff --git a/packages/cli/src/core/config/resolvers/paths.resolver.ts b/packages/cli/src/core/config/resolvers/paths.resolver.ts index ec59c70..329200b 100644 --- a/packages/cli/src/core/config/resolvers/paths.resolver.ts +++ b/packages/cli/src/core/config/resolvers/paths.resolver.ts @@ -1,5 +1,5 @@ -import { resolve } from "pathe"; import type { ApibaraOptions } from "apibara/types"; +import { resolve } from "pathe"; export async function resolvePathOptions(options: ApibaraOptions) { options.rootDir = resolve(options.rootDir || "."); diff --git a/packages/cli/src/core/config/resolvers/preset.resolver.ts b/packages/cli/src/core/config/resolvers/preset.resolver.ts index 372ce8f..7af24d4 100644 --- a/packages/cli/src/core/config/resolvers/preset.resolver.ts +++ b/packages/cli/src/core/config/resolvers/preset.resolver.ts @@ -1,5 +1,5 @@ -import defu from "defu"; import type { ApibaraOptions } from "apibara/types"; +import defu from "defu"; export async function presetResolver(options: ApibaraOptions) { if (options.preset && options.presets?.[options.preset]) { diff --git a/packages/cli/src/core/index.ts b/packages/cli/src/core/index.ts index 4a707e5..926eb04 100644 --- a/packages/cli/src/core/index.ts +++ b/packages/cli/src/core/index.ts @@ -1,3 +1,4 @@ export { createApibara } from "./apibara"; export { build } from "./build/build"; export { prepare } from "./build/prepare"; +export { writeTypes } from "./build/types"; diff --git a/packages/cli/src/hooks/useRuntimeConfig.ts b/packages/cli/src/hooks/useRuntimeConfig.ts index e0ed7f1..b0cd157 100644 --- a/packages/cli/src/hooks/useRuntimeConfig.ts +++ b/packages/cli/src/hooks/useRuntimeConfig.ts @@ -1,3 +1,5 @@ -export function useRuntimeConfig() { +import type { ApibaraRuntimeConfig } from "apibara/types"; + +export function useRuntimeConfig(): ApibaraRuntimeConfig { return JSON.parse(process.env.APIBARA_RUNTIME_CONFIG || "{}"); } diff --git a/packages/cli/src/rollup/config.ts b/packages/cli/src/rollup/config.ts index e1bcc12..1eeed19 100644 --- a/packages/cli/src/rollup/config.ts +++ b/packages/cli/src/rollup/config.ts @@ -4,9 +4,9 @@ import commonjs from "@rollup/plugin-commonjs"; import json from "@rollup/plugin-json"; import { nodeResolve } from "@rollup/plugin-node-resolve"; import typescript from "@rollup/plugin-typescript"; +import type { Apibara, RollupConfig } from "apibara/types"; import fsExtra from "fs-extra"; import { basename, join } from "pathe"; -import type { Apibara, RollupConfig } from "apibara/types"; export const getRollupConfig = ( apibara: Apibara, @@ -36,9 +36,9 @@ export const getRollupConfig = ( // Check if the indexers directory exists and is not empty let indexerFiles: string[] = []; try { - indexerFiles = fsExtra.readdirSync(indexerDir).filter((file) => - file.endsWith(".indexer.ts"), - ); + indexerFiles = fsExtra + .readdirSync(indexerDir) + .filter((file) => file.endsWith(".indexer.ts")); if (indexerFiles.length === 0) { console.warn(`No indexer files found in ${indexerDir}`); } @@ -56,7 +56,8 @@ export const getRollupConfig = ( // Generate main.ts content const mainContent = ` import { createClient } from "@apibara/protocol"; -import { run } from "@apibara/indexer"; +import { createIndexer, run } from "@apibara/indexer"; +import consola from "consola"; import { defineCommand, runMain } from "citty"; import config from './${configPath}'; @@ -64,10 +65,10 @@ ${indexerImports} const indexers = { ${indexerFiles - .map( - (file, index) => `'${basename(file, ".indexer.ts")}': indexer${index},`, - ) - .join("\n ")} + .map( + (file, index) => `'${basename(file, ".indexer.ts")}': indexer${index},`, + ) + .join("\n ")} }; const command = defineCommand({ @@ -112,19 +113,19 @@ const command = defineCommand({ return; } - const indexerFactory = indexers[name]; - const indexer = typeof indexerFactory === 'function' - ? await indexerFactory(runtimeConfig) - : indexerFactory; + const indexerConfig = indexers[name] + const indexer = typeof indexerConfig === 'function' + ? await createIndexer(indexerConfig(runtimeConfig)) + : createIndexer(indexerConfig); const client = createClient(indexer.streamConfig, indexer.options.streamUrl); const sink = sinkFunction(); try { - console.log("Running Indexer: ", name); + consola.log("Running Indexer: ", name); await run(client, indexer, sink); } catch (error) { - console.error(\`Error in indexer \${name}:\`, error); + consola.error(\`Error in indexer \${name}:\`, error); } })); }, @@ -169,6 +170,7 @@ runMain(command); }, }, ], + treeshake: true, external: [ ...builtinModules, "@apibara/indexer", diff --git a/packages/cli/src/types/config.ts b/packages/cli/src/types/config.ts index ae195ea..7910c18 100644 --- a/packages/cli/src/types/config.ts +++ b/packages/cli/src/types/config.ts @@ -7,6 +7,7 @@ import type { } from "c12"; import type { WatchOptions } from "chokidar"; import type { NestedHooks } from "hookable"; +import type { TSConfig } from "pkg-types"; import type { DeepPartial } from "./_utils"; import type { ApibaraHooks } from "./hooks"; import type { RollupConfig } from "./rollup"; @@ -66,6 +67,7 @@ export interface ApibaraOptions< debug: boolean; runtimeConfig: R; rootDir: string; + buildDir: string; outputDir: string; // Dev dev: boolean; @@ -77,4 +79,15 @@ export interface ApibaraOptions< rollupConfig?: RollupConfig; entry: string; minify: boolean; + + // Advanced + typescript: { + strict?: boolean; + internalPaths?: boolean; + generateRuntimeConfigTypes?: boolean; + generateTsConfig?: boolean; + /** the path of the generated `tsconfig.json`, relative to buildDir */ + tsconfigPath: string; + tsConfig?: Partial; + }; } diff --git a/packages/cli/src/types/index.ts b/packages/cli/src/types/index.ts index a3ff743..def4fc4 100644 --- a/packages/cli/src/types/index.ts +++ b/packages/cli/src/types/index.ts @@ -3,3 +3,4 @@ export * from "./_utils"; export * from "./config"; export * from "./hooks"; export * from "./rollup"; +export * from "./runtime"; diff --git a/packages/cli/src/types/runtime.ts b/packages/cli/src/types/runtime.ts new file mode 100644 index 0000000..6a54e4a --- /dev/null +++ b/packages/cli/src/types/runtime.ts @@ -0,0 +1 @@ +export type ApibaraRuntimeConfig = Record; diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json index 42d5044..8d7acb3 100644 --- a/packages/cli/tsconfig.json +++ b/packages/cli/tsconfig.json @@ -5,28 +5,15 @@ "declarationDir": "dist", "noEmit": false, "rootDir": "src", - "types": [ - "node" - ], + "types": ["node"], "paths": { - "apibara/cli": [ - "./src/cli" - ], - "apibara/config": [ - "./src/config" - ], - "apibara/core": [ - "./src/core" - ], - "apibara/rollup": [ - "./src/rollup" - ], - "apibara/types": [ - "./src/types" - ] + "apibara/cli": ["./src/cli"], + "apibara/config": ["./src/config"], + "apibara/core": ["./src/core"], + "apibara/rollup": ["./src/rollup"], + "apibara/types": ["./src/types"], + "apibara/hooks": ["./src/hooks"] } }, - "include": [ - "src/" - ] -} \ No newline at end of file + "include": ["src/"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d3f127f..6f2b11d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -354,6 +354,9 @@ importers: pathe: specifier: ^1.1.2 version: 1.1.2 + pkg-types: + specifier: ^1.1.3 + version: 1.1.3 rollup: specifier: ^4.18.1 version: 4.18.1 @@ -2709,7 +2712,7 @@ packages: ohash: 1.1.3 pathe: 1.1.2 perfect-debounce: 1.0.0 - pkg-types: 1.1.1 + pkg-types: 1.1.3 rc9: 2.1.2 dev: false @@ -4146,7 +4149,7 @@ packages: engines: {node: '>=14'} dependencies: mlly: 1.7.0 - pkg-types: 1.1.1 + pkg-types: 1.1.3 dev: true /locate-path@5.0.0: @@ -4374,7 +4377,7 @@ packages: mlly: 1.7.0 mri: 1.2.0 pathe: 1.1.2 - pkg-types: 1.1.1 + pkg-types: 1.1.3 postcss: 8.4.38 postcss-nested: 6.0.1(postcss@8.4.38) semver: 7.6.0 @@ -4386,17 +4389,17 @@ packages: dependencies: acorn: 8.11.3 pathe: 1.1.2 - pkg-types: 1.1.1 + pkg-types: 1.1.3 ufo: 1.5.3 + dev: true /mlly@1.7.1: resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} dependencies: acorn: 8.11.3 pathe: 1.1.2 - pkg-types: 1.1.1 + pkg-types: 1.1.3 ufo: 1.5.3 - dev: false /module-details-from-path@1.0.3: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} @@ -4497,7 +4500,7 @@ packages: consola: 3.2.3 execa: 8.0.1 pathe: 1.1.2 - pkg-types: 1.1.1 + pkg-types: 1.1.3 ufo: 1.5.3 dev: false @@ -4678,11 +4681,11 @@ packages: find-up: 4.1.0 dev: true - /pkg-types@1.1.1: - resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} + /pkg-types@1.1.3: + resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==} dependencies: confbox: 0.1.7 - mlly: 1.7.0 + mlly: 1.7.1 pathe: 1.1.2 /possible-typed-array-names@1.0.0: @@ -5903,7 +5906,7 @@ packages: mkdist: 1.5.1(typescript@5.4.5) mlly: 1.7.0 pathe: 1.1.2 - pkg-types: 1.1.1 + pkg-types: 1.1.3 pretty-bytes: 6.1.1 rollup: 3.29.4 rollup-plugin-dts: 6.1.1(rollup@3.29.4)(typescript@5.4.5) From 585a50380bd24a1fcb1637c68ef80479130fa6b5 Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Fri, 2 Aug 2024 21:50:45 +0530 Subject: [PATCH 07/10] cli: add dev mode --- examples/cli/indexers/with-config.indexer.ts | 2 + examples/cli/package.json | 1 + packages/cli/package.json | 2 + packages/cli/src/cli/commands/build.ts | 2 +- packages/cli/src/cli/commands/dev.ts | 97 ++++++- packages/cli/src/cli/commands/prepare.ts | 4 +- packages/cli/src/core/apibara.ts | 4 +- packages/cli/src/core/build/build.ts | 6 +- packages/cli/src/core/build/dev.ts | 83 ++++++ packages/cli/src/core/build/error.ts | 34 +++ packages/cli/src/core/build/prepare.ts | 2 +- packages/cli/src/core/build/types.ts | 12 +- packages/cli/src/core/config/loader.ts | 8 +- packages/cli/src/core/config/update.ts | 6 +- packages/cli/src/rollup/config.ts | 35 ++- pnpm-lock.yaml | 254 +++++++++++++++++++ 16 files changed, 518 insertions(+), 34 deletions(-) create mode 100644 packages/cli/src/core/build/dev.ts create mode 100644 packages/cli/src/core/build/error.ts diff --git a/examples/cli/indexers/with-config.indexer.ts b/examples/cli/indexers/with-config.indexer.ts index f8305b6..6eb70c7 100644 --- a/examples/cli/indexers/with-config.indexer.ts +++ b/examples/cli/indexers/with-config.indexer.ts @@ -1,6 +1,7 @@ import { EvmStream } from "@apibara/evm"; import { defineIndexer } from "@apibara/indexer"; import type { ApibaraRuntimeConfig } from "apibara/types"; +import consola from "consola"; import { encodeEventTopics, parseAbi } from "viem"; const abi = parseAbi([ @@ -8,6 +9,7 @@ const abi = parseAbi([ ]); export default function indexer(runtimeConfig: ApibaraRuntimeConfig) { + consola.log("Runtime Config", runtimeConfig); return defineIndexer(EvmStream)({ streamUrl: "https://sepolia.ethereum.a5a.ch", finality: "accepted", diff --git a/examples/cli/package.json b/examples/cli/package.json index 5567051..f24c5f0 100644 --- a/examples/cli/package.json +++ b/examples/cli/package.json @@ -6,6 +6,7 @@ "apibara:build": "apibara build", "apibara:start": "jiti ./dist/main.mjs", "apibara:prepare": "apibara prepare", + "apibara:dev": "apibara dev", "typecheck": "tsc --noEmit", "lint": "biome check .", "lint:fix": "pnpm lint --write", diff --git a/packages/cli/package.json b/packages/cli/package.json index eb9ede5..9e5f130 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -63,10 +63,12 @@ "citty": "^0.1.6", "consola": "^3.2.3", "defu": "^6.1.4", + "esbuild": "^0.23.0", "fs-extra": "^11.2.0", "hookable": "^5.5.3", "klona": "^2.0.6", "pathe": "^1.1.2", + "perfect-debounce": "^1.0.0", "pkg-types": "^1.1.3", "rollup": "^4.18.1", "tslib": "^2.6.3", diff --git a/packages/cli/src/cli/commands/build.ts b/packages/cli/src/cli/commands/build.ts index 8aee0f0..b1cf6e5 100644 --- a/packages/cli/src/cli/commands/build.ts +++ b/packages/cli/src/cli/commands/build.ts @@ -13,7 +13,7 @@ export default defineCommand({ ...commonArgs, }, async run({ args }) { - consola.info("Building with args", args); + consola.start("Building"); const rootDir = resolve((args.dir || args._dir || ".") as string); const apibara = await createApibara({ rootDir, diff --git a/packages/cli/src/cli/commands/dev.ts b/packages/cli/src/cli/commands/dev.ts index 7561240..4a07a55 100644 --- a/packages/cli/src/cli/commands/dev.ts +++ b/packages/cli/src/cli/commands/dev.ts @@ -1,7 +1,17 @@ +import { type ChildProcess, spawn } from "node:child_process"; +import { build, createApibara, prepare, writeTypes } from "apibara/core"; +import type { Apibara } from "apibara/types"; import { defineCommand } from "citty"; import consola from "consola"; +import { resolve } from "pathe"; import { commonArgs } from "../common"; +// Hot module reloading key regex +// for only runtimeConfig.* keys +const hmrKeyRe = /^runtimeConfig\./; + +let childProcess: ChildProcess | undefined; + export default defineCommand({ meta: { name: "dev", @@ -9,9 +19,92 @@ export default defineCommand({ }, args: { ...commonArgs, + indexers: { + type: "string", + description: "Comma-separated list of indexers to run", + }, + preset: { + type: "string", + description: "Preset to use", + }, + sink: { + type: "string", + description: "Sink to use", + }, }, async run({ args }) { - // TODO - consola.info("Not implemented!", args); + consola.start("Starting dev server"); + const rootDir = resolve((args.dir || args._dir || ".") as string); + let apibara: Apibara; + + const reload = async () => { + if (apibara) { + consola.info("Restarting dev server"); + if ("unwatch" in apibara.options._c12) { + await apibara.options._c12.unwatch(); + } + await apibara.close(); + } + apibara = await createApibara( + { + rootDir, + }, + { + watch: true, + c12: { + async onUpdate({ getDiff, newConfig }) { + const diff = getDiff(); + + if (diff.length === 0) { + return; // No changes + } + + consola.info( + `Nitro config updated: + ${diff.map((entry) => ` ${entry.toString()}`).join("\n")}`, + ); + await (diff.every((e) => hmrKeyRe.test(e.key)) + ? apibara.updateConfig(newConfig.config || {}) // Hot reload + : reload()); // Full reload + }, + }, + }, + true, + ); + apibara.hooks.hookOnce("restart", reload); + + await writeTypes(apibara); + await prepare(apibara); + await build(apibara); + + apibara.hooks.hook("dev:reload", () => { + if (childProcess) { + consola.start("Restarting indexers"); + childProcess.kill(); + } else { + consola.success("Dev server started"); + consola.success("Starting indexers"); + } + + const childArgs = [ + resolve(apibara.options.outputDir || "./dist", "main.mjs"), + ...(args.indexers ? ["--indexers", args.indexers] : []), + ...(args.preset ? ["--preset", args.preset] : []), + ...(args.sink ? ["--sink", args.sink] : []), + ]; + + childProcess = spawn("jiti", childArgs, { + stdio: "inherit", + }); + + childProcess.on("close", (code) => { + if (code !== null) { + consola.log(`Indexers process exited with code ${code}`); + } + }); + }); + }; + + await reload(); }, }); diff --git a/packages/cli/src/cli/commands/prepare.ts b/packages/cli/src/cli/commands/prepare.ts index 5b81b00..21f0233 100644 --- a/packages/cli/src/cli/commands/prepare.ts +++ b/packages/cli/src/cli/commands/prepare.ts @@ -3,9 +3,7 @@ import {} from "apibara/types"; import { defineCommand } from "citty"; import consola from "consola"; import { resolve } from "pathe"; -// import { createApibara } from "../../apibara"; import { commonArgs } from "../common"; -// import { writeTypes } from "../../core/build/types"; export default defineCommand({ meta: { @@ -16,7 +14,7 @@ export default defineCommand({ ...commonArgs, }, async run({ args }) { - consola.info("Prepairing \n\n"); + consola.start("Prepairing Types"); const rootDir = resolve((args.dir || ".") as string); const apibara = await createApibara({ rootDir }); await writeTypes(apibara); diff --git a/packages/cli/src/core/apibara.ts b/packages/cli/src/core/apibara.ts index 52bca23..664c6ff 100644 --- a/packages/cli/src/core/apibara.ts +++ b/packages/cli/src/core/apibara.ts @@ -12,9 +12,10 @@ import { updateApibaraConfig } from "./config/update"; export async function createApibara( config: ApibaraConfig = {}, opts: LoadConfigOptions = {}, + dev = false, ): Promise { // load options - const options = await loadOptions(config, opts); + const options = await loadOptions(config, opts, dev); // create apibara context const apibara: Apibara = { @@ -29,6 +30,5 @@ export async function createApibara( apibara.hooks.addHooks(apibara.options.hooks); - // TODO return apibara; } diff --git a/packages/cli/src/core/build/build.ts b/packages/cli/src/core/build/build.ts index 140ed5a..a9cfed3 100644 --- a/packages/cli/src/core/build/build.ts +++ b/packages/cli/src/core/build/build.ts @@ -1,8 +1,12 @@ import { getRollupConfig } from "apibara/rollup"; import type { Apibara } from "apibara/types"; +import { watchDev } from "./dev"; import { buildProduction } from "./prod"; export async function build(apibara: Apibara) { const rollupConfig = getRollupConfig(apibara); - return await buildProduction(apibara, rollupConfig); + await apibara.hooks.callHook("rollup:before", apibara, rollupConfig); + return apibara.options.dev + ? await watchDev(apibara, rollupConfig) + : await buildProduction(apibara, rollupConfig); } diff --git a/packages/cli/src/core/build/dev.ts b/packages/cli/src/core/build/dev.ts new file mode 100644 index 0000000..ff0546b --- /dev/null +++ b/packages/cli/src/core/build/dev.ts @@ -0,0 +1,83 @@ +import type { Apibara, RollupConfig } from "apibara/types"; +import { watch } from "chokidar"; +import defu from "defu"; +import { join } from "pathe"; +import { debounce } from "perfect-debounce"; +import * as rollup from "rollup"; +import { formatRollupError } from "./error"; + +export async function watchDev(apibara: Apibara, rollupConfig: RollupConfig) { + let rollupWatcher: rollup.RollupWatcher; + + async function load() { + if (rollupWatcher) { + await rollupWatcher.close(); + } + rollupWatcher = startRollupWatcher(apibara, rollupConfig); + } + const reload = debounce(load); + + const watchPatterns = [join(apibara.options.rootDir, "indexers")]; + + const watchReloadEvents = new Set(["add", "addDir", "unlink", "unlinkDir"]); + const reloadWatcher = watch(watchPatterns, { ignoreInitial: true }).on( + "all", + (event) => { + if (watchReloadEvents.has(event)) { + reload(); + } + }, + ); + + apibara.hooks.hook("close", () => { + rollupWatcher.close(); + reloadWatcher.close(); + }); + + apibara.hooks.hook("rollup:reload", () => reload()); + + await load(); +} + +function startRollupWatcher(apibara: Apibara, rollupConfig: RollupConfig) { + const watcher = rollup.watch( + defu(rollupConfig, { + watch: { + chokidar: apibara.options.watchOptions, + }, + }), + ); + let start: number; + + watcher.on("event", (event) => { + switch (event.code) { + // The watcher is (re)starting + case "START": { + return; + } + + // Building an individual bundle + case "BUNDLE_START": { + start = Date.now(); + return; + } + + // Finished building all bundles + case "END": { + apibara.hooks.callHook("compiled", apibara); + apibara.logger.success( + "Indexers built", + start ? `in ${Date.now() - start} ms` : "", + ); + apibara.hooks.callHook("dev:reload"); + return; + } + + // Encountered an error while bundling + case "ERROR": { + apibara.logger.error(formatRollupError(event.error)); + } + } + }); + return watcher; +} diff --git a/packages/cli/src/core/build/error.ts b/packages/cli/src/core/build/error.ts new file mode 100644 index 0000000..3a6abe9 --- /dev/null +++ b/packages/cli/src/core/build/error.ts @@ -0,0 +1,34 @@ +import type esbuild from "esbuild"; +import { isAbsolute, relative } from "pathe"; +import type rollup from "rollup"; + +export function formatRollupError( + _error: rollup.RollupError | esbuild.OnResolveResult, +) { + try { + const logs: string[] = [_error.toString()]; + // biome-ignore lint/suspicious/noExplicitAny: + const errors = (_error as any)?.errors || [_error as rollup.RollupError]; + for (const error of errors) { + const id = error.path || error.id || (_error as rollup.RollupError).id; + let path = isAbsolute(id) ? relative(process.cwd(), id) : id; + const location = + (error as rollup.RollupError).loc || + (error as esbuild.PartialMessage).location; + if (location) { + path += `:${location.line}:${location.column}`; + } + const text = + (error as esbuild.PartialMessage).text || + (error as rollup.RollupError).frame; + + logs.push( + // biome-ignore lint/style/useTemplate: + `Rollup error while processing \`${path}\`` + text ? "\n\n" + text : "", + ); + } + return logs.join("\n"); + } catch { + return _error?.toString(); + } +} diff --git a/packages/cli/src/core/build/prepare.ts b/packages/cli/src/core/build/prepare.ts index 782e394..b0cb805 100644 --- a/packages/cli/src/core/build/prepare.ts +++ b/packages/cli/src/core/build/prepare.ts @@ -4,8 +4,8 @@ import consola from "consola"; import fse from "fs-extra"; export async function prepare(apibara: Apibara) { - consola.info("Cleaning output directory"); await prepareDir(apibara.options.outputDir); + consola.success("Output directory cleaned"); } async function prepareDir(dir: string) { diff --git a/packages/cli/src/core/build/types.ts b/packages/cli/src/core/build/types.ts index 667273b..979d963 100644 --- a/packages/cli/src/core/build/types.ts +++ b/packages/cli/src/core/build/types.ts @@ -131,17 +131,7 @@ declare module "apibara/types" {`, }), ); - consola.info( - "To leverage type hints within your project, create a tsconfig.json file that extends auto generated types.\n", - ); - consola.log.raw( - { - extends: "./.apibara/types/tsconfig.json", - }, - "\n\n", - ); - - consola.success("Preparation successful!\n\n"); + consola.success("Types generated"); } const RELATIVE_RE = /^\.{1,2}\//; diff --git a/packages/cli/src/core/config/loader.ts b/packages/cli/src/core/config/loader.ts index ac2b0de..4dd7c81 100644 --- a/packages/cli/src/core/config/loader.ts +++ b/packages/cli/src/core/config/loader.ts @@ -19,8 +19,9 @@ const configResolvers = [ export async function loadOptions( configOverrides: ApibaraConfig = {}, opts: LoadConfigOptions = {}, + dev = false, ): Promise { - const options = await _loadUserConfig(configOverrides, opts); + const options = await _loadUserConfig(configOverrides, opts, dev); for (const resolver of configResolvers) { await resolver(options); } @@ -30,6 +31,7 @@ export async function loadOptions( async function _loadUserConfig( configOverrides: ApibaraConfig = {}, opts: LoadConfigOptions = {}, + dev = false, ): Promise { // biome-ignore lint: noParameterAssign configOverrides = klona(configOverrides); @@ -38,6 +40,7 @@ async function _loadUserConfig( ? watchConfig : loadConfig)({ name: "apibara", + dotenv: dev, // path from where apibara.config.ts is loaded // defautl is "." path // cwd: configOverrides.rootDir, @@ -52,6 +55,9 @@ async function _loadUserConfig( options._config = configOverrides; options._c12 = loadedConfig; + if (dev) { + options.dev = dev; + } return options; } diff --git a/packages/cli/src/core/config/update.ts b/packages/cli/src/core/config/update.ts index b87b102..54d70a2 100644 --- a/packages/cli/src/core/config/update.ts +++ b/packages/cli/src/core/config/update.ts @@ -1,10 +1,10 @@ import type { Apibara, ApibaraDynamicConfig } from "apibara/types"; +import consola from "consola"; export async function updateApibaraConfig( apibara: Apibara, config: ApibaraDynamicConfig, ) { - // Do something - // await apibara.hooks.callHook("rollup:reload"); - // consola.success("Apibara config hot reloaded!"); + await apibara.hooks.callHook("rollup:reload"); + consola.success("Apibara config hot reloaded!"); } diff --git a/packages/cli/src/rollup/config.ts b/packages/cli/src/rollup/config.ts index 1eeed19..d588c02 100644 --- a/packages/cli/src/rollup/config.ts +++ b/packages/cli/src/rollup/config.ts @@ -141,19 +141,19 @@ runMain(command); output: { dir: join(apibara.options.outputDir || "dist"), format: "esm", + exports: "auto", entryFileNames: "[name].mjs", chunkFileNames: "chunks/[name]-[hash].mjs", + generatedCode: { + constBindings: true, + }, + sourcemap: true, + sourcemapExcludeSources: true, + sourcemapIgnoreList(relativePath, sourcemapPath) { + return relativePath.includes("node_modules"); + }, }, plugins: [ - commonjs(), - json(), - typescript({ - tsconfig: join("./tsconfig.json"), - }), - nodeResolve({ - extensions, - preferBuiltins: true, - }), { name: "virtual", resolveId(id) { @@ -169,7 +169,24 @@ runMain(command); return null; }, }, + nodeResolve({ + extensions, + preferBuiltins: true, + }), + commonjs(), + json(), + typescript({ + tsconfig: join("./tsconfig.json"), + }), ], + onwarn(warning, rollupWarn) { + if ( + !["CIRCULAR_DEPENDENCY", "EVAL"].includes(warning.code || "") && + !warning.message.includes("Unsupported source map comment") + ) { + rollupWarn(warning); + } + }, treeshake: true, external: [ ...builtinModules, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6f2b11d..e62f9ae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -342,6 +342,9 @@ importers: defu: specifier: ^6.1.4 version: 6.1.4 + esbuild: + specifier: ^0.23.0 + version: 0.23.0 fs-extra: specifier: ^11.2.0 version: 11.2.0 @@ -354,6 +357,9 @@ importers: pathe: specifier: ^1.1.2 version: 1.1.2 + perfect-debounce: + specifier: ^1.0.0 + version: 1.0.0 pkg-types: specifier: ^1.1.3 version: 1.1.3 @@ -1218,6 +1224,15 @@ packages: dev: true optional: true + /@esbuild/aix-ppc64@0.23.0: + resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: false + optional: true + /@esbuild/android-arm64@0.19.11: resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} engines: {node: '>=12'} @@ -1236,6 +1251,15 @@ packages: dev: true optional: true + /@esbuild/android-arm64@0.23.0: + resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + /@esbuild/android-arm@0.19.11: resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} engines: {node: '>=12'} @@ -1254,6 +1278,15 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.23.0: + resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + /@esbuild/android-x64@0.19.11: resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} engines: {node: '>=12'} @@ -1272,6 +1305,15 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.23.0: + resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + /@esbuild/darwin-arm64@0.19.11: resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} engines: {node: '>=12'} @@ -1290,6 +1332,15 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.23.0: + resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + /@esbuild/darwin-x64@0.19.11: resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} engines: {node: '>=12'} @@ -1308,6 +1359,15 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.23.0: + resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + /@esbuild/freebsd-arm64@0.19.11: resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} engines: {node: '>=12'} @@ -1326,6 +1386,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.23.0: + resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + /@esbuild/freebsd-x64@0.19.11: resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} engines: {node: '>=12'} @@ -1344,6 +1413,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.23.0: + resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-arm64@0.19.11: resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} engines: {node: '>=12'} @@ -1362,6 +1440,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.23.0: + resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-arm@0.19.11: resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} engines: {node: '>=12'} @@ -1380,6 +1467,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.23.0: + resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-ia32@0.19.11: resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} engines: {node: '>=12'} @@ -1398,6 +1494,15 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.23.0: + resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-loong64@0.19.11: resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} engines: {node: '>=12'} @@ -1416,6 +1521,15 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.23.0: + resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-mips64el@0.19.11: resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} engines: {node: '>=12'} @@ -1434,6 +1548,15 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.23.0: + resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-ppc64@0.19.11: resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} engines: {node: '>=12'} @@ -1452,6 +1575,15 @@ packages: dev: true optional: true + /@esbuild/linux-ppc64@0.23.0: + resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-riscv64@0.19.11: resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} engines: {node: '>=12'} @@ -1470,6 +1602,15 @@ packages: dev: true optional: true + /@esbuild/linux-riscv64@0.23.0: + resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-s390x@0.19.11: resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} engines: {node: '>=12'} @@ -1488,6 +1629,15 @@ packages: dev: true optional: true + /@esbuild/linux-s390x@0.23.0: + resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/linux-x64@0.19.11: resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} engines: {node: '>=12'} @@ -1506,6 +1656,15 @@ packages: dev: true optional: true + /@esbuild/linux-x64@0.23.0: + resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@esbuild/netbsd-x64@0.19.11: resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} engines: {node: '>=12'} @@ -1524,6 +1683,24 @@ packages: dev: true optional: true + /@esbuild/netbsd-x64@0.23.0: + resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-arm64@0.23.0: + resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + /@esbuild/openbsd-x64@0.19.11: resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} engines: {node: '>=12'} @@ -1542,6 +1719,15 @@ packages: dev: true optional: true + /@esbuild/openbsd-x64@0.23.0: + resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + /@esbuild/sunos-x64@0.19.11: resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} engines: {node: '>=12'} @@ -1560,6 +1746,15 @@ packages: dev: true optional: true + /@esbuild/sunos-x64@0.23.0: + resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + /@esbuild/win32-arm64@0.19.11: resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} engines: {node: '>=12'} @@ -1578,6 +1773,15 @@ packages: dev: true optional: true + /@esbuild/win32-arm64@0.23.0: + resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@esbuild/win32-ia32@0.19.11: resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} engines: {node: '>=12'} @@ -1596,6 +1800,15 @@ packages: dev: true optional: true + /@esbuild/win32-ia32@0.23.0: + resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@esbuild/win32-x64@0.19.11: resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} engines: {node: '>=12'} @@ -1614,6 +1827,15 @@ packages: dev: true optional: true + /@esbuild/win32-x64@0.23.0: + resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@grpc/grpc-js@1.9.14: resolution: {integrity: sha512-nOpuzZ2G3IuMFN+UPPpKrC6NsLmWsTqSsm66IRfnBt1D4pwTqE27lmbpcPM+l2Ua4gE7PfjRHI6uedAy7hoXUw==} engines: {node: ^8.13.0 || >=10.10.0} @@ -3419,6 +3641,38 @@ packages: '@esbuild/win32-x64': 0.20.2 dev: true + /esbuild@0.23.0: + resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.0 + '@esbuild/android-arm': 0.23.0 + '@esbuild/android-arm64': 0.23.0 + '@esbuild/android-x64': 0.23.0 + '@esbuild/darwin-arm64': 0.23.0 + '@esbuild/darwin-x64': 0.23.0 + '@esbuild/freebsd-arm64': 0.23.0 + '@esbuild/freebsd-x64': 0.23.0 + '@esbuild/linux-arm': 0.23.0 + '@esbuild/linux-arm64': 0.23.0 + '@esbuild/linux-ia32': 0.23.0 + '@esbuild/linux-loong64': 0.23.0 + '@esbuild/linux-mips64el': 0.23.0 + '@esbuild/linux-ppc64': 0.23.0 + '@esbuild/linux-riscv64': 0.23.0 + '@esbuild/linux-s390x': 0.23.0 + '@esbuild/linux-x64': 0.23.0 + '@esbuild/netbsd-x64': 0.23.0 + '@esbuild/openbsd-arm64': 0.23.0 + '@esbuild/openbsd-x64': 0.23.0 + '@esbuild/sunos-x64': 0.23.0 + '@esbuild/win32-arm64': 0.23.0 + '@esbuild/win32-ia32': 0.23.0 + '@esbuild/win32-x64': 0.23.0 + dev: false + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} From 8a0cfd11cb65144065bad8eb080539839d54353f Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Tue, 6 Aug 2024 19:43:46 +0530 Subject: [PATCH 08/10] cli: change output directory to .apibara --- examples/cli/package.json | 4 ++-- packages/cli/src/cli/commands/dev.ts | 2 +- packages/cli/src/cli/commands/prepare.ts | 2 +- packages/cli/src/core/config/defaults.ts | 2 +- packages/cli/src/rollup/config.ts | 8 +++++++- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/examples/cli/package.json b/examples/cli/package.json index f24c5f0..da1bb33 100644 --- a/examples/cli/package.json +++ b/examples/cli/package.json @@ -4,10 +4,10 @@ "private": true, "scripts": { "apibara:build": "apibara build", - "apibara:start": "jiti ./dist/main.mjs", + "apibara:start": "jiti ./.apibara/build/main.mjs", "apibara:prepare": "apibara prepare", "apibara:dev": "apibara dev", - "typecheck": "tsc --noEmit", + "typecheck": "pnpm apibara:prepare && tsc --noEmit", "lint": "biome check .", "lint:fix": "pnpm lint --write", "format": "biome format . --write" diff --git a/packages/cli/src/cli/commands/dev.ts b/packages/cli/src/cli/commands/dev.ts index 4a07a55..e6ce116 100644 --- a/packages/cli/src/cli/commands/dev.ts +++ b/packages/cli/src/cli/commands/dev.ts @@ -87,7 +87,7 @@ export default defineCommand({ } const childArgs = [ - resolve(apibara.options.outputDir || "./dist", "main.mjs"), + resolve(apibara.options.outputDir || "./.apibara/build", "main.mjs"), ...(args.indexers ? ["--indexers", args.indexers] : []), ...(args.preset ? ["--preset", args.preset] : []), ...(args.sink ? ["--sink", args.sink] : []), diff --git a/packages/cli/src/cli/commands/prepare.ts b/packages/cli/src/cli/commands/prepare.ts index 21f0233..d0c7816 100644 --- a/packages/cli/src/cli/commands/prepare.ts +++ b/packages/cli/src/cli/commands/prepare.ts @@ -14,7 +14,7 @@ export default defineCommand({ ...commonArgs, }, async run({ args }) { - consola.start("Prepairing Types"); + consola.start("Preparing Types"); const rootDir = resolve((args.dir || ".") as string); const apibara = await createApibara({ rootDir }); await writeTypes(apibara); diff --git a/packages/cli/src/core/config/defaults.ts b/packages/cli/src/core/config/defaults.ts index c3a4526..7c8673f 100644 --- a/packages/cli/src/core/config/defaults.ts +++ b/packages/cli/src/core/config/defaults.ts @@ -3,7 +3,7 @@ import type { ApibaraConfig } from "apibara/types"; export const ApibaraDefaults: ApibaraConfig = { rootDir: ".", - outputDir: "./dist", + outputDir: "./.apibara/build", runtimeConfig: {}, hooks: {}, diff --git a/packages/cli/src/rollup/config.ts b/packages/cli/src/rollup/config.ts index d588c02..1da6ba6 100644 --- a/packages/cli/src/rollup/config.ts +++ b/packages/cli/src/rollup/config.ts @@ -139,7 +139,7 @@ runMain(command); main: "virtual:main.ts", }, output: { - dir: join(apibara.options.outputDir || "dist"), + dir: join(apibara.options.outputDir || "./.apibara/build"), format: "esm", exports: "auto", entryFileNames: "[name].mjs", @@ -177,6 +177,12 @@ runMain(command); json(), typescript({ tsconfig: join("./tsconfig.json"), + compilerOptions: { + outDir: join(apibara.options.outputDir || "./.apibara/build"), + declarationDir: join(apibara.options.outputDir || "./.apibara/build"), + noEmit: false, + types: ["node"], + }, }), ], onwarn(warning, rollupWarn) { From abd4b77519e3476493533c0aa3f714cd7f40ac06 Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Tue, 6 Aug 2024 22:49:52 +0530 Subject: [PATCH 09/10] ci: fix cli typecheck --- .github/workflows/build.yml | 4 ++-- turbo.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e66e7b7..37a8004 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,9 +33,9 @@ jobs: run: pnpm lint - name: Run format run: pnpm format - - name: Run typecheck - run: pnpm typecheck - name: Run build run: pnpm build + - name: Run typecheck + run: pnpm typecheck - name: Run test run: pnpm test:ci diff --git a/turbo.json b/turbo.json index a7458e6..6732b07 100644 --- a/turbo.json +++ b/turbo.json @@ -12,6 +12,7 @@ "dependsOn": ["build"] }, "typecheck": { + "dependsOn": ["build"], "cache": false }, "lint": { From 16541b912ddecba119b81b38343597cbb091a7cf Mon Sep 17 00:00:00 2001 From: jaipaljadeja Date: Wed, 7 Aug 2024 20:34:49 +0530 Subject: [PATCH 10/10] cli: add playground --- examples/cli/package.json | 37 ---------- packages/cli/package.json | 10 ++- .../cli/playground}/apibara.config.ts | 0 .../playground}/indexers/simple.indexer.ts | 0 .../indexers/with-config.indexer.ts | 0 .../cli/playground}/tsconfig.json | 2 +- packages/cli/src/cli/commands/build.ts | 3 +- packages/cli/src/cli/commands/dev.ts | 2 +- packages/cli/src/core/build/prepare.ts | 1 + packages/cli/src/core/config/defaults.ts | 1 - packages/cli/src/core/config/loader.ts | 4 +- .../core/config/resolvers/paths.resolver.ts | 8 +++ packages/cli/src/rollup/config.ts | 4 +- pnpm-lock.yaml | 67 +++---------------- 14 files changed, 34 insertions(+), 105 deletions(-) delete mode 100644 examples/cli/package.json rename {examples/cli => packages/cli/playground}/apibara.config.ts (100%) rename {examples/cli => packages/cli/playground}/indexers/simple.indexer.ts (100%) rename {examples/cli => packages/cli/playground}/indexers/with-config.indexer.ts (100%) rename {examples/cli => packages/cli/playground}/tsconfig.json (72%) diff --git a/examples/cli/package.json b/examples/cli/package.json deleted file mode 100644 index da1bb33..0000000 --- a/examples/cli/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "example-cli", - "version": "1.0.0", - "private": true, - "scripts": { - "apibara:build": "apibara build", - "apibara:start": "jiti ./.apibara/build/main.mjs", - "apibara:prepare": "apibara prepare", - "apibara:dev": "apibara dev", - "typecheck": "pnpm apibara:prepare && tsc --noEmit", - "lint": "biome check .", - "lint:fix": "pnpm lint --write", - "format": "biome format . --write" - }, - "dependencies": { - "@apibara/evm": "workspace:*", - "@apibara/indexer": "workspace:*", - "@apibara/protocol": "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", - "apibara": "workspace:*", - "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" - } -} diff --git a/packages/cli/package.json b/packages/cli/package.json index 9e5f130..b252043 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -43,17 +43,25 @@ "lint": "biome check .", "typecheck": "tsc --noEmit", "lint:fix": "pnpm lint --write", - "format": "biome format . --write" + "format": "biome format . --write", + "playground": "JITI_ESM_RESOLVE=1 NODE_OPTIONS=\"--enable-source-maps\" jiti ./src/cli/index.ts", + "playground:prepare": "pnpm playground prepare --dir playground", + "playground:dev": "pnpm playground dev --dir playground", + "playground:build": "pnpm playground build --dir playground", + "playground:start": "jiti ./playground/.apibara/build/main.mjs" }, "devDependencies": { "@types/fs-extra": "^11.0.4", "@types/node": "^20.14.0", "jiti": "^1.21.0", "unbuild": "^2.0.0", + "viem": "^2.12.4", "vitest": "^1.6.0" }, "dependencies": { + "@apibara/evm": "workspace:*", "@apibara/indexer": "workspace:*", + "@apibara/protocol": "workspace:*", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", diff --git a/examples/cli/apibara.config.ts b/packages/cli/playground/apibara.config.ts similarity index 100% rename from examples/cli/apibara.config.ts rename to packages/cli/playground/apibara.config.ts diff --git a/examples/cli/indexers/simple.indexer.ts b/packages/cli/playground/indexers/simple.indexer.ts similarity index 100% rename from examples/cli/indexers/simple.indexer.ts rename to packages/cli/playground/indexers/simple.indexer.ts diff --git a/examples/cli/indexers/with-config.indexer.ts b/packages/cli/playground/indexers/with-config.indexer.ts similarity index 100% rename from examples/cli/indexers/with-config.indexer.ts rename to packages/cli/playground/indexers/with-config.indexer.ts diff --git a/examples/cli/tsconfig.json b/packages/cli/playground/tsconfig.json similarity index 72% rename from examples/cli/tsconfig.json rename to packages/cli/playground/tsconfig.json index 3ec03b8..8247ce6 100644 --- a/examples/cli/tsconfig.json +++ b/packages/cli/playground/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": ["../../tsconfig.json", "./.apibara/types/tsconfig.json"], + "extends": ["../../../tsconfig.json", "./.apibara/types/tsconfig.json"], "compilerOptions": { "outDir": "dist", "declarationDir": "dist", diff --git a/packages/cli/src/cli/commands/build.ts b/packages/cli/src/cli/commands/build.ts index b1cf6e5..840d292 100644 --- a/packages/cli/src/cli/commands/build.ts +++ b/packages/cli/src/cli/commands/build.ts @@ -1,4 +1,4 @@ -import { build, createApibara, prepare } from "apibara/core"; +import { build, createApibara, prepare, writeTypes } from "apibara/core"; import { defineCommand } from "citty"; import consola from "consola"; import { resolve } from "pathe"; @@ -19,6 +19,7 @@ export default defineCommand({ rootDir, }); await prepare(apibara); + await writeTypes(apibara); await build(apibara); await apibara.close(); }, diff --git a/packages/cli/src/cli/commands/dev.ts b/packages/cli/src/cli/commands/dev.ts index e6ce116..e37edbd 100644 --- a/packages/cli/src/cli/commands/dev.ts +++ b/packages/cli/src/cli/commands/dev.ts @@ -73,8 +73,8 @@ export default defineCommand({ ); apibara.hooks.hookOnce("restart", reload); - await writeTypes(apibara); await prepare(apibara); + await writeTypes(apibara); await build(apibara); apibara.hooks.hook("dev:reload", () => { diff --git a/packages/cli/src/core/build/prepare.ts b/packages/cli/src/core/build/prepare.ts index b0cb805..3f34de7 100644 --- a/packages/cli/src/core/build/prepare.ts +++ b/packages/cli/src/core/build/prepare.ts @@ -4,6 +4,7 @@ import consola from "consola"; import fse from "fs-extra"; export async function prepare(apibara: Apibara) { + await prepareDir(apibara.options.buildDir); await prepareDir(apibara.options.outputDir); consola.success("Output directory cleaned"); } diff --git a/packages/cli/src/core/config/defaults.ts b/packages/cli/src/core/config/defaults.ts index 7c8673f..0c421c8 100644 --- a/packages/cli/src/core/config/defaults.ts +++ b/packages/cli/src/core/config/defaults.ts @@ -3,7 +3,6 @@ import type { ApibaraConfig } from "apibara/types"; export const ApibaraDefaults: ApibaraConfig = { rootDir: ".", - outputDir: "./.apibara/build", runtimeConfig: {}, hooks: {}, diff --git a/packages/cli/src/core/config/loader.ts b/packages/cli/src/core/config/loader.ts index 4dd7c81..ee3d285 100644 --- a/packages/cli/src/core/config/loader.ts +++ b/packages/cli/src/core/config/loader.ts @@ -41,9 +41,7 @@ async function _loadUserConfig( : loadConfig)({ name: "apibara", dotenv: dev, - // path from where apibara.config.ts is loaded - // defautl is "." path - // cwd: configOverrides.rootDir, + cwd: configOverrides.rootDir, overrides: { ...configOverrides, }, diff --git a/packages/cli/src/core/config/resolvers/paths.resolver.ts b/packages/cli/src/core/config/resolvers/paths.resolver.ts index 329200b..80d056e 100644 --- a/packages/cli/src/core/config/resolvers/paths.resolver.ts +++ b/packages/cli/src/core/config/resolvers/paths.resolver.ts @@ -3,4 +3,12 @@ import { resolve } from "pathe"; export async function resolvePathOptions(options: ApibaraOptions) { options.rootDir = resolve(options.rootDir || "."); + + for (const key of ["buildDir"] as const) { + options[key] = resolve(options.rootDir, options[key]); + } + + if (!options.outputDir) { + options.outputDir = resolve(options.rootDir, ".apibara/build"); + } } diff --git a/packages/cli/src/rollup/config.ts b/packages/cli/src/rollup/config.ts index 1da6ba6..82f6e1f 100644 --- a/packages/cli/src/rollup/config.ts +++ b/packages/cli/src/rollup/config.ts @@ -23,7 +23,7 @@ export const getRollupConfig = ( ]; const indexerDir = join(apibara.options.rootDir, "indexers"); - const configPath = join("./apibara.config.ts"); + const configPath = join(apibara.options.rootDir, "./apibara.config.ts"); // Check if the indexers directory and config file exist if (!existsSync(indexerDir)) { @@ -176,7 +176,7 @@ runMain(command); commonjs(), json(), typescript({ - tsconfig: join("./tsconfig.json"), + tsconfig: join(apibara.options.rootDir, "./tsconfig.json"), compilerOptions: { outDir: join(apibara.options.outputDir || "./.apibara/build"), declarationDir: join(apibara.options.outputDir || "./.apibara/build"), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e62f9ae..232a576 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,64 +49,6 @@ importers: specifier: ^1.21.0 version: 1.21.0 - examples/cli: - dependencies: - '@apibara/evm': - specifier: workspace:* - version: link:../../packages/evm - '@apibara/indexer': - specifier: workspace:* - version: link:../../packages/indexer - '@apibara/protocol': - specifier: workspace:* - version: link:../../packages/protocol - '@opentelemetry/api': - specifier: ^1.9.0 - version: 1.9.0 - '@opentelemetry/exporter-trace-otlp-proto': - specifier: ^0.52.0 - version: 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': - specifier: ^1.25.0 - version: 1.25.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': - specifier: ^0.52.0 - version: 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': - specifier: ^1.25.0 - version: 1.25.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': - specifier: ^1.25.0 - version: 1.25.0 - apibara: - specifier: workspace:* - version: link:../../packages/cli - better-sqlite3: - specifier: ^11.1.2 - version: 11.1.2 - citty: - specifier: ^0.1.6 - version: 0.1.6 - consola: - specifier: ^3.2.3 - version: 3.2.3 - csv-stringify: - specifier: ^6.5.0 - version: 6.5.0 - viem: - specifier: ^2.12.4 - version: 2.13.8(typescript@5.4.5) - devDependencies: - '@types/better-sqlite3': - specifier: ^7.6.11 - version: 7.6.11 - '@types/node': - specifier: ^20.12.12 - version: 20.14.0 - jiti: - specifier: ^1.21.0 - version: 1.21.6 - examples/evm-client: dependencies: '@apibara/evm': @@ -312,9 +254,15 @@ importers: packages/cli: dependencies: + '@apibara/evm': + specifier: workspace:* + version: link:../evm '@apibara/indexer': specifier: workspace:* version: link:../indexer + '@apibara/protocol': + specifier: workspace:* + version: link:../protocol '@rollup/plugin-commonjs': specifier: ^26.0.1 version: 26.0.1(rollup@4.18.1) @@ -385,6 +333,9 @@ importers: unbuild: specifier: ^2.0.0 version: 2.0.0(typescript@5.4.5) + viem: + specifier: ^2.12.4 + version: 2.13.8(typescript@5.4.5) vitest: specifier: ^1.6.0 version: 1.6.0(@types/node@20.14.0)