@symbiosis-lab/moss 0.12.1 → 0.15.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/README.md CHANGED
@@ -1,12 +1,6 @@
1
1
  # @symbiosis-lab/moss
2
2
 
3
- moss on your PATH. This package downloads the official [moss](https://@symbiosis-lab/moss.com)
4
- CLI binary from [moss-releases](https://github.com/Symbiosis-Lab/moss-releases)
5
- and exposes it as the `moss` command.
6
-
7
- > **Publishing note:** the package is currently marked `"private": true` in
8
- > `package.json` so it cannot ship by accident. Flip that (remove the field)
9
- > at publish time — `publishConfig` is already set up.
3
+ moss on your PATH. This package downloads the open [moss-cli](https://github.com/Symbiosis-Lab/moss/tree/develop/crates/moss-cli) binary and exposes it as the `moss` command.
10
4
 
11
5
  ## Install
12
6
 
@@ -15,12 +9,9 @@ npm install -g @symbiosis-lab/moss
15
9
  moss --version
16
10
  ```
17
11
 
18
- The binary is fetched at install time (postinstall). With `--ignore-scripts`,
19
- or if the download failed (e.g. offline), the first `moss` invocation fetches
20
- it lazily instead.
12
+ The binary is fetched at install time (postinstall). With `--ignore-scripts`, or if the download failed (e.g. offline), the first `moss` invocation fetches it lazily instead.
21
13
 
22
- Supported platforms: macOS (Intel and Apple Silicon, one universal binary)
23
- and Linux x86_64.
14
+ Supported platforms: macOS (Intel and Apple Silicon, one universal binary) and Linux x86_64. The binary has no window system in its dependency graph, so it starts on a headless Linux server or inside a container with no desktop libraries to install first.
24
15
 
25
16
  ## Use
26
17
 
@@ -30,29 +21,15 @@ moss build ~/Sites/my-site
30
21
 
31
22
  All arguments pass straight through to the moss binary; see `moss --help`.
32
23
 
33
- ## Linux runtime dependency (temporary)
34
-
35
- The current Linux binary links against WebKitGTK even for headless CLI verbs.
36
- If `moss` fails with `error while loading shared libraries`, install:
37
-
38
- ```sh
39
- sudo apt install libwebkit2gtk-4.1-0
40
- ```
41
-
42
- This requirement is temporary — a moss CLI build without the WebKitGTK
43
- linkage is planned.
24
+ `moss preview` and `moss edit` need a window, which this binary doesn't have: they hand off to [moss desktop](https://mosspub.com) if it's installed, or print a one-line hint if it isn't. On macOS, `moss desktop install` fetches and installs it for you (see `moss desktop install --help`); it always asks before downloading and never runs unattended (no terminal attached, as in CI, is treated as declining). moss desktop isn't packaged for Linux or Windows yet, so `moss desktop install` there just prints where to get it.
44
25
 
45
26
  ## Checksums
46
27
 
47
- Downloads are verified against the `SHA256SUMS` file published with each
48
- release. Releases that predate checksum publishing install with a warning
49
- instead of verification.
28
+ Downloads are verified against the `SHA256SUMS` file published with each release. Releases that predate checksum publishing install with a warning instead of verification.
50
29
 
51
30
  ## Versioning and overrides
52
31
 
53
- The wrapper downloads the moss version matching its own package version;
54
- they are released in lockstep. `MOSS_VERSION_OVERRIDE=v0.11.1` forces a
55
- specific release (ops/testing escape hatch).
32
+ The wrapper downloads the moss version matching its own package version; they are released in lockstep. `MOSS_VERSION_OVERRIDE=v0.11.1` forces a specific release (ops/testing escape hatch).
56
33
 
57
34
  ## Controlling the download
58
35
 
@@ -62,18 +39,10 @@ specific release (ops/testing escape hatch).
62
39
  | `MOSS_BINARY_PATH=/path/to/moss` | Run that binary instead of the vendored one, and skip the download entirely. |
63
40
  | `MOSS_FORCE_BINARY_DOWNLOAD=1` | Download even where the wrapper would otherwise skip. |
64
41
 
65
- Each also reads from `.npmrc` under its lowercased name (`moss_skip_binary_download=true`),
66
- because npm passes config keys to lifecycle scripts as `npm_config_*`.
42
+ Each also reads from `.npmrc` under its lowercased name (`moss_skip_binary_download=true`), because npm passes config keys to lifecycle scripts as `npm_config_*`.
67
43
 
68
- **Inside the moss repo the download is skipped automatically.** A checkout is
69
- not an install: `packages/moss` sits in the workspace rather than under
70
- `node_modules`, so `pnpm install` at the repo root would otherwise pull a
71
- release binary that no moss developer wants — they build from source. Point
72
- `MOSS_BINARY_PATH` at `src-tauri/target/release/moss` to exercise the wrapper
73
- against your own build.
44
+ **Inside the moss repo the download is skipped automatically.** A checkout is not an install: `packages/moss` sits in the workspace rather than under `node_modules`, so `pnpm install` at the repo root would otherwise pull a release binary that no moss developer wants — they build from source. Point `MOSS_BINARY_PATH` at `target/release/moss-cli` (`cargo build --release -p moss-cli`) to exercise the wrapper against your own build.
74
45
 
75
46
  ## License
76
47
 
77
- The wrapper code in this package is MIT (see LICENSE). The moss binary it
78
- downloads is a separate work, distributed under its own terms via
79
- [moss-releases](https://github.com/Symbiosis-Lab/moss-releases).
48
+ The wrapper code in this package is MIT (see LICENSE). The moss binary it downloads is a separate work, distributed under its own terms via [moss](https://github.com/Symbiosis-Lab/moss).
package/bin/moss.js CHANGED
@@ -24,25 +24,10 @@ async function main() {
24
24
  await fetchBinary();
25
25
  }
26
26
 
27
- // stderr is piped so a loader failure can be recognized, then replayed
28
- // verbatim. stdin/stdout stay inherited for interactive use.
29
- const result = spawnSync(binary, process.argv.slice(2), {
30
- stdio: ['inherit', 'inherit', 'pipe'],
31
- });
32
-
33
- const stderr = result.stderr ? result.stderr.toString() : '';
34
- if (stderr) process.stderr.write(stderr);
27
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit' });
35
28
 
36
29
  if (result.error) throw result.error;
37
30
 
38
- if (stderr.includes('error while loading shared libraries')) {
39
- console.error(
40
- '\nmoss-npm: the moss binary currently needs the WebKitGTK runtime libraries:\n' +
41
- ' sudo apt install libwebkit2gtk-4.1-0\n' +
42
- 'This is temporary — a moss CLI build without that linkage is planned.'
43
- );
44
- }
45
-
46
31
  process.exit(result.status === null ? 1 : result.status);
47
32
  }
48
33
 
package/lib/fetch.js CHANGED
@@ -1,4 +1,4 @@
1
- // Downloads the moss CLI binary for this platform from moss-releases.
1
+ // Downloads the moss CLI binary for this platform from moss.
2
2
  //
3
3
  // No dependencies: uses the global fetch that ships with Node >= 18.
4
4
  // The version defaults to this package's own version (the wrapper is
@@ -11,10 +11,15 @@ const crypto = require('node:crypto');
11
11
  const fs = require('node:fs');
12
12
  const path = require('node:path');
13
13
 
14
- const RELEASES = 'https://github.com/Symbiosis-Lab/moss-releases/releases/download';
14
+ const RELEASES = 'https://github.com/Symbiosis-Lab/moss/releases/download';
15
15
 
16
16
  const packageRoot = path.join(__dirname, '..');
17
- const vendorBinary = path.join(packageRoot, 'vendor', 'moss');
17
+
18
+ // Compute the vendored binary path at use time, appending .exe on win32.
19
+ function vendorBinary() {
20
+ const name = process.platform === 'win32' ? 'moss.exe' : 'moss';
21
+ return path.join(packageRoot, 'vendor', name);
22
+ }
18
23
 
19
24
  // npm and pnpm expose every `.npmrc` key to lifecycle scripts as `npm_config_<key>`,
20
25
  // so one lookup covers both the environment variable and the config file. This is
@@ -58,7 +63,7 @@ function skipDownloadReason() {
58
63
  // Which binary `moss` should execute. `MOSS_BINARY_PATH` wins so a developer can
59
64
  // point the wrapper at a locally built moss (esbuild's `ESBUILD_BINARY_PATH`).
60
65
  function resolveBinary() {
61
- return process.env.MOSS_BINARY_PATH || vendorBinary;
66
+ return process.env.MOSS_BINARY_PATH || vendorBinary();
62
67
  }
63
68
 
64
69
  function resolveVersion() {
@@ -77,10 +82,13 @@ function resolveAsset() {
77
82
  if (platform === 'linux' && arch === 'x64') {
78
83
  return 'moss-linux-x86_64';
79
84
  }
85
+ if (platform === 'win32' && arch === 'x64') {
86
+ return 'moss-windows-x86_64.exe';
87
+ }
80
88
  throw new Error(
81
89
  `moss-npm: no moss binary is published for ${platform}-${arch}.\n` +
82
- 'Supported: macOS (x64/arm64) and Linux (x64). ' +
83
- 'See https://github.com/Symbiosis-Lab/moss-releases for available builds.'
90
+ 'Supported: macOS (x64/arm64), Linux (x64), and Windows (x64). ' +
91
+ 'See https://github.com/Symbiosis-Lab/moss for available builds.'
84
92
  );
85
93
  }
86
94
 
@@ -92,26 +100,57 @@ async function download(url) {
92
100
  return Buffer.from(await res.arrayBuffer());
93
101
  }
94
102
 
95
- // Verifies bytes against the release's SHA256SUMS. Releases before v0.11.2
96
- // published no checksums; a missing SHA256SUMS is a warning, not a failure.
103
+ // The first release that published a SHA256SUMS file. Before it there is
104
+ // nothing to verify against; from it on, every release has one.
105
+ const CHECKSUMS_SINCE = [0, 11, 2];
106
+
107
+ // Must a missing checksum be fatal for this version? Anything unparseable
108
+ // answers yes: an unrecognised version string is not a licence to skip the
109
+ // only check on bytes we are about to mark executable.
110
+ function checksumsRequired(version) {
111
+ const parts = String(version).split('-')[0].split('.').map(Number);
112
+ if (parts.length !== 3 || parts.some((n) => !Number.isInteger(n))) return true;
113
+ for (let i = 0; i < 3; i += 1) {
114
+ if (parts[i] !== CHECKSUMS_SINCE[i]) return parts[i] > CHECKSUMS_SINCE[i];
115
+ }
116
+ return true;
117
+ }
118
+
119
+ // Verifies bytes against the release's SHA256SUMS.
120
+ //
121
+ // Every reason we might not reach a checksum — a non-200, a network error, a
122
+ // SHA256SUMS with no line for this asset — is reached over the same connection
123
+ // that just served the binary. So on a version that publishes checksums, taking
124
+ // any of them as permission to skip verification hands the skip to whoever
125
+ // controls that connection: suppress one small request and the binary installs
126
+ // unverified. Fail closed there, and keep the warning only for the pre-v0.11.2
127
+ // releases where the file genuinely does not exist.
97
128
  async function verifyChecksum(bytes, asset, version) {
129
+ const unverified = (reason) => {
130
+ if (checksumsRequired(version)) {
131
+ throw new Error(
132
+ `moss-npm: cannot verify moss v${version} (${asset}): ${reason}.\n` +
133
+ ' Every release from v0.11.2 on publishes SHA256SUMS, so this is either a\n' +
134
+ ' transient network fault or a tampered download. Not installing.'
135
+ );
136
+ }
137
+ console.warn(`moss-npm: ${reason}; skipping checksum verification (v${version} predates SHA256SUMS)`);
138
+ };
139
+
98
140
  let sums;
99
141
  try {
100
142
  const res = await fetch(`${RELEASES}/v${version}/SHA256SUMS`, { redirect: 'follow' });
101
143
  if (!res.ok) {
102
- console.warn(`moss-npm: no SHA256SUMS published for v${version}; skipping checksum verification`);
103
- return;
144
+ return unverified(`no SHA256SUMS published for v${version} (${res.status})`);
104
145
  }
105
146
  sums = await res.text();
106
147
  } catch (err) {
107
- console.warn(`moss-npm: could not fetch SHA256SUMS (${err.message}); skipping checksum verification`);
108
- return;
148
+ return unverified(`could not fetch SHA256SUMS (${err.message})`);
109
149
  }
110
150
 
111
151
  const line = sums.split('\n').find((l) => l.trim().endsWith(asset));
112
152
  if (!line) {
113
- console.warn(`moss-npm: SHA256SUMS has no entry for ${asset}; skipping checksum verification`);
114
- return;
153
+ return unverified(`SHA256SUMS has no entry for ${asset}`);
115
154
  }
116
155
 
117
156
  const expected = line.trim().split(/\s+/)[0];
@@ -134,17 +173,20 @@ async function fetchBinary() {
134
173
  const bytes = await download(url);
135
174
  await verifyChecksum(bytes, asset, version);
136
175
 
137
- fs.mkdirSync(path.dirname(vendorBinary), { recursive: true });
138
- fs.writeFileSync(vendorBinary, bytes, { mode: 0o755 });
139
- console.log(`moss-npm: installed ${vendorBinary}`);
140
- return vendorBinary;
176
+ const binaryPath = vendorBinary();
177
+ fs.mkdirSync(path.dirname(binaryPath), { recursive: true });
178
+ fs.writeFileSync(binaryPath, bytes, { mode: 0o755 });
179
+ console.log(`moss-npm: installed ${binaryPath}`);
180
+ return binaryPath;
141
181
  }
142
182
 
143
183
  module.exports = {
184
+ checksumsRequired,
144
185
  fetchBinary,
145
186
  vendorBinary,
146
187
  resolveAsset,
147
188
  resolveBinary,
148
189
  resolveVersion,
149
190
  skipDownloadReason,
191
+ verifyChecksum,
150
192
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@symbiosis-lab/moss",
3
- "version": "0.12.1",
4
- "description": "moss on your PATH — npm wrapper that installs the moss CLI binary from moss-releases",
3
+ "version": "0.15.9",
4
+ "description": "moss on your PATH — npm wrapper that installs the moss CLI binary from moss",
5
5
  "bin": {
6
6
  "moss": "bin/moss.js"
7
7
  },
@@ -22,7 +22,8 @@
22
22
  },
23
23
  "os": [
24
24
  "darwin",
25
- "linux"
25
+ "linux",
26
+ "win32"
26
27
  ],
27
28
  "cpu": [
28
29
  "x64",
@@ -38,10 +39,10 @@
38
39
  "license": "MIT",
39
40
  "repository": {
40
41
  "type": "git",
41
- "url": "git+https://github.com/Symbiosis-Lab/moss-releases.git"
42
+ "url": "git+https://github.com/Symbiosis-Lab/moss.git"
42
43
  },
43
44
  "bugs": {
44
- "url": "https://github.com/Symbiosis-Lab/moss-releases/issues"
45
+ "url": "https://github.com/Symbiosis-Lab/moss/issues"
45
46
  },
46
47
  "homepage": "https://mosspub.com",
47
48
  "publishConfig": {