apibara 2.1.0-beta.4 → 2.1.0-beta.40
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 +16 -8
- package/dist/chunks/add.mjs.map +1 -0
- package/dist/chunks/build.mjs +4 -2
- package/dist/chunks/build.mjs.map +1 -0
- package/dist/chunks/dev.mjs +55 -21
- package/dist/chunks/dev.mjs.map +1 -0
- package/dist/chunks/init.mjs +11 -7
- package/dist/chunks/init.mjs.map +1 -0
- package/dist/chunks/prepare.mjs +4 -2
- package/dist/chunks/prepare.mjs.map +1 -0
- package/dist/chunks/start.mjs +16 -4
- package/dist/chunks/start.mjs.map +1 -0
- package/dist/chunks/write-project-info.mjs +51 -0
- package/dist/chunks/write-project-info.mjs.map +1 -0
- package/dist/cli/index.mjs +3 -1
- package/dist/cli/index.mjs.map +1 -0
- package/dist/common/index.d.mts +33 -0
- package/dist/common/index.d.ts +33 -0
- package/dist/common/index.mjs +91 -0
- package/dist/common/index.mjs.map +1 -0
- package/dist/config/index.mjs +1 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/core/index.mjs +134 -69
- package/dist/core/index.mjs.map +1 -0
- package/dist/create/index.d.mts +2 -1
- package/dist/create/index.d.ts +2 -1
- package/dist/create/index.mjs +168 -139
- package/dist/create/index.mjs.map +1 -0
- package/dist/hooks/index.mjs +6 -1
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/indexer/index.d.ts +1 -0
- package/dist/indexer/index.mjs +1 -0
- package/dist/indexer/plugins.d.ts +1 -0
- package/dist/indexer/plugins.mjs +1 -0
- package/dist/indexer/testing.d.ts +1 -0
- package/dist/indexer/testing.mjs +1 -0
- package/dist/indexer/vcr.d.ts +1 -0
- package/dist/indexer/vcr.mjs +1 -0
- package/dist/rolldown/index.d.mts +7 -0
- package/dist/rolldown/index.d.ts +7 -0
- package/dist/rolldown/index.mjs +140 -0
- package/dist/rolldown/index.mjs.map +1 -0
- package/dist/runtime/dev.mjs +19 -9
- package/dist/runtime/internal/app.d.ts +14 -1
- package/dist/runtime/internal/app.mjs +26 -21
- package/dist/runtime/project-info.d.ts +3 -0
- package/dist/runtime/project-info.mjs +67 -0
- package/dist/runtime/start.mjs +59 -7
- package/dist/shared/apibara.730bb1e4.mjs +18 -0
- package/dist/shared/apibara.730bb1e4.mjs.map +1 -0
- package/dist/types/index.d.mts +24 -20
- package/dist/types/index.d.ts +24 -20
- package/dist/types/index.mjs +1 -0
- package/dist/types/index.mjs.map +1 -0
- package/package.json +33 -16
- package/src/cli/commands/add.ts +16 -7
- package/src/cli/commands/build.ts +5 -2
- package/src/cli/commands/dev.ts +64 -20
- package/src/cli/commands/init.ts +12 -7
- package/src/cli/commands/prepare.ts +4 -3
- package/src/cli/commands/start.ts +18 -3
- package/src/cli/commands/write-project-info.ts +56 -0
- package/src/cli/index.ts +2 -0
- package/src/common/cli.ts +40 -0
- package/src/common/constants.ts +6 -0
- package/src/common/helper.ts +86 -0
- package/src/common/index.ts +3 -0
- package/src/core/apibara.ts +7 -2
- package/src/core/build/build.ts +13 -5
- package/src/core/build/dev.ts +46 -23
- package/src/core/build/error.ts +9 -14
- package/src/core/build/prepare.ts +5 -3
- package/src/core/build/prod.ts +25 -16
- package/src/core/build/types.ts +11 -1
- package/src/core/config/defaults.ts +3 -0
- package/src/core/config/loader.ts +15 -7
- package/src/core/config/resolvers/runtime.resolver.ts +44 -0
- package/src/core/config/update.ts +6 -2
- package/src/core/scan.ts +1 -1
- package/src/create/add.ts +14 -20
- package/src/create/constants.ts +5 -7
- package/src/create/init.ts +8 -5
- package/src/create/templates.ts +144 -116
- package/src/create/types.ts +3 -0
- package/src/create/utils.ts +20 -7
- package/src/hooks/useRuntimeConfig.ts +4 -1
- package/src/indexer/index.ts +1 -0
- package/src/indexer/plugins.ts +1 -0
- package/src/indexer/testing.ts +1 -0
- package/src/indexer/vcr.ts +1 -0
- package/src/rolldown/config.ts +85 -0
- package/src/rolldown/index.ts +2 -0
- package/src/{rollup → rolldown}/plugins/indexers.ts +3 -3
- package/src/rolldown/plugins/instrumentation.ts +68 -0
- package/src/rolldown/plugins/static-config.ts +21 -0
- package/src/runtime/dev.ts +21 -8
- package/src/runtime/internal/app.ts +42 -29
- package/src/runtime/project-info.ts +90 -0
- package/src/runtime/start.ts +68 -6
- package/src/types/config.ts +27 -13
- 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/indexers.d.ts +4 -1
- package/src/types/virtual/instrumentation.d.ts +4 -0
- package/src/types/virtual/static-config.d.ts +4 -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/dist/shared/apibara.1b515d04.mjs +0 -8
- package/src/cli/common.ts +0 -8
- package/src/core/config/resolvers/preset.resolver.ts +0 -9
- package/src/core/config/resolvers/runtime-config.resolver.ts +0 -6
- 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/types/virtual/config.d.ts +0 -3
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ENV_INTERNAL_APIBARA_PRESET,
|
|
3
|
+
ENV_INTERNAL_APIBARA_PRESETS,
|
|
4
|
+
ENV_INTERNAL_APIBARA_PROCESSED_RUNTIME,
|
|
5
|
+
ENV_INTERNAL_APIBARA_RUNTIME,
|
|
6
|
+
USER_ENV_APIBARA_RUNTIME_CONFIG,
|
|
7
|
+
getProcessedRuntimeConfig,
|
|
8
|
+
} from "apibara/common";
|
|
9
|
+
import type { ApibaraOptions } from "apibara/types";
|
|
10
|
+
|
|
11
|
+
export function runtimeConfigResolver(options: Partial<ApibaraOptions>) {
|
|
12
|
+
try {
|
|
13
|
+
const { runtimeConfig, preset, presets } = options;
|
|
14
|
+
|
|
15
|
+
if (runtimeConfig) {
|
|
16
|
+
process.env[ENV_INTERNAL_APIBARA_RUNTIME] = JSON.stringify(runtimeConfig);
|
|
17
|
+
}
|
|
18
|
+
if (preset) {
|
|
19
|
+
process.env[ENV_INTERNAL_APIBARA_PRESET] = preset;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (presets) {
|
|
23
|
+
process.env[ENV_INTERNAL_APIBARA_PRESETS] = JSON.stringify(presets);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const userEnvRuntimeConfig = JSON.parse(
|
|
27
|
+
process.env[USER_ENV_APIBARA_RUNTIME_CONFIG] ?? "{}",
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// This is final processed runtime config that will be used by the indexer and useRuntimeConfig hook
|
|
31
|
+
process.env[ENV_INTERNAL_APIBARA_PROCESSED_RUNTIME] = JSON.stringify(
|
|
32
|
+
getProcessedRuntimeConfig({
|
|
33
|
+
preset,
|
|
34
|
+
presets,
|
|
35
|
+
runtimeConfig,
|
|
36
|
+
userEnvRuntimeConfig,
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
throw new Error("Failed to process & set runtime environment variables", {
|
|
41
|
+
cause: error,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { Apibara, ApibaraDynamicConfig } from "apibara/types";
|
|
2
|
+
import { runtimeConfigResolver } from "./resolvers/runtime.resolver";
|
|
2
3
|
|
|
3
4
|
export async function updateApibaraConfig(
|
|
4
5
|
apibara: Apibara,
|
|
5
|
-
|
|
6
|
+
newConfig: ApibaraDynamicConfig,
|
|
6
7
|
) {
|
|
7
|
-
|
|
8
|
+
// applies new config values to env again during hot reload
|
|
9
|
+
runtimeConfigResolver(newConfig);
|
|
8
10
|
apibara.logger.success("Apibara config hot reloaded!");
|
|
11
|
+
// we simply stop indexers and restart them with updated runtime values
|
|
12
|
+
await apibara.hooks.callHook("dev:reload");
|
|
9
13
|
}
|
package/src/core/scan.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Apibara } from "apibara/types";
|
|
|
2
2
|
import fse from "fs-extra";
|
|
3
3
|
import { basename, join } from "pathe";
|
|
4
4
|
|
|
5
|
-
const INDEXER_EXTENSIONS = [".indexer.ts", ".indexer.js"];
|
|
5
|
+
const INDEXER_EXTENSIONS = [".indexer.ts", ".indexer.js", ".indexer.mjs"];
|
|
6
6
|
|
|
7
7
|
export async function scanIndexers(apibara: Apibara) {
|
|
8
8
|
apibara.logger.debug("Scanning indexers");
|
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
|
|
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(
|
|
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.${
|
|
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:
|
|
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(
|
|
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
|
}
|
package/src/create/constants.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
94
|
-
ethereumSepolia: "https://
|
|
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.
|
|
97
|
-
starknetSepolia: "https://
|
|
94
|
+
starknet: "https://mainnet.starknet.a5a.ch",
|
|
95
|
+
starknetSepolia: "https://sepolia.starknet.a5a.ch",
|
|
98
96
|
};
|
package/src/create/init.ts
CHANGED
|
@@ -5,6 +5,7 @@ import prompts from "prompts";
|
|
|
5
5
|
import { addIndexer } from "./add";
|
|
6
6
|
import { cyan, green } from "./colors";
|
|
7
7
|
import {
|
|
8
|
+
createGitIgnoreFile,
|
|
8
9
|
generateApibaraConfig,
|
|
9
10
|
generatePackageJson,
|
|
10
11
|
generateTsConfig,
|
|
@@ -129,7 +130,7 @@ export async function initializeProject({
|
|
|
129
130
|
JSON.stringify(packageJson, null, 2) + "\n",
|
|
130
131
|
);
|
|
131
132
|
await formatFile(packageJsonPath);
|
|
132
|
-
consola.success("Created
|
|
133
|
+
consola.success("Created", cyan("package.json"));
|
|
133
134
|
|
|
134
135
|
// Generate tsconfig.json if TypeScript
|
|
135
136
|
if (isTs) {
|
|
@@ -137,7 +138,7 @@ export async function initializeProject({
|
|
|
137
138
|
const tsConfig = generateTsConfig();
|
|
138
139
|
fs.writeFileSync(tsConfigPath, JSON.stringify(tsConfig, null, 2) + "\n");
|
|
139
140
|
await formatFile(tsConfigPath);
|
|
140
|
-
consola.success("Created
|
|
141
|
+
consola.success("Created", cyan("tsconfig.json"));
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
const apibaraConfigPath = path.join(root, `apibara.config.${configExt}`);
|
|
@@ -145,7 +146,7 @@ export async function initializeProject({
|
|
|
145
146
|
const apibaraConfig = generateApibaraConfig(isTs);
|
|
146
147
|
fs.writeFileSync(apibaraConfigPath, apibaraConfig);
|
|
147
148
|
await formatFile(apibaraConfigPath);
|
|
148
|
-
consola.success("Created
|
|
149
|
+
consola.success("Created", cyan(`apibara.config.${configExt}`));
|
|
149
150
|
|
|
150
151
|
// Create "indexers" directory if not exists
|
|
151
152
|
const indexersDir = path.join(root, "indexers");
|
|
@@ -154,6 +155,8 @@ export async function initializeProject({
|
|
|
154
155
|
consola.success(`Created ${cyan("indexers")} directory`);
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
await createGitIgnoreFile(root);
|
|
159
|
+
|
|
157
160
|
console.log("\n");
|
|
158
161
|
|
|
159
162
|
consola.ready(green("Project initialized successfully"));
|
|
@@ -163,12 +166,12 @@ export async function initializeProject({
|
|
|
163
166
|
if (!argNoCreateIndexer) {
|
|
164
167
|
consola.info("Let's create an indexer\n");
|
|
165
168
|
|
|
166
|
-
await addIndexer({});
|
|
169
|
+
await addIndexer({ argRootDir: argTargetDir });
|
|
167
170
|
} else {
|
|
168
171
|
const pkgManager = getPackageManager();
|
|
169
172
|
consola.info(
|
|
170
173
|
"Run ",
|
|
171
|
-
green(`${pkgManager.name}
|
|
174
|
+
green(`${pkgManager.name} install`),
|
|
172
175
|
" to install all dependencies",
|
|
173
176
|
);
|
|
174
177
|
}
|
package/src/create/templates.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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";
|
|
@@ -14,21 +15,18 @@ 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",
|
|
21
22
|
...(isTypeScript && { typecheck: "tsc --noEmit" }),
|
|
22
23
|
},
|
|
23
24
|
dependencies: {
|
|
24
|
-
"@apibara/indexer": packageVersions["@apibara/indexer"],
|
|
25
25
|
"@apibara/protocol": packageVersions["@apibara/protocol"],
|
|
26
26
|
apibara: packageVersions.apibara,
|
|
27
27
|
},
|
|
28
28
|
devDependencies: {
|
|
29
29
|
...(isTypeScript && {
|
|
30
|
-
"@rollup/plugin-typescript":
|
|
31
|
-
packageVersions["@rollup/plugin-typescript"],
|
|
32
30
|
"@types/node": packageVersions["@types/node"],
|
|
33
31
|
typescript: packageVersions.typescript,
|
|
34
32
|
}),
|
|
@@ -58,17 +56,10 @@ export function generateTsConfig() {
|
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
export function generateApibaraConfig(isTypeScript: boolean) {
|
|
61
|
-
return
|
|
59
|
+
return `import { defineConfig } from "apibara/config";
|
|
62
60
|
|
|
63
61
|
export default defineConfig({
|
|
64
|
-
runtimeConfig: {}
|
|
65
|
-
isTypeScript
|
|
66
|
-
? `
|
|
67
|
-
rollupConfig: {
|
|
68
|
-
plugins: [typescript()${isTypeScript ? " as Plugin" : ""}],
|
|
69
|
-
},`
|
|
70
|
-
: ""
|
|
71
|
-
}
|
|
62
|
+
runtimeConfig: {},
|
|
72
63
|
});\n`;
|
|
73
64
|
}
|
|
74
65
|
|
|
@@ -78,9 +69,10 @@ export function generateIndexer({
|
|
|
78
69
|
chain,
|
|
79
70
|
language,
|
|
80
71
|
}: IndexerOptions) {
|
|
81
|
-
return `import { defineIndexer } from "
|
|
82
|
-
import { useLogger } from "
|
|
72
|
+
return `import { defineIndexer } from "apibara/indexer";
|
|
73
|
+
import { useLogger } from "apibara/plugins";
|
|
83
74
|
${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
|
|
75
|
+
${storage === "postgres" ? `import { drizzle } from "@apibara/plugin-drizzle";` : ""}
|
|
84
76
|
${
|
|
85
77
|
chain === "ethereum"
|
|
86
78
|
? `import { EvmStream } from "@apibara/evm";`
|
|
@@ -91,19 +83,16 @@ ${
|
|
|
91
83
|
: ""
|
|
92
84
|
}
|
|
93
85
|
${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
|
|
94
|
-
${
|
|
95
|
-
storage === "postgres"
|
|
96
|
-
? `import { getDrizzlePgDatabase } from "../lib/db";`
|
|
97
|
-
: ""
|
|
98
|
-
}
|
|
86
|
+
${storage === "postgres" ? `import * as schema from "../lib/schema";` : ""}
|
|
99
87
|
|
|
100
88
|
|
|
101
89
|
export default function (runtimeConfig${language === "typescript" ? ": ApibaraRuntimeConfig" : ""}) {
|
|
102
|
-
const
|
|
103
|
-
const { startingBlock, streamUrl${storage === "postgres" ? ", postgresConnectionString" : ""} } = runtimeConfig[indexerId];
|
|
90
|
+
const { startingBlock, streamUrl } = runtimeConfig["${indexerId}"];
|
|
104
91
|
${
|
|
105
92
|
storage === "postgres"
|
|
106
|
-
?
|
|
93
|
+
? `const db = drizzle({
|
|
94
|
+
schema,
|
|
95
|
+
});`
|
|
107
96
|
: ""
|
|
108
97
|
}
|
|
109
98
|
|
|
@@ -120,9 +109,9 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
120
109
|
finality: "accepted",
|
|
121
110
|
startingBlock: BigInt(startingBlock),
|
|
122
111
|
filter: {
|
|
123
|
-
|
|
112
|
+
${chain === "ethereum" ? "logs: []," : chain === "starknet" ? "events: []," : ""}
|
|
124
113
|
},
|
|
125
|
-
plugins: [${storage === "postgres" ? "drizzleStorage({ db,
|
|
114
|
+
plugins: [${storage === "postgres" ? "drizzleStorage({ db, migrate: { migrationsFolder: './drizzle' } })" : ""}],
|
|
126
115
|
async transform({ endCursor, finality }) {
|
|
127
116
|
const logger = useLogger();
|
|
128
117
|
|
|
@@ -136,14 +125,12 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
136
125
|
${
|
|
137
126
|
storage === "postgres"
|
|
138
127
|
? `// Example snippet to insert data into db using drizzle with postgres
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
// });
|
|
146
|
-
// }`
|
|
128
|
+
// const { db: database } = useDrizzleStorage();
|
|
129
|
+
|
|
130
|
+
// await database.insert(schema.cursorTable).values({
|
|
131
|
+
// endCursor: Number(endCursor?.orderKey),
|
|
132
|
+
// uniqueKey: \`\${endCursor?.uniqueKey}\`,
|
|
133
|
+
// });`
|
|
147
134
|
: ""
|
|
148
135
|
}
|
|
149
136
|
},
|
|
@@ -156,7 +143,7 @@ export async function createIndexerFile(options: IndexerOptions) {
|
|
|
156
143
|
const indexerFilePath = path.join(
|
|
157
144
|
options.cwd,
|
|
158
145
|
"indexers",
|
|
159
|
-
`${options.indexerFileId}.indexer.${options.
|
|
146
|
+
`${options.indexerFileId}.indexer.${options.extension}`,
|
|
160
147
|
);
|
|
161
148
|
|
|
162
149
|
const { exists, overwrite } = await checkFileExists(indexerFilePath, {
|
|
@@ -227,20 +214,14 @@ export async function updateApibaraConfigFile({
|
|
|
227
214
|
language,
|
|
228
215
|
network,
|
|
229
216
|
dnaUrl,
|
|
217
|
+
extension,
|
|
230
218
|
}: IndexerOptions) {
|
|
231
|
-
const pathToConfig = path.join(
|
|
232
|
-
cwd,
|
|
233
|
-
`apibara.config.${language === "typescript" ? "ts" : "js"}`,
|
|
234
|
-
);
|
|
219
|
+
const pathToConfig = path.join(cwd, `apibara.config.${extension}`);
|
|
235
220
|
|
|
236
221
|
const runtimeConfigString = `{
|
|
237
222
|
startingBlock: 0,
|
|
238
|
-
streamUrl: "${dnaUrl ?? getDnaUrl(chain, network)}"
|
|
239
|
-
|
|
240
|
-
? `,
|
|
241
|
-
postgresConnectionString: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}"`
|
|
242
|
-
: ""
|
|
243
|
-
}}`;
|
|
223
|
+
streamUrl: "${dnaUrl ?? getDnaUrl(chain, network)}"
|
|
224
|
+
}`;
|
|
244
225
|
|
|
245
226
|
const project = new Project();
|
|
246
227
|
const sourceFile = project.addSourceFileAtPath(pathToConfig);
|
|
@@ -284,12 +265,16 @@ export async function updateApibaraConfigFile({
|
|
|
284
265
|
}
|
|
285
266
|
|
|
286
267
|
export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
287
|
-
const {
|
|
268
|
+
const {
|
|
269
|
+
cwd,
|
|
270
|
+
language,
|
|
271
|
+
storage,
|
|
272
|
+
indexerId,
|
|
273
|
+
extension: fileExtension,
|
|
274
|
+
} = options;
|
|
288
275
|
|
|
289
276
|
if (storage !== "postgres") return;
|
|
290
277
|
|
|
291
|
-
const fileExtension = language === "typescript" ? "ts" : "js";
|
|
292
|
-
|
|
293
278
|
/**
|
|
294
279
|
*
|
|
295
280
|
*
|
|
@@ -312,11 +297,11 @@ export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
|
312
297
|
const drizzleConfigContent = `${language === "typescript" ? 'import type { Config } from "drizzle-kit";' : ""}
|
|
313
298
|
|
|
314
299
|
export default {
|
|
315
|
-
schema: "./lib/schema
|
|
300
|
+
schema: "./lib/schema.${fileExtension}",
|
|
316
301
|
out: "./drizzle",
|
|
317
302
|
dialect: "postgresql",
|
|
318
303
|
dbCredentials: {
|
|
319
|
-
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "",
|
|
304
|
+
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}",
|
|
320
305
|
},
|
|
321
306
|
}${language === "typescript" ? " satisfies Config" : ""};`;
|
|
322
307
|
|
|
@@ -347,14 +332,14 @@ export default {
|
|
|
347
332
|
});
|
|
348
333
|
|
|
349
334
|
if (!schemaExists || schemaOverwrite) {
|
|
350
|
-
const schemaContent = `// --- Add your pg table schemas here ----
|
|
335
|
+
const schemaContent = `// --- Add your pg table schemas here ----
|
|
351
336
|
|
|
352
337
|
// import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
353
338
|
|
|
354
|
-
// export const
|
|
339
|
+
// export const cursorTable = pgTable("cursor_table", {
|
|
355
340
|
// id: uuid("id").primaryKey().defaultRandom(),
|
|
356
|
-
//
|
|
357
|
-
//
|
|
341
|
+
// endCursor: bigint("end_cursor", { mode: "number" }),
|
|
342
|
+
// uniqueKey: text("unique_key"),
|
|
358
343
|
// });
|
|
359
344
|
|
|
360
345
|
export {};
|
|
@@ -366,64 +351,7 @@ export {};
|
|
|
366
351
|
|
|
367
352
|
await formatFile(schemaPath);
|
|
368
353
|
|
|
369
|
-
consola.success(`Created ${cyan(
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
* DB File
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*/
|
|
379
|
-
const dbFileName = `db.${fileExtension}`;
|
|
380
|
-
|
|
381
|
-
const dbPath = path.join(cwd, "lib", dbFileName);
|
|
382
|
-
|
|
383
|
-
const { exists: dbExists, overwrite: dbOverwrite } = await checkFileExists(
|
|
384
|
-
dbPath,
|
|
385
|
-
{
|
|
386
|
-
askPrompt: true,
|
|
387
|
-
fileName: `lib/${dbFileName}`,
|
|
388
|
-
allowIgnore: true,
|
|
389
|
-
},
|
|
390
|
-
);
|
|
391
|
-
|
|
392
|
-
if (!dbExists || dbOverwrite) {
|
|
393
|
-
const dbContent = `import * as schema from "./schema";
|
|
394
|
-
import { drizzle as nodePgDrizzle } from "drizzle-orm/node-postgres";
|
|
395
|
-
import { drizzle as pgLiteDrizzle } from "drizzle-orm/pglite";
|
|
396
|
-
import pg from "pg";
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
export function getDrizzlePgDatabase(connectionString${language === "typescript" ? ": string" : ""}) {
|
|
400
|
-
// Create pglite instance
|
|
401
|
-
if (connectionString.includes("memory")) {
|
|
402
|
-
return {
|
|
403
|
-
db: pgLiteDrizzle({
|
|
404
|
-
schema,
|
|
405
|
-
connection: {
|
|
406
|
-
dataDir: connectionString,
|
|
407
|
-
},
|
|
408
|
-
}),
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// Create node-postgres instance
|
|
413
|
-
const pool = new pg.Pool({
|
|
414
|
-
connectionString,
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
return { db: nodePgDrizzle(pool, { schema }) };
|
|
418
|
-
}`;
|
|
419
|
-
|
|
420
|
-
// create directory if it doesn't exist
|
|
421
|
-
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
422
|
-
fs.writeFileSync(dbPath, dbContent);
|
|
423
|
-
|
|
424
|
-
await formatFile(dbPath);
|
|
425
|
-
|
|
426
|
-
consola.success(`Created ${cyan(`lib/${dbFileName}`)}`);
|
|
354
|
+
consola.success(`Created ${cyan(`lib/${schemaFileName}`)}`);
|
|
427
355
|
}
|
|
428
356
|
|
|
429
357
|
console.log("\n");
|
|
@@ -440,22 +368,22 @@ export function getDrizzlePgDatabase(connectionString${language === "typescript"
|
|
|
440
368
|
|
|
441
369
|
${yellow(`
|
|
442
370
|
┌──────────────────────────────────────────┐
|
|
443
|
-
│ lib/schema
|
|
371
|
+
│ lib/schema │
|
|
444
372
|
└──────────────────────────────────────────┘
|
|
445
373
|
|
|
446
374
|
import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
447
375
|
|
|
448
|
-
export const
|
|
376
|
+
export const cursorTable = pgTable("cursor_table", {
|
|
449
377
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
450
|
-
|
|
451
|
-
|
|
378
|
+
endCursor: bigint("end_cursor", { mode: "number" }),
|
|
379
|
+
uniqueKey: text("unique_key"),
|
|
452
380
|
});`)}`);
|
|
453
381
|
|
|
454
382
|
console.log("\n");
|
|
455
383
|
}
|
|
456
384
|
|
|
457
385
|
consola.info(
|
|
458
|
-
`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.`,
|
|
459
387
|
);
|
|
460
388
|
}
|
|
461
389
|
|
|
@@ -466,3 +394,103 @@ export async function createStorageRelatedFiles(options: IndexerOptions) {
|
|
|
466
394
|
await createDrizzleStorageFiles(options);
|
|
467
395
|
}
|
|
468
396
|
}
|
|
397
|
+
|
|
398
|
+
const gitIgnoreItems: {
|
|
399
|
+
isRecommended: boolean;
|
|
400
|
+
description?: string;
|
|
401
|
+
value: string;
|
|
402
|
+
}[] = [
|
|
403
|
+
{
|
|
404
|
+
isRecommended: false,
|
|
405
|
+
value: "node_modules",
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
isRecommended: false,
|
|
409
|
+
value: "dist",
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
isRecommended: true,
|
|
413
|
+
description: "build and dev files of apibara",
|
|
414
|
+
value: ".apibara",
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
isRecommended: false,
|
|
418
|
+
value: ".env",
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
isRecommended: false,
|
|
422
|
+
description: "for mac users",
|
|
423
|
+
value: ".DS_Store",
|
|
424
|
+
},
|
|
425
|
+
];
|
|
426
|
+
|
|
427
|
+
export async function createGitIgnoreFile(cwd: string) {
|
|
428
|
+
const gitIgnorePath = path.join(cwd, ".gitignore");
|
|
429
|
+
|
|
430
|
+
if (fs.existsSync(gitIgnorePath)) {
|
|
431
|
+
const result = await prompts([
|
|
432
|
+
{
|
|
433
|
+
type: "select",
|
|
434
|
+
name: "overwrite",
|
|
435
|
+
message: `${cyan(".gitignore")} already exists. Please choose how to proceed:`,
|
|
436
|
+
initial: 0,
|
|
437
|
+
choices: [
|
|
438
|
+
{
|
|
439
|
+
title: "Choose items to append in your .gitignore",
|
|
440
|
+
value: "append",
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
title: "Keep original",
|
|
444
|
+
value: "ignore",
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
title: "Overwrite",
|
|
448
|
+
value: "overwrite",
|
|
449
|
+
},
|
|
450
|
+
],
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
type: (overwrite: "append" | "ignore" | "overwrite") =>
|
|
454
|
+
overwrite === "append" ? "multiselect" : null,
|
|
455
|
+
name: "ignoreItems",
|
|
456
|
+
message: "Choose items to append in your .gitignore",
|
|
457
|
+
choices: gitIgnoreItems.map((item) => ({
|
|
458
|
+
title: `${yellow(item.value)}${
|
|
459
|
+
item.description ? ` - ${item.description}` : ""
|
|
460
|
+
}${item.isRecommended ? ` ${green("(recommended)")}` : ""}`,
|
|
461
|
+
value: item.value,
|
|
462
|
+
})),
|
|
463
|
+
},
|
|
464
|
+
]);
|
|
465
|
+
|
|
466
|
+
const { overwrite, ignoreItems } = result as {
|
|
467
|
+
overwrite: "append" | "ignore" | "overwrite";
|
|
468
|
+
ignoreItems: string[];
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
if (overwrite === "append" && ignoreItems.length > 0) {
|
|
472
|
+
const gitIgnoreContent = fs.readFileSync(gitIgnorePath, "utf8");
|
|
473
|
+
fs.writeFileSync(
|
|
474
|
+
gitIgnorePath,
|
|
475
|
+
`${gitIgnoreContent}\n${result.ignoreItems.join("\n")}`,
|
|
476
|
+
);
|
|
477
|
+
consola.success(`Updated ${cyan(".gitignore")}`);
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (overwrite === "overwrite") {
|
|
482
|
+
fs.writeFileSync(
|
|
483
|
+
gitIgnorePath,
|
|
484
|
+
gitIgnoreItems.map((item) => item.value).join("\n"),
|
|
485
|
+
);
|
|
486
|
+
consola.success(`Updated ${cyan(".gitignore")}`);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
fs.writeFileSync(
|
|
492
|
+
gitIgnorePath,
|
|
493
|
+
gitIgnoreItems.map((item) => item.value).join("\n"),
|
|
494
|
+
);
|
|
495
|
+
consola.success(`Created ${cyan(".gitignore")}`);
|
|
496
|
+
}
|
package/src/create/types.ts
CHANGED
|
@@ -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 = {
|