@goliapkg/smix-cli 2.1.0

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/bin/launch.mjs ADDED
@@ -0,0 +1,71 @@
1
+ // Shared launcher for the two executables this package installs.
2
+ //
3
+ // Both are ordinary native binaries: the npm package is a delivery
4
+ // mechanism, not a wrapper. So this hands over argv untouched, inherits
5
+ // all three streams, and exits with whatever the binary exited with.
6
+ //
7
+ // Inheriting stdio is not a detail — `smix-mcp` speaks MCP over stdin and
8
+ // stdout, and anything that buffers, re-encodes, or writes a line of its
9
+ // own into those streams corrupts the protocol.
10
+ import { spawnSync } from 'node:child_process'
11
+ import { createRequire } from 'node:module'
12
+ import { dirname } from 'node:path'
13
+ import process from 'node:process'
14
+
15
+ import { binaryPath, resolvePackage } from '../dist/resolve.js'
16
+
17
+ /** glibc vs musl, or null when the runtime will not say. */
18
+ function detectLibc() {
19
+ // Node reports the libc family in process.report on Linux. On other
20
+ // platforms the question does not arise, and a wrong guess here would
21
+ // refuse an install that was fine.
22
+ if (process.platform !== 'linux') return null
23
+ try {
24
+ const report = process.report?.getReport()
25
+ const header = typeof report === 'object' && report !== null ? report.header : undefined
26
+ const glibc = header?.glibcVersionRuntime
27
+ return typeof glibc === 'string' && glibc !== '' ? 'glibc' : 'musl'
28
+ } catch {
29
+ return null
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Run `exe` with this process's arguments and exit with its status.
35
+ *
36
+ * @param {'smix' | 'smix-mcp'} exe
37
+ */
38
+ export function launch(exe) {
39
+ const pkg = resolvePackage(process.platform, process.arch, detectLibc())
40
+
41
+ let binary
42
+ try {
43
+ // Resolve the package's manifest rather than the binary itself:
44
+ // resolution of an extensionless file is not something a package
45
+ // without an `exports` map is obliged to support, and the manifest
46
+ // always resolves.
47
+ const require = createRequire(import.meta.url)
48
+ binary = binaryPath(dirname(require.resolve(`${pkg}/package.json`)), exe)
49
+ } catch {
50
+ // An optional dependency that did not install is the ordinary way this
51
+ // fails, and `--no-optional` or an offline install is how it happens.
52
+ process.stderr.write(
53
+ `smix: ${pkg} is not installed, so there is no ${exe} binary for this machine.\n` +
54
+ `Reinstall without --no-optional, or build from source: cargo install smix-cli --locked\n`,
55
+ )
56
+ process.exit(127)
57
+ }
58
+
59
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit' })
60
+ if (result.error !== undefined) {
61
+ process.stderr.write(`smix: could not run ${binary}: ${result.error.message}\n`)
62
+ process.exit(126)
63
+ }
64
+ // A binary killed by a signal has no exit code. Reporting 0 there would
65
+ // tell a script the run succeeded.
66
+ if (result.status === null) {
67
+ process.stderr.write(`smix: ${exe} was killed by ${result.signal}\n`)
68
+ process.exit(128)
69
+ }
70
+ process.exit(result.status)
71
+ }
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { launch } from "./launch.mjs"
3
+
4
+ launch("smix-mcp")
package/bin/smix.mjs ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { launch } from "./launch.mjs"
3
+
4
+ launch("smix")
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Which prebuilt package carries the binaries for the machine running this.
3
+ *
4
+ * smix is a Rust workspace, and `cargo install smix-cli` compiles 27 crates
5
+ * and needs a Rust toolchain — a wall in front of someone whose app is
6
+ * Swift or Kotlin and whose machine has never had rustup on it. This
7
+ * package exists so the binaries arrive prebuilt instead.
8
+ */
9
+ /** A target CI builds binaries for, and the npm package they ship in. */
10
+ export interface Target {
11
+ /** Rust target triple, as passed to `cargo build --target`. */
12
+ readonly triple: string;
13
+ /** `process.platform` this triple serves. */
14
+ readonly platform: string;
15
+ /** `process.arch` this triple serves. */
16
+ readonly arch: string;
17
+ /** npm package suffix — the part after `@goliapkg/smix-cli-`. */
18
+ readonly suffix: string;
19
+ }
20
+ /**
21
+ * The build matrix, in one place.
22
+ *
23
+ * `.github/workflows/ci.yml`'s `cli-prebuild` job builds exactly these
24
+ * triples, and a test asserts this table against that list. Two copies of a
25
+ * platform list drift, and the drift shows up as a package that resolves to
26
+ * a subpackage nobody published.
27
+ */
28
+ export declare const TARGETS: readonly Target[];
29
+ /**
30
+ * The platform package for `platform`/`arch`, or throw saying why not.
31
+ *
32
+ * Never guesses. A binary for the wrong architecture installs cleanly and
33
+ * then fails at exec with a loader error that names neither smix nor the
34
+ * mismatch, which is a worse place to find out than here.
35
+ */
36
+ export declare function resolvePackage(platform: string, arch: string, libc: string | null): string;
37
+ /** Specifier for one executable inside a platform package. */
38
+ export declare function binaryPath(pkg: string, exe: 'smix' | 'smix-mcp'): string;
39
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yEAAyE;AACzE,MAAM,WAAW,MAAM;IACrB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,SAAS,MAAM,EAmBpC,CAAA;AAKD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,MAAM,CAeR;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAExE"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Which prebuilt package carries the binaries for the machine running this.
3
+ *
4
+ * smix is a Rust workspace, and `cargo install smix-cli` compiles 27 crates
5
+ * and needs a Rust toolchain — a wall in front of someone whose app is
6
+ * Swift or Kotlin and whose machine has never had rustup on it. This
7
+ * package exists so the binaries arrive prebuilt instead.
8
+ */
9
+ /**
10
+ * The build matrix, in one place.
11
+ *
12
+ * `.github/workflows/ci.yml`'s `cli-prebuild` job builds exactly these
13
+ * triples, and a test asserts this table against that list. Two copies of a
14
+ * platform list drift, and the drift shows up as a package that resolves to
15
+ * a subpackage nobody published.
16
+ */
17
+ export const TARGETS = [
18
+ {
19
+ triple: 'aarch64-apple-darwin',
20
+ platform: 'darwin',
21
+ arch: 'arm64',
22
+ suffix: 'darwin-arm64',
23
+ },
24
+ {
25
+ triple: 'x86_64-apple-darwin',
26
+ platform: 'darwin',
27
+ arch: 'x64',
28
+ suffix: 'darwin-x64',
29
+ },
30
+ {
31
+ triple: 'x86_64-unknown-linux-gnu',
32
+ platform: 'linux',
33
+ arch: 'x64',
34
+ suffix: 'linux-x64-gnu',
35
+ },
36
+ ];
37
+ /** What to tell someone whose machine we have no binary for. */
38
+ const FALLBACK = 'build from source instead: cargo install smix-cli --locked';
39
+ /**
40
+ * The platform package for `platform`/`arch`, or throw saying why not.
41
+ *
42
+ * Never guesses. A binary for the wrong architecture installs cleanly and
43
+ * then fails at exec with a loader error that names neither smix nor the
44
+ * mismatch, which is a worse place to find out than here.
45
+ */
46
+ export function resolvePackage(platform, arch, libc) {
47
+ if (platform === 'linux' && libc !== null && libc !== 'glibc') {
48
+ throw new Error(`smix has no prebuilt binary for linux/${arch} with ${libc} — the published ` +
49
+ `Linux build links against glibc and will not load. ${FALLBACK}`);
50
+ }
51
+ const hit = TARGETS.find((t) => t.platform === platform && t.arch === arch);
52
+ if (hit === undefined) {
53
+ throw new Error(`smix has no prebuilt binary for ${platform}/${arch}. Built targets: ` +
54
+ `${TARGETS.map((t) => `${t.platform}/${t.arch}`).join(', ')}. ${FALLBACK}`);
55
+ }
56
+ return `@goliapkg/smix-cli-${hit.suffix}`;
57
+ }
58
+ /** Specifier for one executable inside a platform package. */
59
+ export function binaryPath(pkg, exe) {
60
+ return `${pkg}/${exe}`;
61
+ }
62
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC;QACE,MAAM,EAAE,sBAAsB;QAC9B,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,cAAc;KACvB;IACD;QACE,MAAM,EAAE,qBAAqB;QAC7B,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,YAAY;KACrB;IACD;QACE,MAAM,EAAE,0BAA0B;QAClC,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,eAAe;KACxB;CACF,CAAA;AAED,gEAAgE;AAChE,MAAM,QAAQ,GAAG,4DAA4D,CAAA;AAE7E;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,IAAY,EACZ,IAAmB;IAEnB,IAAI,QAAQ,KAAK,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CACb,yCAAyC,IAAI,SAAS,IAAI,mBAAmB;YAC3E,sDAAsD,QAAQ,EAAE,CACnE,CAAA;IACH,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;IAC3E,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,mCAAmC,QAAQ,IAAI,IAAI,mBAAmB;YACpE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAC7E,CAAA;IACH,CAAC;IACD,OAAO,sBAAsB,GAAG,CAAC,MAAM,EAAE,CAAA;AAC3C,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,GAAwB;IAC9D,OAAO,GAAG,GAAG,IAAI,GAAG,EAAE,CAAA;AACxB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@goliapkg/smix-cli",
3
+ "version": "2.1.0",
4
+ "description": "The smix CLI and MCP server as prebuilt binaries — no Rust toolchain required.",
5
+ "type": "module",
6
+ "license": "Apache-2.0 OR MIT",
7
+ "homepage": "https://github.com/goliajp/smix",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/goliajp/smix.git"
11
+ },
12
+ "bin": {
13
+ "smix": "bin/smix.mjs",
14
+ "smix-mcp": "bin/smix-mcp.mjs"
15
+ },
16
+ "files": [
17
+ "bin",
18
+ "dist"
19
+ ],
20
+ "optionalDependencies": {
21
+ "@goliapkg/smix-cli-darwin-arm64": "2.1.0",
22
+ "@goliapkg/smix-cli-darwin-x64": "2.1.0",
23
+ "@goliapkg/smix-cli-linux-x64-gnu": "2.1.0"
24
+ },
25
+ "devDependencies": {
26
+ "typescript": "^5",
27
+ "vitest": "^3"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "test": "vitest run"
32
+ }
33
+ }