kitowall 3.5.12 → 3.5.13

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.
Files changed (2) hide show
  1. package/dist/core/init.js +93 -10
  2. package/package.json +1 -1
package/dist/core/init.js CHANGED
@@ -16,6 +16,87 @@ function esc(a) {
16
16
  // ExecStart=... necesita escapado simple. JSON.stringify funciona bien para espacios/comillas.
17
17
  return JSON.stringify(a);
18
18
  }
19
+ async function runHostShell(cmd) {
20
+ if (process.env.FLATPAK_ID) {
21
+ return (0, exec_1.run)('flatpak-spawn', ['--host', 'sh', '-lc', cmd]);
22
+ }
23
+ return (0, exec_1.run)('sh', ['-lc', cmd]);
24
+ }
25
+ async function hostCmdExists(cmd) {
26
+ try {
27
+ await runHostShell(`command -v ${cmd} >/dev/null 2>&1`);
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ async function ensureHostDeps() {
35
+ const required = ['swww', 'swww-daemon', 'hyprctl', 'mpvpaper'];
36
+ const missing = [];
37
+ for (const dep of required) {
38
+ if (!(await hostCmdExists(dep)))
39
+ missing.push(dep);
40
+ }
41
+ if (missing.length === 0)
42
+ return;
43
+ const pkgSet = new Set();
44
+ if (missing.includes('swww') || missing.includes('swww-daemon'))
45
+ pkgSet.add('swww');
46
+ if (missing.includes('hyprctl'))
47
+ pkgSet.add('hyprland');
48
+ if (missing.includes('mpvpaper'))
49
+ pkgSet.add('mpvpaper');
50
+ const packages = Array.from(pkgSet);
51
+ // Best effort auto-install on Arch host; if it fails, we keep a clear actionable error.
52
+ if (packages.length > 0 && await hostCmdExists('pacman')) {
53
+ const pkgArgs = packages.join(' ');
54
+ await runHostShell(`if command -v sudo >/dev/null 2>&1; then ` +
55
+ `(sudo -n pacman -S --needed --noconfirm ${pkgArgs} || sudo pacman -S --needed ${pkgArgs}); ` +
56
+ `else pacman -S --needed ${pkgArgs}; fi`).catch(() => { });
57
+ }
58
+ const stillMissing = [];
59
+ for (const dep of required) {
60
+ if (!(await hostCmdExists(dep)))
61
+ stillMissing.push(dep);
62
+ }
63
+ if (stillMissing.length > 0) {
64
+ throw new Error(`Missing host dependencies: ${stillMissing.join(', ')}. ` +
65
+ `Install on host (Arch): sudo pacman -S --needed swww hyprland mpvpaper`);
66
+ }
67
+ }
68
+ async function ensureHostRendercoreBridge(appId) {
69
+ const home = (0, node_os_1.homedir)();
70
+ const localBinDir = (0, node_path_1.join)(home, '.local', 'bin');
71
+ ensureDir(localBinDir);
72
+ const bridgePath = (0, node_path_1.join)(localBinDir, 'kitsune-rendercore');
73
+ const bridgeScript = `#!/usr/bin/env bash
74
+ set -euo pipefail
75
+ exec /usr/bin/flatpak run --command=kitsune-rendercore ${appId} "$@"
76
+ `;
77
+ (0, node_fs_1.writeFileSync)(bridgePath, bridgeScript, { encoding: 'utf8', mode: 0o755 });
78
+ const userDir = (0, node_path_1.join)(home, '.config', 'systemd', 'user');
79
+ ensureDir(userDir);
80
+ const unitPath = (0, node_path_1.join)(userDir, 'kitsune-rendercore.service');
81
+ const unit = `
82
+ [Unit]
83
+ Description=Kitsune RenderCore Live Wallpaper (Flatpak bridge)
84
+ After=graphical-session.target
85
+ PartOf=graphical-session.target
86
+
87
+ [Service]
88
+ Type=simple
89
+ ExecStart=${bridgePath}
90
+ Restart=on-failure
91
+ RestartSec=1
92
+
93
+ [Install]
94
+ WantedBy=default.target
95
+ `.trimStart();
96
+ (0, node_fs_1.writeFileSync)(unitPath, unit, 'utf8');
97
+ await (0, exec_1.run)('systemctl', ['--user', 'daemon-reload']);
98
+ await (0, exec_1.run)('systemctl', ['--user', 'enable', '--now', 'kitsune-rendercore.service']).catch(() => { });
99
+ }
19
100
  async function disableIfExists(unit) {
20
101
  await (0, exec_1.run)('systemctl', ['--user', 'disable', '--now', unit]).catch(() => { });
21
102
  await (0, exec_1.run)('systemctl', ['--user', 'reset-failed', unit]).catch(() => { });
@@ -39,24 +120,26 @@ async function detectAndHandleConflicts(force) {
39
120
  }
40
121
  }
41
122
  async function initKitowall(opts) {
42
- if (process.env.FLATPAK_ID) {
43
- throw new Error('init/repair cannot be executed from Flatpak UI because it would generate host systemd units with sandbox paths. ' +
44
- 'Run on host shell: kitowall init --namespace kitowall --apply --force (or, in local dev, node dist/cli.js init --namespace kitowall --apply --force)');
45
- }
46
123
  const config = (0, config_1.loadConfig)(); // crea/migra config si hace falta
47
124
  const state = (0, state_1.loadState)(); // crea/migra state si hace falta
48
125
  const ns = (opts.namespace && opts.namespace.trim()) ? opts.namespace.trim() : 'kitowall';
49
126
  const force = !!opts.force;
127
+ const isFlatpak = Boolean(process.env.FLATPAK_ID);
128
+ const flatpakAppId = (process.env.FLATPAK_ID || 'io.kitotsu.KitoWall').trim();
50
129
  // Validaciones mínimas
51
- await (0, exec_1.run)('which', ['swww']).catch(() => { throw new Error('Missing dependency: swww'); });
52
- await (0, exec_1.run)('which', ['swww-daemon']).catch(() => { throw new Error('Missing dependency: swww-daemon'); });
53
- await (0, exec_1.run)('which', ['hyprctl']).catch(() => { throw new Error('Missing dependency: hyprctl'); });
130
+ await ensureHostDeps();
131
+ if (isFlatpak) {
132
+ await ensureHostRendercoreBridge(flatpakAppId);
133
+ }
54
134
  // Apagar servicios que pisan el wallpaper
55
135
  await detectAndHandleConflicts(force);
56
136
  const userDir = (0, node_path_1.join)((0, node_os_1.homedir)(), '.config', 'systemd', 'user');
57
137
  ensureDir(userDir);
58
138
  const nodePath = process.execPath;
59
139
  const cliPath = (0, node_path_1.resolve)(process.argv[1]); // dist/cli.js absoluto
140
+ const cliInvoke = isFlatpak
141
+ ? `/usr/bin/flatpak run --command=kitowall ${flatpakAppId}`
142
+ : `${JSON.stringify(nodePath)} ${JSON.stringify(cliPath)}`;
60
143
  const xdgRuntimeDir = (process.env.XDG_RUNTIME_DIR && process.env.XDG_RUNTIME_DIR.trim())
61
144
  ? process.env.XDG_RUNTIME_DIR.trim()
62
145
  : `/run/user/${process.getuid?.() ?? 1000}`;
@@ -92,7 +175,7 @@ WantedBy=graphical-session.target
92
175
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(userDir, 'swww-daemon@.service'), swwwDaemonTemplate, 'utf8');
93
176
  // 2) kitowall-next.service (oneshot)
94
177
  // OJO: aunque CLI ignore --namespace en algunos comandos, aquí lo dejamos por compatibilidad.
95
- const nextExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${nodePath} ${esc(cliPath)} ${esc('next')} ${esc('--namespace')} ${esc(ns)}`)}`;
178
+ const nextExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${cliInvoke} next --namespace ${JSON.stringify(ns)}`)}`;
96
179
  const kitowallNextService = `
97
180
  [Unit]
98
181
  Description=Kitowall apply next wallpapers
@@ -107,7 +190,7 @@ ExecStart=${nextExec}
107
190
  `.trimStart();
108
191
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(userDir, 'kitowall-next.service'), kitowallNextService, 'utf8');
109
192
  // 3) kitowall-watch.service (hotplug watcher)
110
- const watchExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${nodePath} ${esc(cliPath)} ${esc('watch')} ${esc('--namespace')} ${esc(ns)}`)}`;
193
+ const watchExec = `/bin/sh -lc ${esc(`${waylandBootstrap} exec ${cliInvoke} watch --namespace ${JSON.stringify(ns)}`)}`;
111
194
  const kitowallWatchService = `
112
195
  [Unit]
113
196
  Description=Kitowall watcher (monitor hotplug)
@@ -128,7 +211,7 @@ WantedBy=graphical-session.target
128
211
  `.trimStart();
129
212
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(userDir, 'kitowall-watch.service'), kitowallWatchService, 'utf8');
130
213
  // 4) kitowall-login-apply.service (apply once on login to avoid gray background)
131
- const loginApplyExec = `/bin/sh -lc ${esc(`sleep 2; ${waylandBootstrap} exec ${nodePath} ${esc(cliPath)} ${esc('rotate-now')} ${esc('--namespace')} ${esc(ns)} ${esc('--force')}`)}`;
214
+ const loginApplyExec = `/bin/sh -lc ${esc(`sleep 2; ${waylandBootstrap} exec ${cliInvoke} rotate-now --namespace ${JSON.stringify(ns)} --force`)}`;
132
215
  const kitowallLoginApplyService = `
133
216
  [Unit]
134
217
  Description=Kitowall apply wallpapers on session start
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitowall",
3
- "version": "3.5.12",
3
+ "version": "3.5.13",
4
4
  "description": "CLI/daemon for Hyprland wallpapers using swww with pack-based rotation.",
5
5
  "repository": {
6
6
  "type": "git",