@windagency/valora 2.1.1 → 2.1.3

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.
@@ -0,0 +1,281 @@
1
+ #!/usr/bin/env bash
2
+ # install-tools.sh — Install modern CLI toolkit components
3
+ # Usage:
4
+ # bash install-tools.sh [tool1] [tool2] ...
5
+ # bash install-tools.sh --all
6
+ # bash install-tools.sh --check
7
+ #
8
+ # Supported tools: jq, yq, rg, fd, fzf, lazygit, zoxide, eza
9
+
10
+ set -euo pipefail
11
+
12
+ # ── Versions (pinned for reproducibility) ───────────────────────────────────
13
+ JQ_VERSION="1.7.1"
14
+ YQ_VERSION="4.44.1"
15
+ RG_VERSION="14.1.1"
16
+ FD_VERSION="10.2.0"
17
+ FZF_VERSION="0.57.0"
18
+ LAZYGIT_VERSION="0.44.1"
19
+ ZOXIDE_VERSION="0.9.6"
20
+ EZA_VERSION="0.20.12"
21
+
22
+ # ── Platform detection ──────────────────────────────────────────────────────
23
+ OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
24
+ ARCH="$(uname -m)"
25
+
26
+ case "$ARCH" in
27
+ x86_64) ARCH_ALT="amd64"; ARCH_RG="x86_64" ;;
28
+ aarch64|arm64) ARCH_ALT="arm64"; ARCH_RG="aarch64" ;;
29
+ *) echo "Unsupported architecture: $ARCH"; exit 1 ;;
30
+ esac
31
+
32
+ case "$OS" in
33
+ linux) OS_ALT="linux"; OS_RG="linux" ;;
34
+ darwin) OS_ALT="darwin"; OS_RG="apple-darwin" ;;
35
+ *) echo "Unsupported OS: $OS"; exit 1 ;;
36
+ esac
37
+
38
+ INSTALL_DIR="${INSTALL_DIR:-${HOME}/.local/bin}"
39
+ mkdir -p "$INSTALL_DIR"
40
+
41
+ # Ensure install dir is on PATH for the duration of this script
42
+ if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
43
+ export PATH="$INSTALL_DIR:$PATH"
44
+ # Only persist to .bashrc when using the default home directory location
45
+ if [[ "$INSTALL_DIR" == "${HOME}/.local/bin" ]]; then
46
+ echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> "${HOME}/.bashrc" 2>/dev/null || true
47
+ fi
48
+ fi
49
+
50
+ TMP_DIR=$(mktemp -d)
51
+ trap 'rm -rf "$TMP_DIR"' EXIT
52
+
53
+ # ── Helper functions ────────────────────────────────────────────────────────
54
+ installed() { command -v "$1" >/dev/null 2>&1; }
55
+
56
+ download() {
57
+ local url="$1" dest="$2"
58
+ if installed curl; then
59
+ curl -fsSL "$url" -o "$dest"
60
+ elif installed wget; then
61
+ wget -q "$url" -O "$dest"
62
+ else
63
+ echo "Neither curl nor wget found"; exit 1
64
+ fi
65
+ }
66
+
67
+ # ── Package manager detection ───────────────────────────────────────────────
68
+ HAS_APT=false
69
+ HAS_BREW=false
70
+ if installed apt-get; then HAS_APT=true; fi
71
+ if installed brew; then HAS_BREW=true; fi
72
+
73
+ apt_install() {
74
+ sudo apt-get install -y "$@" >/dev/null 2>&1
75
+ }
76
+
77
+ # ── Tool installers ────────────────────────────────────────────────────────
78
+ # Strategy: try system package manager first (fast, reliable), fall back to
79
+ # GitHub releases if unavailable or if we need a specific version.
80
+
81
+ install_jq() {
82
+ if installed jq; then echo "jq: already installed ($(jq --version))"; return; fi
83
+ echo "Installing jq..."
84
+ if $HAS_APT; then
85
+ apt_install jq
86
+ elif $HAS_BREW; then
87
+ brew install jq >/dev/null 2>&1
88
+ else
89
+ local bin="jq-${OS_ALT}-${ARCH_ALT}"
90
+ [[ "$OS" == "darwin" ]] && bin="jq-macos-${ARCH_ALT}"
91
+ download "https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/${bin}" "$INSTALL_DIR/jq"
92
+ chmod +x "$INSTALL_DIR/jq"
93
+ fi
94
+ echo "jq: installed → $(jq --version)"
95
+ }
96
+
97
+ install_yq() {
98
+ if installed yq; then echo "yq: already installed ($(yq --version 2>&1 | head -1))"; return; fi
99
+ echo "Installing yq..."
100
+ local bin="yq_${OS_ALT}_${ARCH_ALT}"
101
+ download "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/${bin}" "$INSTALL_DIR/yq"
102
+ chmod +x "$INSTALL_DIR/yq"
103
+ echo "yq: installed → $(yq --version 2>&1 | head -1)"
104
+ }
105
+
106
+ install_rg() {
107
+ if installed rg; then echo "rg: already installed ($(rg --version | head -1))"; return; fi
108
+ echo "Installing ripgrep..."
109
+ if $HAS_APT; then
110
+ apt_install ripgrep
111
+ elif $HAS_BREW; then
112
+ brew install ripgrep >/dev/null 2>&1
113
+ else
114
+ local archive="ripgrep-${RG_VERSION}-${ARCH_RG}-unknown-${OS_RG}-musl.tar.gz"
115
+ [[ "$OS" == "darwin" ]] && archive="ripgrep-${RG_VERSION}-${ARCH_RG}-${OS_RG}.tar.gz"
116
+ download "https://github.com/BurntSushi/ripgrep/releases/download/${RG_VERSION}/${archive}" "$TMP_DIR/rg.tar.gz"
117
+ tar xzf "$TMP_DIR/rg.tar.gz" -C "$TMP_DIR"
118
+ cp "$TMP_DIR"/ripgrep-*/rg "$INSTALL_DIR/rg"
119
+ chmod +x "$INSTALL_DIR/rg"
120
+ fi
121
+ echo "rg: installed → $(rg --version | head -1)"
122
+ }
123
+
124
+ install_fd() {
125
+ if installed fd || installed fdfind; then
126
+ local fd_cmd="fd"; installed fdfind && fd_cmd="fdfind"
127
+ echo "fd: already installed ($($fd_cmd --version))"; return
128
+ fi
129
+ echo "Installing fd..."
130
+ if $HAS_APT; then
131
+ apt_install fd-find
132
+ # On Debian/Ubuntu, the binary is called fdfind to avoid conflict
133
+ if installed fdfind && ! installed fd; then
134
+ ln -sf "$(which fdfind)" "$INSTALL_DIR/fd"
135
+ fi
136
+ elif $HAS_BREW; then
137
+ brew install fd >/dev/null 2>&1
138
+ else
139
+ local archive="fd-v${FD_VERSION}-${ARCH_RG}-unknown-${OS_RG}-musl.tar.gz"
140
+ [[ "$OS" == "darwin" ]] && archive="fd-v${FD_VERSION}-${ARCH_RG}-${OS_RG}.tar.gz"
141
+ download "https://github.com/sharkdp/fd/releases/download/v${FD_VERSION}/${archive}" "$TMP_DIR/fd.tar.gz"
142
+ tar xzf "$TMP_DIR/fd.tar.gz" -C "$TMP_DIR"
143
+ cp "$TMP_DIR"/fd-v*/fd "$INSTALL_DIR/fd"
144
+ chmod +x "$INSTALL_DIR/fd"
145
+ fi
146
+ local fd_cmd="fd"; installed fdfind && ! installed fd && fd_cmd="fdfind"
147
+ echo "fd: installed → $($fd_cmd --version)"
148
+ }
149
+
150
+ install_fzf() {
151
+ if installed fzf; then echo "fzf: already installed ($(fzf --version | head -1))"; return; fi
152
+ echo "Installing fzf..."
153
+ if $HAS_APT; then
154
+ apt_install fzf
155
+ elif $HAS_BREW; then
156
+ brew install fzf >/dev/null 2>&1
157
+ else
158
+ local archive="fzf-${FZF_VERSION}-${OS_ALT}_${ARCH_ALT}.tar.gz"
159
+ download "https://github.com/junegunn/fzf/releases/download/v${FZF_VERSION}/${archive}" "$TMP_DIR/fzf.tar.gz"
160
+ tar xzf "$TMP_DIR/fzf.tar.gz" -C "$TMP_DIR"
161
+ cp "$TMP_DIR/fzf" "$INSTALL_DIR/fzf"
162
+ chmod +x "$INSTALL_DIR/fzf"
163
+ fi
164
+ echo "fzf: installed → $(fzf --version | head -1)"
165
+ }
166
+
167
+ install_lazygit() {
168
+ if installed lazygit; then echo "lazygit: already installed ($(lazygit --version | head -1))"; return; fi
169
+ echo "Installing lazygit..."
170
+ local lg_os="Linux" lg_arch="x86_64"
171
+ [[ "$OS" == "darwin" ]] && lg_os="Darwin"
172
+ [[ "$ARCH_ALT" == "arm64" ]] && lg_arch="arm64"
173
+ local archive="lazygit_${LAZYGIT_VERSION}_${lg_os}_${lg_arch}.tar.gz"
174
+ download "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/${archive}" "$TMP_DIR/lazygit.tar.gz"
175
+ tar xzf "$TMP_DIR/lazygit.tar.gz" -C "$TMP_DIR"
176
+ cp "$TMP_DIR/lazygit" "$INSTALL_DIR/lazygit"
177
+ chmod +x "$INSTALL_DIR/lazygit"
178
+ echo "lazygit: installed → $(lazygit --version | head -1)"
179
+ }
180
+
181
+ install_zoxide() {
182
+ if installed zoxide; then echo "zoxide: already installed ($(zoxide --version))"; return; fi
183
+ echo "Installing zoxide..."
184
+ if $HAS_APT && [[ "$(lsb_release -rs 2>/dev/null)" > "23" ]]; then
185
+ apt_install zoxide
186
+ else
187
+ local archive="zoxide-${ZOXIDE_VERSION}-${ARCH_RG}-unknown-${OS_RG}-musl.tar.gz"
188
+ [[ "$OS" == "darwin" ]] && archive="zoxide-${ZOXIDE_VERSION}-${ARCH_RG}-${OS_RG}.tar.gz"
189
+ download "https://github.com/ajeetdsouza/zoxide/releases/download/v${ZOXIDE_VERSION}/${archive}" "$TMP_DIR/zoxide.tar.gz"
190
+ tar xzf "$TMP_DIR/zoxide.tar.gz" -C "$TMP_DIR"
191
+ cp "$TMP_DIR/zoxide" "$INSTALL_DIR/zoxide"
192
+ chmod +x "$INSTALL_DIR/zoxide"
193
+ fi
194
+ echo "zoxide: installed → $(zoxide --version)"
195
+ }
196
+
197
+ install_eza() {
198
+ if installed eza; then echo "eza: already installed ($(eza --version | head -1))"; return; fi
199
+ echo "Installing eza..."
200
+ if $HAS_APT; then
201
+ # eza needs its own repo on older Ubuntu
202
+ if ! apt_install eza; then
203
+ local eza_arch="x86_64"
204
+ [[ "$ARCH_ALT" == "arm64" ]] && eza_arch="aarch64"
205
+ local archive="eza_${eza_arch}-unknown-${OS_RG}-musl.tar.gz"
206
+ [[ "$OS" == "darwin" ]] && archive="eza_${eza_arch}-${OS_RG}.tar.gz"
207
+ download "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/${archive}" "$TMP_DIR/eza.tar.gz"
208
+ tar xzf "$TMP_DIR/eza.tar.gz" -C "$TMP_DIR"
209
+ find "$TMP_DIR" -name 'eza' -type f -exec cp {} "$INSTALL_DIR/eza" \;
210
+ chmod +x "$INSTALL_DIR/eza"
211
+ fi
212
+ elif $HAS_BREW; then
213
+ brew install eza >/dev/null 2>&1
214
+ else
215
+ local eza_arch="x86_64"
216
+ [[ "$ARCH_ALT" == "arm64" ]] && eza_arch="aarch64"
217
+ local archive="eza_${eza_arch}-unknown-${OS_RG}-musl.tar.gz"
218
+ [[ "$OS" == "darwin" ]] && archive="eza_${eza_arch}-${OS_RG}.tar.gz"
219
+ download "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/${archive}" "$TMP_DIR/eza.tar.gz"
220
+ tar xzf "$TMP_DIR/eza.tar.gz" -C "$TMP_DIR"
221
+ find "$TMP_DIR" -name 'eza' -type f -exec cp {} "$INSTALL_DIR/eza" \;
222
+ chmod +x "$INSTALL_DIR/eza"
223
+ fi
224
+ echo "eza: installed → $(eza --version | head -1)"
225
+ }
226
+
227
+ # ── Main ────────────────────────────────────────────────────────────────────
228
+
229
+ ALL_TOOLS=(jq yq rg fd fzf lazygit zoxide eza)
230
+
231
+ check_tools() {
232
+ echo "Tool availability:"
233
+ for tool in "${ALL_TOOLS[@]}"; do
234
+ if installed "$tool"; then
235
+ local ver
236
+ case "$tool" in
237
+ jq) ver=$(jq --version 2>&1) ;;
238
+ yq) ver=$(yq --version 2>&1 | head -1) ;;
239
+ rg) ver=$(rg --version 2>&1 | head -1) ;;
240
+ fd) ver=$(fd --version 2>&1) ;;
241
+ fzf) ver=$(fzf --version 2>&1 | head -1) ;;
242
+ lazygit) ver=$(lazygit --version 2>&1 | head -1) ;;
243
+ zoxide) ver=$(zoxide --version 2>&1) ;;
244
+ eza) ver=$(eza --version 2>&1 | head -1) ;;
245
+ esac
246
+ echo " ✓ $tool: $ver"
247
+ else
248
+ echo " ✗ $tool: not installed"
249
+ fi
250
+ done
251
+ }
252
+
253
+ if [[ $# -eq 0 ]]; then
254
+ echo "Usage: $0 [--all | --check | tool1 tool2 ...]"
255
+ echo "Tools: ${ALL_TOOLS[*]}"
256
+ exit 0
257
+ fi
258
+
259
+ case "$1" in
260
+ --check) check_tools; exit 0 ;;
261
+ --all) TOOLS=("${ALL_TOOLS[@]}") ;;
262
+ *) TOOLS=("$@") ;;
263
+ esac
264
+
265
+ for tool in "${TOOLS[@]}"; do
266
+ case "$tool" in
267
+ jq) install_jq ;;
268
+ yq) install_yq ;;
269
+ rg) install_rg ;;
270
+ fd) install_fd ;;
271
+ fzf) install_fzf ;;
272
+ lazygit) install_lazygit ;;
273
+ zoxide) install_zoxide ;;
274
+ eza) install_eza ;;
275
+ *) echo "Unknown tool: $tool (supported: ${ALL_TOOLS[*]})"; exit 1 ;;
276
+ esac
277
+ done
278
+
279
+ echo ""
280
+ echo "Installation complete. Tools are in: $INSTALL_DIR"
281
+ echo "Run '$0 --check' to verify."
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Valora postinstall — embeds required CLI tools into the package installation.
4
+ *
5
+ * Runs automatically after `pnpm add -g @windagency/valora` (or npm/yarn).
6
+ * Installs pinned versions of jq, yq, rg, fd, fzf, lazygit, zoxide, eza into
7
+ * the package's own vendor/bin directory so valora never relies on the system
8
+ * having these tools pre-installed.
9
+ *
10
+ * Skipped when:
11
+ * - Not a global install (CI, local dependency installs, dev workspace)
12
+ * - CI environment variable is set
13
+ * - SKIP_POSTINSTALL environment variable is set
14
+ */
15
+
16
+ import { execSync } from 'child_process';
17
+ import { existsSync, mkdirSync } from 'fs';
18
+ import { dirname, join } from 'path';
19
+ import { fileURLToPath } from 'url';
20
+
21
+ const __dirname = dirname(fileURLToPath(import.meta.url));
22
+ const packageRoot = join(__dirname, '..');
23
+ const vendorBin = join(packageRoot, 'vendor', 'bin');
24
+ const installScript = join(__dirname, 'install-cli-tools.sh');
25
+
26
+ // Skip in CI environments
27
+ if (process.env.CI) {
28
+ console.log('[valora] Skipping CLI tools installation (CI environment)');
29
+ process.exit(0);
30
+ }
31
+
32
+ // Skip if explicitly disabled
33
+ if (process.env.SKIP_POSTINSTALL) {
34
+ console.log('[valora] Skipping CLI tools installation (SKIP_POSTINSTALL set)');
35
+ process.exit(0);
36
+ }
37
+
38
+ // Only run for global installs — not when valora is a local dependency or
39
+ // when developers run `pnpm install` inside the source repository.
40
+ if (process.env.npm_config_global !== 'true') {
41
+ process.exit(0);
42
+ }
43
+
44
+ if (!existsSync(installScript)) {
45
+ console.warn('[valora] CLI tools install script not found, skipping');
46
+ process.exit(0);
47
+ }
48
+
49
+ mkdirSync(vendorBin, { recursive: true });
50
+
51
+ console.log(`[valora] Installing bundled CLI tools into ${vendorBin} ...`);
52
+ try {
53
+ execSync(`bash "${installScript}" --all`, {
54
+ env: { ...process.env, INSTALL_DIR: vendorBin },
55
+ stdio: 'inherit'
56
+ });
57
+ console.log('[valora] CLI tools installed successfully.');
58
+ } catch {
59
+ console.warn(
60
+ '[valora] Warning: some CLI tools could not be installed. ' +
61
+ 'Valora will fall back to system tools or built-in equivalents.'
62
+ );
63
+ }