@apibara/indexer 2.1.0-beta.30 → 2.1.0-beta.32

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.
Files changed (59) hide show
  1. package/dist/index.cjs +1 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +1 -1
  4. package/dist/index.d.mts +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.mjs +1 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/dist/internal/index.cjs +1 -0
  9. package/dist/internal/index.cjs.map +1 -0
  10. package/dist/internal/index.mjs +1 -0
  11. package/dist/internal/index.mjs.map +1 -0
  12. package/dist/internal/plugins.cjs +1 -0
  13. package/dist/internal/plugins.cjs.map +1 -0
  14. package/dist/internal/plugins.d.cts +1 -1
  15. package/dist/internal/plugins.d.mts +1 -1
  16. package/dist/internal/plugins.d.ts +1 -1
  17. package/dist/internal/plugins.mjs +1 -0
  18. package/dist/internal/plugins.mjs.map +1 -0
  19. package/dist/internal/testing.cjs +1 -0
  20. package/dist/internal/testing.cjs.map +1 -0
  21. package/dist/internal/testing.d.cts +1 -1
  22. package/dist/internal/testing.d.mts +1 -1
  23. package/dist/internal/testing.d.ts +1 -1
  24. package/dist/internal/testing.mjs +1 -0
  25. package/dist/internal/testing.mjs.map +1 -0
  26. package/dist/plugins/index.cjs +1 -0
  27. package/dist/plugins/index.cjs.map +1 -0
  28. package/dist/plugins/index.d.cts +2 -2
  29. package/dist/plugins/index.d.mts +2 -2
  30. package/dist/plugins/index.d.ts +2 -2
  31. package/dist/plugins/index.mjs +1 -0
  32. package/dist/plugins/index.mjs.map +1 -0
  33. package/dist/shared/{indexer.7668fe34.d.cts → indexer.27b29a67.d.cts} +2 -1
  34. package/dist/shared/{indexer.7668fe34.d.mts → indexer.27b29a67.d.mts} +2 -1
  35. package/dist/shared/{indexer.7668fe34.d.ts → indexer.27b29a67.d.ts} +2 -1
  36. package/dist/shared/indexer.479ae593.cjs +1 -0
  37. package/dist/shared/indexer.479ae593.cjs.map +1 -0
  38. package/dist/shared/indexer.75773ef1.mjs +1 -0
  39. package/dist/shared/indexer.75773ef1.mjs.map +1 -0
  40. package/dist/shared/indexer.98a921a7.mjs +1 -0
  41. package/dist/shared/indexer.98a921a7.mjs.map +1 -0
  42. package/dist/shared/indexer.a09fa402.cjs +1 -0
  43. package/dist/shared/indexer.a09fa402.cjs.map +1 -0
  44. package/dist/testing/index.cjs +1 -0
  45. package/dist/testing/index.cjs.map +1 -0
  46. package/dist/testing/index.d.cts +1 -1
  47. package/dist/testing/index.d.mts +1 -1
  48. package/dist/testing/index.d.ts +1 -1
  49. package/dist/testing/index.mjs +1 -0
  50. package/dist/testing/index.mjs.map +1 -0
  51. package/dist/vcr/index.cjs +1 -0
  52. package/dist/vcr/index.cjs.map +1 -0
  53. package/dist/vcr/index.d.cts +1 -1
  54. package/dist/vcr/index.d.mts +1 -1
  55. package/dist/vcr/index.d.ts +1 -1
  56. package/dist/vcr/index.mjs +1 -0
  57. package/dist/vcr/index.mjs.map +1 -0
  58. package/package.json +2 -2
  59. package/src/indexer.ts +2 -0
package/dist/index.cjs CHANGED
@@ -324,3 +324,4 @@ exports.createIndexer = createIndexer;
324
324
  exports.defineIndexer = defineIndexer;
325
325
  exports.run = run;
326
326
  exports.runWithReconnect = runWithReconnect;
327
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/compose.ts","../src/otel.ts","../src/indexer.ts"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2021 - present, Yusuke Wada and Hono contributors\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { IndexerContext } from \"./context\";\n\nexport type NextFunction = () => Promise<void>;\nexport type MiddlewareFunction<C> = (\n context: C,\n next: NextFunction,\n) => Promise<void>;\n\nexport function compose<C extends IndexerContext>(\n middleware: MiddlewareFunction<C>[],\n): (context: C, next?: NextFunction) => Promise<void> {\n return (context, next) => {\n let index = -1;\n\n return dispatch(0);\n\n /// Dispatch the middleware functions.\n async function dispatch(i: number): Promise<void> {\n if (i <= index) {\n throw new Error(\"next() called multiple times\");\n }\n index = i;\n\n let handler: MiddlewareFunction<C> | undefined;\n\n if (i >= middleware.length) {\n if (next) {\n await next();\n }\n\n return;\n }\n\n if (middleware[i]) {\n handler = middleware[i];\n } else {\n handler = i === middleware.length ? next : undefined;\n }\n\n if (!handler) {\n throw new Error(\"Handler not found\");\n }\n\n await handler(context, () => dispatch(i + 1));\n }\n };\n}\n","import { metrics, trace } from \"@opentelemetry/api\";\n\nexport function createTracer() {\n return trace.getTracer(\"@apibara/indexer\");\n}\n\nexport function createIndexerMetrics() {\n const meter = metrics.getMeter(\"@apibara/indexer\");\n\n const currentBlockGauge = meter.createGauge(\"current_block\", {\n description: \"Current block number being processed\",\n unit: \"{block}\",\n });\n\n const processedBlockCounter = meter.createCounter(\"processed_blocks\", {\n description: \"Number of blocks processed\",\n unit: \"{blocks}\",\n });\n\n const reorgCounter = meter.createCounter(\"reorgs\", {\n description: \"Number of reorgs (invalidate messages) received\",\n unit: \"{reorgs}\",\n });\n\n return {\n currentBlockGauge,\n processedBlockCounter,\n reorgCounter,\n };\n}\n","import {\n type Client,\n ClientError,\n type CreateClientOptions,\n type Cursor,\n type DataFinality,\n type Finalize,\n type Invalidate,\n ServerError,\n Status,\n type StreamConfig,\n type StreamDataOptions,\n type StreamDataRequest,\n type StreamDataResponse,\n type SystemMessage,\n} from \"@apibara/protocol\";\nimport consola from \"consola\";\nimport {\n type Hookable,\n type NestedHooks,\n createDebugger,\n createHooks,\n} from \"hookable\";\n\nimport assert from \"node:assert\";\nimport { type MiddlewareFunction, type NextFunction, compose } from \"./compose\";\nimport {\n type IndexerContext,\n indexerAsyncContext,\n useIndexerContext,\n} from \"./context\";\nimport { createIndexerMetrics, createTracer } from \"./otel\";\nimport type { IndexerPlugin } from \"./plugins\";\nimport { useInternalContext } from \"./plugins/context\";\n\nexport type UseMiddlewareFunction = (\n fn: MiddlewareFunction<IndexerContext>,\n) => void;\n\nexport interface IndexerHooks<TFilter, TBlock> {\n \"run:before\": () => void;\n \"run:after\": () => void;\n \"connect:before\": ({\n request,\n options,\n }: {\n request: StreamDataRequest<TFilter>;\n options: StreamDataOptions;\n }) => void;\n \"connect:after\": ({\n request,\n }: { request: StreamDataRequest<TFilter> }) => void;\n \"connect:factory\": ({\n request,\n endCursor,\n }: {\n request: StreamDataRequest<TFilter>;\n endCursor?: Cursor;\n }) => void;\n \"handler:middleware\": ({ use }: { use: UseMiddlewareFunction }) => void;\n message: ({ message }: { message: StreamDataResponse<TBlock> }) => void;\n \"message:invalidate\": ({ message }: { message: Invalidate }) => void;\n \"message:finalize\": ({ message }: { message: Finalize }) => void;\n \"message:heartbeat\": () => void;\n \"message:systemMessage\": ({ message }: { message: SystemMessage }) => void;\n}\n\nexport type IndexerStartingCursor =\n | {\n startingCursor?: never;\n startingBlock: bigint;\n }\n | {\n startingCursor: Cursor;\n startingBlock?: never;\n }\n | {\n startingCursor?: never;\n startingBlock?: never;\n };\n\nexport type IndexerConfig<TFilter, TBlock> = {\n streamUrl: string;\n filter: TFilter;\n finality?: DataFinality;\n clientOptions?: CreateClientOptions;\n factory?: ({\n block,\n context,\n }: { block: TBlock; context: IndexerContext }) => Promise<{\n filter?: TFilter;\n }>;\n transform: (args: {\n block: TBlock;\n cursor?: Cursor | undefined;\n endCursor?: Cursor | undefined;\n finality: DataFinality;\n context: IndexerContext;\n }) => Promise<void>;\n hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;\n plugins?: ReadonlyArray<IndexerPlugin<TFilter, TBlock>>;\n debug?: boolean;\n} & IndexerStartingCursor;\n\nexport type IndexerWithStreamConfig<TFilter, TBlock> = IndexerConfig<\n TFilter,\n TBlock\n> & {\n streamConfig: StreamConfig<TFilter, TBlock>;\n};\n\nexport function defineIndexer<TFilter, TBlock>(\n streamConfig: StreamConfig<TFilter, TBlock>,\n) {\n return (\n config: IndexerConfig<TFilter, TBlock>,\n ): IndexerWithStreamConfig<TFilter, TBlock> => ({\n streamConfig,\n ...config,\n });\n}\n\nexport interface Indexer<TFilter, TBlock> {\n streamConfig: StreamConfig<TFilter, TBlock>;\n options: IndexerConfig<TFilter, TBlock>;\n hooks: Hookable<IndexerHooks<TFilter, TBlock>>;\n}\n\nexport function createIndexer<TFilter, TBlock>({\n streamConfig,\n ...options\n}: IndexerWithStreamConfig<TFilter, TBlock>) {\n const indexer: Indexer<TFilter, TBlock> = {\n options,\n streamConfig,\n hooks: createHooks<IndexerHooks<TFilter, TBlock>>(),\n };\n\n if (indexer.options.debug) {\n createDebugger(indexer.hooks, { tag: \"indexer\" });\n }\n\n indexer.hooks.addHooks(indexer.options.hooks ?? {});\n\n for (const plugin of indexer.options.plugins ?? []) {\n plugin(indexer);\n }\n\n return indexer;\n}\n\nexport interface ReconnectOptions {\n maxRetries?: number;\n retryDelay?: number;\n maxWait?: number;\n}\n\nexport async function runWithReconnect<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n options: ReconnectOptions = {},\n) {\n let retryCount = 0;\n\n const maxRetries = options.maxRetries ?? 10;\n const retryDelay = options.retryDelay ?? 1_000;\n const maxWait = options.maxWait ?? 30_000;\n\n const runOptions: RunOptions = {\n onConnect() {\n retryCount = 0;\n },\n };\n\n while (true) {\n try {\n await run(client, indexer, runOptions);\n return;\n } catch (error) {\n // Only reconnect on internal/server errors.\n // All other errors should be rethrown.\n\n retryCount++;\n\n if (error instanceof ClientError || error instanceof ServerError) {\n const isServerError = error instanceof ServerError;\n\n if (error.code === Status.INTERNAL) {\n if (retryCount < maxRetries) {\n consola.error(\n `Internal ${isServerError ? \"server\" : \"client\"} error: ${\n error.message\n }`,\n );\n consola.start(\"Reconnecting...\");\n console.log();\n\n // Add jitter to the retry delay to avoid all clients retrying at the same time.\n const delay = Math.random() * (retryDelay * 0.2) + retryDelay;\n await new Promise((resolve) =>\n setTimeout(resolve, Math.min(retryCount * delay, maxWait)),\n );\n\n continue;\n }\n }\n }\n\n throw error;\n }\n }\n}\n\nexport interface RunOptions {\n onConnect?: () => void | Promise<void>;\n}\n\nexport async function run<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n runOptions: RunOptions = {},\n) {\n await indexerAsyncContext.callAsync({}, async () => {\n const context = useIndexerContext();\n const middleware = await registerMiddleware(indexer);\n\n const indexerMetrics = createIndexerMetrics();\n const tracer = createTracer();\n\n await indexer.hooks.callHook(\"run:before\");\n\n const { indexerName: indexerId } = useInternalContext();\n\n const isFactoryMode = indexer.options.factory !== undefined;\n\n // Give priority to startingCursor over startingBlock.\n let startingCursor: Cursor | undefined;\n if (indexer.options.startingCursor) {\n startingCursor = indexer.options.startingCursor;\n } else if (indexer.options.startingBlock !== undefined) {\n if (indexer.options.startingBlock === 0n) {\n startingCursor = undefined;\n } else if (indexer.options.startingBlock > 0n) {\n startingCursor = {\n orderKey: indexer.options.startingBlock - 1n,\n };\n }\n }\n\n // if factory mode we add a empty filter at the end of the filter array.\n const request = {\n filter: isFactoryMode\n ? [indexer.options.filter, {} as TFilter]\n : [indexer.options.filter],\n finality: indexer.options.finality,\n startingCursor,\n } as StreamDataRequest<TFilter>;\n\n const options: StreamDataOptions = {};\n\n await indexer.hooks.callHook(\"connect:before\", { request, options });\n\n // store main filter, so later it can be merged\n let mainFilter: TFilter;\n if (isFactoryMode) {\n mainFilter = request.filter[1];\n }\n\n let stream: AsyncIterator<\n StreamDataResponse<TBlock>,\n StreamDataResponse<TBlock>\n > = client.streamData(request, options)[Symbol.asyncIterator]();\n\n await indexer.hooks.callHook(\"connect:after\", { request });\n\n let onConnectCalled = false;\n\n while (true) {\n const { value: message, done } = await stream.next();\n\n if (done) {\n break;\n }\n\n if (!onConnectCalled) {\n onConnectCalled = true;\n if (runOptions.onConnect) {\n await runOptions.onConnect();\n }\n }\n\n await indexer.hooks.callHook(\"message\", { message });\n\n switch (message._tag) {\n case \"data\": {\n await tracer.startActiveSpan(\"message data\", async (span) => {\n const blocks = message.data.data;\n const { cursor, endCursor, finality } = message.data;\n\n context.cursor = cursor;\n context.endCursor = endCursor;\n context.finality = finality;\n\n // Record current block number being processed\n indexerMetrics.currentBlockGauge.record(\n Number(endCursor?.orderKey),\n {\n indexer_id: indexerId,\n },\n );\n\n await middleware(context, async () => {\n let block: TBlock | null;\n\n // when factory mode\n if (isFactoryMode && finality !== \"pending\") {\n assert(indexer.options.factory !== undefined);\n\n const [factoryBlock, mainBlock] = blocks;\n\n block = mainBlock;\n\n if (factoryBlock !== null) {\n const { filter } = await indexer.options.factory({\n block: factoryBlock,\n context,\n });\n\n // write returned data from factory function if filter is not defined\n if (filter) {\n // when filter is defined\n // merge old and new filters\n mainFilter = indexer.streamConfig.mergeFilter(\n mainFilter,\n filter,\n );\n\n // create request with new filters\n const request = {\n filter: [indexer.options.filter, mainFilter],\n finality: indexer.options.finality,\n startingCursor: cursor,\n } as StreamDataRequest<TFilter>;\n\n await indexer.hooks.callHook(\"connect:factory\", {\n request,\n endCursor,\n });\n\n // create new stream with new request\n stream = client\n .streamData(request, options)\n [Symbol.asyncIterator]();\n\n const { value: message } = await stream.next();\n\n assert(message._tag === \"data\");\n\n const [_factoryBlock, _block] = message.data.data;\n\n block = _block;\n }\n }\n } else {\n // when not in factory mode\n block = blocks[0];\n }\n\n // if block is not null\n if (block) {\n await tracer.startActiveSpan(\"handler\", async (span) => {\n await indexer.options.transform({\n block,\n cursor,\n endCursor,\n finality,\n context,\n });\n\n span.end();\n });\n }\n });\n\n span.end();\n });\n\n // Record processed block metric\n indexerMetrics.processedBlockCounter.add(1, {\n indexer_id: indexerId,\n });\n\n context.cursor = undefined;\n context.endCursor = undefined;\n context.finality = undefined;\n\n break;\n }\n case \"invalidate\": {\n await tracer.startActiveSpan(\"message invalidate\", async (span) => {\n // Record reorg metric\n indexerMetrics.reorgCounter.add(1, {\n indexer_id: indexerId,\n });\n await indexer.hooks.callHook(\"message:invalidate\", {\n message: message.invalidate,\n });\n span.end();\n });\n break;\n }\n case \"finalize\": {\n await tracer.startActiveSpan(\"message finalize\", async (span) => {\n await indexer.hooks.callHook(\"message:finalize\", {\n message: message.finalize,\n });\n span.end();\n });\n break;\n }\n case \"heartbeat\": {\n await tracer.startActiveSpan(\"message heartbeat\", async (span) => {\n await indexer.hooks.callHook(\"message:heartbeat\");\n span.end();\n });\n break;\n }\n case \"systemMessage\": {\n await tracer.startActiveSpan(\n \"message systemMessage\",\n async (span) => {\n switch (message.systemMessage.output?._tag) {\n case \"stderr\": {\n consola.warn(message.systemMessage.output.stderr);\n break;\n }\n case \"stdout\": {\n consola.info(message.systemMessage.output.stdout);\n break;\n }\n default: {\n }\n }\n\n await indexer.hooks.callHook(\"message:systemMessage\", {\n message: message.systemMessage,\n });\n span.end();\n },\n );\n break;\n }\n default: {\n consola.warn(\"unexpected message\", message);\n throw new Error(\"not implemented\");\n }\n }\n\n await indexer.hooks.callHook(\"run:after\");\n }\n });\n}\n\nasync function registerMiddleware<TFilter, TBlock>(\n indexer: Indexer<TFilter, TBlock>,\n): Promise<MiddlewareFunction<IndexerContext>> {\n const middleware: MiddlewareFunction<IndexerContext>[] = [];\n const use = (fn: MiddlewareFunction<IndexerContext>) => {\n middleware.push(fn);\n };\n\n await indexer.hooks.callHook(\"handler:middleware\", { use });\n\n const composed = compose(middleware);\n\n // Return a named function to help debugging\n return async function _composedIndexerMiddleware(\n context: IndexerContext,\n next?: NextFunction,\n ) {\n await composed(context, next);\n };\n}\n"],"names":["trace","metrics","createHooks","createDebugger","ClientError","ServerError","Status","consola","indexerAsyncContext","useIndexerContext","useInternalContext","assert","request","message","span"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- export { a as Indexer, c as IndexerConfig, e as IndexerHooks, f as IndexerStartingCursor, I as IndexerWithStreamConfig, R as ReconnectOptions, i as RunOptions, U as UseMiddlewareFunction, h as createIndexer, g as defineIndexer, j as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.7668fe34.cjs';
1
+ export { a as Indexer, c as IndexerConfig, e as IndexerHooks, f as IndexerStartingCursor, I as IndexerWithStreamConfig, R as ReconnectOptions, i as RunOptions, U as UseMiddlewareFunction, h as createIndexer, g as defineIndexer, j as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.27b29a67.cjs';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- export { a as Indexer, c as IndexerConfig, e as IndexerHooks, f as IndexerStartingCursor, I as IndexerWithStreamConfig, R as ReconnectOptions, i as RunOptions, U as UseMiddlewareFunction, h as createIndexer, g as defineIndexer, j as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.7668fe34.mjs';
1
+ export { a as Indexer, c as IndexerConfig, e as IndexerHooks, f as IndexerStartingCursor, I as IndexerWithStreamConfig, R as ReconnectOptions, i as RunOptions, U as UseMiddlewareFunction, h as createIndexer, g as defineIndexer, j as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.27b29a67.mjs';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { a as Indexer, c as IndexerConfig, e as IndexerHooks, f as IndexerStartingCursor, I as IndexerWithStreamConfig, R as ReconnectOptions, i as RunOptions, U as UseMiddlewareFunction, h as createIndexer, g as defineIndexer, j as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.7668fe34.js';
1
+ export { a as Indexer, c as IndexerConfig, e as IndexerHooks, f as IndexerStartingCursor, I as IndexerWithStreamConfig, R as ReconnectOptions, i as RunOptions, U as UseMiddlewareFunction, h as createIndexer, g as defineIndexer, j as run, r as runWithReconnect, u as useIndexerContext } from './shared/indexer.27b29a67.js';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
package/dist/index.mjs CHANGED
@@ -313,3 +313,4 @@ async function registerMiddleware(indexer) {
313
313
  }
314
314
 
315
315
  export { createIndexer, defineIndexer, run, runWithReconnect, useIndexerContext };
316
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/compose.ts","../src/otel.ts","../src/indexer.ts"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2021 - present, Yusuke Wada and Hono contributors\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { IndexerContext } from \"./context\";\n\nexport type NextFunction = () => Promise<void>;\nexport type MiddlewareFunction<C> = (\n context: C,\n next: NextFunction,\n) => Promise<void>;\n\nexport function compose<C extends IndexerContext>(\n middleware: MiddlewareFunction<C>[],\n): (context: C, next?: NextFunction) => Promise<void> {\n return (context, next) => {\n let index = -1;\n\n return dispatch(0);\n\n /// Dispatch the middleware functions.\n async function dispatch(i: number): Promise<void> {\n if (i <= index) {\n throw new Error(\"next() called multiple times\");\n }\n index = i;\n\n let handler: MiddlewareFunction<C> | undefined;\n\n if (i >= middleware.length) {\n if (next) {\n await next();\n }\n\n return;\n }\n\n if (middleware[i]) {\n handler = middleware[i];\n } else {\n handler = i === middleware.length ? next : undefined;\n }\n\n if (!handler) {\n throw new Error(\"Handler not found\");\n }\n\n await handler(context, () => dispatch(i + 1));\n }\n };\n}\n","import { metrics, trace } from \"@opentelemetry/api\";\n\nexport function createTracer() {\n return trace.getTracer(\"@apibara/indexer\");\n}\n\nexport function createIndexerMetrics() {\n const meter = metrics.getMeter(\"@apibara/indexer\");\n\n const currentBlockGauge = meter.createGauge(\"current_block\", {\n description: \"Current block number being processed\",\n unit: \"{block}\",\n });\n\n const processedBlockCounter = meter.createCounter(\"processed_blocks\", {\n description: \"Number of blocks processed\",\n unit: \"{blocks}\",\n });\n\n const reorgCounter = meter.createCounter(\"reorgs\", {\n description: \"Number of reorgs (invalidate messages) received\",\n unit: \"{reorgs}\",\n });\n\n return {\n currentBlockGauge,\n processedBlockCounter,\n reorgCounter,\n };\n}\n","import {\n type Client,\n ClientError,\n type CreateClientOptions,\n type Cursor,\n type DataFinality,\n type Finalize,\n type Invalidate,\n ServerError,\n Status,\n type StreamConfig,\n type StreamDataOptions,\n type StreamDataRequest,\n type StreamDataResponse,\n type SystemMessage,\n} from \"@apibara/protocol\";\nimport consola from \"consola\";\nimport {\n type Hookable,\n type NestedHooks,\n createDebugger,\n createHooks,\n} from \"hookable\";\n\nimport assert from \"node:assert\";\nimport { type MiddlewareFunction, type NextFunction, compose } from \"./compose\";\nimport {\n type IndexerContext,\n indexerAsyncContext,\n useIndexerContext,\n} from \"./context\";\nimport { createIndexerMetrics, createTracer } from \"./otel\";\nimport type { IndexerPlugin } from \"./plugins\";\nimport { useInternalContext } from \"./plugins/context\";\n\nexport type UseMiddlewareFunction = (\n fn: MiddlewareFunction<IndexerContext>,\n) => void;\n\nexport interface IndexerHooks<TFilter, TBlock> {\n \"run:before\": () => void;\n \"run:after\": () => void;\n \"connect:before\": ({\n request,\n options,\n }: {\n request: StreamDataRequest<TFilter>;\n options: StreamDataOptions;\n }) => void;\n \"connect:after\": ({\n request,\n }: { request: StreamDataRequest<TFilter> }) => void;\n \"connect:factory\": ({\n request,\n endCursor,\n }: {\n request: StreamDataRequest<TFilter>;\n endCursor?: Cursor;\n }) => void;\n \"handler:middleware\": ({ use }: { use: UseMiddlewareFunction }) => void;\n message: ({ message }: { message: StreamDataResponse<TBlock> }) => void;\n \"message:invalidate\": ({ message }: { message: Invalidate }) => void;\n \"message:finalize\": ({ message }: { message: Finalize }) => void;\n \"message:heartbeat\": () => void;\n \"message:systemMessage\": ({ message }: { message: SystemMessage }) => void;\n}\n\nexport type IndexerStartingCursor =\n | {\n startingCursor?: never;\n startingBlock: bigint;\n }\n | {\n startingCursor: Cursor;\n startingBlock?: never;\n }\n | {\n startingCursor?: never;\n startingBlock?: never;\n };\n\nexport type IndexerConfig<TFilter, TBlock> = {\n streamUrl: string;\n filter: TFilter;\n finality?: DataFinality;\n clientOptions?: CreateClientOptions;\n factory?: ({\n block,\n context,\n }: { block: TBlock; context: IndexerContext }) => Promise<{\n filter?: TFilter;\n }>;\n transform: (args: {\n block: TBlock;\n cursor?: Cursor | undefined;\n endCursor?: Cursor | undefined;\n finality: DataFinality;\n context: IndexerContext;\n }) => Promise<void>;\n hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;\n plugins?: ReadonlyArray<IndexerPlugin<TFilter, TBlock>>;\n debug?: boolean;\n} & IndexerStartingCursor;\n\nexport type IndexerWithStreamConfig<TFilter, TBlock> = IndexerConfig<\n TFilter,\n TBlock\n> & {\n streamConfig: StreamConfig<TFilter, TBlock>;\n};\n\nexport function defineIndexer<TFilter, TBlock>(\n streamConfig: StreamConfig<TFilter, TBlock>,\n) {\n return (\n config: IndexerConfig<TFilter, TBlock>,\n ): IndexerWithStreamConfig<TFilter, TBlock> => ({\n streamConfig,\n ...config,\n });\n}\n\nexport interface Indexer<TFilter, TBlock> {\n streamConfig: StreamConfig<TFilter, TBlock>;\n options: IndexerConfig<TFilter, TBlock>;\n hooks: Hookable<IndexerHooks<TFilter, TBlock>>;\n}\n\nexport function createIndexer<TFilter, TBlock>({\n streamConfig,\n ...options\n}: IndexerWithStreamConfig<TFilter, TBlock>) {\n const indexer: Indexer<TFilter, TBlock> = {\n options,\n streamConfig,\n hooks: createHooks<IndexerHooks<TFilter, TBlock>>(),\n };\n\n if (indexer.options.debug) {\n createDebugger(indexer.hooks, { tag: \"indexer\" });\n }\n\n indexer.hooks.addHooks(indexer.options.hooks ?? {});\n\n for (const plugin of indexer.options.plugins ?? []) {\n plugin(indexer);\n }\n\n return indexer;\n}\n\nexport interface ReconnectOptions {\n maxRetries?: number;\n retryDelay?: number;\n maxWait?: number;\n}\n\nexport async function runWithReconnect<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n options: ReconnectOptions = {},\n) {\n let retryCount = 0;\n\n const maxRetries = options.maxRetries ?? 10;\n const retryDelay = options.retryDelay ?? 1_000;\n const maxWait = options.maxWait ?? 30_000;\n\n const runOptions: RunOptions = {\n onConnect() {\n retryCount = 0;\n },\n };\n\n while (true) {\n try {\n await run(client, indexer, runOptions);\n return;\n } catch (error) {\n // Only reconnect on internal/server errors.\n // All other errors should be rethrown.\n\n retryCount++;\n\n if (error instanceof ClientError || error instanceof ServerError) {\n const isServerError = error instanceof ServerError;\n\n if (error.code === Status.INTERNAL) {\n if (retryCount < maxRetries) {\n consola.error(\n `Internal ${isServerError ? \"server\" : \"client\"} error: ${\n error.message\n }`,\n );\n consola.start(\"Reconnecting...\");\n console.log();\n\n // Add jitter to the retry delay to avoid all clients retrying at the same time.\n const delay = Math.random() * (retryDelay * 0.2) + retryDelay;\n await new Promise((resolve) =>\n setTimeout(resolve, Math.min(retryCount * delay, maxWait)),\n );\n\n continue;\n }\n }\n }\n\n throw error;\n }\n }\n}\n\nexport interface RunOptions {\n onConnect?: () => void | Promise<void>;\n}\n\nexport async function run<TFilter, TBlock>(\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n runOptions: RunOptions = {},\n) {\n await indexerAsyncContext.callAsync({}, async () => {\n const context = useIndexerContext();\n const middleware = await registerMiddleware(indexer);\n\n const indexerMetrics = createIndexerMetrics();\n const tracer = createTracer();\n\n await indexer.hooks.callHook(\"run:before\");\n\n const { indexerName: indexerId } = useInternalContext();\n\n const isFactoryMode = indexer.options.factory !== undefined;\n\n // Give priority to startingCursor over startingBlock.\n let startingCursor: Cursor | undefined;\n if (indexer.options.startingCursor) {\n startingCursor = indexer.options.startingCursor;\n } else if (indexer.options.startingBlock !== undefined) {\n if (indexer.options.startingBlock === 0n) {\n startingCursor = undefined;\n } else if (indexer.options.startingBlock > 0n) {\n startingCursor = {\n orderKey: indexer.options.startingBlock - 1n,\n };\n }\n }\n\n // if factory mode we add a empty filter at the end of the filter array.\n const request = {\n filter: isFactoryMode\n ? [indexer.options.filter, {} as TFilter]\n : [indexer.options.filter],\n finality: indexer.options.finality,\n startingCursor,\n } as StreamDataRequest<TFilter>;\n\n const options: StreamDataOptions = {};\n\n await indexer.hooks.callHook(\"connect:before\", { request, options });\n\n // store main filter, so later it can be merged\n let mainFilter: TFilter;\n if (isFactoryMode) {\n mainFilter = request.filter[1];\n }\n\n let stream: AsyncIterator<\n StreamDataResponse<TBlock>,\n StreamDataResponse<TBlock>\n > = client.streamData(request, options)[Symbol.asyncIterator]();\n\n await indexer.hooks.callHook(\"connect:after\", { request });\n\n let onConnectCalled = false;\n\n while (true) {\n const { value: message, done } = await stream.next();\n\n if (done) {\n break;\n }\n\n if (!onConnectCalled) {\n onConnectCalled = true;\n if (runOptions.onConnect) {\n await runOptions.onConnect();\n }\n }\n\n await indexer.hooks.callHook(\"message\", { message });\n\n switch (message._tag) {\n case \"data\": {\n await tracer.startActiveSpan(\"message data\", async (span) => {\n const blocks = message.data.data;\n const { cursor, endCursor, finality } = message.data;\n\n context.cursor = cursor;\n context.endCursor = endCursor;\n context.finality = finality;\n\n // Record current block number being processed\n indexerMetrics.currentBlockGauge.record(\n Number(endCursor?.orderKey),\n {\n indexer_id: indexerId,\n },\n );\n\n await middleware(context, async () => {\n let block: TBlock | null;\n\n // when factory mode\n if (isFactoryMode && finality !== \"pending\") {\n assert(indexer.options.factory !== undefined);\n\n const [factoryBlock, mainBlock] = blocks;\n\n block = mainBlock;\n\n if (factoryBlock !== null) {\n const { filter } = await indexer.options.factory({\n block: factoryBlock,\n context,\n });\n\n // write returned data from factory function if filter is not defined\n if (filter) {\n // when filter is defined\n // merge old and new filters\n mainFilter = indexer.streamConfig.mergeFilter(\n mainFilter,\n filter,\n );\n\n // create request with new filters\n const request = {\n filter: [indexer.options.filter, mainFilter],\n finality: indexer.options.finality,\n startingCursor: cursor,\n } as StreamDataRequest<TFilter>;\n\n await indexer.hooks.callHook(\"connect:factory\", {\n request,\n endCursor,\n });\n\n // create new stream with new request\n stream = client\n .streamData(request, options)\n [Symbol.asyncIterator]();\n\n const { value: message } = await stream.next();\n\n assert(message._tag === \"data\");\n\n const [_factoryBlock, _block] = message.data.data;\n\n block = _block;\n }\n }\n } else {\n // when not in factory mode\n block = blocks[0];\n }\n\n // if block is not null\n if (block) {\n await tracer.startActiveSpan(\"handler\", async (span) => {\n await indexer.options.transform({\n block,\n cursor,\n endCursor,\n finality,\n context,\n });\n\n span.end();\n });\n }\n });\n\n span.end();\n });\n\n // Record processed block metric\n indexerMetrics.processedBlockCounter.add(1, {\n indexer_id: indexerId,\n });\n\n context.cursor = undefined;\n context.endCursor = undefined;\n context.finality = undefined;\n\n break;\n }\n case \"invalidate\": {\n await tracer.startActiveSpan(\"message invalidate\", async (span) => {\n // Record reorg metric\n indexerMetrics.reorgCounter.add(1, {\n indexer_id: indexerId,\n });\n await indexer.hooks.callHook(\"message:invalidate\", {\n message: message.invalidate,\n });\n span.end();\n });\n break;\n }\n case \"finalize\": {\n await tracer.startActiveSpan(\"message finalize\", async (span) => {\n await indexer.hooks.callHook(\"message:finalize\", {\n message: message.finalize,\n });\n span.end();\n });\n break;\n }\n case \"heartbeat\": {\n await tracer.startActiveSpan(\"message heartbeat\", async (span) => {\n await indexer.hooks.callHook(\"message:heartbeat\");\n span.end();\n });\n break;\n }\n case \"systemMessage\": {\n await tracer.startActiveSpan(\n \"message systemMessage\",\n async (span) => {\n switch (message.systemMessage.output?._tag) {\n case \"stderr\": {\n consola.warn(message.systemMessage.output.stderr);\n break;\n }\n case \"stdout\": {\n consola.info(message.systemMessage.output.stdout);\n break;\n }\n default: {\n }\n }\n\n await indexer.hooks.callHook(\"message:systemMessage\", {\n message: message.systemMessage,\n });\n span.end();\n },\n );\n break;\n }\n default: {\n consola.warn(\"unexpected message\", message);\n throw new Error(\"not implemented\");\n }\n }\n\n await indexer.hooks.callHook(\"run:after\");\n }\n });\n}\n\nasync function registerMiddleware<TFilter, TBlock>(\n indexer: Indexer<TFilter, TBlock>,\n): Promise<MiddlewareFunction<IndexerContext>> {\n const middleware: MiddlewareFunction<IndexerContext>[] = [];\n const use = (fn: MiddlewareFunction<IndexerContext>) => {\n middleware.push(fn);\n };\n\n await indexer.hooks.callHook(\"handler:middleware\", { use });\n\n const composed = compose(middleware);\n\n // Return a named function to help debugging\n return async function _composedIndexerMiddleware(\n context: IndexerContext,\n next?: NextFunction,\n ) {\n await composed(context, next);\n };\n}\n"],"names":["request","message","span"],"mappings":"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"}
@@ -8,3 +8,4 @@ function generateIndexerId(fileBasedName, identifier) {
8
8
  }
9
9
 
10
10
  exports.generateIndexerId = generateIndexerId;
11
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/internal/index.ts"],"sourcesContent":["export function generateIndexerId(fileBasedName: string, identifier?: string) {\n return `indexer_${fileBasedName}_${identifier || \"default\"}`.replace(\n /[^a-zA-Z0-9_]/g,\n \"_\",\n );\n}\n"],"names":[],"mappings":";;AAAgB,SAAA,iBAAA,CAAkB,eAAuB,UAAqB,EAAA;AAC5E,EAAA,OAAO,CAAW,QAAA,EAAA,aAAa,CAAI,CAAA,EAAA,UAAA,IAAc,SAAS,CAAG,CAAA,CAAA,OAAA;AAAA,IAC3D,gBAAA;AAAA,IACA,GAAA;AAAA,GACF,CAAA;AACF;;;;"}
@@ -6,3 +6,4 @@ function generateIndexerId(fileBasedName, identifier) {
6
6
  }
7
7
 
8
8
  export { generateIndexerId };
9
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/internal/index.ts"],"sourcesContent":["export function generateIndexerId(fileBasedName: string, identifier?: string) {\n return `indexer_${fileBasedName}_${identifier || \"default\"}`.replace(\n /[^a-zA-Z0-9_]/g,\n \"_\",\n );\n}\n"],"names":[],"mappings":"AAAgB,SAAA,iBAAA,CAAkB,eAAuB,UAAqB,EAAA;AAC5E,EAAA,OAAO,CAAW,QAAA,EAAA,aAAa,CAAI,CAAA,EAAA,UAAA,IAAc,SAAS,CAAG,CAAA,CAAA,OAAA;AAAA,IAC3D,gBAAA;AAAA,IACA,GAAA;AAAA,GACF,CAAA;AACF;;;;"}
@@ -35,3 +35,4 @@ function useInternalContext() {
35
35
  exports.INTERNAL_CONTEXT_PROPERTY = INTERNAL_CONTEXT_PROPERTY;
36
36
  exports.internalContext = internalContext;
37
37
  exports.useInternalContext = useInternalContext;
38
+ //# sourceMappingURL=plugins.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.cjs","sources":["../../src/plugins/context.ts"],"sourcesContent":["import { useIndexerContext } from \"../context\";\nimport { defineIndexerPlugin } from \"./config\";\n\nexport const INTERNAL_CONTEXT_PROPERTY = \"_internal\";\n\nexport function internalContext<TFilter, TBlock, TTxnParams>(\n values: Record<string, unknown>,\n) {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n indexer.hooks.hook(\"run:before\", () => {\n try {\n const ctx = useIndexerContext();\n ctx[INTERNAL_CONTEXT_PROPERTY] = {\n ...(ctx[INTERNAL_CONTEXT_PROPERTY] || {}),\n ...values,\n };\n } catch (error) {\n throw new Error(\"Failed to set internal context\", {\n cause: error,\n });\n }\n });\n });\n}\n\nexport type InternalContext = {\n indexerName: string;\n availableIndexers: string[];\n};\n\nexport function useInternalContext(): InternalContext {\n const ctx = useIndexerContext();\n\n if (ctx[INTERNAL_CONTEXT_PROPERTY] === undefined) {\n throw new Error(\n \"Internal context is not available, possibly 'internalContext' plugin is missing!\",\n );\n }\n return ctx[INTERNAL_CONTEXT_PROPERTY];\n}\n"],"names":["defineIndexerPlugin","useIndexerContext"],"mappings":";;;;;;AAGO,MAAM,yBAA4B,GAAA,YAAA;AAElC,SAAS,gBACd,MACA,EAAA;AACA,EAAO,OAAAA,0BAAA,CAAqC,CAAC,OAAY,KAAA;AACvD,IAAQ,OAAA,CAAA,KAAA,CAAM,IAAK,CAAA,YAAA,EAAc,MAAM;AACrC,MAAI,IAAA;AACF,QAAA,MAAM,MAAMC,wBAAkB,EAAA,CAAA;AAC9B,QAAA,GAAA,CAAI,yBAAyB,CAAI,GAAA;AAAA,UAC/B,GAAI,GAAA,CAAI,yBAAyB,CAAA,IAAK,EAAC;AAAA,UACvC,GAAG,MAAA;AAAA,SACL,CAAA;AAAA,eACO,KAAO,EAAA;AACd,QAAM,MAAA,IAAI,MAAM,gCAAkC,EAAA;AAAA,UAChD,KAAO,EAAA,KAAA;AAAA,SACR,CAAA,CAAA;AAAA,OACH;AAAA,KACD,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH,CAAA;AAOO,SAAS,kBAAsC,GAAA;AACpD,EAAA,MAAM,MAAMA,wBAAkB,EAAA,CAAA;AAE9B,EAAI,IAAA,GAAA,CAAI,yBAAyB,CAAA,KAAM,KAAW,CAAA,EAAA;AAChD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kFAAA;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAA,OAAO,IAAI,yBAAyB,CAAA,CAAA;AACtC;;;;;;"}
@@ -1,4 +1,4 @@
1
- import { b as IndexerPlugin } from '../shared/indexer.7668fe34.cjs';
1
+ import { b as IndexerPlugin } from '../shared/indexer.27b29a67.cjs';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
4
4
 
@@ -1,4 +1,4 @@
1
- import { b as IndexerPlugin } from '../shared/indexer.7668fe34.mjs';
1
+ import { b as IndexerPlugin } from '../shared/indexer.27b29a67.mjs';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
4
4
 
@@ -1,4 +1,4 @@
1
- import { b as IndexerPlugin } from '../shared/indexer.7668fe34.js';
1
+ import { b as IndexerPlugin } from '../shared/indexer.27b29a67.js';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
4
4
 
@@ -31,3 +31,4 @@ function useInternalContext() {
31
31
  }
32
32
 
33
33
  export { INTERNAL_CONTEXT_PROPERTY, internalContext, useInternalContext };
34
+ //# sourceMappingURL=plugins.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.mjs","sources":["../../src/plugins/context.ts"],"sourcesContent":["import { useIndexerContext } from \"../context\";\nimport { defineIndexerPlugin } from \"./config\";\n\nexport const INTERNAL_CONTEXT_PROPERTY = \"_internal\";\n\nexport function internalContext<TFilter, TBlock, TTxnParams>(\n values: Record<string, unknown>,\n) {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n indexer.hooks.hook(\"run:before\", () => {\n try {\n const ctx = useIndexerContext();\n ctx[INTERNAL_CONTEXT_PROPERTY] = {\n ...(ctx[INTERNAL_CONTEXT_PROPERTY] || {}),\n ...values,\n };\n } catch (error) {\n throw new Error(\"Failed to set internal context\", {\n cause: error,\n });\n }\n });\n });\n}\n\nexport type InternalContext = {\n indexerName: string;\n availableIndexers: string[];\n};\n\nexport function useInternalContext(): InternalContext {\n const ctx = useIndexerContext();\n\n if (ctx[INTERNAL_CONTEXT_PROPERTY] === undefined) {\n throw new Error(\n \"Internal context is not available, possibly 'internalContext' plugin is missing!\",\n );\n }\n return ctx[INTERNAL_CONTEXT_PROPERTY];\n}\n"],"names":[],"mappings":";;;;AAGO,MAAM,yBAA4B,GAAA,YAAA;AAElC,SAAS,gBACd,MACA,EAAA;AACA,EAAO,OAAA,mBAAA,CAAqC,CAAC,OAAY,KAAA;AACvD,IAAQ,OAAA,CAAA,KAAA,CAAM,IAAK,CAAA,YAAA,EAAc,MAAM;AACrC,MAAI,IAAA;AACF,QAAA,MAAM,MAAM,iBAAkB,EAAA,CAAA;AAC9B,QAAA,GAAA,CAAI,yBAAyB,CAAI,GAAA;AAAA,UAC/B,GAAI,GAAA,CAAI,yBAAyB,CAAA,IAAK,EAAC;AAAA,UACvC,GAAG,MAAA;AAAA,SACL,CAAA;AAAA,eACO,KAAO,EAAA;AACd,QAAM,MAAA,IAAI,MAAM,gCAAkC,EAAA;AAAA,UAChD,KAAO,EAAA,KAAA;AAAA,SACR,CAAA,CAAA;AAAA,OACH;AAAA,KACD,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH,CAAA;AAOO,SAAS,kBAAsC,GAAA;AACpD,EAAA,MAAM,MAAM,iBAAkB,EAAA,CAAA;AAE9B,EAAI,IAAA,GAAA,CAAI,yBAAyB,CAAA,KAAM,KAAW,CAAA,EAAA;AAChD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,kFAAA;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAA,OAAO,IAAI,yBAAyB,CAAA,CAAA;AACtC;;;;"}
@@ -130,3 +130,4 @@ exports.generateMockMessages = generateMockMessages;
130
130
  exports.getMockIndexer = getMockIndexer;
131
131
  exports.mockSink = mockSink;
132
132
  exports.useMockSink = useMockSink;
133
+ //# sourceMappingURL=testing.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.cjs","sources":["../../src/internal/testing.ts"],"sourcesContent":["import { type Finalize, type Invalidate, isCursor } from \"@apibara/protocol\";\nimport {\n type MockBlock,\n type MockFilter,\n MockStream,\n type MockStreamResponse,\n} from \"@apibara/protocol/testing\";\nimport { useIndexerContext } from \"../context\";\nimport { type IndexerConfig, createIndexer, defineIndexer } from \"../indexer\";\nimport { defineIndexerPlugin, logger } from \"../plugins\";\nimport { type InternalContext, internalContext } from \"./plugins\";\n\nexport type MockMessagesOptions = {\n invalidate?: {\n invalidateFromIndex: number;\n invalidateTriggerIndex: number;\n };\n finalize?: {\n finalizeToIndex: number;\n finalizeTriggerIndex: number;\n };\n uniqueKey?: boolean;\n baseBlockNumber?: bigint;\n};\n\nexport function generateMockMessages(\n count = 10,\n options?: MockMessagesOptions,\n): MockStreamResponse[] {\n const invalidateAt = options?.invalidate;\n const finalizeAt = options?.finalize;\n const messages: MockStreamResponse[] = [];\n\n const baseBlockNumber = options?.baseBlockNumber ?? BigInt(5_000_000);\n\n for (let i = 0; i < count; i++) {\n const currentBlockNumber = baseBlockNumber + BigInt(i);\n const uniqueKey = uniqueKeyFromOrderKey(currentBlockNumber);\n if (invalidateAt && i === invalidateAt.invalidateTriggerIndex) {\n const invalidateToBlock =\n baseBlockNumber + BigInt(invalidateAt.invalidateFromIndex);\n messages.push({\n _tag: \"invalidate\",\n invalidate: {\n cursor: {\n orderKey: invalidateToBlock,\n uniqueKey: options?.uniqueKey\n ? uniqueKeyFromOrderKey(invalidateToBlock)\n : undefined,\n },\n } as Invalidate,\n });\n } else if (finalizeAt && i === finalizeAt.finalizeTriggerIndex) {\n const fianlizedToBlock =\n baseBlockNumber + BigInt(finalizeAt.finalizeToIndex);\n messages.push({\n _tag: \"finalize\",\n finalize: {\n cursor: {\n orderKey: fianlizedToBlock,\n uniqueKey: options?.uniqueKey\n ? uniqueKeyFromOrderKey(fianlizedToBlock)\n : undefined,\n },\n } as Finalize,\n });\n } else {\n messages.push({\n _tag: \"data\",\n data: {\n cursor: { orderKey: currentBlockNumber - 1n },\n finality: \"accepted\",\n data: [{ data: `${baseBlockNumber + BigInt(i)}` }],\n endCursor: {\n orderKey: currentBlockNumber,\n uniqueKey: options?.uniqueKey ? uniqueKey : undefined,\n },\n production: \"backfill\",\n },\n });\n }\n }\n\n return messages;\n}\n\nfunction uniqueKeyFromOrderKey(orderKey: bigint): `0x${string}` {\n return `0xff00${orderKey.toString()}`;\n}\n\ntype MockIndexerParams = {\n internalContext?: InternalContext;\n override?: Partial<IndexerConfig<MockFilter, MockBlock>>;\n};\n\nexport function getMockIndexer(params?: MockIndexerParams) {\n const { internalContext: contextParams, override } = params ?? {};\n const { plugins, ...rest } = override ?? {};\n\n return createIndexer(\n defineIndexer(MockStream)({\n streamUrl: \"https://sepolia.ethereum.a5a.ch\",\n finality: \"accepted\",\n filter: {},\n async transform() {},\n plugins: [\n logger(),\n internalContext(\n contextParams ??\n ({\n availableIndexers: [\"testing\"],\n indexerName: \"testing\",\n } as InternalContext),\n ),\n ...(plugins ?? []),\n ],\n ...(rest ?? {}),\n }),\n );\n}\n\nexport type MockRet = {\n data: string;\n};\n\n/**\n * A mock sink used for testing. The indexer function can write to the output array.\n * The indexer context is optionally written to the metadata object.\n */\nexport function mockSink<TFilter, TBlock>({\n output,\n metadata,\n}: { output: unknown[]; metadata?: Record<string, unknown> }) {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n indexer.hooks.hook(\"connect:before\", ({ request }) => {\n if (metadata?.lastCursor && isCursor(metadata.lastCursor)) {\n request.startingCursor = metadata.lastCursor;\n }\n\n if (metadata?.lastFilter) {\n request.filter[1] = metadata.lastFilter as TFilter;\n }\n });\n\n indexer.hooks.hook(\"connect:factory\", ({ request, endCursor }) => {\n if (request.filter[1]) {\n if (metadata) {\n metadata.lastCursor = endCursor;\n metadata.lastFilter = request.filter[1];\n }\n }\n });\n\n indexer.hooks.hook(\"handler:middleware\", ({ use }) => {\n use(async (context, next) => {\n context.output = output;\n await next();\n context.output = null;\n\n if (metadata) {\n metadata.lastCursor = context.endCursor;\n }\n });\n });\n });\n}\n\nexport function useMockSink(): { output: unknown[] } {\n const context = useIndexerContext();\n return { output: context.output };\n}\n"],"names":["createIndexer","defineIndexer","MockStream","logger","internalContext","defineIndexerPlugin","isCursor","useIndexerContext"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.7668fe34.cjs';
1
+ import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.27b29a67.cjs';
2
2
  import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
3
3
  import { InternalContext } from './plugins.cjs';
4
4
  import '@apibara/protocol';
@@ -1,4 +1,4 @@
1
- import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.7668fe34.mjs';
1
+ import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.27b29a67.mjs';
2
2
  import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
3
3
  import { InternalContext } from './plugins.mjs';
4
4
  import '@apibara/protocol';
@@ -1,4 +1,4 @@
1
- import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.7668fe34.js';
1
+ import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.27b29a67.js';
2
2
  import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
3
3
  import { InternalContext } from './plugins.js';
4
4
  import '@apibara/protocol';
@@ -125,3 +125,4 @@ function useMockSink() {
125
125
  }
126
126
 
127
127
  export { generateMockMessages, getMockIndexer, mockSink, useMockSink };
128
+ //# sourceMappingURL=testing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.mjs","sources":["../../src/internal/testing.ts"],"sourcesContent":["import { type Finalize, type Invalidate, isCursor } from \"@apibara/protocol\";\nimport {\n type MockBlock,\n type MockFilter,\n MockStream,\n type MockStreamResponse,\n} from \"@apibara/protocol/testing\";\nimport { useIndexerContext } from \"../context\";\nimport { type IndexerConfig, createIndexer, defineIndexer } from \"../indexer\";\nimport { defineIndexerPlugin, logger } from \"../plugins\";\nimport { type InternalContext, internalContext } from \"./plugins\";\n\nexport type MockMessagesOptions = {\n invalidate?: {\n invalidateFromIndex: number;\n invalidateTriggerIndex: number;\n };\n finalize?: {\n finalizeToIndex: number;\n finalizeTriggerIndex: number;\n };\n uniqueKey?: boolean;\n baseBlockNumber?: bigint;\n};\n\nexport function generateMockMessages(\n count = 10,\n options?: MockMessagesOptions,\n): MockStreamResponse[] {\n const invalidateAt = options?.invalidate;\n const finalizeAt = options?.finalize;\n const messages: MockStreamResponse[] = [];\n\n const baseBlockNumber = options?.baseBlockNumber ?? BigInt(5_000_000);\n\n for (let i = 0; i < count; i++) {\n const currentBlockNumber = baseBlockNumber + BigInt(i);\n const uniqueKey = uniqueKeyFromOrderKey(currentBlockNumber);\n if (invalidateAt && i === invalidateAt.invalidateTriggerIndex) {\n const invalidateToBlock =\n baseBlockNumber + BigInt(invalidateAt.invalidateFromIndex);\n messages.push({\n _tag: \"invalidate\",\n invalidate: {\n cursor: {\n orderKey: invalidateToBlock,\n uniqueKey: options?.uniqueKey\n ? uniqueKeyFromOrderKey(invalidateToBlock)\n : undefined,\n },\n } as Invalidate,\n });\n } else if (finalizeAt && i === finalizeAt.finalizeTriggerIndex) {\n const fianlizedToBlock =\n baseBlockNumber + BigInt(finalizeAt.finalizeToIndex);\n messages.push({\n _tag: \"finalize\",\n finalize: {\n cursor: {\n orderKey: fianlizedToBlock,\n uniqueKey: options?.uniqueKey\n ? uniqueKeyFromOrderKey(fianlizedToBlock)\n : undefined,\n },\n } as Finalize,\n });\n } else {\n messages.push({\n _tag: \"data\",\n data: {\n cursor: { orderKey: currentBlockNumber - 1n },\n finality: \"accepted\",\n data: [{ data: `${baseBlockNumber + BigInt(i)}` }],\n endCursor: {\n orderKey: currentBlockNumber,\n uniqueKey: options?.uniqueKey ? uniqueKey : undefined,\n },\n production: \"backfill\",\n },\n });\n }\n }\n\n return messages;\n}\n\nfunction uniqueKeyFromOrderKey(orderKey: bigint): `0x${string}` {\n return `0xff00${orderKey.toString()}`;\n}\n\ntype MockIndexerParams = {\n internalContext?: InternalContext;\n override?: Partial<IndexerConfig<MockFilter, MockBlock>>;\n};\n\nexport function getMockIndexer(params?: MockIndexerParams) {\n const { internalContext: contextParams, override } = params ?? {};\n const { plugins, ...rest } = override ?? {};\n\n return createIndexer(\n defineIndexer(MockStream)({\n streamUrl: \"https://sepolia.ethereum.a5a.ch\",\n finality: \"accepted\",\n filter: {},\n async transform() {},\n plugins: [\n logger(),\n internalContext(\n contextParams ??\n ({\n availableIndexers: [\"testing\"],\n indexerName: \"testing\",\n } as InternalContext),\n ),\n ...(plugins ?? []),\n ],\n ...(rest ?? {}),\n }),\n );\n}\n\nexport type MockRet = {\n data: string;\n};\n\n/**\n * A mock sink used for testing. The indexer function can write to the output array.\n * The indexer context is optionally written to the metadata object.\n */\nexport function mockSink<TFilter, TBlock>({\n output,\n metadata,\n}: { output: unknown[]; metadata?: Record<string, unknown> }) {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n indexer.hooks.hook(\"connect:before\", ({ request }) => {\n if (metadata?.lastCursor && isCursor(metadata.lastCursor)) {\n request.startingCursor = metadata.lastCursor;\n }\n\n if (metadata?.lastFilter) {\n request.filter[1] = metadata.lastFilter as TFilter;\n }\n });\n\n indexer.hooks.hook(\"connect:factory\", ({ request, endCursor }) => {\n if (request.filter[1]) {\n if (metadata) {\n metadata.lastCursor = endCursor;\n metadata.lastFilter = request.filter[1];\n }\n }\n });\n\n indexer.hooks.hook(\"handler:middleware\", ({ use }) => {\n use(async (context, next) => {\n context.output = output;\n await next();\n context.output = null;\n\n if (metadata) {\n metadata.lastCursor = context.endCursor;\n }\n });\n });\n });\n}\n\nexport function useMockSink(): { output: unknown[] } {\n const context = useIndexerContext();\n return { output: context.output };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;AAyBgB,SAAA,oBAAA,CACd,KAAQ,GAAA,EAAA,EACR,OACsB,EAAA;AACtB,EAAA,MAAM,eAAe,OAAS,EAAA,UAAA,CAAA;AAC9B,EAAA,MAAM,aAAa,OAAS,EAAA,QAAA,CAAA;AAC5B,EAAA,MAAM,WAAiC,EAAC,CAAA;AAExC,EAAA,MAAM,eAAkB,GAAA,OAAA,EAAS,eAAmB,IAAA,MAAA,CAAO,GAAS,CAAA,CAAA;AAEpE,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,KAAA,EAAO,CAAK,EAAA,EAAA;AAC9B,IAAM,MAAA,kBAAA,GAAqB,eAAkB,GAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AACrD,IAAM,MAAA,SAAA,GAAY,sBAAsB,kBAAkB,CAAA,CAAA;AAC1D,IAAI,IAAA,YAAA,IAAgB,CAAM,KAAA,YAAA,CAAa,sBAAwB,EAAA;AAC7D,MAAA,MAAM,iBACJ,GAAA,eAAA,GAAkB,MAAO,CAAA,YAAA,CAAa,mBAAmB,CAAA,CAAA;AAC3D,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,IAAM,EAAA,YAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,MAAQ,EAAA;AAAA,YACN,QAAU,EAAA,iBAAA;AAAA,YACV,SAAW,EAAA,OAAA,EAAS,SAChB,GAAA,qBAAA,CAAsB,iBAAiB,CACvC,GAAA,KAAA,CAAA;AAAA,WACN;AAAA,SACF;AAAA,OACD,CAAA,CAAA;AAAA,KACQ,MAAA,IAAA,UAAA,IAAc,CAAM,KAAA,UAAA,CAAW,oBAAsB,EAAA;AAC9D,MAAA,MAAM,gBACJ,GAAA,eAAA,GAAkB,MAAO,CAAA,UAAA,CAAW,eAAe,CAAA,CAAA;AACrD,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,IAAM,EAAA,UAAA;AAAA,QACN,QAAU,EAAA;AAAA,UACR,MAAQ,EAAA;AAAA,YACN,QAAU,EAAA,gBAAA;AAAA,YACV,SAAW,EAAA,OAAA,EAAS,SAChB,GAAA,qBAAA,CAAsB,gBAAgB,CACtC,GAAA,KAAA,CAAA;AAAA,WACN;AAAA,SACF;AAAA,OACD,CAAA,CAAA;AAAA,KACI,MAAA;AACL,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,IAAM,EAAA,MAAA;AAAA,QACN,IAAM,EAAA;AAAA,UACJ,MAAQ,EAAA,EAAE,QAAU,EAAA,kBAAA,GAAqB,EAAG,EAAA;AAAA,UAC5C,QAAU,EAAA,UAAA;AAAA,UACV,IAAA,EAAM,CAAC,EAAE,IAAM,EAAA,CAAA,EAAG,kBAAkB,MAAO,CAAA,CAAC,CAAC,CAAA,CAAA,EAAI,CAAA;AAAA,UACjD,SAAW,EAAA;AAAA,YACT,QAAU,EAAA,kBAAA;AAAA,YACV,SAAA,EAAW,OAAS,EAAA,SAAA,GAAY,SAAY,GAAA,KAAA,CAAA;AAAA,WAC9C;AAAA,UACA,UAAY,EAAA,UAAA;AAAA,SACd;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,GACF;AAEA,EAAO,OAAA,QAAA,CAAA;AACT,CAAA;AAEA,SAAS,sBAAsB,QAAiC,EAAA;AAC9D,EAAO,OAAA,CAAA,MAAA,EAAS,QAAS,CAAA,QAAA,EAAU,CAAA,CAAA,CAAA;AACrC,CAAA;AAOO,SAAS,eAAe,MAA4B,EAAA;AACzD,EAAA,MAAM,EAAE,eAAiB,EAAA,aAAA,EAAe,QAAS,EAAA,GAAI,UAAU,EAAC,CAAA;AAChE,EAAA,MAAM,EAAE,OAAS,EAAA,GAAG,IAAK,EAAA,GAAI,YAAY,EAAC,CAAA;AAE1C,EAAO,OAAA,aAAA;AAAA,IACL,aAAA,CAAc,UAAU,CAAE,CAAA;AAAA,MACxB,SAAW,EAAA,iCAAA;AAAA,MACX,QAAU,EAAA,UAAA;AAAA,MACV,QAAQ,EAAC;AAAA,MACT,MAAM,SAAY,GAAA;AAAA,OAAC;AAAA,MACnB,OAAS,EAAA;AAAA,QACP,MAAO,EAAA;AAAA,QACP,eAAA;AAAA,UACE,aACG,IAAA;AAAA,YACC,iBAAA,EAAmB,CAAC,SAAS,CAAA;AAAA,YAC7B,WAAa,EAAA,SAAA;AAAA,WACf;AAAA,SACJ;AAAA,QACA,GAAI,WAAW,EAAC;AAAA,OAClB;AAAA,MACA,GAAI,QAAQ,EAAC;AAAA,KACd,CAAA;AAAA,GACH,CAAA;AACF,CAAA;AAUO,SAAS,QAA0B,CAAA;AAAA,EACxC,MAAA;AAAA,EACA,QAAA;AACF,CAA8D,EAAA;AAC5D,EAAO,OAAA,mBAAA,CAAqC,CAAC,OAAY,KAAA;AACvD,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,gBAAA,EAAkB,CAAC,EAAE,SAAc,KAAA;AACpD,MAAA,IAAI,QAAU,EAAA,UAAA,IAAc,QAAS,CAAA,QAAA,CAAS,UAAU,CAAG,EAAA;AACzD,QAAA,OAAA,CAAQ,iBAAiB,QAAS,CAAA,UAAA,CAAA;AAAA,OACpC;AAEA,MAAA,IAAI,UAAU,UAAY,EAAA;AACxB,QAAQ,OAAA,CAAA,MAAA,CAAO,CAAC,CAAA,GAAI,QAAS,CAAA,UAAA,CAAA;AAAA,OAC/B;AAAA,KACD,CAAA,CAAA;AAED,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,iBAAA,EAAmB,CAAC,EAAE,OAAA,EAAS,WAAgB,KAAA;AAChE,MAAI,IAAA,OAAA,CAAQ,MAAO,CAAA,CAAC,CAAG,EAAA;AACrB,QAAA,IAAI,QAAU,EAAA;AACZ,UAAA,QAAA,CAAS,UAAa,GAAA,SAAA,CAAA;AACtB,UAAS,QAAA,CAAA,UAAA,GAAa,OAAQ,CAAA,MAAA,CAAO,CAAC,CAAA,CAAA;AAAA,SACxC;AAAA,OACF;AAAA,KACD,CAAA,CAAA;AAED,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,oBAAA,EAAsB,CAAC,EAAE,KAAU,KAAA;AACpD,MAAI,GAAA,CAAA,OAAO,SAAS,IAAS,KAAA;AAC3B,QAAA,OAAA,CAAQ,MAAS,GAAA,MAAA,CAAA;AACjB,QAAA,MAAM,IAAK,EAAA,CAAA;AACX,QAAA,OAAA,CAAQ,MAAS,GAAA,IAAA,CAAA;AAEjB,QAAA,IAAI,QAAU,EAAA;AACZ,UAAA,QAAA,CAAS,aAAa,OAAQ,CAAA,SAAA,CAAA;AAAA,SAChC;AAAA,OACD,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH,CAAA;AAEO,SAAS,WAAqC,GAAA;AACnD,EAAA,MAAM,UAAU,iBAAkB,EAAA,CAAA;AAClC,EAAO,OAAA,EAAE,MAAQ,EAAA,OAAA,CAAQ,MAAO,EAAA,CAAA;AAClC;;;;"}
@@ -40,3 +40,4 @@ exports.defineIndexerPlugin = config.defineIndexerPlugin;
40
40
  exports.logger = logger.logger;
41
41
  exports.useLogger = logger.useLogger;
42
42
  exports.inMemoryPersistence = inMemoryPersistence;
43
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/plugins/persistence.ts"],"sourcesContent":["import { type Cursor, isCursor } from \"@apibara/protocol\";\n\nimport { defineIndexerPlugin } from \"./config\";\n\n/**\n * A plugin that persists the last cursor and filter to memory.\n */\nexport function inMemoryPersistence<TFilter, TBlock>() {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n let lastCursor: Cursor | undefined;\n let lastFilter: TFilter | undefined;\n\n indexer.hooks.hook(\"connect:before\", ({ request }) => {\n if (lastCursor) {\n request.startingCursor = lastCursor;\n }\n\n if (lastFilter) {\n request.filter[1] = lastFilter;\n }\n });\n\n indexer.hooks.hook(\"connect:factory\", ({ request, endCursor }) => {\n if (request.filter[1]) {\n lastCursor = endCursor;\n lastFilter = request.filter[1];\n }\n });\n\n indexer.hooks.hook(\"handler:middleware\", ({ use }) => {\n use(async (context, next) => {\n await next();\n if (context.endCursor && isCursor(context.endCursor)) {\n lastCursor = context.endCursor;\n }\n });\n });\n });\n}\n"],"names":["defineIndexerPlugin","isCursor"],"mappings":";;;;;;;;;AAOO,SAAS,mBAAuC,GAAA;AACrD,EAAO,OAAAA,0BAAA,CAAqC,CAAC,OAAY,KAAA;AACvD,IAAI,IAAA,UAAA,CAAA;AACJ,IAAI,IAAA,UAAA,CAAA;AAEJ,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,gBAAA,EAAkB,CAAC,EAAE,SAAc,KAAA;AACpD,MAAA,IAAI,UAAY,EAAA;AACd,QAAA,OAAA,CAAQ,cAAiB,GAAA,UAAA,CAAA;AAAA,OAC3B;AAEA,MAAA,IAAI,UAAY,EAAA;AACd,QAAQ,OAAA,CAAA,MAAA,CAAO,CAAC,CAAI,GAAA,UAAA,CAAA;AAAA,OACtB;AAAA,KACD,CAAA,CAAA;AAED,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,iBAAA,EAAmB,CAAC,EAAE,OAAA,EAAS,WAAgB,KAAA;AAChE,MAAI,IAAA,OAAA,CAAQ,MAAO,CAAA,CAAC,CAAG,EAAA;AACrB,QAAa,UAAA,GAAA,SAAA,CAAA;AACb,QAAa,UAAA,GAAA,OAAA,CAAQ,OAAO,CAAC,CAAA,CAAA;AAAA,OAC/B;AAAA,KACD,CAAA,CAAA;AAED,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,oBAAA,EAAsB,CAAC,EAAE,KAAU,KAAA;AACpD,MAAI,GAAA,CAAA,OAAO,SAAS,IAAS,KAAA;AAC3B,QAAA,MAAM,IAAK,EAAA,CAAA;AACX,QAAA,IAAI,OAAQ,CAAA,SAAA,IAAaC,iBAAS,CAAA,OAAA,CAAQ,SAAS,CAAG,EAAA;AACpD,UAAA,UAAA,GAAa,OAAQ,CAAA,SAAA,CAAA;AAAA,SACvB;AAAA,OACD,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH;;;;;;;"}
@@ -1,5 +1,5 @@
1
- import { b as IndexerPlugin } from '../shared/indexer.7668fe34.cjs';
2
- export { d as defineIndexerPlugin } from '../shared/indexer.7668fe34.cjs';
1
+ import { b as IndexerPlugin } from '../shared/indexer.27b29a67.cjs';
2
+ export { d as defineIndexerPlugin } from '../shared/indexer.27b29a67.cjs';
3
3
  import { ConsolaReporter, ConsolaInstance } from 'consola';
4
4
  export { ConsolaInstance, ConsolaReporter } from 'consola';
5
5
  import '@apibara/protocol';
@@ -1,5 +1,5 @@
1
- import { b as IndexerPlugin } from '../shared/indexer.7668fe34.mjs';
2
- export { d as defineIndexerPlugin } from '../shared/indexer.7668fe34.mjs';
1
+ import { b as IndexerPlugin } from '../shared/indexer.27b29a67.mjs';
2
+ export { d as defineIndexerPlugin } from '../shared/indexer.27b29a67.mjs';
3
3
  import { ConsolaReporter, ConsolaInstance } from 'consola';
4
4
  export { ConsolaInstance, ConsolaReporter } from 'consola';
5
5
  import '@apibara/protocol';
@@ -1,5 +1,5 @@
1
- import { b as IndexerPlugin } from '../shared/indexer.7668fe34.js';
2
- export { d as defineIndexerPlugin } from '../shared/indexer.7668fe34.js';
1
+ import { b as IndexerPlugin } from '../shared/indexer.27b29a67.js';
2
+ export { d as defineIndexerPlugin } from '../shared/indexer.27b29a67.js';
3
3
  import { ConsolaReporter, ConsolaInstance } from 'consola';
4
4
  export { ConsolaInstance, ConsolaReporter } from 'consola';
5
5
  import '@apibara/protocol';
@@ -35,3 +35,4 @@ function inMemoryPersistence() {
35
35
  }
36
36
 
37
37
  export { defineIndexerPlugin, inMemoryPersistence };
38
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/plugins/persistence.ts"],"sourcesContent":["import { type Cursor, isCursor } from \"@apibara/protocol\";\n\nimport { defineIndexerPlugin } from \"./config\";\n\n/**\n * A plugin that persists the last cursor and filter to memory.\n */\nexport function inMemoryPersistence<TFilter, TBlock>() {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n let lastCursor: Cursor | undefined;\n let lastFilter: TFilter | undefined;\n\n indexer.hooks.hook(\"connect:before\", ({ request }) => {\n if (lastCursor) {\n request.startingCursor = lastCursor;\n }\n\n if (lastFilter) {\n request.filter[1] = lastFilter;\n }\n });\n\n indexer.hooks.hook(\"connect:factory\", ({ request, endCursor }) => {\n if (request.filter[1]) {\n lastCursor = endCursor;\n lastFilter = request.filter[1];\n }\n });\n\n indexer.hooks.hook(\"handler:middleware\", ({ use }) => {\n use(async (context, next) => {\n await next();\n if (context.endCursor && isCursor(context.endCursor)) {\n lastCursor = context.endCursor;\n }\n });\n });\n });\n}\n"],"names":[],"mappings":";;;;;;;AAOO,SAAS,mBAAuC,GAAA;AACrD,EAAO,OAAA,mBAAA,CAAqC,CAAC,OAAY,KAAA;AACvD,IAAI,IAAA,UAAA,CAAA;AACJ,IAAI,IAAA,UAAA,CAAA;AAEJ,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,gBAAA,EAAkB,CAAC,EAAE,SAAc,KAAA;AACpD,MAAA,IAAI,UAAY,EAAA;AACd,QAAA,OAAA,CAAQ,cAAiB,GAAA,UAAA,CAAA;AAAA,OAC3B;AAEA,MAAA,IAAI,UAAY,EAAA;AACd,QAAQ,OAAA,CAAA,MAAA,CAAO,CAAC,CAAI,GAAA,UAAA,CAAA;AAAA,OACtB;AAAA,KACD,CAAA,CAAA;AAED,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,iBAAA,EAAmB,CAAC,EAAE,OAAA,EAAS,WAAgB,KAAA;AAChE,MAAI,IAAA,OAAA,CAAQ,MAAO,CAAA,CAAC,CAAG,EAAA;AACrB,QAAa,UAAA,GAAA,SAAA,CAAA;AACb,QAAa,UAAA,GAAA,OAAA,CAAQ,OAAO,CAAC,CAAA,CAAA;AAAA,OAC/B;AAAA,KACD,CAAA,CAAA;AAED,IAAA,OAAA,CAAQ,MAAM,IAAK,CAAA,oBAAA,EAAsB,CAAC,EAAE,KAAU,KAAA;AACpD,MAAI,GAAA,CAAA,OAAO,SAAS,IAAS,KAAA;AAC3B,QAAA,MAAM,IAAK,EAAA,CAAA;AACX,QAAA,IAAI,OAAQ,CAAA,SAAA,IAAa,QAAS,CAAA,OAAA,CAAQ,SAAS,CAAG,EAAA;AACpD,UAAA,UAAA,GAAa,OAAQ,CAAA,SAAA,CAAA;AAAA,SACvB;AAAA,OACD,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH;;;;"}
@@ -1,4 +1,4 @@
1
- import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, SystemMessage, DataFinality, StreamConfig, Client } from '@apibara/protocol';
1
+ import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, SystemMessage, DataFinality, CreateClientOptions, StreamConfig, Client } from '@apibara/protocol';
2
2
  import { NestedHooks, Hookable } from 'hookable';
3
3
 
4
4
  interface IndexerContext extends Record<string, any> {
@@ -57,6 +57,7 @@ type IndexerConfig<TFilter, TBlock> = {
57
57
  streamUrl: string;
58
58
  filter: TFilter;
59
59
  finality?: DataFinality;
60
+ clientOptions?: CreateClientOptions;
60
61
  factory?: ({ block, context, }: {
61
62
  block: TBlock;
62
63
  context: IndexerContext;
@@ -1,4 +1,4 @@
1
- import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, SystemMessage, DataFinality, StreamConfig, Client } from '@apibara/protocol';
1
+ import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, SystemMessage, DataFinality, CreateClientOptions, StreamConfig, Client } from '@apibara/protocol';
2
2
  import { NestedHooks, Hookable } from 'hookable';
3
3
 
4
4
  interface IndexerContext extends Record<string, any> {
@@ -57,6 +57,7 @@ type IndexerConfig<TFilter, TBlock> = {
57
57
  streamUrl: string;
58
58
  filter: TFilter;
59
59
  finality?: DataFinality;
60
+ clientOptions?: CreateClientOptions;
60
61
  factory?: ({ block, context, }: {
61
62
  block: TBlock;
62
63
  context: IndexerContext;
@@ -1,4 +1,4 @@
1
- import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, SystemMessage, DataFinality, StreamConfig, Client } from '@apibara/protocol';
1
+ import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, SystemMessage, DataFinality, CreateClientOptions, StreamConfig, Client } from '@apibara/protocol';
2
2
  import { NestedHooks, Hookable } from 'hookable';
3
3
 
4
4
  interface IndexerContext extends Record<string, any> {
@@ -57,6 +57,7 @@ type IndexerConfig<TFilter, TBlock> = {
57
57
  streamUrl: string;
58
58
  filter: TFilter;
59
59
  finality?: DataFinality;
60
+ clientOptions?: CreateClientOptions;
60
61
  factory?: ({ block, context, }: {
61
62
  block: TBlock;
62
63
  context: IndexerContext;
@@ -18,3 +18,4 @@ function defineIndexerPlugin(def) {
18
18
  exports.defineIndexerPlugin = defineIndexerPlugin;
19
19
  exports.indexerAsyncContext = indexerAsyncContext;
20
20
  exports.useIndexerContext = useIndexerContext;
21
+ //# sourceMappingURL=indexer.479ae593.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.479ae593.cjs","sources":["../../src/context.ts","../../src/plugins/config.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Cursor, DataFinality } from \"@apibara/protocol\";\nimport { getContext } from \"unctx\";\n\n// biome-ignore lint/suspicious/noExplicitAny: context type\nexport interface IndexerContext extends Record<string, any> {}\n\nexport const indexerAsyncContext = getContext<IndexerContext>(\"indexer\", {\n asyncContext: true,\n AsyncLocalStorage,\n});\n\nexport function useIndexerContext() {\n return indexerAsyncContext.use() as IndexerContext;\n}\n\nexport interface MessageMetadataContext extends IndexerContext {\n cursor?: Cursor;\n endCursor?: Cursor;\n finality?: DataFinality;\n}\n\nexport function useMessageMetadataContext(): MessageMetadataContext {\n return useIndexerContext() as MessageMetadataContext;\n}\n","import type { Indexer } from \"../indexer\";\n\nexport type IndexerPlugin<TFilter, TBlock> = (\n indexer: Indexer<TFilter, TBlock>,\n) => void;\n\nexport function defineIndexerPlugin<TFilter, TBlock>(\n def: IndexerPlugin<TFilter, TBlock>,\n) {\n return def;\n}\n"],"names":["getContext","AsyncLocalStorage"],"mappings":";;;;;AAOa,MAAA,mBAAA,GAAsBA,iBAA2B,SAAW,EAAA;AAAA,EACvE,YAAc,EAAA,IAAA;AAAA,qBACdC,kCAAA;AACF,CAAC,EAAA;AAEM,SAAS,iBAAoB,GAAA;AAClC,EAAA,OAAO,oBAAoB,GAAI,EAAA,CAAA;AACjC;;ACRO,SAAS,oBACd,GACA,EAAA;AACA,EAAO,OAAA,GAAA,CAAA;AACT;;;;;;"}
@@ -14,3 +14,4 @@ function defineIndexerPlugin(def) {
14
14
  }
15
15
 
16
16
  export { defineIndexerPlugin as d, indexerAsyncContext as i, useIndexerContext as u };
17
+ //# sourceMappingURL=indexer.75773ef1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.75773ef1.mjs","sources":["../../src/context.ts","../../src/plugins/config.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Cursor, DataFinality } from \"@apibara/protocol\";\nimport { getContext } from \"unctx\";\n\n// biome-ignore lint/suspicious/noExplicitAny: context type\nexport interface IndexerContext extends Record<string, any> {}\n\nexport const indexerAsyncContext = getContext<IndexerContext>(\"indexer\", {\n asyncContext: true,\n AsyncLocalStorage,\n});\n\nexport function useIndexerContext() {\n return indexerAsyncContext.use() as IndexerContext;\n}\n\nexport interface MessageMetadataContext extends IndexerContext {\n cursor?: Cursor;\n endCursor?: Cursor;\n finality?: DataFinality;\n}\n\nexport function useMessageMetadataContext(): MessageMetadataContext {\n return useIndexerContext() as MessageMetadataContext;\n}\n","import type { Indexer } from \"../indexer\";\n\nexport type IndexerPlugin<TFilter, TBlock> = (\n indexer: Indexer<TFilter, TBlock>,\n) => void;\n\nexport function defineIndexerPlugin<TFilter, TBlock>(\n def: IndexerPlugin<TFilter, TBlock>,\n) {\n return def;\n}\n"],"names":[],"mappings":";;;AAOa,MAAA,mBAAA,GAAsB,WAA2B,SAAW,EAAA;AAAA,EACvE,YAAc,EAAA,IAAA;AAAA,EACd,iBAAA;AACF,CAAC,EAAA;AAEM,SAAS,iBAAoB,GAAA;AAClC,EAAA,OAAO,oBAAoB,GAAI,EAAA,CAAA;AACjC;;ACRO,SAAS,oBACd,GACA,EAAA;AACA,EAAO,OAAA,GAAA,CAAA;AACT;;;;"}
@@ -23,3 +23,4 @@ function useLogger() {
23
23
  }
24
24
 
25
25
  export { logger as l, useLogger as u };
26
+ //# sourceMappingURL=indexer.98a921a7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.98a921a7.mjs","sources":["../../src/plugins/logger.ts"],"sourcesContent":["import { type ConsolaInstance, type ConsolaReporter, consola } from \"consola\";\nimport { useIndexerContext } from \"../context\";\nimport { defineIndexerPlugin } from \"./config\";\n\nexport type { ConsolaReporter, ConsolaInstance } from \"consola\";\n\nexport function logger<TFilter, TBlock, TTxnParams>({\n logger,\n}: { logger?: ConsolaReporter } = {}) {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n indexer.hooks.hook(\"run:before\", () => {\n const ctx = useIndexerContext();\n\n if (logger) {\n ctx.logger = consola.create({ reporters: [logger] });\n } else {\n ctx.logger = consola.create({});\n }\n });\n });\n}\n\nexport function useLogger(): ConsolaInstance {\n const ctx = useIndexerContext();\n\n if (!ctx?.logger)\n throw new Error(\"Logger plugin is not available in context\");\n\n return ctx.logger;\n}\n"],"names":["logger"],"mappings":";;;AAMO,SAAS,MAAoC,CAAA;AAAA,EAClD,MAAAA,EAAAA,OAAAA;AACF,CAAA,GAAkC,EAAI,EAAA;AACpC,EAAO,OAAA,mBAAA,CAAqC,CAAC,OAAY,KAAA;AACvD,IAAQ,OAAA,CAAA,KAAA,CAAM,IAAK,CAAA,YAAA,EAAc,MAAM;AACrC,MAAA,MAAM,MAAM,iBAAkB,EAAA,CAAA;AAE9B,MAAA,IAAIA,OAAQ,EAAA;AACV,QAAI,GAAA,CAAA,MAAA,GAAS,QAAQ,MAAO,CAAA,EAAE,WAAW,CAACA,OAAM,GAAG,CAAA,CAAA;AAAA,OAC9C,MAAA;AACL,QAAA,GAAA,CAAI,MAAS,GAAA,OAAA,CAAQ,MAAO,CAAA,EAAE,CAAA,CAAA;AAAA,OAChC;AAAA,KACD,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH,CAAA;AAEO,SAAS,SAA6B,GAAA;AAC3C,EAAA,MAAM,MAAM,iBAAkB,EAAA,CAAA;AAE9B,EAAA,IAAI,CAAC,GAAK,EAAA,MAAA;AACR,IAAM,MAAA,IAAI,MAAM,2CAA2C,CAAA,CAAA;AAE7D,EAAA,OAAO,GAAI,CAAA,MAAA,CAAA;AACb;;;;"}
@@ -26,3 +26,4 @@ function useLogger() {
26
26
 
27
27
  exports.logger = logger;
28
28
  exports.useLogger = useLogger;
29
+ //# sourceMappingURL=indexer.a09fa402.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.a09fa402.cjs","sources":["../../src/plugins/logger.ts"],"sourcesContent":["import { type ConsolaInstance, type ConsolaReporter, consola } from \"consola\";\nimport { useIndexerContext } from \"../context\";\nimport { defineIndexerPlugin } from \"./config\";\n\nexport type { ConsolaReporter, ConsolaInstance } from \"consola\";\n\nexport function logger<TFilter, TBlock, TTxnParams>({\n logger,\n}: { logger?: ConsolaReporter } = {}) {\n return defineIndexerPlugin<TFilter, TBlock>((indexer) => {\n indexer.hooks.hook(\"run:before\", () => {\n const ctx = useIndexerContext();\n\n if (logger) {\n ctx.logger = consola.create({ reporters: [logger] });\n } else {\n ctx.logger = consola.create({});\n }\n });\n });\n}\n\nexport function useLogger(): ConsolaInstance {\n const ctx = useIndexerContext();\n\n if (!ctx?.logger)\n throw new Error(\"Logger plugin is not available in context\");\n\n return ctx.logger;\n}\n"],"names":["logger","defineIndexerPlugin","useIndexerContext","consola"],"mappings":";;;;;AAMO,SAAS,MAAoC,CAAA;AAAA,EAClD,MAAAA,EAAAA,OAAAA;AACF,CAAA,GAAkC,EAAI,EAAA;AACpC,EAAO,OAAAC,0BAAA,CAAqC,CAAC,OAAY,KAAA;AACvD,IAAQ,OAAA,CAAA,KAAA,CAAM,IAAK,CAAA,YAAA,EAAc,MAAM;AACrC,MAAA,MAAM,MAAMC,wBAAkB,EAAA,CAAA;AAE9B,MAAA,IAAIF,OAAQ,EAAA;AACV,QAAI,GAAA,CAAA,MAAA,GAASG,gBAAQ,MAAO,CAAA,EAAE,WAAW,CAACH,OAAM,GAAG,CAAA,CAAA;AAAA,OAC9C,MAAA;AACL,QAAA,GAAA,CAAI,MAAS,GAAAG,eAAA,CAAQ,MAAO,CAAA,EAAE,CAAA,CAAA;AAAA,OAChC;AAAA,KACD,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH,CAAA;AAEO,SAAS,SAA6B,GAAA;AAC3C,EAAA,MAAM,MAAMD,wBAAkB,EAAA,CAAA;AAE9B,EAAA,IAAI,CAAC,GAAK,EAAA,MAAA;AACR,IAAM,MAAA,IAAI,MAAM,2CAA2C,CAAA,CAAA;AAE7D,EAAA,OAAO,GAAI,CAAA,MAAA,CAAA;AACb;;;;;"}
@@ -68,3 +68,4 @@ function createVcr() {
68
68
  }
69
69
 
70
70
  exports.createVcr = createVcr;
71
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/testing/index.ts"],"sourcesContent":["import { createClient } from \"@apibara/protocol\";\nimport ci from \"ci-info\";\nimport { useIndexerContext } from \"../context\";\nimport { type IndexerWithStreamConfig, createIndexer } from \"../indexer\";\nimport { type InternalContext, internalContext } from \"../plugins/context\";\nimport { logger } from \"../plugins/logger\";\nimport type { CassetteOptions, VcrConfig } from \"../vcr/config\";\nimport { isCassetteAvailable } from \"../vcr/helper\";\nimport { record } from \"../vcr/record\";\nimport { replay } from \"../vcr/replay\";\n\nexport type VcrResult = Record<string, unknown>;\n\nexport function createVcr() {\n let result: VcrResult;\n\n return {\n async run<TFilter, TBlock>(\n cassetteName: string,\n indexerConfig: IndexerWithStreamConfig<TFilter, TBlock>,\n range: { fromBlock: bigint; toBlock: bigint },\n ) {\n const vcrConfig: VcrConfig = {\n cassetteDir: \"cassettes\",\n };\n\n const cassetteOptions: CassetteOptions = {\n name: cassetteName,\n startingCursor: {\n orderKey: range.fromBlock,\n },\n endingCursor: {\n orderKey: range.toBlock,\n },\n };\n\n indexerConfig.plugins = [\n internalContext({\n indexerName: cassetteName,\n availableIndexers: [cassetteName],\n } as InternalContext),\n logger(),\n ...(indexerConfig.plugins ?? []),\n ];\n\n const indexer = createIndexer(indexerConfig);\n\n indexer.hooks.hook(\"run:after\", () => {\n result = useIndexerContext();\n });\n\n if (!isCassetteAvailable(vcrConfig, cassetteName)) {\n if (ci.isCI) {\n throw new Error(\"Cannot record cassette in CI\");\n }\n\n const client = createClient(\n indexer.streamConfig,\n indexer.options.streamUrl,\n );\n await record(vcrConfig, client, indexer, cassetteOptions);\n } else {\n await replay(vcrConfig, indexer, cassetteName);\n }\n\n return result;\n },\n };\n}\n"],"names":["internalContext","logger","createIndexer","useIndexerContext","isCassetteAvailable","ci","createClient","record","replay"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAaO,SAAS,SAAY,GAAA;AAC1B,EAAI,IAAA,MAAA,CAAA;AAEJ,EAAO,OAAA;AAAA,IACL,MAAM,GAAA,CACJ,YACA,EAAA,aAAA,EACA,KACA,EAAA;AACA,MAAA,MAAM,SAAuB,GAAA;AAAA,QAC3B,WAAa,EAAA,WAAA;AAAA,OACf,CAAA;AAEA,MAAA,MAAM,eAAmC,GAAA;AAAA,QACvC,IAAM,EAAA,YAAA;AAAA,QACN,cAAgB,EAAA;AAAA,UACd,UAAU,KAAM,CAAA,SAAA;AAAA,SAClB;AAAA,QACA,YAAc,EAAA;AAAA,UACZ,UAAU,KAAM,CAAA,OAAA;AAAA,SAClB;AAAA,OACF,CAAA;AAEA,MAAA,aAAA,CAAc,OAAU,GAAA;AAAA,QACtBA,gCAAgB,CAAA;AAAA,UACd,WAAa,EAAA,YAAA;AAAA,UACb,iBAAA,EAAmB,CAAC,YAAY,CAAA;AAAA,SACd,CAAA;AAAA,QACpBC,aAAO,EAAA;AAAA,QACP,GAAI,aAAc,CAAA,OAAA,IAAW,EAAC;AAAA,OAChC,CAAA;AAEA,MAAM,MAAA,OAAA,GAAUC,oBAAc,aAAa,CAAA,CAAA;AAE3C,MAAQ,OAAA,CAAA,KAAA,CAAM,IAAK,CAAA,WAAA,EAAa,MAAM;AACpC,QAAA,MAAA,GAASC,wBAAkB,EAAA,CAAA;AAAA,OAC5B,CAAA,CAAA;AAED,MAAA,IAAI,CAACC,6BAAA,CAAoB,SAAW,EAAA,YAAY,CAAG,EAAA;AACjD,QAAA,IAAIC,YAAG,IAAM,EAAA;AACX,UAAM,MAAA,IAAI,MAAM,8BAA8B,CAAA,CAAA;AAAA,SAChD;AAEA,QAAA,MAAM,MAAS,GAAAC,qBAAA;AAAA,UACb,OAAQ,CAAA,YAAA;AAAA,UACR,QAAQ,OAAQ,CAAA,SAAA;AAAA,SAClB,CAAA;AACA,QAAA,MAAMC,gBAAO,CAAA,SAAA,EAAW,MAAQ,EAAA,OAAA,EAAS,eAAe,CAAA,CAAA;AAAA,OACnD,MAAA;AACL,QAAM,MAAAC,gBAAA,CAAO,SAAW,EAAA,OAAA,EAAS,YAAY,CAAA,CAAA;AAAA,OAC/C;AAEA,MAAO,OAAA,MAAA,CAAA;AAAA,KACT;AAAA,GACF,CAAA;AACF;;;;"}
@@ -1,4 +1,4 @@
1
- import { I as IndexerWithStreamConfig } from '../shared/indexer.7668fe34.cjs';
1
+ import { I as IndexerWithStreamConfig } from '../shared/indexer.27b29a67.cjs';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
4
4
 
@@ -1,4 +1,4 @@
1
- import { I as IndexerWithStreamConfig } from '../shared/indexer.7668fe34.mjs';
1
+ import { I as IndexerWithStreamConfig } from '../shared/indexer.27b29a67.mjs';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
4
4
 
@@ -1,4 +1,4 @@
1
- import { I as IndexerWithStreamConfig } from '../shared/indexer.7668fe34.js';
1
+ import { I as IndexerWithStreamConfig } from '../shared/indexer.27b29a67.js';
2
2
  import '@apibara/protocol';
3
3
  import 'hookable';
4
4
 
@@ -62,3 +62,4 @@ function createVcr() {
62
62
  }
63
63
 
64
64
  export { createVcr };
65
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/testing/index.ts"],"sourcesContent":["import { createClient } from \"@apibara/protocol\";\nimport ci from \"ci-info\";\nimport { useIndexerContext } from \"../context\";\nimport { type IndexerWithStreamConfig, createIndexer } from \"../indexer\";\nimport { type InternalContext, internalContext } from \"../plugins/context\";\nimport { logger } from \"../plugins/logger\";\nimport type { CassetteOptions, VcrConfig } from \"../vcr/config\";\nimport { isCassetteAvailable } from \"../vcr/helper\";\nimport { record } from \"../vcr/record\";\nimport { replay } from \"../vcr/replay\";\n\nexport type VcrResult = Record<string, unknown>;\n\nexport function createVcr() {\n let result: VcrResult;\n\n return {\n async run<TFilter, TBlock>(\n cassetteName: string,\n indexerConfig: IndexerWithStreamConfig<TFilter, TBlock>,\n range: { fromBlock: bigint; toBlock: bigint },\n ) {\n const vcrConfig: VcrConfig = {\n cassetteDir: \"cassettes\",\n };\n\n const cassetteOptions: CassetteOptions = {\n name: cassetteName,\n startingCursor: {\n orderKey: range.fromBlock,\n },\n endingCursor: {\n orderKey: range.toBlock,\n },\n };\n\n indexerConfig.plugins = [\n internalContext({\n indexerName: cassetteName,\n availableIndexers: [cassetteName],\n } as InternalContext),\n logger(),\n ...(indexerConfig.plugins ?? []),\n ];\n\n const indexer = createIndexer(indexerConfig);\n\n indexer.hooks.hook(\"run:after\", () => {\n result = useIndexerContext();\n });\n\n if (!isCassetteAvailable(vcrConfig, cassetteName)) {\n if (ci.isCI) {\n throw new Error(\"Cannot record cassette in CI\");\n }\n\n const client = createClient(\n indexer.streamConfig,\n indexer.options.streamUrl,\n );\n await record(vcrConfig, client, indexer, cassetteOptions);\n } else {\n await replay(vcrConfig, indexer, cassetteName);\n }\n\n return result;\n },\n };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAaO,SAAS,SAAY,GAAA;AAC1B,EAAI,IAAA,MAAA,CAAA;AAEJ,EAAO,OAAA;AAAA,IACL,MAAM,GAAA,CACJ,YACA,EAAA,aAAA,EACA,KACA,EAAA;AACA,MAAA,MAAM,SAAuB,GAAA;AAAA,QAC3B,WAAa,EAAA,WAAA;AAAA,OACf,CAAA;AAEA,MAAA,MAAM,eAAmC,GAAA;AAAA,QACvC,IAAM,EAAA,YAAA;AAAA,QACN,cAAgB,EAAA;AAAA,UACd,UAAU,KAAM,CAAA,SAAA;AAAA,SAClB;AAAA,QACA,YAAc,EAAA;AAAA,UACZ,UAAU,KAAM,CAAA,OAAA;AAAA,SAClB;AAAA,OACF,CAAA;AAEA,MAAA,aAAA,CAAc,OAAU,GAAA;AAAA,QACtB,eAAgB,CAAA;AAAA,UACd,WAAa,EAAA,YAAA;AAAA,UACb,iBAAA,EAAmB,CAAC,YAAY,CAAA;AAAA,SACd,CAAA;AAAA,QACpB,MAAO,EAAA;AAAA,QACP,GAAI,aAAc,CAAA,OAAA,IAAW,EAAC;AAAA,OAChC,CAAA;AAEA,MAAM,MAAA,OAAA,GAAU,cAAc,aAAa,CAAA,CAAA;AAE3C,MAAQ,OAAA,CAAA,KAAA,CAAM,IAAK,CAAA,WAAA,EAAa,MAAM;AACpC,QAAA,MAAA,GAAS,iBAAkB,EAAA,CAAA;AAAA,OAC5B,CAAA,CAAA;AAED,MAAA,IAAI,CAAC,mBAAA,CAAoB,SAAW,EAAA,YAAY,CAAG,EAAA;AACjD,QAAA,IAAI,GAAG,IAAM,EAAA;AACX,UAAM,MAAA,IAAI,MAAM,8BAA8B,CAAA,CAAA;AAAA,SAChD;AAEA,QAAA,MAAM,MAAS,GAAA,YAAA;AAAA,UACb,OAAQ,CAAA,YAAA;AAAA,UACR,QAAQ,OAAQ,CAAA,SAAA;AAAA,SAClB,CAAA;AACA,QAAA,MAAM,MAAO,CAAA,SAAA,EAAW,MAAQ,EAAA,OAAA,EAAS,eAAe,CAAA,CAAA;AAAA,OACnD,MAAA;AACL,QAAM,MAAA,MAAA,CAAO,SAAW,EAAA,OAAA,EAAS,YAAY,CAAA,CAAA;AAAA,OAC/C;AAEA,MAAO,OAAA,MAAA,CAAA;AAAA,KACT;AAAA,GACF,CAAA;AACF;;;;"}
@@ -91,3 +91,4 @@ exports.loadCassette = loadCassette;
91
91
  exports.record = record;
92
92
  exports.replay = replay;
93
93
  exports.serialize = serialize;
94
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/vcr/helper.ts","../../src/vcr/record.ts","../../src/vcr/replay.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { VcrConfig } from \"./config\";\n\nexport function deserialize(str: string) {\n return JSON.parse(str, (_, value) =>\n typeof value === \"string\" && value.match(/^\\d+n$/)\n ? BigInt(value.slice(0, -1))\n : value,\n );\n}\n\nexport function serialize(obj: Record<string, unknown>): string {\n return JSON.stringify(\n obj,\n (_, value) => (typeof value === \"bigint\" ? `${value.toString()}n` : value),\n \"\\t\",\n );\n}\n\nexport function isCassetteAvailable(\n vcrConfig: VcrConfig,\n cassetteName: string,\n): boolean {\n const filePath = path.join(vcrConfig.cassetteDir, `${cassetteName}.json`);\n return fs.existsSync(filePath);\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Client, StreamDataResponse } from \"@apibara/protocol\";\nimport { type Indexer, run } from \"../indexer\";\nimport type { CassetteOptions, VcrConfig } from \"./config\";\nimport { serialize } from \"./helper\";\n\nexport type CassetteDataType<TFilter, TBlock> = {\n filter: TFilter;\n messages: StreamDataResponse<TBlock>[];\n};\n\nexport async function record<TFilter, TBlock, TTxnParams>(\n vcrConfig: VcrConfig,\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n cassetteOptions: CassetteOptions,\n) {\n const messages: StreamDataResponse<TBlock>[] = [];\n\n indexer.hooks.addHooks({\n \"connect:before\"({ options, request }) {\n request.startingCursor = cassetteOptions.startingCursor;\n options.endingCursor = cassetteOptions.endingCursor;\n },\n message({ message }) {\n messages.push(message);\n },\n async \"run:after\"() {\n const output: CassetteDataType<TFilter, TBlock> = {\n filter: indexer.options.filter,\n messages: messages,\n };\n\n await fs.mkdir(vcrConfig.cassetteDir, { recursive: true });\n\n const filePath = path.join(\n vcrConfig.cassetteDir,\n `${cassetteOptions.name}.json`,\n );\n\n await fs.writeFile(filePath, serialize(output), { flag: \"w\" });\n },\n });\n\n await run(client, indexer);\n}\n","import assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { Client } from \"@apibara/protocol\";\nimport { MockClient } from \"@apibara/protocol/testing\";\nimport { type Indexer, run } from \"../indexer\";\nimport { type CassetteDataType, deserialize } from \"../vcr\";\nimport type { VcrConfig } from \"./config\";\n\nexport async function replay<TFilter, TBlock, TTxnParams>(\n vcrConfig: VcrConfig,\n indexer: Indexer<TFilter, TBlock>,\n cassetteName: string,\n) {\n const client = loadCassette<TFilter, TBlock>(vcrConfig, cassetteName);\n await run(client, indexer);\n}\n\nexport function loadCassette<TFilter, TBlock>(\n vcrConfig: VcrConfig,\n cassetteName: string,\n): Client<TFilter, TBlock> {\n const filePath = path.join(vcrConfig.cassetteDir, `${cassetteName}.json`);\n\n const data = fs.readFileSync(filePath, \"utf8\");\n const cassetteData: CassetteDataType<TFilter, TBlock> = deserialize(data);\n\n const { filter, messages } = cassetteData;\n\n return new MockClient<TFilter, TBlock>((request, options) => {\n // Notice that the request filter is an array of filters,\n // so we need to wrap the indexer filter in an array.\n assert.deepStrictEqual(\n request.filter,\n [filter],\n \"Indexer and cassette filter mismatch. Hint: delete the cassette and run again.\",\n );\n\n return messages;\n });\n}\n"],"names":["path","fs","run","MockClient","assert"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Cursor, StreamDataResponse, Client } from '@apibara/protocol';
2
- import { a as Indexer } from '../shared/indexer.7668fe34.cjs';
2
+ import { a as Indexer } from '../shared/indexer.27b29a67.cjs';
3
3
  import 'hookable';
4
4
 
5
5
  type VcrConfig = {
@@ -1,5 +1,5 @@
1
1
  import { Cursor, StreamDataResponse, Client } from '@apibara/protocol';
2
- import { a as Indexer } from '../shared/indexer.7668fe34.mjs';
2
+ import { a as Indexer } from '../shared/indexer.27b29a67.mjs';
3
3
  import 'hookable';
4
4
 
5
5
  type VcrConfig = {
@@ -1,5 +1,5 @@
1
1
  import { Cursor, StreamDataResponse, Client } from '@apibara/protocol';
2
- import { a as Indexer } from '../shared/indexer.7668fe34.js';
2
+ import { a as Indexer } from '../shared/indexer.27b29a67.js';
3
3
  import 'hookable';
4
4
 
5
5
  type VcrConfig = {
@@ -77,3 +77,4 @@ function loadCassette(vcrConfig, cassetteName) {
77
77
  }
78
78
 
79
79
  export { deserialize, isCassetteAvailable, loadCassette, record, replay, serialize };
80
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/vcr/helper.ts","../../src/vcr/record.ts","../../src/vcr/replay.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { VcrConfig } from \"./config\";\n\nexport function deserialize(str: string) {\n return JSON.parse(str, (_, value) =>\n typeof value === \"string\" && value.match(/^\\d+n$/)\n ? BigInt(value.slice(0, -1))\n : value,\n );\n}\n\nexport function serialize(obj: Record<string, unknown>): string {\n return JSON.stringify(\n obj,\n (_, value) => (typeof value === \"bigint\" ? `${value.toString()}n` : value),\n \"\\t\",\n );\n}\n\nexport function isCassetteAvailable(\n vcrConfig: VcrConfig,\n cassetteName: string,\n): boolean {\n const filePath = path.join(vcrConfig.cassetteDir, `${cassetteName}.json`);\n return fs.existsSync(filePath);\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Client, StreamDataResponse } from \"@apibara/protocol\";\nimport { type Indexer, run } from \"../indexer\";\nimport type { CassetteOptions, VcrConfig } from \"./config\";\nimport { serialize } from \"./helper\";\n\nexport type CassetteDataType<TFilter, TBlock> = {\n filter: TFilter;\n messages: StreamDataResponse<TBlock>[];\n};\n\nexport async function record<TFilter, TBlock, TTxnParams>(\n vcrConfig: VcrConfig,\n client: Client<TFilter, TBlock>,\n indexer: Indexer<TFilter, TBlock>,\n cassetteOptions: CassetteOptions,\n) {\n const messages: StreamDataResponse<TBlock>[] = [];\n\n indexer.hooks.addHooks({\n \"connect:before\"({ options, request }) {\n request.startingCursor = cassetteOptions.startingCursor;\n options.endingCursor = cassetteOptions.endingCursor;\n },\n message({ message }) {\n messages.push(message);\n },\n async \"run:after\"() {\n const output: CassetteDataType<TFilter, TBlock> = {\n filter: indexer.options.filter,\n messages: messages,\n };\n\n await fs.mkdir(vcrConfig.cassetteDir, { recursive: true });\n\n const filePath = path.join(\n vcrConfig.cassetteDir,\n `${cassetteOptions.name}.json`,\n );\n\n await fs.writeFile(filePath, serialize(output), { flag: \"w\" });\n },\n });\n\n await run(client, indexer);\n}\n","import assert from \"node:assert\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { Client } from \"@apibara/protocol\";\nimport { MockClient } from \"@apibara/protocol/testing\";\nimport { type Indexer, run } from \"../indexer\";\nimport { type CassetteDataType, deserialize } from \"../vcr\";\nimport type { VcrConfig } from \"./config\";\n\nexport async function replay<TFilter, TBlock, TTxnParams>(\n vcrConfig: VcrConfig,\n indexer: Indexer<TFilter, TBlock>,\n cassetteName: string,\n) {\n const client = loadCassette<TFilter, TBlock>(vcrConfig, cassetteName);\n await run(client, indexer);\n}\n\nexport function loadCassette<TFilter, TBlock>(\n vcrConfig: VcrConfig,\n cassetteName: string,\n): Client<TFilter, TBlock> {\n const filePath = path.join(vcrConfig.cassetteDir, `${cassetteName}.json`);\n\n const data = fs.readFileSync(filePath, \"utf8\");\n const cassetteData: CassetteDataType<TFilter, TBlock> = deserialize(data);\n\n const { filter, messages } = cassetteData;\n\n return new MockClient<TFilter, TBlock>((request, options) => {\n // Notice that the request filter is an array of filters,\n // so we need to wrap the indexer filter in an array.\n assert.deepStrictEqual(\n request.filter,\n [filter],\n \"Indexer and cassette filter mismatch. Hint: delete the cassette and run again.\",\n );\n\n return messages;\n });\n}\n"],"names":["fs"],"mappings":";;;;;;;;;;;;;;;AAIO,SAAS,YAAY,GAAa,EAAA;AACvC,EAAA,OAAO,IAAK,CAAA,KAAA;AAAA,IAAM,GAAA;AAAA,IAAK,CAAC,CAAG,EAAA,KAAA,KACzB,OAAO,KAAA,KAAU,YAAY,KAAM,CAAA,KAAA,CAAM,QAAQ,CAAA,GAC7C,OAAO,KAAM,CAAA,KAAA,CAAM,CAAG,EAAA,CAAA,CAAE,CAAC,CACzB,GAAA,KAAA;AAAA,GACN,CAAA;AACF,CAAA;AAEO,SAAS,UAAU,GAAsC,EAAA;AAC9D,EAAA,OAAO,IAAK,CAAA,SAAA;AAAA,IACV,GAAA;AAAA,IACA,CAAC,CAAG,EAAA,KAAA,KAAW,OAAO,KAAA,KAAU,WAAW,CAAG,EAAA,KAAA,CAAM,QAAS,EAAC,CAAM,CAAA,CAAA,GAAA,KAAA;AAAA,IACpE,GAAA;AAAA,GACF,CAAA;AACF,CAAA;AAEgB,SAAA,mBAAA,CACd,WACA,YACS,EAAA;AACT,EAAA,MAAM,WAAW,IAAK,CAAA,IAAA,CAAK,UAAU,WAAa,EAAA,CAAA,EAAG,YAAY,CAAO,KAAA,CAAA,CAAA,CAAA;AACxE,EAAO,OAAA,EAAA,CAAG,WAAW,QAAQ,CAAA,CAAA;AAC/B;;ACdA,eAAsB,MACpB,CAAA,SAAA,EACA,MACA,EAAA,OAAA,EACA,eACA,EAAA;AACA,EAAA,MAAM,WAAyC,EAAC,CAAA;AAEhD,EAAA,OAAA,CAAQ,MAAM,QAAS,CAAA;AAAA,IACrB,gBAAiB,CAAA,EAAE,OAAS,EAAA,OAAA,EAAW,EAAA;AACrC,MAAA,OAAA,CAAQ,iBAAiB,eAAgB,CAAA,cAAA,CAAA;AACzC,MAAA,OAAA,CAAQ,eAAe,eAAgB,CAAA,YAAA,CAAA;AAAA,KACzC;AAAA,IACA,OAAA,CAAQ,EAAE,OAAA,EAAW,EAAA;AACnB,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA,CAAA;AAAA,KACvB;AAAA,IACA,MAAM,WAAc,GAAA;AAClB,MAAA,MAAM,MAA4C,GAAA;AAAA,QAChD,MAAA,EAAQ,QAAQ,OAAQ,CAAA,MAAA;AAAA,QACxB,QAAA;AAAA,OACF,CAAA;AAEA,MAAA,MAAMA,KAAG,KAAM,CAAA,SAAA,CAAU,aAAa,EAAE,SAAA,EAAW,MAAM,CAAA,CAAA;AAEzD,MAAA,MAAM,WAAW,IAAK,CAAA,IAAA;AAAA,QACpB,SAAU,CAAA,WAAA;AAAA,QACV,CAAA,EAAG,gBAAgB,IAAI,CAAA,KAAA,CAAA;AAAA,OACzB,CAAA;AAEA,MAAM,MAAAA,IAAA,CAAG,UAAU,QAAU,EAAA,SAAA,CAAU,MAAM,CAAG,EAAA,EAAE,IAAM,EAAA,GAAA,EAAK,CAAA,CAAA;AAAA,KAC/D;AAAA,GACD,CAAA,CAAA;AAED,EAAM,MAAA,GAAA,CAAI,QAAQ,OAAO,CAAA,CAAA;AAC3B;;ACrCsB,eAAA,MAAA,CACpB,SACA,EAAA,OAAA,EACA,YACA,EAAA;AACA,EAAM,MAAA,MAAA,GAAS,YAA8B,CAAA,SAAA,EAAW,YAAY,CAAA,CAAA;AACpE,EAAM,MAAA,GAAA,CAAI,QAAQ,OAAO,CAAA,CAAA;AAC3B,CAAA;AAEgB,SAAA,YAAA,CACd,WACA,YACyB,EAAA;AACzB,EAAA,MAAM,WAAW,IAAK,CAAA,IAAA,CAAK,UAAU,WAAa,EAAA,CAAA,EAAG,YAAY,CAAO,KAAA,CAAA,CAAA,CAAA;AAExE,EAAA,MAAM,IAAO,GAAA,EAAA,CAAG,YAAa,CAAA,QAAA,EAAU,MAAM,CAAA,CAAA;AAC7C,EAAM,MAAA,YAAA,GAAkD,YAAY,IAAI,CAAA,CAAA;AAExE,EAAM,MAAA,EAAE,MAAQ,EAAA,QAAA,EAAa,GAAA,YAAA,CAAA;AAE7B,EAAA,OAAO,IAAI,UAAA,CAA4B,CAAC,OAAA,EAAS,OAAY,KAAA;AAG3D,IAAO,MAAA,CAAA,eAAA;AAAA,MACL,OAAQ,CAAA,MAAA;AAAA,MACR,CAAC,MAAM,CAAA;AAAA,MACP,gFAAA;AAAA,KACF,CAAA;AAEA,IAAO,OAAA,QAAA,CAAA;AAAA,GACR,CAAA,CAAA;AACH;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apibara/indexer",
3
- "version": "2.1.0-beta.30",
3
+ "version": "2.1.0-beta.32",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -70,7 +70,7 @@
70
70
  "vitest": "^1.6.0"
71
71
  },
72
72
  "dependencies": {
73
- "@apibara/protocol": "2.1.0-beta.30",
73
+ "@apibara/protocol": "2.1.0-beta.32",
74
74
  "@opentelemetry/api": "^1.9.0",
75
75
  "ci-info": "^4.1.0",
76
76
  "consola": "^3.4.2",
package/src/indexer.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  type Client,
3
3
  ClientError,
4
+ type CreateClientOptions,
4
5
  type Cursor,
5
6
  type DataFinality,
6
7
  type Finalize,
@@ -82,6 +83,7 @@ export type IndexerConfig<TFilter, TBlock> = {
82
83
  streamUrl: string;
83
84
  filter: TFilter;
84
85
  finality?: DataFinality;
86
+ clientOptions?: CreateClientOptions;
85
87
  factory?: ({
86
88
  block,
87
89
  context,