@git.zone/cli 2.20.0 → 2.21.0

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,506 @@
1
+ #!/bin/bash
2
+ # Managed by @git.zone/cli from assets/templates/asset_deno_binary_installer. Do not edit by hand.
3
+
4
+ set -euo pipefail
5
+
6
+ SHOW_HELP=0
7
+ SPECIFIED_VERSION=""
8
+ SPECIFIED_MAJOR=""
9
+ INSTALL_DIR="{{installer.installDir}}"
10
+ BIN_DIR="{{installer.binDir}}"
11
+ INSTALL_MODE="{{installer.defaultMode}}"
12
+ GITEA_BASE_URL="https://{{repository.host}}"
13
+ GITEA_REPO="{{repository.path}}"
14
+ REPO_URL="{{{repository.gitUrl}}}"
15
+ SERVICE_RESTART_NAME="{{installer.service.restartName}}"
16
+ PRIMARY_PRESERVE_PATH="{{installer.primaryPreservePath}}"
17
+
18
+ SERVICE_NAMES=(
19
+ {{#each installer.service.detectNames}}
20
+ "{{this}}"
21
+ {{/each}}
22
+ )
23
+
24
+ LEGACY_SERVICE_NAMES=(
25
+ {{#each installer.service.removeLegacyUnits}}
26
+ "{{this}}"
27
+ {{/each}}
28
+ )
29
+
30
+ while [[ $# -gt 0 ]]; do
31
+ case "$1" in
32
+ -h|--help)
33
+ SHOW_HELP=1
34
+ shift
35
+ ;;
36
+ --version)
37
+ if [[ $# -lt 2 ]]; then
38
+ echo "Error: --version requires a value"
39
+ exit 1
40
+ fi
41
+ SPECIFIED_VERSION="$2"
42
+ shift 2
43
+ ;;
44
+ {{#if installer.supportsMajor}}
45
+ --major)
46
+ if [[ $# -lt 2 ]]; then
47
+ echo "Error: --major requires a value"
48
+ exit 1
49
+ fi
50
+ SPECIFIED_MAJOR="${2#v}"
51
+ shift 2
52
+ ;;
53
+ {{/if}}
54
+ --install-dir)
55
+ if [[ $# -lt 2 ]]; then
56
+ echo "Error: --install-dir requires a value"
57
+ exit 1
58
+ fi
59
+ INSTALL_DIR="$2"
60
+ shift 2
61
+ ;;
62
+ {{#if installer.source.enabled}}
63
+ --binary)
64
+ INSTALL_MODE="binary"
65
+ shift
66
+ ;;
67
+ --source)
68
+ INSTALL_MODE="source"
69
+ shift
70
+ ;;
71
+ {{/if}}
72
+ *)
73
+ echo "Unknown option: $1"
74
+ echo "Use -h or --help for usage information"
75
+ exit 1
76
+ ;;
77
+ esac
78
+ done
79
+
80
+ if [[ $SHOW_HELP -eq 1 ]]; then
81
+ echo "{{displayName}} Installer Script"
82
+ echo "Downloads and installs pre-compiled {{displayName}} release binaries."
83
+ echo ""
84
+ echo "Usage: $0 [options]"
85
+ echo ""
86
+ echo "Options:"
87
+ echo " -h, --help Show this help message"
88
+ echo " --version VERSION Install a specific tag/version (e.g. vX.Y.Z)"
89
+ {{#if installer.supportsMajor}}
90
+ echo " --major MAJOR Install latest release for a major version (e.g. 1)"
91
+ {{/if}}
92
+ echo " --install-dir DIR Installation directory (default: {{installer.installDir}})"
93
+ {{#if installer.source.enabled}}
94
+ echo " --binary Install release binary (default)"
95
+ echo " --source Clone the tag and build from source locally"
96
+ {{/if}}
97
+ echo ""
98
+ echo "Examples:"
99
+ echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash"
100
+ echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash -s -- --version vX.Y.Z"
101
+ {{#if installer.supportsMajor}}
102
+ echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash -s -- --major 1"
103
+ {{/if}}
104
+ {{#if installer.source.enabled}}
105
+ echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash -s -- --source"
106
+ {{/if}}
107
+ exit 0
108
+ fi
109
+
110
+ if [[ -n "$SPECIFIED_VERSION" && -n "$SPECIFIED_MAJOR" ]]; then
111
+ echo "Error: --version and --major are mutually exclusive"
112
+ exit 1
113
+ fi
114
+
115
+ if [[ -n "$SPECIFIED_MAJOR" && ! "$SPECIFIED_MAJOR" =~ ^[0-9]+$ ]]; then
116
+ echo "Error: --major must be a numeric major version, for example: --major 1"
117
+ exit 1
118
+ fi
119
+
120
+ if [[ "$EUID" -ne 0 ]]; then
121
+ echo "Please run as root (sudo bash install.sh or pipe to sudo bash)"
122
+ exit 1
123
+ fi
124
+
125
+ case "$INSTALL_DIR" in
126
+ ""|"/")
127
+ echo "Error: unsafe install directory: $INSTALL_DIR"
128
+ exit 1
129
+ ;;
130
+ esac
131
+
132
+ require_command() {
133
+ if ! command -v "$1" >/dev/null 2>&1; then
134
+ echo "Error: required command not found: $1"
135
+ exit 1
136
+ fi
137
+ }
138
+
139
+ ensure_pnpm() {
140
+ if command -v pnpm >/dev/null 2>&1; then
141
+ return
142
+ fi
143
+ if command -v corepack >/dev/null 2>&1; then
144
+ corepack enable
145
+ fi
146
+ if ! command -v pnpm >/dev/null 2>&1; then
147
+ echo "Error: pnpm is required for source installs. Install Node.js with corepack/pnpm first."
148
+ exit 1
149
+ fi
150
+ }
151
+
152
+ get_latest_version() {
153
+ echo "Fetching latest release version from Gitea..." >&2
154
+ local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases/latest"
155
+ local response
156
+ if ! response=$(curl -fsSL "$api_url" 2>/dev/null); then
157
+ echo "Error: Failed to fetch latest release information from Gitea API" >&2
158
+ echo "URL: $api_url" >&2
159
+ exit 1
160
+ fi
161
+
162
+ local version
163
+ version=$(printf '%s' "$response" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
164
+ if [[ -z "$version" ]]; then
165
+ echo "Error: Could not determine latest version from API response" >&2
166
+ exit 1
167
+ fi
168
+ echo "$version"
169
+ }
170
+
171
+ {{#if installer.supportsMajor}}
172
+ get_latest_major_version() {
173
+ local major="$1"
174
+ echo "Fetching latest v${major}.x release version from Gitea..." >&2
175
+ local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases?limit=50"
176
+ local response
177
+ if ! response=$(curl -fsSL "$api_url" 2>/dev/null); then
178
+ echo "Error: Failed to fetch release list from Gitea API" >&2
179
+ echo "URL: $api_url" >&2
180
+ exit 1
181
+ fi
182
+
183
+ local version
184
+ version=$(printf '%s' "$response" | grep -o '"tag_name":"v'"${major}"'\.[^"]*"' | cut -d'"' -f4 | head -n 1)
185
+ if [[ -z "$version" ]]; then
186
+ echo "Error: Could not determine latest v${major}.x version from API response" >&2
187
+ exit 1
188
+ fi
189
+ echo "$version"
190
+ }
191
+
192
+ {{/if}}
193
+ detect_binary_name() {
194
+ local os
195
+ local arch
196
+ local os_name
197
+ local arch_name
198
+ os=$(uname -s)
199
+ arch=$(uname -m)
200
+
201
+ case "$os" in
202
+ Linux) os_name="linux" ;;
203
+ Darwin) os_name="macos" ;;
204
+ MINGW*|MSYS*|CYGWIN*) os_name="windows" ;;
205
+ *)
206
+ echo "Error: Unsupported operating system: $os" >&2
207
+ echo "Supported platforms: {{binary.supportedPlatformText}}" >&2
208
+ {{#if installer.source.enabled}}
209
+ echo "Use --source to build locally on this platform." >&2
210
+ {{/if}}
211
+ exit 1
212
+ ;;
213
+ esac
214
+
215
+ case "$arch" in
216
+ x86_64|amd64) arch_name="x64" ;;
217
+ aarch64|arm64) arch_name="arm64" ;;
218
+ *)
219
+ echo "Error: Unsupported architecture: $arch" >&2
220
+ echo "Supported platforms: {{binary.supportedPlatformText}}" >&2
221
+ {{#if installer.source.enabled}}
222
+ echo "Use --source to build locally on this architecture." >&2
223
+ {{/if}}
224
+ exit 1
225
+ ;;
226
+ esac
227
+
228
+ case "${os_name}-${arch_name}" in
229
+ {{#each binary.targets}}
230
+ {{os}}-{{arch}}) echo "{{assetName}}" ;;
231
+ {{/each}}
232
+ *)
233
+ echo "Error: Unsupported platform: ${os_name}-${arch_name}" >&2
234
+ echo "Supported platforms: {{binary.supportedPlatformText}}" >&2
235
+ {{#if installer.source.enabled}}
236
+ echo "Use --source to build locally on this platform." >&2
237
+ {{/if}}
238
+ exit 1
239
+ ;;
240
+ esac
241
+ }
242
+
243
+ echo "================================================"
244
+ echo " {{displayName}} Installation Script"
245
+ echo "================================================"
246
+ echo ""
247
+
248
+ require_command curl
249
+ require_command sed
250
+
251
+ if [[ -n "$SPECIFIED_VERSION" ]]; then
252
+ VERSION="$SPECIFIED_VERSION"
253
+ echo "Installing specified version: $VERSION"
254
+ {{#if installer.supportsMajor}}
255
+ elif [[ -n "$SPECIFIED_MAJOR" ]]; then
256
+ VERSION=$(get_latest_major_version "$SPECIFIED_MAJOR")
257
+ echo "Installing latest v${SPECIFIED_MAJOR}.x version: $VERSION"
258
+ {{/if}}
259
+ else
260
+ VERSION=$(get_latest_version)
261
+ echo "Installing latest version: $VERSION"
262
+ fi
263
+ echo "Install mode: $INSTALL_MODE"
264
+ echo ""
265
+
266
+ TEMP_DIR=$(mktemp -d)
267
+ SOURCE_DIR="$TEMP_DIR/source"
268
+ BACKUP_DIR=""
269
+ SERVICE_WAS_RUNNING=0
270
+ SERVICE_STOPPED=0
271
+ SYSTEMD_AVAILABLE=0
272
+ PRESERVE_PATH_EXISTS=0
273
+
274
+ cleanup_temp() {
275
+ rm -rf "$TEMP_DIR"
276
+ }
277
+ trap cleanup_temp EXIT
278
+
279
+ if command -v systemctl >/dev/null 2>&1; then
280
+ SYSTEMD_AVAILABLE=1
281
+ for service_name in "${SERVICE_NAMES[@]}"; do
282
+ if systemctl is-active --quiet "$service_name" 2>/dev/null; then
283
+ SERVICE_WAS_RUNNING=1
284
+ break
285
+ fi
286
+ done
287
+ fi
288
+
289
+ if [[ -n "$PRIMARY_PRESERVE_PATH" && -e "$PRIMARY_PRESERVE_PATH" ]]; then
290
+ PRESERVE_PATH_EXISTS=1
291
+ fi
292
+
293
+ restore_previous_installation() {
294
+ if [[ -n "$BACKUP_DIR" && -d "$BACKUP_DIR" ]]; then
295
+ echo "Restoring previous installation from $BACKUP_DIR..."
296
+ rm -rf "$INSTALL_DIR" || true
297
+ mv "$BACKUP_DIR" "$INSTALL_DIR" || true
298
+ if [[ -f "$INSTALL_DIR/{{binary.installFileName}}" ]]; then
299
+ mkdir -p "$BIN_DIR" || true
300
+ ln -sf "$INSTALL_DIR/{{binary.installFileName}}" "$BIN_DIR/{{cliName}}" || true
301
+ {{#if installer.source.enabled}}
302
+ elif [[ -f "$INSTALL_DIR/{{installer.source.executable}}" ]]; then
303
+ mkdir -p "$BIN_DIR" || true
304
+ ln -sf "$INSTALL_DIR/{{installer.source.executable}}" "$BIN_DIR/{{cliName}}" || true
305
+ {{/if}}
306
+ fi
307
+ fi
308
+ }
309
+
310
+ restart_previous_service_on_error() {
311
+ if [[ $SERVICE_STOPPED -eq 1 && $SYSTEMD_AVAILABLE -eq 1 && -n "$SERVICE_RESTART_NAME" ]]; then
312
+ echo "Installation failed after stopping {{displayName}}; restarting previous service..."
313
+ systemctl start "$SERVICE_RESTART_NAME" || true
314
+ fi
315
+ }
316
+
317
+ handle_install_error() {
318
+ trap - ERR
319
+ restore_previous_installation
320
+ restart_previous_service_on_error
321
+ }
322
+ trap handle_install_error ERR
323
+
324
+ stop_service_if_running() {
325
+ if [[ $SYSTEMD_AVAILABLE -ne 1 ]]; then
326
+ return
327
+ fi
328
+ for service_name in "${SERVICE_NAMES[@]}"; do
329
+ if systemctl is-active --quiet "$service_name" 2>/dev/null; then
330
+ echo "Stopping service: $service_name"
331
+ systemctl stop "$service_name"
332
+ SERVICE_STOPPED=1
333
+ fi
334
+ done
335
+ }
336
+
337
+ remove_legacy_services() {
338
+ if [[ $SYSTEMD_AVAILABLE -ne 1 ]]; then
339
+ return
340
+ fi
341
+ local needs_reload=0
342
+ for service_name in "${LEGACY_SERVICE_NAMES[@]}"; do
343
+ if systemctl is-enabled --quiet "$service_name" 2>/dev/null \
344
+ || systemctl is-active --quiet "$service_name" 2>/dev/null \
345
+ || systemctl is-failed --quiet "$service_name" 2>/dev/null \
346
+ || [[ -f "/etc/systemd/system/${service_name}.service" ]] \
347
+ || [[ -f "/usr/lib/systemd/system/${service_name}.service" ]] \
348
+ || [[ -f "/lib/systemd/system/${service_name}.service" ]]; then
349
+ echo "Removing legacy service: $service_name"
350
+ if systemctl is-active --quiet "$service_name" 2>/dev/null; then
351
+ systemctl stop "$service_name"
352
+ fi
353
+ systemctl disable "$service_name" 2>/dev/null || true
354
+ systemctl reset-failed "$service_name" 2>/dev/null || true
355
+ rm -f \
356
+ "/etc/systemd/system/${service_name}.service" \
357
+ "/usr/lib/systemd/system/${service_name}.service" \
358
+ "/lib/systemd/system/${service_name}.service"
359
+ needs_reload=1
360
+ fi
361
+ done
362
+ if [[ $needs_reload -eq 1 ]]; then
363
+ systemctl daemon-reload
364
+ fi
365
+ }
366
+
367
+ move_previous_installation() {
368
+ mkdir -p "$(dirname "$INSTALL_DIR")"
369
+ if [[ -d "$INSTALL_DIR" ]]; then
370
+ BACKUP_DIR="${INSTALL_DIR}.previous.$$"
371
+ echo "Moving previous installation to $BACKUP_DIR"
372
+ mv "$INSTALL_DIR" "$BACKUP_DIR"
373
+ fi
374
+ }
375
+
376
+ install_release_binary() {
377
+ local binary_name
378
+ local download_url
379
+ local temp_file
380
+
381
+ binary_name=$(detect_binary_name)
382
+ download_url="${GITEA_BASE_URL}/${GITEA_REPO}/releases/download/${VERSION}/${binary_name}"
383
+ temp_file="$TEMP_DIR/$binary_name"
384
+
385
+ echo "Downloading {{displayName}} binary: $download_url"
386
+ curl -fSL "$download_url" -o "$temp_file"
387
+ chmod 0755 "$temp_file"
388
+
389
+ echo "Validating downloaded binary..."
390
+ "$temp_file" --version >/dev/null
391
+
392
+ stop_service_if_running
393
+ move_previous_installation
394
+
395
+ echo "Installing binary to $INSTALL_DIR"
396
+ mkdir -p "$INSTALL_DIR"
397
+ install -m 0755 "$temp_file" "$INSTALL_DIR/{{binary.installFileName}}"
398
+
399
+ mkdir -p "$BIN_DIR"
400
+ ln -sf "$INSTALL_DIR/{{binary.installFileName}}" "$BIN_DIR/{{cliName}}"
401
+ }
402
+
403
+ {{#if installer.source.enabled}}
404
+ install_source_build() {
405
+ require_command git
406
+ require_command node
407
+ ensure_pnpm
408
+
409
+ echo "Cloning {{displayName}} source from $REPO_URL ($VERSION)..."
410
+ git clone --depth 1 --branch "$VERSION" "$REPO_URL" "$SOURCE_DIR"
411
+
412
+ echo "Building {{displayName}} from source..."
413
+ (
414
+ cd "$SOURCE_DIR"
415
+ {{#each installer.source.commands}}
416
+ {{{this}}}
417
+ {{/each}}
418
+ {{{installer.source.validateCommand}}}
419
+ )
420
+
421
+ stop_service_if_running
422
+ move_previous_installation
423
+
424
+ echo "Installing source build to $INSTALL_DIR"
425
+ mv "$SOURCE_DIR" "$INSTALL_DIR"
426
+ {{#each installer.source.executableFiles}}
427
+ chmod 0755 "$INSTALL_DIR/{{this}}"
428
+ {{/each}}
429
+
430
+ mkdir -p "$BIN_DIR"
431
+ ln -sf "$INSTALL_DIR/{{installer.source.executable}}" "$BIN_DIR/{{cliName}}"
432
+ }
433
+
434
+ {{/if}}
435
+ remove_legacy_services
436
+
437
+ if [[ "$INSTALL_MODE" == "source" ]]; then
438
+ {{#if installer.source.enabled}}
439
+ install_source_build
440
+ {{else}}
441
+ echo "Error: source install mode is not enabled for {{displayName}}"
442
+ exit 1
443
+ {{/if}}
444
+ else
445
+ install_release_binary
446
+ fi
447
+
448
+ echo "Symlink created: $BIN_DIR/{{cliName}}"
449
+
450
+ {{#each installer.ensureDirs}}
451
+ mkdir -p "{{this}}"
452
+ {{/each}}
453
+
454
+ if ! "$BIN_DIR/{{cliName}}" --version >/dev/null; then
455
+ echo "Error: Installed {{displayName}} CLI failed validation"
456
+ restore_previous_installation
457
+ restart_previous_service_on_error
458
+ exit 1
459
+ fi
460
+
461
+ if [[ -n "$BACKUP_DIR" && -d "$BACKUP_DIR" ]]; then
462
+ rm -rf "$BACKUP_DIR"
463
+ fi
464
+
465
+ if [[ $SERVICE_WAS_RUNNING -eq 1 && $SYSTEMD_AVAILABLE -eq 1 ]]; then
466
+ {{#if installer.service.hasRefreshCommand}}
467
+ echo "Refreshing systemd service..."
468
+ {{{installer.service.refreshCommand}}}
469
+ {{/if}}
470
+ if [[ -n "$SERVICE_RESTART_NAME" ]]; then
471
+ echo "Restarting service: $SERVICE_RESTART_NAME"
472
+ systemctl restart "$SERVICE_RESTART_NAME"
473
+ SERVICE_STOPPED=0
474
+ echo "Service restarted successfully."
475
+ echo ""
476
+ fi
477
+ fi
478
+
479
+ trap - ERR
480
+
481
+ echo "================================================"
482
+ echo " {{displayName}} Installation Complete!"
483
+ echo "================================================"
484
+ echo ""
485
+ echo "Installation details:"
486
+ echo " Install directory: $INSTALL_DIR"
487
+ echo " Symlink location: $BIN_DIR/{{cliName}}"
488
+ echo " Version: $VERSION"
489
+ echo " Mode: $INSTALL_MODE"
490
+ echo ""
491
+
492
+ if [[ $PRESERVE_PATH_EXISTS -eq 1 ]]; then
493
+ echo "Existing data/configuration preserved: $PRIMARY_PRESERVE_PATH"
494
+ echo ""
495
+ if [[ $SERVICE_WAS_RUNNING -eq 1 ]]; then
496
+ echo "The service has been restarted with your current settings."
497
+ else
498
+ echo "Start the service with: {{installer.service.startHint}}"
499
+ fi
500
+ else
501
+ echo "Get started:"
502
+ {{#each installer.successHints}}
503
+ echo " {{this}}"
504
+ {{/each}}
505
+ fi
506
+ echo ""
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ // Managed by @git.zone/cli from assets/templates/asset_deno_binary_postinstall. Do not edit by hand.
3
+
4
+ import { arch, platform } from 'node:os';
5
+ import { existsSync } from 'node:fs';
6
+ import { dirname, join } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { spawnSync } from 'node:child_process';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ const BINARY_MAP = new Map([
13
+ {{#each binary.targets}}
14
+ ['{{nodeKey}}', '{{assetName}}'],
15
+ {{/each}}
16
+ ]);
17
+
18
+ const key = `${platform()}:${arch()}`;
19
+ const binaryName = BINARY_MAP.get(key);
20
+ if (!binaryName) {
21
+ console.error(`Unsupported platform/architecture: ${platform()}/${arch()}`);
22
+ process.exit(1);
23
+ }
24
+
25
+ const binaryPath = join(__dirname, '..', '{{{npmWrapper.binariesDir}}}', binaryName);
26
+ if (!existsSync(binaryPath)) {
27
+ console.error('{{displayName}} binary not found. Try reinstalling the package.');
28
+ console.error(`Missing binary: ${binaryPath}`);
29
+ process.exit(1);
30
+ }
31
+
32
+ const result = spawnSync(binaryPath, process.argv.slice(2), { stdio: 'inherit' });
33
+ if (result.error) {
34
+ console.error(result.error.message);
35
+ process.exit(1);
36
+ }
37
+ process.exit(result.status ?? 0);
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+ // Managed by @git.zone/cli from assets/templates/asset_deno_binary_postinstall. Do not edit by hand.
3
+
4
+ import { arch, platform } from 'node:os';
5
+ import { chmodSync, existsSync, mkdirSync, unlinkSync } from 'node:fs';
6
+ import { dirname, join } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import https from 'node:https';
9
+ import { pipeline } from 'node:stream';
10
+ import { createWriteStream } from 'node:fs';
11
+ import process from 'node:process';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ const REPO_BASE = '{{{repository.baseUrl}}}';
17
+ const FALLBACK_BRANCH = '{{repository.branch}}';
18
+ const VERSION = process.env.npm_package_version || '{{versionFallback}}';
19
+ const BINARY_MAP = new Map([
20
+ {{#each binary.targets}}
21
+ ['{{nodeKey}}', '{{assetName}}'],
22
+ {{/each}}
23
+ ]);
24
+
25
+ function getBinaryInfo() {
26
+ const key = `${platform()}:${arch()}`;
27
+ const binaryName = BINARY_MAP.get(key);
28
+ if (!binaryName) {
29
+ return { supported: false, key, platform: platform(), arch: arch() };
30
+ }
31
+ return { supported: true, key, binaryName, platform: platform(), arch: arch() };
32
+ }
33
+
34
+ function downloadFile(url, destination) {
35
+ return new Promise((resolve, reject) => {
36
+ const download = (nextUrl, redirectCount = 0) => {
37
+ if (redirectCount > 5) {
38
+ reject(new Error('Too many redirects'));
39
+ return;
40
+ }
41
+
42
+ console.log(`Downloading from: ${nextUrl}`);
43
+ https.get(nextUrl, (response) => {
44
+ if (response.statusCode === 301 || response.statusCode === 302) {
45
+ download(response.headers.location, redirectCount + 1);
46
+ return;
47
+ }
48
+ if (response.statusCode !== 200) {
49
+ reject(new Error(`Failed to download: ${response.statusCode} ${response.statusMessage}`));
50
+ return;
51
+ }
52
+
53
+ const file = createWriteStream(destination);
54
+ pipeline(response, file, (error) => {
55
+ if (error) {
56
+ reject(error);
57
+ } else {
58
+ resolve();
59
+ }
60
+ });
61
+ }).on('error', reject);
62
+ };
63
+
64
+ download(url);
65
+ });
66
+ }
67
+
68
+ async function main() {
69
+ console.log('===========================================');
70
+ console.log(' {{displayName}} - Binary Installation');
71
+ console.log('===========================================');
72
+ console.log('');
73
+
74
+ const binaryInfo = getBinaryInfo();
75
+ if (!binaryInfo.supported) {
76
+ console.error(`Error: Unsupported platform/architecture: ${binaryInfo.platform}/${binaryInfo.arch}`);
77
+ console.error('Supported platforms: {{binary.supportedPlatformText}}');
78
+ process.exit(1);
79
+ }
80
+
81
+ const binariesDir = join(__dirname, '..', '{{{npmWrapper.binariesDir}}}');
82
+ if (!existsSync(binariesDir)) {
83
+ mkdirSync(binariesDir, { recursive: true });
84
+ }
85
+
86
+ const binaryPath = join(binariesDir, binaryInfo.binaryName);
87
+ if (existsSync(binaryPath)) {
88
+ console.log('Binary already exists, skipping download');
89
+ } else {
90
+ const releaseUrl = `${REPO_BASE}/releases/download/v${VERSION}/${binaryInfo.binaryName}`;
91
+ const fallbackUrl = `${REPO_BASE}/raw/branch/${FALLBACK_BRANCH}/{{{npmWrapper.binariesDir}}}/${binaryInfo.binaryName}`;
92
+
93
+ try {
94
+ await downloadFile(releaseUrl, binaryPath);
95
+ } catch (error) {
96
+ console.log(`Release download failed: ${error.message}`);
97
+ console.log('Trying fallback URL...');
98
+ try {
99
+ await downloadFile(fallbackUrl, binaryPath);
100
+ } catch (fallbackError) {
101
+ if (existsSync(binaryPath)) {
102
+ unlinkSync(binaryPath);
103
+ }
104
+ console.error('Error: Failed to download binary');
105
+ console.error(` Primary URL: ${releaseUrl}`);
106
+ console.error(` Fallback URL: ${fallbackUrl}`);
107
+ console.error(` Cause: ${fallbackError.message}`);
108
+ process.exit(1);
109
+ }
110
+ }
111
+ }
112
+
113
+ if (binaryInfo.platform !== 'win32') {
114
+ chmodSync(binaryPath, 0o755);
115
+ }
116
+
117
+ console.log('{{displayName}} installation completed successfully.');
118
+ }
119
+
120
+ main().catch((error) => {
121
+ console.error(`Installation failed: ${error.message}`);
122
+ process.exit(1);
123
+ });