apibara 2.1.0-beta.5 → 2.1.0-beta.50

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 (119) hide show
  1. package/dist/chunks/add.mjs +16 -8
  2. package/dist/chunks/add.mjs.map +1 -0
  3. package/dist/chunks/build.mjs +4 -2
  4. package/dist/chunks/build.mjs.map +1 -0
  5. package/dist/chunks/dev.mjs +55 -21
  6. package/dist/chunks/dev.mjs.map +1 -0
  7. package/dist/chunks/init.mjs +11 -7
  8. package/dist/chunks/init.mjs.map +1 -0
  9. package/dist/chunks/prepare.mjs +4 -2
  10. package/dist/chunks/prepare.mjs.map +1 -0
  11. package/dist/chunks/start.mjs +16 -4
  12. package/dist/chunks/start.mjs.map +1 -0
  13. package/dist/chunks/write-project-info.mjs +51 -0
  14. package/dist/chunks/write-project-info.mjs.map +1 -0
  15. package/dist/cli/index.mjs +3 -1
  16. package/dist/cli/index.mjs.map +1 -0
  17. package/dist/common/index.d.mts +33 -0
  18. package/dist/common/index.d.ts +33 -0
  19. package/dist/common/index.mjs +91 -0
  20. package/dist/common/index.mjs.map +1 -0
  21. package/dist/config/index.mjs +1 -0
  22. package/dist/config/index.mjs.map +1 -0
  23. package/dist/core/index.mjs +134 -69
  24. package/dist/core/index.mjs.map +1 -0
  25. package/dist/create/index.d.mts +2 -1
  26. package/dist/create/index.d.ts +2 -1
  27. package/dist/create/index.mjs +80 -136
  28. package/dist/create/index.mjs.map +1 -0
  29. package/dist/hooks/index.mjs +6 -1
  30. package/dist/hooks/index.mjs.map +1 -0
  31. package/dist/indexer/index.d.ts +1 -0
  32. package/dist/indexer/index.mjs +1 -0
  33. package/dist/indexer/plugins.d.ts +1 -0
  34. package/dist/indexer/plugins.mjs +1 -0
  35. package/dist/indexer/testing.d.ts +1 -0
  36. package/dist/indexer/testing.mjs +1 -0
  37. package/dist/indexer/vcr.d.ts +1 -0
  38. package/dist/indexer/vcr.mjs +1 -0
  39. package/dist/rolldown/index.d.mts +7 -0
  40. package/dist/rolldown/index.d.ts +7 -0
  41. package/dist/rolldown/index.mjs +141 -0
  42. package/dist/rolldown/index.mjs.map +1 -0
  43. package/dist/runtime/dev.mjs +39 -17
  44. package/dist/runtime/internal/app.d.ts +14 -1
  45. package/dist/runtime/internal/app.mjs +26 -21
  46. package/dist/runtime/project-info.d.ts +3 -0
  47. package/dist/runtime/project-info.mjs +67 -0
  48. package/dist/runtime/start.mjs +78 -11
  49. package/dist/shared/apibara.730bb1e4.mjs +18 -0
  50. package/dist/shared/apibara.730bb1e4.mjs.map +1 -0
  51. package/dist/types/index.d.mts +24 -20
  52. package/dist/types/index.d.ts +24 -20
  53. package/dist/types/index.mjs +1 -0
  54. package/dist/types/index.mjs.map +1 -0
  55. package/package.json +34 -17
  56. package/src/cli/commands/add.ts +16 -7
  57. package/src/cli/commands/build.ts +5 -2
  58. package/src/cli/commands/dev.ts +64 -20
  59. package/src/cli/commands/init.ts +12 -7
  60. package/src/cli/commands/prepare.ts +4 -3
  61. package/src/cli/commands/start.ts +18 -3
  62. package/src/cli/commands/write-project-info.ts +56 -0
  63. package/src/cli/index.ts +2 -0
  64. package/src/common/cli.ts +40 -0
  65. package/src/common/constants.ts +6 -0
  66. package/src/common/helper.ts +86 -0
  67. package/src/common/index.ts +3 -0
  68. package/src/core/apibara.ts +7 -2
  69. package/src/core/build/build.ts +13 -5
  70. package/src/core/build/dev.ts +46 -23
  71. package/src/core/build/error.ts +9 -14
  72. package/src/core/build/prepare.ts +5 -3
  73. package/src/core/build/prod.ts +25 -16
  74. package/src/core/build/types.ts +11 -1
  75. package/src/core/config/defaults.ts +3 -0
  76. package/src/core/config/loader.ts +15 -7
  77. package/src/core/config/resolvers/runtime.resolver.ts +44 -0
  78. package/src/core/config/update.ts +6 -2
  79. package/src/core/scan.ts +1 -1
  80. package/src/create/add.ts +14 -20
  81. package/src/create/constants.ts +5 -7
  82. package/src/create/init.ts +2 -2
  83. package/src/create/templates.ts +43 -116
  84. package/src/create/types.ts +3 -0
  85. package/src/create/utils.ts +20 -7
  86. package/src/hooks/useRuntimeConfig.ts +4 -1
  87. package/src/indexer/index.ts +1 -0
  88. package/src/indexer/plugins.ts +1 -0
  89. package/src/indexer/testing.ts +1 -0
  90. package/src/indexer/vcr.ts +1 -0
  91. package/src/rolldown/config.ts +86 -0
  92. package/src/rolldown/index.ts +2 -0
  93. package/src/{rollup → rolldown}/plugins/indexers.ts +3 -3
  94. package/src/rolldown/plugins/instrumentation.ts +68 -0
  95. package/src/rolldown/plugins/static-config.ts +21 -0
  96. package/src/runtime/dev.ts +49 -19
  97. package/src/runtime/internal/app.ts +42 -29
  98. package/src/runtime/project-info.ts +90 -0
  99. package/src/runtime/start.ts +91 -11
  100. package/src/types/config.ts +27 -13
  101. package/src/types/hooks.ts +8 -5
  102. package/src/types/index.ts +1 -1
  103. package/src/types/rolldown.ts +5 -0
  104. package/src/types/virtual/indexers.d.ts +4 -1
  105. package/src/types/virtual/instrumentation.d.ts +4 -0
  106. package/src/types/virtual/static-config.d.ts +4 -0
  107. package/dist/rollup/index.d.mts +0 -6
  108. package/dist/rollup/index.d.ts +0 -6
  109. package/dist/rollup/index.mjs +0 -150
  110. package/dist/shared/apibara.1b515d04.mjs +0 -8
  111. package/src/cli/common.ts +0 -8
  112. package/src/core/config/resolvers/preset.resolver.ts +0 -9
  113. package/src/core/config/resolvers/runtime-config.resolver.ts +0 -6
  114. package/src/rollup/config.ts +0 -87
  115. package/src/rollup/index.ts +0 -2
  116. package/src/rollup/plugins/config.ts +0 -12
  117. package/src/rollup/plugins/esm-shim.ts +0 -69
  118. package/src/types/rollup.ts +0 -8
  119. package/src/types/virtual/config.d.ts +0 -3
package/src/create/add.ts CHANGED
@@ -37,6 +37,7 @@ type Options = {
37
37
  argNetwork?: string;
38
38
  argStorage?: string;
39
39
  argDnaUrl?: string;
40
+ argRootDir?: string;
40
41
  };
41
42
 
42
43
  export async function addIndexer({
@@ -45,8 +46,10 @@ export async function addIndexer({
45
46
  argNetwork,
46
47
  argStorage,
47
48
  argDnaUrl,
49
+ argRootDir,
48
50
  }: Options) {
49
- const configExists = hasApibaraConfig(process.cwd());
51
+ const cwd = path.join(process.cwd(), argRootDir ?? ".");
52
+ const configExists = hasApibaraConfig(cwd);
50
53
 
51
54
  if (!configExists) {
52
55
  consola.error("No apibara.config found in the current directory.");
@@ -74,7 +77,7 @@ export async function addIndexer({
74
77
  }
75
78
  }
76
79
 
77
- const language = getApibaraConfigLanguage(process.cwd());
80
+ const { language, extension } = getApibaraConfigLanguage(cwd);
78
81
 
79
82
  validateIndexerId(argIndexerId, true);
80
83
  validateChain(argChain, true);
@@ -92,14 +95,10 @@ export async function addIndexer({
92
95
  validate: (id) =>
93
96
  validateIndexerId(id)
94
97
  ? checkFileExists(
95
- path.join(
96
- process.cwd(),
97
- "indexers",
98
- `${id}.indexer.${language === "typescript" ? "ts" : "js"}`,
99
- ),
98
+ path.join(cwd, "indexers", `${id}.indexer.${extension}`),
100
99
  ).then(({ exists }) =>
101
100
  exists
102
- ? `Indexer ${cyan(`${id}.indexer.${language === "typescript" ? "ts" : "js"}`)} already exists`
101
+ ? `Indexer ${cyan(`${id}.indexer.${extension}`)} already exists`
103
102
  : true,
104
103
  )
105
104
  : "Invalid indexer ID, it cannot be empty and must be in kebab-case format",
@@ -197,7 +196,7 @@ export async function addIndexer({
197
196
  const pkgManager = getPackageManager();
198
197
 
199
198
  const options: IndexerOptions = {
200
- cwd: process.cwd(),
199
+ cwd: cwd,
201
200
  indexerFileId,
202
201
  indexerId: convertKebabToCamelCase(indexerFileId),
203
202
  chain: (argChain as Chain) ?? prompt_chain?.name!,
@@ -206,13 +205,12 @@ export async function addIndexer({
206
205
  dnaUrl: argDnaUrl ?? prompt_dnaUrl,
207
206
  language,
208
207
  packageManager: pkgManager.name,
208
+ extension,
209
209
  };
210
210
 
211
211
  await updateApibaraConfigFile(options);
212
212
 
213
- consola.success(
214
- `Updated ${cyan("apibara.config." + (language === "typescript" ? "ts" : "js"))}`,
215
- );
213
+ consola.success(`Updated ${cyan(`apibara.config.${extension}`)}`);
216
214
 
217
215
  await updatePackageJson(options);
218
216
 
@@ -220,19 +218,15 @@ export async function addIndexer({
220
218
 
221
219
  await createIndexerFile(options);
222
220
 
223
- consola.success(
224
- `Created ${cyan(`${indexerFileId}.indexer.${language === "typescript" ? "ts" : "js"}`)}`,
225
- );
221
+ consola.success(`Created ${cyan(`${indexerFileId}.indexer.${extension}`)}`);
226
222
 
227
223
  await createStorageRelatedFiles(options);
228
224
 
229
225
  console.log();
230
226
 
227
+ const baseCommand = `${options.packageManager} install`;
228
+ const tsCommand = `${baseCommand} && ${options.packageManager} run prepare`;
231
229
  consola.info(
232
- `Before running the indexer, run ${cyan(`${options.packageManager} run install`)}${
233
- language === "typescript"
234
- ? " & " + cyan(`${options.packageManager} run prepare`)
235
- : ""
236
- }`,
230
+ `Before running the indexer, run ${cyan(language === "typescript" ? tsCommand : baseCommand)}`,
237
231
  );
238
232
  }
@@ -67,7 +67,6 @@ export const storages: StorageDataType[] = [
67
67
  export const packageVersions = {
68
68
  // Required Dependencies
69
69
  apibara: "next",
70
- "@apibara/indexer": "next",
71
70
  "@apibara/protocol": "next",
72
71
  // Chain Dependencies
73
72
  "@apibara/evm": "next",
@@ -79,20 +78,19 @@ export const packageVersions = {
79
78
  "@apibara/plugin-sqlite": "next",
80
79
  // Postgres Dependencies
81
80
  "@electric-sql/pglite": "^0.2.17",
82
- "drizzle-orm": "^0.37.0",
81
+ "drizzle-orm": "^0.40.1",
83
82
  pg: "^8.13.1",
84
83
  "@types/pg": "^8.11.10",
85
84
  "drizzle-kit": "^0.29.0",
86
85
  // Typescript Dependencies
87
86
  typescript: "^5.6.2",
88
- "@rollup/plugin-typescript": "^11.1.6",
89
87
  "@types/node": "^20.5.2",
90
88
  };
91
89
 
92
90
  export const dnaUrls = {
93
- ethereum: "https://ethereum.preview.apibara.org",
94
- ethereumSepolia: "https://ethereum-sepolia.preview.apibara.org",
91
+ ethereum: "https://mainnet.ethereum.a5a.ch",
92
+ ethereumSepolia: "https://sepolia.ethereum.a5a.ch",
95
93
  beaconchain: "https://beaconchain.preview.apibara.org",
96
- starknet: "https://starknet.preview.apibara.org",
97
- starknetSepolia: "https://starknet-sepolia.preview.apibara.org",
94
+ starknet: "https://mainnet.starknet.a5a.ch",
95
+ starknetSepolia: "https://sepolia.starknet.a5a.ch",
98
96
  };
@@ -166,12 +166,12 @@ export async function initializeProject({
166
166
  if (!argNoCreateIndexer) {
167
167
  consola.info("Let's create an indexer\n");
168
168
 
169
- await addIndexer({});
169
+ await addIndexer({ argRootDir: argTargetDir });
170
170
  } else {
171
171
  const pkgManager = getPackageManager();
172
172
  consola.info(
173
173
  "Run ",
174
- green(`${pkgManager.name} run install`),
174
+ green(`${pkgManager.name} install`),
175
175
  " to install all dependencies",
176
176
  );
177
177
  }
@@ -15,21 +15,18 @@ export function generatePackageJson(isTypeScript: boolean) {
15
15
  private: true,
16
16
  type: "module",
17
17
  scripts: {
18
- prepare: "apibara prepare",
18
+ ...(isTypeScript && { prepare: "apibara prepare" }),
19
19
  dev: "apibara dev",
20
20
  start: "apibara start",
21
21
  build: "apibara build",
22
22
  ...(isTypeScript && { typecheck: "tsc --noEmit" }),
23
23
  },
24
24
  dependencies: {
25
- "@apibara/indexer": packageVersions["@apibara/indexer"],
26
25
  "@apibara/protocol": packageVersions["@apibara/protocol"],
27
26
  apibara: packageVersions.apibara,
28
27
  },
29
28
  devDependencies: {
30
29
  ...(isTypeScript && {
31
- "@rollup/plugin-typescript":
32
- packageVersions["@rollup/plugin-typescript"],
33
30
  "@types/node": packageVersions["@types/node"],
34
31
  typescript: packageVersions.typescript,
35
32
  }),
@@ -59,17 +56,10 @@ export function generateTsConfig() {
59
56
  }
60
57
 
61
58
  export function generateApibaraConfig(isTypeScript: boolean) {
62
- return `${isTypeScript ? 'import typescript from "@rollup/plugin-typescript";\nimport type { Plugin } from "apibara/rollup";\n' : ""}import { defineConfig } from "apibara/config";
59
+ return `import { defineConfig } from "apibara/config";
63
60
 
64
61
  export default defineConfig({
65
- runtimeConfig: {},${
66
- isTypeScript
67
- ? `
68
- rollupConfig: {
69
- plugins: [typescript()${isTypeScript ? " as Plugin" : ""}],
70
- },`
71
- : ""
72
- }
62
+ runtimeConfig: {},
73
63
  });\n`;
74
64
  }
75
65
 
@@ -79,9 +69,10 @@ export function generateIndexer({
79
69
  chain,
80
70
  language,
81
71
  }: IndexerOptions) {
82
- return `import { defineIndexer } from "@apibara/indexer";
83
- import { useLogger } from "@apibara/indexer/plugins";
72
+ return `import { defineIndexer } from "apibara/indexer";
73
+ import { useLogger } from "apibara/plugins";
84
74
  ${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
75
+ ${storage === "postgres" ? `import { drizzle } from "@apibara/plugin-drizzle";` : ""}
85
76
  ${
86
77
  chain === "ethereum"
87
78
  ? `import { EvmStream } from "@apibara/evm";`
@@ -92,19 +83,16 @@ ${
92
83
  : ""
93
84
  }
94
85
  ${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
95
- ${
96
- storage === "postgres"
97
- ? `import { getDrizzlePgDatabase } from "../lib/db";`
98
- : ""
99
- }
86
+ ${storage === "postgres" ? `import * as schema from "../lib/schema";` : ""}
100
87
 
101
88
 
102
89
  export default function (runtimeConfig${language === "typescript" ? ": ApibaraRuntimeConfig" : ""}) {
103
- const indexerId = "${indexerId}";
104
- const { startingBlock, streamUrl${storage === "postgres" ? ", postgresConnectionString" : ""} } = runtimeConfig[indexerId];
90
+ const { startingBlock, streamUrl } = runtimeConfig["${indexerId}"];
105
91
  ${
106
92
  storage === "postgres"
107
- ? "const { db } = getDrizzlePgDatabase(postgresConnectionString);"
93
+ ? `const db = drizzle({
94
+ schema,
95
+ });`
108
96
  : ""
109
97
  }
110
98
 
@@ -121,9 +109,9 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
121
109
  finality: "accepted",
122
110
  startingBlock: BigInt(startingBlock),
123
111
  filter: {
124
- header: "always",
112
+ ${chain === "ethereum" ? "logs: []," : chain === "starknet" ? "events: []," : ""}
125
113
  },
126
- plugins: [${storage === "postgres" ? "drizzleStorage({ db, persistState: true })" : ""}],
114
+ plugins: [${storage === "postgres" ? "drizzleStorage({ db, migrate: { migrationsFolder: './drizzle' } })" : ""}],
127
115
  async transform({ endCursor, finality }) {
128
116
  const logger = useLogger();
129
117
 
@@ -137,14 +125,12 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
137
125
  ${
138
126
  storage === "postgres"
139
127
  ? `// Example snippet to insert data into db using drizzle with postgres
140
- // const { db } = useDrizzleStorage();
141
- // const { logs } = block;
142
- // for (const log of logs) {
143
- // await db.insert(exampleTable).values({
144
- // number: Number(endCursor?.orderKey),
145
- // hash: log.transactionHash,
146
- // });
147
- // }`
128
+ // const { db: database } = useDrizzleStorage();
129
+
130
+ // await database.insert(schema.cursorTable).values({
131
+ // endCursor: Number(endCursor?.orderKey),
132
+ // uniqueKey: \`\${endCursor?.uniqueKey}\`,
133
+ // });`
148
134
  : ""
149
135
  }
150
136
  },
@@ -157,7 +143,7 @@ export async function createIndexerFile(options: IndexerOptions) {
157
143
  const indexerFilePath = path.join(
158
144
  options.cwd,
159
145
  "indexers",
160
- `${options.indexerFileId}.indexer.${options.language === "typescript" ? "ts" : "js"}`,
146
+ `${options.indexerFileId}.indexer.${options.extension}`,
161
147
  );
162
148
 
163
149
  const { exists, overwrite } = await checkFileExists(indexerFilePath, {
@@ -228,20 +214,14 @@ export async function updateApibaraConfigFile({
228
214
  language,
229
215
  network,
230
216
  dnaUrl,
217
+ extension,
231
218
  }: IndexerOptions) {
232
- const pathToConfig = path.join(
233
- cwd,
234
- `apibara.config.${language === "typescript" ? "ts" : "js"}`,
235
- );
219
+ const pathToConfig = path.join(cwd, `apibara.config.${extension}`);
236
220
 
237
221
  const runtimeConfigString = `{
238
222
  startingBlock: 0,
239
- streamUrl: "${dnaUrl ?? getDnaUrl(chain, network)}"${
240
- storage === "postgres"
241
- ? `,
242
- postgresConnectionString: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}"`
243
- : ""
244
- }}`;
223
+ streamUrl: "${dnaUrl ?? getDnaUrl(chain, network)}"
224
+ }`;
245
225
 
246
226
  const project = new Project();
247
227
  const sourceFile = project.addSourceFileAtPath(pathToConfig);
@@ -285,12 +265,16 @@ export async function updateApibaraConfigFile({
285
265
  }
286
266
 
287
267
  export async function createDrizzleStorageFiles(options: IndexerOptions) {
288
- const { cwd, language, storage } = options;
268
+ const {
269
+ cwd,
270
+ language,
271
+ storage,
272
+ indexerId,
273
+ extension: fileExtension,
274
+ } = options;
289
275
 
290
276
  if (storage !== "postgres") return;
291
277
 
292
- const fileExtension = language === "typescript" ? "ts" : "js";
293
-
294
278
  /**
295
279
  *
296
280
  *
@@ -313,11 +297,11 @@ export async function createDrizzleStorageFiles(options: IndexerOptions) {
313
297
  const drizzleConfigContent = `${language === "typescript" ? 'import type { Config } from "drizzle-kit";' : ""}
314
298
 
315
299
  export default {
316
- schema: "./lib/schema.ts",
300
+ schema: "./lib/schema.${fileExtension}",
317
301
  out: "./drizzle",
318
302
  dialect: "postgresql",
319
303
  dbCredentials: {
320
- url: process.env["POSTGRES_CONNECTION_STRING"] ?? "",
304
+ url: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}",
321
305
  },
322
306
  }${language === "typescript" ? " satisfies Config" : ""};`;
323
307
 
@@ -348,14 +332,14 @@ export default {
348
332
  });
349
333
 
350
334
  if (!schemaExists || schemaOverwrite) {
351
- const schemaContent = `// --- Add your pg table schemas here ----
335
+ const schemaContent = `// --- Add your pg table schemas here ----
352
336
 
353
337
  // import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
354
338
 
355
- // export const exampleTable = pgTable("example_table", {
339
+ // export const cursorTable = pgTable("cursor_table", {
356
340
  // id: uuid("id").primaryKey().defaultRandom(),
357
- // number: bigint("number", { mode: "number" }),
358
- // hash: text("hash"),
341
+ // endCursor: bigint("end_cursor", { mode: "number" }),
342
+ // uniqueKey: text("unique_key"),
359
343
  // });
360
344
 
361
345
  export {};
@@ -367,64 +351,7 @@ export {};
367
351
 
368
352
  await formatFile(schemaPath);
369
353
 
370
- consola.success(`Created ${cyan("lib/schema.ts")}`);
371
- }
372
-
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}`)}`);
354
+ consola.success(`Created ${cyan(`lib/${schemaFileName}`)}`);
428
355
  }
429
356
 
430
357
  console.log("\n");
@@ -441,22 +368,22 @@ export function getDrizzlePgDatabase(connectionString${language === "typescript"
441
368
 
442
369
  ${yellow(`
443
370
  ┌──────────────────────────────────────────┐
444
- │ lib/schema.ts
371
+ │ lib/schema
445
372
  └──────────────────────────────────────────┘
446
373
 
447
374
  import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
448
375
 
449
- export const exampleTable = pgTable("example_table", {
376
+ export const cursorTable = pgTable("cursor_table", {
450
377
  id: uuid("id").primaryKey().defaultRandom(),
451
- number: bigint("number", { mode: "number" }),
452
- hash: text("hash"),
378
+ endCursor: bigint("end_cursor", { mode: "number" }),
379
+ uniqueKey: text("unique_key"),
453
380
  });`)}`);
454
381
 
455
382
  console.log("\n");
456
383
  }
457
384
 
458
385
  consola.info(
459
- `Run ${green(`${options.packageManager} run drizzle:generate`)} & ${green(`${options.packageManager} run drizzle:migrate`)} to generate and apply migrations.`,
386
+ `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
387
  );
461
388
  }
462
389
 
@@ -16,6 +16,8 @@ export type Network =
16
16
 
17
17
  export type Storage = "postgres" | "none";
18
18
 
19
+ export type FileExtension = "js" | "ts" | "mjs";
20
+
19
21
  export type IndexerOptions = {
20
22
  cwd: string;
21
23
  indexerFileId: string;
@@ -26,6 +28,7 @@ export type IndexerOptions = {
26
28
  dnaUrl?: string;
27
29
  packageManager: string;
28
30
  language: Language;
31
+ extension: FileExtension;
29
32
  };
30
33
 
31
34
  export type PkgInfo = {
@@ -4,7 +4,7 @@ import * as prettier from "prettier";
4
4
  import prompts from "prompts";
5
5
  import { blue, cyan, red, yellow } from "./colors";
6
6
  import { dnaUrls, networks } from "./constants";
7
- import type { Chain, Language, Network, PkgInfo } from "./types";
7
+ import type { Chain, FileExtension, Language, Network, PkgInfo } from "./types";
8
8
 
9
9
  export function isEmpty(path: string) {
10
10
  const files = fs.readdirSync(path);
@@ -31,7 +31,8 @@ export function validateLanguage(language?: string, throwError = false) {
31
31
  language === "typescript" ||
32
32
  language === "ts" ||
33
33
  language === "javascript" ||
34
- language === "js"
34
+ language === "js" ||
35
+ language === "mjs"
35
36
  ) {
36
37
  return true;
37
38
  }
@@ -49,7 +50,7 @@ export function getLanguageFromAlias(alias: string): Language {
49
50
  if (alias === "ts" || alias === "typescript") {
50
51
  return "typescript";
51
52
  }
52
- if (alias === "js" || alias === "javascript") {
53
+ if (alias === "js" || alias === "javascript" || alias === "mjs") {
53
54
  return "javascript";
54
55
  }
55
56
 
@@ -184,19 +185,31 @@ export function validateDnaUrl(dnaUrl?: string, throwError = false) {
184
185
  export function hasApibaraConfig(cwd: string): boolean {
185
186
  const configPathJS = path.join(cwd, "apibara.config.js");
186
187
  const configPathTS = path.join(cwd, "apibara.config.ts");
188
+ const configPathMJS = path.join(cwd, "apibara.config.mjs");
187
189
 
188
- return fs.existsSync(configPathJS) || fs.existsSync(configPathTS);
190
+ return (
191
+ fs.existsSync(configPathJS) ||
192
+ fs.existsSync(configPathTS) ||
193
+ fs.existsSync(configPathMJS)
194
+ );
189
195
  }
190
196
 
191
- export function getApibaraConfigLanguage(cwd: string): Language {
197
+ export function getApibaraConfigLanguage(cwd: string): {
198
+ language: Language;
199
+ extension: FileExtension;
200
+ } {
192
201
  const configPathJS = path.join(cwd, "apibara.config.js");
193
202
  const configPathTS = path.join(cwd, "apibara.config.ts");
203
+ const configPathMJS = path.join(cwd, "apibara.config.mjs");
194
204
 
205
+ if (fs.existsSync(configPathMJS)) {
206
+ return { language: "javascript", extension: "mjs" };
207
+ }
195
208
  if (fs.existsSync(configPathJS)) {
196
- return "javascript";
209
+ return { language: "javascript", extension: "js" };
197
210
  }
198
211
  if (fs.existsSync(configPathTS)) {
199
- return "typescript";
212
+ return { language: "typescript", extension: "ts" };
200
213
  }
201
214
 
202
215
  throw new Error(red("✖") + " No apibara.config found");
@@ -1,5 +1,8 @@
1
+ import { ENV_INTERNAL_APIBARA_PROCESSED_RUNTIME } from "apibara/common";
1
2
  import type { ApibaraRuntimeConfig } from "apibara/types";
2
3
 
3
4
  export function useRuntimeConfig(): ApibaraRuntimeConfig {
4
- return JSON.parse(process.env.APIBARA_RUNTIME_CONFIG || "{}");
5
+ return JSON.parse(
6
+ process.env[ENV_INTERNAL_APIBARA_PROCESSED_RUNTIME] || "{}",
7
+ );
5
8
  }
@@ -0,0 +1 @@
1
+ export * from "@apibara/indexer";
@@ -0,0 +1 @@
1
+ export * from "@apibara/indexer/plugins";
@@ -0,0 +1 @@
1
+ export * from "@apibara/indexer/testing";
@@ -0,0 +1 @@
1
+ export * from "@apibara/indexer/vcr";
@@ -0,0 +1,86 @@
1
+ import { existsSync } from "node:fs";
2
+ import { builtinModules } from "node:module";
3
+ import type { Apibara } from "apibara/types";
4
+ import defu from "defu";
5
+ import { join } from "pathe";
6
+ import type {
7
+ ConfigExport,
8
+ RolldownOptions,
9
+ RolldownPluginOption,
10
+ } from "rolldown";
11
+ import { indexers } from "./plugins/indexers";
12
+ import { instrumentation } from "./plugins/instrumentation";
13
+ import { staticConfig } from "./plugins/static-config";
14
+
15
+ const runtimeDependencies = [
16
+ "better-sqlite3",
17
+ "@electric-sql/pglite",
18
+ "pg",
19
+ // https://socket.io/docs/v4/server-installation/#additional-packages
20
+ "utf-8-validate",
21
+ "bufferutil",
22
+ "fsevents",
23
+ // was giving unresolved import warnings from `node-fetch` library.
24
+ "encoding",
25
+ ];
26
+
27
+ export function getRolldownConfig(apibara: Apibara): RolldownOptions {
28
+ const extensions: string[] = [
29
+ ".ts",
30
+ ".mjs",
31
+ ".js",
32
+ ".json",
33
+ ".node",
34
+ ".tsx",
35
+ ".jsx",
36
+ ];
37
+
38
+ const tsConfigExists = existsSync(
39
+ join(apibara.options.rootDir, "tsconfig.json"),
40
+ );
41
+
42
+ const rolldownConfig: RolldownOptions & {
43
+ plugins: RolldownPluginOption[];
44
+ } = defu(
45
+ // biome-ignore lint/suspicious/noExplicitAny: apibara.options.rolldownConfig is typed
46
+ apibara.options.rolldownConfig as any,
47
+ <ConfigExport>{
48
+ platform: "node",
49
+ input: apibara.options.entry,
50
+ output: {
51
+ dir: join(apibara.options.outputDir || "./.apibara/build"),
52
+ format: "esm",
53
+ entryFileNames: "[name].mjs",
54
+ chunkFileNames: "chunks/[name]-[hash].mjs",
55
+ sourcemap: true,
56
+ },
57
+ plugins: [],
58
+ onwarn(warning, rolldownWarn) {
59
+ if (
60
+ !["CIRCULAR_DEPENDENCY", "EVAL", "THIS_IS_UNDEFINED"].includes(
61
+ warning.code || "",
62
+ ) &&
63
+ !warning.message.includes("Unsupported source map comment") &&
64
+ !warning.message.includes("@__PURE__") &&
65
+ !warning.message.includes("/*#__PURE__*/")
66
+ ) {
67
+ rolldownWarn(warning);
68
+ }
69
+ },
70
+ resolve: {
71
+ extensions,
72
+ preferBuiltins: !!apibara.options.node,
73
+ mainFields: ["main"],
74
+ exportConditions: apibara.options.exportConditions,
75
+ tsconfigFilename: tsConfigExists ? "tsconfig.json" : undefined,
76
+ },
77
+ treeshake: true,
78
+ external: [...builtinModules, ...runtimeDependencies],
79
+ },
80
+ );
81
+
82
+ rolldownConfig.plugins?.push(staticConfig(apibara));
83
+ rolldownConfig.plugins?.push(instrumentation(apibara));
84
+ rolldownConfig.plugins?.push(indexers(apibara));
85
+ return rolldownConfig;
86
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./config";
2
+ export type { Plugin } from "rolldown";
@@ -1,17 +1,17 @@
1
1
  import virtual from "@rollup/plugin-virtual";
2
2
  import type { Apibara } from "apibara/types";
3
3
  import { hash } from "ohash";
4
+ import type { RolldownPluginOption } from "rolldown";
4
5
 
5
6
  export function indexers(apibara: Apibara) {
6
7
  const indexers = [...new Set(apibara.indexers)];
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")}
14
14
  ];
15
15
  `,
16
- });
16
+ }) as RolldownPluginOption;
17
17
  }