@cnwenf/occ 2.1.268 → 2.1.269
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/bin/occ.cjs +204 -0
- package/dist/cli.js +13436 -11193
- package/package.json +7 -3
package/bin/occ.cjs
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* OCC launcher shim.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS
|
|
6
|
+
* OCC ships a Bun-target bundle at dist/cli.js (built with
|
|
7
|
+
* `bun build --target bun`, shebang `#!/usr/bin/env bun`). When a user
|
|
8
|
+
* installs OCC via `npm i -g @cnwenf/occ` on a machine that has npm but
|
|
9
|
+
* NOT Bun, the kernel's shebang resolution fails with
|
|
10
|
+
* `/usr/bin/env: 'bun': No such file or directory` — so the `occ`
|
|
11
|
+
* command never even starts.
|
|
12
|
+
*
|
|
13
|
+
* This shim is a Node script (npm guarantees Node is present), so it
|
|
14
|
+
* ALWAYS runs. It locates a Bun binary, then spawns
|
|
15
|
+
* `bun <package>/dist/cli.js <args…>`. If no Bun is available it prints
|
|
16
|
+
* a clear install instruction instead of a cryptic env error.
|
|
17
|
+
*
|
|
18
|
+
* BUN RESOLUTION ORDER
|
|
19
|
+
* 1. `$BUN_PATH` env (power-user override)
|
|
20
|
+
* 2. `bun` on PATH (the common case: `bun` is an OCC optionalDependency
|
|
21
|
+
* whose postinstall puts the real binary on PATH)
|
|
22
|
+
* 3. `~/.bun/bin/bun` (user installed Bun via bun.sh installer)
|
|
23
|
+
* 4. The optional-dep platform binary directly, e.g.
|
|
24
|
+
* `@oven/bun-linux-x64/bin/bun`. This path works EVEN WHEN npm was
|
|
25
|
+
* run with `--ignore-scripts` (so `bun`'s postinstall never ran and
|
|
26
|
+
* `bun` is not on PATH), because the `@oven/bun-*` packages ship the
|
|
27
|
+
* real ELF/Mach-O/PE binary in the tarball — no postinstall needed.
|
|
28
|
+
* 5. The `bun` meta-package's `bin/bun.exe` (real only if its
|
|
29
|
+
* postinstall ran; redundant with #2 but harmless).
|
|
30
|
+
*
|
|
31
|
+
* If none resolve, print install instructions and exit 1.
|
|
32
|
+
*/
|
|
33
|
+
'use strict'
|
|
34
|
+
|
|
35
|
+
const { existsSync } = require('node:fs')
|
|
36
|
+
const { spawn } = require('node:child_process')
|
|
37
|
+
const path = require('node:path')
|
|
38
|
+
const os = require('node:os')
|
|
39
|
+
|
|
40
|
+
const pkgRoot = path.join(__dirname, '..')
|
|
41
|
+
const cliJs = path.join(pkgRoot, 'dist', 'cli.js')
|
|
42
|
+
const isWin = process.platform === 'win32'
|
|
43
|
+
const bunExeName = isWin ? 'bun.exe' : 'bun'
|
|
44
|
+
|
|
45
|
+
if (!existsSync(cliJs)) {
|
|
46
|
+
console.error(
|
|
47
|
+
'occ: dist/cli.js not found — the package install is incomplete or corrupt.',
|
|
48
|
+
)
|
|
49
|
+
console.error('Reinstall with: npm i -g @cnwenf/occ')
|
|
50
|
+
process.exit(1)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The @oven/bun-<platform>-<arch> package(s) that match the current
|
|
55
|
+
* process, ordered by preference (glibc before musl, non-baseline before
|
|
56
|
+
* baseline). Each ships the real Bun binary at `bin/bun` (or `bin/bun.exe`
|
|
57
|
+
* on Windows). List gleaned from the `bun` npm meta-package's
|
|
58
|
+
* optionalDependencies (@oven 1.3.14).
|
|
59
|
+
*/
|
|
60
|
+
function platformPackages() {
|
|
61
|
+
const p = process.platform
|
|
62
|
+
const a = process.arch
|
|
63
|
+
if (p === 'darwin' && a === 'x64') return ['@oven/bun-darwin-x64']
|
|
64
|
+
if (p === 'darwin' && a === 'arm64') return ['@oven/bun-darwin-aarch64']
|
|
65
|
+
if (p === 'linux' && a === 'x64')
|
|
66
|
+
return [
|
|
67
|
+
'@oven/bun-linux-x64',
|
|
68
|
+
'@oven/bun-linux-x64-musl',
|
|
69
|
+
'@oven/bun-linux-x64-baseline',
|
|
70
|
+
'@oven/bun-linux-x64-musl-baseline',
|
|
71
|
+
]
|
|
72
|
+
if (p === 'linux' && a === 'arm64')
|
|
73
|
+
return ['@oven/bun-linux-aarch64', '@oven/bun-linux-aarch64-musl']
|
|
74
|
+
if (p === 'win32' && a === 'x64') return ['@oven/bun-windows-x64']
|
|
75
|
+
if (p === 'win32' && a === 'arm64') return ['@oven/bun-windows-aarch64']
|
|
76
|
+
return []
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Resolve a path inside a dependency package, or null if not installed. */
|
|
80
|
+
function resolveDepFile(spec) {
|
|
81
|
+
try {
|
|
82
|
+
return require.resolve(spec)
|
|
83
|
+
} catch (_) {
|
|
84
|
+
return null
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Ordered candidate Bun binaries. Bare 'bun' (PATH) validated by findOnPath. */
|
|
89
|
+
function bunCandidates() {
|
|
90
|
+
const cands = []
|
|
91
|
+
|
|
92
|
+
// 1. Power-user override.
|
|
93
|
+
if (process.env.BUN_PATH && existsSync(process.env.BUN_PATH)) {
|
|
94
|
+
cands.push(process.env.BUN_PATH)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 2. `bun` on PATH — verified by findBun via an explicit PATH walk. If not
|
|
98
|
+
// present, fall through to #3/#4/#5 instead of returning a phantom
|
|
99
|
+
// candidate that would ENOENT at spawn and skip the better fallbacks.
|
|
100
|
+
cands.push('bun')
|
|
101
|
+
|
|
102
|
+
// 3. ~/.bun/bin/bun (bun.sh installer default location).
|
|
103
|
+
const homeBun = path.join(os.homedir(), '.bun', 'bin', bunExeName)
|
|
104
|
+
if (existsSync(homeBun)) cands.push(homeBun)
|
|
105
|
+
|
|
106
|
+
// 4. Optional-dep platform binary (robust under --ignore-scripts).
|
|
107
|
+
for (const pkg of platformPackages()) {
|
|
108
|
+
const resolved = resolveDepFile(path.posix.join(pkg, 'bin', bunExeName))
|
|
109
|
+
if (resolved && existsSync(resolved)) cands.push(resolved)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 5. `bun` meta-package bin (real only if its postinstall ran).
|
|
113
|
+
const metaBin = resolveDepFile('bun/bin/bun.exe')
|
|
114
|
+
if (metaBin && existsSync(metaBin)) cands.push(metaBin)
|
|
115
|
+
|
|
116
|
+
return cands
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Walk PATH for an executable named `name` (with Windows PATHEXT extensions
|
|
121
|
+
* on win32). Returns the absolute path if found, else null. This is what
|
|
122
|
+
* `bun:bundle`'s bare-candidate check needs — without it, returning 'bun'
|
|
123
|
+
* unconditionally makes the shim skip #3/#4/#5 fallbacks when bun isn't on
|
|
124
|
+
* PATH (the exact scenario the shim exists to handle).
|
|
125
|
+
*/
|
|
126
|
+
function findOnPath(name) {
|
|
127
|
+
const pathVar = process.env.PATH || process.env.Path
|
|
128
|
+
if (!pathVar) return null
|
|
129
|
+
const sep = isWin ? ';' : ':'
|
|
130
|
+
const exts = isWin
|
|
131
|
+
? (process.env.PATHEXT ? process.env.PATHEXT.split(';') : ['.exe', '.cmd', '.bat', ''])
|
|
132
|
+
: ['']
|
|
133
|
+
for (const dir of pathVar.split(sep)) {
|
|
134
|
+
if (!dir) continue
|
|
135
|
+
for (const ext of exts) {
|
|
136
|
+
const candidate = path.join(dir, name + ext)
|
|
137
|
+
if (existsSync(candidate)) return candidate
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return null
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function findBun() {
|
|
144
|
+
const tried = []
|
|
145
|
+
for (const c of bunCandidates()) {
|
|
146
|
+
if (!c) continue
|
|
147
|
+
tried.push(c)
|
|
148
|
+
// Bare 'bun' is only usable if it's actually on PATH. Verify now so the
|
|
149
|
+
// #3/#4/#5 fallbacks get a chance when it isn't — otherwise we'd return
|
|
150
|
+
// a phantom 'bun' that ENOENTs at spawn, defeating the shim's purpose.
|
|
151
|
+
if (c === 'bun') {
|
|
152
|
+
if (findOnPath(bunExeName)) return { bin: c, viaShell: isWin, tried }
|
|
153
|
+
continue
|
|
154
|
+
}
|
|
155
|
+
if (existsSync(c)) return { bin: c, viaShell: false, tried }
|
|
156
|
+
}
|
|
157
|
+
return { bin: null, viaShell: false, tried }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const { bin: bunBin, viaShell, tried } = findBun()
|
|
161
|
+
|
|
162
|
+
if (!bunBin) {
|
|
163
|
+
console.error('')
|
|
164
|
+
console.error('occ: Bun runtime not found.')
|
|
165
|
+
console.error('')
|
|
166
|
+
console.error('OCC requires Bun (>= 1.3.11) to run. Install it with one of:')
|
|
167
|
+
console.error(' npm i -g bun')
|
|
168
|
+
console.error(' curl -fsSL https://bun.sh/install | bash')
|
|
169
|
+
console.error('Then run `occ` again.')
|
|
170
|
+
console.error('')
|
|
171
|
+
console.error('Tried: ' + tried.join(', '))
|
|
172
|
+
process.exit(1)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const child = spawn(bunBin, [cliJs, ...process.argv.slice(2)], {
|
|
176
|
+
stdio: 'inherit',
|
|
177
|
+
env: process.env,
|
|
178
|
+
shell: viaShell,
|
|
179
|
+
windowsHide: false,
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
child.on('error', (err) => {
|
|
183
|
+
if (err && err.code === 'ENOENT' && bunBin === 'bun') {
|
|
184
|
+
console.error('')
|
|
185
|
+
console.error('occ: `bun` is on PATH but not executable. Reinstall Bun:')
|
|
186
|
+
console.error(' npm i -g bun')
|
|
187
|
+
console.error(' curl -fsSL https://bun.sh/install | bash')
|
|
188
|
+
process.exit(1)
|
|
189
|
+
}
|
|
190
|
+
console.error('occ: failed to launch bun:', err ? err.message : 'unknown error')
|
|
191
|
+
process.exit(1)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
child.on('exit', (code, signal) => {
|
|
195
|
+
if (signal) {
|
|
196
|
+
try {
|
|
197
|
+
process.kill(process.pid, signal)
|
|
198
|
+
} catch (_) {
|
|
199
|
+
process.exit(1)
|
|
200
|
+
}
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
process.exit(code ?? 0)
|
|
204
|
+
})
|