@lszio/zio 0.0.0-stage → 0.2.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/README.md +27 -2
- package/bin/zio-lsp.js +18 -0
- package/bin/zio.js +16 -0
- package/install.js +118 -0
- package/package.json +33 -4
package/README.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @lszio/zio
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Zio language toolchain. The package carries no binaries of its own:
|
|
4
|
+
on first run it downloads the release archive that matches the installed
|
|
5
|
+
version, checks it against the published checksum, and runs the `zio`
|
|
6
|
+
inside it.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install -g @lszio/zio
|
|
10
|
+
zio program.zio # run a script
|
|
11
|
+
zio # REPL
|
|
12
|
+
zio fmt program.zio # format
|
|
13
|
+
zio lsp # language server on stdio
|
|
14
|
+
zio-lsp # the same server, directly
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Supported platforms are the ones the release publishes archives for:
|
|
18
|
+
linux x86_64/arm64, macOS x86_64/arm64, Windows x86_64. The download
|
|
19
|
+
needs `curl` (or a curl-compatible tool) and `tar` on PATH; on Windows
|
|
20
|
+
the archive unpacks through PowerShell.
|
|
21
|
+
|
|
22
|
+
The engine as WebAssembly — interpreter, compiler and the same session
|
|
23
|
+
the CLI runs — is published separately as
|
|
24
|
+
[`@lszio/zio-core`](https://www.npmjs.com/package/@lszio/zio-core), for
|
|
25
|
+
browser and Node embedding.
|
|
26
|
+
|
|
27
|
+
Documentation and the language reference live in the
|
|
28
|
+
[Zio repository](https://github.com/lszio/zio).
|
package/bin/zio-lsp.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `zio-lsp` on PATH: the language server that ships inside the platform
|
|
3
|
+
// archive, reached through the CLI wrapper so an editor that starts
|
|
4
|
+
// `zio-lsp` gets the server that belongs to this install.
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const { spawnSync } = require("child_process");
|
|
9
|
+
const { ensureBinary } = require("../install.js");
|
|
10
|
+
|
|
11
|
+
const binary = ensureBinary();
|
|
12
|
+
const sibling = path.join(path.dirname(binary), "zio-lsp");
|
|
13
|
+
const child = spawnSync(sibling, process.argv.slice(2), { stdio: "inherit" });
|
|
14
|
+
if (child.error) {
|
|
15
|
+
console.error(`zio: cannot run the language server at ${sibling}: ${child.error.message}`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
process.exit(child.status === null ? 1 : child.status);
|
package/bin/zio.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `zio` on PATH: make sure the platform binary is present, then run it
|
|
3
|
+
// with this process's stdio and exit with its status, so a wrapper in
|
|
4
|
+
// front of the real CLI is invisible to the shell.
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
const { spawnSync } = require("child_process");
|
|
8
|
+
const { ensureBinary } = require("../install.js");
|
|
9
|
+
|
|
10
|
+
const binary = ensureBinary();
|
|
11
|
+
const child = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
12
|
+
if (child.error) {
|
|
13
|
+
console.error(`zio: cannot run ${binary}: ${child.error.message}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
process.exit(child.status === null ? 1 : child.status);
|
package/install.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Fetch the platform binary for this @lszio/zio install.
|
|
2
|
+
//
|
|
3
|
+
// The npm package ships no binaries of its own: it downloads the archive
|
|
4
|
+
// that matches the installed version from the release tagged with that
|
|
5
|
+
// same version, verifies it against the published checksum, and unpacks
|
|
6
|
+
// it beside this file. The version the wrapper installs and the version
|
|
7
|
+
// of the CLI it runs are therefore the same number by construction —
|
|
8
|
+
// there is no second version to drift.
|
|
9
|
+
//
|
|
10
|
+
// The download happens on first run rather than on install, so an
|
|
11
|
+
// install inside an offline build does not fail; the first `zio`
|
|
12
|
+
// invocation reports the failure it actually hit.
|
|
13
|
+
"use strict";
|
|
14
|
+
|
|
15
|
+
const crypto = require("crypto");
|
|
16
|
+
const fs = require("fs");
|
|
17
|
+
const path = require("path");
|
|
18
|
+
const { spawnSync } = require("child_process");
|
|
19
|
+
|
|
20
|
+
const REPO = "lszio/zio";
|
|
21
|
+
const VERSION = require("../package.json").version;
|
|
22
|
+
const BASE = `https://github.com/${REPO}/releases/download/v${VERSION}`;
|
|
23
|
+
|
|
24
|
+
const TARGETS = {
|
|
25
|
+
"linux-x64": "zio-linux-x86_64.tar.gz",
|
|
26
|
+
"linux-arm64": "zio-linux-aarch64.tar.gz",
|
|
27
|
+
"darwin-x64": "zio-macos-x86_64.tar.gz",
|
|
28
|
+
"darwin-arm64": "zio-macos-aarch64.tar.gz",
|
|
29
|
+
"win32-x64": "zio-windows-x86_64.zip",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const key = `${process.platform}-${process.arch}`;
|
|
33
|
+
const archive = TARGETS[key];
|
|
34
|
+
if (!archive) {
|
|
35
|
+
console.error(
|
|
36
|
+
`zio: no release archive for ${key}; build from source or download a ` +
|
|
37
|
+
`platform archive from https://github.com/${REPO}/releases`,
|
|
38
|
+
);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const vendor = path.join(__dirname, "..", "vendor");
|
|
43
|
+
const archivePath = path.join(vendor, archive);
|
|
44
|
+
const tree = path.join(vendor, archive.replace(/\.(tar\.gz|zip)$/, ""));
|
|
45
|
+
const binary = path.join(tree, "bin", process.platform === "win32" ? "zio.exe" : "zio");
|
|
46
|
+
|
|
47
|
+
/// Download, verify and unpack the archive for this platform, then
|
|
48
|
+
/// return the path of the `zio` binary inside it.
|
|
49
|
+
function ensureBinary() {
|
|
50
|
+
if (!fs.existsSync(binary)) {
|
|
51
|
+
download();
|
|
52
|
+
}
|
|
53
|
+
return binary;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function fail(message) {
|
|
57
|
+
console.error(`zio: ${message}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function fetch(url) {
|
|
62
|
+
const curl = spawnSync("curl", ["-fsSL", "--retry", "3", url], {
|
|
63
|
+
maxBuffer: 512 * 1024 * 1024,
|
|
64
|
+
});
|
|
65
|
+
if (curl.error) {
|
|
66
|
+
fail(`cannot download ${url}: ${curl.error.message}`);
|
|
67
|
+
}
|
|
68
|
+
if (curl.status !== 0) {
|
|
69
|
+
fail(
|
|
70
|
+
`cannot download ${url} (curl exit ${curl.status}); ` +
|
|
71
|
+
`check that release v${VERSION} publishes ${archive}`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return curl.stdout;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function download() {
|
|
78
|
+
fs.mkdirSync(vendor, { recursive: true });
|
|
79
|
+
process.stderr.write(`zio: downloading ${archive} (v${VERSION})…\n`);
|
|
80
|
+
|
|
81
|
+
const bytes = fetch(`${BASE}/${archive}`);
|
|
82
|
+
fs.writeFileSync(archivePath, bytes);
|
|
83
|
+
|
|
84
|
+
// The release publishes a checksum beside the archive. A binary that
|
|
85
|
+
// does not match its checksum is a supply-chain event, not a warning.
|
|
86
|
+
const expected = fetch(`${BASE}/${archive}.sha256`).toString("utf8").trim().split(/\s+/)[0];
|
|
87
|
+
const actual = crypto.createHash("sha256").update(bytes).digest("hex");
|
|
88
|
+
if (expected !== actual) {
|
|
89
|
+
fs.rmSync(archivePath, { force: true });
|
|
90
|
+
fail(`checksum mismatch for ${archive}: expected ${expected}, got ${actual}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (archive.endsWith(".zip")) {
|
|
94
|
+
const unzip = spawnSync(
|
|
95
|
+
"powershell",
|
|
96
|
+
[
|
|
97
|
+
"-NoProfile",
|
|
98
|
+
"-Command",
|
|
99
|
+
`Expand-Archive -LiteralPath '${archivePath}' -DestinationPath '${vendor}' -Force`,
|
|
100
|
+
],
|
|
101
|
+
{ stdio: "inherit" },
|
|
102
|
+
);
|
|
103
|
+
if (unzip.error || unzip.status !== 0) {
|
|
104
|
+
fail(`cannot unpack ${archive}`);
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
const tar = spawnSync("tar", ["-xzf", archivePath, "-C", vendor], { stdio: "inherit" });
|
|
108
|
+
if (tar.error || tar.status !== 0) {
|
|
109
|
+
fail(`cannot unpack ${archive} (GNU tar must be on PATH)`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
fs.rmSync(archivePath, { force: true });
|
|
113
|
+
if (!fs.existsSync(binary)) {
|
|
114
|
+
fail(`the unpacked archive did not contain bin/${path.basename(binary)}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = { ensureBinary, binary };
|
package/package.json
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lszio/zio",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The Zio language: a general-purpose Lisp with a self-hosting compiler, an image runtime, and one CLI — REPL, script runner, compiler, formatter and language server",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/lszio/zio.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/lszio/zio#readme",
|
|
11
|
+
"bugs": "https://github.com/lszio/zio/issues",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"zio",
|
|
14
|
+
"lisp",
|
|
15
|
+
"language",
|
|
16
|
+
"compiler",
|
|
17
|
+
"cli"
|
|
18
|
+
],
|
|
19
|
+
"type": "commonjs",
|
|
20
|
+
"bin": {
|
|
21
|
+
"zio": "bin/zio.js",
|
|
22
|
+
"zio-lsp": "bin/zio-lsp.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"bin",
|
|
26
|
+
"install.js",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|