apibara 2.1.0-beta.1 → 2.1.0-beta.11
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 +12 -7
- package/dist/chunks/dev.mjs +25 -6
- package/dist/chunks/init.mjs +3 -7
- package/dist/chunks/start.mjs +2 -1
- package/dist/core/index.mjs +85 -42
- package/dist/create/index.d.mts +2 -1
- package/dist/create/index.d.ts +2 -1
- package/dist/create/index.mjs +185 -121
- package/dist/hooks/index.mjs +3 -1
- package/dist/rolldown/index.d.mts +7 -0
- package/dist/rolldown/index.d.ts +7 -0
- package/dist/rolldown/index.mjs +126 -0
- package/dist/runtime/dev.mjs +3 -0
- package/dist/runtime/internal/app.d.ts +1 -1
- package/dist/runtime/internal/app.mjs +12 -11
- package/dist/runtime/start.mjs +5 -0
- package/dist/shared/apibara.af330c7d.mjs +15 -0
- package/dist/types/index.d.mts +18 -15
- package/dist/types/index.d.ts +18 -15
- package/package.json +13 -15
- package/src/cli/commands/add.ts +12 -6
- package/src/cli/commands/dev.ts +27 -5
- package/src/cli/commands/init.ts +3 -7
- package/src/cli/commands/start.ts +1 -0
- package/src/core/build/build.ts +13 -5
- package/src/core/build/dev.ts +44 -23
- package/src/core/build/error.ts +9 -14
- package/src/core/build/prod.ts +15 -10
- package/src/core/build/types.ts +8 -0
- package/src/core/config/defaults.ts +3 -0
- package/src/core/config/resolvers/runtime-config.resolver.ts +21 -2
- package/src/core/config/update.ts +1 -1
- package/src/create/add.ts +26 -12
- package/src/create/constants.ts +9 -10
- package/src/create/init.ts +28 -14
- package/src/create/templates.ts +154 -118
- package/src/create/utils.ts +10 -0
- package/src/hooks/useRuntimeConfig.ts +2 -1
- package/src/rolldown/config.ts +108 -0
- package/src/rolldown/index.ts +2 -0
- package/src/rolldown/plugins/config.ts +25 -0
- package/src/{rollup → rolldown}/plugins/indexers.ts +3 -3
- package/src/runtime/dev.ts +3 -0
- package/src/runtime/internal/app.ts +30 -13
- package/src/runtime/start.ts +5 -0
- package/src/types/config.ts +12 -7
- package/src/types/hooks.ts +8 -5
- package/src/types/index.ts +1 -1
- package/src/types/rolldown.ts +5 -0
- package/src/types/virtual/config.d.ts +4 -1
- package/src/types/virtual/indexers.d.ts +4 -1
- package/src/utils/helper.ts +15 -0
- package/dist/rollup/index.d.mts +0 -6
- package/dist/rollup/index.d.ts +0 -6
- package/dist/rollup/index.mjs +0 -150
- package/src/rollup/config.ts +0 -87
- package/src/rollup/index.ts +0 -2
- package/src/rollup/plugins/config.ts +0 -12
- package/src/rollup/plugins/esm-shim.ts +0 -69
- package/src/types/rollup.ts +0 -8
package/src/create/templates.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { consola } from "consola";
|
|
4
|
+
import prompts from "prompts";
|
|
4
5
|
import { type ObjectLiteralExpression, Project, SyntaxKind } from "ts-morph";
|
|
5
6
|
import { cyan, green, magenta, yellow } from "./colors";
|
|
6
7
|
import { packageVersions } from "./constants";
|
|
7
8
|
import type { IndexerOptions } from "./types";
|
|
8
|
-
import { checkFileExists, getDnaUrl } from "./utils";
|
|
9
|
+
import { checkFileExists, formatFile, getDnaUrl } from "./utils";
|
|
9
10
|
|
|
10
11
|
export function generatePackageJson(isTypeScript: boolean) {
|
|
11
12
|
return {
|
|
@@ -14,7 +15,7 @@ export function generatePackageJson(isTypeScript: boolean) {
|
|
|
14
15
|
private: true,
|
|
15
16
|
type: "module",
|
|
16
17
|
scripts: {
|
|
17
|
-
prepare: "apibara prepare",
|
|
18
|
+
...(isTypeScript && { prepare: "apibara prepare" }),
|
|
18
19
|
dev: "apibara dev",
|
|
19
20
|
start: "apibara start",
|
|
20
21
|
build: "apibara build",
|
|
@@ -27,8 +28,6 @@ export function generatePackageJson(isTypeScript: boolean) {
|
|
|
27
28
|
},
|
|
28
29
|
devDependencies: {
|
|
29
30
|
...(isTypeScript && {
|
|
30
|
-
"@rollup/plugin-typescript":
|
|
31
|
-
packageVersions["@rollup/plugin-typescript"],
|
|
32
31
|
"@types/node": packageVersions["@types/node"],
|
|
33
32
|
typescript: packageVersions.typescript,
|
|
34
33
|
}),
|
|
@@ -58,17 +57,10 @@ export function generateTsConfig() {
|
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
export function generateApibaraConfig(isTypeScript: boolean) {
|
|
61
|
-
return
|
|
60
|
+
return `import { defineConfig } from "apibara/config";
|
|
62
61
|
|
|
63
62
|
export default defineConfig({
|
|
64
|
-
runtimeConfig: {}
|
|
65
|
-
isTypeScript
|
|
66
|
-
? `
|
|
67
|
-
rollupConfig: {
|
|
68
|
-
plugins: [typescript()${isTypeScript ? " as Plugin" : ""}],
|
|
69
|
-
},`
|
|
70
|
-
: ""
|
|
71
|
-
}
|
|
63
|
+
runtimeConfig: {},
|
|
72
64
|
});\n`;
|
|
73
65
|
}
|
|
74
66
|
|
|
@@ -78,24 +70,21 @@ export function generateIndexer({
|
|
|
78
70
|
chain,
|
|
79
71
|
language,
|
|
80
72
|
}: IndexerOptions) {
|
|
81
|
-
return
|
|
82
|
-
chain === "ethereum"
|
|
83
|
-
? `import { EvmStream } from "@apibara/evm";`
|
|
84
|
-
: chain === "beaconchain"
|
|
85
|
-
? `import { BeaconChainStream } from "@apibara/beaconchain";`
|
|
86
|
-
: chain === "starknet"
|
|
87
|
-
? `import { StarknetStream } from "@apibara/starknet";`
|
|
88
|
-
: ""
|
|
89
|
-
}
|
|
90
|
-
import { defineIndexer } from "@apibara/indexer";
|
|
91
|
-
${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
|
|
92
|
-
${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
|
|
73
|
+
return `import { defineIndexer } from "@apibara/indexer";
|
|
93
74
|
import { useLogger } from "@apibara/indexer/plugins";
|
|
75
|
+
${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
|
|
76
|
+
${storage === "postgres" ? `import { drizzle } from "@apibara/plugin-drizzle";` : ""}
|
|
94
77
|
${
|
|
95
|
-
|
|
96
|
-
? `import {
|
|
97
|
-
: ""
|
|
78
|
+
chain === "ethereum"
|
|
79
|
+
? `import { EvmStream } from "@apibara/evm";`
|
|
80
|
+
: chain === "beaconchain"
|
|
81
|
+
? `import { BeaconChainStream } from "@apibara/beaconchain";`
|
|
82
|
+
: chain === "starknet"
|
|
83
|
+
? `import { StarknetStream } from "@apibara/starknet";`
|
|
84
|
+
: ""
|
|
98
85
|
}
|
|
86
|
+
${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
|
|
87
|
+
${storage === "postgres" ? `import * as schema from "../lib/schema";` : ""}
|
|
99
88
|
|
|
100
89
|
|
|
101
90
|
export default function (runtimeConfig${language === "typescript" ? ": ApibaraRuntimeConfig" : ""}) {
|
|
@@ -103,7 +92,10 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
103
92
|
const { startingBlock, streamUrl${storage === "postgres" ? ", postgresConnectionString" : ""} } = runtimeConfig[indexerId];
|
|
104
93
|
${
|
|
105
94
|
storage === "postgres"
|
|
106
|
-
?
|
|
95
|
+
? `const db = drizzle({
|
|
96
|
+
schema,
|
|
97
|
+
connectionString: postgresConnectionString,
|
|
98
|
+
});`
|
|
107
99
|
: ""
|
|
108
100
|
}
|
|
109
101
|
|
|
@@ -122,7 +114,7 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
122
114
|
filter: {
|
|
123
115
|
header: "always",
|
|
124
116
|
},
|
|
125
|
-
plugins: [${storage === "postgres" ? "drizzleStorage({ db,
|
|
117
|
+
plugins: [${storage === "postgres" ? "drizzleStorage({ db, migrate: { migrationsFolder: './drizzle' } })" : ""}],
|
|
126
118
|
async transform({ endCursor, finality }) {
|
|
127
119
|
const logger = useLogger();
|
|
128
120
|
|
|
@@ -136,14 +128,12 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
136
128
|
${
|
|
137
129
|
storage === "postgres"
|
|
138
130
|
? `// Example snippet to insert data into db using drizzle with postgres
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
// });
|
|
146
|
-
// }`
|
|
131
|
+
// const { db: database } = useDrizzleStorage();
|
|
132
|
+
|
|
133
|
+
// await database.insert(schema.cursorTable).values({
|
|
134
|
+
// endCursor: Number(endCursor?.orderKey),
|
|
135
|
+
// uniqueKey: \`\${endCursor?.uniqueKey}\`,
|
|
136
|
+
// });`
|
|
147
137
|
: ""
|
|
148
138
|
}
|
|
149
139
|
},
|
|
@@ -169,17 +159,19 @@ export async function createIndexerFile(options: IndexerOptions) {
|
|
|
169
159
|
|
|
170
160
|
fs.mkdirSync(path.dirname(indexerFilePath), { recursive: true });
|
|
171
161
|
fs.writeFileSync(indexerFilePath, indexerContent);
|
|
162
|
+
|
|
163
|
+
await formatFile(indexerFilePath);
|
|
172
164
|
}
|
|
173
165
|
|
|
174
|
-
export function updatePackageJson({
|
|
166
|
+
export async function updatePackageJson({
|
|
175
167
|
cwd,
|
|
176
168
|
chain,
|
|
177
169
|
storage,
|
|
178
170
|
language,
|
|
179
171
|
}: IndexerOptions) {
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
);
|
|
172
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
173
|
+
|
|
174
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
183
175
|
|
|
184
176
|
if (chain === "ethereum") {
|
|
185
177
|
packageJson.dependencies["@apibara/evm"] = packageVersions["@apibara/evm"];
|
|
@@ -212,13 +204,12 @@ export function updatePackageJson({
|
|
|
212
204
|
}
|
|
213
205
|
}
|
|
214
206
|
|
|
215
|
-
fs.writeFileSync(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
);
|
|
207
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
208
|
+
|
|
209
|
+
await formatFile(packageJsonPath);
|
|
219
210
|
}
|
|
220
211
|
|
|
221
|
-
export function updateApibaraConfigFile({
|
|
212
|
+
export async function updateApibaraConfigFile({
|
|
222
213
|
indexerId,
|
|
223
214
|
cwd,
|
|
224
215
|
chain,
|
|
@@ -279,15 +270,11 @@ export function updateApibaraConfigFile({
|
|
|
279
270
|
// Save the changes
|
|
280
271
|
sourceFile.saveSync();
|
|
281
272
|
|
|
282
|
-
|
|
283
|
-
tabSize: 2,
|
|
284
|
-
insertSpaceAfterOpeningAndBeforeClosingEmptyBraces: true,
|
|
285
|
-
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
|
|
286
|
-
});
|
|
273
|
+
await formatFile(pathToConfig);
|
|
287
274
|
}
|
|
288
275
|
|
|
289
276
|
export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
290
|
-
const { cwd, language, storage } = options;
|
|
277
|
+
const { cwd, language, storage, indexerId } = options;
|
|
291
278
|
|
|
292
279
|
if (storage !== "postgres") return;
|
|
293
280
|
|
|
@@ -315,16 +302,18 @@ export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
|
315
302
|
const drizzleConfigContent = `${language === "typescript" ? 'import type { Config } from "drizzle-kit";' : ""}
|
|
316
303
|
|
|
317
304
|
export default {
|
|
318
|
-
schema: "./lib/schema
|
|
305
|
+
schema: "./lib/schema.${fileExtension}",
|
|
319
306
|
out: "./drizzle",
|
|
320
307
|
dialect: "postgresql",
|
|
321
308
|
dbCredentials: {
|
|
322
|
-
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "",
|
|
309
|
+
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}",
|
|
323
310
|
},
|
|
324
311
|
}${language === "typescript" ? " satisfies Config" : ""};`;
|
|
325
312
|
|
|
326
313
|
fs.writeFileSync(drizzleConfigPath, drizzleConfigContent);
|
|
327
314
|
|
|
315
|
+
await formatFile(drizzleConfigPath);
|
|
316
|
+
|
|
328
317
|
consola.success(`Created ${cyan(drizzleConfigFileName)}`);
|
|
329
318
|
}
|
|
330
319
|
|
|
@@ -348,14 +337,14 @@ export default {
|
|
|
348
337
|
});
|
|
349
338
|
|
|
350
339
|
if (!schemaExists || schemaOverwrite) {
|
|
351
|
-
const schemaContent = `// --- Add your pg table schemas here ----
|
|
340
|
+
const schemaContent = `// --- Add your pg table schemas here ----
|
|
352
341
|
|
|
353
342
|
// import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
354
343
|
|
|
355
|
-
// export const
|
|
344
|
+
// export const cursorTable = pgTable("cursor_table", {
|
|
356
345
|
// id: uuid("id").primaryKey().defaultRandom(),
|
|
357
|
-
//
|
|
358
|
-
//
|
|
346
|
+
// endCursor: bigint("end_cursor", { mode: "number" }),
|
|
347
|
+
// uniqueKey: text("unique_key"),
|
|
359
348
|
// });
|
|
360
349
|
|
|
361
350
|
export {};
|
|
@@ -365,62 +354,9 @@ export {};
|
|
|
365
354
|
fs.mkdirSync(path.dirname(schemaPath), { recursive: true });
|
|
366
355
|
fs.writeFileSync(schemaPath, schemaContent);
|
|
367
356
|
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* DB File
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*/
|
|
378
|
-
const dbFileName = `db.${fileExtension}`;
|
|
379
|
-
|
|
380
|
-
const dbPath = path.join(cwd, "lib", dbFileName);
|
|
357
|
+
await formatFile(schemaPath);
|
|
381
358
|
|
|
382
|
-
|
|
383
|
-
dbPath,
|
|
384
|
-
{
|
|
385
|
-
askPrompt: true,
|
|
386
|
-
fileName: `lib/${dbFileName}`,
|
|
387
|
-
allowIgnore: true,
|
|
388
|
-
},
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
if (!dbExists || dbOverwrite) {
|
|
392
|
-
const dbContent = `import * as schema from "./schema";
|
|
393
|
-
import { drizzle as nodePgDrizzle } from "drizzle-orm/node-postgres";
|
|
394
|
-
import { drizzle as pgLiteDrizzle } from "drizzle-orm/pglite";
|
|
395
|
-
import pg from "pg";
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
export function getDrizzlePgDatabase(connectionString${language === "typescript" ? ": string" : ""}) {
|
|
399
|
-
// Create pglite instance
|
|
400
|
-
if (connectionString.includes("memory")) {
|
|
401
|
-
return {
|
|
402
|
-
db: pgLiteDrizzle({
|
|
403
|
-
schema,
|
|
404
|
-
connection: {
|
|
405
|
-
dataDir: connectionString,
|
|
406
|
-
},
|
|
407
|
-
}),
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Create node-postgres instance
|
|
412
|
-
const pool = new pg.Pool({
|
|
413
|
-
connectionString,
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
return { db: nodePgDrizzle(pool, { schema }) };
|
|
417
|
-
}`;
|
|
418
|
-
|
|
419
|
-
// create directory if it doesn't exist
|
|
420
|
-
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
421
|
-
fs.writeFileSync(dbPath, dbContent);
|
|
422
|
-
|
|
423
|
-
consola.success(`Created ${cyan(`lib/${dbFileName}`)}`);
|
|
359
|
+
consola.success(`Created ${cyan("lib/schema.ts")}`);
|
|
424
360
|
}
|
|
425
361
|
|
|
426
362
|
console.log("\n");
|
|
@@ -442,17 +378,17 @@ ${yellow(`
|
|
|
442
378
|
|
|
443
379
|
import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
444
380
|
|
|
445
|
-
export const
|
|
381
|
+
export const cursorTable = pgTable("cursor_table", {
|
|
446
382
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
447
|
-
|
|
448
|
-
|
|
383
|
+
endCursor: bigint("end_cursor", { mode: "number" }),
|
|
384
|
+
uniqueKey: text("unique_key"),
|
|
449
385
|
});`)}`);
|
|
450
386
|
|
|
451
387
|
console.log("\n");
|
|
452
388
|
}
|
|
453
389
|
|
|
454
390
|
consola.info(
|
|
455
|
-
`Run ${green(`${options.packageManager} run drizzle:generate`)} & ${green(`${options.packageManager} run drizzle:migrate`)} to generate and apply migrations.`,
|
|
391
|
+
`Run ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:generate`)} & ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:migrate`)} to generate and apply migrations.`,
|
|
456
392
|
);
|
|
457
393
|
}
|
|
458
394
|
|
|
@@ -463,3 +399,103 @@ export async function createStorageRelatedFiles(options: IndexerOptions) {
|
|
|
463
399
|
await createDrizzleStorageFiles(options);
|
|
464
400
|
}
|
|
465
401
|
}
|
|
402
|
+
|
|
403
|
+
const gitIgnoreItems: {
|
|
404
|
+
isRecommended: boolean;
|
|
405
|
+
description?: string;
|
|
406
|
+
value: string;
|
|
407
|
+
}[] = [
|
|
408
|
+
{
|
|
409
|
+
isRecommended: false,
|
|
410
|
+
value: "node_modules",
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
isRecommended: false,
|
|
414
|
+
value: "dist",
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
isRecommended: true,
|
|
418
|
+
description: "build and dev files of apibara",
|
|
419
|
+
value: ".apibara",
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
isRecommended: false,
|
|
423
|
+
value: ".env",
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
isRecommended: false,
|
|
427
|
+
description: "for mac users",
|
|
428
|
+
value: ".DS_Store",
|
|
429
|
+
},
|
|
430
|
+
];
|
|
431
|
+
|
|
432
|
+
export async function createGitIgnoreFile(cwd: string) {
|
|
433
|
+
const gitIgnorePath = path.join(cwd, ".gitignore");
|
|
434
|
+
|
|
435
|
+
if (fs.existsSync(gitIgnorePath)) {
|
|
436
|
+
const result = await prompts([
|
|
437
|
+
{
|
|
438
|
+
type: "select",
|
|
439
|
+
name: "overwrite",
|
|
440
|
+
message: `${cyan(".gitignore")} already exists. Please choose how to proceed:`,
|
|
441
|
+
initial: 0,
|
|
442
|
+
choices: [
|
|
443
|
+
{
|
|
444
|
+
title: "Choose items to append in your .gitignore",
|
|
445
|
+
value: "append",
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
title: "Keep original",
|
|
449
|
+
value: "ignore",
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
title: "Overwrite",
|
|
453
|
+
value: "overwrite",
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
type: (overwrite: "append" | "ignore" | "overwrite") =>
|
|
459
|
+
overwrite === "append" ? "multiselect" : null,
|
|
460
|
+
name: "ignoreItems",
|
|
461
|
+
message: "Choose items to append in your .gitignore",
|
|
462
|
+
choices: gitIgnoreItems.map((item) => ({
|
|
463
|
+
title: `${yellow(item.value)}${
|
|
464
|
+
item.description ? ` - ${item.description}` : ""
|
|
465
|
+
}${item.isRecommended ? ` ${green("(recommended)")}` : ""}`,
|
|
466
|
+
value: item.value,
|
|
467
|
+
})),
|
|
468
|
+
},
|
|
469
|
+
]);
|
|
470
|
+
|
|
471
|
+
const { overwrite, ignoreItems } = result as {
|
|
472
|
+
overwrite: "append" | "ignore" | "overwrite";
|
|
473
|
+
ignoreItems: string[];
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
if (overwrite === "append" && ignoreItems.length > 0) {
|
|
477
|
+
const gitIgnoreContent = fs.readFileSync(gitIgnorePath, "utf8");
|
|
478
|
+
fs.writeFileSync(
|
|
479
|
+
gitIgnorePath,
|
|
480
|
+
`${gitIgnoreContent}\n${result.ignoreItems.join("\n")}`,
|
|
481
|
+
);
|
|
482
|
+
consola.success(`Updated ${cyan(".gitignore")}`);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (overwrite === "overwrite") {
|
|
487
|
+
fs.writeFileSync(
|
|
488
|
+
gitIgnorePath,
|
|
489
|
+
gitIgnoreItems.map((item) => item.value).join("\n"),
|
|
490
|
+
);
|
|
491
|
+
consola.success(`Updated ${cyan(".gitignore")}`);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
fs.writeFileSync(
|
|
497
|
+
gitIgnorePath,
|
|
498
|
+
gitIgnoreItems.map((item) => item.value).join("\n"),
|
|
499
|
+
);
|
|
500
|
+
consola.success(`Created ${cyan(".gitignore")}`);
|
|
501
|
+
}
|
package/src/create/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path, { basename } from "node:path";
|
|
3
|
+
import * as prettier from "prettier";
|
|
3
4
|
import prompts from "prompts";
|
|
4
5
|
import { blue, cyan, red, yellow } from "./colors";
|
|
5
6
|
import { dnaUrls, networks } from "./constants";
|
|
@@ -410,3 +411,12 @@ function pkgFromUserAgent(userAgent: string | undefined): PkgInfo | undefined {
|
|
|
410
411
|
version: pkgSpecArr[1],
|
|
411
412
|
};
|
|
412
413
|
}
|
|
414
|
+
|
|
415
|
+
export async function formatFile(path: string) {
|
|
416
|
+
const file = fs.readFileSync(path, "utf8");
|
|
417
|
+
const formatted = await prettier.format(file, {
|
|
418
|
+
filepath: path,
|
|
419
|
+
tabWidth: 2,
|
|
420
|
+
});
|
|
421
|
+
fs.writeFileSync(path, formatted);
|
|
422
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ApibaraRuntimeConfig } from "apibara/types";
|
|
2
|
+
import { deserialize } from "../utils/helper";
|
|
2
3
|
|
|
3
4
|
export function useRuntimeConfig(): ApibaraRuntimeConfig {
|
|
4
|
-
return
|
|
5
|
+
return deserialize(process.env.APIBARA_RUNTIME_CONFIG || "{}");
|
|
5
6
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { builtinModules } from "node:module";
|
|
3
|
+
import replace from "@rollup/plugin-replace";
|
|
4
|
+
import type { Apibara } from "apibara/types";
|
|
5
|
+
import defu from "defu";
|
|
6
|
+
import { join } from "pathe";
|
|
7
|
+
import type {
|
|
8
|
+
ConfigExport,
|
|
9
|
+
RolldownOptions,
|
|
10
|
+
RolldownPluginOption,
|
|
11
|
+
} from "rolldown";
|
|
12
|
+
import { serialize } from "../utils/helper";
|
|
13
|
+
import { appConfig } from "./plugins/config";
|
|
14
|
+
import { indexers } from "./plugins/indexers";
|
|
15
|
+
|
|
16
|
+
const runtimeDependencies = [
|
|
17
|
+
"better-sqlite3",
|
|
18
|
+
"@electric-sql/pglite",
|
|
19
|
+
"pg",
|
|
20
|
+
// https://socket.io/docs/v4/server-installation/#additional-packages
|
|
21
|
+
"utf-8-validate",
|
|
22
|
+
"bufferutil",
|
|
23
|
+
"node-fetch",
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export function getRolldownConfig(apibara: Apibara): RolldownOptions {
|
|
27
|
+
const extensions: string[] = [
|
|
28
|
+
".ts",
|
|
29
|
+
".mjs",
|
|
30
|
+
".js",
|
|
31
|
+
".json",
|
|
32
|
+
".node",
|
|
33
|
+
".tsx",
|
|
34
|
+
".jsx",
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const tsConfigExists = existsSync(
|
|
38
|
+
join(apibara.options.rootDir, "tsconfig.json"),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const rolldownConfig: RolldownOptions & {
|
|
42
|
+
plugins: RolldownPluginOption[];
|
|
43
|
+
} = defu(
|
|
44
|
+
// biome-ignore lint/suspicious/noExplicitAny: apibara.options.rolldownConfig is typed
|
|
45
|
+
apibara.options.rolldownConfig as any,
|
|
46
|
+
<ConfigExport>{
|
|
47
|
+
platform: "node",
|
|
48
|
+
input: apibara.options.entry,
|
|
49
|
+
output: {
|
|
50
|
+
dir: join(apibara.options.outputDir || "./.apibara/build"),
|
|
51
|
+
format: "esm",
|
|
52
|
+
entryFileNames: "[name].mjs",
|
|
53
|
+
chunkFileNames: "chunks/[name]-[hash].mjs",
|
|
54
|
+
sourcemap: true,
|
|
55
|
+
},
|
|
56
|
+
plugins: [],
|
|
57
|
+
onwarn(warning, rolldownWarn) {
|
|
58
|
+
if (
|
|
59
|
+
!["CIRCULAR_DEPENDENCY", "EVAL", "THIS_IS_UNDEFINED"].includes(
|
|
60
|
+
warning.code || "",
|
|
61
|
+
) &&
|
|
62
|
+
!warning.message.includes("Unsupported source map comment") &&
|
|
63
|
+
!warning.message.includes("@__PURE__") &&
|
|
64
|
+
!warning.message.includes("/*#__PURE__*/")
|
|
65
|
+
) {
|
|
66
|
+
rolldownWarn(warning);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
resolve: {
|
|
70
|
+
extensions,
|
|
71
|
+
preferBuiltins: !!apibara.options.node,
|
|
72
|
+
mainFields: ["main"],
|
|
73
|
+
exportConditions: apibara.options.exportConditions,
|
|
74
|
+
tsconfigFilename: tsConfigExists ? "tsconfig.json" : undefined,
|
|
75
|
+
},
|
|
76
|
+
treeshake: true,
|
|
77
|
+
external: [...builtinModules, ...runtimeDependencies],
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
rolldownConfig.plugins?.push(
|
|
82
|
+
replace({
|
|
83
|
+
preventAssignment: true,
|
|
84
|
+
values: {
|
|
85
|
+
"process.env.APIBARA_CONFIG": getSerializedRuntimeConfig(apibara),
|
|
86
|
+
},
|
|
87
|
+
}) as RolldownPluginOption,
|
|
88
|
+
);
|
|
89
|
+
rolldownConfig.plugins?.push(indexers(apibara));
|
|
90
|
+
rolldownConfig.plugins?.push(appConfig(apibara));
|
|
91
|
+
|
|
92
|
+
return rolldownConfig;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getSerializedRuntimeConfig(apibara: Apibara) {
|
|
96
|
+
try {
|
|
97
|
+
return serialize({
|
|
98
|
+
runtimeConfig: apibara.options.runtimeConfig,
|
|
99
|
+
preset: apibara.options.preset,
|
|
100
|
+
presets: apibara.options.presets,
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
"Failed to serialize runtime config. Please ensure all values in your runtime configuration are JSON serializable. BigInt values are supported, but functions, symbols, etc. are not. Check your configuration for non-serializable values.",
|
|
105
|
+
{ cause: error },
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import virtual from "@rollup/plugin-virtual";
|
|
2
|
+
import type { Apibara } from "apibara/types";
|
|
3
|
+
import type { RolldownPluginOption } from "rolldown";
|
|
4
|
+
|
|
5
|
+
export function appConfig(apibara: Apibara) {
|
|
6
|
+
return virtual({
|
|
7
|
+
"#apibara-internal-virtual/config": `
|
|
8
|
+
const serializedConfig = \`process.env.APIBARA_CONFIG\`;
|
|
9
|
+
|
|
10
|
+
if (serializedConfig === undefined || serializedConfig === "") {
|
|
11
|
+
throw new Error("APIBARA_CONFIG is not defined");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function deserialize(str) {
|
|
15
|
+
return JSON.parse(str, (_, value) =>
|
|
16
|
+
typeof value === "string" && value.match(/^\\d+n$/)
|
|
17
|
+
? BigInt(value.slice(0, -1))
|
|
18
|
+
: value,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const config = deserialize(serializedConfig);
|
|
23
|
+
`,
|
|
24
|
+
}) as RolldownPluginOption;
|
|
25
|
+
}
|
|
@@ -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
|
}
|
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,
|