@cparra/apex-reflection 2.22.0-dev.20251224082625 → 2.22.0-dev.20251224084554

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cparra/apex-reflection",
3
- "version": "2.22.0-dev.20251224082625",
3
+ "version": "2.22.0-dev.20251224084554",
4
4
  "description": "Provides tools for reflecting Apex code, the language used in Salesforce development.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -11,6 +11,7 @@
11
11
  "dev:build:native:host": "node scripts/build-natives.js --host",
12
12
  "dev:chmod:native:host": "node scripts/dev-chmod-native-host.js",
13
13
  "dev:version:prerelease": "node scripts/dev-bump-version-prerelease.js",
14
+ "dev:github:release": "node scripts/dev-github-release.js",
14
15
  "dev:publish": "node scripts/dev-publish.js",
15
16
  "test": "jest"
16
17
  },
@@ -17,6 +17,10 @@
17
17
  * v<version> (version taken from this package's package.json)
18
18
  *
19
19
  * This keeps the npm package small by downloading only the needed binary at install time.
20
+ *
21
+ * Note:
22
+ * - Some GitHub UI surfaces show a simplified download URL even when the asset name includes the arch.
23
+ * - To make installs resilient (especially for dev releases), we try multiple possible asset names.
20
24
  */
21
25
 
22
26
  const https = require("https");
@@ -40,35 +44,48 @@ function main() {
40
44
  }
41
45
 
42
46
  const target = resolveTarget(process.platform, process.arch);
43
- const assetName = `apex-reflection-${target.releasePlatform}-${target.releaseArch}${target.exeExt}`;
44
47
  const tag = `v${version}`;
45
48
 
46
- const downloadUrl = `https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${tag}/${assetName}`;
47
-
48
- const outDir = path.join(__dirname, "..", "dist", "native", target.folderName);
49
+ const outDir = path.join(
50
+ __dirname,
51
+ "..",
52
+ "dist",
53
+ "native",
54
+ target.folderName,
55
+ );
49
56
  const outPath = path.join(outDir, target.binaryFileName);
50
57
 
51
58
  fs.mkdirSync(outDir, { recursive: true });
52
59
 
53
- return downloadFile(downloadUrl, outPath)
54
- .then(() => {
60
+ const candidateAssetNames = buildCandidateAssetNames(target);
61
+
62
+ return downloadFirstAvailableAsset(tag, candidateAssetNames, outPath)
63
+ .then(({ assetName }) => {
55
64
  if (process.platform !== "win32") {
56
65
  try {
57
66
  fs.chmodSync(outPath, 0o755);
58
67
  } catch (e) {
59
68
  console.warn(
60
- `[apex-reflection] postinstall: could not chmod +x ${outPath}: ${stringifyErr(e)}`
69
+ `[apex-reflection] postinstall: could not chmod +x ${outPath}: ${stringifyErr(e)}`,
61
70
  );
62
71
  }
63
72
  }
64
73
 
65
- console.log(`[apex-reflection] postinstall: native binary installed at: ${outPath}`);
74
+ console.log(
75
+ `[apex-reflection] postinstall: native binary installed at: ${outPath} (asset: ${assetName})`,
76
+ );
66
77
  })
67
78
  .catch((err) => {
68
- console.error("[apex-reflection] postinstall: failed to install native binary.");
79
+ console.error(
80
+ "[apex-reflection] postinstall: failed to install native binary.",
81
+ );
69
82
  console.error(`[apex-reflection] postinstall: ${stringifyErr(err)}`);
70
- console.error("[apex-reflection] postinstall: Verify the release assets here:");
71
- console.error(`https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/tag/${tag}`);
83
+ console.error(
84
+ "[apex-reflection] postinstall: Verify the release assets here:",
85
+ );
86
+ console.error(
87
+ `https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/tag/${tag}`,
88
+ );
72
89
  process.exit(1);
73
90
  });
74
91
  }
@@ -117,6 +134,66 @@ function resolveTarget(nodePlatform, nodeArch) {
117
134
  };
118
135
  }
119
136
 
137
+ function buildCandidateAssetNames(target) {
138
+ // Primary convention (expected):
139
+ // apex-reflection-<platform>-<arch>[.exe]
140
+ const primary = `apex-reflection-${target.releasePlatform}-${target.releaseArch}${target.exeExt}`;
141
+
142
+ // Fallbacks (mainly for dev flows / edge cases):
143
+ // - Some dev releases might end up with an unsuffixed asset name.
144
+ // - Additionally, for non-windows platforms, try without extension explicitly.
145
+ const fallbacks = [];
146
+
147
+ // Unsuffixed name (no arch/platform)
148
+ // - For windows, prefer .exe and then without extension (just in case).
149
+ if (target.releasePlatform === "windows") {
150
+ fallbacks.push("apex-reflection.exe");
151
+ fallbacks.push("apex-reflection");
152
+ } else {
153
+ fallbacks.push("apex-reflection");
154
+ }
155
+
156
+ // De-dup while preserving order
157
+ const seen = new Set();
158
+ const all = [primary, ...fallbacks].filter((name) => {
159
+ if (seen.has(name)) return false;
160
+ seen.add(name);
161
+ return true;
162
+ });
163
+
164
+ return all;
165
+ }
166
+
167
+ function downloadFirstAvailableAsset(tag, assetNames, destPath) {
168
+ const base = `https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${tag}/`;
169
+
170
+ let lastErr = null;
171
+
172
+ // Try sequentially until one downloads successfully
173
+ return assetNames
174
+ .reduce(
175
+ (p, assetName) => {
176
+ return p.catch((_) => {
177
+ const url = `${base}${assetName}`;
178
+ process.stdout.write(
179
+ `[apex-reflection] postinstall: trying ${url}\n`,
180
+ );
181
+ return downloadFile(url, destPath).then(() => ({ assetName }));
182
+ });
183
+ },
184
+ Promise.reject(new Error("No candidate asset attempted yet.")),
185
+ )
186
+ .catch((err) => {
187
+ lastErr = err;
188
+ const tried = assetNames.map((n) => `${base}${n}`).join("\n");
189
+ const msg =
190
+ `Unable to download any matching binary asset for ${process.platform}/${process.arch}.\n` +
191
+ `Tried:\n${tried}\n` +
192
+ `Last error: ${stringifyErr(lastErr)}`;
193
+ throw new Error(msg);
194
+ });
195
+ }
196
+
120
197
  function downloadFile(url, destPath) {
121
198
  return new Promise((resolve, reject) => {
122
199
  const tmpPath = `${destPath}.tmp`;
@@ -131,13 +208,16 @@ function downloadFile(url, destPath) {
131
208
  if (response.statusCode === 301 || response.statusCode === 302) {
132
209
  const next = response.headers.location;
133
210
  response.resume();
134
- if (!next) return reject(new Error(`Redirect with no location for ${url}`));
211
+ if (!next)
212
+ return reject(new Error(`Redirect with no location for ${url}`));
135
213
  return downloadFile(next, destPath).then(resolve, reject);
136
214
  }
137
215
 
138
216
  if (response.statusCode !== 200) {
139
217
  response.resume();
140
- return reject(new Error(`HTTP ${response.statusCode} while downloading ${url}`));
218
+ return reject(
219
+ new Error(`HTTP ${response.statusCode} while downloading ${url}`),
220
+ );
141
221
  }
142
222
 
143
223
  const totalSize = Number(response.headers["content-length"] || 0);
@@ -147,7 +227,9 @@ function downloadFile(url, destPath) {
147
227
  downloaded += chunk.length;
148
228
  if (totalSize > 0) {
149
229
  const pct = Math.floor((downloaded / totalSize) * 100);
150
- process.stdout.write(`\r[apex-reflection] postinstall: downloading... ${pct}%`);
230
+ process.stdout.write(
231
+ `\r[apex-reflection] postinstall: downloading... ${pct}%`,
232
+ );
151
233
  }
152
234
  });
153
235