@barnaby.build/barnaby 0.0.171 → 0.0.234
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/README.md +162 -200
- package/bin/barnaby.cjs +19 -19
- package/dist/assets/index-92s3dAHv.js +225 -0
- package/dist/assets/index-DY-L_K7b.css +32 -0
- package/dist/debug-window.html +65 -65
- package/dist/index.html +2 -2
- package/dist/splash.html +46 -46
- package/dist-electron/main/index.js +7470 -10257
- package/dist-electron/preload/index.mjs +2 -2
- package/docs/screenshots/barnaby-dark.png +0 -0
- package/docs/screenshots/barnaby-light.png +0 -0
- package/docs/screenshots/barnaby-main.png +0 -0
- package/package.json +27 -11
- package/public/debug-window.html +65 -65
- package/public/splash.html +46 -46
- package/scripts/apply-exe-icon.mjs +51 -0
- package/scripts/build-dispatch.mjs +40 -0
- package/scripts/bump-version.mjs +35 -35
- package/scripts/create-release-notes.mjs +47 -47
- package/scripts/electron-builder-after-pack.cjs +27 -0
- package/scripts/generate-license-key.mjs +99 -0
- package/scripts/license-keypair-init.mjs +56 -0
- package/scripts/patch-nord-theme.mjs +14 -14
- package/scripts/rebuild-native.mjs +47 -47
- package/scripts/run-with-version-bump.mjs +80 -0
- package/scripts/shortcut-win.mjs +57 -57
- package/scripts/sync-icon.mjs +20 -0
- package/dist/assets/index-BGgZBU-P.js +0 -280
- package/dist/assets/index-Cmxmzasv.css +0 -32
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const fs = require('node:fs')
|
|
2
|
+
const path = require('node:path')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Patch the packed app executable icon before artifacts (portable/nsis) are produced.
|
|
6
|
+
* This avoids mutating the final portable SFX, which rcedit corrupts.
|
|
7
|
+
*/
|
|
8
|
+
exports.default = async function afterPack(context) {
|
|
9
|
+
if (context.electronPlatformName !== 'win32') return
|
|
10
|
+
|
|
11
|
+
const { rcedit } = await import('rcedit')
|
|
12
|
+
const exeName = `${context.packager.appInfo.productFilename}.exe`
|
|
13
|
+
const exePath = path.join(context.appOutDir, exeName)
|
|
14
|
+
const iconPath = path.join(context.packager.projectDir, 'build', 'icon.ico')
|
|
15
|
+
|
|
16
|
+
if (!fs.existsSync(iconPath)) {
|
|
17
|
+
console.warn('[afterPack] icon missing, skipping:', iconPath)
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
if (!fs.existsSync(exePath)) {
|
|
21
|
+
console.warn('[afterPack] app exe missing, skipping:', exePath)
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
await rcedit(exePath, { icon: iconPath })
|
|
26
|
+
console.log('[afterPack] Applied icon to', exePath)
|
|
27
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate a license key for a customer.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node scripts/generate-license-key.mjs --email customer@example.com
|
|
7
|
+
* node scripts/generate-license-key.mjs --email customer@example.com --tier pro
|
|
8
|
+
* node scripts/generate-license-key.mjs --email customer@example.com --exp 2027-01-01
|
|
9
|
+
*
|
|
10
|
+
* Options:
|
|
11
|
+
* --email Customer email (required)
|
|
12
|
+
* --tier License tier: pro, enterprise (default: pro)
|
|
13
|
+
* --exp Expiry date in YYYY-MM-DD format (optional, omit for perpetual)
|
|
14
|
+
*
|
|
15
|
+
* Reads the private key from: ~/.barnaby/license-private-key.pem
|
|
16
|
+
* Run license-keypair-init.mjs first if you haven't generated a keypair.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import crypto from 'node:crypto'
|
|
20
|
+
import fs from 'node:fs'
|
|
21
|
+
import path from 'node:path'
|
|
22
|
+
import os from 'node:os'
|
|
23
|
+
|
|
24
|
+
const PRIVATE_KEY_PATH = path.join(os.homedir(), '.barnaby', 'license-private-key.pem')
|
|
25
|
+
|
|
26
|
+
// Parse args
|
|
27
|
+
const args = process.argv.slice(2)
|
|
28
|
+
function getArg(name) {
|
|
29
|
+
const idx = args.indexOf(`--${name}`)
|
|
30
|
+
if (idx === -1 || idx + 1 >= args.length) return undefined
|
|
31
|
+
return args[idx + 1]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const email = getArg('email')
|
|
35
|
+
const tier = getArg('tier') || 'pro'
|
|
36
|
+
const expStr = getArg('exp')
|
|
37
|
+
|
|
38
|
+
if (!email) {
|
|
39
|
+
console.error('❌ Missing --email argument')
|
|
40
|
+
console.error('Usage: node scripts/generate-license-key.mjs --email customer@example.com')
|
|
41
|
+
process.exit(1)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Read private key
|
|
45
|
+
if (!fs.existsSync(PRIVATE_KEY_PATH)) {
|
|
46
|
+
console.error('❌ Private key not found at:', PRIVATE_KEY_PATH)
|
|
47
|
+
console.error(' Run: node scripts/license-keypair-init.mjs')
|
|
48
|
+
process.exit(1)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const privateKeyPem = fs.readFileSync(PRIVATE_KEY_PATH, 'utf8')
|
|
52
|
+
const privateKey = crypto.createPrivateKey(privateKeyPem)
|
|
53
|
+
|
|
54
|
+
// Build payload
|
|
55
|
+
const payload = {
|
|
56
|
+
email: email.toLowerCase().trim(),
|
|
57
|
+
product: 'orchestrator',
|
|
58
|
+
tier,
|
|
59
|
+
iat: Date.now(),
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (expStr) {
|
|
63
|
+
const expDate = new Date(expStr)
|
|
64
|
+
if (isNaN(expDate.getTime())) {
|
|
65
|
+
console.error('❌ Invalid --exp date format. Use YYYY-MM-DD.')
|
|
66
|
+
process.exit(1)
|
|
67
|
+
}
|
|
68
|
+
payload.exp = expDate.getTime()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Encode payload
|
|
72
|
+
const payloadBuf = Buffer.from(JSON.stringify(payload), 'utf8')
|
|
73
|
+
|
|
74
|
+
// Sign
|
|
75
|
+
const signature = crypto.sign(null, payloadBuf, privateKey)
|
|
76
|
+
|
|
77
|
+
// Base64url encode (no padding)
|
|
78
|
+
function base64urlEncode(buf) {
|
|
79
|
+
return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const key = `ORCH-${base64urlEncode(payloadBuf)}.${base64urlEncode(signature)}`
|
|
83
|
+
|
|
84
|
+
console.log()
|
|
85
|
+
console.log('✅ License key generated for:', email)
|
|
86
|
+
console.log()
|
|
87
|
+
console.log('Details:')
|
|
88
|
+
console.log(' Email:', payload.email)
|
|
89
|
+
console.log(' Tier:', payload.tier)
|
|
90
|
+
console.log(' Issued:', new Date(payload.iat).toISOString())
|
|
91
|
+
console.log(' Expires:', payload.exp ? new Date(payload.exp).toISOString() : 'Never (perpetual)')
|
|
92
|
+
console.log()
|
|
93
|
+
console.log('License Key:')
|
|
94
|
+
console.log('─'.repeat(60))
|
|
95
|
+
console.log(key)
|
|
96
|
+
console.log('─'.repeat(60))
|
|
97
|
+
console.log()
|
|
98
|
+
console.log('Send this key to the customer. They paste it into')
|
|
99
|
+
console.log('Settings → Orchestrator → License Key.')
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* One-time script: Generate an ed25519 keypair for license key signing.
|
|
4
|
+
*
|
|
5
|
+
* Run: node scripts/license-keypair-init.mjs
|
|
6
|
+
*
|
|
7
|
+
* Output:
|
|
8
|
+
* - Prints the PUBLIC key PEM (embed in licenseKeys.ts)
|
|
9
|
+
* - Saves the PRIVATE key to ~/.barnaby/license-private-key.pem
|
|
10
|
+
*
|
|
11
|
+
* IMPORTANT: The private key file must NEVER be committed to version control.
|
|
12
|
+
* Back it up securely — if you lose it, you can't generate new keys.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import crypto from 'node:crypto'
|
|
16
|
+
import fs from 'node:fs'
|
|
17
|
+
import path from 'node:path'
|
|
18
|
+
import os from 'node:os'
|
|
19
|
+
|
|
20
|
+
const PRIVATE_KEY_PATH = path.join(os.homedir(), '.barnaby', 'license-private-key.pem')
|
|
21
|
+
|
|
22
|
+
// Check if keypair already exists
|
|
23
|
+
if (fs.existsSync(PRIVATE_KEY_PATH)) {
|
|
24
|
+
console.log('⚠️ Private key already exists at:', PRIVATE_KEY_PATH)
|
|
25
|
+
console.log(' Delete it first if you want to generate a new keypair.')
|
|
26
|
+
console.log()
|
|
27
|
+
|
|
28
|
+
// Show the existing public key for reference
|
|
29
|
+
const existingPrivate = fs.readFileSync(PRIVATE_KEY_PATH, 'utf8')
|
|
30
|
+
const privateKey = crypto.createPrivateKey(existingPrivate)
|
|
31
|
+
const publicKeyPem = crypto.createPublicKey(privateKey).export({ type: 'spki', format: 'pem' })
|
|
32
|
+
console.log('Existing PUBLIC key (already in licenseKeys.ts):')
|
|
33
|
+
console.log(publicKeyPem)
|
|
34
|
+
process.exit(0)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Generate new ed25519 keypair
|
|
38
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519')
|
|
39
|
+
|
|
40
|
+
const publicKeyPem = publicKey.export({ type: 'spki', format: 'pem' })
|
|
41
|
+
const privateKeyPem = privateKey.export({ type: 'pkcs8', format: 'pem' })
|
|
42
|
+
|
|
43
|
+
// Save private key
|
|
44
|
+
const dir = path.dirname(PRIVATE_KEY_PATH)
|
|
45
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
46
|
+
fs.writeFileSync(PRIVATE_KEY_PATH, privateKeyPem, { mode: 0o600 })
|
|
47
|
+
|
|
48
|
+
console.log('✅ Ed25519 keypair generated successfully!')
|
|
49
|
+
console.log()
|
|
50
|
+
console.log('PRIVATE key saved to:', PRIVATE_KEY_PATH)
|
|
51
|
+
console.log('⚠️ NEVER commit this file. Back it up securely.')
|
|
52
|
+
console.log()
|
|
53
|
+
console.log('PUBLIC key — copy this into electron/main/licenseKeys.ts:')
|
|
54
|
+
console.log('─'.repeat(60))
|
|
55
|
+
console.log(publicKeyPem)
|
|
56
|
+
console.log('─'.repeat(60))
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
|
|
3
|
-
const p = 'C:/Users/stuar/AppData/Roaming/Barnaby/.storage/app-state.json'
|
|
4
|
-
const d = JSON.parse(fs.readFileSync(p, 'utf8'))
|
|
5
|
-
const s = d.state
|
|
6
|
-
if (!s.themeOverrides) s.themeOverrides = {}
|
|
7
|
-
if (!s.themeOverrides['nord-light']) s.themeOverrides['nord-light'] = {}
|
|
8
|
-
Object.assign(s.themeOverrides['nord-light'], {
|
|
9
|
-
accentSoft: '#f0f6ff',
|
|
10
|
-
assistantBubbleBgLight: '#f0f0f0',
|
|
11
|
-
thinkingProgress: '#082cdd',
|
|
12
|
-
})
|
|
13
|
-
fs.writeFileSync(p, JSON.stringify(d, null, 2))
|
|
14
|
-
console.log('nord-light overrides patched')
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
|
|
3
|
+
const p = 'C:/Users/stuar/AppData/Roaming/Barnaby/.storage/app-state.json'
|
|
4
|
+
const d = JSON.parse(fs.readFileSync(p, 'utf8'))
|
|
5
|
+
const s = d.state
|
|
6
|
+
if (!s.themeOverrides) s.themeOverrides = {}
|
|
7
|
+
if (!s.themeOverrides['nord-light']) s.themeOverrides['nord-light'] = {}
|
|
8
|
+
Object.assign(s.themeOverrides['nord-light'], {
|
|
9
|
+
accentSoft: '#f0f6ff',
|
|
10
|
+
assistantBubbleBgLight: '#f0f0f0',
|
|
11
|
+
thinkingProgress: '#082cdd',
|
|
12
|
+
})
|
|
13
|
+
fs.writeFileSync(p, JSON.stringify(d, null, 2))
|
|
14
|
+
console.log('nord-light overrides patched')
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Best-effort rebuild of native Node modules (node-pty) for Electron.
|
|
4
|
-
* Runs as part of postinstall. Fails silently if build tools are missing.
|
|
5
|
-
*
|
|
6
|
-
* Requirements for a successful rebuild:
|
|
7
|
-
* - Python 3.x on PATH
|
|
8
|
-
* - C++ build tools (Visual Studio on Windows, Xcode CLT on macOS, gcc on Linux)
|
|
9
|
-
*
|
|
10
|
-
* If these are missing, node-pty's N-API prebuilds may still work at runtime.
|
|
11
|
-
*/
|
|
12
|
-
import { execSync } from 'node:child_process'
|
|
13
|
-
import { existsSync } from 'node:fs'
|
|
14
|
-
import { join, dirname } from 'node:path'
|
|
15
|
-
import { fileURLToPath } from 'node:url'
|
|
16
|
-
|
|
17
|
-
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
18
|
-
const root = join(__dirname, '..')
|
|
19
|
-
|
|
20
|
-
const nodePtyDir = join(root, 'node_modules', 'node-pty')
|
|
21
|
-
if (!existsSync(nodePtyDir)) {
|
|
22
|
-
// node-pty not installed (optional dep) — nothing to do
|
|
23
|
-
process.exit(0)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const electronRebuild = join(root, 'node_modules', '.bin', 'electron-rebuild')
|
|
27
|
-
if (!existsSync(electronRebuild) && !existsSync(electronRebuild + '.cmd')) {
|
|
28
|
-
process.exit(0)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
console.log('[postinstall] Rebuilding native modules for Electron...')
|
|
33
|
-
execSync(`"${electronRebuild}" -m "${nodePtyDir}"`, {
|
|
34
|
-
cwd: root,
|
|
35
|
-
stdio: 'inherit',
|
|
36
|
-
timeout: 120_000,
|
|
37
|
-
})
|
|
38
|
-
console.log('[postinstall] Native modules rebuilt successfully.')
|
|
39
|
-
} catch {
|
|
40
|
-
console.log(
|
|
41
|
-
'[postinstall] Native module rebuild skipped (missing Python or C++ build tools).\n' +
|
|
42
|
-
' The built-in terminal may not work. To fix:\n' +
|
|
43
|
-
' 1. Install Python 3: https://www.python.org/downloads/\n' +
|
|
44
|
-
' 2. Install C++ build tools (Visual Studio or `npm install -g windows-build-tools`)\n' +
|
|
45
|
-
' 3. Run: npx electron-rebuild'
|
|
46
|
-
)
|
|
47
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Best-effort rebuild of native Node modules (node-pty) for Electron.
|
|
4
|
+
* Runs as part of postinstall. Fails silently if build tools are missing.
|
|
5
|
+
*
|
|
6
|
+
* Requirements for a successful rebuild:
|
|
7
|
+
* - Python 3.x on PATH
|
|
8
|
+
* - C++ build tools (Visual Studio on Windows, Xcode CLT on macOS, gcc on Linux)
|
|
9
|
+
*
|
|
10
|
+
* If these are missing, node-pty's N-API prebuilds may still work at runtime.
|
|
11
|
+
*/
|
|
12
|
+
import { execSync } from 'node:child_process'
|
|
13
|
+
import { existsSync } from 'node:fs'
|
|
14
|
+
import { join, dirname } from 'node:path'
|
|
15
|
+
import { fileURLToPath } from 'node:url'
|
|
16
|
+
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
18
|
+
const root = join(__dirname, '..')
|
|
19
|
+
|
|
20
|
+
const nodePtyDir = join(root, 'node_modules', 'node-pty')
|
|
21
|
+
if (!existsSync(nodePtyDir)) {
|
|
22
|
+
// node-pty not installed (optional dep) — nothing to do
|
|
23
|
+
process.exit(0)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const electronRebuild = join(root, 'node_modules', '.bin', 'electron-rebuild')
|
|
27
|
+
if (!existsSync(electronRebuild) && !existsSync(electronRebuild + '.cmd')) {
|
|
28
|
+
process.exit(0)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
console.log('[postinstall] Rebuilding native modules for Electron...')
|
|
33
|
+
execSync(`"${electronRebuild}" -m "${nodePtyDir}"`, {
|
|
34
|
+
cwd: root,
|
|
35
|
+
stdio: 'inherit',
|
|
36
|
+
timeout: 120_000,
|
|
37
|
+
})
|
|
38
|
+
console.log('[postinstall] Native modules rebuilt successfully.')
|
|
39
|
+
} catch {
|
|
40
|
+
console.log(
|
|
41
|
+
'[postinstall] Native module rebuild skipped (missing Python or C++ build tools).\n' +
|
|
42
|
+
' The built-in terminal may not work. To fix:\n' +
|
|
43
|
+
' 1. Install Python 3: https://www.python.org/downloads/\n' +
|
|
44
|
+
' 2. Install C++ build tools (Visual Studio or `npm install -g windows-build-tools`)\n' +
|
|
45
|
+
' 3. Run: npx electron-rebuild'
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { spawn } from 'node:child_process'
|
|
4
|
+
|
|
5
|
+
const command = process.argv.slice(2).join(' ').trim()
|
|
6
|
+
if (!command) {
|
|
7
|
+
console.error('Usage: node scripts/run-with-version-bump.mjs "<command>"')
|
|
8
|
+
process.exit(1)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const root = process.cwd()
|
|
12
|
+
const packageJsonPath = path.join(root, 'package.json')
|
|
13
|
+
const packageLockPath = path.join(root, 'package-lock.json')
|
|
14
|
+
|
|
15
|
+
const originalPackageJsonText = fs.readFileSync(packageJsonPath, 'utf8')
|
|
16
|
+
const hadPackageLock = fs.existsSync(packageLockPath)
|
|
17
|
+
const originalPackageLockText = hadPackageLock ? fs.readFileSync(packageLockPath, 'utf8') : null
|
|
18
|
+
|
|
19
|
+
function bumpPatch(version) {
|
|
20
|
+
const parts = String(version).trim().split('.')
|
|
21
|
+
if (parts.length !== 3) {
|
|
22
|
+
throw new Error(`Expected semantic version x.y.z, got "${version}"`)
|
|
23
|
+
}
|
|
24
|
+
const [major, minor, patch] = parts.map((p) => Number(p))
|
|
25
|
+
if ([major, minor, patch].some((n) => Number.isNaN(n))) {
|
|
26
|
+
throw new Error(`Expected numeric semantic version, got "${version}"`)
|
|
27
|
+
}
|
|
28
|
+
return `${major}.${minor}.${patch + 1}`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function restoreVersionFiles() {
|
|
32
|
+
fs.writeFileSync(packageJsonPath, originalPackageJsonText, 'utf8')
|
|
33
|
+
if (originalPackageLockText === null) {
|
|
34
|
+
if (fs.existsSync(packageLockPath)) fs.rmSync(packageLockPath)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
fs.writeFileSync(packageLockPath, originalPackageLockText, 'utf8')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const packageJson = JSON.parse(originalPackageJsonText)
|
|
41
|
+
const currentVersion = packageJson.version
|
|
42
|
+
const nextVersion = bumpPatch(currentVersion)
|
|
43
|
+
packageJson.version = nextVersion
|
|
44
|
+
fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8')
|
|
45
|
+
|
|
46
|
+
if (hadPackageLock) {
|
|
47
|
+
const packageLock = JSON.parse(originalPackageLockText)
|
|
48
|
+
if (typeof packageLock.version === 'string') packageLock.version = nextVersion
|
|
49
|
+
if (packageLock.packages && packageLock.packages[''] && typeof packageLock.packages[''].version === 'string') {
|
|
50
|
+
packageLock.packages[''].version = nextVersion
|
|
51
|
+
}
|
|
52
|
+
fs.writeFileSync(packageLockPath, `${JSON.stringify(packageLock, null, 2)}\n`, 'utf8')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log(`Version bumped: ${currentVersion} -> ${nextVersion}`)
|
|
56
|
+
|
|
57
|
+
const child = spawn(command, {
|
|
58
|
+
cwd: root,
|
|
59
|
+
env: process.env,
|
|
60
|
+
shell: true,
|
|
61
|
+
stdio: 'inherit'
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
child.on('error', (error) => {
|
|
65
|
+
console.error(`Failed to start command: ${error.message}`)
|
|
66
|
+
restoreVersionFiles()
|
|
67
|
+
process.exit(1)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
child.on('exit', (code, signal) => {
|
|
71
|
+
if (code === 0) process.exit(0)
|
|
72
|
+
|
|
73
|
+
restoreVersionFiles()
|
|
74
|
+
if (signal) {
|
|
75
|
+
console.error(`Command terminated by signal: ${signal}`)
|
|
76
|
+
} else {
|
|
77
|
+
console.error(`Command failed with exit code ${code}`)
|
|
78
|
+
}
|
|
79
|
+
process.exit(code ?? 1)
|
|
80
|
+
})
|
package/scripts/shortcut-win.mjs
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Creates a Start menu shortcut for Barnaby on Windows (global install only).
|
|
4
|
-
* Fixes: (1) App not findable in Windows search (2) Taskbar pinning shows Electron.
|
|
5
|
-
* Tip: Pin the "Barnaby" shortcut from Start menu to taskbar for correct icon.
|
|
6
|
-
*/
|
|
7
|
-
import { platform } from 'node:os'
|
|
8
|
-
import { existsSync, writeFileSync } from 'node:fs'
|
|
9
|
-
import { dirname, join } from 'node:path'
|
|
10
|
-
import { fileURLToPath } from 'node:url'
|
|
11
|
-
import { execSync } from 'node:child_process'
|
|
12
|
-
|
|
13
|
-
function main() {
|
|
14
|
-
if (platform() !== 'win32') return
|
|
15
|
-
const force = process.argv.includes('--force')
|
|
16
|
-
if (!force && process.env.npm_config_global !== 'true') return
|
|
17
|
-
|
|
18
|
-
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
19
|
-
const pkgRoot = join(__dirname, '..')
|
|
20
|
-
|
|
21
|
-
// Use node + our script directly (barnaby.cmd may not exist yet when postinstall runs)
|
|
22
|
-
const barnabyScript = join(pkgRoot, 'bin', 'barnaby.cjs')
|
|
23
|
-
if (!existsSync(barnabyScript)) return
|
|
24
|
-
const nodeExe = process.execPath
|
|
25
|
-
|
|
26
|
-
// Prefer .ico for Windows shortcuts (PNG often fails)
|
|
27
|
-
const iconPath = [
|
|
28
|
-
join(pkgRoot, 'build', 'icon.ico'),
|
|
29
|
-
join(pkgRoot, 'dist', 'favicon.ico'),
|
|
30
|
-
join(pkgRoot, 'public', 'favicon.ico'),
|
|
31
|
-
join(pkgRoot, 'dist', 'appicon.png'),
|
|
32
|
-
join(pkgRoot, 'public', 'appicon.png')
|
|
33
|
-
].find(existsSync)
|
|
34
|
-
const startMenuDir = join(process.env.APPDATA || '', 'Microsoft', 'Windows', 'Start Menu', 'Programs')
|
|
35
|
-
const shortcutPath = join(startMenuDir, 'Barnaby.lnk')
|
|
36
|
-
|
|
37
|
-
const ps = `
|
|
38
|
-
$WshShell = New-Object -ComObject WScript.Shell
|
|
39
|
-
$Shortcut = $WshShell.CreateShortcut('${shortcutPath.replace(/'/g, "''")}')
|
|
40
|
-
$Shortcut.TargetPath = '${nodeExe.replace(/'/g, "''")}'
|
|
41
|
-
$Shortcut.Arguments = '${barnabyScript.replace(/'/g, "''")}'
|
|
42
|
-
$Shortcut.WorkingDirectory = '${(process.env.USERPROFILE || '').replace(/'/g, "''")}'
|
|
43
|
-
$Shortcut.Description = 'Barnaby - AI agent IDE'
|
|
44
|
-
${iconPath ? `if (Test-Path '${iconPath.replace(/'/g, "''")}') { $Shortcut.IconLocation = '${iconPath.replace(/'/g, "''")},0' }` : ''}
|
|
45
|
-
$Shortcut.Save()
|
|
46
|
-
`
|
|
47
|
-
try {
|
|
48
|
-
const tmp = join(process.env.TEMP || '', 'barnaby-shortcut.ps1')
|
|
49
|
-
writeFileSync(tmp, ps.trim(), 'utf8')
|
|
50
|
-
execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${tmp}"`, { stdio: 'pipe' })
|
|
51
|
-
console.log('[Barnaby] Start menu shortcut created. Pin it to taskbar for the correct icon.')
|
|
52
|
-
} catch {
|
|
53
|
-
// Silent fail - shortcut is optional
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
main()
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Creates a Start menu shortcut for Barnaby on Windows (global install only).
|
|
4
|
+
* Fixes: (1) App not findable in Windows search (2) Taskbar pinning shows Electron.
|
|
5
|
+
* Tip: Pin the "Barnaby" shortcut from Start menu to taskbar for correct icon.
|
|
6
|
+
*/
|
|
7
|
+
import { platform } from 'node:os'
|
|
8
|
+
import { existsSync, writeFileSync } from 'node:fs'
|
|
9
|
+
import { dirname, join } from 'node:path'
|
|
10
|
+
import { fileURLToPath } from 'node:url'
|
|
11
|
+
import { execSync } from 'node:child_process'
|
|
12
|
+
|
|
13
|
+
function main() {
|
|
14
|
+
if (platform() !== 'win32') return
|
|
15
|
+
const force = process.argv.includes('--force')
|
|
16
|
+
if (!force && process.env.npm_config_global !== 'true') return
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
19
|
+
const pkgRoot = join(__dirname, '..')
|
|
20
|
+
|
|
21
|
+
// Use node + our script directly (barnaby.cmd may not exist yet when postinstall runs)
|
|
22
|
+
const barnabyScript = join(pkgRoot, 'bin', 'barnaby.cjs')
|
|
23
|
+
if (!existsSync(barnabyScript)) return
|
|
24
|
+
const nodeExe = process.execPath
|
|
25
|
+
|
|
26
|
+
// Prefer .ico for Windows shortcuts (PNG often fails)
|
|
27
|
+
const iconPath = [
|
|
28
|
+
join(pkgRoot, 'build', 'icon.ico'),
|
|
29
|
+
join(pkgRoot, 'dist', 'favicon.ico'),
|
|
30
|
+
join(pkgRoot, 'public', 'favicon.ico'),
|
|
31
|
+
join(pkgRoot, 'dist', 'appicon.png'),
|
|
32
|
+
join(pkgRoot, 'public', 'appicon.png')
|
|
33
|
+
].find(existsSync)
|
|
34
|
+
const startMenuDir = join(process.env.APPDATA || '', 'Microsoft', 'Windows', 'Start Menu', 'Programs')
|
|
35
|
+
const shortcutPath = join(startMenuDir, 'Barnaby.lnk')
|
|
36
|
+
|
|
37
|
+
const ps = `
|
|
38
|
+
$WshShell = New-Object -ComObject WScript.Shell
|
|
39
|
+
$Shortcut = $WshShell.CreateShortcut('${shortcutPath.replace(/'/g, "''")}')
|
|
40
|
+
$Shortcut.TargetPath = '${nodeExe.replace(/'/g, "''")}'
|
|
41
|
+
$Shortcut.Arguments = '${barnabyScript.replace(/'/g, "''")}'
|
|
42
|
+
$Shortcut.WorkingDirectory = '${(process.env.USERPROFILE || '').replace(/'/g, "''")}'
|
|
43
|
+
$Shortcut.Description = 'Barnaby - AI agent IDE'
|
|
44
|
+
${iconPath ? `if (Test-Path '${iconPath.replace(/'/g, "''")}') { $Shortcut.IconLocation = '${iconPath.replace(/'/g, "''")},0' }` : ''}
|
|
45
|
+
$Shortcut.Save()
|
|
46
|
+
`
|
|
47
|
+
try {
|
|
48
|
+
const tmp = join(process.env.TEMP || '', 'barnaby-shortcut.ps1')
|
|
49
|
+
writeFileSync(tmp, ps.trim(), 'utf8')
|
|
50
|
+
execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${tmp}"`, { stdio: 'pipe' })
|
|
51
|
+
console.log('[Barnaby] Start menu shortcut created. Pin it to taskbar for the correct icon.')
|
|
52
|
+
} catch {
|
|
53
|
+
// Silent fail - shortcut is optional
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
main()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Sync build/icon.ico to public/favicon.ico so the BrowserWindow and packaged
|
|
4
|
+
* app use the same icon. electron-builder reads build/icon.ico for the .exe;
|
|
5
|
+
* the runtime uses public/favicon.ico (copied to dist by Vite).
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs'
|
|
8
|
+
import path from 'node:path'
|
|
9
|
+
|
|
10
|
+
const root = process.cwd()
|
|
11
|
+
const src = path.join(root, 'build', 'icon.ico')
|
|
12
|
+
const dest = path.join(root, 'public', 'favicon.ico')
|
|
13
|
+
|
|
14
|
+
if (!fs.existsSync(src)) {
|
|
15
|
+
console.warn('[sync-icon] build/icon.ico not found, skipping sync')
|
|
16
|
+
process.exit(0)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fs.copyFileSync(src, dest)
|
|
20
|
+
console.log('[sync-icon] Copied build/icon.ico → public/favicon.ico')
|