apibara 2.1.0-beta.5 → 2.1.0-beta.7
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/chunks/add.mjs +5 -5
- package/dist/core/index.mjs +5 -3
- package/dist/create/index.mjs +30 -66
- package/dist/rollup/index.mjs +4 -3
- package/dist/runtime/dev.mjs +3 -0
- package/dist/runtime/internal/app.d.ts +1 -1
- package/dist/runtime/internal/app.mjs +11 -3
- package/dist/runtime/start.mjs +5 -0
- package/dist/types/index.d.mts +2 -0
- package/dist/types/index.d.ts +2 -0
- package/package.json +5 -7
- package/src/cli/commands/add.ts +5 -5
- package/src/core/build/error.ts +3 -10
- package/src/core/config/defaults.ts +3 -0
- package/src/create/add.ts +5 -2
- package/src/create/init.ts +3 -1
- package/src/create/templates.ts +24 -83
- package/src/rollup/config.ts +3 -1
- package/src/rollup/plugins/indexers.ts +1 -1
- package/src/runtime/dev.ts +3 -0
- package/src/runtime/internal/app.ts +13 -5
- package/src/runtime/start.ts +5 -0
- package/src/types/config.ts +2 -0
- package/src/types/virtual/indexers.d.ts +4 -1
package/dist/chunks/add.mjs
CHANGED
|
@@ -9,24 +9,24 @@ const add = defineCommand({
|
|
|
9
9
|
args: {
|
|
10
10
|
indexerId: {
|
|
11
11
|
type: "positional",
|
|
12
|
-
description: "Indexer ID",
|
|
12
|
+
description: "Indexer ID - must be in kebab-case",
|
|
13
13
|
required: false
|
|
14
14
|
},
|
|
15
15
|
chain: {
|
|
16
16
|
type: "string",
|
|
17
|
-
description: "
|
|
17
|
+
description: "Blockchain - ethereum, beaconchain, starknet"
|
|
18
18
|
},
|
|
19
19
|
network: {
|
|
20
20
|
type: "string",
|
|
21
|
-
description: "Network"
|
|
21
|
+
description: "Network - mainnet, sepolia, other"
|
|
22
22
|
},
|
|
23
23
|
storage: {
|
|
24
24
|
type: "string",
|
|
25
|
-
description: "Storage"
|
|
25
|
+
description: "Storage - postgres, none"
|
|
26
26
|
},
|
|
27
27
|
dnaUrl: {
|
|
28
28
|
type: "string",
|
|
29
|
-
description: "DNA URL"
|
|
29
|
+
description: "DNA URL - https://custom-dna-url.apibara.org"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
async run({ args }) {
|
package/dist/core/index.mjs
CHANGED
|
@@ -24,7 +24,9 @@ const ApibaraDefaults = {
|
|
|
24
24
|
strict: false,
|
|
25
25
|
generateRuntimeConfigTypes: true,
|
|
26
26
|
internalPaths: false
|
|
27
|
-
}
|
|
27
|
+
},
|
|
28
|
+
node: true,
|
|
29
|
+
exportConditions: ["node"]
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
async function resolvePathOptions(options) {
|
|
@@ -141,11 +143,11 @@ function formatRollupError(_error) {
|
|
|
141
143
|
for (const error of errors) {
|
|
142
144
|
const id = error.path || error.id || _error.id;
|
|
143
145
|
let path = isAbsolute(id) ? relative(process.cwd(), id) : id;
|
|
144
|
-
const location = error.loc
|
|
146
|
+
const location = error.loc;
|
|
145
147
|
if (location) {
|
|
146
148
|
path += `:${location.line}:${location.column}`;
|
|
147
149
|
}
|
|
148
|
-
const text = error.
|
|
150
|
+
const text = error.frame;
|
|
149
151
|
logs.push(
|
|
150
152
|
`Rollup error while processing \`${path}\`` + text ? "\n\n" + text : ""
|
|
151
153
|
);
|
package/dist/create/index.mjs
CHANGED
|
@@ -446,15 +446,19 @@ function generateIndexer({
|
|
|
446
446
|
return `import { defineIndexer } from "@apibara/indexer";
|
|
447
447
|
import { useLogger } from "@apibara/indexer/plugins";
|
|
448
448
|
${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
|
|
449
|
+
${storage === "postgres" ? `import { drizzle } from "@apibara/plugin-drizzle";` : ""}
|
|
449
450
|
${chain === "ethereum" ? `import { EvmStream } from "@apibara/evm";` : chain === "beaconchain" ? `import { BeaconChainStream } from "@apibara/beaconchain";` : chain === "starknet" ? `import { StarknetStream } from "@apibara/starknet";` : ""}
|
|
450
451
|
${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
|
|
451
|
-
${storage === "postgres" ? `import
|
|
452
|
+
${storage === "postgres" ? `import * as schema from "../lib/schema";` : ""}
|
|
452
453
|
|
|
453
454
|
|
|
454
455
|
export default function (runtimeConfig${language === "typescript" ? ": ApibaraRuntimeConfig" : ""}) {
|
|
455
456
|
const indexerId = "${indexerId}";
|
|
456
457
|
const { startingBlock, streamUrl${storage === "postgres" ? ", postgresConnectionString" : ""} } = runtimeConfig[indexerId];
|
|
457
|
-
${storage === "postgres" ?
|
|
458
|
+
${storage === "postgres" ? `const db = drizzle({
|
|
459
|
+
schema,
|
|
460
|
+
connectionString: postgresConnectionString,
|
|
461
|
+
});` : ""}
|
|
458
462
|
|
|
459
463
|
return defineIndexer(${chain === "ethereum" ? "EvmStream" : chain === "beaconchain" ? "BeaconChainStream" : chain === "starknet" ? "StarknetStream" : ""})({
|
|
460
464
|
streamUrl,
|
|
@@ -463,7 +467,7 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
463
467
|
filter: {
|
|
464
468
|
header: "always",
|
|
465
469
|
},
|
|
466
|
-
plugins: [${storage === "postgres" ? "drizzleStorage({ db,
|
|
470
|
+
plugins: [${storage === "postgres" ? "drizzleStorage({ db, migrate: { migrationsFolder: './drizzle' } })" : ""}],
|
|
467
471
|
async transform({ endCursor, finality }) {
|
|
468
472
|
const logger = useLogger();
|
|
469
473
|
|
|
@@ -475,14 +479,12 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
475
479
|
);
|
|
476
480
|
|
|
477
481
|
${storage === "postgres" ? `// Example snippet to insert data into db using drizzle with postgres
|
|
478
|
-
//
|
|
479
|
-
|
|
480
|
-
//
|
|
481
|
-
//
|
|
482
|
-
//
|
|
483
|
-
//
|
|
484
|
-
// });
|
|
485
|
-
// }` : ""}
|
|
482
|
+
// const { db: database } = useDrizzleStorage();
|
|
483
|
+
|
|
484
|
+
// await database.insert(schema.cursorTable).values({
|
|
485
|
+
// endCursor: Number(endCursor?.orderKey),
|
|
486
|
+
// uniqueKey: \`\${endCursor?.uniqueKey}\`,
|
|
487
|
+
// });` : ""}
|
|
486
488
|
},
|
|
487
489
|
});
|
|
488
490
|
}
|
|
@@ -581,7 +583,7 @@ async function updateApibaraConfigFile({
|
|
|
581
583
|
await formatFile(pathToConfig);
|
|
582
584
|
}
|
|
583
585
|
async function createDrizzleStorageFiles(options) {
|
|
584
|
-
const { cwd, language, storage } = options;
|
|
586
|
+
const { cwd, language, storage, indexerId } = options;
|
|
585
587
|
if (storage !== "postgres")
|
|
586
588
|
return;
|
|
587
589
|
const fileExtension = language === "typescript" ? "ts" : "js";
|
|
@@ -595,11 +597,11 @@ async function createDrizzleStorageFiles(options) {
|
|
|
595
597
|
const drizzleConfigContent = `${language === "typescript" ? 'import type { Config } from "drizzle-kit";' : ""}
|
|
596
598
|
|
|
597
599
|
export default {
|
|
598
|
-
schema: "./lib/schema
|
|
600
|
+
schema: "./lib/schema.${fileExtension}",
|
|
599
601
|
out: "./drizzle",
|
|
600
602
|
dialect: "postgresql",
|
|
601
603
|
dbCredentials: {
|
|
602
|
-
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "",
|
|
604
|
+
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}",
|
|
603
605
|
},
|
|
604
606
|
}${language === "typescript" ? " satisfies Config" : ""};`;
|
|
605
607
|
fs.writeFileSync(drizzleConfigPath, drizzleConfigContent);
|
|
@@ -614,14 +616,14 @@ export default {
|
|
|
614
616
|
fileName: `lib/${schemaFileName}`
|
|
615
617
|
});
|
|
616
618
|
if (!schemaExists || schemaOverwrite) {
|
|
617
|
-
const schemaContent = `// --- Add your pg table schemas here ----
|
|
619
|
+
const schemaContent = `// --- Add your pg table schemas here ----
|
|
618
620
|
|
|
619
621
|
// import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
620
622
|
|
|
621
|
-
// export const
|
|
623
|
+
// export const cursorTable = pgTable("cursor_table", {
|
|
622
624
|
// id: uuid("id").primaryKey().defaultRandom(),
|
|
623
|
-
//
|
|
624
|
-
//
|
|
625
|
+
// endCursor: bigint("end_cursor", { mode: "number" }),
|
|
626
|
+
// uniqueKey: text("unique_key"),
|
|
625
627
|
// });
|
|
626
628
|
|
|
627
629
|
export {};
|
|
@@ -631,48 +633,6 @@ export {};
|
|
|
631
633
|
await formatFile(schemaPath);
|
|
632
634
|
consola.success(`Created ${cyan("lib/schema.ts")}`);
|
|
633
635
|
}
|
|
634
|
-
const dbFileName = `db.${fileExtension}`;
|
|
635
|
-
const dbPath = path.join(cwd, "lib", dbFileName);
|
|
636
|
-
const { exists: dbExists, overwrite: dbOverwrite } = await checkFileExists(
|
|
637
|
-
dbPath,
|
|
638
|
-
{
|
|
639
|
-
askPrompt: true,
|
|
640
|
-
fileName: `lib/${dbFileName}`,
|
|
641
|
-
allowIgnore: true
|
|
642
|
-
}
|
|
643
|
-
);
|
|
644
|
-
if (!dbExists || dbOverwrite) {
|
|
645
|
-
const dbContent = `import * as schema from "./schema";
|
|
646
|
-
import { drizzle as nodePgDrizzle } from "drizzle-orm/node-postgres";
|
|
647
|
-
import { drizzle as pgLiteDrizzle } from "drizzle-orm/pglite";
|
|
648
|
-
import pg from "pg";
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
export function getDrizzlePgDatabase(connectionString${language === "typescript" ? ": string" : ""}) {
|
|
652
|
-
// Create pglite instance
|
|
653
|
-
if (connectionString.includes("memory")) {
|
|
654
|
-
return {
|
|
655
|
-
db: pgLiteDrizzle({
|
|
656
|
-
schema,
|
|
657
|
-
connection: {
|
|
658
|
-
dataDir: connectionString,
|
|
659
|
-
},
|
|
660
|
-
}),
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// Create node-postgres instance
|
|
665
|
-
const pool = new pg.Pool({
|
|
666
|
-
connectionString,
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
return { db: nodePgDrizzle(pool, { schema }) };
|
|
670
|
-
}`;
|
|
671
|
-
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
672
|
-
fs.writeFileSync(dbPath, dbContent);
|
|
673
|
-
await formatFile(dbPath);
|
|
674
|
-
consola.success(`Created ${cyan(`lib/${dbFileName}`)}`);
|
|
675
|
-
}
|
|
676
636
|
console.log("\n");
|
|
677
637
|
if (!schemaExists || schemaOverwrite) {
|
|
678
638
|
consola.info(
|
|
@@ -688,15 +648,15 @@ ${yellow(`
|
|
|
688
648
|
|
|
689
649
|
import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
690
650
|
|
|
691
|
-
export const
|
|
651
|
+
export const cursorTable = pgTable("cursor_table", {
|
|
692
652
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
693
|
-
|
|
694
|
-
|
|
653
|
+
endCursor: bigint("end_cursor", { mode: "number" }),
|
|
654
|
+
uniqueKey: text("unique_key"),
|
|
695
655
|
});`)}`);
|
|
696
656
|
console.log("\n");
|
|
697
657
|
}
|
|
698
658
|
consola.info(
|
|
699
|
-
`Run ${green(`${options.packageManager} run drizzle:generate`)} & ${green(`${options.packageManager} run drizzle:migrate`)} to generate and apply migrations.`
|
|
659
|
+
`Run ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:generate`)} & ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:migrate`)} to generate and apply migrations.`
|
|
700
660
|
);
|
|
701
661
|
}
|
|
702
662
|
async function createStorageRelatedFiles(options) {
|
|
@@ -902,7 +862,9 @@ async function initializeProject({
|
|
|
902
862
|
const pkgManager = getPackageManager();
|
|
903
863
|
consola$1.info(
|
|
904
864
|
"Run ",
|
|
905
|
-
green(
|
|
865
|
+
green(
|
|
866
|
+
`${pkgManager.name}${pkgManager.name === "npm" ? " run" : ""} install`
|
|
867
|
+
),
|
|
906
868
|
" to install all dependencies"
|
|
907
869
|
);
|
|
908
870
|
}
|
|
@@ -1059,7 +1021,9 @@ async function addIndexer({
|
|
|
1059
1021
|
await createStorageRelatedFiles(options);
|
|
1060
1022
|
console.log();
|
|
1061
1023
|
consola$1.info(
|
|
1062
|
-
`Before running the indexer, run ${cyan(`${options.packageManager} run install`)}${language === "typescript" ? " & " + cyan(
|
|
1024
|
+
`Before running the indexer, run ${cyan(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} install`)}${language === "typescript" ? " & " + cyan(
|
|
1025
|
+
`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} prepare`
|
|
1026
|
+
) : ""}`
|
|
1063
1027
|
);
|
|
1064
1028
|
}
|
|
1065
1029
|
|
package/dist/rollup/index.mjs
CHANGED
|
@@ -74,7 +74,7 @@ function indexers(apibara) {
|
|
|
74
74
|
const indexers2 = [...new Set(apibara.indexers)];
|
|
75
75
|
return virtual({
|
|
76
76
|
"#apibara-internal-virtual/indexers": `
|
|
77
|
-
${indexers2.map((i) => `import _${hash(i)} from '${i.indexer}';`).join("\n")}
|
|
77
|
+
${indexers2.map((i) => `import * as _${hash(i)} from '${i.indexer}';`).join("\n")}
|
|
78
78
|
|
|
79
79
|
export const indexers = [
|
|
80
80
|
${indexers2.map((i) => `{ name: "${i.name}", indexer: _${hash(i)} }`).join(",\n")}
|
|
@@ -138,8 +138,9 @@ function getRollupConfig(apibara) {
|
|
|
138
138
|
rollupConfig.plugins.push(
|
|
139
139
|
nodeResolve({
|
|
140
140
|
extensions,
|
|
141
|
-
preferBuiltins:
|
|
142
|
-
mainFields: ["main"]
|
|
141
|
+
preferBuiltins: !!apibara.options.node,
|
|
142
|
+
mainFields: ["main"],
|
|
143
|
+
exportConditions: apibara.options.exportConditions
|
|
143
144
|
})
|
|
144
145
|
);
|
|
145
146
|
rollupConfig.plugins.push(indexers(apibara));
|
package/dist/runtime/dev.mjs
CHANGED
|
@@ -33,6 +33,9 @@ const startCommand = defineCommand({
|
|
|
33
33
|
await Promise.all(
|
|
34
34
|
selectedIndexers.map(async (indexer) => {
|
|
35
35
|
const indexerInstance = createIndexer(indexer, preset);
|
|
36
|
+
if (!indexerInstance) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
36
39
|
const client = createClient(
|
|
37
40
|
indexerInstance.streamConfig,
|
|
38
41
|
indexerInstance.options.streamUrl
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const availableIndexers: any;
|
|
2
|
-
export declare function createIndexer(indexerName: string, preset?: string): import("@apibara/indexer").Indexer<unknown, unknown
|
|
2
|
+
export declare function createIndexer(indexerName: string, preset?: string): import("@apibara/indexer").Indexer<unknown, unknown> | undefined;
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
inMemoryPersistence,
|
|
7
7
|
logger
|
|
8
8
|
} from "@apibara/indexer/plugins";
|
|
9
|
+
import consola from "consola";
|
|
9
10
|
import { config } from "#apibara-internal-virtual/config";
|
|
10
11
|
import { indexers } from "#apibara-internal-virtual/indexers";
|
|
11
12
|
import { createLogger } from "./logger.mjs";
|
|
@@ -30,7 +31,14 @@ export function createIndexer(indexerName, preset) {
|
|
|
30
31
|
`Specified indexer "${indexerName}" but it was not defined`
|
|
31
32
|
);
|
|
32
33
|
}
|
|
33
|
-
const
|
|
34
|
+
const indexerModule = indexerDefinition.indexer?.default;
|
|
35
|
+
if (indexerModule === void 0) {
|
|
36
|
+
consola.warn(
|
|
37
|
+
`Specified indexer "${indexerName}" but it does not export a default. Ignoring.`
|
|
38
|
+
);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const definition = typeof indexerModule === "function" ? indexerModule(runtimeConfig) : indexerModule;
|
|
34
42
|
let reporter = createLogger({
|
|
35
43
|
indexer: indexerName,
|
|
36
44
|
preset,
|
|
@@ -48,9 +56,9 @@ export function createIndexer(indexerName, preset) {
|
|
|
48
56
|
indexerName,
|
|
49
57
|
availableIndexers
|
|
50
58
|
}),
|
|
59
|
+
logger({ logger: reporter }),
|
|
51
60
|
inMemoryPersistence(),
|
|
52
|
-
...definition.plugins ?? []
|
|
53
|
-
logger({ logger: reporter })
|
|
61
|
+
...definition.plugins ?? []
|
|
54
62
|
];
|
|
55
63
|
return _createIndexer(definition);
|
|
56
64
|
}
|
package/dist/runtime/start.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { runWithReconnect } from "@apibara/indexer";
|
|
2
2
|
import { createClient } from "@apibara/protocol";
|
|
3
3
|
import { defineCommand, runMain } from "citty";
|
|
4
|
+
import consola from "consola";
|
|
4
5
|
import { createIndexer } from "./internal/app.mjs";
|
|
5
6
|
const startCommand = defineCommand({
|
|
6
7
|
meta: {
|
|
@@ -21,6 +22,10 @@ const startCommand = defineCommand({
|
|
|
21
22
|
async run({ args }) {
|
|
22
23
|
const { indexer, preset } = args;
|
|
23
24
|
const indexerInstance = createIndexer(indexer, preset);
|
|
25
|
+
if (!indexerInstance) {
|
|
26
|
+
consola.error(`Specified indexer "${indexer}" but it was not defined`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
24
29
|
const client = createClient(
|
|
25
30
|
indexerInstance.streamConfig,
|
|
26
31
|
indexerInstance.options.streamUrl
|
package/dist/types/index.d.mts
CHANGED
|
@@ -65,6 +65,8 @@ interface ApibaraOptions<T extends Record<string, DeepPartial<Pick<ApibaraConfig
|
|
|
65
65
|
sourceMap?: boolean;
|
|
66
66
|
entry: string;
|
|
67
67
|
commonJS?: RollupCommonJSOptions;
|
|
68
|
+
node: boolean;
|
|
69
|
+
exportConditions?: string[];
|
|
68
70
|
typescript: {
|
|
69
71
|
strict?: boolean;
|
|
70
72
|
internalPaths?: boolean;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ interface ApibaraOptions<T extends Record<string, DeepPartial<Pick<ApibaraConfig
|
|
|
65
65
|
sourceMap?: boolean;
|
|
66
66
|
entry: string;
|
|
67
67
|
commonJS?: RollupCommonJSOptions;
|
|
68
|
+
node: boolean;
|
|
69
|
+
exportConditions?: string[];
|
|
68
70
|
typescript: {
|
|
69
71
|
strict?: boolean;
|
|
70
72
|
internalPaths?: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apibara",
|
|
3
|
-
"version": "2.1.0-beta.
|
|
3
|
+
"version": "2.1.0-beta.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/core/index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"playground:start": "pnpm playground start --dir playground --indexer starknet"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@apibara/starknet": "2.1.0-beta.
|
|
79
|
+
"@apibara/starknet": "2.1.0-beta.7",
|
|
80
80
|
"@types/fs-extra": "^11.0.4",
|
|
81
81
|
"@types/node": "^20.14.0",
|
|
82
82
|
"@types/prompts": "^2.4.9",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"vitest": "^1.6.0"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"@apibara/indexer": "2.1.0-beta.
|
|
91
|
-
"@apibara/protocol": "2.1.0-beta.
|
|
90
|
+
"@apibara/indexer": "2.1.0-beta.7",
|
|
91
|
+
"@apibara/protocol": "2.1.0-beta.7",
|
|
92
92
|
"@rollup/plugin-commonjs": "^26.0.1",
|
|
93
93
|
"@rollup/plugin-json": "^6.1.0",
|
|
94
94
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
@@ -99,7 +99,6 @@
|
|
|
99
99
|
"citty": "^0.1.6",
|
|
100
100
|
"consola": "^3.2.3",
|
|
101
101
|
"defu": "^6.1.4",
|
|
102
|
-
"esbuild": "^0.23.0",
|
|
103
102
|
"fs-extra": "^11.2.0",
|
|
104
103
|
"hookable": "^5.5.3",
|
|
105
104
|
"klona": "^2.0.6",
|
|
@@ -111,8 +110,7 @@
|
|
|
111
110
|
"pkg-types": "^1.1.3",
|
|
112
111
|
"prettier": "^3.5.2",
|
|
113
112
|
"prompts": "^2.4.2",
|
|
114
|
-
"rollup": "^4.
|
|
115
|
-
"rollup-plugin-esbuild": "^6.1.1",
|
|
113
|
+
"rollup": "^4.34.8",
|
|
116
114
|
"ts-morph": "^25.0.1",
|
|
117
115
|
"tslib": "^2.6.3",
|
|
118
116
|
"untyped": "^1.4.2"
|
package/src/cli/commands/add.ts
CHANGED
|
@@ -10,24 +10,24 @@ export default defineCommand({
|
|
|
10
10
|
args: {
|
|
11
11
|
indexerId: {
|
|
12
12
|
type: "positional",
|
|
13
|
-
description: "Indexer ID",
|
|
13
|
+
description: "Indexer ID - must be in kebab-case",
|
|
14
14
|
required: false,
|
|
15
15
|
},
|
|
16
16
|
chain: {
|
|
17
17
|
type: "string",
|
|
18
|
-
description: "
|
|
18
|
+
description: "Blockchain - ethereum, beaconchain, starknet",
|
|
19
19
|
},
|
|
20
20
|
network: {
|
|
21
21
|
type: "string",
|
|
22
|
-
description: "Network",
|
|
22
|
+
description: "Network - mainnet, sepolia, other",
|
|
23
23
|
},
|
|
24
24
|
storage: {
|
|
25
25
|
type: "string",
|
|
26
|
-
description: "Storage",
|
|
26
|
+
description: "Storage - postgres, none",
|
|
27
27
|
},
|
|
28
28
|
dnaUrl: {
|
|
29
29
|
type: "string",
|
|
30
|
-
description: "DNA URL",
|
|
30
|
+
description: "DNA URL - https://custom-dna-url.apibara.org",
|
|
31
31
|
},
|
|
32
32
|
},
|
|
33
33
|
async run({ args }) {
|
package/src/core/build/error.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import type esbuild from "esbuild";
|
|
2
1
|
import { isAbsolute, relative } from "pathe";
|
|
3
2
|
import type rollup from "rollup";
|
|
4
3
|
|
|
5
|
-
export function formatRollupError(
|
|
6
|
-
_error: rollup.RollupError | esbuild.OnResolveResult,
|
|
7
|
-
) {
|
|
4
|
+
export function formatRollupError(_error: rollup.RollupError) {
|
|
8
5
|
try {
|
|
9
6
|
const logs: string[] = [_error.toString()];
|
|
10
7
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
@@ -12,15 +9,11 @@ export function formatRollupError(
|
|
|
12
9
|
for (const error of errors) {
|
|
13
10
|
const id = error.path || error.id || (_error as rollup.RollupError).id;
|
|
14
11
|
let path = isAbsolute(id) ? relative(process.cwd(), id) : id;
|
|
15
|
-
const location =
|
|
16
|
-
(error as rollup.RollupError).loc ||
|
|
17
|
-
(error as esbuild.PartialMessage).location;
|
|
12
|
+
const location = (error as rollup.RollupError).loc;
|
|
18
13
|
if (location) {
|
|
19
14
|
path += `:${location.line}:${location.column}`;
|
|
20
15
|
}
|
|
21
|
-
const text =
|
|
22
|
-
(error as esbuild.PartialMessage).text ||
|
|
23
|
-
(error as rollup.RollupError).frame;
|
|
16
|
+
const text = (error as rollup.RollupError).frame;
|
|
24
17
|
|
|
25
18
|
logs.push(
|
|
26
19
|
`Rollup error while processing \`${path}\`` + text ? "\n\n" + text : "",
|
package/src/create/add.ts
CHANGED
|
@@ -229,9 +229,12 @@ export async function addIndexer({
|
|
|
229
229
|
console.log();
|
|
230
230
|
|
|
231
231
|
consola.info(
|
|
232
|
-
`Before running the indexer, run ${cyan(`${options.packageManager} run install`)}${
|
|
232
|
+
`Before running the indexer, run ${cyan(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} install`)}${
|
|
233
233
|
language === "typescript"
|
|
234
|
-
? " & " +
|
|
234
|
+
? " & " +
|
|
235
|
+
cyan(
|
|
236
|
+
`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} prepare`,
|
|
237
|
+
)
|
|
235
238
|
: ""
|
|
236
239
|
}`,
|
|
237
240
|
);
|
package/src/create/init.ts
CHANGED
|
@@ -171,7 +171,9 @@ export async function initializeProject({
|
|
|
171
171
|
const pkgManager = getPackageManager();
|
|
172
172
|
consola.info(
|
|
173
173
|
"Run ",
|
|
174
|
-
green(
|
|
174
|
+
green(
|
|
175
|
+
`${pkgManager.name}${pkgManager.name === "npm" ? " run" : ""} install`,
|
|
176
|
+
),
|
|
175
177
|
" to install all dependencies",
|
|
176
178
|
);
|
|
177
179
|
}
|
package/src/create/templates.ts
CHANGED
|
@@ -82,6 +82,7 @@ export function generateIndexer({
|
|
|
82
82
|
return `import { defineIndexer } from "@apibara/indexer";
|
|
83
83
|
import { useLogger } from "@apibara/indexer/plugins";
|
|
84
84
|
${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
|
|
85
|
+
${storage === "postgres" ? `import { drizzle } from "@apibara/plugin-drizzle";` : ""}
|
|
85
86
|
${
|
|
86
87
|
chain === "ethereum"
|
|
87
88
|
? `import { EvmStream } from "@apibara/evm";`
|
|
@@ -92,11 +93,7 @@ ${
|
|
|
92
93
|
: ""
|
|
93
94
|
}
|
|
94
95
|
${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
|
|
95
|
-
${
|
|
96
|
-
storage === "postgres"
|
|
97
|
-
? `import { getDrizzlePgDatabase } from "../lib/db";`
|
|
98
|
-
: ""
|
|
99
|
-
}
|
|
96
|
+
${storage === "postgres" ? `import * as schema from "../lib/schema";` : ""}
|
|
100
97
|
|
|
101
98
|
|
|
102
99
|
export default function (runtimeConfig${language === "typescript" ? ": ApibaraRuntimeConfig" : ""}) {
|
|
@@ -104,7 +101,10 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
104
101
|
const { startingBlock, streamUrl${storage === "postgres" ? ", postgresConnectionString" : ""} } = runtimeConfig[indexerId];
|
|
105
102
|
${
|
|
106
103
|
storage === "postgres"
|
|
107
|
-
?
|
|
104
|
+
? `const db = drizzle({
|
|
105
|
+
schema,
|
|
106
|
+
connectionString: postgresConnectionString,
|
|
107
|
+
});`
|
|
108
108
|
: ""
|
|
109
109
|
}
|
|
110
110
|
|
|
@@ -123,7 +123,7 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
123
123
|
filter: {
|
|
124
124
|
header: "always",
|
|
125
125
|
},
|
|
126
|
-
plugins: [${storage === "postgres" ? "drizzleStorage({ db,
|
|
126
|
+
plugins: [${storage === "postgres" ? "drizzleStorage({ db, migrate: { migrationsFolder: './drizzle' } })" : ""}],
|
|
127
127
|
async transform({ endCursor, finality }) {
|
|
128
128
|
const logger = useLogger();
|
|
129
129
|
|
|
@@ -137,14 +137,12 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
137
137
|
${
|
|
138
138
|
storage === "postgres"
|
|
139
139
|
? `// Example snippet to insert data into db using drizzle with postgres
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
// });
|
|
147
|
-
// }`
|
|
140
|
+
// const { db: database } = useDrizzleStorage();
|
|
141
|
+
|
|
142
|
+
// await database.insert(schema.cursorTable).values({
|
|
143
|
+
// endCursor: Number(endCursor?.orderKey),
|
|
144
|
+
// uniqueKey: \`\${endCursor?.uniqueKey}\`,
|
|
145
|
+
// });`
|
|
148
146
|
: ""
|
|
149
147
|
}
|
|
150
148
|
},
|
|
@@ -285,7 +283,7 @@ export async function updateApibaraConfigFile({
|
|
|
285
283
|
}
|
|
286
284
|
|
|
287
285
|
export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
288
|
-
const { cwd, language, storage } = options;
|
|
286
|
+
const { cwd, language, storage, indexerId } = options;
|
|
289
287
|
|
|
290
288
|
if (storage !== "postgres") return;
|
|
291
289
|
|
|
@@ -313,11 +311,11 @@ export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
|
313
311
|
const drizzleConfigContent = `${language === "typescript" ? 'import type { Config } from "drizzle-kit";' : ""}
|
|
314
312
|
|
|
315
313
|
export default {
|
|
316
|
-
schema: "./lib/schema
|
|
314
|
+
schema: "./lib/schema.${fileExtension}",
|
|
317
315
|
out: "./drizzle",
|
|
318
316
|
dialect: "postgresql",
|
|
319
317
|
dbCredentials: {
|
|
320
|
-
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "",
|
|
318
|
+
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}",
|
|
321
319
|
},
|
|
322
320
|
}${language === "typescript" ? " satisfies Config" : ""};`;
|
|
323
321
|
|
|
@@ -348,14 +346,14 @@ export default {
|
|
|
348
346
|
});
|
|
349
347
|
|
|
350
348
|
if (!schemaExists || schemaOverwrite) {
|
|
351
|
-
const schemaContent = `// --- Add your pg table schemas here ----
|
|
349
|
+
const schemaContent = `// --- Add your pg table schemas here ----
|
|
352
350
|
|
|
353
351
|
// import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
354
352
|
|
|
355
|
-
// export const
|
|
353
|
+
// export const cursorTable = pgTable("cursor_table", {
|
|
356
354
|
// id: uuid("id").primaryKey().defaultRandom(),
|
|
357
|
-
//
|
|
358
|
-
//
|
|
355
|
+
// endCursor: bigint("end_cursor", { mode: "number" }),
|
|
356
|
+
// uniqueKey: text("unique_key"),
|
|
359
357
|
// });
|
|
360
358
|
|
|
361
359
|
export {};
|
|
@@ -370,63 +368,6 @@ export {};
|
|
|
370
368
|
consola.success(`Created ${cyan("lib/schema.ts")}`);
|
|
371
369
|
}
|
|
372
370
|
|
|
373
|
-
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* DB File
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*/
|
|
380
|
-
const dbFileName = `db.${fileExtension}`;
|
|
381
|
-
|
|
382
|
-
const dbPath = path.join(cwd, "lib", dbFileName);
|
|
383
|
-
|
|
384
|
-
const { exists: dbExists, overwrite: dbOverwrite } = await checkFileExists(
|
|
385
|
-
dbPath,
|
|
386
|
-
{
|
|
387
|
-
askPrompt: true,
|
|
388
|
-
fileName: `lib/${dbFileName}`,
|
|
389
|
-
allowIgnore: true,
|
|
390
|
-
},
|
|
391
|
-
);
|
|
392
|
-
|
|
393
|
-
if (!dbExists || dbOverwrite) {
|
|
394
|
-
const dbContent = `import * as schema from "./schema";
|
|
395
|
-
import { drizzle as nodePgDrizzle } from "drizzle-orm/node-postgres";
|
|
396
|
-
import { drizzle as pgLiteDrizzle } from "drizzle-orm/pglite";
|
|
397
|
-
import pg from "pg";
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
export function getDrizzlePgDatabase(connectionString${language === "typescript" ? ": string" : ""}) {
|
|
401
|
-
// Create pglite instance
|
|
402
|
-
if (connectionString.includes("memory")) {
|
|
403
|
-
return {
|
|
404
|
-
db: pgLiteDrizzle({
|
|
405
|
-
schema,
|
|
406
|
-
connection: {
|
|
407
|
-
dataDir: connectionString,
|
|
408
|
-
},
|
|
409
|
-
}),
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Create node-postgres instance
|
|
414
|
-
const pool = new pg.Pool({
|
|
415
|
-
connectionString,
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
return { db: nodePgDrizzle(pool, { schema }) };
|
|
419
|
-
}`;
|
|
420
|
-
|
|
421
|
-
// create directory if it doesn't exist
|
|
422
|
-
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
423
|
-
fs.writeFileSync(dbPath, dbContent);
|
|
424
|
-
|
|
425
|
-
await formatFile(dbPath);
|
|
426
|
-
|
|
427
|
-
consola.success(`Created ${cyan(`lib/${dbFileName}`)}`);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
371
|
console.log("\n");
|
|
431
372
|
|
|
432
373
|
// If schema file is created, show the example
|
|
@@ -446,17 +387,17 @@ ${yellow(`
|
|
|
446
387
|
|
|
447
388
|
import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
448
389
|
|
|
449
|
-
export const
|
|
390
|
+
export const cursorTable = pgTable("cursor_table", {
|
|
450
391
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
451
|
-
|
|
452
|
-
|
|
392
|
+
endCursor: bigint("end_cursor", { mode: "number" }),
|
|
393
|
+
uniqueKey: text("unique_key"),
|
|
453
394
|
});`)}`);
|
|
454
395
|
|
|
455
396
|
console.log("\n");
|
|
456
397
|
}
|
|
457
398
|
|
|
458
399
|
consola.info(
|
|
459
|
-
`Run ${green(`${options.packageManager} run drizzle:generate`)} & ${green(`${options.packageManager} run drizzle:migrate`)} to generate and apply migrations.`,
|
|
400
|
+
`Run ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:generate`)} & ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:migrate`)} to generate and apply migrations.`,
|
|
460
401
|
);
|
|
461
402
|
}
|
|
462
403
|
|
package/src/rollup/config.ts
CHANGED
|
@@ -76,10 +76,12 @@ export function getRollupConfig(apibara: Apibara): RollupConfig {
|
|
|
76
76
|
rollupConfig.plugins.push(
|
|
77
77
|
nodeResolve({
|
|
78
78
|
extensions,
|
|
79
|
-
preferBuiltins:
|
|
79
|
+
preferBuiltins: !!apibara.options.node,
|
|
80
80
|
mainFields: ["main"],
|
|
81
|
+
exportConditions: apibara.options.exportConditions,
|
|
81
82
|
}),
|
|
82
83
|
);
|
|
84
|
+
|
|
83
85
|
rollupConfig.plugins.push(indexers(apibara));
|
|
84
86
|
rollupConfig.plugins.push(appConfig(apibara));
|
|
85
87
|
|
|
@@ -7,7 +7,7 @@ export function indexers(apibara: Apibara) {
|
|
|
7
7
|
|
|
8
8
|
return virtual({
|
|
9
9
|
"#apibara-internal-virtual/indexers": `
|
|
10
|
-
${indexers.map((i) => `import _${hash(i)} from '${i.indexer}';`).join("\n")}
|
|
10
|
+
${indexers.map((i) => `import * as _${hash(i)} from '${i.indexer}';`).join("\n")}
|
|
11
11
|
|
|
12
12
|
export const indexers = [
|
|
13
13
|
${indexers.map((i) => `{ name: "${i.name}", indexer: _${hash(i)} }`).join(",\n")}
|
package/src/runtime/dev.ts
CHANGED
|
@@ -37,6 +37,9 @@ const startCommand = defineCommand({
|
|
|
37
37
|
await Promise.all(
|
|
38
38
|
selectedIndexers.map(async (indexer) => {
|
|
39
39
|
const indexerInstance = createIndexer(indexer, preset);
|
|
40
|
+
if (!indexerInstance) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
40
43
|
|
|
41
44
|
const client = createClient(
|
|
42
45
|
indexerInstance.streamConfig,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
inMemoryPersistence,
|
|
9
9
|
logger,
|
|
10
10
|
} from "@apibara/indexer/plugins";
|
|
11
|
+
import consola from "consola";
|
|
11
12
|
import { config } from "#apibara-internal-virtual/config";
|
|
12
13
|
import { indexers } from "#apibara-internal-virtual/indexers";
|
|
13
14
|
import { createLogger } from "./logger";
|
|
@@ -42,10 +43,18 @@ export function createIndexer(indexerName: string, preset?: string) {
|
|
|
42
43
|
);
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
const indexerModule = indexerDefinition.indexer?.default;
|
|
47
|
+
if (indexerModule === undefined) {
|
|
48
|
+
consola.warn(
|
|
49
|
+
`Specified indexer "${indexerName}" but it does not export a default. Ignoring.`,
|
|
50
|
+
);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
45
54
|
const definition =
|
|
46
|
-
typeof
|
|
47
|
-
?
|
|
48
|
-
:
|
|
55
|
+
typeof indexerModule === "function"
|
|
56
|
+
? indexerModule(runtimeConfig)
|
|
57
|
+
: indexerModule;
|
|
49
58
|
|
|
50
59
|
let reporter: ConsolaReporter = createLogger({
|
|
51
60
|
indexer: indexerName,
|
|
@@ -63,15 +72,14 @@ export function createIndexer(indexerName: string, preset?: string) {
|
|
|
63
72
|
|
|
64
73
|
// Put the in-memory persistence plugin first so that it can be overridden by any user-defined
|
|
65
74
|
// persistence plugin.
|
|
66
|
-
// Put the logger last since we want to override any user-defined logger.
|
|
67
75
|
definition.plugins = [
|
|
68
76
|
internalContext({
|
|
69
77
|
indexerName,
|
|
70
78
|
availableIndexers,
|
|
71
79
|
} as InternalContext),
|
|
80
|
+
logger({ logger: reporter }),
|
|
72
81
|
inMemoryPersistence(),
|
|
73
82
|
...(definition.plugins ?? []),
|
|
74
|
-
logger({ logger: reporter }),
|
|
75
83
|
];
|
|
76
84
|
|
|
77
85
|
return _createIndexer(definition);
|
package/src/runtime/start.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { runWithReconnect } from "@apibara/indexer";
|
|
2
2
|
import { createClient } from "@apibara/protocol";
|
|
3
3
|
import { defineCommand, runMain } from "citty";
|
|
4
|
+
import consola from "consola";
|
|
4
5
|
import { createIndexer } from "./internal/app";
|
|
5
6
|
|
|
6
7
|
const startCommand = defineCommand({
|
|
@@ -23,6 +24,10 @@ const startCommand = defineCommand({
|
|
|
23
24
|
const { indexer, preset } = args;
|
|
24
25
|
|
|
25
26
|
const indexerInstance = createIndexer(indexer, preset);
|
|
27
|
+
if (!indexerInstance) {
|
|
28
|
+
consola.error(`Specified indexer "${indexer}" but it was not defined`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
26
31
|
|
|
27
32
|
const client = createClient(
|
|
28
33
|
indexerInstance.streamConfig,
|
package/src/types/config.ts
CHANGED
|
@@ -7,4 +7,7 @@ export type IndexerConstructor =
|
|
|
7
7
|
) => IndexerWithStreamConfig<unknown, unknown, unknown>)
|
|
8
8
|
| IndexerWithStreamConfig<unknown, unknown, unknown>;
|
|
9
9
|
|
|
10
|
-
export const indexers: {
|
|
10
|
+
export const indexers: {
|
|
11
|
+
name: string;
|
|
12
|
+
indexer: { default?: IndexerConstructor | undefined };
|
|
13
|
+
}[] = [];
|