@tomasko/mb 0.0.0-stage → 0.1.1

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 (4) hide show
  1. package/README.md +52 -2
  2. package/bin/mb.js +27 -0
  3. package/install.js +117 -0
  4. package/package.json +40 -4
package/README.md CHANGED
@@ -1,3 +1,53 @@
1
- # Temporary Holding Version
1
+ # mb (npm)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ npm wrapper for [`mb`](../../README.md) — a MoonBit-native, uv-style toolchain
4
+ and package manager.
5
+
6
+ ```bash
7
+ pnpm install -g @tomasko/mb
8
+ mb --help
9
+ mb moon install 0.10.14
10
+ mb tool install bobzhang/zip
11
+ ```
12
+
13
+ ## How it works
14
+
15
+ The package itself contains only a small launcher. On install,
16
+ `install.js` downloads the prebuilt `mb` binary for the current platform from
17
+ GitHub Releases and writes it to `bin/mb`. The published `bin` entry
18
+ (`bin/mb.js`) then spawns it, forwarding arguments and standard IO.
19
+
20
+ Supported targets:
21
+
22
+ | Node `platform-arch` | Release asset |
23
+ | -------------------- | ------------------- |
24
+ | `linux-x64` | `mb-linux-x86_64` |
25
+ | `linux-arm64` | `mb-linux-aarch64` |
26
+ | `darwin-arm64` | `mb-darwin-aarch64` |
27
+
28
+ Intel macOS (`darwin-x64`) is not supported: the MoonBit toolchain no longer
29
+ ships a `darwin-x86_64` target, so no such build can be produced.
30
+
31
+ Assets are produced by `.github/workflows/release.yml` when a `v*` tag is
32
+ pushed.
33
+
34
+ ## Overrides
35
+
36
+ | Variable | Purpose |
37
+ | -------------------- | ------------------------------------------------ |
38
+ | `MB_REPO` | `owner/repo` to download from |
39
+ | `MB_VERSION` | release version to download |
40
+ | `MB_DOWNLOAD_BASE` | full base URL (mirror), e.g. `https://host/assets` |
41
+ | `MB_FORCE_DOWNLOAD` | re-download even if the binary is present |
42
+ | `MB_SKIP_DOWNLOAD` | skip the download entirely |
43
+
44
+ ## Publishing
45
+
46
+ From this directory:
47
+
48
+ ```bash
49
+ npm publish --access public
50
+ ```
51
+
52
+ Change `name`, `repository` and `homepage` in `package.json` first if you
53
+ publish under a different scope or repository.
package/bin/mb.js ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ // Thin launcher for the downloaded native `mb` binary.
3
+ "use strict";
4
+
5
+ const { spawnSync } = require("child_process");
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+
9
+ const ext = process.platform === "win32" ? ".exe" : "";
10
+ const binary = path.join(__dirname, "mb" + ext);
11
+
12
+ if (!fs.existsSync(binary)) {
13
+ console.error(
14
+ `mb: native binary not found at ${binary}\n` +
15
+ "mb: reinstall it with `npm rebuild mb` (or `npm install -g mb --force`)."
16
+ );
17
+ process.exit(1);
18
+ }
19
+
20
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
21
+
22
+ if (result.error) {
23
+ console.error(`mb: failed to launch ${binary}: ${result.error.message}`);
24
+ process.exit(1);
25
+ }
26
+
27
+ process.exit(typeof result.status === "number" ? result.status : 1);
package/install.js ADDED
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+ // Downloads the prebuilt `mb` binary for the current platform from GitHub
3
+ // Releases and drops it next to this package's launcher (`bin/mb.js`).
4
+ //
5
+ // Overridable for forks / private mirrors:
6
+ // MB_REPO owner/repo (default: parsed from package.json)
7
+ // MB_VERSION release version (default: package.json version)
8
+ // MB_DOWNLOAD_BASE full base URL (overrides MB_REPO/MB_VERSION)
9
+ // MB_SKIP_DOWNLOAD set to skip fetching
10
+ "use strict";
11
+
12
+ const fs = require("fs");
13
+ const path = require("path");
14
+ const https = require("https");
15
+ const http = require("http");
16
+
17
+ const pkg = require("./package.json");
18
+
19
+ const TARGETS = {
20
+ "linux-x64": "linux-x86_64",
21
+ "linux-arm64": "linux-aarch64",
22
+ "darwin-arm64": "darwin-aarch64",
23
+ };
24
+
25
+ function repoSlug(repo) {
26
+ if (!repo) return null;
27
+ const url = typeof repo === "string" ? repo : repo.url || "";
28
+ const m = url.match(/github\.com[/:]([^/]+)\/([^/.]+)/);
29
+ return m ? `${m[1]}/${m[2]}` : null;
30
+ }
31
+
32
+ function target() {
33
+ return TARGETS[`${process.platform}-${process.arch}`];
34
+ }
35
+
36
+ function downloadUrl(targetName) {
37
+ if (process.env.MB_DOWNLOAD_BASE) {
38
+ return `${process.env.MB_DOWNLOAD_BASE.replace(/\/$/, "")}/mb-${targetName}`;
39
+ }
40
+ const repo = process.env.MB_REPO || repoSlug(pkg.repository) || "tomasky/mb";
41
+ const version = process.env.MB_VERSION || pkg.version;
42
+ return `https://github.com/${repo}/releases/download/v${version}/mb-${targetName}`;
43
+ }
44
+
45
+ function fetch(url, redirects) {
46
+ return new Promise((resolve, reject) => {
47
+ if (redirects > 10) return reject(new Error("too many redirects"));
48
+ const client = url.startsWith("http:") ? http : https;
49
+ const req = client.get(
50
+ url,
51
+ { headers: { "user-agent": `mb-npm/${pkg.version}` } },
52
+ (res) => {
53
+ const { statusCode, headers } = res;
54
+ if (statusCode >= 300 && statusCode < 400 && headers.location) {
55
+ res.resume();
56
+ const next = new URL(headers.location, url).toString();
57
+ resolve(fetch(next, (redirects || 0) + 1));
58
+ return;
59
+ }
60
+ if (statusCode !== 200) {
61
+ res.resume();
62
+ reject(new Error(`GET ${url} -> HTTP ${statusCode}`));
63
+ return;
64
+ }
65
+ resolve(res);
66
+ }
67
+ );
68
+ req.on("error", reject);
69
+ });
70
+ }
71
+
72
+ async function main() {
73
+ if (process.env.MB_SKIP_DOWNLOAD) {
74
+ console.log("mb: MB_SKIP_DOWNLOAD set, skipping binary download");
75
+ return;
76
+ }
77
+
78
+ const targetName = target();
79
+ if (!targetName) {
80
+ throw new Error(
81
+ `unsupported platform ${process.platform}-${process.arch}; mb ` +
82
+ `supports linux-x64, linux-arm64 and darwin-arm64 (the MoonBit ` +
83
+ `toolchain no longer ships a darwin-x64 target)`
84
+ );
85
+ }
86
+
87
+ const ext = process.platform === "win32" ? ".exe" : "";
88
+ const dest = path.join(__dirname, "bin", "mb" + ext);
89
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
90
+
91
+ if (fs.existsSync(dest) && !process.env.MB_FORCE_DOWNLOAD) {
92
+ console.log(`mb: ${dest} already present, skipping download`);
93
+ return;
94
+ }
95
+
96
+ const url = downloadUrl(targetName);
97
+ console.log(`mb: downloading ${url}`);
98
+ const res = await fetch(url, 0);
99
+ await new Promise((resolve, reject) => {
100
+ const out = fs.createWriteStream(dest);
101
+ res.pipe(out);
102
+ out.on("finish", () => out.close(resolve));
103
+ out.on("error", reject);
104
+ res.on("error", reject);
105
+ });
106
+ fs.chmodSync(dest, 0o755);
107
+ console.log(`mb: installed ${dest}`);
108
+ }
109
+
110
+ main().catch((err) => {
111
+ console.error(`mb: failed to install the native binary: ${err.message}`);
112
+ console.error(
113
+ "mb: set MB_DOWNLOAD_BASE (or MB_REPO/MB_VERSION) to point at a mirror, " +
114
+ "or set MB_SKIP_DOWNLOAD=1 to skip."
115
+ );
116
+ process.exit(1);
117
+ });
package/package.json CHANGED
@@ -1,6 +1,42 @@
1
1
  {
2
2
  "name": "@tomasko/mb",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "A MoonBit-native, uv-style toolchain and package manager: manage MoonBit toolchains and install tools from mooncakes.io.",
5
+ "license": "Apache-2.0",
6
+ "bin": {
7
+ "mb": "bin/mb.js"
8
+ },
9
+ "scripts": {
10
+ "postinstall": "node install.js"
11
+ },
12
+ "files": [
13
+ "bin/mb.js",
14
+ "install.js",
15
+ "README.md"
16
+ ],
17
+ "engines": {
18
+ "node": ">=20"
19
+ },
20
+ "os": [
21
+ "darwin",
22
+ "linux"
23
+ ],
24
+ "cpu": [
25
+ "x64",
26
+ "arm64"
27
+ ],
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/tomasky/mb.git"
31
+ },
32
+ "homepage": "https://github.com/tomasky/mb",
33
+ "bugs": "https://github.com/tomasky/mb/issues",
34
+ "keywords": [
35
+ "moonbit",
36
+ "mooncakes",
37
+ "toolchain",
38
+ "package-manager",
39
+ "uv"
40
+ ],
41
+ "preferGlobal": true
42
+ }