apibara 2.1.0-beta.3 → 2.1.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 (81) hide show
  1. package/dist/chunks/add.mjs +16 -8
  2. package/dist/chunks/build.mjs +4 -2
  3. package/dist/chunks/dev.mjs +44 -14
  4. package/dist/chunks/init.mjs +11 -7
  5. package/dist/chunks/prepare.mjs +4 -2
  6. package/dist/chunks/start.mjs +14 -4
  7. package/dist/chunks/write-project-info.mjs +50 -0
  8. package/dist/cli/index.mjs +2 -1
  9. package/dist/core/index.mjs +98 -68
  10. package/dist/create/index.d.mts +2 -1
  11. package/dist/create/index.d.ts +2 -1
  12. package/dist/create/index.mjs +142 -112
  13. package/dist/hooks/index.mjs +1 -1
  14. package/dist/rolldown/index.d.mts +7 -0
  15. package/dist/rolldown/index.d.ts +7 -0
  16. package/dist/rolldown/index.mjs +159 -0
  17. package/dist/runtime/dev.mjs +14 -4
  18. package/dist/runtime/internal/app.d.ts +6 -1
  19. package/dist/runtime/internal/app.mjs +50 -19
  20. package/dist/runtime/internal/helper.d.ts +12 -0
  21. package/dist/runtime/internal/helper.mjs +33 -0
  22. package/dist/runtime/project-info.d.ts +3 -0
  23. package/dist/runtime/project-info.mjs +53 -0
  24. package/dist/runtime/start.mjs +18 -4
  25. package/dist/shared/apibara.63c9a277.mjs +29 -0
  26. package/dist/shared/apibara.730bb1e4.mjs +17 -0
  27. package/dist/types/index.d.mts +23 -19
  28. package/dist/types/index.d.ts +23 -19
  29. package/package.json +13 -16
  30. package/src/cli/commands/add.ts +16 -7
  31. package/src/cli/commands/build.ts +5 -2
  32. package/src/cli/commands/dev.ts +56 -13
  33. package/src/cli/commands/init.ts +12 -7
  34. package/src/cli/commands/prepare.ts +4 -2
  35. package/src/cli/commands/start.ts +16 -3
  36. package/src/cli/commands/write-project-info.ts +56 -0
  37. package/src/cli/common.ts +33 -1
  38. package/src/cli/index.ts +2 -0
  39. package/src/core/apibara.ts +5 -0
  40. package/src/core/build/build.ts +13 -5
  41. package/src/core/build/dev.ts +44 -23
  42. package/src/core/build/error.ts +9 -14
  43. package/src/core/build/prepare.ts +5 -3
  44. package/src/core/build/prod.ts +25 -16
  45. package/src/core/build/types.ts +11 -1
  46. package/src/core/config/defaults.ts +3 -0
  47. package/src/core/config/loader.ts +13 -7
  48. package/src/core/config/resolvers/preset.resolver.ts +3 -0
  49. package/src/core/config/update.ts +1 -1
  50. package/src/create/add.ts +10 -9
  51. package/src/create/constants.ts +10 -11
  52. package/src/create/init.ts +8 -5
  53. package/src/create/templates.ts +130 -102
  54. package/src/hooks/useRuntimeConfig.ts +1 -1
  55. package/src/rolldown/config.ts +111 -0
  56. package/src/rolldown/index.ts +2 -0
  57. package/src/rolldown/plugins/config.ts +17 -0
  58. package/src/{rollup → rolldown}/plugins/indexers.ts +3 -3
  59. package/src/rolldown/plugins/instrumentation.ts +68 -0
  60. package/src/runtime/dev.ts +16 -4
  61. package/src/runtime/internal/app.ts +66 -25
  62. package/src/runtime/internal/helper.ts +55 -0
  63. package/src/runtime/project-info.ts +72 -0
  64. package/src/runtime/start.ts +21 -4
  65. package/src/types/config.ts +23 -12
  66. package/src/types/hooks.ts +8 -5
  67. package/src/types/index.ts +1 -1
  68. package/src/types/rolldown.ts +5 -0
  69. package/src/types/virtual/config.d.ts +4 -1
  70. package/src/types/virtual/indexers.d.ts +4 -1
  71. package/src/types/virtual/instrumentation.d.ts +4 -0
  72. package/dist/rollup/index.d.mts +0 -6
  73. package/dist/rollup/index.d.ts +0 -6
  74. package/dist/rollup/index.mjs +0 -150
  75. package/dist/shared/apibara.1b515d04.mjs +0 -8
  76. package/src/core/config/resolvers/runtime-config.resolver.ts +0 -6
  77. package/src/rollup/config.ts +0 -87
  78. package/src/rollup/index.ts +0 -2
  79. package/src/rollup/plugins/config.ts +0 -12
  80. package/src/rollup/plugins/esm-shim.ts +0 -69
  81. package/src/types/rollup.ts +0 -8
@@ -1,24 +1,11 @@
1
1
  import path, { basename } from 'node:path';
2
2
  import consola$1, { consola } from 'consola';
3
3
  import prompts from 'prompts';
4
- import colors from 'picocolors';
4
+ import { a as blue, y as yellow, c as green, r as red, d as cyan, m as magenta, e as reset } from '../shared/apibara.730bb1e4.mjs';
5
5
  import fs from 'node:fs';
6
6
  import { Project, SyntaxKind } from 'ts-morph';
7
7
  import * as prettier from 'prettier';
8
-
9
- const {
10
- blue,
11
- blueBright,
12
- cyan,
13
- gray,
14
- green,
15
- greenBright,
16
- magenta,
17
- red,
18
- redBright,
19
- reset,
20
- yellow
21
- } = colors;
8
+ import 'picocolors';
22
9
 
23
10
  const chains = [
24
11
  {
@@ -57,26 +44,25 @@ const storages = [
57
44
  ];
58
45
  const packageVersions = {
59
46
  // Required Dependencies
60
- apibara: "^2.1.0-beta.2",
61
- "@apibara/indexer": "^2.1.0-beta.2",
62
- "@apibara/protocol": "^2.1.0-beta.2",
47
+ apibara: "next",
48
+ "@apibara/indexer": "next",
49
+ "@apibara/protocol": "next",
63
50
  // Chain Dependencies
64
- "@apibara/evm": "^2.1.0-beta.2",
65
- "@apibara/beaconchain": "^2.1.0-beta.2",
66
- "@apibara/starknet": "^2.1.0-beta.2",
51
+ "@apibara/evm": "next",
52
+ "@apibara/beaconchain": "next",
53
+ "@apibara/starknet": "next",
67
54
  // Storage Dependencies
68
- "@apibara/plugin-drizzle": "^2.1.0-beta.2",
69
- "@apibara/plugin-mongo": "^2.1.0-beta.2",
70
- "@apibara/plugin-sqlite": "^2.1.0-beta.2",
55
+ "@apibara/plugin-drizzle": "next",
56
+ "@apibara/plugin-mongo": "next",
57
+ "@apibara/plugin-sqlite": "next",
71
58
  // Postgres Dependencies
72
59
  "@electric-sql/pglite": "^0.2.17",
73
- "drizzle-orm": "^0.37.0",
60
+ "drizzle-orm": "^0.40.1",
74
61
  pg: "^8.13.1",
75
62
  "@types/pg": "^8.11.10",
76
63
  "drizzle-kit": "^0.29.0",
77
64
  // Typescript Dependencies
78
65
  typescript: "^5.6.2",
79
- "@rollup/plugin-typescript": "^11.1.6",
80
66
  "@types/node": "^20.5.2"
81
67
  };
82
68
  const dnaUrls = {
@@ -386,7 +372,7 @@ function generatePackageJson(isTypeScript) {
386
372
  private: true,
387
373
  type: "module",
388
374
  scripts: {
389
- prepare: "apibara prepare",
375
+ ...isTypeScript && { prepare: "apibara prepare" },
390
376
  dev: "apibara dev",
391
377
  start: "apibara start",
392
378
  build: "apibara build",
@@ -399,7 +385,6 @@ function generatePackageJson(isTypeScript) {
399
385
  },
400
386
  devDependencies: {
401
387
  ...isTypeScript && {
402
- "@rollup/plugin-typescript": packageVersions["@rollup/plugin-typescript"],
403
388
  "@types/node": packageVersions["@types/node"],
404
389
  typescript: packageVersions.typescript
405
390
  }
@@ -427,13 +412,10 @@ function generateTsConfig() {
427
412
  };
428
413
  }
429
414
  function generateApibaraConfig(isTypeScript) {
430
- return `${isTypeScript ? 'import typescript from "@rollup/plugin-typescript";\nimport type { Plugin } from "apibara/rollup";\n' : ""}import { defineConfig } from "apibara/config";
415
+ return `import { defineConfig } from "apibara/config";
431
416
 
432
417
  export default defineConfig({
433
- runtimeConfig: {},${isTypeScript ? `
434
- rollupConfig: {
435
- plugins: [typescript()${isTypeScript ? " as Plugin" : ""}],
436
- },` : ""}
418
+ runtimeConfig: {},
437
419
  });
438
420
  `;
439
421
  }
@@ -446,15 +428,18 @@ function generateIndexer({
446
428
  return `import { defineIndexer } from "@apibara/indexer";
447
429
  import { useLogger } from "@apibara/indexer/plugins";
448
430
  ${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
431
+ ${storage === "postgres" ? `import { drizzle } from "@apibara/plugin-drizzle";` : ""}
449
432
  ${chain === "ethereum" ? `import { EvmStream } from "@apibara/evm";` : chain === "beaconchain" ? `import { BeaconChainStream } from "@apibara/beaconchain";` : chain === "starknet" ? `import { StarknetStream } from "@apibara/starknet";` : ""}
450
433
  ${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
451
- ${storage === "postgres" ? `import { getDrizzlePgDatabase } from "../lib/db";` : ""}
434
+ ${storage === "postgres" ? `import * as schema from "../lib/schema";` : ""}
452
435
 
453
436
 
454
437
  export default function (runtimeConfig${language === "typescript" ? ": ApibaraRuntimeConfig" : ""}) {
455
438
  const indexerId = "${indexerId}";
456
- const { startingBlock, streamUrl${storage === "postgres" ? ", postgresConnectionString" : ""} } = runtimeConfig[indexerId];
457
- ${storage === "postgres" ? "const { db } = getDrizzlePgDatabase(postgresConnectionString);" : ""}
439
+ const { startingBlock, streamUrl } = runtimeConfig[indexerId];
440
+ ${storage === "postgres" ? `const db = drizzle({
441
+ schema,
442
+ });` : ""}
458
443
 
459
444
  return defineIndexer(${chain === "ethereum" ? "EvmStream" : chain === "beaconchain" ? "BeaconChainStream" : chain === "starknet" ? "StarknetStream" : ""})({
460
445
  streamUrl,
@@ -463,7 +448,7 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
463
448
  filter: {
464
449
  header: "always",
465
450
  },
466
- plugins: [${storage === "postgres" ? "drizzleStorage({ db, persistState: true })" : ""}],
451
+ plugins: [${storage === "postgres" ? "drizzleStorage({ db, migrate: { migrationsFolder: './drizzle' } })" : ""}],
467
452
  async transform({ endCursor, finality }) {
468
453
  const logger = useLogger();
469
454
 
@@ -475,14 +460,12 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
475
460
  );
476
461
 
477
462
  ${storage === "postgres" ? `// Example snippet to insert data into db using drizzle with postgres
478
- // const { db } = useDrizzleStorage();
479
- // const { logs } = block;
480
- // for (const log of logs) {
481
- // await db.insert(exampleTable).values({
482
- // number: Number(endCursor?.orderKey),
483
- // hash: log.transactionHash,
484
- // });
485
- // }` : ""}
463
+ // const { db: database } = useDrizzleStorage();
464
+
465
+ // await database.insert(schema.cursorTable).values({
466
+ // endCursor: Number(endCursor?.orderKey),
467
+ // uniqueKey: \`\${endCursor?.uniqueKey}\`,
468
+ // });` : ""}
486
469
  },
487
470
  });
488
471
  }
@@ -549,8 +532,8 @@ async function updateApibaraConfigFile({
549
532
  );
550
533
  const runtimeConfigString = `{
551
534
  startingBlock: 0,
552
- streamUrl: "${dnaUrl ?? getDnaUrl(chain, network)}"${storage === "postgres" ? `,
553
- postgresConnectionString: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}"` : ""}}`;
535
+ streamUrl: "${dnaUrl ?? getDnaUrl(chain, network)}"
536
+ }`;
554
537
  const project = new Project();
555
538
  const sourceFile = project.addSourceFileAtPath(pathToConfig);
556
539
  const defineConfigCall = sourceFile.getFirstDescendantByKind(
@@ -581,7 +564,7 @@ async function updateApibaraConfigFile({
581
564
  await formatFile(pathToConfig);
582
565
  }
583
566
  async function createDrizzleStorageFiles(options) {
584
- const { cwd, language, storage } = options;
567
+ const { cwd, language, storage, indexerId } = options;
585
568
  if (storage !== "postgres")
586
569
  return;
587
570
  const fileExtension = language === "typescript" ? "ts" : "js";
@@ -595,11 +578,11 @@ async function createDrizzleStorageFiles(options) {
595
578
  const drizzleConfigContent = `${language === "typescript" ? 'import type { Config } from "drizzle-kit";' : ""}
596
579
 
597
580
  export default {
598
- schema: "./lib/schema.ts",
581
+ schema: "./lib/schema.${fileExtension}",
599
582
  out: "./drizzle",
600
583
  dialect: "postgresql",
601
584
  dbCredentials: {
602
- url: process.env["POSTGRES_CONNECTION_STRING"] ?? "",
585
+ url: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}",
603
586
  },
604
587
  }${language === "typescript" ? " satisfies Config" : ""};`;
605
588
  fs.writeFileSync(drizzleConfigPath, drizzleConfigContent);
@@ -614,14 +597,14 @@ export default {
614
597
  fileName: `lib/${schemaFileName}`
615
598
  });
616
599
  if (!schemaExists || schemaOverwrite) {
617
- const schemaContent = `// --- Add your pg table schemas here ----
600
+ const schemaContent = `// --- Add your pg table schemas here ----
618
601
 
619
602
  // import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
620
603
 
621
- // export const exampleTable = pgTable("example_table", {
604
+ // export const cursorTable = pgTable("cursor_table", {
622
605
  // id: uuid("id").primaryKey().defaultRandom(),
623
- // number: bigint("number", { mode: "number" }),
624
- // hash: text("hash"),
606
+ // endCursor: bigint("end_cursor", { mode: "number" }),
607
+ // uniqueKey: text("unique_key"),
625
608
  // });
626
609
 
627
610
  export {};
@@ -631,48 +614,6 @@ export {};
631
614
  await formatFile(schemaPath);
632
615
  consola.success(`Created ${cyan("lib/schema.ts")}`);
633
616
  }
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
617
  console.log("\n");
677
618
  if (!schemaExists || schemaOverwrite) {
678
619
  consola.info(
@@ -688,15 +629,15 @@ ${yellow(`
688
629
 
689
630
  import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
690
631
 
691
- export const exampleTable = pgTable("example_table", {
632
+ export const cursorTable = pgTable("cursor_table", {
692
633
  id: uuid("id").primaryKey().defaultRandom(),
693
- number: bigint("number", { mode: "number" }),
694
- hash: text("hash"),
634
+ endCursor: bigint("end_cursor", { mode: "number" }),
635
+ uniqueKey: text("unique_key"),
695
636
  });`)}`);
696
637
  console.log("\n");
697
638
  }
698
639
  consola.info(
699
- `Run ${green(`${options.packageManager} run drizzle:generate`)} & ${green(`${options.packageManager} run drizzle:migrate`)} to generate and apply migrations.`
640
+ `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
641
  );
701
642
  }
702
643
  async function createStorageRelatedFiles(options) {
@@ -705,6 +646,90 @@ async function createStorageRelatedFiles(options) {
705
646
  await createDrizzleStorageFiles(options);
706
647
  }
707
648
  }
649
+ const gitIgnoreItems = [
650
+ {
651
+ isRecommended: false,
652
+ value: "node_modules"
653
+ },
654
+ {
655
+ isRecommended: false,
656
+ value: "dist"
657
+ },
658
+ {
659
+ isRecommended: true,
660
+ description: "build and dev files of apibara",
661
+ value: ".apibara"
662
+ },
663
+ {
664
+ isRecommended: false,
665
+ value: ".env"
666
+ },
667
+ {
668
+ isRecommended: false,
669
+ description: "for mac users",
670
+ value: ".DS_Store"
671
+ }
672
+ ];
673
+ async function createGitIgnoreFile(cwd) {
674
+ const gitIgnorePath = path.join(cwd, ".gitignore");
675
+ if (fs.existsSync(gitIgnorePath)) {
676
+ const result = await prompts([
677
+ {
678
+ type: "select",
679
+ name: "overwrite",
680
+ message: `${cyan(".gitignore")} already exists. Please choose how to proceed:`,
681
+ initial: 0,
682
+ choices: [
683
+ {
684
+ title: "Choose items to append in your .gitignore",
685
+ value: "append"
686
+ },
687
+ {
688
+ title: "Keep original",
689
+ value: "ignore"
690
+ },
691
+ {
692
+ title: "Overwrite",
693
+ value: "overwrite"
694
+ }
695
+ ]
696
+ },
697
+ {
698
+ type: (overwrite2) => overwrite2 === "append" ? "multiselect" : null,
699
+ name: "ignoreItems",
700
+ message: "Choose items to append in your .gitignore",
701
+ choices: gitIgnoreItems.map((item) => ({
702
+ title: `${yellow(item.value)}${item.description ? ` - ${item.description}` : ""}${item.isRecommended ? ` ${green("(recommended)")}` : ""}`,
703
+ value: item.value
704
+ }))
705
+ }
706
+ ]);
707
+ const { overwrite, ignoreItems } = result;
708
+ if (overwrite === "append" && ignoreItems.length > 0) {
709
+ const gitIgnoreContent = fs.readFileSync(gitIgnorePath, "utf8");
710
+ fs.writeFileSync(
711
+ gitIgnorePath,
712
+ `${gitIgnoreContent}
713
+ ${result.ignoreItems.join("\n")}`
714
+ );
715
+ consola.success(`Updated ${cyan(".gitignore")}`);
716
+ return;
717
+ }
718
+ if (overwrite === "overwrite") {
719
+ fs.writeFileSync(
720
+ gitIgnorePath,
721
+ gitIgnoreItems.map((item) => item.value).join("\n")
722
+ );
723
+ consola.success(`Updated ${cyan(".gitignore")}`);
724
+ return;
725
+ }
726
+ }
727
+ fs.writeFileSync(
728
+ gitIgnorePath,
729
+ gitIgnoreItems.map((item) => item.value).join("\n")
730
+ );
731
+ consola.success(`Created ${cyan(".gitignore")}`);
732
+ }
708
733
 
709
734
  async function initializeProject({
710
735
  argTargetDir,
@@ -789,35 +814,36 @@ async function initializeProject({
789
814
  JSON.stringify(packageJson, null, 2) + "\n"
790
815
  );
791
816
  await formatFile(packageJsonPath);
792
- consola$1.success("Created ", cyan("package.json"));
817
+ consola$1.success("Created", cyan("package.json"));
793
818
  if (isTs) {
794
819
  const tsConfigPath = path.join(root, "tsconfig.json");
795
820
  const tsConfig = generateTsConfig();
796
821
  fs.writeFileSync(tsConfigPath, JSON.stringify(tsConfig, null, 2) + "\n");
797
822
  await formatFile(tsConfigPath);
798
- consola$1.success("Created ", cyan("tsconfig.json"));
823
+ consola$1.success("Created", cyan("tsconfig.json"));
799
824
  }
800
825
  const apibaraConfigPath = path.join(root, `apibara.config.${configExt}`);
801
- const apibaraConfig = generateApibaraConfig(isTs);
826
+ const apibaraConfig = generateApibaraConfig();
802
827
  fs.writeFileSync(apibaraConfigPath, apibaraConfig);
803
828
  await formatFile(apibaraConfigPath);
804
- consola$1.success("Created ", cyan(`apibara.config.${configExt}`));
829
+ consola$1.success("Created", cyan(`apibara.config.${configExt}`));
805
830
  const indexersDir = path.join(root, "indexers");
806
831
  if (!fs.existsSync(indexersDir)) {
807
832
  fs.mkdirSync(indexersDir, { recursive: true });
808
833
  consola$1.success(`Created ${cyan("indexers")} directory`);
809
834
  }
835
+ await createGitIgnoreFile(root);
810
836
  console.log("\n");
811
837
  consola$1.ready(green("Project initialized successfully"));
812
838
  console.log();
813
839
  if (!argNoCreateIndexer) {
814
840
  consola$1.info("Let's create an indexer\n");
815
- await addIndexer({});
841
+ await addIndexer({ argRootDir: argTargetDir });
816
842
  } else {
817
843
  const pkgManager = getPackageManager();
818
844
  consola$1.info(
819
845
  "Run ",
820
- green(`${pkgManager.name} run install`),
846
+ green(`${pkgManager.name} install`),
821
847
  " to install all dependencies"
822
848
  );
823
849
  }
@@ -828,9 +854,11 @@ async function addIndexer({
828
854
  argChain,
829
855
  argNetwork,
830
856
  argStorage,
831
- argDnaUrl
857
+ argDnaUrl,
858
+ argRootDir
832
859
  }) {
833
- const configExists = hasApibaraConfig(process.cwd());
860
+ const cwd = path.join(process.cwd(), argRootDir ?? ".");
861
+ const configExists = hasApibaraConfig(cwd);
834
862
  if (!configExists) {
835
863
  consola$1.error("No apibara.config found in the current directory.");
836
864
  const prompt_initialize = await prompts({
@@ -854,7 +882,7 @@ async function addIndexer({
854
882
  );
855
883
  }
856
884
  }
857
- const language = getApibaraConfigLanguage(process.cwd());
885
+ const language = getApibaraConfigLanguage(cwd);
858
886
  validateIndexerId(argIndexerId, true);
859
887
  validateChain(argChain, true);
860
888
  validateNetwork(argChain, argNetwork, true);
@@ -869,7 +897,7 @@ async function addIndexer({
869
897
  initial: argIndexerId ?? "my-indexer",
870
898
  validate: (id) => validateIndexerId(id) ? checkFileExists(
871
899
  path.join(
872
- process.cwd(),
900
+ cwd,
873
901
  "indexers",
874
902
  `${id}.indexer.${language === "typescript" ? "ts" : "js"}`
875
903
  )
@@ -951,7 +979,7 @@ async function addIndexer({
951
979
  const indexerFileId = argIndexerId ?? prompt_indexerId;
952
980
  const pkgManager = getPackageManager();
953
981
  const options = {
954
- cwd: process.cwd(),
982
+ cwd,
955
983
  indexerFileId,
956
984
  indexerId: convertKebabToCamelCase(indexerFileId),
957
985
  chain: argChain ?? prompt_chain?.name,
@@ -973,8 +1001,10 @@ async function addIndexer({
973
1001
  );
974
1002
  await createStorageRelatedFiles(options);
975
1003
  console.log();
1004
+ const baseCommand = `${options.packageManager} install`;
1005
+ const tsCommand = `${baseCommand} && ${options.packageManager} run prepare`;
976
1006
  consola$1.info(
977
- `Before running the indexer, run ${cyan(`${options.packageManager} run install`)}${language === "typescript" ? " & " + cyan(`${options.packageManager} run prepare`) : ""}`
1007
+ `Before running the indexer, run ${cyan(language === "typescript" ? tsCommand : baseCommand)}`
978
1008
  );
979
1009
  }
980
1010
 
@@ -1,5 +1,5 @@
1
1
  function useRuntimeConfig() {
2
- return JSON.parse(process.env.APIBARA_RUNTIME_CONFIG || "{}");
2
+ return JSON.parse(process.env.APIBARA_RUNTIME_CONFIG_HOOK_DATA || "{}");
3
3
  }
4
4
 
5
5
  export { useRuntimeConfig };
@@ -0,0 +1,7 @@
1
+ import { Apibara } from 'apibara/types';
2
+ import { RolldownOptions } from 'rolldown';
3
+ export { Plugin } from 'rolldown';
4
+
5
+ declare function getRolldownConfig(apibara: Apibara): RolldownOptions;
6
+
7
+ export { getRolldownConfig };
@@ -0,0 +1,7 @@
1
+ import { Apibara } from 'apibara/types';
2
+ import { RolldownOptions } from 'rolldown';
3
+ export { Plugin } from 'rolldown';
4
+
5
+ declare function getRolldownConfig(apibara: Apibara): RolldownOptions;
6
+
7
+ export { getRolldownConfig };
@@ -0,0 +1,159 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { builtinModules } from 'node:module';
3
+ import replace from '@rollup/plugin-replace';
4
+ import defu from 'defu';
5
+ import { join as join$1 } from 'pathe';
6
+ import virtual from '@rollup/plugin-virtual';
7
+ import { hash } from 'ohash';
8
+ import { join } from 'node:path';
9
+
10
+ function appConfig(apibara) {
11
+ return virtual({
12
+ "#apibara-internal-virtual/config": `
13
+ const serializedConfig = \`process.env.APIBARA_CONFIG\`;
14
+
15
+ if (serializedConfig === undefined || serializedConfig === "") {
16
+ throw new Error("APIBARA_CONFIG is not defined");
17
+ }
18
+
19
+ export const config = JSON.parse(serializedConfig);
20
+ `
21
+ });
22
+ }
23
+
24
+ function indexers(apibara) {
25
+ const indexers2 = [...new Set(apibara.indexers)];
26
+ return virtual({
27
+ "#apibara-internal-virtual/indexers": `
28
+ ${indexers2.map((i) => `import * as _${hash(i)} from '${i.indexer}';`).join("\n")}
29
+
30
+ export const indexers = [
31
+ ${indexers2.map((i) => `{ name: "${i.name}", indexer: _${hash(i)} }`).join(",\n")}
32
+ ];
33
+ `
34
+ });
35
+ }
36
+
37
+ function instrumentation(apibara) {
38
+ const instrumentationPath = join(
39
+ apibara.options._c12.cwd,
40
+ `instrumentation.${apibara.options._c12.configFile?.endsWith(".ts") ? "ts" : "js"}`
41
+ );
42
+ if (!existsSync(instrumentationPath)) {
43
+ return virtual({
44
+ "#apibara-internal-virtual/instrumentation": `
45
+ let register = undefined;
46
+ let logger = undefined;
47
+
48
+ export { register, logger };
49
+ `
50
+ });
51
+ }
52
+ return virtual({
53
+ "#apibara-internal-virtual/instrumentation": `
54
+ let register = undefined;
55
+ let logger = undefined;
56
+
57
+ try {
58
+ const instrumentation = require('${instrumentationPath}');
59
+
60
+ if (instrumentation?.register && typeof instrumentation.register === "function") {
61
+ register = instrumentation.register;
62
+ }
63
+
64
+ if (instrumentation?.logger && typeof instrumentation.logger === "function") {
65
+ logger = instrumentation.logger;
66
+ }
67
+ } catch {
68
+ // Silently handle any require errors
69
+ }
70
+
71
+ export { register, logger };
72
+ `
73
+ });
74
+ }
75
+
76
+ const runtimeDependencies = [
77
+ "better-sqlite3",
78
+ "@electric-sql/pglite",
79
+ "pg",
80
+ // https://socket.io/docs/v4/server-installation/#additional-packages
81
+ "utf-8-validate",
82
+ "bufferutil",
83
+ // was giving unresolved import warnings from `node-fetch` library.
84
+ "encoding"
85
+ ];
86
+ function getRolldownConfig(apibara) {
87
+ const extensions = [
88
+ ".ts",
89
+ ".mjs",
90
+ ".js",
91
+ ".json",
92
+ ".node",
93
+ ".tsx",
94
+ ".jsx"
95
+ ];
96
+ const tsConfigExists = existsSync(
97
+ join$1(apibara.options.rootDir, "tsconfig.json")
98
+ );
99
+ const rolldownConfig = defu(
100
+ // biome-ignore lint/suspicious/noExplicitAny: apibara.options.rolldownConfig is typed
101
+ apibara.options.rolldownConfig,
102
+ {
103
+ platform: "node",
104
+ input: apibara.options.entry,
105
+ output: {
106
+ dir: join$1(apibara.options.outputDir || "./.apibara/build"),
107
+ format: "esm",
108
+ entryFileNames: "[name].mjs",
109
+ chunkFileNames: "chunks/[name]-[hash].mjs",
110
+ sourcemap: true
111
+ },
112
+ plugins: [],
113
+ onwarn(warning, rolldownWarn) {
114
+ if (!["CIRCULAR_DEPENDENCY", "EVAL", "THIS_IS_UNDEFINED"].includes(
115
+ warning.code || ""
116
+ ) && !warning.message.includes("Unsupported source map comment") && !warning.message.includes("@__PURE__") && !warning.message.includes("/*#__PURE__*/")) {
117
+ rolldownWarn(warning);
118
+ }
119
+ },
120
+ resolve: {
121
+ extensions,
122
+ preferBuiltins: !!apibara.options.node,
123
+ mainFields: ["main"],
124
+ exportConditions: apibara.options.exportConditions,
125
+ tsconfigFilename: tsConfigExists ? "tsconfig.json" : void 0
126
+ },
127
+ treeshake: true,
128
+ external: [...builtinModules, ...runtimeDependencies]
129
+ }
130
+ );
131
+ rolldownConfig.plugins?.push(
132
+ replace({
133
+ preventAssignment: true,
134
+ values: {
135
+ "process.env.APIBARA_CONFIG": getSerializedRuntimeConfig(apibara)
136
+ }
137
+ })
138
+ );
139
+ rolldownConfig.plugins?.push(instrumentation(apibara));
140
+ rolldownConfig.plugins?.push(indexers(apibara));
141
+ rolldownConfig.plugins?.push(appConfig());
142
+ return rolldownConfig;
143
+ }
144
+ function getSerializedRuntimeConfig(apibara) {
145
+ try {
146
+ return JSON.stringify({
147
+ runtimeConfig: apibara.options.runtimeConfig,
148
+ preset: apibara.options.preset,
149
+ presets: apibara.options.presets
150
+ });
151
+ } catch (error) {
152
+ throw new Error(
153
+ "Failed to serialize runtime config. Please ensure all values in your runtime configuration are JSON serializable.",
154
+ { cause: error }
155
+ );
156
+ }
157
+ }
158
+
159
+ export { getRolldownConfig };
@@ -1,7 +1,11 @@
1
1
  import { runWithReconnect } from "@apibara/indexer";
2
- import { createClient } from "@apibara/protocol";
3
2
  import { defineCommand, runMain } from "citty";
4
- import { availableIndexers, createIndexer } from "./internal/app.mjs";
3
+ import { blueBright } from "picocolors";
4
+ import {
5
+ availableIndexers,
6
+ createAuthenticatedClient,
7
+ createIndexer
8
+ } from "./internal/app.mjs";
5
9
  const startCommand = defineCommand({
6
10
  meta: {
7
11
  name: "start",
@@ -32,11 +36,17 @@ const startCommand = defineCommand({
32
36
  }
33
37
  await Promise.all(
34
38
  selectedIndexers.map(async (indexer) => {
35
- const indexerInstance = createIndexer(indexer, preset);
36
- const client = createClient(
39
+ const { indexer: indexerInstance, logger } = createIndexer(indexer, preset) ?? {};
40
+ if (!indexerInstance) {
41
+ return;
42
+ }
43
+ const client = createAuthenticatedClient(
37
44
  indexerInstance.streamConfig,
38
45
  indexerInstance.options.streamUrl
39
46
  );
47
+ if (logger) {
48
+ logger.info(`Indexer ${blueBright(indexer)} started`);
49
+ }
40
50
  await runWithReconnect(client, indexerInstance);
41
51
  })
42
52
  );
@@ -1,2 +1,7 @@
1
+ import { type CreateClientOptions, type StreamConfig } from "@apibara/protocol";
1
2
  export declare const availableIndexers: any;
2
- export declare function createIndexer(indexerName: string, preset?: string): import("@apibara/indexer").Indexer<unknown, unknown>;
3
+ export declare function createIndexer(indexerName: string, preset?: string): {
4
+ indexer: import("@apibara/indexer").Indexer<unknown, unknown>;
5
+ logger: any;
6
+ } | undefined;
7
+ export declare function createAuthenticatedClient(config: StreamConfig<unknown, unknown>, streamUrl: string, options?: CreateClientOptions): import("@apibara/protocol").GrpcClient<unknown, unknown>;