@previewio/cli 0.2.0-cf1b36a → 0.2.0-d26dd93
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/{install.cjs → install.mjs} +45 -26
- package/package.json +3 -3
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const { dirname, join } = require('node:path');
|
|
1
|
+
import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
5
4
|
|
|
6
5
|
const PUBLIC_DOWNLOAD_ORIGIN = 'https://download.preview.io';
|
|
7
6
|
const VERSION_PATTERN = /^[A-Za-z0-9._-]+$/;
|
|
8
7
|
const RESERVED_VERSIONS = new Set(['latest', 'install', '.', '..']);
|
|
9
8
|
const BINARY_FETCH_TIMEOUT_MS = 120_000;
|
|
10
9
|
|
|
11
|
-
function binaryObjectName(platform, arch) {
|
|
10
|
+
export function binaryObjectName(platform, arch) {
|
|
12
11
|
if (platform === 'darwin' && arch === 'arm64') return 'preview-darwin-arm64';
|
|
13
12
|
if (platform === 'darwin' && (arch === 'x64' || arch === 'x86_64')) return 'preview-darwin-x64';
|
|
14
13
|
if (platform === 'linux' && (arch === 'x64' || arch === 'x86_64')) return 'preview-linux-x64';
|
|
@@ -18,18 +17,45 @@ function binaryObjectName(platform, arch) {
|
|
|
18
17
|
|
|
19
18
|
function assertReleaseVersion(version) {
|
|
20
19
|
if (!VERSION_PATTERN.test(version) || RESERVED_VERSIONS.has(version) || version === '0.0.0-dev') {
|
|
21
|
-
throw new Error(
|
|
22
|
-
`Invalid CLI release version ${version}. Publish stamps the package version to the CDN stamp.`,
|
|
23
|
-
);
|
|
20
|
+
throw new Error(`Invalid CLI release version ${version}. Publish stamps the package version to the CDN stamp.`);
|
|
24
21
|
}
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
function downloadUrl(origin, version, object) {
|
|
24
|
+
export function downloadUrl(origin, version, object) {
|
|
28
25
|
assertReleaseVersion(version);
|
|
29
26
|
return `${origin.replace(/\/+$/, '')}/cli/${version}/${object}`;
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
function
|
|
29
|
+
function installedBinaryName(platform) {
|
|
30
|
+
return platform === 'win32' ? 'preview.exe' : 'preview';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function npmGlobalInstall(env) {
|
|
34
|
+
const value = env.npm_config_global?.trim().toLowerCase();
|
|
35
|
+
return value === '1' || value === 'true' || value === 'yes';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function windowsShimDirs(packageRoot, env) {
|
|
39
|
+
const dirs = [join(packageRoot, '..', '..', '.bin')];
|
|
40
|
+
const prefix = env.npm_config_prefix?.trim();
|
|
41
|
+
if (prefix && npmGlobalInstall(env)) dirs.push(prefix);
|
|
42
|
+
return dirs;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function writeWindowsLaunchers(exePath, packageRoot, env) {
|
|
46
|
+
const cmd = `@ECHO OFF\r\n"${exePath}" %*\r\n`;
|
|
47
|
+
const ps1 = `& '${exePath.replaceAll("'", "''")}' @args\r\n`;
|
|
48
|
+
const sh = `#!/bin/sh\nexec "${exePath}" "$@"\n`;
|
|
49
|
+
for (const dir of windowsShimDirs(packageRoot, env)) {
|
|
50
|
+
mkdirSync(dir, { recursive: true });
|
|
51
|
+
writeFileSync(join(dir, 'preview.cmd'), cmd);
|
|
52
|
+
writeFileSync(join(dir, 'preview.ps1'), ps1);
|
|
53
|
+
writeFileSync(join(dir, 'preview'), sh);
|
|
54
|
+
chmodSync(join(dir, 'preview'), 0o755);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function looksLikePublishedBinary(bytes, platform) {
|
|
33
59
|
if (platform === 'linux') {
|
|
34
60
|
return bytes.byteLength >= 4 && bytes[0] === 0x7f && bytes[1] === 0x45 && bytes[2] === 0x4c && bytes[3] === 0x46;
|
|
35
61
|
}
|
|
@@ -52,11 +78,7 @@ function looksLikePublishedBinary(bytes, platform) {
|
|
|
52
78
|
}
|
|
53
79
|
|
|
54
80
|
function packageVersion(packageRoot) {
|
|
55
|
-
|
|
56
|
-
if (typeof pkg.version !== 'string' || !pkg.version) {
|
|
57
|
-
throw new Error('package.json is missing a version');
|
|
58
|
-
}
|
|
59
|
-
return pkg.version;
|
|
81
|
+
return JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')).version;
|
|
60
82
|
}
|
|
61
83
|
|
|
62
84
|
async function fetchBinary(url, fetchImpl) {
|
|
@@ -71,8 +93,8 @@ async function fetchBinary(url, fetchImpl) {
|
|
|
71
93
|
return new Uint8Array(await response.arrayBuffer());
|
|
72
94
|
}
|
|
73
95
|
|
|
74
|
-
async function install(opts = {}) {
|
|
75
|
-
const packageRoot = opts.packageRoot ??
|
|
96
|
+
export async function install(opts = {}) {
|
|
97
|
+
const packageRoot = opts.packageRoot ?? dirname(fileURLToPath(import.meta.url));
|
|
76
98
|
const version = opts.version ?? packageVersion(packageRoot);
|
|
77
99
|
const platform = opts.platform ?? process.platform;
|
|
78
100
|
const arch = opts.arch ?? process.arch;
|
|
@@ -81,7 +103,7 @@ async function install(opts = {}) {
|
|
|
81
103
|
throw new Error(`Unsupported platform: ${platform} ${arch}`);
|
|
82
104
|
}
|
|
83
105
|
const url = downloadUrl(opts.origin ?? PUBLIC_DOWNLOAD_ORIGIN, version, object);
|
|
84
|
-
const dest = join(opts.binDir ?? join(packageRoot, 'bin'),
|
|
106
|
+
const dest = join(opts.binDir ?? join(packageRoot, 'bin'), installedBinaryName(platform));
|
|
85
107
|
const bytes = await fetchBinary(url, opts.fetch ?? globalThis.fetch);
|
|
86
108
|
if (bytes.byteLength === 0 || !looksLikePublishedBinary(bytes, platform)) {
|
|
87
109
|
throw new Error(`Refused non-binary body from ${url}`);
|
|
@@ -91,17 +113,14 @@ async function install(opts = {}) {
|
|
|
91
113
|
writeFileSync(tmp, bytes);
|
|
92
114
|
chmodSync(tmp, 0o755);
|
|
93
115
|
renameSync(tmp, dest);
|
|
116
|
+
if (platform === 'win32') {
|
|
117
|
+
writeWindowsLaunchers(dest, packageRoot, opts.env ?? process.env);
|
|
118
|
+
}
|
|
94
119
|
return dest;
|
|
95
120
|
}
|
|
96
121
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
downloadUrl,
|
|
100
|
-
looksLikePublishedBinary,
|
|
101
|
-
install,
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
if (require.main === module) {
|
|
122
|
+
const invoked = process.argv[1] ? resolve(process.argv[1]) : '';
|
|
123
|
+
if (invoked && invoked === fileURLToPath(import.meta.url)) {
|
|
105
124
|
install({}).catch((err) => {
|
|
106
125
|
console.error(err instanceof Error ? err.message : err);
|
|
107
126
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@previewio/cli",
|
|
3
|
-
"version": "0.2.0-
|
|
3
|
+
"version": "0.2.0-d26dd93",
|
|
4
4
|
"description": "Preview CLI — JSON-first client for agentic tooling",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"bin",
|
|
16
|
-
"install.
|
|
16
|
+
"install.mjs"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"postinstall": "node install.
|
|
19
|
+
"postinstall": "node install.mjs"
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=18"
|