apibara 2.0.0-beta.9 → 2.1.0-beta.10
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 +49 -0
- package/dist/chunks/build.mjs +3 -3
- package/dist/chunks/dev.mjs +41 -19
- package/dist/chunks/init.mjs +37 -0
- package/dist/chunks/prepare.mjs +0 -2
- package/dist/chunks/start.mjs +56 -0
- package/dist/cli/index.mjs +5 -1
- package/dist/config/index.d.mts +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/core/index.mjs +127 -134
- package/dist/create/index.d.mts +18 -0
- package/dist/create/index.d.ts +18 -0
- package/dist/create/index.mjs +1025 -0
- package/dist/rolldown/index.d.mts +7 -0
- package/dist/rolldown/index.d.ts +7 -0
- package/dist/rolldown/index.mjs +90 -0
- package/dist/runtime/dev.d.ts +3 -0
- package/dist/runtime/dev.mjs +58 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.mjs +2 -0
- package/dist/runtime/internal/app.d.ts +2 -0
- package/dist/runtime/internal/app.mjs +64 -0
- package/dist/runtime/internal/logger.d.ts +14 -0
- package/dist/runtime/internal/logger.mjs +45 -0
- package/dist/runtime/start.d.ts +3 -0
- package/dist/runtime/start.mjs +46 -0
- package/dist/types/index.d.mts +35 -29
- package/dist/types/index.d.ts +35 -29
- package/package.json +40 -22
- package/runtime-meta.d.ts +2 -0
- package/runtime-meta.mjs +7 -0
- package/src/cli/commands/add.ts +50 -0
- package/src/cli/commands/build.ts +5 -3
- package/src/cli/commands/dev.ts +50 -19
- package/src/cli/commands/init.ts +36 -0
- package/src/cli/commands/prepare.ts +0 -2
- package/src/cli/commands/start.ts +61 -0
- package/src/cli/index.ts +3 -0
- package/src/config/index.ts +5 -4
- package/src/core/apibara.ts +4 -2
- package/src/core/build/build.ts +15 -5
- package/src/core/build/dev.ts +44 -22
- package/src/core/build/error.ts +9 -15
- package/src/core/build/prepare.ts +5 -2
- package/src/core/build/prod.ts +24 -15
- package/src/core/build/types.ts +12 -95
- package/src/core/config/defaults.ts +4 -4
- package/src/core/config/loader.ts +1 -0
- package/src/core/config/resolvers/runtime-config.resolver.ts +1 -1
- package/src/core/config/update.ts +3 -4
- package/src/core/path.ts +11 -0
- package/src/core/scan.ts +40 -0
- package/src/create/add.ts +239 -0
- package/src/create/colors.ts +15 -0
- package/src/create/constants.ts +97 -0
- package/src/create/index.ts +2 -0
- package/src/create/init.ts +178 -0
- package/src/create/templates.ts +501 -0
- package/src/create/types.ts +34 -0
- package/src/create/utils.ts +422 -0
- package/src/rolldown/config.ts +83 -0
- package/src/rolldown/index.ts +2 -0
- package/src/rolldown/plugins/config.ts +13 -0
- package/src/rolldown/plugins/indexers.ts +17 -0
- package/src/runtime/dev.ts +67 -0
- package/src/runtime/index.ts +2 -0
- package/src/runtime/internal/app.ts +86 -0
- package/src/runtime/internal/logger.ts +70 -0
- package/src/runtime/start.ts +53 -0
- package/src/types/apibara.ts +8 -0
- package/src/types/config.ts +37 -31
- package/src/types/hooks.ts +8 -4
- package/src/types/index.ts +1 -1
- package/src/types/rolldown.ts +5 -0
- package/src/types/virtual/config.d.ts +3 -0
- package/src/types/virtual/indexers.d.ts +13 -0
- package/dist/internal/citty/index.d.mts +0 -1
- package/dist/internal/citty/index.d.ts +0 -1
- package/dist/internal/citty/index.mjs +0 -1
- package/dist/internal/consola/index.d.mts +0 -2
- package/dist/internal/consola/index.d.ts +0 -2
- package/dist/internal/consola/index.mjs +0 -1
- package/dist/rollup/index.d.mts +0 -5
- package/dist/rollup/index.d.ts +0 -5
- package/dist/rollup/index.mjs +0 -187
- package/src/internal/citty/index.ts +0 -1
- package/src/internal/consola/index.ts +0 -1
- package/src/rollup/config.ts +0 -209
- package/src/rollup/index.ts +0 -1
- package/src/types/rollup.ts +0 -8
package/src/core/build/error.ts
CHANGED
|
@@ -1,30 +1,24 @@
|
|
|
1
|
-
import type esbuild from "esbuild";
|
|
2
1
|
import { isAbsolute, relative } from "pathe";
|
|
3
|
-
import type
|
|
2
|
+
import type * as rolldown from "rolldown";
|
|
4
3
|
|
|
5
|
-
export function
|
|
6
|
-
_error: rollup.RollupError | esbuild.OnResolveResult,
|
|
7
|
-
) {
|
|
4
|
+
export function formatRolldownError(_error: rolldown.RollupError) {
|
|
8
5
|
try {
|
|
9
6
|
const logs: string[] = [_error.toString()];
|
|
10
7
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
11
|
-
const errors = (_error as any)?.errors || [_error as
|
|
8
|
+
const errors = (_error as any)?.errors || [_error as rolldown.RollupError];
|
|
12
9
|
for (const error of errors) {
|
|
13
|
-
const id = error.path || error.id || (_error as
|
|
10
|
+
const id = error.path || error.id || (_error as rolldown.RollupError).id;
|
|
14
11
|
let path = isAbsolute(id) ? relative(process.cwd(), id) : id;
|
|
15
|
-
const location =
|
|
16
|
-
(error as rollup.RollupError).loc ||
|
|
17
|
-
(error as esbuild.PartialMessage).location;
|
|
12
|
+
const location = (error as rolldown.RollupError).loc;
|
|
18
13
|
if (location) {
|
|
19
14
|
path += `:${location.line}:${location.column}`;
|
|
20
15
|
}
|
|
21
|
-
const text =
|
|
22
|
-
(error as esbuild.PartialMessage).text ||
|
|
23
|
-
(error as rollup.RollupError).frame;
|
|
16
|
+
const text = (error as rolldown.RollupError).frame;
|
|
24
17
|
|
|
25
18
|
logs.push(
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
`Rolldown error while processing \`${path}\`` + text
|
|
20
|
+
? "\n\n" + text
|
|
21
|
+
: "",
|
|
28
22
|
);
|
|
29
23
|
}
|
|
30
24
|
return logs.join("\n");
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import fsp from "node:fs/promises";
|
|
2
2
|
import type { Apibara } from "apibara/types";
|
|
3
|
-
import consola from "consola";
|
|
4
3
|
import fse from "fs-extra";
|
|
4
|
+
import { prettyPath } from "../path";
|
|
5
5
|
|
|
6
6
|
export async function prepare(apibara: Apibara) {
|
|
7
7
|
await prepareDir(apibara.options.buildDir);
|
|
8
8
|
await prepareDir(apibara.options.outputDir);
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
apibara.logger.success(
|
|
11
|
+
`Output directory ${prettyPath(apibara.options.outputDir)} cleaned`,
|
|
12
|
+
);
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
async function prepareDir(dir: string) {
|
package/src/core/build/prod.ts
CHANGED
|
@@ -1,32 +1,41 @@
|
|
|
1
|
-
import type { Apibara
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import type { Apibara } from "apibara/types";
|
|
2
|
+
import { colors } from "consola/utils";
|
|
3
|
+
import * as rolldown from "rolldown";
|
|
4
4
|
|
|
5
5
|
export async function buildProduction(
|
|
6
6
|
apibara: Apibara,
|
|
7
|
-
|
|
7
|
+
rolldownConfig: rolldown.RolldownOptions,
|
|
8
8
|
) {
|
|
9
|
+
apibara.logger.start(
|
|
10
|
+
`Building ${colors.cyan(apibara.indexers.length)} indexers`,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const startTime = Date.now();
|
|
14
|
+
|
|
9
15
|
try {
|
|
10
|
-
|
|
11
|
-
const bundle = await rollup(rollupConfig);
|
|
16
|
+
const bundle = await rolldown.rolldown(rolldownConfig);
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
for (const outputOptions of rollupConfig.output) {
|
|
18
|
+
if (Array.isArray(rolldownConfig.output)) {
|
|
19
|
+
for (const outputOptions of rolldownConfig.output) {
|
|
16
20
|
await bundle.write(outputOptions);
|
|
17
21
|
}
|
|
18
|
-
} else if (
|
|
19
|
-
await bundle.write(
|
|
22
|
+
} else if (rolldownConfig.output) {
|
|
23
|
+
await bundle.write(rolldownConfig.output as rolldown.OutputOptions);
|
|
20
24
|
} else {
|
|
21
|
-
throw new Error("No output options specified in
|
|
25
|
+
throw new Error("No output options specified in Rolldown config");
|
|
22
26
|
}
|
|
23
27
|
|
|
24
|
-
// Close the bundle
|
|
25
28
|
await bundle.close();
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
const endTime = Date.now();
|
|
31
|
+
const duration = endTime - startTime;
|
|
32
|
+
|
|
33
|
+
apibara.logger.success(`Build succeeded in ${duration}ms`);
|
|
34
|
+
apibara.logger.info(
|
|
35
|
+
`You can start the indexers with ${colors.cyan("apibara start")}`,
|
|
36
|
+
);
|
|
28
37
|
} catch (error) {
|
|
29
|
-
|
|
38
|
+
apibara.logger.error("Build failed", error);
|
|
30
39
|
throw error;
|
|
31
40
|
}
|
|
32
41
|
}
|
package/src/core/build/types.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import fsp from "node:fs/promises";
|
|
2
2
|
import type { Apibara } from "apibara/types";
|
|
3
|
-
import
|
|
4
|
-
import defu from "defu";
|
|
5
|
-
import { dirname, isAbsolute, join, relative, resolve } from "pathe";
|
|
6
|
-
import type { TSConfig } from "pkg-types";
|
|
3
|
+
import { dirname, join, resolve } from "pathe";
|
|
7
4
|
import { type JSValue, generateTypes, resolveSchema } from "untyped";
|
|
5
|
+
import { prettyPath } from "../path";
|
|
8
6
|
|
|
9
7
|
export async function writeTypes(apibara: Apibara) {
|
|
8
|
+
// Check if the config file has a TypeScript extension so we assume it's a TypeScript project
|
|
9
|
+
const isTypeScript = apibara.options._c12.configFile?.endsWith(".ts");
|
|
10
|
+
|
|
11
|
+
if (!isTypeScript) {
|
|
12
|
+
// If it's not a TypeScript project, we don't need to generate the types
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
const typesDir = resolve(apibara.options.buildDir, "types");
|
|
11
17
|
|
|
12
18
|
const config = [
|
|
@@ -31,12 +37,7 @@ declare module "apibara/types" {`,
|
|
|
31
37
|
: "",
|
|
32
38
|
"}",
|
|
33
39
|
// Makes this a module for augmentation purposes
|
|
34
|
-
"export type {}",
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const declarations = [
|
|
38
|
-
// local apibara augmentations
|
|
39
|
-
'/// <reference path="./apibara-config.d.ts" />',
|
|
40
|
+
"export type {};",
|
|
40
41
|
];
|
|
41
42
|
|
|
42
43
|
const buildFiles: { path: string; contents: string }[] = [];
|
|
@@ -46,83 +47,6 @@ declare module "apibara/types" {`,
|
|
|
46
47
|
contents: config.join("\n"),
|
|
47
48
|
});
|
|
48
49
|
|
|
49
|
-
buildFiles.push({
|
|
50
|
-
path: join(typesDir, "apibara.d.ts"),
|
|
51
|
-
contents: declarations.join("\n"),
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
if (apibara.options.typescript.generateTsConfig) {
|
|
55
|
-
const tsConfigPath = resolve(
|
|
56
|
-
apibara.options.buildDir,
|
|
57
|
-
apibara.options.typescript.tsconfigPath,
|
|
58
|
-
);
|
|
59
|
-
const tsconfigDir = dirname(tsConfigPath);
|
|
60
|
-
const tsConfig: TSConfig = defu(apibara.options.typescript.tsConfig, {
|
|
61
|
-
compilerOptions: {
|
|
62
|
-
forceConsistentCasingInFileNames: true,
|
|
63
|
-
strict: apibara.options.typescript.strict,
|
|
64
|
-
noEmit: true,
|
|
65
|
-
target: "ESNext",
|
|
66
|
-
module: "ESNext",
|
|
67
|
-
moduleResolution: "Bundler",
|
|
68
|
-
allowJs: true,
|
|
69
|
-
resolveJsonModule: true,
|
|
70
|
-
jsx: "preserve",
|
|
71
|
-
allowSyntheticDefaultImports: true,
|
|
72
|
-
jsxFactory: "h",
|
|
73
|
-
jsxFragmentFactory: "Fragment",
|
|
74
|
-
},
|
|
75
|
-
include: [
|
|
76
|
-
relativeWithDot(tsconfigDir, join(typesDir, "apibara.d.ts")).replace(
|
|
77
|
-
/^(?=[^.])/,
|
|
78
|
-
"./",
|
|
79
|
-
),
|
|
80
|
-
],
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
for (const alias in tsConfig.compilerOptions!.paths) {
|
|
84
|
-
const paths = tsConfig.compilerOptions!.paths[alias];
|
|
85
|
-
tsConfig.compilerOptions!.paths[alias] = await Promise.all(
|
|
86
|
-
paths.map(async (path: string) => {
|
|
87
|
-
if (!isAbsolute(path)) {
|
|
88
|
-
return path;
|
|
89
|
-
}
|
|
90
|
-
const stats = await fsp
|
|
91
|
-
.stat(path)
|
|
92
|
-
.catch(() => null /* file does not exist */);
|
|
93
|
-
return relativeWithDot(
|
|
94
|
-
tsconfigDir,
|
|
95
|
-
stats?.isFile()
|
|
96
|
-
? path.replace(/(?<=\w)\.\w+$/g, "") /* remove extension */
|
|
97
|
-
: path,
|
|
98
|
-
);
|
|
99
|
-
}),
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
tsConfig.include = [
|
|
104
|
-
...new Set(
|
|
105
|
-
tsConfig.include!.map((p) =>
|
|
106
|
-
isAbsolute(p) ? relativeWithDot(tsconfigDir, p) : p,
|
|
107
|
-
),
|
|
108
|
-
),
|
|
109
|
-
];
|
|
110
|
-
if (tsConfig.exclude) {
|
|
111
|
-
tsConfig.exclude = [
|
|
112
|
-
...new Set(
|
|
113
|
-
tsConfig.exclude!.map((p) =>
|
|
114
|
-
isAbsolute(p) ? relativeWithDot(tsconfigDir, p) : p,
|
|
115
|
-
),
|
|
116
|
-
),
|
|
117
|
-
];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
buildFiles.push({
|
|
121
|
-
path: tsConfigPath,
|
|
122
|
-
contents: JSON.stringify(tsConfig, null, 2),
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
50
|
await Promise.all(
|
|
127
51
|
buildFiles.map(async (file) => {
|
|
128
52
|
const _file = resolve(apibara.options.buildDir, file.path);
|
|
@@ -131,12 +55,5 @@ declare module "apibara/types" {`,
|
|
|
131
55
|
}),
|
|
132
56
|
);
|
|
133
57
|
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const RELATIVE_RE = /^\.{1,2}\//;
|
|
138
|
-
|
|
139
|
-
export function relativeWithDot(from: string, to: string) {
|
|
140
|
-
const rel = relative(from, to);
|
|
141
|
-
return RELATIVE_RE.test(rel) ? rel : `./${rel}`;
|
|
58
|
+
apibara.logger.success(`Types written to ${prettyPath(typesDir)}`);
|
|
142
59
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// import { defaultSink } from "@apibara/indexer";
|
|
2
1
|
import type { ApibaraConfig } from "apibara/types";
|
|
3
2
|
|
|
4
3
|
export const ApibaraDefaults: ApibaraConfig = {
|
|
5
4
|
rootDir: ".",
|
|
5
|
+
indexersDir: "indexers",
|
|
6
6
|
|
|
7
7
|
runtimeConfig: {},
|
|
8
8
|
hooks: {},
|
|
@@ -11,10 +11,10 @@ export const ApibaraDefaults: ApibaraConfig = {
|
|
|
11
11
|
|
|
12
12
|
typescript: {
|
|
13
13
|
strict: false,
|
|
14
|
-
generateTsConfig: true,
|
|
15
14
|
generateRuntimeConfigTypes: true,
|
|
16
|
-
tsconfigPath: "types/tsconfig.json",
|
|
17
15
|
internalPaths: false,
|
|
18
|
-
tsConfig: {},
|
|
19
16
|
},
|
|
17
|
+
|
|
18
|
+
node: true,
|
|
19
|
+
exportConditions: ["node"],
|
|
20
20
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ApibaraOptions } from "apibara/types";
|
|
2
2
|
|
|
3
3
|
export async function resolveRuntimeConfigOptions(options: ApibaraOptions) {
|
|
4
|
-
options.runtimeConfig = { ...options.runtimeConfig
|
|
4
|
+
options.runtimeConfig = { ...options.runtimeConfig };
|
|
5
5
|
process.env.APIBARA_RUNTIME_CONFIG = JSON.stringify(options.runtimeConfig);
|
|
6
6
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { Apibara, ApibaraDynamicConfig } from "apibara/types";
|
|
2
|
-
import consola from "consola";
|
|
3
2
|
|
|
4
3
|
export async function updateApibaraConfig(
|
|
5
4
|
apibara: Apibara,
|
|
6
|
-
|
|
5
|
+
_config: ApibaraDynamicConfig,
|
|
7
6
|
) {
|
|
8
|
-
await apibara.hooks.callHook("
|
|
9
|
-
|
|
7
|
+
await apibara.hooks.callHook("rolldown:reload");
|
|
8
|
+
apibara.logger.success("Apibara config hot reloaded!");
|
|
10
9
|
}
|
package/src/core/path.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { colors } from "consola/utils";
|
|
2
|
+
import { relative } from "pathe";
|
|
3
|
+
|
|
4
|
+
/** Return a (possibly highlighted) path relative to the current working directory.
|
|
5
|
+
*
|
|
6
|
+
* From nitrojs/nitro.
|
|
7
|
+
*/
|
|
8
|
+
export function prettyPath(path: string, highlight = true) {
|
|
9
|
+
const rel = relative(process.cwd(), path);
|
|
10
|
+
return highlight ? colors.cyan(rel) : rel;
|
|
11
|
+
}
|
package/src/core/scan.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Apibara } from "apibara/types";
|
|
2
|
+
import fse from "fs-extra";
|
|
3
|
+
import { basename, join } from "pathe";
|
|
4
|
+
|
|
5
|
+
const INDEXER_EXTENSIONS = [".indexer.ts", ".indexer.js"];
|
|
6
|
+
|
|
7
|
+
export async function scanIndexers(apibara: Apibara) {
|
|
8
|
+
apibara.logger.debug("Scanning indexers");
|
|
9
|
+
|
|
10
|
+
const indexersDir = join(
|
|
11
|
+
apibara.options.rootDir,
|
|
12
|
+
apibara.options.indexersDir,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
if (!fse.existsSync(indexersDir)) {
|
|
16
|
+
throw new Error(`Indexers directory not found: ${indexersDir}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
apibara.indexers = [];
|
|
20
|
+
|
|
21
|
+
for (const file of fse.readdirSync(indexersDir)) {
|
|
22
|
+
const indexerName = indexerNameFromFile(file);
|
|
23
|
+
if (indexerName) {
|
|
24
|
+
apibara.indexers.push({
|
|
25
|
+
name: indexerName,
|
|
26
|
+
indexer: join(indexersDir, file),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
apibara.logger.debug(`Found ${apibara.indexers.length} indexers`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function indexerNameFromFile(file: string) {
|
|
35
|
+
for (const extension of INDEXER_EXTENSIONS) {
|
|
36
|
+
if (file.endsWith(extension)) {
|
|
37
|
+
return basename(file, extension);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import consola from "consola";
|
|
3
|
+
import prompts from "prompts";
|
|
4
|
+
import { cyan, red, reset } from "./colors";
|
|
5
|
+
import {
|
|
6
|
+
type ChainDataType,
|
|
7
|
+
type NetworkDataType,
|
|
8
|
+
type StorageDataType,
|
|
9
|
+
chains,
|
|
10
|
+
storages,
|
|
11
|
+
} from "./constants";
|
|
12
|
+
import { initializeProject } from "./init";
|
|
13
|
+
import {
|
|
14
|
+
createIndexerFile,
|
|
15
|
+
createStorageRelatedFiles,
|
|
16
|
+
updateApibaraConfigFile,
|
|
17
|
+
updatePackageJson,
|
|
18
|
+
} from "./templates";
|
|
19
|
+
import type { Chain, IndexerOptions, Network, Storage } from "./types";
|
|
20
|
+
import {
|
|
21
|
+
cancelOperation,
|
|
22
|
+
checkFileExists,
|
|
23
|
+
convertKebabToCamelCase,
|
|
24
|
+
getApibaraConfigLanguage,
|
|
25
|
+
getPackageManager,
|
|
26
|
+
hasApibaraConfig,
|
|
27
|
+
validateChain,
|
|
28
|
+
validateDnaUrl,
|
|
29
|
+
validateIndexerId,
|
|
30
|
+
validateNetwork,
|
|
31
|
+
validateStorage,
|
|
32
|
+
} from "./utils";
|
|
33
|
+
|
|
34
|
+
type Options = {
|
|
35
|
+
argIndexerId?: string;
|
|
36
|
+
argChain?: string;
|
|
37
|
+
argNetwork?: string;
|
|
38
|
+
argStorage?: string;
|
|
39
|
+
argDnaUrl?: string;
|
|
40
|
+
argRootDir?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export async function addIndexer({
|
|
44
|
+
argIndexerId,
|
|
45
|
+
argChain,
|
|
46
|
+
argNetwork,
|
|
47
|
+
argStorage,
|
|
48
|
+
argDnaUrl,
|
|
49
|
+
argRootDir,
|
|
50
|
+
}: Options) {
|
|
51
|
+
const cwd = path.join(process.cwd(), argRootDir ?? ".");
|
|
52
|
+
const configExists = hasApibaraConfig(cwd);
|
|
53
|
+
|
|
54
|
+
if (!configExists) {
|
|
55
|
+
consola.error("No apibara.config found in the current directory.");
|
|
56
|
+
|
|
57
|
+
const prompt_initialize = await prompts({
|
|
58
|
+
type: "confirm",
|
|
59
|
+
name: "prompt_initialize",
|
|
60
|
+
message: reset(
|
|
61
|
+
"Do you want to initialize a apibara project here before adding an indexer?",
|
|
62
|
+
),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (prompt_initialize.prompt_initialize) {
|
|
66
|
+
await initializeProject({
|
|
67
|
+
argTargetDir: process.cwd(),
|
|
68
|
+
argNoCreateIndexer: true,
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
consola.info(
|
|
72
|
+
`Initialize a project with ${cyan("apibara init")} before adding an indexer`,
|
|
73
|
+
);
|
|
74
|
+
throw new Error(
|
|
75
|
+
red("✖") + " Operation cancelled: No apibara.config found",
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const language = getApibaraConfigLanguage(cwd);
|
|
81
|
+
|
|
82
|
+
validateIndexerId(argIndexerId, true);
|
|
83
|
+
validateChain(argChain, true);
|
|
84
|
+
validateNetwork(argChain, argNetwork, true);
|
|
85
|
+
validateStorage(argStorage, true);
|
|
86
|
+
validateDnaUrl(argDnaUrl, true);
|
|
87
|
+
|
|
88
|
+
const result = await prompts(
|
|
89
|
+
[
|
|
90
|
+
{
|
|
91
|
+
type: argIndexerId ? null : "text",
|
|
92
|
+
name: "prompt_indexerId",
|
|
93
|
+
message: reset("Indexer ID:"),
|
|
94
|
+
initial: argIndexerId ?? "my-indexer",
|
|
95
|
+
validate: (id) =>
|
|
96
|
+
validateIndexerId(id)
|
|
97
|
+
? checkFileExists(
|
|
98
|
+
path.join(
|
|
99
|
+
cwd,
|
|
100
|
+
"indexers",
|
|
101
|
+
`${id}.indexer.${language === "typescript" ? "ts" : "js"}`,
|
|
102
|
+
),
|
|
103
|
+
).then(({ exists }) =>
|
|
104
|
+
exists
|
|
105
|
+
? `Indexer ${cyan(`${id}.indexer.${language === "typescript" ? "ts" : "js"}`)} already exists`
|
|
106
|
+
: true,
|
|
107
|
+
)
|
|
108
|
+
: "Invalid indexer ID, it cannot be empty and must be in kebab-case format",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: argChain ? null : "select",
|
|
112
|
+
name: "prompt_chain",
|
|
113
|
+
message: reset("Select a chain:"),
|
|
114
|
+
choices: chains.map((chain) => ({
|
|
115
|
+
title: chain.color(chain.display),
|
|
116
|
+
value: chain,
|
|
117
|
+
})),
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
type: argNetwork ? null : "select",
|
|
121
|
+
name: "prompt_network",
|
|
122
|
+
message: reset("Select a network:"),
|
|
123
|
+
choices: (chain: ChainDataType | undefined) => [
|
|
124
|
+
...(
|
|
125
|
+
chain?.networks ??
|
|
126
|
+
chains.find((c) => c.name === argChain)?.networks ??
|
|
127
|
+
[]
|
|
128
|
+
).map((network) => ({
|
|
129
|
+
title: network.color(network.display),
|
|
130
|
+
value: network,
|
|
131
|
+
})),
|
|
132
|
+
{
|
|
133
|
+
title: cyan("Other"),
|
|
134
|
+
value: {
|
|
135
|
+
color: cyan,
|
|
136
|
+
display: "Other",
|
|
137
|
+
name: "other",
|
|
138
|
+
} as NetworkDataType,
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: (network: NetworkDataType | undefined) => {
|
|
144
|
+
if (network || argNetwork) {
|
|
145
|
+
return network?.name === "other" || argNetwork === "other"
|
|
146
|
+
? "text"
|
|
147
|
+
: null;
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
},
|
|
151
|
+
name: "prompt_dnaUrl",
|
|
152
|
+
message: reset("Enter a DNA URL:"),
|
|
153
|
+
validate: (url) => validateDnaUrl(url) || "Provide a valid DNA Url",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: argStorage ? null : "select",
|
|
157
|
+
name: "prompt_storage",
|
|
158
|
+
message: reset("Select a storage:"),
|
|
159
|
+
choices: storages.map((storage) => ({
|
|
160
|
+
title: storage.color(storage.display),
|
|
161
|
+
value: storage,
|
|
162
|
+
})),
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
{
|
|
166
|
+
onCancel: () => {
|
|
167
|
+
cancelOperation();
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const {
|
|
173
|
+
prompt_indexerId,
|
|
174
|
+
prompt_chain,
|
|
175
|
+
prompt_network,
|
|
176
|
+
prompt_storage,
|
|
177
|
+
prompt_dnaUrl,
|
|
178
|
+
} = result as {
|
|
179
|
+
prompt_indexerId: string | undefined;
|
|
180
|
+
prompt_chain: ChainDataType | undefined;
|
|
181
|
+
prompt_network: NetworkDataType | undefined;
|
|
182
|
+
prompt_storage: StorageDataType | undefined;
|
|
183
|
+
prompt_dnaUrl: string | undefined;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
if (!argIndexerId && !prompt_indexerId) {
|
|
187
|
+
throw new Error(red("✖") + " Indexer ID is required");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (!argChain && !prompt_chain) {
|
|
191
|
+
throw new Error(red("✖") + " Chain is required");
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!argNetwork && !prompt_network) {
|
|
195
|
+
throw new Error(red("✖") + " Network is required");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const indexerFileId = argIndexerId! ?? prompt_indexerId!;
|
|
199
|
+
|
|
200
|
+
const pkgManager = getPackageManager();
|
|
201
|
+
|
|
202
|
+
const options: IndexerOptions = {
|
|
203
|
+
cwd: cwd,
|
|
204
|
+
indexerFileId,
|
|
205
|
+
indexerId: convertKebabToCamelCase(indexerFileId),
|
|
206
|
+
chain: (argChain as Chain) ?? prompt_chain?.name!,
|
|
207
|
+
network: (argNetwork as Network) ?? prompt_network?.name!,
|
|
208
|
+
storage: (argStorage as Storage) ?? prompt_storage?.name!,
|
|
209
|
+
dnaUrl: argDnaUrl ?? prompt_dnaUrl,
|
|
210
|
+
language,
|
|
211
|
+
packageManager: pkgManager.name,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
await updateApibaraConfigFile(options);
|
|
215
|
+
|
|
216
|
+
consola.success(
|
|
217
|
+
`Updated ${cyan("apibara.config." + (language === "typescript" ? "ts" : "js"))}`,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
await updatePackageJson(options);
|
|
221
|
+
|
|
222
|
+
consola.success(`Updated ${cyan("package.json")}`);
|
|
223
|
+
|
|
224
|
+
await createIndexerFile(options);
|
|
225
|
+
|
|
226
|
+
consola.success(
|
|
227
|
+
`Created ${cyan(`${indexerFileId}.indexer.${language === "typescript" ? "ts" : "js"}`)}`,
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
await createStorageRelatedFiles(options);
|
|
231
|
+
|
|
232
|
+
console.log();
|
|
233
|
+
|
|
234
|
+
const baseCommand = `${options.packageManager} install`;
|
|
235
|
+
const tsCommand = `${baseCommand} && ${options.packageManager} run prepare`;
|
|
236
|
+
consola.info(
|
|
237
|
+
`Before running the indexer, run ${cyan(language === "typescript" ? tsCommand : baseCommand)}`,
|
|
238
|
+
);
|
|
239
|
+
}
|