@alumbwe/anvil 1.0.40 → 1.0.41
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/anvil.js +120 -0
- package/package.json +3 -3
package/bin/anvil.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Anvil CLI launcher — the npm `bin` entry for `anvil`.
|
|
4
|
+
*
|
|
5
|
+
* Runs on plain Node.js (Bun is NOT required upfront) and works from cmd,
|
|
6
|
+
* PowerShell and POSIX shells: npm generates a shim for each shell that all
|
|
7
|
+
* execute this file with `node`.
|
|
8
|
+
*
|
|
9
|
+
* Strategy:
|
|
10
|
+
* 1. Already running under Bun (e.g. `bunx anvil`) → import the TS entry directly.
|
|
11
|
+
* 2. Else locate a Bun executable: local node_modules/.bin, global
|
|
12
|
+
* node_modules/.bin, ~/.bun/bin, /usr/local/bin, Homebrew, then PATH.
|
|
13
|
+
* 3. Else install Bun once via `npm i -g bun`, then retry.
|
|
14
|
+
* 4. Spawn `bun src/entry.ts <args>` with inherited stdio and forward the
|
|
15
|
+
* exit code, so the TUI behaves exactly as when run directly.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { spawnSync } from 'child_process'
|
|
19
|
+
import fs from 'fs'
|
|
20
|
+
import os from 'os'
|
|
21
|
+
import path from 'path'
|
|
22
|
+
import { fileURLToPath, pathToFileURL } from 'url'
|
|
23
|
+
|
|
24
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url))
|
|
25
|
+
const PKG_ROOT = path.resolve(HERE, '..')
|
|
26
|
+
const ENTRY = path.join(PKG_ROOT, 'src', 'entry.ts')
|
|
27
|
+
const IS_WIN = process.platform === 'win32'
|
|
28
|
+
const BUN_EXE = IS_WIN ? 'bun.exe' : 'bun'
|
|
29
|
+
|
|
30
|
+
/** Check that a candidate command is a working bun executable. */
|
|
31
|
+
function isBun(cmd) {
|
|
32
|
+
try {
|
|
33
|
+
const r = spawnSync(cmd, ['--version'], {
|
|
34
|
+
encoding: 'utf8',
|
|
35
|
+
timeout: 15000,
|
|
36
|
+
windowsHide: true,
|
|
37
|
+
})
|
|
38
|
+
return !r.error && r.status === 0
|
|
39
|
+
} catch {
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Locate a usable bun executable without assuming anything about the machine. */
|
|
45
|
+
function findBun() {
|
|
46
|
+
// Already running under Bun itself
|
|
47
|
+
if (process.versions.bun) return process.execPath
|
|
48
|
+
|
|
49
|
+
const candidates = [
|
|
50
|
+
// Local install: <pkg>/node_modules/.bin/bun
|
|
51
|
+
path.join(PKG_ROOT, 'node_modules', '.bin', BUN_EXE),
|
|
52
|
+
// Hoisted install: <prefix>/node_modules/.bin/bun
|
|
53
|
+
// global: <prefix>/node_modules/@alumbwe/anvil → ../../.bin
|
|
54
|
+
// project: <project>/node_modules/@alumbwe/anvil → ../../.bin
|
|
55
|
+
path.join(PKG_ROOT, '..', '..', '.bin', BUN_EXE),
|
|
56
|
+
// Official bun installer location
|
|
57
|
+
path.join(os.homedir(), '.bun', 'bin', BUN_EXE),
|
|
58
|
+
]
|
|
59
|
+
if (!IS_WIN) {
|
|
60
|
+
candidates.push('/usr/local/bin/bun', '/opt/homebrew/bin/bun')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (const candidate of candidates) {
|
|
64
|
+
if (fs.existsSync(candidate) && isBun(candidate)) return candidate
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Last resort: let the OS resolve `bun` from PATH.
|
|
68
|
+
if (isBun(BUN_EXE)) return BUN_EXE
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** One-time automatic install of Bun through npm (same prefix as this CLI). */
|
|
73
|
+
function installBun() {
|
|
74
|
+
console.error('')
|
|
75
|
+
console.error('Anvil runs on the Bun runtime, which was not found on this machine.')
|
|
76
|
+
console.error('Installing Bun via npm (one-time, this may take a minute)...')
|
|
77
|
+
console.error('')
|
|
78
|
+
const r = spawnSync('npm', ['install', '-g', 'bun'], {
|
|
79
|
+
stdio: 'inherit',
|
|
80
|
+
shell: IS_WIN,
|
|
81
|
+
windowsHide: true,
|
|
82
|
+
})
|
|
83
|
+
return r.status === 0
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function printManualInstructions() {
|
|
87
|
+
console.error('')
|
|
88
|
+
console.error('Could not install Bun automatically. Install it manually, then re-run anvil:')
|
|
89
|
+
if (IS_WIN) {
|
|
90
|
+
console.error(' powershell -c "irm bun.sh/install.ps1 | iex"')
|
|
91
|
+
} else {
|
|
92
|
+
console.error(' curl -fsSL https://bun.sh/install | bash')
|
|
93
|
+
}
|
|
94
|
+
console.error(' (or) npm i -g bun')
|
|
95
|
+
console.error('')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Under Bun: run the TypeScript entry in-process.
|
|
99
|
+
if (process.versions.bun) {
|
|
100
|
+
await import(pathToFileURL(ENTRY).href)
|
|
101
|
+
} else {
|
|
102
|
+
let bun = findBun()
|
|
103
|
+
if (!bun && installBun()) bun = findBun()
|
|
104
|
+
if (!bun) {
|
|
105
|
+
printManualInstructions()
|
|
106
|
+
process.exit(1)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const result = spawnSync(bun, [ENTRY, ...process.argv.slice(2)], {
|
|
110
|
+
stdio: 'inherit',
|
|
111
|
+
env: process.env,
|
|
112
|
+
windowsHide: true,
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
if (result.error) {
|
|
116
|
+
console.error(`Failed to start Anvil via Bun (${bun}):`, result.error.message)
|
|
117
|
+
process.exit(1)
|
|
118
|
+
}
|
|
119
|
+
process.exit(result.status ?? (result.signal ? 1 : 0))
|
|
120
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alumbwe/anvil",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.41",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"anvil": "./bin/anvil"
|
|
7
|
+
"anvil": "./bin/anvil.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"bin/anvil",
|
|
10
|
+
"bin/anvil.js",
|
|
11
11
|
"bin/tree-sitter.wasm",
|
|
12
12
|
"src/",
|
|
13
13
|
"vendor/",
|