graphify-sf 0.3.7 → 0.3.9

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/install.js CHANGED
@@ -1,8 +1,56 @@
1
1
  "use strict";
2
2
 
3
- const { download } = require("./lib/download");
3
+ // postinstall hook.
4
+ //
5
+ // As of 0.3.9 the prebuilt binary normally arrives WITH `npm install`, shipped
6
+ // inside a platform-specific scoped subpackage (@graphify-sf/cli-<plat>-<arch>)
7
+ // declared in optionalDependencies. npm installs only the subpackage matching
8
+ // the host os/cpu, so on a supported platform the binary is already present and
9
+ // this hook makes ZERO network requests.
10
+ //
11
+ // Resolution order (see lib/download.js ensureBinary):
12
+ // 1. GRAPHIFY_BIN env override
13
+ // 2. the installed platform subpackage <-- 0.3.9 happy path, no network
14
+ // 3. a previously-downloaded binary in bin/
15
+ // 4. download from GitHub Releases <-- fallback only
16
+ //
17
+ // A failed download in step 4 MUST NOT abort the consumer's `npm install`
18
+ // (graphify-sf is an optional second engine for its consumers). So this hook
19
+ // always exits 0: if no binary resolves and the fallback download fails, we
20
+ // print actionable remediation and still exit 0; the binary is fetched lazily
21
+ // on first run instead.
4
22
 
5
- download().catch((err) => {
6
- process.stderr.write(`graphify-sf postinstall failed: ${err.message}\n`);
7
- process.exit(1);
8
- });
23
+ const { envBinary, subpackageBinary, download } = require("./lib/download");
24
+
25
+ async function main() {
26
+ // If a binary already resolves (env override or the platform subpackage),
27
+ // there is nothing to do — and crucially, no network request.
28
+ if (envBinary() || subpackageBinary()) {
29
+ process.exit(0);
30
+ }
31
+
32
+ // No prebuilt binary available for this platform (unsupported platform,
33
+ // --no-optional, or a registry that doesn't carry the scoped subpackages).
34
+ // Try the GitHub Releases fallback, but never fail the install.
35
+ try {
36
+ await download();
37
+ process.exit(0);
38
+ } catch (err) {
39
+ process.stderr.write(
40
+ `\ngraphify-sf: no prebuilt binary for this platform and the fallback download failed.\n` +
41
+ ` Reason: ${err.message}\n` +
42
+ `\n` +
43
+ ` This is non-fatal — installation will continue. The binary will be\n` +
44
+ ` fetched automatically the first time you run graphify-sf, provided\n` +
45
+ ` network access is available then.\n` +
46
+ `\n` +
47
+ ` If your network blocks GitHub Releases, use one of these instead:\n` +
48
+ ` • Install the Python package directly: pipx install graphify-sf\n` +
49
+ ` • Point at an existing binary: export GRAPHIFY_BIN=/path/to/graphify-sf\n` +
50
+ `\n`
51
+ );
52
+ process.exit(0);
53
+ }
54
+ }
55
+
56
+ main();
package/lib/download.js CHANGED
@@ -120,12 +120,107 @@ async function download() {
120
120
  process.stdout.write(`graphify-sf: installed to ${dest}\n`);
121
121
  }
122
122
 
123
+ // Resolve a user-supplied binary path from the GRAPHIFY_BIN environment
124
+ // variable. This is the highest-priority resolution and is the documented
125
+ // escape hatch for locked-down networks where the GitHub download is blocked.
126
+ // Returns the path if it points at an existing file, otherwise null.
127
+ function envBinary() {
128
+ const p = process.env.GRAPHIFY_BIN;
129
+ if (p && fs.existsSync(p)) {
130
+ return p;
131
+ }
132
+ return null;
133
+ }
134
+
135
+ // Name of the platform-specific scoped subpackage that ships the prebuilt
136
+ // binary for the current platform/arch, e.g. "@graphify-sf/cli-linux-x64".
137
+ // Returns null on unsupported platforms.
138
+ function subpackageName() {
139
+ const plat = process.platform;
140
+ const arch = process.arch;
141
+ const supported = SUPPORTED[plat];
142
+ if (!supported || !supported.includes(arch)) {
143
+ return null;
144
+ }
145
+ return `@graphify-sf/cli-${plat}-${arch}`;
146
+ }
147
+
148
+ // Resolve the binary from an installed platform subpackage (the 0.3.9 happy
149
+ // path — the binary arrives with `npm install` via optionalDependencies, no
150
+ // network). Returns the absolute path, or null if the subpackage is not
151
+ // installed (unsupported platform, --no-optional, or a registry mirror that
152
+ // does not carry the scoped subpackages).
153
+ function subpackageBinary() {
154
+ const name = subpackageName();
155
+ if (!name) return null;
156
+ const binName = process.platform === "win32" ? "graphify-sf.exe" : "graphify-sf";
157
+
158
+ // Build a robust set of resolution roots. In a normal install the subpackage
159
+ // is a peer in the consumer's node_modules and resolves from this module's
160
+ // own location; but with non-hoisted / nested layouts (or when invoked from a
161
+ // different cwd, e.g. tests) it may live elsewhere. Searching from this
162
+ // module, the package root, and the current working directory covers npm,
163
+ // pnpm and yarn layouts.
164
+ const searchPaths = [__dirname, path.join(__dirname, ".."), process.cwd()];
165
+
166
+ let resolved = null;
167
+ try {
168
+ resolved = require.resolve(`${name}/${binName}`, { paths: searchPaths });
169
+ } catch {
170
+ // Subpackage not installed — fall through to other resolution strategies.
171
+ return null;
172
+ }
173
+
174
+ if (resolved && fs.existsSync(resolved)) {
175
+ // Defensive: npm tarballs preserve mode, but ensure executable on Unix.
176
+ if (process.platform !== "win32") {
177
+ try {
178
+ fs.accessSync(resolved, fs.constants.X_OK);
179
+ } catch {
180
+ try {
181
+ fs.chmodSync(resolved, 0o755);
182
+ } catch {
183
+ /* best-effort; resolution still returned below */
184
+ }
185
+ }
186
+ }
187
+ return resolved;
188
+ }
189
+ return null;
190
+ }
191
+
123
192
  async function ensureBinary() {
193
+ // 1. Explicit override always wins.
194
+ const fromEnv = envBinary();
195
+ if (fromEnv) {
196
+ return fromEnv;
197
+ }
198
+
199
+ // 2. Prebuilt binary shipped in the platform subpackage (0.3.9 happy path,
200
+ // no network).
201
+ const fromSubpkg = subpackageBinary();
202
+ if (fromSubpkg) {
203
+ return fromSubpkg;
204
+ }
205
+
206
+ // 3. Already-downloaded binary in the package's bin/ dir (legacy cache).
124
207
  const dest = binaryPath();
125
- if (!fs.existsSync(dest)) {
126
- await download();
208
+ if (fs.existsSync(dest)) {
209
+ return dest;
127
210
  }
211
+
212
+ // 4. Last resort: lazily download from GitHub Releases on first use.
213
+ await download();
128
214
  return dest;
129
215
  }
130
216
 
131
- module.exports = { assetName, binaryPath, binDir, download, ensureBinary };
217
+ module.exports = {
218
+ assetName,
219
+ binaryPath,
220
+ binDir,
221
+ download,
222
+ ensureBinary,
223
+ envBinary,
224
+ subpackageName,
225
+ subpackageBinary,
226
+ };
package/package.json CHANGED
@@ -1,13 +1,21 @@
1
1
  {
2
2
  "name": "graphify-sf",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "description": "Turn any Salesforce SFDX project into a queryable knowledge graph — no Python required.",
5
5
  "bin": {
6
6
  "graphify-sf": "bin/graphify-sf.js"
7
7
  },
8
8
  "main": "index.js",
9
9
  "scripts": {
10
- "postinstall": "node install.js"
10
+ "postinstall": "node install.js",
11
+ "test": "node --test"
12
+ },
13
+ "optionalDependencies": {
14
+ "@graphify-sf/cli-linux-x64": "0.3.9",
15
+ "@graphify-sf/cli-linux-arm64": "0.3.9",
16
+ "@graphify-sf/cli-darwin-x64": "0.3.9",
17
+ "@graphify-sf/cli-darwin-arm64": "0.3.9",
18
+ "@graphify-sf/cli-win32-x64": "0.3.9"
11
19
  },
12
20
  "files": [
13
21
  "bin/",