@apibara/indexer 2.0.0-beta.9 → 2.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +271 -39
- package/dist/index.d.cts +1 -16
- package/dist/index.d.mts +1 -16
- package/dist/index.d.ts +1 -16
- package/dist/index.mjs +262 -25
- package/dist/internal/index.cjs +10 -0
- package/dist/internal/index.d.cts +3 -0
- package/dist/internal/index.d.mts +3 -0
- package/dist/internal/index.d.ts +3 -0
- package/dist/internal/index.mjs +8 -0
- package/dist/internal/plugins.cjs +38 -0
- package/dist/internal/plugins.d.cts +13 -0
- package/dist/internal/plugins.d.mts +13 -0
- package/dist/internal/plugins.d.ts +13 -0
- package/dist/internal/plugins.mjs +34 -0
- package/dist/internal/testing.cjs +118 -0
- package/dist/internal/testing.d.cts +42 -0
- package/dist/internal/testing.d.mts +42 -0
- package/dist/internal/testing.d.ts +42 -0
- package/dist/internal/testing.mjs +113 -0
- package/dist/plugins/index.cjs +39 -3
- package/dist/plugins/index.d.cts +16 -2
- package/dist/plugins/index.d.mts +16 -2
- package/dist/plugins/index.d.ts +16 -2
- package/dist/plugins/index.mjs +36 -3
- package/dist/shared/indexer.077335f3.cjs +15 -0
- package/dist/shared/indexer.2416906c.cjs +29 -0
- package/dist/shared/indexer.601ceab0.cjs +7 -0
- package/dist/shared/indexer.9b21ddd2.mjs +5 -0
- package/dist/shared/indexer.a55ad619.mjs +12 -0
- package/dist/shared/indexer.fedcd831.d.cts +100 -0
- package/dist/shared/indexer.fedcd831.d.mts +100 -0
- package/dist/shared/indexer.fedcd831.d.ts +100 -0
- package/dist/shared/indexer.ff25c953.mjs +26 -0
- package/dist/testing/index.cjs +52 -50
- package/dist/testing/index.d.cts +8 -36
- package/dist/testing/index.d.mts +8 -36
- package/dist/testing/index.d.ts +8 -36
- package/dist/testing/index.mjs +47 -47
- package/dist/vcr/index.cjs +84 -17
- package/dist/vcr/index.d.cts +16 -7
- package/dist/vcr/index.d.mts +16 -7
- package/dist/vcr/index.d.ts +16 -7
- package/dist/vcr/index.mjs +75 -11
- package/package.json +22 -42
- package/src/compose.test.ts +76 -0
- package/src/compose.ts +71 -0
- package/src/context.ts +14 -8
- package/src/index.ts +0 -5
- package/src/indexer.test.ts +125 -186
- package/src/indexer.ts +278 -151
- package/src/internal/index.ts +6 -0
- package/src/internal/plugins.ts +1 -0
- package/src/internal/testing.ts +148 -0
- package/src/plugins/config.ts +4 -4
- package/src/plugins/context.ts +40 -0
- package/src/plugins/index.ts +8 -1
- package/src/plugins/logger.ts +30 -0
- package/src/plugins/persistence.ts +24 -187
- package/src/testing/index.ts +58 -3
- package/src/vcr/record.ts +5 -3
- package/src/vcr/replay.ts +8 -18
- package/dist/plugins/kv.cjs +0 -131
- package/dist/plugins/kv.d.cts +0 -32
- package/dist/plugins/kv.d.mts +0 -32
- package/dist/plugins/kv.d.ts +0 -32
- package/dist/plugins/kv.mjs +0 -124
- package/dist/plugins/persistence.cjs +0 -182
- package/dist/plugins/persistence.d.cts +0 -50
- package/dist/plugins/persistence.d.mts +0 -50
- package/dist/plugins/persistence.d.ts +0 -50
- package/dist/plugins/persistence.mjs +0 -179
- package/dist/shared/indexer.2c23c9cd.mjs +0 -35
- package/dist/shared/indexer.318d3617.cjs +0 -47
- package/dist/shared/indexer.36530330.mjs +0 -249
- package/dist/shared/indexer.500fd281.d.cts +0 -23
- package/dist/shared/indexer.541d43eb.cjs +0 -266
- package/dist/shared/indexer.93d6b2eb.mjs +0 -17
- package/dist/shared/indexer.a8b7ab1f.cjs +0 -25
- package/dist/shared/indexer.b9c8f0d8.d.cts +0 -19
- package/dist/shared/indexer.b9c8f0d8.d.mts +0 -19
- package/dist/shared/indexer.b9c8f0d8.d.ts +0 -19
- package/dist/shared/indexer.c7ed6b83.d.cts +0 -82
- package/dist/shared/indexer.e1856641.d.mts +0 -23
- package/dist/shared/indexer.e4f2430f.d.ts +0 -23
- package/dist/shared/indexer.e8bd138d.d.mts +0 -82
- package/dist/shared/indexer.f761abcd.d.ts +0 -82
- package/dist/sinks/csv.cjs +0 -85
- package/dist/sinks/csv.d.cts +0 -66
- package/dist/sinks/csv.d.mts +0 -66
- package/dist/sinks/csv.d.ts +0 -66
- package/dist/sinks/csv.mjs +0 -78
- package/dist/sinks/drizzle/index.cjs +0 -212
- package/dist/sinks/drizzle/index.d.cts +0 -153
- package/dist/sinks/drizzle/index.d.mts +0 -153
- package/dist/sinks/drizzle/index.d.ts +0 -153
- package/dist/sinks/drizzle/index.mjs +0 -198
- package/dist/sinks/sqlite.cjs +0 -90
- package/dist/sinks/sqlite.d.cts +0 -71
- package/dist/sinks/sqlite.d.mts +0 -71
- package/dist/sinks/sqlite.d.ts +0 -71
- package/dist/sinks/sqlite.mjs +0 -87
- package/src/hooks/index.ts +0 -2
- package/src/hooks/useKVStore.ts +0 -12
- package/src/hooks/useSink.ts +0 -13
- package/src/plugins/kv.test.ts +0 -120
- package/src/plugins/kv.ts +0 -132
- package/src/plugins/persistence.test.ts +0 -151
- package/src/sink.ts +0 -36
- package/src/sinks/csv.test.ts +0 -65
- package/src/sinks/csv.ts +0 -159
- package/src/sinks/drizzle/Int8Range.ts +0 -52
- package/src/sinks/drizzle/delete.ts +0 -42
- package/src/sinks/drizzle/drizzle.test.ts +0 -239
- package/src/sinks/drizzle/drizzle.ts +0 -115
- package/src/sinks/drizzle/index.ts +0 -6
- package/src/sinks/drizzle/insert.ts +0 -42
- package/src/sinks/drizzle/select.ts +0 -44
- package/src/sinks/drizzle/transaction.ts +0 -49
- package/src/sinks/drizzle/update.ts +0 -47
- package/src/sinks/drizzle/utils.ts +0 -99
- package/src/sinks/sqlite.test.ts +0 -99
- package/src/sinks/sqlite.ts +0 -170
- package/src/testing/helper.ts +0 -13
- package/src/testing/indexer.ts +0 -35
- package/src/testing/setup.ts +0 -59
- package/src/testing/vcr.ts +0 -54
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const context = require('../shared/indexer.077335f3.cjs');
|
|
4
|
+
const config = require('../shared/indexer.601ceab0.cjs');
|
|
5
|
+
require('node:async_hooks');
|
|
6
|
+
require('unctx');
|
|
7
|
+
|
|
8
|
+
const INTERNAL_CONTEXT_PROPERTY = "_internal";
|
|
9
|
+
function internalContext(values) {
|
|
10
|
+
return config.defineIndexerPlugin((indexer) => {
|
|
11
|
+
indexer.hooks.hook("run:before", () => {
|
|
12
|
+
try {
|
|
13
|
+
const ctx = context.useIndexerContext();
|
|
14
|
+
ctx[INTERNAL_CONTEXT_PROPERTY] = {
|
|
15
|
+
...ctx[INTERNAL_CONTEXT_PROPERTY] || {},
|
|
16
|
+
...values
|
|
17
|
+
};
|
|
18
|
+
} catch (error) {
|
|
19
|
+
throw new Error("Failed to set internal context", {
|
|
20
|
+
cause: error
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function useInternalContext() {
|
|
27
|
+
const ctx = context.useIndexerContext();
|
|
28
|
+
if (ctx[INTERNAL_CONTEXT_PROPERTY] === void 0) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
"Internal context is not available, possibly 'internalContext' plugin is missing!"
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return ctx[INTERNAL_CONTEXT_PROPERTY];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.INTERNAL_CONTEXT_PROPERTY = INTERNAL_CONTEXT_PROPERTY;
|
|
37
|
+
exports.internalContext = internalContext;
|
|
38
|
+
exports.useInternalContext = useInternalContext;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { b as IndexerPlugin } from '../shared/indexer.fedcd831.cjs';
|
|
2
|
+
import '@apibara/protocol';
|
|
3
|
+
import 'hookable';
|
|
4
|
+
|
|
5
|
+
declare const INTERNAL_CONTEXT_PROPERTY = "_internal";
|
|
6
|
+
declare function internalContext<TFilter, TBlock, TTxnParams>(values: Record<string, unknown>): IndexerPlugin<TFilter, TBlock>;
|
|
7
|
+
type InternalContext = {
|
|
8
|
+
indexerName: string;
|
|
9
|
+
availableIndexers: string[];
|
|
10
|
+
};
|
|
11
|
+
declare function useInternalContext(): InternalContext;
|
|
12
|
+
|
|
13
|
+
export { INTERNAL_CONTEXT_PROPERTY, type InternalContext, internalContext, useInternalContext };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { b as IndexerPlugin } from '../shared/indexer.fedcd831.mjs';
|
|
2
|
+
import '@apibara/protocol';
|
|
3
|
+
import 'hookable';
|
|
4
|
+
|
|
5
|
+
declare const INTERNAL_CONTEXT_PROPERTY = "_internal";
|
|
6
|
+
declare function internalContext<TFilter, TBlock, TTxnParams>(values: Record<string, unknown>): IndexerPlugin<TFilter, TBlock>;
|
|
7
|
+
type InternalContext = {
|
|
8
|
+
indexerName: string;
|
|
9
|
+
availableIndexers: string[];
|
|
10
|
+
};
|
|
11
|
+
declare function useInternalContext(): InternalContext;
|
|
12
|
+
|
|
13
|
+
export { INTERNAL_CONTEXT_PROPERTY, type InternalContext, internalContext, useInternalContext };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { b as IndexerPlugin } from '../shared/indexer.fedcd831.js';
|
|
2
|
+
import '@apibara/protocol';
|
|
3
|
+
import 'hookable';
|
|
4
|
+
|
|
5
|
+
declare const INTERNAL_CONTEXT_PROPERTY = "_internal";
|
|
6
|
+
declare function internalContext<TFilter, TBlock, TTxnParams>(values: Record<string, unknown>): IndexerPlugin<TFilter, TBlock>;
|
|
7
|
+
type InternalContext = {
|
|
8
|
+
indexerName: string;
|
|
9
|
+
availableIndexers: string[];
|
|
10
|
+
};
|
|
11
|
+
declare function useInternalContext(): InternalContext;
|
|
12
|
+
|
|
13
|
+
export { INTERNAL_CONTEXT_PROPERTY, type InternalContext, internalContext, useInternalContext };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { u as useIndexerContext } from '../shared/indexer.a55ad619.mjs';
|
|
2
|
+
import { d as defineIndexerPlugin } from '../shared/indexer.9b21ddd2.mjs';
|
|
3
|
+
import 'node:async_hooks';
|
|
4
|
+
import 'unctx';
|
|
5
|
+
|
|
6
|
+
const INTERNAL_CONTEXT_PROPERTY = "_internal";
|
|
7
|
+
function internalContext(values) {
|
|
8
|
+
return defineIndexerPlugin((indexer) => {
|
|
9
|
+
indexer.hooks.hook("run:before", () => {
|
|
10
|
+
try {
|
|
11
|
+
const ctx = useIndexerContext();
|
|
12
|
+
ctx[INTERNAL_CONTEXT_PROPERTY] = {
|
|
13
|
+
...ctx[INTERNAL_CONTEXT_PROPERTY] || {},
|
|
14
|
+
...values
|
|
15
|
+
};
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw new Error("Failed to set internal context", {
|
|
18
|
+
cause: error
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function useInternalContext() {
|
|
25
|
+
const ctx = useIndexerContext();
|
|
26
|
+
if (ctx[INTERNAL_CONTEXT_PROPERTY] === void 0) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
"Internal context is not available, possibly 'internalContext' plugin is missing!"
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return ctx[INTERNAL_CONTEXT_PROPERTY];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { INTERNAL_CONTEXT_PROPERTY, internalContext, useInternalContext };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const protocol = require('@apibara/protocol');
|
|
4
|
+
const testing = require('@apibara/protocol/testing');
|
|
5
|
+
const context = require('../shared/indexer.077335f3.cjs');
|
|
6
|
+
const index = require('../index.cjs');
|
|
7
|
+
const config = require('../shared/indexer.601ceab0.cjs');
|
|
8
|
+
require('consola');
|
|
9
|
+
const internal_plugins = require('./plugins.cjs');
|
|
10
|
+
require('node:async_hooks');
|
|
11
|
+
require('unctx');
|
|
12
|
+
require('hookable');
|
|
13
|
+
require('node:assert');
|
|
14
|
+
require('@opentelemetry/api');
|
|
15
|
+
|
|
16
|
+
function generateMockMessages(count = 10, options) {
|
|
17
|
+
const invalidateAt = options?.invalidate;
|
|
18
|
+
const finalizeAt = options?.finalize;
|
|
19
|
+
const messages = [];
|
|
20
|
+
for (let i = 0; i < count; i++) {
|
|
21
|
+
if (invalidateAt && i === invalidateAt.invalidateTriggerIndex) {
|
|
22
|
+
messages.push({
|
|
23
|
+
_tag: "invalidate",
|
|
24
|
+
invalidate: {
|
|
25
|
+
cursor: {
|
|
26
|
+
orderKey: BigInt(5e6 + invalidateAt.invalidateFromIndex)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
} else if (finalizeAt && i === finalizeAt.finalizeTriggerIndex) {
|
|
31
|
+
messages.push({
|
|
32
|
+
_tag: "finalize",
|
|
33
|
+
finalize: {
|
|
34
|
+
cursor: {
|
|
35
|
+
orderKey: BigInt(5e6 + finalizeAt.finalizeToIndex)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
} else {
|
|
40
|
+
messages.push({
|
|
41
|
+
_tag: "data",
|
|
42
|
+
data: {
|
|
43
|
+
cursor: { orderKey: BigInt(5e6 + i - 1) },
|
|
44
|
+
finality: "accepted",
|
|
45
|
+
data: [{ data: `${5e6 + i}` }],
|
|
46
|
+
endCursor: { orderKey: BigInt(5e6 + i) },
|
|
47
|
+
production: "backfill"
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return messages;
|
|
53
|
+
}
|
|
54
|
+
function getMockIndexer(params) {
|
|
55
|
+
const { internalContext: contextParams, override } = params ?? {};
|
|
56
|
+
const { plugins, ...rest } = override ?? {};
|
|
57
|
+
return index.createIndexer(
|
|
58
|
+
index.defineIndexer(testing.MockStream)({
|
|
59
|
+
streamUrl: "https://sepolia.ethereum.a5a.ch",
|
|
60
|
+
finality: "accepted",
|
|
61
|
+
filter: {},
|
|
62
|
+
async transform() {
|
|
63
|
+
},
|
|
64
|
+
plugins: [
|
|
65
|
+
internal_plugins.internalContext(
|
|
66
|
+
contextParams ?? {
|
|
67
|
+
availableIndexers: ["testing"],
|
|
68
|
+
indexerName: "testing"
|
|
69
|
+
}
|
|
70
|
+
),
|
|
71
|
+
...plugins ?? []
|
|
72
|
+
],
|
|
73
|
+
...rest ?? {}
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
function mockSink({
|
|
78
|
+
output,
|
|
79
|
+
metadata
|
|
80
|
+
}) {
|
|
81
|
+
return config.defineIndexerPlugin((indexer) => {
|
|
82
|
+
indexer.hooks.hook("connect:before", ({ request }) => {
|
|
83
|
+
if (metadata?.lastCursor && protocol.isCursor(metadata.lastCursor)) {
|
|
84
|
+
request.startingCursor = metadata.lastCursor;
|
|
85
|
+
}
|
|
86
|
+
if (metadata?.lastFilter) {
|
|
87
|
+
request.filter[1] = metadata.lastFilter;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
indexer.hooks.hook("connect:factory", ({ request, endCursor }) => {
|
|
91
|
+
if (request.filter[1]) {
|
|
92
|
+
if (metadata) {
|
|
93
|
+
metadata.lastCursor = endCursor;
|
|
94
|
+
metadata.lastFilter = request.filter[1];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
indexer.hooks.hook("handler:middleware", ({ use }) => {
|
|
99
|
+
use(async (context, next) => {
|
|
100
|
+
context.output = output;
|
|
101
|
+
await next();
|
|
102
|
+
context.output = null;
|
|
103
|
+
if (metadata) {
|
|
104
|
+
metadata.lastCursor = context.endCursor;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function useMockSink() {
|
|
111
|
+
const context$1 = context.useIndexerContext();
|
|
112
|
+
return { output: context$1.output };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
exports.generateMockMessages = generateMockMessages;
|
|
116
|
+
exports.getMockIndexer = getMockIndexer;
|
|
117
|
+
exports.mockSink = mockSink;
|
|
118
|
+
exports.useMockSink = useMockSink;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.fedcd831.cjs';
|
|
2
|
+
import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
|
|
3
|
+
import { InternalContext } from './plugins.cjs';
|
|
4
|
+
import '@apibara/protocol';
|
|
5
|
+
import 'hookable';
|
|
6
|
+
|
|
7
|
+
type MockMessagesOptions = {
|
|
8
|
+
invalidate?: {
|
|
9
|
+
invalidateFromIndex: number;
|
|
10
|
+
invalidateTriggerIndex: number;
|
|
11
|
+
};
|
|
12
|
+
finalize?: {
|
|
13
|
+
finalizeToIndex: number;
|
|
14
|
+
finalizeTriggerIndex: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
declare function generateMockMessages(count?: number, options?: MockMessagesOptions): MockStreamResponse[];
|
|
18
|
+
type MockIndexerParams = {
|
|
19
|
+
internalContext?: InternalContext;
|
|
20
|
+
override?: Partial<IndexerConfig<MockFilter, MockBlock>>;
|
|
21
|
+
};
|
|
22
|
+
declare function getMockIndexer(params?: MockIndexerParams): Indexer<{
|
|
23
|
+
readonly filter?: string | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
readonly data?: string | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
type MockRet = {
|
|
28
|
+
data: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A mock sink used for testing. The indexer function can write to the output array.
|
|
32
|
+
* The indexer context is optionally written to the metadata object.
|
|
33
|
+
*/
|
|
34
|
+
declare function mockSink<TFilter, TBlock>({ output, metadata, }: {
|
|
35
|
+
output: unknown[];
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
37
|
+
}): IndexerPlugin<TFilter, TBlock>;
|
|
38
|
+
declare function useMockSink(): {
|
|
39
|
+
output: unknown[];
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { type MockMessagesOptions, type MockRet, generateMockMessages, getMockIndexer, mockSink, useMockSink };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.fedcd831.mjs';
|
|
2
|
+
import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
|
|
3
|
+
import { InternalContext } from './plugins.mjs';
|
|
4
|
+
import '@apibara/protocol';
|
|
5
|
+
import 'hookable';
|
|
6
|
+
|
|
7
|
+
type MockMessagesOptions = {
|
|
8
|
+
invalidate?: {
|
|
9
|
+
invalidateFromIndex: number;
|
|
10
|
+
invalidateTriggerIndex: number;
|
|
11
|
+
};
|
|
12
|
+
finalize?: {
|
|
13
|
+
finalizeToIndex: number;
|
|
14
|
+
finalizeTriggerIndex: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
declare function generateMockMessages(count?: number, options?: MockMessagesOptions): MockStreamResponse[];
|
|
18
|
+
type MockIndexerParams = {
|
|
19
|
+
internalContext?: InternalContext;
|
|
20
|
+
override?: Partial<IndexerConfig<MockFilter, MockBlock>>;
|
|
21
|
+
};
|
|
22
|
+
declare function getMockIndexer(params?: MockIndexerParams): Indexer<{
|
|
23
|
+
readonly filter?: string | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
readonly data?: string | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
type MockRet = {
|
|
28
|
+
data: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A mock sink used for testing. The indexer function can write to the output array.
|
|
32
|
+
* The indexer context is optionally written to the metadata object.
|
|
33
|
+
*/
|
|
34
|
+
declare function mockSink<TFilter, TBlock>({ output, metadata, }: {
|
|
35
|
+
output: unknown[];
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
37
|
+
}): IndexerPlugin<TFilter, TBlock>;
|
|
38
|
+
declare function useMockSink(): {
|
|
39
|
+
output: unknown[];
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { type MockMessagesOptions, type MockRet, generateMockMessages, getMockIndexer, mockSink, useMockSink };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { a as Indexer, b as IndexerPlugin, c as IndexerConfig } from '../shared/indexer.fedcd831.js';
|
|
2
|
+
import { MockStreamResponse, MockFilter, MockBlock } from '@apibara/protocol/testing';
|
|
3
|
+
import { InternalContext } from './plugins.js';
|
|
4
|
+
import '@apibara/protocol';
|
|
5
|
+
import 'hookable';
|
|
6
|
+
|
|
7
|
+
type MockMessagesOptions = {
|
|
8
|
+
invalidate?: {
|
|
9
|
+
invalidateFromIndex: number;
|
|
10
|
+
invalidateTriggerIndex: number;
|
|
11
|
+
};
|
|
12
|
+
finalize?: {
|
|
13
|
+
finalizeToIndex: number;
|
|
14
|
+
finalizeTriggerIndex: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
declare function generateMockMessages(count?: number, options?: MockMessagesOptions): MockStreamResponse[];
|
|
18
|
+
type MockIndexerParams = {
|
|
19
|
+
internalContext?: InternalContext;
|
|
20
|
+
override?: Partial<IndexerConfig<MockFilter, MockBlock>>;
|
|
21
|
+
};
|
|
22
|
+
declare function getMockIndexer(params?: MockIndexerParams): Indexer<{
|
|
23
|
+
readonly filter?: string | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
readonly data?: string | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
type MockRet = {
|
|
28
|
+
data: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A mock sink used for testing. The indexer function can write to the output array.
|
|
32
|
+
* The indexer context is optionally written to the metadata object.
|
|
33
|
+
*/
|
|
34
|
+
declare function mockSink<TFilter, TBlock>({ output, metadata, }: {
|
|
35
|
+
output: unknown[];
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
37
|
+
}): IndexerPlugin<TFilter, TBlock>;
|
|
38
|
+
declare function useMockSink(): {
|
|
39
|
+
output: unknown[];
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { type MockMessagesOptions, type MockRet, generateMockMessages, getMockIndexer, mockSink, useMockSink };
|
|
@@ -0,0 +1,113 @@
|
|
|
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 { internalContext } from './plugins.mjs';
|
|
8
|
+
import 'node:async_hooks';
|
|
9
|
+
import 'unctx';
|
|
10
|
+
import 'hookable';
|
|
11
|
+
import 'node:assert';
|
|
12
|
+
import '@opentelemetry/api';
|
|
13
|
+
|
|
14
|
+
function generateMockMessages(count = 10, options) {
|
|
15
|
+
const invalidateAt = options?.invalidate;
|
|
16
|
+
const finalizeAt = options?.finalize;
|
|
17
|
+
const messages = [];
|
|
18
|
+
for (let i = 0; i < count; i++) {
|
|
19
|
+
if (invalidateAt && i === invalidateAt.invalidateTriggerIndex) {
|
|
20
|
+
messages.push({
|
|
21
|
+
_tag: "invalidate",
|
|
22
|
+
invalidate: {
|
|
23
|
+
cursor: {
|
|
24
|
+
orderKey: BigInt(5e6 + invalidateAt.invalidateFromIndex)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
} else if (finalizeAt && i === finalizeAt.finalizeTriggerIndex) {
|
|
29
|
+
messages.push({
|
|
30
|
+
_tag: "finalize",
|
|
31
|
+
finalize: {
|
|
32
|
+
cursor: {
|
|
33
|
+
orderKey: BigInt(5e6 + finalizeAt.finalizeToIndex)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
messages.push({
|
|
39
|
+
_tag: "data",
|
|
40
|
+
data: {
|
|
41
|
+
cursor: { orderKey: BigInt(5e6 + i - 1) },
|
|
42
|
+
finality: "accepted",
|
|
43
|
+
data: [{ data: `${5e6 + i}` }],
|
|
44
|
+
endCursor: { orderKey: BigInt(5e6 + i) },
|
|
45
|
+
production: "backfill"
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return messages;
|
|
51
|
+
}
|
|
52
|
+
function getMockIndexer(params) {
|
|
53
|
+
const { internalContext: contextParams, override } = params ?? {};
|
|
54
|
+
const { plugins, ...rest } = override ?? {};
|
|
55
|
+
return createIndexer(
|
|
56
|
+
defineIndexer(MockStream)({
|
|
57
|
+
streamUrl: "https://sepolia.ethereum.a5a.ch",
|
|
58
|
+
finality: "accepted",
|
|
59
|
+
filter: {},
|
|
60
|
+
async transform() {
|
|
61
|
+
},
|
|
62
|
+
plugins: [
|
|
63
|
+
internalContext(
|
|
64
|
+
contextParams ?? {
|
|
65
|
+
availableIndexers: ["testing"],
|
|
66
|
+
indexerName: "testing"
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
...plugins ?? []
|
|
70
|
+
],
|
|
71
|
+
...rest ?? {}
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
function mockSink({
|
|
76
|
+
output,
|
|
77
|
+
metadata
|
|
78
|
+
}) {
|
|
79
|
+
return defineIndexerPlugin((indexer) => {
|
|
80
|
+
indexer.hooks.hook("connect:before", ({ request }) => {
|
|
81
|
+
if (metadata?.lastCursor && isCursor(metadata.lastCursor)) {
|
|
82
|
+
request.startingCursor = metadata.lastCursor;
|
|
83
|
+
}
|
|
84
|
+
if (metadata?.lastFilter) {
|
|
85
|
+
request.filter[1] = metadata.lastFilter;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
indexer.hooks.hook("connect:factory", ({ request, endCursor }) => {
|
|
89
|
+
if (request.filter[1]) {
|
|
90
|
+
if (metadata) {
|
|
91
|
+
metadata.lastCursor = endCursor;
|
|
92
|
+
metadata.lastFilter = request.filter[1];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
indexer.hooks.hook("handler:middleware", ({ use }) => {
|
|
97
|
+
use(async (context, next) => {
|
|
98
|
+
context.output = output;
|
|
99
|
+
await next();
|
|
100
|
+
context.output = null;
|
|
101
|
+
if (metadata) {
|
|
102
|
+
metadata.lastCursor = context.endCursor;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function useMockSink() {
|
|
109
|
+
const context = useIndexerContext();
|
|
110
|
+
return { output: context.output };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export { generateMockMessages, getMockIndexer, mockSink, useMockSink };
|
package/dist/plugins/index.cjs
CHANGED
|
@@ -1,7 +1,43 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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
|
+
});
|
|
5
38
|
}
|
|
6
39
|
|
|
7
|
-
exports.defineIndexerPlugin = defineIndexerPlugin;
|
|
40
|
+
exports.defineIndexerPlugin = config.defineIndexerPlugin;
|
|
41
|
+
exports.logger = logger.logger;
|
|
42
|
+
exports.useLogger = logger.useLogger;
|
|
43
|
+
exports.inMemoryPersistence = inMemoryPersistence;
|
package/dist/plugins/index.d.cts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { b as IndexerPlugin } from '../shared/indexer.fedcd831.cjs';
|
|
2
|
+
export { d as defineIndexerPlugin } from '../shared/indexer.fedcd831.cjs';
|
|
3
|
+
import { ConsolaReporter, ConsolaInstance } from 'consola';
|
|
4
|
+
export { ConsolaInstance, ConsolaReporter } from 'consola';
|
|
2
5
|
import '@apibara/protocol';
|
|
3
6
|
import 'hookable';
|
|
4
|
-
|
|
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 };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { b as IndexerPlugin } from '../shared/indexer.fedcd831.mjs';
|
|
2
|
+
export { d as defineIndexerPlugin } from '../shared/indexer.fedcd831.mjs';
|
|
3
|
+
import { ConsolaReporter, ConsolaInstance } from 'consola';
|
|
4
|
+
export { ConsolaInstance, ConsolaReporter } from 'consola';
|
|
2
5
|
import '@apibara/protocol';
|
|
3
6
|
import 'hookable';
|
|
4
|
-
|
|
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 };
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { b as IndexerPlugin } from '../shared/indexer.fedcd831.js';
|
|
2
|
+
export { d as defineIndexerPlugin } from '../shared/indexer.fedcd831.js';
|
|
3
|
+
import { ConsolaReporter, ConsolaInstance } from 'consola';
|
|
4
|
+
export { ConsolaInstance, ConsolaReporter } from 'consola';
|
|
2
5
|
import '@apibara/protocol';
|
|
3
6
|
import 'hookable';
|
|
4
|
-
|
|
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 };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
+
});
|
|
3
36
|
}
|
|
4
37
|
|
|
5
|
-
export { defineIndexerPlugin };
|
|
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;
|