topaz-lang 5.2.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.
- package/README.md +21 -0
- package/bin/topaz.js +21 -0
- package/install.js +85 -0
- package/package.json +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# topaz-lang
|
|
2
|
+
|
|
3
|
+
The [Topaz](https://topaz.ooo) toolchain as a prebuilt binary — no repo clone, no build.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install -g topaz-lang
|
|
7
|
+
topaz version
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
One-off, without installing:
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npx -p topaz-lang topaz run main.tpz
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
On install, a `postinstall` step downloads the `topaz` binary for your platform
|
|
17
|
+
(matching this package's version) and verifies its SHA256. `topaz run`,
|
|
18
|
+
`topaz check`, and `topaz emit` are standalone; `topaz build` additionally needs
|
|
19
|
+
a Rust toolchain present on your machine.
|
|
20
|
+
|
|
21
|
+
License: Apache-2.0.
|
package/bin/topaz.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Shim: exec the downloaded `topaz` binary, forwarding args + exit status.
|
|
3
|
+
'use strict';
|
|
4
|
+
const { spawnSync } = require('node:child_process');
|
|
5
|
+
const { constants } = require('node:os');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
|
|
8
|
+
const bin = path.join(__dirname, process.platform === 'win32' ? 'topaz.exe' : 'topaz-bin');
|
|
9
|
+
const res = spawnSync(bin, process.argv.slice(2), { stdio: 'inherit' });
|
|
10
|
+
|
|
11
|
+
if (res.error) {
|
|
12
|
+
const why = res.error.code === 'ENOENT' ? 'binary not found — reinstall topaz-lang' : res.error.message;
|
|
13
|
+
console.error(`topaz: ${why}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
if (res.signal) {
|
|
17
|
+
// Preserve signal-death semantics (128 + signal number, the shell convention).
|
|
18
|
+
const n = constants.signals[res.signal];
|
|
19
|
+
process.exit(n ? 128 + n : 1);
|
|
20
|
+
}
|
|
21
|
+
process.exit(res.status === null ? 1 : res.status);
|
package/install.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// postinstall: download the prebuilt `topaz` binary that matches THIS package
|
|
2
|
+
// version (so `npm i topaz-lang@5.2.1` pins topaz v5.2.1), verify its SHA256,
|
|
3
|
+
// and drop it next to the bin shim. No Rust source, no build.
|
|
4
|
+
'use strict';
|
|
5
|
+
const { mkdir, writeFile, chmod, rename } = require('node:fs/promises');
|
|
6
|
+
const { createHash } = require('node:crypto');
|
|
7
|
+
const path = require('node:path');
|
|
8
|
+
|
|
9
|
+
const VERSION = require('./package.json').version;
|
|
10
|
+
const TAG = `v${VERSION}`;
|
|
11
|
+
const DL_BASE = (process.env.TOPAZ_DL_BASE || 'https://topaz.ooo/dl').replace(/\/$/, '');
|
|
12
|
+
const TIMEOUT_MS = 60_000;
|
|
13
|
+
const MAX_BYTES = 100 * 1024 * 1024; // a sane ceiling for a single CLI binary
|
|
14
|
+
|
|
15
|
+
// Honour HTTP(S)_PROXY where the running Node exposes the helper.
|
|
16
|
+
try {
|
|
17
|
+
require('node:http').setGlobalProxyFromEnv?.();
|
|
18
|
+
} catch {
|
|
19
|
+
/* older Node without env-proxy support */
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function linuxAsset(name) {
|
|
23
|
+
// The published Linux binaries are glibc-based; glibcVersionRuntime is absent
|
|
24
|
+
// on musl/Alpine, so fail clearly instead of installing an unrunnable binary.
|
|
25
|
+
const glibc = process.report?.getReport?.()?.header?.glibcVersionRuntime;
|
|
26
|
+
if (!glibc) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'this looks like a musl/Alpine system; the published Linux binaries are ' +
|
|
29
|
+
'glibc-based. Use a glibc distro or build from source (https://topaz.ooo).',
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return name;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function assetName() {
|
|
36
|
+
const p = process.platform;
|
|
37
|
+
const a = process.arch;
|
|
38
|
+
if (p === 'linux' && a === 'x64') return linuxAsset('topaz-linux-x86_64');
|
|
39
|
+
if (p === 'linux' && a === 'arm64') return linuxAsset('topaz-linux-aarch64');
|
|
40
|
+
if (p === 'darwin' && a === 'arm64') return 'topaz-macos-aarch64';
|
|
41
|
+
if (p === 'darwin' && a === 'x64') return 'topaz-macos-x86_64';
|
|
42
|
+
if (p === 'win32' && (a === 'x64' || a === 'arm64')) return 'topaz-windows-x86_64.exe';
|
|
43
|
+
throw new Error(`unsupported platform ${p}/${a}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function get(url) {
|
|
47
|
+
const ctrl = new AbortController();
|
|
48
|
+
const timer = setTimeout(() => ctrl.abort(), TIMEOUT_MS);
|
|
49
|
+
try {
|
|
50
|
+
const res = await fetch(url, { signal: ctrl.signal }); // node >=18, follows redirects
|
|
51
|
+
if (!res.ok) throw new Error(`fetch ${res.status} for ${url}`);
|
|
52
|
+
const len = Number(res.headers.get('content-length'));
|
|
53
|
+
if (len && len > MAX_BYTES) throw new Error(`refusing ${len} bytes from ${url}`);
|
|
54
|
+
return res;
|
|
55
|
+
} finally {
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function main() {
|
|
61
|
+
const name = assetName();
|
|
62
|
+
const url = `${DL_BASE}/${TAG}/${name}`;
|
|
63
|
+
const binDir = path.join(__dirname, 'bin');
|
|
64
|
+
const out = path.join(binDir, process.platform === 'win32' ? 'topaz.exe' : 'topaz-bin');
|
|
65
|
+
|
|
66
|
+
const buf = Buffer.from(await (await get(url)).arrayBuffer());
|
|
67
|
+
if (buf.length > MAX_BYTES) throw new Error(`downloaded ${buf.length} bytes (over the cap)`);
|
|
68
|
+
|
|
69
|
+
const want = (await (await get(`${url}.sha256`)).text()).trim().split(/\s+/)[0].toLowerCase();
|
|
70
|
+
if (!/^[0-9a-f]{64}$/.test(want)) throw new Error('malformed checksum');
|
|
71
|
+
const got = createHash('sha256').update(buf).digest('hex');
|
|
72
|
+
if (got !== want) throw new Error(`checksum mismatch (expected ${want}, got ${got})`);
|
|
73
|
+
|
|
74
|
+
await mkdir(binDir, { recursive: true });
|
|
75
|
+
const tmp = `${out}.tmp`;
|
|
76
|
+
await writeFile(tmp, buf);
|
|
77
|
+
await chmod(tmp, 0o755);
|
|
78
|
+
await rename(tmp, out); // atomic swap into place
|
|
79
|
+
console.log(`topaz: installed ${TAG} (${name})`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
main().catch((e) => {
|
|
83
|
+
console.error(`topaz: install failed — ${e.message}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "topaz-lang",
|
|
3
|
+
"version": "5.2.1",
|
|
4
|
+
"description": "The Topaz language toolchain (topaz run / check / emit / build).",
|
|
5
|
+
"homepage": "https://topaz.ooo",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"bin": {
|
|
8
|
+
"topaz": "bin/topaz.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"postinstall": "node install.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin/topaz.js",
|
|
15
|
+
"install.js"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18"
|
|
19
|
+
}
|
|
20
|
+
}
|