@thru/indexer 0.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +477 -0
- package/dist/index.cjs +1208 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1064 -0
- package/dist/index.d.ts +1064 -0
- package/dist/index.mjs +1185 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema/builder.ts","../src/schema/table.ts","../src/schema/validation.ts","../src/streams/define.ts","../src/checkpoint/table.ts","../src/checkpoint/repository.ts","../src/checkpoint/index.ts","../src/streams/processor.ts","../src/accounts/define.ts","../src/accounts/processor.ts","../src/api/pagination.ts","../src/api/schemas.ts","../src/api/routes.ts","../src/runtime/indexer.ts"],"names":["z","pgTable","text","bigint","timestamp","exports","pascalCase","eq","sql"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Fluent column builder API for defining schemas.\n * Exports a global `t` object for concise schema definitions.\n *\n * @example\n * ```ts\n * import { t } from \"@thru/indexer\";\n *\n * const schema = {\n * id: t.text().primaryKey(),\n * slot: t.bigint().notNull().index(),\n * amount: t.bigint().notNull(),\n * timestamp: t.timestamp(),\n * };\n * ```\n */\n\nimport type { PgTableWithColumns } from \"drizzle-orm/pg-core\";\nimport type { ColumnDef, ColumnType } from \"./types\";\n\n// ============================================================\n// Column Definition Implementation\n// ============================================================\n\ninterface ColumnState<T> {\n _type: T;\n _columnType: ColumnType;\n _nullable: boolean;\n _indexed: boolean;\n _unique: boolean;\n _primary: boolean;\n _default?: T;\n _defaultNow?: boolean;\n _references?: { table: PgTableWithColumns<any>; column: string };\n}\n\n/**\n * Create a builder object from state with the given nullability type parameter.\n */\nfunction createBuilder<T, TNull extends boolean>(\n state: ColumnState<T>\n): ColumnDef<T, TNull> {\n const builder: ColumnDef<T, TNull> = {\n get _type() { return state._type; },\n get _columnType() { return state._columnType; },\n get _nullable() { return state._nullable as TNull; },\n get _indexed() { return state._indexed; },\n get _unique() { return state._unique; },\n get _primary() { return state._primary; },\n get _default() { return state._default; },\n get _defaultNow() { return state._defaultNow; },\n get _references() { return state._references; },\n\n notNull(): ColumnDef<T, false> {\n state._nullable = false;\n return createBuilder<T, false>(state);\n },\n\n index(): ColumnDef<T, TNull> {\n state._indexed = true;\n return builder;\n },\n\n unique(): ColumnDef<T, TNull> {\n state._unique = true;\n return builder;\n },\n\n primaryKey(): ColumnDef<T, false> {\n state._primary = true;\n state._nullable = false;\n return createBuilder<T, false>(state);\n },\n\n default(value: T): ColumnDef<T, TNull> {\n state._default = value;\n return builder;\n },\n\n defaultNow(): ColumnDef<T, TNull> {\n state._defaultNow = true;\n return builder;\n },\n\n references<TTable extends PgTableWithColumns<any>>(\n table: TTable | (() => TTable),\n column: keyof TTable[\"_\"][\"columns\"]\n ): ColumnDef<T, TNull> {\n const resolvedTable = typeof table === \"function\" ? table() : table;\n state._references = { table: resolvedTable, column: column as string };\n return builder;\n },\n };\n\n return builder;\n}\n\n/**\n * Creates a column definition with proper type tracking.\n */\nfunction createColumnDef<T>(type: ColumnType): ColumnDef<T, true> {\n const state: ColumnState<T> = {\n _type: undefined as T,\n _columnType: type,\n _nullable: true,\n _indexed: false,\n _unique: false,\n _primary: false,\n _default: undefined,\n _defaultNow: false,\n _references: undefined,\n };\n\n return createBuilder<T, true>(state);\n}\n\n// ============================================================\n// Column Builder Interface\n// ============================================================\n\n/**\n * Interface for the column builder.\n * Each method creates a new column definition of the appropriate type.\n */\nexport interface ColumnBuilder {\n /** Text column (varchar) */\n text(): ColumnDef<string, true>;\n /** BigInt column (64-bit integer) - use for slots, amounts */\n bigint(): ColumnDef<bigint, true>;\n /** Integer column (32-bit) */\n integer(): ColumnDef<number, true>;\n /** Boolean column */\n boolean(): ColumnDef<boolean, true>;\n /** Timestamp column with timezone */\n timestamp(): ColumnDef<Date, true>;\n}\n\n// ============================================================\n// Global Column Builder\n// ============================================================\n\n/**\n * Global column builder for defining schemas.\n *\n * @example\n * ```ts\n * const schema = {\n * id: t.text().primaryKey(),\n * slot: t.bigint().notNull().index(),\n * name: t.text(),\n * active: t.boolean().notNull().default(true),\n * createdAt: t.timestamp().notNull().defaultNow(),\n * };\n * ```\n */\nexport const t: ColumnBuilder = {\n text: () => createColumnDef<string>(\"text\"),\n bigint: () => createColumnDef<bigint>(\"bigint\"),\n integer: () => createColumnDef<number>(\"integer\"),\n boolean: () => createColumnDef<boolean>(\"boolean\"),\n timestamp: () => createColumnDef<Date>(\"timestamp\"),\n};\n\n/**\n * Alternative export for the column builder.\n * Same as `t` but with a more descriptive name.\n */\nexport const columnBuilder = t;\n","/**\n * Build Drizzle tables from schema definitions.\n */\n\nimport {\n pgTable,\n text,\n bigint,\n integer,\n boolean,\n timestamp,\n index,\n type PgTableWithColumns,\n type PgColumnBuilderBase,\n} from \"drizzle-orm/pg-core\";\nimport type { AnyColumnDef, ColumnType, SchemaDefinition } from \"./types\";\n\n// ============================================================\n// Internal Types\n// ============================================================\n\ninterface ColumnDefInternal {\n _type: unknown;\n _columnType: ColumnType;\n _nullable: boolean;\n _indexed: boolean;\n _unique: boolean;\n _primary: boolean;\n _default?: unknown;\n _defaultNow?: boolean;\n _references?: { table: PgTableWithColumns<any>; column: string };\n}\n\n// ============================================================\n// Utilities\n// ============================================================\n\n/**\n * Convert camelCase to snake_case for database column names.\n */\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n// ============================================================\n// Table Builder\n// ============================================================\n\n/**\n * Build a Drizzle pgTable from a schema definition object.\n *\n * @param tableName - The database table name\n * @param schema - Schema definition object with column definitions\n * @returns A Drizzle table with proper types\n *\n * @example\n * ```ts\n * const schema = {\n * id: t.text().primaryKey(),\n * slot: t.bigint().notNull().index(),\n * };\n *\n * const table = buildDrizzleTable(\"my_events\", schema);\n * ```\n */\nexport function buildDrizzleTable<TSchema extends SchemaDefinition>(\n tableName: string,\n schema: TSchema\n): PgTableWithColumns<any> {\n // Build column definitions\n const columns: Record<string, PgColumnBuilderBase> = {};\n const indices: Array<(table: any) => any> = [];\n\n for (const [name, def] of Object.entries(schema)) {\n const internal = def as ColumnDefInternal;\n const snakeName = camelToSnake(name);\n\n // Create the base column\n let col: PgColumnBuilderBase;\n switch (internal._columnType) {\n case \"text\":\n col = text(snakeName);\n break;\n case \"bigint\":\n col = bigint(snakeName, { mode: \"bigint\" });\n break;\n case \"integer\":\n col = integer(snakeName);\n break;\n case \"boolean\":\n col = boolean(snakeName);\n break;\n case \"timestamp\":\n col = timestamp(snakeName, { withTimezone: true });\n break;\n default:\n throw new Error(`Unknown column type: ${internal._columnType}`);\n }\n\n // Apply modifiers\n if (internal._primary) {\n col = (col as any).primaryKey();\n }\n if (internal._unique) {\n col = (col as any).unique();\n }\n if (!internal._nullable) {\n col = (col as any).notNull();\n }\n if (internal._defaultNow && internal._columnType === \"timestamp\") {\n col = (col as any).defaultNow();\n } else if (internal._default !== undefined) {\n col = (col as any).default(internal._default);\n }\n if (internal._references) {\n const refTable = internal._references.table;\n const refColumn = internal._references.column;\n col = (col as any).references(() => refTable[refColumn]);\n }\n\n columns[name] = col;\n\n // Track indices\n if (internal._indexed) {\n indices.push((table: any) =>\n index(`${tableName}_${snakeName}_idx`).on(table[name])\n );\n }\n }\n\n // Create the table\n if (indices.length > 0) {\n return pgTable(tableName, columns, (table) =>\n indices.map((fn) => fn(table))\n );\n }\n return pgTable(tableName, columns);\n}\n","/**\n * Runtime validation for parsed data.\n * Generates Zod schemas from column definitions for validation.\n */\n\nimport { z } from \"zod\";\nimport type { SchemaDefinition, AnyColumnDef } from \"./types\";\n\n/**\n * Generate a Zod schema from column definitions.\n * Used for runtime validation of parse output.\n */\nexport function generateZodSchema<TSchema extends SchemaDefinition>(\n schema: TSchema\n): z.ZodObject<any> {\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const [key, col] of Object.entries(schema)) {\n const colDef = col as AnyColumnDef;\n let zodType: z.ZodTypeAny;\n\n // Map column type to Zod type\n switch (colDef._columnType) {\n case \"text\":\n zodType = z.string();\n break;\n case \"bigint\":\n zodType = z.bigint();\n break;\n case \"integer\":\n zodType = z.number().int();\n break;\n case \"boolean\":\n zodType = z.boolean();\n break;\n case \"timestamp\":\n zodType = z.date();\n break;\n default:\n zodType = z.unknown();\n }\n\n // Handle nullability\n if (colDef._nullable) {\n zodType = zodType.nullable();\n }\n\n shape[key] = zodType;\n }\n\n return z.object(shape);\n}\n\n/**\n * Validate parsed data against schema.\n * Returns validation result with detailed errors.\n */\nexport function validateParsedData<TSchema extends SchemaDefinition>(\n schema: TSchema,\n data: unknown,\n streamName: string\n): { success: true; data: unknown } | { success: false; error: string } {\n const zodSchema = generateZodSchema(schema);\n const result = zodSchema.safeParse(data);\n\n if (result.success) {\n return { success: true, data: result.data };\n }\n\n const errorMessages = result.error.errors\n .map((e) => ` - ${e.path.join(\".\")}: ${e.message}`)\n .join(\"\\n\");\n\n return {\n success: false,\n error: `Stream \"${streamName}\" parse returned invalid data:\\n${errorMessages}`,\n };\n}\n","/**\n * Define an event stream for indexing blockchain events.\n *\n * Event streams index historical, immutable event data from the chain.\n * Each event is stored once and never updated.\n *\n * @example\n * ```ts\n * import { defineEventStream, t } from \"@thru/indexer\";\n * import { create } from \"@bufbuild/protobuf\";\n * import { FilterSchema, type Event } from \"@thru/replay\";\n *\n * export const transfers = defineEventStream({\n * name: \"transfers\",\n *\n * schema: {\n * id: t.text().primaryKey(),\n * slot: t.bigint().notNull().index(),\n * source: t.text().notNull().index(),\n * dest: t.text().notNull().index(),\n * amount: t.bigint().notNull(),\n * },\n *\n * filter: create(FilterSchema, {\n * expression: \"event.program.value == params.address\",\n * params: { address: ... },\n * }),\n *\n * parse: (event: Event) => {\n * if (!event.payload) return null;\n * return {\n * id: event.eventId,\n * slot: event.slot!,\n * source: decodeAddress(event.payload, 0),\n * dest: decodeAddress(event.payload, 32),\n * amount: decodeBigint(event.payload, 64),\n * };\n * },\n *\n * api: { filters: [\"source\", \"dest\"] },\n * });\n *\n * // Export the table for Drizzle migrations\n * export const transfersTable = transfers.table;\n * ```\n */\n\nimport type { Filter } from \"@thru/replay\";\nimport type { SchemaDefinition } from \"../schema/types\";\nimport { buildDrizzleTable } from \"../schema/table\";\nimport type { EventStreamDefinition, EventStream } from \"./types\";\n\n// ============================================================\n// Utilities\n// ============================================================\n\nfunction pascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\n// ============================================================\n// Main Export\n// ============================================================\n\n/**\n * Define an event stream for indexing blockchain events.\n *\n * @param definition - Stream definition with schema, filter, and parse function\n * @returns A compiled event stream ready for use with the indexer\n */\nexport function defineEventStream<TSchema extends SchemaDefinition>(\n definition: EventStreamDefinition<TSchema>\n): EventStream<TSchema> {\n // Validate that either filter or filterFactory is provided\n if (!definition.filter && !definition.filterFactory) {\n throw new Error(`Stream \"${definition.name}\" must provide either filter or filterFactory`);\n }\n\n // Build table name (e.g., \"transfers\" -> \"transfer_events\")\n const tableName = `${definition.name.replace(/s$/, \"\")}_events`;\n\n // Build Drizzle table from schema\n const table = buildDrizzleTable(tableName, definition.schema);\n\n // Lazy filter resolution (cached after first call)\n let cachedFilter: Filter | null = definition.filter ?? null;\n const getFilter = (): Filter => {\n if (!cachedFilter) {\n if (definition.filterFactory) {\n cachedFilter = definition.filterFactory();\n } else {\n throw new Error(`Stream \"${definition.name}\" has no filter configured`);\n }\n }\n return cachedFilter;\n };\n\n return {\n name: definition.name,\n description: definition.description ?? `${pascalCase(definition.name)} events`,\n schema: definition.schema,\n table,\n // Column accessors for Drizzle operators\n c: table as any,\n getFilter,\n parse: definition.parse,\n api: definition.api,\n filterBatch: definition.filterBatch,\n onCommit: definition.onCommit,\n };\n}\n","/**\n * Checkpoint table schema.\n *\n * Users should export this from their Drizzle schema for migrations.\n *\n * @example\n * ```ts\n * // db/schema.ts\n * import { checkpointTable } from \"@thru/indexer\";\n * export { checkpointTable };\n * ```\n */\n\nimport {\n pgTable,\n text,\n bigint,\n timestamp,\n} from \"drizzle-orm/pg-core\";\n\n/**\n * Per-stream checkpoint table.\n * Each stream has its own checkpoint keyed by stream name.\n *\n * This table should be included in your Drizzle migrations.\n */\nexport const checkpointTable = pgTable(\"indexer_checkpoints\", {\n /** Stream name (primary key) */\n streamName: text(\"stream_name\").primaryKey(),\n /** Last indexed slot number */\n lastIndexedSlot: bigint(\"last_indexed_slot\", { mode: \"bigint\" }).notNull(),\n /** Last event ID (for cursor-based resume) */\n lastEventId: text(\"last_event_id\"),\n /** When the checkpoint was last updated */\n updatedAt: timestamp(\"updated_at\", { withTimezone: true })\n .defaultNow()\n .notNull(),\n});\n\n/**\n * Checkpoint data structure.\n */\nexport interface Checkpoint {\n /** Last indexed slot number */\n slot: bigint;\n /** Last event ID (for cursor-based resume) */\n eventId: string | null;\n}\n","/**\n * Checkpoint repository for reading and updating stream checkpoints.\n */\n\nimport { eq } from \"drizzle-orm\";\nimport type { DatabaseClient } from \"../schema/types\";\nimport { checkpointTable, type Checkpoint } from \"./table\";\n\n/**\n * Get the checkpoint for a specific stream.\n * Returns null if no checkpoint exists yet.\n *\n * @param db - Database client\n * @param streamName - Name of the stream\n * @returns Checkpoint or null if not found\n */\nexport async function getCheckpoint(\n db: DatabaseClient,\n streamName: string\n): Promise<Checkpoint | null> {\n const [row] = await db\n .select()\n .from(checkpointTable)\n .where(eq(checkpointTable.streamName, streamName))\n .limit(1);\n\n if (!row) {\n return null;\n }\n\n return {\n slot: row.lastIndexedSlot,\n eventId: row.lastEventId,\n };\n}\n\n/**\n * Update the checkpoint for a specific stream.\n * Uses upsert to handle both insert and update cases.\n *\n * @param db - Database client (can be a transaction)\n * @param streamName - Name of the stream\n * @param slot - Last indexed slot number\n * @param eventId - Last event ID (optional)\n */\nexport async function updateCheckpoint(\n db: DatabaseClient,\n streamName: string,\n slot: bigint,\n eventId: string | null = null\n): Promise<void> {\n await db\n .insert(checkpointTable)\n .values({\n streamName,\n lastIndexedSlot: slot,\n lastEventId: eventId,\n updatedAt: new Date(),\n })\n .onConflictDoUpdate({\n target: checkpointTable.streamName,\n set: {\n lastIndexedSlot: slot,\n lastEventId: eventId,\n updatedAt: new Date(),\n },\n });\n}\n\n/**\n * Delete the checkpoint for a specific stream.\n * Use with caution - this will cause the stream to re-index from the start.\n *\n * @param db - Database client\n * @param streamName - Name of the stream\n */\nexport async function deleteCheckpoint(\n db: DatabaseClient,\n streamName: string\n): Promise<void> {\n await db\n .delete(checkpointTable)\n .where(eq(checkpointTable.streamName, streamName));\n}\n\n/**\n * Get all checkpoints.\n * Useful for monitoring and debugging.\n *\n * @param db - Database client\n * @returns Array of checkpoints with stream names\n */\nexport async function getAllCheckpoints(\n db: DatabaseClient\n): Promise<Array<{ streamName: string; checkpoint: Checkpoint }>> {\n const rows = await db.select().from(checkpointTable);\n\n return rows.map((row) => ({\n streamName: row.streamName,\n checkpoint: {\n slot: row.lastIndexedSlot,\n eventId: row.lastEventId,\n },\n }));\n}\n","/**\n * Checkpoint module exports.\n */\n\nexport { checkpointTable, type Checkpoint } from \"./table\";\nexport {\n getCheckpoint,\n updateCheckpoint,\n deleteCheckpoint,\n getAllCheckpoints,\n} from \"./repository\";\n\nimport { checkpointTable } from \"./table\";\nimport type { EventStream } from \"../streams/types\";\nimport type { AccountStream } from \"../accounts/types\";\nimport type { PgTableWithColumns } from \"drizzle-orm/pg-core\";\n\n/**\n * Get all tables that need to be exported for Drizzle migrations.\n *\n * This helper collects the checkpoint table and all stream tables\n * into a single object for easy export in your schema file.\n *\n * @example\n * ```ts\n * // db/schema.ts\n * import { getSchemaExports } from \"@thru/indexer\";\n * import transfers from \"../streams/transfers\";\n * import tokenAccounts from \"../account-streams/token-accounts\";\n *\n * export const {\n * checkpointTable,\n * transfersTable,\n * tokenAccountsTable,\n * } = getSchemaExports({\n * eventStreams: [transfers],\n * accountStreams: [tokenAccounts],\n * tableNames: {\n * transfers: \"transfersTable\",\n * \"token-accounts\": \"tokenAccountsTable\",\n * },\n * });\n * ```\n */\nexport function getSchemaExports(config: {\n eventStreams?: EventStream<any>[];\n accountStreams?: AccountStream<any>[];\n tableNames?: Record<string, string>;\n}): Record<string, PgTableWithColumns<any>> {\n const { eventStreams = [], accountStreams = [], tableNames = {} } = config;\n\n const exports: Record<string, PgTableWithColumns<any>> = {\n checkpointTable,\n };\n\n for (const stream of eventStreams) {\n const exportName = tableNames[stream.name] ?? `${stream.name}Table`;\n exports[exportName] = stream.table as PgTableWithColumns<any>;\n }\n\n for (const stream of accountStreams) {\n const exportName = tableNames[stream.name] ?? `${stream.name.replace(/-/g, \"\")}Table`;\n exports[exportName] = stream.table as PgTableWithColumns<any>;\n }\n\n return exports;\n}\n","/**\n * Event stream processor.\n *\n * Processes events from @thru/replay and commits them to the database\n * with batching and checkpointing.\n */\n\nimport type { ChainClientFactory } from \"@thru/replay\";\nimport { createEventReplay, createConsoleLogger } from \"@thru/replay\";\nimport type { PgTable } from \"drizzle-orm/pg-core\";\nimport type { DatabaseClient } from \"../schema/types\";\nimport { validateParsedData } from \"../schema/validation\";\nimport { getCheckpoint, updateCheckpoint } from \"../checkpoint\";\nimport type { EventStream } from \"./types\";\nimport type { StreamBatch } from \"../types\";\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface ProcessorOptions {\n /** Factory to create fresh chain clients for reconnection */\n clientFactory: ChainClientFactory;\n /** Database client */\n db: DatabaseClient;\n /** Start slot if no checkpoint exists */\n defaultStartSlot: bigint;\n /** Safety margin for finality (in slots) */\n safetyMargin?: number;\n /** Page size for fetching events */\n pageSize?: number;\n /** Log level */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n /** Validate parse output with Zod (useful for development) */\n validateParse?: boolean;\n}\n\nexport interface ProcessorStats {\n /** Total events processed */\n eventsProcessed: number;\n /** Total batches committed */\n batchesCommitted: number;\n /** Last slot processed */\n lastSlot: bigint | null;\n}\n\n// ============================================================\n// Batcher\n// ============================================================\n\n/**\n * Generic batcher that collects events by slot and flushes on slot change\n * or when thresholds are reached.\n */\nclass StreamBatcher {\n private currentSlot: bigint | null = null;\n private pendingEvents: unknown[] = [];\n private lastFlushTime = Date.now();\n private maxPendingCount = 100;\n private maxPendingMs = 5000;\n\n addEvent(event: unknown, slot: bigint): StreamBatch | null {\n // If slot changed or thresholds reached, flush pending\n if (this.shouldFlush(slot)) {\n const batch = this.flush();\n this.currentSlot = slot;\n this.pendingEvents = [event];\n return batch;\n }\n\n this.currentSlot = slot;\n this.pendingEvents.push(event);\n return null;\n }\n\n private shouldFlush(newSlot: bigint): boolean {\n if (this.pendingEvents.length === 0) return false;\n if (this.currentSlot !== null && newSlot !== this.currentSlot) return true;\n if (this.pendingEvents.length >= this.maxPendingCount) return true;\n if (Date.now() - this.lastFlushTime >= this.maxPendingMs) return true;\n return false;\n }\n\n flush(): StreamBatch | null {\n if (this.pendingEvents.length === 0 || this.currentSlot === null) {\n return null;\n }\n const batch = {\n slot: this.currentSlot,\n events: this.pendingEvents,\n };\n this.pendingEvents = [];\n this.lastFlushTime = Date.now();\n return batch;\n }\n\n getPendingCount(): number {\n return this.pendingEvents.length;\n }\n\n /**\n * Flush if the timeout has elapsed since last flush.\n * Called by background timer to ensure events don't sit in buffer indefinitely.\n */\n flushIfStale(): StreamBatch | null {\n if (\n this.pendingEvents.length > 0 &&\n Date.now() - this.lastFlushTime >= this.maxPendingMs\n ) {\n return this.flush();\n }\n return null;\n }\n}\n\n// ============================================================\n// Processor\n// ============================================================\n\n/**\n * Run an event stream processor.\n *\n * Fetches events from the chain using @thru/replay, parses them,\n * batches by slot, and commits to the database with checkpointing.\n *\n * @param stream - The event stream to process\n * @param options - Processor configuration\n * @param abortSignal - Optional signal to stop processing\n * @returns Processor statistics\n */\nexport async function runEventStreamProcessor(\n stream: EventStream,\n options: ProcessorOptions,\n abortSignal?: AbortSignal\n): Promise<ProcessorStats> {\n const {\n clientFactory,\n db,\n defaultStartSlot,\n safetyMargin = 64,\n pageSize = 512,\n logLevel = \"info\",\n validateParse = false,\n } = options;\n\n const log = (level: string, msg: string) => {\n if (logLevel === \"debug\" || level !== \"debug\") {\n console.log(`[${stream.name}] ${msg}`);\n }\n };\n\n log(\"info\", `Starting stream processor: ${stream.description}`);\n\n // Get checkpoint for this stream\n const checkpoint = await getCheckpoint(db, stream.name);\n const startSlot = checkpoint ? checkpoint.slot + 1n : defaultStartSlot;\n\n log(\n \"info\",\n `Starting from slot ${startSlot}${checkpoint ? \" (resuming)\" : \" (fresh start)\"}`\n );\n\n // Create logger\n const logger =\n logLevel === \"debug\"\n ? createConsoleLogger(stream.name)\n : {\n debug: () => {},\n info: (msg: string) => log(\"info\", msg),\n warn: (msg: string) => log(\"warn\", msg),\n error: (msg: string) => log(\"error\", msg),\n };\n\n // Create replay stream with factory for robust reconnection\n const replay = createEventReplay({\n clientFactory,\n startSlot,\n safetyMargin: BigInt(safetyMargin),\n pageSize,\n filter: stream.getFilter(),\n logger,\n resubscribeOnEnd: true,\n });\n\n const batcher = new StreamBatcher();\n const stats: ProcessorStats = {\n eventsProcessed: 0,\n batchesCommitted: 0,\n lastSlot: null,\n };\n\n let lastLogTime = Date.now();\n let eventsReceivedSinceLastLog = 0;\n\n // Commit a batch to the database\n const commitBatch = async (batch: StreamBatch): Promise<void> => {\n let eventsToCommit = batch.events as Record<string, unknown>[];\n\n // Apply filterBatch hook if defined\n if (stream.filterBatch) {\n try {\n eventsToCommit = (await stream.filterBatch(\n eventsToCommit as any,\n { db }\n )) as any;\n if (eventsToCommit.length === 0) {\n log(\n \"debug\",\n `All ${batch.events.length} events filtered out at slot ${batch.slot}`\n );\n return;\n }\n if (eventsToCommit.length < batch.events.length) {\n log(\n \"debug\",\n `Filtered ${batch.events.length - eventsToCommit.length} of ${batch.events.length} events at slot ${batch.slot}`\n );\n }\n } catch (filterErr) {\n log(\n \"error\",\n `filterBatch hook failed: ${filterErr instanceof Error ? filterErr.message : String(filterErr)}`\n );\n // On filter error, skip the batch\n return;\n }\n }\n\n await db.transaction(async (tx) => {\n // Insert events (skip duplicates)\n await tx\n .insert(stream.table as PgTable)\n .values(eventsToCommit)\n .onConflictDoNothing();\n\n // Update checkpoint\n const lastEvent = eventsToCommit[eventsToCommit.length - 1] as {\n id: string;\n };\n await updateCheckpoint(\n tx as unknown as DatabaseClient,\n stream.name,\n batch.slot,\n lastEvent.id\n );\n });\n\n stats.batchesCommitted++;\n stats.lastSlot = batch.slot;\n\n // Call onCommit hook if defined\n if (stream.onCommit) {\n try {\n await stream.onCommit({ ...batch, events: eventsToCommit }, { db });\n } catch (hookErr) {\n log(\n \"error\",\n `onCommit hook failed: ${hookErr instanceof Error ? hookErr.message : String(hookErr)}`\n );\n // Don't rethrow - hooks should not block indexing\n }\n }\n };\n\n // Background timer to flush pending events that exceed the timeout\n const flushInterval = setInterval(async () => {\n const batch = batcher.flushIfStale();\n if (batch) {\n try {\n await commitBatch(batch);\n log(\n \"debug\",\n `Timeout flush: ${batch.events.length} event(s) at slot ${batch.slot}`\n );\n } catch (err) {\n log(\n \"error\",\n `Timeout flush failed: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n }, 1000);\n\n try {\n for await (const event of replay) {\n if (abortSignal?.aborted) {\n log(\"info\", \"Abort signal received, stopping...\");\n break;\n }\n\n eventsReceivedSinceLastLog++;\n\n // Parse the event\n const parsed = stream.parse(event);\n if (!parsed) continue;\n\n // Validate parse output if enabled\n if (validateParse) {\n const validation = validateParsedData(stream.schema, parsed, stream.name);\n if (!validation.success) {\n log(\"error\", validation.error);\n continue; // Skip invalid events\n }\n }\n\n stats.eventsProcessed++;\n\n // Add to batcher\n const batch = batcher.addEvent(parsed, event.slot!);\n if (batch) {\n await commitBatch(batch);\n log(\n \"info\",\n `Committed ${batch.events.length} event(s) at slot ${batch.slot} (total: ${stats.eventsProcessed})`\n );\n }\n\n // Heartbeat logging\n const now = Date.now();\n if (now - lastLogTime >= 30000) {\n log(\n \"info\",\n `Heartbeat: ${eventsReceivedSinceLastLog} events received, ${batcher.getPendingCount()} pending`\n );\n eventsReceivedSinceLastLog = 0;\n lastLogTime = now;\n }\n }\n\n // Flush any remaining events\n const finalBatch = batcher.flush();\n if (finalBatch) {\n await commitBatch(finalBatch);\n log(\n \"info\",\n `Final flush: ${finalBatch.events.length} event(s) at slot ${finalBatch.slot}`\n );\n }\n } catch (err) {\n log(\n \"error\",\n `Stream error: ${err instanceof Error ? err.message : String(err)}`\n );\n throw err;\n } finally {\n clearInterval(flushInterval);\n }\n\n log(\n \"info\",\n `Stream stopped. Processed ${stats.eventsProcessed} events in ${stats.batchesCommitted} batches.`\n );\n return stats;\n}\n","/**\n * Define an account stream for indexing on-chain account state.\n *\n * Account streams track current state of on-chain accounts.\n * Unlike event streams (historical log), account streams are mutable -\n * rows are updated when account state changes.\n *\n * @example\n * ```ts\n * import { defineAccountStream, t } from \"@thru/indexer\";\n * import { decodeAddress } from \"@thru/helpers\";\n * import type { AccountState } from \"@thru/replay\";\n *\n * export const tokenAccounts = defineAccountStream({\n * name: \"token-accounts\",\n *\n * ownerProgram: decodeAddress(TOKEN_PROGRAM_PUBKEY),\n * expectedSize: 73, // TokenAccount size in bytes\n *\n * schema: {\n * address: t.text().primaryKey(),\n * mint: t.text().notNull().index(),\n * owner: t.text().notNull().index(),\n * amount: t.bigint().notNull(),\n * isFrozen: t.boolean().notNull(),\n * slot: t.bigint().notNull(),\n * seq: t.bigint().notNull(),\n * updatedAt: t.timestamp().notNull().defaultNow(),\n * },\n *\n * parse: (account: AccountState) => {\n * if (account.data.length !== 73) return null;\n * return {\n * address: encodeAddress(account.address),\n * mint: parseAddress(account.data, 0),\n * owner: parseAddress(account.data, 32),\n * amount: parseBigint(account.data, 64),\n * isFrozen: account.data[72] !== 0,\n * slot: account.slot,\n * seq: account.seq,\n * updatedAt: new Date(),\n * };\n * },\n *\n * api: { filters: [\"mint\", \"owner\"], idField: \"address\" },\n * });\n *\n * // Export the table for Drizzle migrations\n * export const tokenAccountsTable = tokenAccounts.table;\n * ```\n */\n\nimport type { SchemaDefinition } from \"../schema/types\";\nimport { buildDrizzleTable } from \"../schema/table\";\nimport type { AccountStreamDefinition, AccountStream } from \"./types\";\n\n// ============================================================\n// Utilities\n// ============================================================\n\nfunction pascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\n// ============================================================\n// Main Export\n// ============================================================\n\n/**\n * Define an account stream for indexing on-chain account state.\n *\n * @param definition - Stream definition with schema, ownerProgram, and parse function\n * @returns A compiled account stream ready for use with the indexer\n */\nexport function defineAccountStream<TSchema extends SchemaDefinition>(\n definition: AccountStreamDefinition<TSchema>\n): AccountStream<TSchema> {\n // Validate that either ownerProgram or ownerProgramFactory is provided\n if (!definition.ownerProgram && !definition.ownerProgramFactory) {\n throw new Error(`Stream \"${definition.name}\" must provide either ownerProgram or ownerProgramFactory`);\n }\n\n // Build table name (e.g., \"token-accounts\" -> \"token_accounts\")\n const tableName = definition.name.replace(/-/g, \"_\");\n\n // Build Drizzle table from schema\n const table = buildDrizzleTable(tableName, definition.schema);\n\n // Lazy ownerProgram resolution (cached after first call)\n let cachedOwnerProgram: Uint8Array | null = definition.ownerProgram ?? null;\n const getOwnerProgram = (): Uint8Array => {\n if (!cachedOwnerProgram) {\n if (definition.ownerProgramFactory) {\n cachedOwnerProgram = definition.ownerProgramFactory();\n } else {\n throw new Error(`Stream \"${definition.name}\" has no ownerProgram configured`);\n }\n }\n return cachedOwnerProgram;\n };\n\n return {\n name: definition.name,\n description: definition.description ?? `${pascalCase(definition.name)} accounts`,\n schema: definition.schema,\n getOwnerProgram,\n expectedSize: definition.expectedSize,\n dataSizes: definition.dataSizes,\n table,\n // Column accessors for Drizzle operators\n c: table as any,\n parse: definition.parse,\n api: definition.api,\n };\n}\n","/**\n * Account stream processor.\n *\n * Processes account state from @thru/replay and commits to the database\n * with slot-aware upserts and checkpointing.\n */\n\nimport { sql } from \"drizzle-orm\";\nimport type { ChainClientFactory } from \"@thru/replay\";\nimport { createAccountsByOwnerReplay, AccountView } from \"@thru/replay\";\nimport type { DatabaseClient } from \"../schema/types\";\nimport { validateParsedData } from \"../schema/validation\";\nimport { getCheckpoint, updateCheckpoint } from \"../checkpoint\";\nimport type { AccountStream } from \"./types\";\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface AccountProcessorOptions {\n /** Factory to create fresh chain clients for reconnection */\n clientFactory: ChainClientFactory;\n /** Database client */\n db: DatabaseClient;\n /** Log level */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n /** Validate parse output with Zod (useful for development) */\n validateParse?: boolean;\n}\n\nexport interface AccountProcessorStats {\n /** Total accounts processed */\n accountsProcessed: number;\n /** Total accounts inserted/updated */\n accountsUpdated: number;\n /** Total accounts deleted */\n accountsDeleted: number;\n}\n\n// ============================================================\n// Utilities\n// ============================================================\n\nfunction shouldLog(level: string, minLevel: string): boolean {\n const levels = [\"debug\", \"info\", \"warn\", \"error\"];\n return levels.indexOf(level) >= levels.indexOf(minLevel);\n}\n\n// ============================================================\n// Processor\n// ============================================================\n\n/**\n * Run an account stream processor.\n *\n * Backfills all accounts via ListAccounts, then streams live updates.\n * Supports resumable indexing via checkpoint persistence.\n *\n * @param stream - The account stream to process\n * @param options - Processor configuration\n * @param abortSignal - Optional signal to stop processing\n * @returns Processor statistics\n */\nexport async function runAccountStreamProcessor(\n stream: AccountStream,\n options: AccountProcessorOptions,\n abortSignal?: AbortSignal\n): Promise<AccountProcessorStats> {\n const { clientFactory, db, logLevel = \"info\", validateParse = false } = options;\n const checkpointName = `account:${stream.name}`;\n\n const log = (\n level: string,\n msg: string,\n meta?: Record<string, unknown>\n ) => {\n if (shouldLog(level, logLevel)) {\n console.log(\n `[account-stream:${stream.name}] ${msg}`,\n meta ?? \"\"\n );\n }\n };\n\n const stats: AccountProcessorStats = {\n accountsProcessed: 0,\n accountsUpdated: 0,\n accountsDeleted: 0,\n };\n\n // Load checkpoint for resumable backfill\n const checkpoint = await getCheckpoint(db, checkpointName);\n const minUpdatedSlot = checkpoint?.slot ?? undefined;\n if (minUpdatedSlot) {\n log(\"info\", `Resuming from checkpoint: slot ${minUpdatedSlot}`);\n }\n\n log(\"info\", `Starting account stream: ${stream.description}`);\n if (stream.expectedSize) {\n log(\"info\", `Expected data size: ${stream.expectedSize} bytes`);\n }\n\n // Track highest slot seen for checkpoint persistence\n let lastProcessedSlot = minUpdatedSlot ?? 0n;\n\n try {\n // Use createAccountsByOwnerReplay for hybrid backfill + streaming\n const replay = createAccountsByOwnerReplay({\n clientFactory,\n owner: stream.getOwnerProgram(),\n view: AccountView.FULL,\n dataSizes: stream.dataSizes ?? (stream.expectedSize ? [stream.expectedSize] : undefined),\n minUpdatedSlot,\n onBackfillComplete: (highestSlot) => {\n log(\n \"info\",\n `Backfill complete. Highest slot: ${highestSlot}, accounts processed: ${stats.accountsProcessed}`\n );\n lastProcessedSlot = highestSlot;\n },\n });\n\n for await (const event of replay) {\n if (abortSignal?.aborted) {\n log(\"info\", \"Abort signal received, stopping\");\n break;\n }\n\n if (event.type === \"account\") {\n const account = event.account;\n stats.accountsProcessed++;\n\n // Log first few accounts for debugging\n if (stats.accountsProcessed <= 3) {\n log(\n \"info\",\n `Account ${stats.accountsProcessed}: ${account.addressHex}, slot=${account.slot}, dataLen=${account.data.length}`\n );\n }\n\n // Parse using stream's parser\n const parsed = stream.parse(account);\n if (!parsed) {\n log(\n \"debug\",\n `Skipped account ${account.addressHex} - parser returned null (dataLen=${account.data.length})`\n );\n continue;\n }\n\n // Validate parse output if enabled\n if (validateParse) {\n const validation = validateParsedData(stream.schema, parsed, stream.name);\n if (!validation.success) {\n log(\"error\", validation.error);\n continue; // Skip invalid accounts\n }\n }\n\n if (account.isDelete) {\n log(\"debug\", `Account deleted: ${account.addressHex}`);\n stats.accountsDeleted++;\n // Optionally delete from DB - for now we skip\n continue;\n }\n\n // Slot-aware upsert: only update if incoming slot >= existing slot\n const table = stream.table as any;\n const idField = stream.api?.idField ?? \"address\";\n\n try {\n await db\n .insert(stream.table)\n .values(parsed)\n .onConflictDoUpdate({\n target: table[idField],\n set: parsed,\n where: sql`${table.slot} <= ${(parsed as any).slot}`,\n });\n\n stats.accountsUpdated++;\n\n if (stats.accountsUpdated <= 3) {\n log(\n \"info\",\n `Successfully inserted account ${stats.accountsUpdated}`\n );\n }\n } catch (err) {\n log(\n \"error\",\n `Failed to upsert account ${account.addressHex}: ${err}`\n );\n }\n\n // Track highest slot for checkpoint\n if (account.slot > lastProcessedSlot) {\n lastProcessedSlot = account.slot;\n }\n\n // Progress logging\n if (stats.accountsProcessed % 100 === 0) {\n log(\n \"info\",\n `Processed ${stats.accountsProcessed} accounts, updated ${stats.accountsUpdated}`\n );\n }\n } else if (event.type === \"blockFinished\") {\n // Persist checkpoint at block boundaries\n const slot = event.block.slot;\n if (slot > lastProcessedSlot) {\n lastProcessedSlot = slot;\n }\n await updateCheckpoint(db, checkpointName, lastProcessedSlot, null);\n log(\"debug\", `Block finished: slot ${slot}, checkpoint saved`);\n }\n }\n\n // Final checkpoint save\n if (lastProcessedSlot > 0n) {\n await updateCheckpoint(db, checkpointName, lastProcessedSlot, null);\n log(\"info\", `Final checkpoint saved: slot ${lastProcessedSlot}`);\n }\n } catch (err) {\n if (abortSignal?.aborted) {\n log(\"info\", \"Stream aborted\");\n } else {\n log(\n \"error\",\n `Stream error: ${err instanceof Error ? err.message : String(err)}`\n );\n throw err;\n }\n }\n\n log(\n \"info\",\n `Finished. Processed: ${stats.accountsProcessed}, Updated: ${stats.accountsUpdated}, Deleted: ${stats.accountsDeleted}`\n );\n\n return stats;\n}\n","/**\n * Pagination utilities for API routes.\n */\n\nimport { z } from \"@hono/zod-openapi\";\n\n// ============================================================\n// Schemas\n// ============================================================\n\n/**\n * Query parameters for paginated list endpoints.\n */\nexport const paginationQuerySchema = z.object({\n limit: z.coerce.number().int().min(1).max(100).default(20).openapi({\n description: \"Number of results to return (1-100)\",\n example: 20,\n }),\n offset: z.coerce.number().int().min(0).default(0).openapi({\n description: \"Number of results to skip\",\n example: 0,\n }),\n cursor: z.string().optional().openapi({\n description: \"Cursor for pagination (format: slot:id)\",\n example: \"3181195:abc123\",\n }),\n});\n\nexport type PaginationQuery = z.infer<typeof paginationQuerySchema>;\n\n/**\n * Pagination metadata in responses.\n */\nexport const paginationResponseSchema = z.object({\n limit: z.number().openapi({ example: 20 }),\n offset: z.number().openapi({ example: 0 }),\n hasMore: z.boolean().openapi({ example: true }),\n nextCursor: z.string().nullable().openapi({ example: \"3181195:abc123\" }),\n});\n\nexport type PaginationResponse = z.infer<typeof paginationResponseSchema>;\n\n// ============================================================\n// Response Wrappers\n// ============================================================\n\n/**\n * Wrap a schema in a data response.\n */\nexport function dataResponse<T extends z.ZodTypeAny>(schema: T) {\n return z.object({ data: schema });\n}\n\n/**\n * Wrap a schema in a list response with pagination.\n */\nexport function listResponse<T extends z.ZodTypeAny>(schema: T) {\n return z.object({\n data: z.array(schema),\n pagination: paginationResponseSchema,\n });\n}\n\n/**\n * Standard error response schema.\n */\nexport const errorSchema = z\n .object({\n error: z.string().openapi({ example: \"Not found\" }),\n code: z.string().optional().openapi({ example: \"NOT_FOUND\" }),\n })\n .openapi(\"Error\");\n\nexport type ErrorResponse = z.infer<typeof errorSchema>;\n\n// ============================================================\n// Pagination Helpers\n// ============================================================\n\nexport interface PaginationResult<T> {\n data: T[];\n pagination: PaginationResponse;\n}\n\n/**\n * Process raw results into paginated response.\n * Expects `limit + 1` rows to determine hasMore.\n *\n * @param rows - Query results (should have limit + 1 rows)\n * @param query - The pagination query parameters\n * @param getCursor - Optional function to get cursor from last item\n * @returns Paginated result with data and pagination metadata\n */\nexport function paginate<T>(\n rows: T[],\n query: PaginationQuery,\n getCursor?: (item: T) => string | null\n): PaginationResult<T> {\n const hasMore = rows.length > query.limit;\n const data = hasMore ? rows.slice(0, -1) : rows;\n const lastItem = data[data.length - 1];\n\n let nextCursor: string | null = null;\n if (hasMore && lastItem) {\n if (getCursor) {\n nextCursor = getCursor(lastItem);\n } else {\n // Default: try to build cursor from slot:id if available\n const item = lastItem as Record<string, unknown>;\n if (item.slot !== undefined && item.id !== undefined) {\n nextCursor = `${item.slot}:${item.id}`;\n }\n }\n }\n\n return {\n data,\n pagination: {\n limit: query.limit,\n offset: query.offset,\n hasMore,\n nextCursor,\n },\n };\n}\n\n/**\n * Parse a cursor string into slot and id components.\n *\n * @param cursor - Cursor string in format \"slot:id\"\n * @returns Parsed cursor or null if invalid\n */\nexport function parseCursor(\n cursor: string\n): { slot: bigint; id: string } | null {\n const colonIndex = cursor.indexOf(\":\");\n if (colonIndex === -1) return null;\n\n try {\n const slot = BigInt(cursor.slice(0, colonIndex));\n const id = cursor.slice(colonIndex + 1);\n return { slot, id };\n } catch {\n return null;\n }\n}\n","/**\n * Schema generation utilities.\n *\n * Generates Zod schemas and serializers from Drizzle tables.\n */\n\nimport { z } from \"@hono/zod-openapi\";\nimport { createSelectSchema, createInsertSchema } from \"drizzle-zod\";\nimport { getTableColumns } from \"drizzle-orm\";\nimport type { PgTableWithColumns } from \"drizzle-orm/pg-core\";\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface GeneratedSchemas {\n /** Row schema (database types) */\n row: z.ZodTypeAny;\n /** Insert schema (validation for inserts) */\n insert: z.ZodTypeAny;\n /** API output schema (serialized for JSON) */\n api: z.ZodTypeAny;\n /** Serialize a database row for API output */\n serialize: (row: Record<string, unknown>) => Record<string, unknown>;\n}\n\n// ============================================================\n// Utilities\n// ============================================================\n\nfunction pascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\n// ============================================================\n// Schema Generation\n// ============================================================\n\n/**\n * Generate Zod schemas from a Drizzle table.\n *\n * Handles bigint → string and Date → ISO string serialization\n * for JSON-safe API responses.\n *\n * @param table - Drizzle table\n * @param name - Schema name for OpenAPI\n * @param suffix - Suffix for OpenAPI schema name (e.g., \"Event\", \"Account\")\n * @returns Generated schemas and serializer\n */\nexport function generateSchemas(\n table: PgTableWithColumns<any>,\n name: string,\n suffix: string = \"\"\n): GeneratedSchemas {\n const rowSchema = createSelectSchema(table);\n const insertSchema = createInsertSchema(table);\n\n // Build API schema with serialization transforms\n const apiFields: Record<string, z.ZodTypeAny> = {};\n const columns = getTableColumns(table);\n\n for (const [colName, col] of Object.entries(columns)) {\n const dataType = (col as any).dataType;\n const notNull = (col as any).notNull;\n\n let fieldSchema: z.ZodTypeAny;\n switch (dataType) {\n case \"bigint\":\n // Serialize bigint as string for JSON safety\n fieldSchema = z.string().openapi({ description: `${colName} (bigint)` });\n break;\n case \"date\":\n // Serialize Date as ISO string\n fieldSchema = z.string().openapi({ description: `${colName} (ISO timestamp)` });\n break;\n case \"string\":\n fieldSchema = z.string();\n break;\n case \"number\":\n fieldSchema = z.number();\n break;\n case \"boolean\":\n fieldSchema = z.boolean();\n break;\n default:\n fieldSchema = z.any();\n }\n\n if (!notNull) {\n fieldSchema = fieldSchema.nullable();\n }\n\n apiFields[colName] = fieldSchema;\n }\n\n const schemaName = suffix ? `${pascalCase(name)}${suffix}` : pascalCase(name);\n const apiSchema = z.object(apiFields).openapi(schemaName);\n\n // Build serializer function\n const serialize = (row: Record<string, unknown>): Record<string, unknown> => {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n if (typeof value === \"bigint\") {\n result[key] = value.toString();\n } else if (value instanceof Date) {\n result[key] = value.toISOString();\n } else {\n result[key] = value;\n }\n }\n return result;\n };\n\n return {\n row: rowSchema as unknown as z.ZodTypeAny,\n insert: insertSchema as unknown as z.ZodTypeAny,\n api: apiSchema as z.ZodTypeAny,\n serialize,\n };\n}\n","/**\n * Route generation for event and account streams.\n *\n * Auto-generates list and get routes with filtering and pagination.\n */\n\nimport { OpenAPIHono, createRoute, z } from \"@hono/zod-openapi\";\nimport { and, desc, eq, gte, lte, sql, type SQL } from \"drizzle-orm\";\nimport type { PgTableWithColumns } from \"drizzle-orm/pg-core\";\nimport type { DatabaseClient } from \"../schema/types\";\nimport type { EventStream } from \"../streams/types\";\nimport type { AccountStream } from \"../accounts/types\";\nimport {\n paginationQuerySchema,\n dataResponse,\n listResponse,\n errorSchema,\n paginate,\n parseCursor,\n type PaginationQuery,\n} from \"./pagination\";\nimport { generateSchemas, type GeneratedSchemas } from \"./schemas\";\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface MountRoutesOptions {\n /** Database client */\n db: DatabaseClient;\n /** Event streams to create routes for */\n eventStreams?: EventStream[];\n /** Account streams to create routes for */\n accountStreams?: AccountStream[];\n /** Path prefix (default: \"/api/v1\") */\n pathPrefix?: string;\n}\n\n// ============================================================\n// Utilities\n// ============================================================\n\nfunction pascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\n// ============================================================\n// Route Builders\n// ============================================================\n\ninterface BuildRoutesConfig {\n db: DatabaseClient;\n name: string;\n table: PgTableWithColumns<any>;\n schemas: GeneratedSchemas;\n filters: string[];\n idField: string;\n resourceType: \"event\" | \"account\";\n includeSlotFilters: boolean;\n sortField: string;\n secondarySortField?: string;\n}\n\nfunction buildRoutes(config: BuildRoutesConfig): OpenAPIHono {\n const {\n db,\n name,\n table,\n schemas,\n filters,\n idField,\n resourceType,\n includeSlotFilters,\n sortField,\n secondarySortField,\n } = config;\n\n const router = new OpenAPIHono();\n const tag = pascalCase(name);\n\n // Build filter query params schema\n const filterFields: Record<string, z.ZodTypeAny> = {};\n for (const field of filters) {\n filterFields[field] = z.string().optional().openapi({\n description: `Filter by ${field}`,\n });\n }\n\n // Add slot range filters for event streams\n if (includeSlotFilters) {\n filterFields.fromSlot = z.string().optional().openapi({\n description: \"Minimum slot number\",\n });\n filterFields.toSlot = z.string().optional().openapi({\n description: \"Maximum slot number\",\n });\n }\n\n const listQuerySchema = paginationQuerySchema.extend(filterFields);\n\n // GET / - List route\n const listRoute = createRoute({\n method: \"get\",\n path: \"/\",\n tags: [tag],\n summary: `List ${name} ${resourceType}s`,\n description: `Returns a paginated list of ${name} ${resourceType}s with optional filtering.`,\n request: { query: listQuerySchema },\n responses: {\n 200: {\n description: `List of ${name} ${resourceType}s`,\n content: { \"application/json\": { schema: listResponse(schemas.api) } },\n },\n },\n });\n\n router.openapi(listRoute, async (c) => {\n const query = c.req.valid(\"query\") as PaginationQuery &\n Record<string, string | undefined>;\n const conditions: SQL[] = [];\n\n // Apply custom filters\n for (const field of filters) {\n const value = query[field];\n if (value !== undefined && value !== \"\") {\n conditions.push(eq((table as any)[field], value));\n }\n }\n\n // Apply slot range filters\n if (includeSlotFilters) {\n if (query.fromSlot) {\n conditions.push(gte((table as any).slot, BigInt(query.fromSlot)));\n }\n if (query.toSlot) {\n conditions.push(lte((table as any).slot, BigInt(query.toSlot)));\n }\n }\n\n // Apply cursor (for event streams with slot + id)\n if (query.cursor && secondarySortField) {\n const parsed = parseCursor(query.cursor);\n if (parsed) {\n conditions.push(\n sql`(${(table as any).slot} < ${parsed.slot} OR (${(table as any).slot} = ${parsed.slot} AND ${(table as any)[secondarySortField]} < ${parsed.id}))`\n );\n }\n }\n\n // Build order by clause\n const orderBy = secondarySortField\n ? [desc((table as any)[sortField]), desc((table as any)[secondarySortField])]\n : [desc((table as any)[sortField])];\n\n const rows = await db\n .select()\n .from(table)\n .where(conditions.length > 0 ? and(...conditions) : undefined)\n .orderBy(...orderBy)\n .limit(query.limit + 1)\n .offset(query.cursor ? 0 : query.offset);\n\n const result = paginate(rows, query);\n\n return c.json({\n data: result.data.map((row) =>\n schemas.serialize(row as Record<string, unknown>)\n ),\n pagination: result.pagination,\n });\n });\n\n // GET /:id - Get by ID route\n const getRoute = createRoute({\n method: \"get\",\n path: `/{${idField}}`,\n tags: [tag],\n summary: `Get ${name} ${resourceType} by ${idField}`,\n description: `Returns a single ${name} ${resourceType} by its ${idField}.`,\n request: {\n params: z.object({\n [idField]: z\n .string()\n .openapi({ description: `${pascalCase(resourceType)} ${idField}` }),\n }),\n },\n responses: {\n 200: {\n description: `${pascalCase(name)} ${resourceType} found`,\n content: { \"application/json\": { schema: dataResponse(schemas.api) } },\n },\n 404: {\n description: `${pascalCase(resourceType)} not found`,\n content: { \"application/json\": { schema: errorSchema } },\n },\n },\n });\n\n // @ts-expect-error - OpenAPI handler with multiple response types\n router.openapi(getRoute, async (c) => {\n const id = c.req.param(idField);\n\n const [row] = await db\n .select()\n .from(table)\n .where(eq((table as any)[idField], id))\n .limit(1);\n\n if (!row) {\n return c.json({ error: \"Not found\" }, 404);\n }\n\n return c.json({\n data: schemas.serialize(row as Record<string, unknown>),\n });\n });\n\n return router;\n}\n\n// ============================================================\n// Mount Routes\n// ============================================================\n\n/**\n * Mount auto-generated routes for event and account streams.\n *\n * @param app - Hono app to mount routes on\n * @param options - Configuration options\n *\n * @example\n * ```ts\n * import { OpenAPIHono } from \"@hono/zod-openapi\";\n * import { mountStreamRoutes } from \"@thru/indexer\";\n * import { transfers } from \"./streams/transfers\";\n * import { tokenAccounts } from \"./account-streams/token-accounts\";\n *\n * const app = new OpenAPIHono();\n *\n * mountStreamRoutes(app, {\n * db,\n * eventStreams: [transfers],\n * accountStreams: [tokenAccounts],\n * });\n *\n * // Routes generated:\n * // GET /api/v1/transfers\n * // GET /api/v1/transfers/:id\n * // GET /api/v1/token-accounts\n * // GET /api/v1/token-accounts/:address\n * ```\n */\nexport function mountStreamRoutes(\n app: OpenAPIHono,\n options: MountRoutesOptions\n): void {\n const {\n db,\n eventStreams = [],\n accountStreams = [],\n pathPrefix = \"/api/v1\",\n } = options;\n\n // Mount event stream routes\n for (const stream of eventStreams) {\n if (stream.api?.enabled === false) continue;\n\n const schemas = generateSchemas(stream.table, stream.name, \"Event\");\n const filters = (stream.api?.filters ?? []) as string[];\n const idField = (stream.api?.idField ?? \"id\") as string;\n\n const router = buildRoutes({\n db,\n name: stream.name,\n table: stream.table,\n schemas,\n filters,\n idField,\n resourceType: \"event\",\n includeSlotFilters: true,\n sortField: \"slot\",\n secondarySortField: \"id\",\n });\n\n app.route(`${pathPrefix}/${stream.name}`, router);\n }\n\n // Mount account stream routes\n for (const stream of accountStreams) {\n if (stream.api?.enabled === false) continue;\n\n const schemas = generateSchemas(stream.table, stream.name, \"Account\");\n const filters = (stream.api?.filters ?? []) as string[];\n const idField = (stream.api?.idField ?? \"address\") as string;\n\n const router = buildRoutes({\n db,\n name: stream.name,\n table: stream.table,\n schemas,\n filters,\n idField,\n resourceType: \"account\",\n includeSlotFilters: false,\n sortField: \"updatedAt\",\n secondarySortField: undefined,\n });\n\n app.route(`${pathPrefix}/${stream.name}`, router);\n }\n}\n","/**\n * Indexer runtime class.\n *\n * Orchestrates running multiple event and account streams concurrently\n * with graceful shutdown support.\n *\n * @example\n * ```ts\n * import { Indexer } from \"@thru/indexer\";\n * import { ChainClient } from \"@thru/replay\";\n * import { transfers } from \"./streams/transfers\";\n * import { tokenAccounts } from \"./account-streams/token-accounts\";\n *\n * const indexer = new Indexer({\n * db,\n * clientFactory: () => new ChainClient({ baseUrl: RPC_URL }),\n * eventStreams: [transfers],\n * accountStreams: [tokenAccounts],\n * defaultStartSlot: 0n,\n * safetyMargin: 64,\n * });\n *\n * // Handle graceful shutdown\n * process.on(\"SIGINT\", () => indexer.stop());\n * process.on(\"SIGTERM\", () => indexer.stop());\n *\n * // Start indexing\n * await indexer.start();\n * ```\n */\n\nimport { sql } from \"drizzle-orm\";\nimport type { IndexerConfig } from \"./config\";\nimport { runEventStreamProcessor, type ProcessorStats } from \"../streams/processor\";\nimport { runAccountStreamProcessor, type AccountProcessorStats } from \"../accounts/processor\";\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface IndexerResult {\n /** Results from event stream processors */\n eventStreams: Array<{\n name: string;\n status: \"fulfilled\" | \"rejected\";\n result?: ProcessorStats;\n error?: Error;\n }>;\n /** Results from account stream processors */\n accountStreams: Array<{\n name: string;\n status: \"fulfilled\" | \"rejected\";\n result?: AccountProcessorStats;\n error?: Error;\n }>;\n}\n\n// ============================================================\n// Indexer Class\n// ============================================================\n\n/**\n * Indexer runtime that orchestrates event and account streams.\n */\nexport class Indexer {\n private config: IndexerConfig;\n private abortController: AbortController | null = null;\n private running = false;\n private shutdownRequested = false;\n\n constructor(config: IndexerConfig) {\n this.config = {\n defaultStartSlot: 0n,\n safetyMargin: 64,\n pageSize: 512,\n logLevel: \"info\",\n ...config,\n };\n }\n\n /**\n * Check if the checkpoint table exists in the database.\n * Logs a warning if it doesn't exist (user may have forgotten to export it in schema).\n */\n private async checkCheckpointTable(): Promise<void> {\n try {\n // Try to query the checkpoint table\n await this.config.db.execute(\n sql`SELECT 1 FROM indexer_checkpoints LIMIT 1`\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n // Check if error is about missing table\n if (message.includes(\"does not exist\") || message.includes(\"relation\")) {\n console.warn(\n `[indexer] WARNING: Checkpoint table \"indexer_checkpoints\" not found.\n[indexer] Make sure to export checkpointTable from your Drizzle schema:\n\n // db/schema.ts\n export { checkpointTable } from \"@thru/indexer\";\n\n[indexer] Then run: pnpm drizzle-kit push (or generate + migrate)\n`\n );\n }\n // Re-throw so startup fails\n throw err;\n }\n }\n\n /**\n * Start the indexer.\n *\n * Runs all configured event and account streams concurrently.\n * Returns when all streams complete or when stop() is called.\n *\n * @returns Results from all stream processors\n */\n async start(): Promise<IndexerResult> {\n if (this.running) {\n throw new Error(\"Indexer is already running\");\n }\n\n // Check that checkpoint table exists before starting\n await this.checkCheckpointTable();\n\n this.running = true;\n this.shutdownRequested = false;\n this.abortController = new AbortController();\n\n const {\n db,\n clientFactory,\n eventStreams = [],\n accountStreams = [],\n defaultStartSlot,\n safetyMargin,\n pageSize,\n logLevel,\n validateParse,\n } = this.config;\n\n console.log(\"[indexer] Starting indexer...\");\n console.log(\n `[indexer] Running ${eventStreams.length} event stream(s): ${eventStreams.map((s) => s.name).join(\", \") || \"none\"}`\n );\n console.log(\n `[indexer] Running ${accountStreams.length} account stream(s): ${accountStreams.map((s) => s.name).join(\", \") || \"none\"}`\n );\n\n try {\n // Processor options\n const eventProcessorOptions = {\n clientFactory,\n db,\n defaultStartSlot: defaultStartSlot!,\n safetyMargin,\n pageSize,\n logLevel,\n validateParse,\n };\n\n const accountProcessorOptions = {\n clientFactory,\n db,\n logLevel,\n validateParse,\n };\n\n // Start all processors concurrently\n const eventStreamPromises = eventStreams.map((stream) =>\n runEventStreamProcessor(\n stream,\n eventProcessorOptions,\n this.abortController!.signal\n )\n );\n\n const accountStreamPromises = accountStreams.map((stream) =>\n runAccountStreamProcessor(\n stream,\n accountProcessorOptions,\n this.abortController!.signal\n )\n );\n\n const [eventResults, accountResults] = await Promise.all([\n Promise.allSettled(eventStreamPromises),\n Promise.allSettled(accountStreamPromises),\n ]);\n\n // Build result\n const result: IndexerResult = {\n eventStreams: eventStreams.map((stream, i) => {\n const r = eventResults[i];\n if (r.status === \"fulfilled\") {\n console.log(\n `[indexer] Event stream \"${stream.name}\" completed: ${r.value.eventsProcessed} events in ${r.value.batchesCommitted} batches`\n );\n return {\n name: stream.name,\n status: \"fulfilled\" as const,\n result: r.value,\n };\n } else {\n console.error(\n `[indexer] Event stream \"${stream.name}\" failed:`,\n r.reason\n );\n return {\n name: stream.name,\n status: \"rejected\" as const,\n error: r.reason,\n };\n }\n }),\n accountStreams: accountStreams.map((stream, i) => {\n const r = accountResults[i];\n if (r.status === \"fulfilled\") {\n console.log(\n `[indexer] Account stream \"${stream.name}\" completed: ${r.value.accountsUpdated} accounts updated, ${r.value.accountsDeleted} deleted`\n );\n return {\n name: stream.name,\n status: \"fulfilled\" as const,\n result: r.value,\n };\n } else {\n console.error(\n `[indexer] Account stream \"${stream.name}\" failed:`,\n r.reason\n );\n return {\n name: stream.name,\n status: \"rejected\" as const,\n error: r.reason,\n };\n }\n }),\n };\n\n console.log(\"[indexer] All streams stopped.\");\n return result;\n } finally {\n this.running = false;\n this.abortController = null;\n }\n }\n\n /**\n * Stop the indexer gracefully.\n *\n * Signals all streams to finish their current batch and stop.\n * The start() promise will resolve once all streams have stopped.\n */\n stop(): void {\n if (!this.running || !this.abortController) {\n console.log(\"[indexer] Not running\");\n return;\n }\n\n if (this.shutdownRequested) {\n console.log(\"[indexer] Force shutdown...\");\n process.exit(1);\n }\n\n console.log(\"[indexer] Shutdown requested, finishing current batches...\");\n this.shutdownRequested = true;\n this.abortController.abort();\n }\n\n /**\n * Check if the indexer is currently running.\n */\n isRunning(): boolean {\n return this.running;\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thru/indexer",
|
|
3
|
+
"version": "0.1.38",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@hono/zod-openapi": "0.18.4",
|
|
21
|
+
"drizzle-orm": "^0.38.0",
|
|
22
|
+
"drizzle-zod": "^0.8.3",
|
|
23
|
+
"hono": "^4.6.0",
|
|
24
|
+
"zod": "^3.23.0"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"postgres": "^3.4.0",
|
|
28
|
+
"@thru/replay": "0.1.38"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^20.11.0",
|
|
32
|
+
"postgres": "^3.4.0",
|
|
33
|
+
"tsup": "^8.1.0",
|
|
34
|
+
"tsx": "^4.7.0",
|
|
35
|
+
"typescript": "^5.3.3",
|
|
36
|
+
"vitest": "^1.2.0",
|
|
37
|
+
"@thru/replay": "0.1.38"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"typecheck": "tsc --noEmit",
|
|
42
|
+
"dev": "tsx watch src/index.ts",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"lint": "eslint src/"
|
|
45
|
+
}
|
|
46
|
+
}
|