@luutuankiet/gsd-reader 0.2.18 → 0.2.20

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/cli.cjs +35 -21
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -242,28 +242,35 @@ function promptPassword(prompt) {
242
242
  });
243
243
  }
244
244
 
245
- function httpRequest(url, options, data) {
246
- return new Promise((resolve, reject) => {
247
- const protocol = url.protocol === 'https:' ? https : http;
248
-
249
- const req = protocol.request(url, options, (res) => {
250
- let body = '';
251
- res.on('data', (chunk) => body += chunk);
252
- res.on('end', () => {
253
- if (res.statusCode >= 200 && res.statusCode < 300) {
254
- resolve(body.trim() || `HTTP ${res.statusCode}`);
255
- } else if (res.statusCode === 401) {
256
- reject(new Error('Authentication failed (401). Check username/password.'));
257
- } else {
258
- reject(new Error(`HTTP ${res.statusCode}: ${body}`));
259
- }
260
- });
245
+ async function httpRequest(url, options, data) {
246
+ const controller = new AbortController();
247
+ const timeout = setTimeout(() => controller.abort(), 30000);
248
+
249
+ try {
250
+ const res = await fetch(url, {
251
+ method: options.method || 'POST',
252
+ headers: options.headers,
253
+ body: data,
254
+ signal: controller.signal,
261
255
  });
262
-
263
- req.on('error', reject);
264
- req.write(data);
265
- req.end();
266
- });
256
+
257
+ const body = await res.text();
258
+
259
+ if (res.ok) {
260
+ return body.trim() || `HTTP ${res.status}`;
261
+ } else if (res.status === 401) {
262
+ throw new Error('Authentication failed (401). Check username/password.');
263
+ } else {
264
+ throw new Error(`HTTP ${res.status}: ${body}`);
265
+ }
266
+ } catch (err) {
267
+ if (err.name === 'AbortError') {
268
+ throw new Error('Request timed out after 30s. Check server/proxy status.');
269
+ }
270
+ throw err;
271
+ } finally {
272
+ clearTimeout(timeout);
273
+ }
267
274
  }
268
275
 
269
276
  // =============================================================================
@@ -485,11 +492,18 @@ function commandServe() {
485
492
  process.on('SIGINT', () => {
486
493
  console.log('\n[gsd-reader] Shutting down...');
487
494
  watcher.close();
495
+ // Force-terminate all WebSocket clients immediately
496
+ wss.clients.forEach(client => client.terminate());
488
497
  wss.close();
489
498
  server.close(() => {
490
499
  console.log('[gsd-reader] Goodbye!');
491
500
  process.exit(0);
492
501
  });
502
+ // Safety net: force exit after 2s if connections still linger
503
+ setTimeout(() => {
504
+ console.log('[gsd-reader] Force exit (connections still open)');
505
+ process.exit(0);
506
+ }, 2000).unref();
493
507
  });
494
508
 
495
509
  process.on('SIGTERM', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luutuankiet/gsd-reader",
3
- "version": "0.2.18",
3
+ "version": "0.2.20",
4
4
  "description": "Interactive Worklog Reader for GSD-Lite WORK.md files with live reload",
5
5
  "keywords": [
6
6
  "gsd-lite",