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.
Files changed (90) hide show
  1. package/dist/chunks/add.mjs +49 -0
  2. package/dist/chunks/build.mjs +3 -3
  3. package/dist/chunks/dev.mjs +41 -19
  4. package/dist/chunks/init.mjs +37 -0
  5. package/dist/chunks/prepare.mjs +0 -2
  6. package/dist/chunks/start.mjs +56 -0
  7. package/dist/cli/index.mjs +5 -1
  8. package/dist/config/index.d.mts +1 -1
  9. package/dist/config/index.d.ts +1 -1
  10. package/dist/core/index.mjs +127 -134
  11. package/dist/create/index.d.mts +18 -0
  12. package/dist/create/index.d.ts +18 -0
  13. package/dist/create/index.mjs +1025 -0
  14. package/dist/rolldown/index.d.mts +7 -0
  15. package/dist/rolldown/index.d.ts +7 -0
  16. package/dist/rolldown/index.mjs +90 -0
  17. package/dist/runtime/dev.d.ts +3 -0
  18. package/dist/runtime/dev.mjs +58 -0
  19. package/dist/runtime/index.d.ts +2 -0
  20. package/dist/runtime/index.mjs +2 -0
  21. package/dist/runtime/internal/app.d.ts +2 -0
  22. package/dist/runtime/internal/app.mjs +64 -0
  23. package/dist/runtime/internal/logger.d.ts +14 -0
  24. package/dist/runtime/internal/logger.mjs +45 -0
  25. package/dist/runtime/start.d.ts +3 -0
  26. package/dist/runtime/start.mjs +46 -0
  27. package/dist/types/index.d.mts +35 -29
  28. package/dist/types/index.d.ts +35 -29
  29. package/package.json +40 -22
  30. package/runtime-meta.d.ts +2 -0
  31. package/runtime-meta.mjs +7 -0
  32. package/src/cli/commands/add.ts +50 -0
  33. package/src/cli/commands/build.ts +5 -3
  34. package/src/cli/commands/dev.ts +50 -19
  35. package/src/cli/commands/init.ts +36 -0
  36. package/src/cli/commands/prepare.ts +0 -2
  37. package/src/cli/commands/start.ts +61 -0
  38. package/src/cli/index.ts +3 -0
  39. package/src/config/index.ts +5 -4
  40. package/src/core/apibara.ts +4 -2
  41. package/src/core/build/build.ts +15 -5
  42. package/src/core/build/dev.ts +44 -22
  43. package/src/core/build/error.ts +9 -15
  44. package/src/core/build/prepare.ts +5 -2
  45. package/src/core/build/prod.ts +24 -15
  46. package/src/core/build/types.ts +12 -95
  47. package/src/core/config/defaults.ts +4 -4
  48. package/src/core/config/loader.ts +1 -0
  49. package/src/core/config/resolvers/runtime-config.resolver.ts +1 -1
  50. package/src/core/config/update.ts +3 -4
  51. package/src/core/path.ts +11 -0
  52. package/src/core/scan.ts +40 -0
  53. package/src/create/add.ts +239 -0
  54. package/src/create/colors.ts +15 -0
  55. package/src/create/constants.ts +97 -0
  56. package/src/create/index.ts +2 -0
  57. package/src/create/init.ts +178 -0
  58. package/src/create/templates.ts +501 -0
  59. package/src/create/types.ts +34 -0
  60. package/src/create/utils.ts +422 -0
  61. package/src/rolldown/config.ts +83 -0
  62. package/src/rolldown/index.ts +2 -0
  63. package/src/rolldown/plugins/config.ts +13 -0
  64. package/src/rolldown/plugins/indexers.ts +17 -0
  65. package/src/runtime/dev.ts +67 -0
  66. package/src/runtime/index.ts +2 -0
  67. package/src/runtime/internal/app.ts +86 -0
  68. package/src/runtime/internal/logger.ts +70 -0
  69. package/src/runtime/start.ts +53 -0
  70. package/src/types/apibara.ts +8 -0
  71. package/src/types/config.ts +37 -31
  72. package/src/types/hooks.ts +8 -4
  73. package/src/types/index.ts +1 -1
  74. package/src/types/rolldown.ts +5 -0
  75. package/src/types/virtual/config.d.ts +3 -0
  76. package/src/types/virtual/indexers.d.ts +13 -0
  77. package/dist/internal/citty/index.d.mts +0 -1
  78. package/dist/internal/citty/index.d.ts +0 -1
  79. package/dist/internal/citty/index.mjs +0 -1
  80. package/dist/internal/consola/index.d.mts +0 -2
  81. package/dist/internal/consola/index.d.ts +0 -2
  82. package/dist/internal/consola/index.mjs +0 -1
  83. package/dist/rollup/index.d.mts +0 -5
  84. package/dist/rollup/index.d.ts +0 -5
  85. package/dist/rollup/index.mjs +0 -187
  86. package/src/internal/citty/index.ts +0 -1
  87. package/src/internal/consola/index.ts +0 -1
  88. package/src/rollup/config.ts +0 -209
  89. package/src/rollup/index.ts +0 -1
  90. package/src/types/rollup.ts +0 -8
@@ -1,30 +1,24 @@
1
- import type esbuild from "esbuild";
2
1
  import { isAbsolute, relative } from "pathe";
3
- import type rollup from "rollup";
2
+ import type * as rolldown from "rolldown";
4
3
 
5
- export function formatRollupError(
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 rollup.RollupError];
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 rollup.RollupError).id;
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
- // biome-ignore lint/style/useTemplate: <explanation>
27
- `Rollup error while processing \`${path}\`` + text ? "\n\n" + text : "",
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
- consola.success("Output directory cleaned");
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) {
@@ -1,32 +1,41 @@
1
- import type { Apibara, RollupConfig } from "apibara/types";
2
- import consola from "consola";
3
- import { type OutputOptions, rollup } from "rollup";
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
- rollupConfig: RollupConfig,
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
- // Create a bundle
11
- const bundle = await rollup(rollupConfig);
16
+ const bundle = await rolldown.rolldown(rolldownConfig);
12
17
 
13
- // Generate output
14
- if (Array.isArray(rollupConfig.output)) {
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 (rollupConfig.output) {
19
- await bundle.write(rollupConfig.output as OutputOptions);
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 Rollup config");
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
- consola.success("Build completed successfully!");
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
- console.error("Build failed:", error);
38
+ apibara.logger.error("Build failed", error);
30
39
  throw error;
31
40
  }
32
41
  }
@@ -1,12 +1,18 @@
1
1
  import fsp from "node:fs/promises";
2
2
  import type { Apibara } from "apibara/types";
3
- import consola from "consola";
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
- consola.success("Types generated");
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
  };
@@ -53,6 +53,7 @@ async function _loadUserConfig(
53
53
 
54
54
  options._config = configOverrides;
55
55
  options._c12 = loadedConfig;
56
+
56
57
  if (dev) {
57
58
  options.dev = dev;
58
59
  }
@@ -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, default: "value" };
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
- config: ApibaraDynamicConfig,
5
+ _config: ApibaraDynamicConfig,
7
6
  ) {
8
- await apibara.hooks.callHook("rollup:reload");
9
- consola.success("Apibara config hot reloaded!");
7
+ await apibara.hooks.callHook("rolldown:reload");
8
+ apibara.logger.success("Apibara config hot reloaded!");
10
9
  }
@@ -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
+ }
@@ -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
+ }
@@ -0,0 +1,15 @@
1
+ import colors from "picocolors";
2
+
3
+ export const {
4
+ blue,
5
+ blueBright,
6
+ cyan,
7
+ gray,
8
+ green,
9
+ greenBright,
10
+ magenta,
11
+ red,
12
+ redBright,
13
+ reset,
14
+ yellow,
15
+ } = colors;