@walldock/agent 0.2.0 → 0.2.2

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/dist/main.js CHANGED
@@ -47,6 +47,7 @@ const pid_1 = require("./pid");
47
47
  const tray_1 = require("./tray");
48
48
  // ─── Logging ─────────────────────────────────────────────────────────────────
49
49
  const isDaemon = process.argv.includes('--daemon');
50
+ const isTray = process.argv.includes('--tray');
50
51
  function logDir() {
51
52
  if (process.platform === 'darwin')
52
53
  return path.join(os.homedir(), 'Library', 'Logs');
@@ -62,7 +63,7 @@ async function openLog() {
62
63
  }
63
64
  function log(msg) {
64
65
  const line = `[${new Date().toISOString()}] ${msg}\n`;
65
- if (isDaemon && logStream) {
66
+ if ((isDaemon || isTray) && logStream) {
66
67
  logStream.write(line).catch(() => undefined);
67
68
  }
68
69
  else {
@@ -74,6 +75,15 @@ async function main() {
74
75
  const args = process.argv.slice(2);
75
76
  // --unlink: remove stored credentials and startup entry
76
77
  if (args.includes('--unlink')) {
78
+ // Kill any running background instance first so the user can re-pair immediately
79
+ const bgPid = await (0, pid_1.runningPid)();
80
+ if (bgPid) {
81
+ try {
82
+ process.kill(bgPid);
83
+ }
84
+ catch { /* already dead */ }
85
+ await new Promise(r => setTimeout(r, 600));
86
+ }
77
87
  const token = await storage.getDeviceToken();
78
88
  if (token) {
79
89
  const api = new api_1.AgentApi();
@@ -96,7 +106,7 @@ async function main() {
96
106
  }
97
107
  return;
98
108
  }
99
- if (isDaemon)
109
+ if (isDaemon || isTray)
100
110
  await openLog();
101
111
  // Single-instance guard
102
112
  try {
@@ -104,6 +114,7 @@ async function main() {
104
114
  }
105
115
  catch (err) {
106
116
  console.error(`\n${err}`);
117
+ console.error('To re-link: right-click the tray icon → Quit, or run: walldock-agent --unlink');
107
118
  process.exit(1);
108
119
  }
109
120
  const api = new api_1.AgentApi(process.env['WALLDOCK_API_URL'] ?? undefined);
@@ -125,8 +136,8 @@ async function main() {
125
136
  log('Device token is no longer valid. Clearing credentials…');
126
137
  await storage.deleteDeviceToken();
127
138
  await storage.clearDeviceIdentity();
128
- if (isDaemon) {
129
- log('Run "walldock-agent" (without --daemon) to re-pair this device.');
139
+ if (isDaemon || isTray) {
140
+ log('Run "walldock-agent" to re-pair this device.');
130
141
  await shutdown();
131
142
  return;
132
143
  }
@@ -163,15 +174,28 @@ async function main() {
163
174
  }
164
175
  process.on('SIGINT', () => { void shutdown(); });
165
176
  process.on('SIGTERM', () => { void shutdown(); });
166
- function maybeStartTray() {
167
- if (isDaemon || trayHandle)
168
- return;
169
- try {
170
- trayHandle = (0, tray_1.startTray)(() => { void sync.syncNow(); }, () => { void shutdown(); });
171
- }
172
- catch {
173
- // tray unavailable (headless/no display) — continue without it
177
+ async function maybeStartTray() {
178
+ if (isDaemon)
179
+ return false;
180
+ if (isTray) {
181
+ // Already a detached background process start the tray in-place
182
+ try {
183
+ trayHandle = (0, tray_1.startTray)(() => { void sync.syncNow(); }, () => { void shutdown(); });
184
+ }
185
+ catch { /* no display — run headlessly */ }
186
+ return false;
174
187
  }
188
+ // Console-attached interactive session: re-spawn detached so closing the
189
+ // terminal doesn't kill the agent.
190
+ await (0, pid_1.releaseLock)();
191
+ const { spawn } = await Promise.resolve().then(() => __importStar(require('node:child_process')));
192
+ const child = spawn(process.execPath, [process.argv[1], '--tray'], {
193
+ detached: true,
194
+ stdio: 'ignore',
195
+ windowsHide: true,
196
+ });
197
+ child.unref();
198
+ return true;
175
199
  }
176
200
  // Try to resume from stored token
177
201
  log('Walldock Agent starting…');
@@ -179,15 +203,16 @@ async function main() {
179
203
  if (existing) {
180
204
  await storage.setDeviceIdentity({ deviceId: existing.deviceId, deviceName: existing.deviceName });
181
205
  log(`Linked as "${existing.deviceName}". Starting sync…`);
182
- maybeStartTray();
183
- sync.start({ token: existing.token, deviceId: existing.deviceId });
184
- if (trayHandle)
206
+ if (await maybeStartTray()) {
185
207
  console.log('Walldock Agent is running in the system tray.');
186
- return; // sync loop keeps process alive
208
+ process.exit(0);
209
+ }
210
+ sync.start({ token: existing.token, deviceId: existing.deviceId });
211
+ return; // sync loop keeps process alive (isTray path)
187
212
  }
188
213
  // No valid token — need to pair
189
- if (isDaemon) {
190
- log('No valid device token found. Run without --daemon to pair this device.');
214
+ if (isDaemon || isTray) {
215
+ log('No valid device token found. Run "walldock-agent" to pair this device.');
191
216
  process.exit(1);
192
217
  }
193
218
  // Interactive pairing
@@ -220,16 +245,13 @@ async function main() {
220
245
  }
221
246
  catch (err) {
222
247
  console.warn(` Could not register for startup: ${err}`);
223
- console.warn(' You can run "walldock-agent --daemon" manually to start syncing.');
248
+ console.warn(' You can run "walldock-agent" manually to start syncing.');
224
249
  }
225
250
  }
226
251
  }
227
- maybeStartTray();
228
- if (trayHandle) {
229
- console.log('\nWalldock Agent is running in the system tray. You can close this terminal.\n');
230
- }
231
- else {
232
- console.log('\nStarting sync. Press Ctrl+C to stop.\n');
252
+ if (await maybeStartTray()) {
253
+ console.log('\nWalldock Agent is running in the system tray.\n');
254
+ process.exit(0);
233
255
  }
234
256
  sync.start({ token: result.token, deviceId: result.deviceId });
235
257
  }
@@ -47,7 +47,7 @@ public class MonitorHelper {
47
47
  [MonitorHelper]::Enumerate() | ForEach-Object { Write-Output $_ }
48
48
  `.trim();
49
49
  async function listScreensWindows() {
50
- const { stdout } = await exec('powershell.exe', ['-NoProfile', '-Command', PS_SCRIPT]);
50
+ const { stdout } = await exec('powershell.exe', ['-NoProfile', '-Command', PS_SCRIPT], { windowsHide: true, encoding: 'utf8' });
51
51
  const screens = [];
52
52
  for (const line of stdout.trim().split(/\r?\n/)) {
53
53
  if (!line.trim())
package/dist/startup.js CHANGED
@@ -83,7 +83,7 @@ function plistContent(binPath) {
83
83
  <key>ProgramArguments</key>
84
84
  <array>
85
85
  <string>${binPath}</string>
86
- <string>--daemon</string>
86
+ <string>--tray</string>
87
87
  </array>
88
88
  <key>RunAtLoad</key>
89
89
  <true/>
@@ -112,7 +112,7 @@ const REG_KEY = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';
112
112
  const REG_VALUE = 'WalldockAgent';
113
113
  async function registerWindows() {
114
114
  const binPath = await resolveGlobalBin();
115
- const cmd = `"${binPath}" --daemon`;
115
+ const cmd = `"${binPath}" --tray`;
116
116
  await exec('reg', ['add', REG_KEY, '/v', REG_VALUE, '/t', 'REG_SZ', '/d', cmd, '/f']);
117
117
  }
118
118
  async function unregisterWindows() {
@@ -130,7 +130,7 @@ After=network-online.target
130
130
  Wants=network-online.target
131
131
 
132
132
  [Service]
133
- ExecStart=${binPath} --daemon
133
+ ExecStart=${binPath} --tray
134
134
  Restart=on-failure
135
135
  RestartSec=10s
136
136
 
@@ -142,7 +142,7 @@ function desktopContent(binPath) {
142
142
  return `[Desktop Entry]
143
143
  Type=Application
144
144
  Name=Walldock Agent
145
- Exec=${binPath} --daemon
145
+ Exec=${binPath} --tray
146
146
  Hidden=false
147
147
  NoDisplay=false
148
148
  X-GNOME-Autostart-enabled=true
@@ -53,5 +53,5 @@ public class WallpaperHelper {
53
53
  "@
54
54
  [WallpaperHelper]::Set(${monitorIndex}, '${safePath}')
55
55
  `.trim();
56
- await exec('powershell.exe', ['-NoProfile', '-Command', script]);
56
+ await exec('powershell.exe', ['-NoProfile', '-Command', script], { windowsHide: true, encoding: 'utf8' });
57
57
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walldock/agent",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Walldock desktop agent — sync wallpapers across all your screens",
5
5
  "license": "MIT",
6
6
  "main": "dist/main.js",