@deadbolt/cli 0.0.0-dev-143 → 0.0.0-dev-145
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/deadbolt +12 -6
- package/package.json +7 -7
- package/postinstall.mjs +46 -39
package/bin/deadbolt
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# @deadbolt/cli's postinstall replaces this with a link to this platform's
|
|
3
3
|
# deadbolt (postinstall.mjs). When the package manager skipped install
|
|
4
|
-
# scripts (pnpm, bun, npm with scripts disallowed), the
|
|
5
|
-
#
|
|
4
|
+
# scripts (pnpm, bun, npm with scripts disallowed), or the postinstall
|
|
5
|
+
# couldn't link (npm didn't serve this platform's package yet), the first run
|
|
6
|
+
# links it here, then runs it. It never deletes anything.
|
|
6
7
|
self=$0
|
|
7
8
|
while [ -L "$self" ]; do
|
|
8
9
|
link=$(readlink "$self")
|
|
@@ -12,10 +13,15 @@ while [ -L "$self" ]; do
|
|
|
12
13
|
esac
|
|
13
14
|
done
|
|
14
15
|
package=$(cd "$(dirname "$self")/.." && pwd)
|
|
15
|
-
if command -v node > /dev/null 2>&1
|
|
16
|
+
if ! command -v node > /dev/null 2>&1; then
|
|
17
|
+
echo "Error: @deadbolt/cli isn't fully installed, and finishing that needs node on PATH." >&2
|
|
18
|
+
echo "Run \`node $package/postinstall.mjs\`, or reinstall @deadbolt/cli." >&2
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
node "$package/postinstall.mjs" >&2
|
|
22
|
+
if [ -L "$package/bin/deadbolt" ]; then
|
|
16
23
|
exec "$package/bin/deadbolt" "$@"
|
|
17
24
|
fi
|
|
18
|
-
echo "Error: @deadbolt/cli'
|
|
19
|
-
echo "" >&2
|
|
20
|
-
echo "Run \`node $package/postinstall.mjs\`, or reinstall with install scripts enabled." >&2
|
|
25
|
+
echo "Error: @deadbolt/cli isn't fully installed: this platform's package couldn't be installed (above)." >&2
|
|
26
|
+
echo "If @deadbolt/cli was just released, npm may not serve it yet; run deadbolt again in a few minutes." >&2
|
|
21
27
|
exit 1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deadbolt/cli",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-145",
|
|
4
4
|
"description": "Deadbolt, a local-first password manager: the CLI, with the desktop app built in.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"homepage": "https://deadbolt.pw",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"x64"
|
|
27
27
|
],
|
|
28
28
|
"optionalDependencies": {
|
|
29
|
-
"@deadbolt/cli-linux-x64": "0.0.0-dev-
|
|
30
|
-
"@deadbolt/cli-linux-arm64": "0.0.0-dev-
|
|
31
|
-
"@deadbolt/cli-linux-x64-musl": "0.0.0-dev-
|
|
32
|
-
"@deadbolt/cli-linux-arm64-musl": "0.0.0-dev-
|
|
33
|
-
"@deadbolt/cli-darwin-arm64": "0.0.0-dev-
|
|
34
|
-
"@deadbolt/cli-darwin-x64": "0.0.0-dev-
|
|
29
|
+
"@deadbolt/cli-linux-x64": "0.0.0-dev-145",
|
|
30
|
+
"@deadbolt/cli-linux-arm64": "0.0.0-dev-145",
|
|
31
|
+
"@deadbolt/cli-linux-x64-musl": "0.0.0-dev-145",
|
|
32
|
+
"@deadbolt/cli-linux-arm64-musl": "0.0.0-dev-145",
|
|
33
|
+
"@deadbolt/cli-darwin-arm64": "0.0.0-dev-145",
|
|
34
|
+
"@deadbolt/cli-darwin-x64": "0.0.0-dev-145"
|
|
35
35
|
}
|
|
36
36
|
}
|
package/postinstall.mjs
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
// are one install, and `deadbolt app` opens that Deadbolt.app. Links, never
|
|
7
7
|
// copies: Deadbolt knows its own files by real path (the Touch ID helper
|
|
8
8
|
// beside it, the app around it).
|
|
9
|
+
//
|
|
10
|
+
// It never fails the install: a package manager that sees a failed script
|
|
11
|
+
// removes the package, and with it the user's `deadbolt`. When it can't link
|
|
12
|
+
// (npm doesn't serve this platform's package yet, say), it says so and leaves
|
|
13
|
+
// the placeholder bin/deadbolt, which runs this again on first use.
|
|
9
14
|
|
|
10
15
|
import childProcess from "node:child_process"
|
|
11
16
|
import fs from "node:fs"
|
|
@@ -21,26 +26,32 @@ const target = path.join(directory, "bin", "deadbolt")
|
|
|
21
26
|
const dependencies = packageJson.optionalDependencies ?? {}
|
|
22
27
|
const platform = { darwin: "darwin", linux: "linux" }[os.platform()]
|
|
23
28
|
const arch = { x64: "x64", arm64: "arm64" }[os.arch()]
|
|
24
|
-
if (!platform || !arch) throw new Error(`Deadbolt has no build for ${os.platform()}-${os.arch()}`)
|
|
25
29
|
const base = `@deadbolt/cli-${platform}-${arch}`
|
|
26
30
|
const npm = process.env.npm_execpath?.endsWith("npm-cli.js") ? [process.execPath, process.env.npm_execpath] : ["npm"]
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
// The system's libc, as the install script tells it: musl (Alpine,
|
|
33
|
+
// /lib/ld-musl-*, or `ldd --version` says so), glibc older than 2.28 (too old
|
|
34
|
+
// for the build with the app), else glibc.
|
|
35
|
+
function libc() {
|
|
36
|
+
if (fs.existsSync("/etc/alpine-release")) return "musl"
|
|
30
37
|
try {
|
|
31
|
-
if (fs.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
if (fs.readdirSync("/lib").some((name) => name.startsWith("ld-musl-"))) return "musl"
|
|
39
|
+
} catch {}
|
|
40
|
+
const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
|
|
41
|
+
const text = `${result.stdout || ""}${result.stderr || ""}`
|
|
42
|
+
if (text.toLowerCase().includes("musl")) return "musl"
|
|
43
|
+
const version = text.split("\n")[0].trim().match(/(\d+)\.(\d+)$/)
|
|
44
|
+
if (version && (Number(version[1]) < 2 || (Number(version[1]) === 2 && Number(version[2]) < 28))) return "old-glibc"
|
|
45
|
+
return "glibc"
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
//
|
|
41
|
-
//
|
|
48
|
+
// On glibc only the build with the app: never the static build quietly in
|
|
49
|
+
// its place. On musl the static build, else the glibc one (which runs where
|
|
50
|
+
// glibc compatibility is installed); on a glibc older than 2.28 only the
|
|
51
|
+
// static build.
|
|
42
52
|
function packageNames() {
|
|
43
|
-
|
|
53
|
+
if (platform !== "linux") return [base]
|
|
54
|
+
const names = { musl: [`${base}-musl`, base], "old-glibc": [`${base}-musl`], glibc: [base] }[libc()]
|
|
44
55
|
return names.filter((name) => dependencies[name])
|
|
45
56
|
}
|
|
46
57
|
|
|
@@ -51,11 +62,19 @@ function binaryIn(packageDir) {
|
|
|
51
62
|
return fs.existsSync(helper) ? helper : path.join(packageDir, "bin", "deadbolt")
|
|
52
63
|
}
|
|
53
64
|
|
|
65
|
+
// Links bin/deadbolt to `source` once a link beside it runs, so a build that
|
|
66
|
+
// doesn't run here never replaces the placeholder.
|
|
54
67
|
function link(source) {
|
|
55
68
|
if (!fs.existsSync(source)) throw new Error(`Binary not found at ${source}`)
|
|
69
|
+
const staged = `${target}.link`
|
|
56
70
|
fs.mkdirSync(path.dirname(target), { recursive: true })
|
|
57
|
-
fs.rmSync(
|
|
58
|
-
fs.symlinkSync(path.relative(path.dirname(target), source),
|
|
71
|
+
fs.rmSync(staged, { force: true })
|
|
72
|
+
fs.symlinkSync(path.relative(path.dirname(target), source), staged)
|
|
73
|
+
if (childProcess.spawnSync(staged, ["--version"], { stdio: "ignore" }).status !== 0) {
|
|
74
|
+
fs.rmSync(staged, { force: true })
|
|
75
|
+
throw new Error(`${source} doesn't run here`)
|
|
76
|
+
}
|
|
77
|
+
fs.renameSync(staged, target)
|
|
59
78
|
}
|
|
60
79
|
|
|
61
80
|
function resolvePackage(name) {
|
|
@@ -94,40 +113,28 @@ function installPackage(name) {
|
|
|
94
113
|
return true
|
|
95
114
|
}
|
|
96
115
|
|
|
97
|
-
function verify() {
|
|
98
|
-
return childProcess.spawnSync(target, ["--version"], { stdio: "ignore" }).status === 0
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Says so when this system's first choice wasn't installable (a registry
|
|
102
|
-
// that doesn't serve the new version yet, say) and another build stands in:
|
|
103
|
-
// on glibc that's the static build, which has no desktop app.
|
|
104
|
-
function fellBack(name, names) {
|
|
105
|
-
if (name === names[0]) return
|
|
106
|
-
console.error(
|
|
107
|
-
`deadbolt: installed ${name}, as ${names[0]}@${dependencies[names[0]]} couldn't be installed` +
|
|
108
|
-
(name.endsWith("-musl") ? " (this build has no desktop app)" : "") +
|
|
109
|
-
`. Reinstall @deadbolt/cli later to get ${names[0]}.`,
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
116
|
function main() {
|
|
117
|
+
if (!platform || !arch) return `Deadbolt has no build for ${os.platform()}-${os.arch()}`
|
|
114
118
|
const names = packageNames()
|
|
115
119
|
for (const name of names) {
|
|
116
120
|
try {
|
|
117
|
-
link(binaryIn(resolvePackage(name)))
|
|
118
|
-
if (verify()) return fellBack(name, names)
|
|
121
|
+
return link(binaryIn(resolvePackage(name)))
|
|
119
122
|
} catch {
|
|
120
|
-
|
|
123
|
+
try {
|
|
124
|
+
if (installPackage(name)) return
|
|
125
|
+
} catch {}
|
|
121
126
|
}
|
|
122
127
|
}
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
const wanted = names.map((name) => `${name}@${dependencies[name]}`).join(" or ") || `a package for ${base}`
|
|
129
|
+
return (
|
|
130
|
+
`couldn't install ${wanted}; if it was just released, npm may not serve it yet. ` +
|
|
131
|
+
"`deadbolt` finishes this when it next runs, or reinstall @deadbolt/cli."
|
|
125
132
|
)
|
|
126
133
|
}
|
|
127
134
|
|
|
128
135
|
try {
|
|
129
|
-
main()
|
|
136
|
+
const problem = main()
|
|
137
|
+
if (problem) console.error(`deadbolt: ${problem}`)
|
|
130
138
|
} catch (error) {
|
|
131
|
-
console.error(error instanceof Error ? error.message : String(error))
|
|
132
|
-
process.exit(1)
|
|
139
|
+
console.error(`deadbolt: ${error instanceof Error ? error.message : String(error)}`)
|
|
133
140
|
}
|