@apibara/indexer 2.0.0-beta.3 → 2.0.0-beta.30

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 (74) hide show
  1. package/dist/index.cjs +270 -0
  2. package/dist/index.d.cts +3 -0
  3. package/dist/index.d.mts +3 -0
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.mjs +259 -0
  6. package/dist/internal/testing.cjs +109 -0
  7. package/dist/internal/testing.d.cts +40 -0
  8. package/dist/internal/testing.d.mts +40 -0
  9. package/dist/internal/testing.d.ts +40 -0
  10. package/dist/internal/testing.mjs +104 -0
  11. package/dist/plugins/index.cjs +43 -0
  12. package/dist/plugins/index.d.cts +18 -0
  13. package/dist/plugins/index.d.mts +18 -0
  14. package/dist/plugins/index.d.ts +18 -0
  15. package/dist/plugins/index.mjs +38 -0
  16. package/dist/shared/indexer.077335f3.cjs +15 -0
  17. package/dist/shared/indexer.2416906c.cjs +29 -0
  18. package/dist/shared/indexer.601ceab0.cjs +7 -0
  19. package/dist/shared/indexer.8939ecc8.d.cts +91 -0
  20. package/dist/shared/indexer.8939ecc8.d.mts +91 -0
  21. package/dist/shared/indexer.8939ecc8.d.ts +91 -0
  22. package/dist/shared/indexer.9b21ddd2.mjs +5 -0
  23. package/dist/shared/indexer.a55ad619.mjs +12 -0
  24. package/dist/shared/indexer.ff25c953.mjs +26 -0
  25. package/dist/testing/index.cjs +58 -0
  26. package/dist/testing/index.d.cts +12 -0
  27. package/dist/testing/index.d.mts +12 -0
  28. package/dist/testing/index.d.ts +12 -0
  29. package/dist/testing/index.mjs +52 -0
  30. package/dist/vcr/index.cjs +92 -0
  31. package/dist/vcr/index.d.cts +27 -0
  32. package/dist/vcr/index.d.mts +27 -0
  33. package/dist/vcr/index.d.ts +27 -0
  34. package/dist/vcr/index.mjs +78 -0
  35. package/package.json +31 -41
  36. package/src/compose.test.ts +76 -0
  37. package/src/compose.ts +71 -0
  38. package/src/context.ts +14 -8
  39. package/src/index.ts +0 -5
  40. package/src/indexer.test.ts +109 -186
  41. package/src/indexer.ts +244 -144
  42. package/src/internal/testing.ts +135 -0
  43. package/src/plugins/config.ts +4 -4
  44. package/src/plugins/index.ts +8 -1
  45. package/src/plugins/logger.ts +30 -0
  46. package/src/plugins/persistence.ts +24 -187
  47. package/src/testing/index.ts +50 -3
  48. package/src/vcr/record.ts +6 -4
  49. package/src/vcr/replay.ts +8 -18
  50. package/src/hooks/index.ts +0 -2
  51. package/src/hooks/useKVStore.ts +0 -12
  52. package/src/hooks/useSink.ts +0 -13
  53. package/src/plugins/kv.test.ts +0 -120
  54. package/src/plugins/kv.ts +0 -132
  55. package/src/plugins/persistence.test.ts +0 -151
  56. package/src/sink.ts +0 -36
  57. package/src/sinks/csv.test.ts +0 -65
  58. package/src/sinks/csv.ts +0 -159
  59. package/src/sinks/drizzle/Int8Range.ts +0 -52
  60. package/src/sinks/drizzle/delete.ts +0 -42
  61. package/src/sinks/drizzle/drizzle.test.ts +0 -239
  62. package/src/sinks/drizzle/drizzle.ts +0 -115
  63. package/src/sinks/drizzle/index.ts +0 -6
  64. package/src/sinks/drizzle/insert.ts +0 -39
  65. package/src/sinks/drizzle/select.ts +0 -44
  66. package/src/sinks/drizzle/transaction.ts +0 -49
  67. package/src/sinks/drizzle/update.ts +0 -47
  68. package/src/sinks/drizzle/utils.ts +0 -36
  69. package/src/sinks/sqlite.test.ts +0 -99
  70. package/src/sinks/sqlite.ts +0 -170
  71. package/src/testing/helper.ts +0 -13
  72. package/src/testing/indexer.ts +0 -35
  73. package/src/testing/setup.ts +0 -59
  74. package/src/testing/vcr.ts +0 -54
@@ -0,0 +1,40 @@
1
+ import { a as IndexerPlugin, b as IndexerConfig, c as Indexer } from '../shared/indexer.8939ecc8.mjs';
2
+ import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
3
+ import '@apibara/protocol';
4
+ import 'hookable';
5
+
6
+ type MockMessagesOptions = {
7
+ invalidate?: {
8
+ invalidateFromIndex: number;
9
+ invalidateTriggerIndex: number;
10
+ };
11
+ finalize?: {
12
+ finalizeToIndex: number;
13
+ finalizeTriggerIndex: number;
14
+ };
15
+ };
16
+ declare function generateMockMessages(count?: number, options?: MockMessagesOptions): MockStreamResponse[];
17
+ declare function getMockIndexer({ plugins, override, }?: {
18
+ plugins?: ReadonlyArray<IndexerPlugin<MockFilter, MockBlock>>;
19
+ override?: Partial<IndexerConfig<MockFilter, MockBlock>>;
20
+ }): Indexer<{
21
+ readonly filter?: string | undefined;
22
+ }, {
23
+ readonly data?: string | undefined;
24
+ }>;
25
+ type MockRet = {
26
+ data: string;
27
+ };
28
+ /**
29
+ * A mock sink used for testing. The indexer function can write to the output array.
30
+ * The indexer context is optionally written to the metadata object.
31
+ */
32
+ declare function mockSink<TFilter, TBlock>({ output, metadata, }: {
33
+ output: unknown[];
34
+ metadata?: Record<string, unknown>;
35
+ }): IndexerPlugin<TFilter, TBlock>;
36
+ declare function useMockSink(): {
37
+ output: unknown[];
38
+ };
39
+
40
+ export { type MockMessagesOptions, type MockRet, generateMockMessages, getMockIndexer, mockSink, useMockSink };
@@ -0,0 +1,40 @@
1
+ import { a as IndexerPlugin, b as IndexerConfig, c as Indexer } from '../shared/indexer.8939ecc8.js';
2
+ import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
3
+ import '@apibara/protocol';
4
+ import 'hookable';
5
+
6
+ type MockMessagesOptions = {
7
+ invalidate?: {
8
+ invalidateFromIndex: number;
9
+ invalidateTriggerIndex: number;
10
+ };
11
+ finalize?: {
12
+ finalizeToIndex: number;
13
+ finalizeTriggerIndex: number;
14
+ };
15
+ };
16
+ declare function generateMockMessages(count?: number, options?: MockMessagesOptions): MockStreamResponse[];
17
+ declare function getMockIndexer({ plugins, override, }?: {
18
+ plugins?: ReadonlyArray<IndexerPlugin<MockFilter, MockBlock>>;
19
+ override?: Partial<IndexerConfig<MockFilter, MockBlock>>;
20
+ }): Indexer<{
21
+ readonly filter?: string | undefined;
22
+ }, {
23
+ readonly data?: string | undefined;
24
+ }>;
25
+ type MockRet = {
26
+ data: string;
27
+ };
28
+ /**
29
+ * A mock sink used for testing. The indexer function can write to the output array.
30
+ * The indexer context is optionally written to the metadata object.
31
+ */
32
+ declare function mockSink<TFilter, TBlock>({ output, metadata, }: {
33
+ output: unknown[];
34
+ metadata?: Record<string, unknown>;
35
+ }): IndexerPlugin<TFilter, TBlock>;
36
+ declare function useMockSink(): {
37
+ output: unknown[];
38
+ };
39
+
40
+ export { type MockMessagesOptions, type MockRet, generateMockMessages, getMockIndexer, mockSink, useMockSink };
@@ -0,0 +1,104 @@
1
+ import { isCursor } from '@apibara/protocol';
2
+ import { MockStream } from '@apibara/protocol/testing';
3
+ import { u as useIndexerContext } from '../shared/indexer.a55ad619.mjs';
4
+ import { createIndexer, defineIndexer } from '../index.mjs';
5
+ import { d as defineIndexerPlugin } from '../shared/indexer.9b21ddd2.mjs';
6
+ import 'consola';
7
+ import 'node:async_hooks';
8
+ import 'unctx';
9
+ import 'hookable';
10
+ import 'node:assert';
11
+ import '@opentelemetry/api';
12
+
13
+ function generateMockMessages(count = 10, options) {
14
+ const invalidateAt = options?.invalidate;
15
+ const finalizeAt = options?.finalize;
16
+ const messages = [];
17
+ for (let i = 0; i < count; i++) {
18
+ if (invalidateAt && i === invalidateAt.invalidateTriggerIndex) {
19
+ messages.push({
20
+ _tag: "invalidate",
21
+ invalidate: {
22
+ cursor: {
23
+ orderKey: BigInt(5e6 + invalidateAt.invalidateFromIndex)
24
+ }
25
+ }
26
+ });
27
+ } else if (finalizeAt && i === finalizeAt.finalizeTriggerIndex) {
28
+ messages.push({
29
+ _tag: "finalize",
30
+ finalize: {
31
+ cursor: {
32
+ orderKey: BigInt(5e6 + finalizeAt.finalizeToIndex)
33
+ }
34
+ }
35
+ });
36
+ } else {
37
+ messages.push({
38
+ _tag: "data",
39
+ data: {
40
+ cursor: { orderKey: BigInt(5e6 + i - 1) },
41
+ finality: "accepted",
42
+ data: [{ data: `${5e6 + i}` }],
43
+ endCursor: { orderKey: BigInt(5e6 + i) }
44
+ }
45
+ });
46
+ }
47
+ }
48
+ return messages;
49
+ }
50
+ function getMockIndexer({
51
+ plugins,
52
+ override
53
+ } = {}) {
54
+ return createIndexer(
55
+ defineIndexer(MockStream)({
56
+ streamUrl: "https://sepolia.ethereum.a5a.ch",
57
+ finality: "accepted",
58
+ filter: {},
59
+ async transform({ block: { data }, context }) {
60
+ },
61
+ plugins,
62
+ ...override
63
+ })
64
+ );
65
+ }
66
+ function mockSink({
67
+ output,
68
+ metadata
69
+ }) {
70
+ return defineIndexerPlugin((indexer) => {
71
+ indexer.hooks.hook("connect:before", ({ request }) => {
72
+ if (metadata?.lastCursor && isCursor(metadata.lastCursor)) {
73
+ request.startingCursor = metadata.lastCursor;
74
+ }
75
+ if (metadata?.lastFilter) {
76
+ request.filter[1] = metadata.lastFilter;
77
+ }
78
+ });
79
+ indexer.hooks.hook("connect:factory", ({ request, endCursor }) => {
80
+ if (request.filter[1]) {
81
+ if (metadata) {
82
+ metadata.lastCursor = endCursor;
83
+ metadata.lastFilter = request.filter[1];
84
+ }
85
+ }
86
+ });
87
+ indexer.hooks.hook("handler:middleware", ({ use }) => {
88
+ use(async (context, next) => {
89
+ context.output = output;
90
+ await next();
91
+ context.output = null;
92
+ if (metadata) {
93
+ metadata.lastCursor = context.endCursor;
94
+ }
95
+ });
96
+ });
97
+ });
98
+ }
99
+ function useMockSink() {
100
+ const context = useIndexerContext();
101
+ return { output: context.output };
102
+ }
103
+
104
+ export { generateMockMessages, getMockIndexer, mockSink, useMockSink };
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ const config = require('../shared/indexer.601ceab0.cjs');
4
+ const logger = require('../shared/indexer.2416906c.cjs');
5
+ const protocol = require('@apibara/protocol');
6
+ require('consola');
7
+ require('../shared/indexer.077335f3.cjs');
8
+ require('node:async_hooks');
9
+ require('unctx');
10
+
11
+ function inMemoryPersistence() {
12
+ return config.defineIndexerPlugin((indexer) => {
13
+ let lastCursor;
14
+ let lastFilter;
15
+ indexer.hooks.hook("connect:before", ({ request }) => {
16
+ if (lastCursor) {
17
+ request.startingCursor = lastCursor;
18
+ }
19
+ if (lastFilter) {
20
+ request.filter[1] = lastFilter;
21
+ }
22
+ });
23
+ indexer.hooks.hook("connect:factory", ({ request, endCursor }) => {
24
+ if (request.filter[1]) {
25
+ lastCursor = endCursor;
26
+ lastFilter = request.filter[1];
27
+ }
28
+ });
29
+ indexer.hooks.hook("handler:middleware", ({ use }) => {
30
+ use(async (context, next) => {
31
+ await next();
32
+ if (context.endCursor && protocol.isCursor(context.endCursor)) {
33
+ lastCursor = context.endCursor;
34
+ }
35
+ });
36
+ });
37
+ });
38
+ }
39
+
40
+ exports.defineIndexerPlugin = config.defineIndexerPlugin;
41
+ exports.logger = logger.logger;
42
+ exports.useLogger = logger.useLogger;
43
+ exports.inMemoryPersistence = inMemoryPersistence;
@@ -0,0 +1,18 @@
1
+ import { a as IndexerPlugin } from '../shared/indexer.8939ecc8.cjs';
2
+ export { d as defineIndexerPlugin } from '../shared/indexer.8939ecc8.cjs';
3
+ import { ConsolaReporter, ConsolaInstance } from 'consola';
4
+ export { ConsolaInstance, ConsolaReporter } from 'consola';
5
+ import '@apibara/protocol';
6
+ import 'hookable';
7
+
8
+ declare function logger<TFilter, TBlock, TTxnParams>({ logger, }?: {
9
+ logger?: ConsolaReporter;
10
+ }): IndexerPlugin<TFilter, TBlock>;
11
+ declare function useLogger(): ConsolaInstance;
12
+
13
+ /**
14
+ * A plugin that persists the last cursor and filter to memory.
15
+ */
16
+ declare function inMemoryPersistence<TFilter, TBlock>(): IndexerPlugin<TFilter, TBlock>;
17
+
18
+ export { IndexerPlugin, inMemoryPersistence, logger, useLogger };
@@ -0,0 +1,18 @@
1
+ import { a as IndexerPlugin } from '../shared/indexer.8939ecc8.mjs';
2
+ export { d as defineIndexerPlugin } from '../shared/indexer.8939ecc8.mjs';
3
+ import { ConsolaReporter, ConsolaInstance } from 'consola';
4
+ export { ConsolaInstance, ConsolaReporter } from 'consola';
5
+ import '@apibara/protocol';
6
+ import 'hookable';
7
+
8
+ declare function logger<TFilter, TBlock, TTxnParams>({ logger, }?: {
9
+ logger?: ConsolaReporter;
10
+ }): IndexerPlugin<TFilter, TBlock>;
11
+ declare function useLogger(): ConsolaInstance;
12
+
13
+ /**
14
+ * A plugin that persists the last cursor and filter to memory.
15
+ */
16
+ declare function inMemoryPersistence<TFilter, TBlock>(): IndexerPlugin<TFilter, TBlock>;
17
+
18
+ export { IndexerPlugin, inMemoryPersistence, logger, useLogger };
@@ -0,0 +1,18 @@
1
+ import { a as IndexerPlugin } from '../shared/indexer.8939ecc8.js';
2
+ export { d as defineIndexerPlugin } from '../shared/indexer.8939ecc8.js';
3
+ import { ConsolaReporter, ConsolaInstance } from 'consola';
4
+ export { ConsolaInstance, ConsolaReporter } from 'consola';
5
+ import '@apibara/protocol';
6
+ import 'hookable';
7
+
8
+ declare function logger<TFilter, TBlock, TTxnParams>({ logger, }?: {
9
+ logger?: ConsolaReporter;
10
+ }): IndexerPlugin<TFilter, TBlock>;
11
+ declare function useLogger(): ConsolaInstance;
12
+
13
+ /**
14
+ * A plugin that persists the last cursor and filter to memory.
15
+ */
16
+ declare function inMemoryPersistence<TFilter, TBlock>(): IndexerPlugin<TFilter, TBlock>;
17
+
18
+ export { IndexerPlugin, inMemoryPersistence, logger, useLogger };
@@ -0,0 +1,38 @@
1
+ import { d as defineIndexerPlugin } from '../shared/indexer.9b21ddd2.mjs';
2
+ export { l as logger, u as useLogger } from '../shared/indexer.ff25c953.mjs';
3
+ import { isCursor } from '@apibara/protocol';
4
+ import 'consola';
5
+ import '../shared/indexer.a55ad619.mjs';
6
+ import 'node:async_hooks';
7
+ import 'unctx';
8
+
9
+ function inMemoryPersistence() {
10
+ return defineIndexerPlugin((indexer) => {
11
+ let lastCursor;
12
+ let lastFilter;
13
+ indexer.hooks.hook("connect:before", ({ request }) => {
14
+ if (lastCursor) {
15
+ request.startingCursor = lastCursor;
16
+ }
17
+ if (lastFilter) {
18
+ request.filter[1] = lastFilter;
19
+ }
20
+ });
21
+ indexer.hooks.hook("connect:factory", ({ request, endCursor }) => {
22
+ if (request.filter[1]) {
23
+ lastCursor = endCursor;
24
+ lastFilter = request.filter[1];
25
+ }
26
+ });
27
+ indexer.hooks.hook("handler:middleware", ({ use }) => {
28
+ use(async (context, next) => {
29
+ await next();
30
+ if (context.endCursor && isCursor(context.endCursor)) {
31
+ lastCursor = context.endCursor;
32
+ }
33
+ });
34
+ });
35
+ });
36
+ }
37
+
38
+ export { defineIndexerPlugin, inMemoryPersistence };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const node_async_hooks = require('node:async_hooks');
4
+ const unctx = require('unctx');
5
+
6
+ const indexerAsyncContext = unctx.getContext("indexer", {
7
+ asyncContext: true,
8
+ AsyncLocalStorage: node_async_hooks.AsyncLocalStorage
9
+ });
10
+ function useIndexerContext() {
11
+ return indexerAsyncContext.use();
12
+ }
13
+
14
+ exports.indexerAsyncContext = indexerAsyncContext;
15
+ exports.useIndexerContext = useIndexerContext;
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const consola = require('consola');
4
+ const context = require('./indexer.077335f3.cjs');
5
+ const config = require('./indexer.601ceab0.cjs');
6
+
7
+ function logger({
8
+ logger: logger2
9
+ } = {}) {
10
+ return config.defineIndexerPlugin((indexer) => {
11
+ indexer.hooks.hook("run:before", () => {
12
+ const ctx = context.useIndexerContext();
13
+ if (logger2) {
14
+ ctx.logger = consola.consola.create({ reporters: [logger2] });
15
+ } else {
16
+ ctx.logger = consola.consola.create({});
17
+ }
18
+ });
19
+ });
20
+ }
21
+ function useLogger() {
22
+ const ctx = context.useIndexerContext();
23
+ if (!ctx?.logger)
24
+ throw new Error("Logger plugin is not available in context");
25
+ return ctx.logger;
26
+ }
27
+
28
+ exports.logger = logger;
29
+ exports.useLogger = useLogger;
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ function defineIndexerPlugin(def) {
4
+ return def;
5
+ }
6
+
7
+ exports.defineIndexerPlugin = defineIndexerPlugin;
@@ -0,0 +1,91 @@
1
+ import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, Heartbeat, SystemMessage, DataFinality, StreamConfig, Client } from '@apibara/protocol';
2
+ import { NestedHooks, Hookable } from 'hookable';
3
+
4
+ interface IndexerContext extends Record<string, any> {
5
+ }
6
+ declare function useIndexerContext(): IndexerContext;
7
+
8
+ type NextFunction = () => Promise<void>;
9
+ type MiddlewareFunction<C> = (context: C, next: NextFunction) => Promise<void>;
10
+
11
+ type IndexerPlugin<TFilter, TBlock> = (indexer: Indexer<TFilter, TBlock>) => void;
12
+ declare function defineIndexerPlugin<TFilter, TBlock>(def: IndexerPlugin<TFilter, TBlock>): IndexerPlugin<TFilter, TBlock>;
13
+
14
+ type UseMiddlewareFunction = (fn: MiddlewareFunction<IndexerContext>) => void;
15
+ interface IndexerHooks<TFilter, TBlock> {
16
+ "run:before": () => void;
17
+ "run:after": () => void;
18
+ "connect:before": ({ request, options, }: {
19
+ request: StreamDataRequest<TFilter>;
20
+ options: StreamDataOptions;
21
+ }) => void;
22
+ "connect:after": ({ request, }: {
23
+ request: StreamDataRequest<TFilter>;
24
+ }) => void;
25
+ "connect:factory": ({ request, endCursor, }: {
26
+ request: StreamDataRequest<TFilter>;
27
+ endCursor?: Cursor;
28
+ }) => void;
29
+ "handler:middleware": ({ use }: {
30
+ use: UseMiddlewareFunction;
31
+ }) => void;
32
+ message: ({ message }: {
33
+ message: StreamDataResponse<TBlock>;
34
+ }) => void;
35
+ "message:invalidate": ({ message }: {
36
+ message: Invalidate;
37
+ }) => void;
38
+ "message:finalize": ({ message }: {
39
+ message: Finalize;
40
+ }) => void;
41
+ "message:heartbeat": ({ message }: {
42
+ message: Heartbeat;
43
+ }) => void;
44
+ "message:systemMessage": ({ message }: {
45
+ message: SystemMessage;
46
+ }) => void;
47
+ }
48
+ interface IndexerConfig<TFilter, TBlock> {
49
+ streamUrl: string;
50
+ filter: TFilter;
51
+ finality?: DataFinality;
52
+ startingCursor?: Cursor;
53
+ factory?: ({ block, context, }: {
54
+ block: TBlock;
55
+ context: IndexerContext;
56
+ }) => Promise<{
57
+ filter?: TFilter;
58
+ }>;
59
+ transform: (args: {
60
+ block: TBlock;
61
+ cursor?: Cursor | undefined;
62
+ endCursor?: Cursor | undefined;
63
+ finality: DataFinality;
64
+ context: IndexerContext;
65
+ }) => Promise<void>;
66
+ hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;
67
+ plugins?: ReadonlyArray<IndexerPlugin<TFilter, TBlock>>;
68
+ debug?: boolean;
69
+ }
70
+ interface IndexerWithStreamConfig<TFilter, TBlock> extends IndexerConfig<TFilter, TBlock> {
71
+ streamConfig: StreamConfig<TFilter, TBlock>;
72
+ }
73
+ declare function defineIndexer<TFilter, TBlock>(streamConfig: StreamConfig<TFilter, TBlock>): (config: IndexerConfig<TFilter, TBlock>) => IndexerWithStreamConfig<TFilter, TBlock>;
74
+ interface Indexer<TFilter, TBlock> {
75
+ streamConfig: StreamConfig<TFilter, TBlock>;
76
+ options: IndexerConfig<TFilter, TBlock>;
77
+ hooks: Hookable<IndexerHooks<TFilter, TBlock>>;
78
+ }
79
+ declare function createIndexer<TFilter, TBlock>({ streamConfig, ...options }: IndexerWithStreamConfig<TFilter, TBlock>): Indexer<TFilter, TBlock>;
80
+ interface ReconnectOptions {
81
+ maxRetries?: number;
82
+ retryDelay?: number;
83
+ maxWait?: number;
84
+ }
85
+ declare function runWithReconnect<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, options?: ReconnectOptions): Promise<void>;
86
+ interface RunOptions {
87
+ onConnect?: () => void | Promise<void>;
88
+ }
89
+ declare function run<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, runOptions?: RunOptions): Promise<void>;
90
+
91
+ export { type IndexerWithStreamConfig as I, type ReconnectOptions as R, type UseMiddlewareFunction as U, type IndexerPlugin as a, type IndexerConfig as b, type Indexer as c, defineIndexerPlugin as d, type IndexerHooks as e, defineIndexer as f, createIndexer as g, type RunOptions as h, run as i, runWithReconnect as r, useIndexerContext as u };
@@ -0,0 +1,91 @@
1
+ import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, Heartbeat, SystemMessage, DataFinality, StreamConfig, Client } from '@apibara/protocol';
2
+ import { NestedHooks, Hookable } from 'hookable';
3
+
4
+ interface IndexerContext extends Record<string, any> {
5
+ }
6
+ declare function useIndexerContext(): IndexerContext;
7
+
8
+ type NextFunction = () => Promise<void>;
9
+ type MiddlewareFunction<C> = (context: C, next: NextFunction) => Promise<void>;
10
+
11
+ type IndexerPlugin<TFilter, TBlock> = (indexer: Indexer<TFilter, TBlock>) => void;
12
+ declare function defineIndexerPlugin<TFilter, TBlock>(def: IndexerPlugin<TFilter, TBlock>): IndexerPlugin<TFilter, TBlock>;
13
+
14
+ type UseMiddlewareFunction = (fn: MiddlewareFunction<IndexerContext>) => void;
15
+ interface IndexerHooks<TFilter, TBlock> {
16
+ "run:before": () => void;
17
+ "run:after": () => void;
18
+ "connect:before": ({ request, options, }: {
19
+ request: StreamDataRequest<TFilter>;
20
+ options: StreamDataOptions;
21
+ }) => void;
22
+ "connect:after": ({ request, }: {
23
+ request: StreamDataRequest<TFilter>;
24
+ }) => void;
25
+ "connect:factory": ({ request, endCursor, }: {
26
+ request: StreamDataRequest<TFilter>;
27
+ endCursor?: Cursor;
28
+ }) => void;
29
+ "handler:middleware": ({ use }: {
30
+ use: UseMiddlewareFunction;
31
+ }) => void;
32
+ message: ({ message }: {
33
+ message: StreamDataResponse<TBlock>;
34
+ }) => void;
35
+ "message:invalidate": ({ message }: {
36
+ message: Invalidate;
37
+ }) => void;
38
+ "message:finalize": ({ message }: {
39
+ message: Finalize;
40
+ }) => void;
41
+ "message:heartbeat": ({ message }: {
42
+ message: Heartbeat;
43
+ }) => void;
44
+ "message:systemMessage": ({ message }: {
45
+ message: SystemMessage;
46
+ }) => void;
47
+ }
48
+ interface IndexerConfig<TFilter, TBlock> {
49
+ streamUrl: string;
50
+ filter: TFilter;
51
+ finality?: DataFinality;
52
+ startingCursor?: Cursor;
53
+ factory?: ({ block, context, }: {
54
+ block: TBlock;
55
+ context: IndexerContext;
56
+ }) => Promise<{
57
+ filter?: TFilter;
58
+ }>;
59
+ transform: (args: {
60
+ block: TBlock;
61
+ cursor?: Cursor | undefined;
62
+ endCursor?: Cursor | undefined;
63
+ finality: DataFinality;
64
+ context: IndexerContext;
65
+ }) => Promise<void>;
66
+ hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;
67
+ plugins?: ReadonlyArray<IndexerPlugin<TFilter, TBlock>>;
68
+ debug?: boolean;
69
+ }
70
+ interface IndexerWithStreamConfig<TFilter, TBlock> extends IndexerConfig<TFilter, TBlock> {
71
+ streamConfig: StreamConfig<TFilter, TBlock>;
72
+ }
73
+ declare function defineIndexer<TFilter, TBlock>(streamConfig: StreamConfig<TFilter, TBlock>): (config: IndexerConfig<TFilter, TBlock>) => IndexerWithStreamConfig<TFilter, TBlock>;
74
+ interface Indexer<TFilter, TBlock> {
75
+ streamConfig: StreamConfig<TFilter, TBlock>;
76
+ options: IndexerConfig<TFilter, TBlock>;
77
+ hooks: Hookable<IndexerHooks<TFilter, TBlock>>;
78
+ }
79
+ declare function createIndexer<TFilter, TBlock>({ streamConfig, ...options }: IndexerWithStreamConfig<TFilter, TBlock>): Indexer<TFilter, TBlock>;
80
+ interface ReconnectOptions {
81
+ maxRetries?: number;
82
+ retryDelay?: number;
83
+ maxWait?: number;
84
+ }
85
+ declare function runWithReconnect<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, options?: ReconnectOptions): Promise<void>;
86
+ interface RunOptions {
87
+ onConnect?: () => void | Promise<void>;
88
+ }
89
+ declare function run<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, runOptions?: RunOptions): Promise<void>;
90
+
91
+ export { type IndexerWithStreamConfig as I, type ReconnectOptions as R, type UseMiddlewareFunction as U, type IndexerPlugin as a, type IndexerConfig as b, type Indexer as c, defineIndexerPlugin as d, type IndexerHooks as e, defineIndexer as f, createIndexer as g, type RunOptions as h, run as i, runWithReconnect as r, useIndexerContext as u };
@@ -0,0 +1,91 @@
1
+ import { StreamDataRequest, StreamDataOptions, Cursor, StreamDataResponse, Invalidate, Finalize, Heartbeat, SystemMessage, DataFinality, StreamConfig, Client } from '@apibara/protocol';
2
+ import { NestedHooks, Hookable } from 'hookable';
3
+
4
+ interface IndexerContext extends Record<string, any> {
5
+ }
6
+ declare function useIndexerContext(): IndexerContext;
7
+
8
+ type NextFunction = () => Promise<void>;
9
+ type MiddlewareFunction<C> = (context: C, next: NextFunction) => Promise<void>;
10
+
11
+ type IndexerPlugin<TFilter, TBlock> = (indexer: Indexer<TFilter, TBlock>) => void;
12
+ declare function defineIndexerPlugin<TFilter, TBlock>(def: IndexerPlugin<TFilter, TBlock>): IndexerPlugin<TFilter, TBlock>;
13
+
14
+ type UseMiddlewareFunction = (fn: MiddlewareFunction<IndexerContext>) => void;
15
+ interface IndexerHooks<TFilter, TBlock> {
16
+ "run:before": () => void;
17
+ "run:after": () => void;
18
+ "connect:before": ({ request, options, }: {
19
+ request: StreamDataRequest<TFilter>;
20
+ options: StreamDataOptions;
21
+ }) => void;
22
+ "connect:after": ({ request, }: {
23
+ request: StreamDataRequest<TFilter>;
24
+ }) => void;
25
+ "connect:factory": ({ request, endCursor, }: {
26
+ request: StreamDataRequest<TFilter>;
27
+ endCursor?: Cursor;
28
+ }) => void;
29
+ "handler:middleware": ({ use }: {
30
+ use: UseMiddlewareFunction;
31
+ }) => void;
32
+ message: ({ message }: {
33
+ message: StreamDataResponse<TBlock>;
34
+ }) => void;
35
+ "message:invalidate": ({ message }: {
36
+ message: Invalidate;
37
+ }) => void;
38
+ "message:finalize": ({ message }: {
39
+ message: Finalize;
40
+ }) => void;
41
+ "message:heartbeat": ({ message }: {
42
+ message: Heartbeat;
43
+ }) => void;
44
+ "message:systemMessage": ({ message }: {
45
+ message: SystemMessage;
46
+ }) => void;
47
+ }
48
+ interface IndexerConfig<TFilter, TBlock> {
49
+ streamUrl: string;
50
+ filter: TFilter;
51
+ finality?: DataFinality;
52
+ startingCursor?: Cursor;
53
+ factory?: ({ block, context, }: {
54
+ block: TBlock;
55
+ context: IndexerContext;
56
+ }) => Promise<{
57
+ filter?: TFilter;
58
+ }>;
59
+ transform: (args: {
60
+ block: TBlock;
61
+ cursor?: Cursor | undefined;
62
+ endCursor?: Cursor | undefined;
63
+ finality: DataFinality;
64
+ context: IndexerContext;
65
+ }) => Promise<void>;
66
+ hooks?: NestedHooks<IndexerHooks<TFilter, TBlock>>;
67
+ plugins?: ReadonlyArray<IndexerPlugin<TFilter, TBlock>>;
68
+ debug?: boolean;
69
+ }
70
+ interface IndexerWithStreamConfig<TFilter, TBlock> extends IndexerConfig<TFilter, TBlock> {
71
+ streamConfig: StreamConfig<TFilter, TBlock>;
72
+ }
73
+ declare function defineIndexer<TFilter, TBlock>(streamConfig: StreamConfig<TFilter, TBlock>): (config: IndexerConfig<TFilter, TBlock>) => IndexerWithStreamConfig<TFilter, TBlock>;
74
+ interface Indexer<TFilter, TBlock> {
75
+ streamConfig: StreamConfig<TFilter, TBlock>;
76
+ options: IndexerConfig<TFilter, TBlock>;
77
+ hooks: Hookable<IndexerHooks<TFilter, TBlock>>;
78
+ }
79
+ declare function createIndexer<TFilter, TBlock>({ streamConfig, ...options }: IndexerWithStreamConfig<TFilter, TBlock>): Indexer<TFilter, TBlock>;
80
+ interface ReconnectOptions {
81
+ maxRetries?: number;
82
+ retryDelay?: number;
83
+ maxWait?: number;
84
+ }
85
+ declare function runWithReconnect<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, options?: ReconnectOptions): Promise<void>;
86
+ interface RunOptions {
87
+ onConnect?: () => void | Promise<void>;
88
+ }
89
+ declare function run<TFilter, TBlock>(client: Client<TFilter, TBlock>, indexer: Indexer<TFilter, TBlock>, runOptions?: RunOptions): Promise<void>;
90
+
91
+ export { type IndexerWithStreamConfig as I, type ReconnectOptions as R, type UseMiddlewareFunction as U, type IndexerPlugin as a, type IndexerConfig as b, type Indexer as c, defineIndexerPlugin as d, type IndexerHooks as e, defineIndexer as f, createIndexer as g, type RunOptions as h, run as i, runWithReconnect as r, useIndexerContext as u };
@@ -0,0 +1,5 @@
1
+ function defineIndexerPlugin(def) {
2
+ return def;
3
+ }
4
+
5
+ export { defineIndexerPlugin as d };
@@ -0,0 +1,12 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { getContext } from 'unctx';
3
+
4
+ const indexerAsyncContext = getContext("indexer", {
5
+ asyncContext: true,
6
+ AsyncLocalStorage
7
+ });
8
+ function useIndexerContext() {
9
+ return indexerAsyncContext.use();
10
+ }
11
+
12
+ export { indexerAsyncContext as i, useIndexerContext as u };