@jetbrains/junie-cli 1.0.0 → 458.1.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.
package/bin/index.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ const {spawnSync} = require('child_process')
3
+ const {getExecutable} = require('../getExecutable')
4
+
5
+ function main() {
6
+ try {
7
+ const exe = getExecutable()
8
+ const result = spawnSync(exe, process.argv.slice(2), {stdio: 'inherit'})
9
+ process.exit(result.status ?? 0)
10
+ } catch (error) {
11
+ console.error('[Junie] Error:', error.message)
12
+ process.exit(1)
13
+ }
14
+ }
15
+
16
+ main()
@@ -0,0 +1,34 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const { platform } = require("node:os")
4
+
5
+ function getExpectedBinaryPath() {
6
+ const workDir = path.resolve(__dirname, 'bin', 'junie')
7
+
8
+ return platform() === 'darwin'
9
+ ? path.join(workDir, 'Applications', 'junie.app', 'Contents', 'MacOS', 'junie')
10
+ : path.join(workDir, 'junie', 'bin', 'junie')
11
+ }
12
+
13
+
14
+ function getExecutable() {
15
+ const markerFile = path.resolve(__dirname, 'bin', 'junie.download')
16
+
17
+ if (fs.existsSync(markerFile)) {
18
+ const binaryPath = getExpectedBinaryPath()
19
+
20
+ if (fs.existsSync(binaryPath)) {
21
+ return binaryPath
22
+ } else {
23
+ console.error('Junie binary not found. Please re-install the package')
24
+ }
25
+ } else {
26
+ console.error('Junie download is corrupted. Please re-install the package')
27
+ }
28
+ }
29
+
30
+
31
+ module.exports = {
32
+ getExpectedBinaryPath,
33
+ getExecutable,
34
+ };
package/package.json CHANGED
@@ -1,12 +1,30 @@
1
1
  {
2
2
  "name": "@jetbrains/junie-cli",
3
- "version": "1.0.0",
4
- "description": "",
5
- "license": "ISC",
6
- "author": "",
7
- "type": "commonjs",
8
- "main": "index.js",
3
+ "version": "458.1.0",
4
+ "junieVersion": "458.1",
5
+ "description": "Junie command‑line client",
6
+ "license": "SEE LICENSE IN LICENSE.md",
7
+ "repository": "https://github.com/jetbrains-junie/junie",
8
+ "homepage": "https://github.com/jetbrains-junie/junie#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/jetbrains-junie/junie/issues"
11
+ },
12
+ "main": "bin/index.js",
13
+ "bin": {
14
+ "junie": "bin/index.js"
15
+ },
9
16
  "scripts": {
10
- "test": "echo \"Error: no test specified\" && exit 1"
17
+ "postinstall": "node postinstall.js"
18
+ },
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "files": [
23
+ "bin/",
24
+ "postinstall.js",
25
+ "getExecutable.js"
26
+ ],
27
+ "dependencies": {
28
+ "unzipper": "0.12.3"
11
29
  }
12
30
  }
package/postinstall.js ADDED
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require("path")
4
+ const fs = require("fs")
5
+ const { pipeline } = require("stream/promises")
6
+ const unzipper = require('unzipper')
7
+ const os = require("os")
8
+ const { getExpectedBinaryPath } = require("./getExecutable")
9
+
10
+ const ARCH_MAP = {
11
+ x64: 'amd64',
12
+ amd64: 'amd64',
13
+ arm64: 'aarch64',
14
+ aarch64: 'aarch64'
15
+ }
16
+ const OS_MAP = {
17
+ linux: 'linux',
18
+ darwin: 'macos'
19
+ }
20
+
21
+ function resolveTarget() {
22
+ const arch = ARCH_MAP[os.arch()]
23
+ const osName = OS_MAP[os.platform()]
24
+ if (!arch) throw new Error(`Unsupported architecture: ${os.arch()}`)
25
+ if (!osName) throw new Error(`Unsupported platform: ${os.platform()}`)
26
+ return {arch, osName}
27
+ }
28
+
29
+ function buildUrl({arch, osName}) {
30
+ const JUNIE_VERSION = require("./package.json").junieVersion
31
+ const tag = `${JUNIE_VERSION}`
32
+ return `https://github.com/jetbrains-junie/junie/releases/download/${tag}/junie-cloud-eap.${JUNIE_VERSION}-${osName}-${arch}.zip`
33
+ }
34
+
35
+ function stripQuarantine(targetPath) {
36
+ if (os.platform() !== 'darwin') return
37
+ try {
38
+ execSync(`xattr -dr com.apple.quarantine "${targetPath}"`, { stdio: 'ignore' })
39
+ } catch {
40
+ // ignore if xattr not available or attribute missing
41
+ }
42
+ }
43
+
44
+ function chmodRecursive(dirPath) {
45
+ if (!fs.existsSync(dirPath)) return
46
+ const stack = [dirPath]
47
+ while (stack.length) {
48
+ const current = stack.pop()
49
+ let stat;
50
+ try {
51
+ stat = fs.lstatSync(current)
52
+ } catch {
53
+ continue
54
+ }
55
+ if (stat.isSymbolicLink()) continue;
56
+ if (stat.isDirectory()) {
57
+ try {
58
+ for (const entry of fs.readdirSync(current)) {
59
+ stack.push(path.join(current, entry))
60
+ }
61
+ } catch {
62
+ // ignore unreadable dirs
63
+ }
64
+ } else if (stat.isFile()) {
65
+ try {
66
+ fs.chmodSync(current, 0o755);
67
+ } catch {
68
+ // ignore files we can't chmod
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ async function downloadAndInstall() {
75
+ const {arch, osName} = resolveTarget()
76
+ const url = buildUrl({arch, osName})
77
+ const workDir = path.resolve(__dirname, 'bin', 'junie')
78
+ const markerFile = path.resolve(__dirname, 'bin', 'junie.download')
79
+
80
+ fs.mkdirSync(workDir, {recursive: true})
81
+
82
+ const zipPath = path.join(workDir, 'junie-runner.zip')
83
+ console.log(`[Junie] Downloading from ${url}`)
84
+
85
+ const res = await fetch(url)
86
+ if (!res.ok) throw new Error(`Download failed: ${res.status} ${res.statusText}`)
87
+
88
+ await pipeline(res.body, fs.createWriteStream(zipPath))
89
+
90
+ await fs.createReadStream(zipPath).pipe(unzipper.Extract({ path: workDir })).promise()
91
+
92
+ chmodRecursive(workDir)
93
+ stripQuarantine(workDir)
94
+
95
+ const binaryPath = getExpectedBinaryPath()
96
+ // Re-assert main binary is executable (cheap, idempotent)
97
+ try { fs.chmodSync(binaryPath, 0o755); } catch {}
98
+
99
+ fs.rmSync(zipPath)
100
+
101
+ fs.writeFileSync(markerFile, binaryPath, 'utf8')
102
+
103
+ console.log('[Junie] Installation complete.')
104
+
105
+ return binaryPath
106
+ }
107
+
108
+ async function main() {
109
+ try {
110
+ await downloadAndInstall()
111
+ } catch (error) {
112
+ console.error('[Junie] Post-install error:', error)
113
+ process.exit(1)
114
+ }
115
+ }
116
+
117
+ main()