@paimaexample/npm-midnight-indexer 0.3.127 → 0.3.128

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/binary.js CHANGED
@@ -44,6 +44,8 @@ function getBinaryUrl() {
44
44
  return `https://github.com/effectstream/binaries/releases/download/0.3.120/indexer-standalone-${platform}-${CURRENT_BINARY_VERSION}.zip`;
45
45
  }
46
46
 
47
+ const ZIP_FILE_PATH = path.join(__dirname, "indexer-standalone.zip");
48
+
47
49
  /*
48
50
  @returns {Promise<void>} Downloads and saves the binary for the current platform.
49
51
  */
@@ -52,9 +54,7 @@ async function downloadAndSaveBinary() {
52
54
  try {
53
55
  console.error(`Downloading... ${url}`);
54
56
  const response = await axios.get(url, { responseType: "stream" });
55
- const writer = fs.createWriteStream(
56
- path.join(__dirname, "indexer-standalone.zip"),
57
- );
57
+ const writer = fs.createWriteStream(ZIP_FILE_PATH);
58
58
 
59
59
  response.data.pipe(writer);
60
60
 
@@ -76,27 +76,65 @@ async function unzipBinary() {
76
76
  if (!fs.existsSync(dir)) {
77
77
  fs.mkdirSync(dir, { recursive: true });
78
78
  }
79
- await extract(path.join(__dirname, "indexer-standalone.zip"), { dir });
79
+ await extract(ZIP_FILE_PATH, { dir });
80
80
  const dataDir = path.join(dir, "data");
81
81
  if (!fs.existsSync(dataDir)) {
82
82
  fs.mkdirSync(dataDir, { recursive: true });
83
83
  }
84
84
 
85
85
  const platform = getPlatform();
86
- const extractedBinaryPath = path.join(
87
- dir,
86
+ const possibleBinaryNames = [
87
+ `indexer-standalone-${platform}-${CURRENT_BINARY_VERSION}`,
88
88
  `indexer-standalone`,
89
- );
89
+ `indexer-standalone-${platform}`
90
+ ];
91
+
92
+ let extractedBinaryPath = null;
93
+ for (const name of possibleBinaryNames) {
94
+ const p = path.join(dir, name);
95
+ if (fs.existsSync(p) && fs.statSync(p).isFile()) {
96
+ extractedBinaryPath = p;
97
+ break;
98
+ }
99
+ }
100
+
90
101
  const finalBinaryPath = path.join(dir, FINAL_BINARY_NAME);
91
102
 
92
103
  // Rename the extracted file to indexer-standalone
93
- if (fs.existsSync(extractedBinaryPath)) {
94
- if (fs.existsSync(finalBinaryPath)) {
95
- fs.unlinkSync(finalBinaryPath);
104
+ if (extractedBinaryPath) {
105
+ if (extractedBinaryPath !== finalBinaryPath) {
106
+ if (fs.existsSync(finalBinaryPath)) {
107
+ fs.unlinkSync(finalBinaryPath);
108
+ }
109
+ fs.renameSync(extractedBinaryPath, finalBinaryPath);
96
110
  }
97
- fs.renameSync(extractedBinaryPath, finalBinaryPath);
98
111
  } else {
99
- throw new Error(`Extracted binary not found at: ${extractedBinaryPath}`);
112
+ throw new Error(`Extracted binary not found in: ${dir}. Expected one of: ${possibleBinaryNames.join(", ")}`);
113
+ }
114
+
115
+ // Clean up any other extracted files (e.g., readme.md)
116
+ const files = fs.readdirSync(dir);
117
+ for (const file of files) {
118
+ const filePath = path.join(dir, file);
119
+ // Explicitly protect config.yaml and other potential config files
120
+ const isConfigFile =
121
+ file === "config.yaml" ||
122
+ file === "config.yml" ||
123
+ file.endsWith(".yaml") ||
124
+ file.endsWith(".yml") ||
125
+ file.endsWith(".toml") ||
126
+ file.endsWith(".json");
127
+
128
+ if (
129
+ filePath !== finalBinaryPath &&
130
+ file !== "data" &&
131
+ !isConfigFile &&
132
+ fs.existsSync(filePath) &&
133
+ fs.statSync(filePath).isFile()
134
+ ) {
135
+ console.log(`Cleaning up extracted file: ${file}`);
136
+ fs.unlinkSync(filePath);
137
+ }
100
138
  }
101
139
 
102
140
  if (!fs.existsSync(finalBinaryPath)) {
@@ -104,7 +142,7 @@ async function unzipBinary() {
104
142
  }
105
143
 
106
144
  fs.chmodSync(finalBinaryPath, 0o755);
107
- fs.unlinkSync(path.join(__dirname, "indexer-standalone.zip"));
145
+ fs.unlinkSync(ZIP_FILE_PATH);
108
146
  }
109
147
 
110
148
  async function binary() {
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const { binary } = require("./binary");
1
+ const { binary, getPlatform } = require("./binary");
2
2
  const { runMidnightIndexer } = require("./run_midnight_indexer");
3
3
  const { checkIfDockerExists, pullDockerImage, runDockerContainer } = require(
4
4
  "./docker",
@@ -21,21 +21,9 @@ function checkIfBinaryExists() {
21
21
  * @returns {boolean} True if binary execution is supported
22
22
  */
23
23
  function isBinarySupported() {
24
- const platform = os.platform();
25
- const arch = os.arch();
26
-
27
- // Check if the current platform-arch combination is supported
24
+ const platformString = getPlatform();
28
25
  const supportedPlatforms = require("./package.json").supportedPlatforms;
29
26
 
30
- let platformString;
31
- if (platform === "darwin") {
32
- platformString = arch === "x64" ? "macos-amd64" : `macos-${arch}`;
33
- } else {
34
- platformString = arch === "x64"
35
- ? `${platform}-amd64`
36
- : `${platform}-${arch}`;
37
- }
38
-
39
27
  return supportedPlatforms.includes(platformString);
40
28
  }
41
29
 
@@ -37,4 +37,4 @@ telemetry:
37
37
  metrics:
38
38
  enabled: false
39
39
  address: "0.0.0.0"
40
- port: 9000
40
+ port: 9000
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paimaexample/npm-midnight-indexer",
3
- "version": "0.3.127",
3
+ "version": "0.3.128",
4
4
  "description": "Downloads and runs the Midnight Indexer. It needs a running Midnight Node",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -4,6 +4,91 @@ const fs = require("fs");
4
4
  const yaml = require("js-yaml");
5
5
 
6
6
  const BINARY_NAME = "indexer-standalone";
7
+
8
+ /**
9
+ * Resolves the configuration file path
10
+ * @param {Object} env - Environment variables
11
+ * @param {string} workingDir - The working directory where the indexer runs
12
+ * @returns {string} The resolved configuration file path
13
+ */
14
+ function resolveConfigPath(env, workingDir) {
15
+ if (env.CONFIG_FILE) {
16
+ return path.isAbsolute(env.CONFIG_FILE)
17
+ ? env.CONFIG_FILE
18
+ : path.resolve(workingDir, env.CONFIG_FILE);
19
+ }
20
+ // Fall back to config.yaml in the current working directory
21
+ return path.join(workingDir, "config.yaml");
22
+ }
23
+
24
+ /**
25
+ * Ensures that a configuration file exists at the given path
26
+ * @param {string} configPath - The path to the configuration file
27
+ * @param {Object} env - Environment variables
28
+ */
29
+ function ensureConfigExists(configPath, env) {
30
+ if (fs.existsSync(configPath)) {
31
+ return;
32
+ }
33
+
34
+ console.log(
35
+ `Config file not found. Generating default config at: ${configPath}`,
36
+ );
37
+
38
+ const networkId = env.LEDGER_NETWORK_ID || "Undeployed";
39
+ const nodeUrl = env.SUBSTRATE_NODE_WS_URL ||
40
+ env.APP__INFRA__NODE__URL ||
41
+ "ws://localhost:9944";
42
+ const cnnUrl = env.APP__INFRA__STORAGE__CNN_URL || "./data/indexer.sqlite";
43
+ const apiPort = env.APP__INFRA__API__PORT || 8088;
44
+
45
+ const defaultConfig = `
46
+ run_migrations: true
47
+ network_id: &network_id "${networkId}"
48
+
49
+ chain_indexer_application:
50
+ network_id: *network_id
51
+ blocks_buffer: 60
52
+ save_zswap_state_after: 1000
53
+ caught_up_max_distance: 60
54
+ caught_up_leeway: 30
55
+
56
+ wallet_indexer_application:
57
+ network_id: *network_id
58
+ active_wallets_repeat_delay: "100ms"
59
+ active_wallets_ttl: "30m"
60
+ transaction_batch_size: 10
61
+
62
+ infra:
63
+ node:
64
+ url: "${nodeUrl}"
65
+ reconnect_max_delay: "10s"
66
+ reconnect_max_attempts: 30
67
+
68
+ storage:
69
+ cnn_url: "${cnnUrl}"
70
+
71
+ api:
72
+ address: "0.0.0.0"
73
+ port: ${apiPort}
74
+ request_body_limit: "1MiB"
75
+ max_complexity: 200
76
+ max_depth: 15
77
+ network_id: *network_id
78
+
79
+ telemetry:
80
+ tracing:
81
+ enabled: false
82
+ service_name: "indexer"
83
+ metrics:
84
+ enabled: false
85
+ address: "0.0.0.0"
86
+ port: 9000
87
+ `;
88
+
89
+ fs.writeFileSync(configPath, defaultConfig.trim());
90
+ }
91
+
7
92
  /**
8
93
  * Resolves the SQLite database path using the midnight-indexer configuration rules
9
94
  * @param {Object} env - Environment variables
@@ -18,17 +103,7 @@ function resolveSqlitePath(env, workingDir) {
18
103
  return envCnnUrl;
19
104
  }
20
105
 
21
- // Determine config file path using the configuration resolution rules
22
- let configPath;
23
- if (env.CONFIG_FILE) {
24
- configPath = path.isAbsolute(env.CONFIG_FILE)
25
- ? env.CONFIG_FILE
26
- : path.resolve(workingDir, env.CONFIG_FILE);
27
- } else {
28
- // Fall back to config.yaml in the current working directory
29
- configPath = path.join(workingDir, "config.yaml");
30
- }
31
-
106
+ const configPath = resolveConfigPath(env, workingDir);
32
107
  console.log(`Looking for config file at: ${configPath}`);
33
108
 
34
109
  // Check if config file exists
@@ -65,6 +140,24 @@ function resolveSqlitePath(env, workingDir) {
65
140
  }
66
141
  }
67
142
 
143
+ /**
144
+ * Resolves the SQLite database path with a fallback to the default location
145
+ * @param {Object} env - Environment variables
146
+ * @param {string} workingDir - The working directory where the indexer runs
147
+ * @returns {string} The resolved SQLite database path
148
+ */
149
+ function resolveSqlitePathWithFallback(env, workingDir) {
150
+ const sqlitePath = resolveSqlitePath(env, workingDir);
151
+ if (sqlitePath) {
152
+ return sqlitePath;
153
+ }
154
+
155
+ // Fallback to default indexer location: data/indexer.sqlite
156
+ const defaultPath = path.join(workingDir, "data", "indexer.sqlite");
157
+ console.log(`Using default SQLite path: ${defaultPath}`);
158
+ return defaultPath;
159
+ }
160
+
68
161
  /**
69
162
  * Handles the --clean flag by deleting the SQLite database file
70
163
  * @param {Object} env - Environment variables
@@ -73,12 +166,7 @@ function resolveSqlitePath(env, workingDir) {
73
166
  function handleCleanFlag(env, workingDir) {
74
167
  console.log("Processing --clean flag...");
75
168
 
76
- const sqlitePath = resolveSqlitePath(env, workingDir);
77
-
78
- if (!sqlitePath) {
79
- console.warn("Could not resolve SQLite database path. Skipping cleanup.");
80
- return;
81
- }
169
+ const sqlitePath = resolveSqlitePathWithFallback(env, workingDir);
82
170
 
83
171
  // Handle sqlite:// URLs and extract the file path
84
172
  let filePath = sqlitePath;
@@ -118,6 +206,9 @@ function runMidnightIndexer(env = process.env, args = []) {
118
206
  );
119
207
  const workingDir = path.join(__dirname, "indexer-standalone");
120
208
 
209
+ const configPath = resolveConfigPath(env, workingDir);
210
+ ensureConfigExists(configPath, env);
211
+
121
212
  // Check for --clean flag and handle it
122
213
  const cleanFlagIndex = args.indexOf("--clean");
123
214
  if (cleanFlagIndex !== -1) {