khal-os 1.260404.2 → 1.260405.1
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/cli.js +3 -0
- package/package.json +6 -110
- package/LICENSE +0 -45
- package/README.md +0 -38
- package/packages/npx-cli/bin/cli.cjs +0 -120
- package/packages/npx-cli/install.cjs +0 -197
package/cli.js
ADDED
package/package.json
CHANGED
|
@@ -1,113 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "khal-os",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
"packages/npx-cli/install.cjs"
|
|
10
|
-
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"dev": "next dev --port 8888",
|
|
13
|
-
"build": "npx tsx scripts/build-apps.ts && NEXT_PRIVATE_BUILD_WORKER=false next build",
|
|
14
|
-
"start": "next start --port 8888",
|
|
15
|
-
"postinstall": "node packages/npx-cli/install.cjs && chmod +x node_modules/.pnpm/node-pty@*/node_modules/node-pty/prebuilds/darwin-*/spawn-helper 2>/dev/null || true",
|
|
16
|
-
"pty-server": "node pty-server.mjs",
|
|
17
|
-
"lint": "biome check .",
|
|
18
|
-
"lint:fix": "biome check --write .",
|
|
19
|
-
"knip": "knip",
|
|
20
|
-
"services": "tsx src/lib/service-loader.ts",
|
|
21
|
-
"tauri": "cd tauri && cargo run",
|
|
22
|
-
"tauri:dev": "cd tauri && cargo tauri dev",
|
|
23
|
-
"tauri:build": "cd tauri && cargo build --release",
|
|
24
|
-
"prepare": "husky"
|
|
25
|
-
},
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"@json-render/core": "^0.7.0",
|
|
28
|
-
"@json-render/react": "^0.7.0",
|
|
29
|
-
"@khal-os/sdk": "^1.0.1",
|
|
30
|
-
"@khal-os/ui": "^1.0.1",
|
|
31
|
-
"@nats-io/jetstream": "^3.3.1",
|
|
32
|
-
"@nats-io/transport-node": "^3.3.1",
|
|
33
|
-
"@number-flow/react": "^0.6.0",
|
|
34
|
-
"@opentelemetry/api": "^1.9.0",
|
|
35
|
-
"@opentelemetry/core": "^2.6.1",
|
|
36
|
-
"@opentelemetry/instrumentation-http": "^0.214.0",
|
|
37
|
-
"@opentelemetry/instrumentation-pg": "^0.66.0",
|
|
38
|
-
"@opentelemetry/instrumentation-runtime-node": "^0.27.0",
|
|
39
|
-
"@opentelemetry/resources": "^2.6.1",
|
|
40
|
-
"@opentelemetry/sdk-metrics": "^2.6.1",
|
|
41
|
-
"@opentelemetry/sdk-node": "^0.214.0",
|
|
42
|
-
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
43
|
-
"@paper-design/shaders-react": "^0.0.72",
|
|
44
|
-
"@radix-ui/react-context-menu": "^2.2.16",
|
|
45
|
-
"@radix-ui/react-dialog": "^1.1.15",
|
|
46
|
-
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
47
|
-
"@radix-ui/react-label": "^2.1.8",
|
|
48
|
-
"@radix-ui/react-separator": "^1.1.8",
|
|
49
|
-
"@radix-ui/react-slot": "^1.2.4",
|
|
50
|
-
"@radix-ui/react-switch": "^1.2.6",
|
|
51
|
-
"@radix-ui/react-tooltip": "^1.2.8",
|
|
52
|
-
"@sentry/nextjs": "^10.39.0",
|
|
53
|
-
"@sinclair/typebox": "^0.34.48",
|
|
54
|
-
"@tauri-apps/api": "^2.10.1",
|
|
55
|
-
"@temporalio/activity": "^1.15.0",
|
|
56
|
-
"@temporalio/client": "^1.15.0",
|
|
57
|
-
"@temporalio/worker": "^1.15.0",
|
|
58
|
-
"@temporalio/workflow": "^1.15.0",
|
|
59
|
-
"@types/archiver": "^7.0.0",
|
|
60
|
-
"@workos-inc/authkit-nextjs": "^2.14.0",
|
|
61
|
-
"@xterm/addon-fit": "^0.11.0",
|
|
62
|
-
"@xterm/addon-webgl": "^0.19.0",
|
|
63
|
-
"@xterm/xterm": "^6.0.0",
|
|
64
|
-
"archiver": "^7.0.1",
|
|
65
|
-
"class-variance-authority": "^0.7.1",
|
|
66
|
-
"clsx": "^2.1.1",
|
|
67
|
-
"cmdk": "^1.1.1",
|
|
68
|
-
"iron-session": "^8.0.4",
|
|
69
|
-
"jose": "^6.1.3",
|
|
70
|
-
"lucide-react": "^0.563.0",
|
|
71
|
-
"motion": "^12.38.0",
|
|
72
|
-
"next": "16.1.6",
|
|
73
|
-
"next-themes": "^0.4.6",
|
|
74
|
-
"node-pty": "^1.1.0",
|
|
75
|
-
"react": "19.2.3",
|
|
76
|
-
"react-dom": "19.2.3",
|
|
77
|
-
"tailwind-merge": "^3.4.0",
|
|
78
|
-
"ulidx": "^2.4.1",
|
|
79
|
-
"uuid": "^13.0.0",
|
|
80
|
-
"ws": "^8.20.0",
|
|
81
|
-
"zod": "^4.3.6",
|
|
82
|
-
"zustand": "^5.0.11"
|
|
83
|
-
},
|
|
84
|
-
"devDependencies": {
|
|
85
|
-
"@biomejs/biome": "^2.4.2",
|
|
86
|
-
"@commitlint/cli": "^20.5.0",
|
|
87
|
-
"@commitlint/config-conventional": "^20.5.0",
|
|
88
|
-
"@tailwindcss/postcss": "^4",
|
|
89
|
-
"@types/node": "^20",
|
|
90
|
-
"@types/react": "^19",
|
|
91
|
-
"@types/react-dom": "^19",
|
|
92
|
-
"@types/uuid": "^11.0.0",
|
|
93
|
-
"@types/ws": "^8.18.1",
|
|
94
|
-
"esbuild": "^0.27.4",
|
|
95
|
-
"git-cliff": "^2.12.0",
|
|
96
|
-
"husky": "^9.1.7",
|
|
97
|
-
"knip": "^5.85.0",
|
|
98
|
-
"tailwindcss": "^4",
|
|
99
|
-
"tsx": "^4.21.0",
|
|
100
|
-
"typescript": "^5"
|
|
101
|
-
},
|
|
102
|
-
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
|
|
103
|
-
"pnpm": {
|
|
104
|
-
"onlyBuiltDependencies": [
|
|
105
|
-
"esbuild",
|
|
106
|
-
"node-pty",
|
|
107
|
-
"@sentry/cli",
|
|
108
|
-
"@swc/core",
|
|
109
|
-
"protobufjs"
|
|
110
|
-
]
|
|
111
|
-
},
|
|
112
|
-
"license": "SEE LICENSE IN LICENSE"
|
|
3
|
+
"version": "1.260405.1",
|
|
4
|
+
"description": "KhalOS CLI — manage, monitor, and deploy KhalOS instances. Coming soon.",
|
|
5
|
+
"bin": {"khal-os": "./cli.js"},
|
|
6
|
+
"files": ["cli.js"],
|
|
7
|
+
"license": "UNLICENSED",
|
|
8
|
+
"repository": {"type": "git", "url": "https://github.com/khal-os/core"}
|
|
113
9
|
}
|
package/LICENSE
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2026 KhalOS. All rights reserved.
|
|
2
|
-
|
|
3
|
-
PROPRIETARY SOFTWARE LICENSE
|
|
4
|
-
|
|
5
|
-
This software and associated documentation files (the "Software") are the
|
|
6
|
-
exclusive property of KhalOS. The Software is protected by copyright laws
|
|
7
|
-
and international treaty provisions.
|
|
8
|
-
|
|
9
|
-
1. GRANT OF LICENSE
|
|
10
|
-
No license is granted under this agreement. Access to this repository does
|
|
11
|
-
not constitute a license to use, copy, modify, or distribute the Software.
|
|
12
|
-
|
|
13
|
-
2. RESTRICTIONS
|
|
14
|
-
You may not, without prior written authorization from KhalOS:
|
|
15
|
-
a. Copy, reproduce, or duplicate the Software;
|
|
16
|
-
b. Modify, adapt, translate, or create derivative works of the Software;
|
|
17
|
-
c. Distribute, sublicense, lease, rent, loan, or otherwise transfer the
|
|
18
|
-
Software to any third party;
|
|
19
|
-
d. Reverse engineer, disassemble, decompile, or otherwise attempt to
|
|
20
|
-
derive the source code of the Software;
|
|
21
|
-
e. Remove, alter, or obscure any proprietary notices on the Software.
|
|
22
|
-
|
|
23
|
-
3. CONFIDENTIALITY
|
|
24
|
-
The Software contains trade secrets and proprietary information of KhalOS.
|
|
25
|
-
You agree to maintain the confidentiality of the Software and not to
|
|
26
|
-
disclose it to any third party without prior written consent.
|
|
27
|
-
|
|
28
|
-
4. OWNERSHIP
|
|
29
|
-
KhalOS retains all right, title, and interest in and to the Software,
|
|
30
|
-
including all intellectual property rights therein.
|
|
31
|
-
|
|
32
|
-
5. TERMINATION
|
|
33
|
-
Any unauthorized use of the Software will result in immediate termination
|
|
34
|
-
of any implied rights and may result in legal action.
|
|
35
|
-
|
|
36
|
-
6. NO WARRANTY
|
|
37
|
-
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
38
|
-
IMPLIED. KHALOS DISCLAIMS ALL WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
|
|
39
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
40
|
-
|
|
41
|
-
7. LIMITATION OF LIABILITY
|
|
42
|
-
IN NO EVENT SHALL KHALOS BE LIABLE FOR ANY DAMAGES ARISING OUT OF THE USE
|
|
43
|
-
OR INABILITY TO USE THE SOFTWARE.
|
|
44
|
-
|
|
45
|
-
For licensing inquiries, contact: legal@khal.ai
|
package/README.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Khal
|
|
2
|
-
|
|
3
|
-
A desktop-in-browser OS shell built with Next.js, React, and Tailwind CSS.
|
|
4
|
-
|
|
5
|
-
## Quick Start
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pnpm install
|
|
9
|
-
pnpm dev # Next.js on port 1111
|
|
10
|
-
node pty-server.mjs # PTY + WebSocket on port 1112
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Open http://localhost:1111 to see the desktop.
|
|
14
|
-
|
|
15
|
-
## Default Apps
|
|
16
|
-
|
|
17
|
-
- **Terminal** — Full terminal emulator (xterm.js + node-pty)
|
|
18
|
-
- **Settings** — Theme switcher and desktop configuration
|
|
19
|
-
- **Files** — Example stub app (replace with your own)
|
|
20
|
-
|
|
21
|
-
## Adding a New App
|
|
22
|
-
|
|
23
|
-
1. Create a component in `src/components/apps/<your-app>/`
|
|
24
|
-
- Must accept `{ windowId: string; meta?: Record<string, unknown> }`
|
|
25
|
-
2. Register in `src/components/apps/app-registry.ts`
|
|
26
|
-
3. Add a `DesktopEntry` in `src/stores/desktop-store.ts`
|
|
27
|
-
4. (Optional) Set default window size in `src/lib/hooks/use-launch-app.ts`
|
|
28
|
-
5. (Optional) Add a keyboard shortcut in `src/lib/keyboard/defaults.ts`
|
|
29
|
-
|
|
30
|
-
## Architecture
|
|
31
|
-
|
|
32
|
-
- **Window Manager** — Draggable, resizable windows with snap, minimize, maximize
|
|
33
|
-
- **Taskbar** — App launcher, running apps, system tray, workspace switcher
|
|
34
|
-
- **Workspaces** — Virtual desktops
|
|
35
|
-
- **Keyboard Shortcuts** — Configurable global hotkeys
|
|
36
|
-
- **Notifications** — Toast + notification center
|
|
37
|
-
- **PTY Server** — WebSocket-based terminal backend with session persistence
|
|
38
|
-
- **Theme System** — Light/dark mode via CSS custom properties
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* khal-os CLI shim — resolves the platform-specific binary and execFile's it.
|
|
5
|
-
*
|
|
6
|
-
* Pattern: same as esbuild, turbo, swc, prisma, tailwindcss.
|
|
7
|
-
*
|
|
8
|
-
* Flow:
|
|
9
|
-
* 1. Detect platform + arch
|
|
10
|
-
* 2. Resolve khal-os-<platform-arch> package (installed via optionalDependencies)
|
|
11
|
-
* 3. Find bin/node and bin/server/server.cjs in the platform package
|
|
12
|
-
* 4. execFileSync(nodeBin, [serverCjs, ...args])
|
|
13
|
-
*
|
|
14
|
-
* If the platform package is missing (e.g. --ignore-optional), falls back to
|
|
15
|
-
* ~/.khal-os/bin/ where install.js may have downloaded it.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const { execFileSync } = require('child_process');
|
|
19
|
-
const { existsSync } = require('fs');
|
|
20
|
-
const { join } = require('path');
|
|
21
|
-
const { homedir } = require('os');
|
|
22
|
-
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// Platform detection
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
|
|
27
|
-
// ---------------------------------------------------------------------------
|
|
28
|
-
// Resolve platform binary
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Try to find the platform binary in ~/.khal-os/bin/ (postinstall fallback location).
|
|
33
|
-
* Returns { nodeBin, serverCjs } or null.
|
|
34
|
-
*/
|
|
35
|
-
function resolveFromCache() {
|
|
36
|
-
const platform = process.platform === 'darwin' ? 'darwin' : 'linux';
|
|
37
|
-
const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
|
|
38
|
-
const cacheDir = join(homedir(), '.khal-os', 'platform', `${platform}-${arch}`);
|
|
39
|
-
|
|
40
|
-
const nodeBin = join(cacheDir, 'bin', 'node');
|
|
41
|
-
const serverCjs = join(cacheDir, 'bin', 'server', 'server.cjs');
|
|
42
|
-
|
|
43
|
-
if (existsSync(nodeBin) && existsSync(serverCjs)) {
|
|
44
|
-
return { nodeBin, serverCjs };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
// Main
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
|
|
54
|
-
function main() {
|
|
55
|
-
// --update: clear cache and re-download
|
|
56
|
-
if (process.argv.includes('--update')) {
|
|
57
|
-
const platform = process.platform === 'darwin' ? 'darwin' : 'linux';
|
|
58
|
-
const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
|
|
59
|
-
const cacheDir = join(homedir(), '.khal-os', 'platform', `${platform}-${arch}`);
|
|
60
|
-
try {
|
|
61
|
-
require('fs').rmSync(cacheDir, { recursive: true, force: true });
|
|
62
|
-
console.log('khal-os: Cache cleared. Re-downloading...\n');
|
|
63
|
-
} catch {
|
|
64
|
-
// Already gone
|
|
65
|
-
}
|
|
66
|
-
// Remove --update from argv so server doesn't see it
|
|
67
|
-
process.argv = process.argv.filter((a) => a !== '--update');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// 1. Try cached binary (downloaded on previous run or by postinstall)
|
|
71
|
-
const fromCache = resolveFromCache();
|
|
72
|
-
if (fromCache) {
|
|
73
|
-
return run(fromCache.nodeBin, fromCache.serverCjs);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// 2. Download from GitHub Releases (one npm package, binary from releases)
|
|
77
|
-
console.log('\nkhal-os: Downloading platform binary...');
|
|
78
|
-
console.log(' This is a one-time download.\n');
|
|
79
|
-
try {
|
|
80
|
-
// postinstall script handles the download
|
|
81
|
-
const { execSync: exec } = require('child_process');
|
|
82
|
-
exec('node ' + join(__dirname, '..', 'install.cjs'), {
|
|
83
|
-
stdio: 'inherit',
|
|
84
|
-
env: { ...process.env, KHAL_OS_FORCE_DOWNLOAD: '1' },
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Retry cache after download
|
|
88
|
-
const afterDownload = resolveFromCache();
|
|
89
|
-
if (afterDownload) {
|
|
90
|
-
return run(afterDownload.nodeBin, afterDownload.serverCjs);
|
|
91
|
-
}
|
|
92
|
-
} catch {
|
|
93
|
-
// Download failed
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// 3. No binary available
|
|
97
|
-
console.error('\nkhal-os: Could not download platform binary.');
|
|
98
|
-
console.error('Check your internet connection or GitHub access.');
|
|
99
|
-
console.error('You may need to authenticate: gh auth login\n');
|
|
100
|
-
process.exit(1);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function run(nodeBin, serverCjs) {
|
|
104
|
-
try {
|
|
105
|
-
execFileSync(nodeBin, [serverCjs, ...process.argv.slice(2)], {
|
|
106
|
-
stdio: 'inherit',
|
|
107
|
-
env: process.env,
|
|
108
|
-
});
|
|
109
|
-
} catch (err) {
|
|
110
|
-
// execFileSync throws on non-zero exit. The child already printed to stdio.
|
|
111
|
-
if (err.status != null) {
|
|
112
|
-
process.exit(err.status);
|
|
113
|
-
}
|
|
114
|
-
// Actual exec error (binary missing, permission denied, etc.)
|
|
115
|
-
console.error(`khal-os: Failed to execute binary: ${err.message}`);
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
main();
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* khal-os postinstall — verify platform binary exists, fallback to GitHub Release.
|
|
5
|
-
*
|
|
6
|
-
* Pattern: same as esbuild's install.js
|
|
7
|
-
*
|
|
8
|
-
* When npm installs khal-os, it should also install the correct platform package
|
|
9
|
-
* via optionalDependencies (e.g., khal-os-darwin-arm64). But if the user ran
|
|
10
|
-
* `npm install --ignore-optional` or their registry doesn't support optional deps,
|
|
11
|
-
* this script downloads the platform binary from GitHub Releases.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const { existsSync, mkdirSync, createWriteStream, chmodSync, rmSync } = require('fs');
|
|
15
|
-
const { join, dirname } = require('path');
|
|
16
|
-
const { homedir } = require('os');
|
|
17
|
-
const https = require('https');
|
|
18
|
-
|
|
19
|
-
const REPO = 'namastexlabs/genie-os';
|
|
20
|
-
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// Platform detection
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
|
|
25
|
-
function getPlatformInfo() {
|
|
26
|
-
const platform = process.platform === 'darwin' ? 'darwin' : 'linux';
|
|
27
|
-
const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
|
|
28
|
-
return { platform, arch, pkgName: `khal-os-${platform}-${arch}` };
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
// Check if platform package was installed
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
|
|
35
|
-
function isPlatformPackageInstalled() {
|
|
36
|
-
const { pkgName } = getPlatformInfo();
|
|
37
|
-
try {
|
|
38
|
-
const pkgJson = require.resolve(`${pkgName}/package.json`);
|
|
39
|
-
const pkgDir = dirname(pkgJson);
|
|
40
|
-
const nodeBin = join(pkgDir, 'bin', 'node');
|
|
41
|
-
const serverCjs = join(pkgDir, 'bin', 'server', 'server.cjs');
|
|
42
|
-
return existsSync(nodeBin) && existsSync(serverCjs);
|
|
43
|
-
} catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
// Get version
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
|
|
52
|
-
function getVersion() {
|
|
53
|
-
try {
|
|
54
|
-
const pkg = require(join(__dirname, '..', '..', 'package.json'));
|
|
55
|
-
if (pkg.version && pkg.version !== '0.0.0') return pkg.version;
|
|
56
|
-
} catch {
|
|
57
|
-
// Not found at expected path
|
|
58
|
-
}
|
|
59
|
-
try {
|
|
60
|
-
const pkg = require(join(__dirname, 'package.json'));
|
|
61
|
-
if (pkg.version && pkg.version !== '0.0.0') return pkg.version;
|
|
62
|
-
} catch {
|
|
63
|
-
// Not found
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
|
-
// Download helpers
|
|
70
|
-
// ---------------------------------------------------------------------------
|
|
71
|
-
|
|
72
|
-
function downloadFile(url, dest) {
|
|
73
|
-
return new Promise((resolve, reject) => {
|
|
74
|
-
function doRequest(requestUrl, redirects) {
|
|
75
|
-
if (redirects > 10) return reject(new Error('Too many redirects'));
|
|
76
|
-
|
|
77
|
-
const mod = requestUrl.startsWith('https:') ? https : require('http');
|
|
78
|
-
const parsedUrl = new URL(requestUrl);
|
|
79
|
-
|
|
80
|
-
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
81
|
-
const headers = { 'User-Agent': 'khal-os-install' };
|
|
82
|
-
if (token && requestUrl.includes('github.com')) {
|
|
83
|
-
headers['Authorization'] = `token ${token}`;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
mod
|
|
87
|
-
.get(
|
|
88
|
-
{
|
|
89
|
-
hostname: parsedUrl.hostname,
|
|
90
|
-
path: parsedUrl.pathname + parsedUrl.search,
|
|
91
|
-
headers,
|
|
92
|
-
},
|
|
93
|
-
(res) => {
|
|
94
|
-
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
95
|
-
return doRequest(res.headers.location, redirects + 1);
|
|
96
|
-
}
|
|
97
|
-
if (res.statusCode !== 200) {
|
|
98
|
-
return reject(new Error(`HTTP ${res.statusCode}`));
|
|
99
|
-
}
|
|
100
|
-
const file = createWriteStream(dest);
|
|
101
|
-
res.pipe(file);
|
|
102
|
-
file.on('finish', () => {
|
|
103
|
-
file.close();
|
|
104
|
-
resolve();
|
|
105
|
-
});
|
|
106
|
-
res.on('error', reject);
|
|
107
|
-
}
|
|
108
|
-
)
|
|
109
|
-
.on('error', reject);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
doRequest(url, 0);
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
|
-
// Main
|
|
118
|
-
// ---------------------------------------------------------------------------
|
|
119
|
-
|
|
120
|
-
async function main() {
|
|
121
|
-
// Skip in CI or if explicitly told not to
|
|
122
|
-
if (process.env.KHAL_OS_SKIP_INSTALL === '1') return;
|
|
123
|
-
|
|
124
|
-
// Check if platform package was installed normally
|
|
125
|
-
if (process.env.KHAL_OS_FORCE_DOWNLOAD !== '1' && isPlatformPackageInstalled()) {
|
|
126
|
-
// All good — platform binary available via optionalDependencies
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const version = getVersion();
|
|
131
|
-
if (!version) {
|
|
132
|
-
console.warn('khal-os: Could not determine version, skipping binary download.');
|
|
133
|
-
console.warn(' The platform binary will be downloaded on first run.');
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const { platform, arch } = getPlatformInfo();
|
|
138
|
-
const tag = `v${version}`;
|
|
139
|
-
const assetName = `khal-os-platform-${platform}-${arch}.tar.gz`;
|
|
140
|
-
const cacheDir = join(homedir(), '.khal-os', 'platform', `${platform}-${arch}`);
|
|
141
|
-
const tmpArchive = join(homedir(), '.khal-os', 'platform', `${assetName}.tmp`);
|
|
142
|
-
|
|
143
|
-
// Check if already cached
|
|
144
|
-
if (existsSync(join(cacheDir, 'bin', 'node')) && existsSync(join(cacheDir, 'bin', 'server', 'server.cjs'))) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
console.log('khal-os: Platform package not found, downloading from GitHub Release...');
|
|
149
|
-
console.log(' ' + REPO + '@' + tag + ' for ' + platform + '-' + arch);
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
mkdirSync(dirname(tmpArchive), { recursive: true });
|
|
153
|
-
mkdirSync(cacheDir, { recursive: true });
|
|
154
|
-
|
|
155
|
-
// Use gh CLI for private repos (handles auth natively)
|
|
156
|
-
const { execSync } = require('child_process');
|
|
157
|
-
try {
|
|
158
|
-
execSync(
|
|
159
|
-
`gh release download "${tag}" --repo "${REPO}" --pattern "${assetName}" --dir "${dirname(tmpArchive)}" --clobber`,
|
|
160
|
-
{ stdio: 'pipe', timeout: 120000 }
|
|
161
|
-
);
|
|
162
|
-
const ghDownloaded = join(dirname(tmpArchive), assetName);
|
|
163
|
-
if (existsSync(ghDownloaded) && ghDownloaded !== tmpArchive) {
|
|
164
|
-
require('fs').renameSync(ghDownloaded, tmpArchive);
|
|
165
|
-
}
|
|
166
|
-
} catch {
|
|
167
|
-
// gh CLI failed — try direct HTTPS (works for public repos)
|
|
168
|
-
const url = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
169
|
-
await downloadFile(url, tmpArchive);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Extract
|
|
173
|
-
execSync(`tar xzf "${tmpArchive}" -C "${cacheDir}"`, { stdio: 'pipe' });
|
|
174
|
-
|
|
175
|
-
// Make node binary executable
|
|
176
|
-
const nodeBin = join(cacheDir, 'bin', 'node');
|
|
177
|
-
if (existsSync(nodeBin)) {
|
|
178
|
-
chmodSync(nodeBin, 0o755);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
console.log('khal-os: Platform binary cached at ' + cacheDir);
|
|
182
|
-
} catch (err) {
|
|
183
|
-
console.warn('khal-os: Failed to download platform binary: ' + err.message);
|
|
184
|
-
console.warn(' The binary will be downloaded on first run.');
|
|
185
|
-
} finally {
|
|
186
|
-
try {
|
|
187
|
-
rmSync(tmpArchive, { force: true });
|
|
188
|
-
} catch {
|
|
189
|
-
// Best effort
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
main().catch((err) => {
|
|
195
|
-
// Postinstall must not fail the entire npm install
|
|
196
|
-
console.warn(`khal-os: postinstall warning: ${err.message}`);
|
|
197
|
-
});
|