lobsterboard 0.6.0 → 0.6.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.
@@ -8,9 +8,9 @@ const __filename = fileURLToPath(import.meta.url);
8
8
  const __dirname = dirname(__filename);
9
9
  const packageDir = join(__dirname, '..');
10
10
 
11
+ // Keep user's working directory so custom pages/data work
11
12
  const child = fork(join(packageDir, 'server.cjs'), {
12
- cwd: packageDir,
13
- env: { ...process.env },
13
+ env: { ...process.env, LOBSTERBOARD_PKG_DIR: packageDir },
14
14
  stdio: 'inherit'
15
15
  });
16
16
 
@@ -1,4 +1,4 @@
1
- /* LobsterBoard v0.6.0 - Dashboard Styles */
1
+ /* LobsterBoard v0.6.2 - Dashboard Styles */
2
2
  /* LobsterBoard Dashboard - Generated Styles */
3
3
 
4
4
  :root {
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * LobsterBoard v0.6.0
2
+ * LobsterBoard v0.6.2
3
3
  * Dashboard builder with customizable widgets
4
4
  * https://github.com/curbob/LobsterBoard
5
5
  * @license MIT
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * LobsterBoard v0.6.0
2
+ * LobsterBoard v0.6.2
3
3
  * Dashboard builder with customizable widgets
4
4
  * https://github.com/curbob/LobsterBoard
5
5
  * @license MIT
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * LobsterBoard v0.6.0
2
+ * LobsterBoard v0.6.2
3
3
  * Dashboard builder with customizable widgets
4
4
  * https://github.com/curbob/LobsterBoard
5
5
  * @license MIT
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * LobsterBoard v0.6.0
2
+ * LobsterBoard v0.6.2
3
3
  * Dashboard builder with customizable widgets
4
4
  * https://github.com/curbob/LobsterBoard
5
5
  * @license MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lobsterboard",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Self-hosted drag-and-drop dashboard builder with 50 widgets, template gallery, and custom pages. Works standalone or with OpenClaw.",
5
5
  "keywords": [
6
6
  "dashboard",
@@ -73,7 +73,7 @@
73
73
  "rollup-plugin-copy": "^3.5.0"
74
74
  },
75
75
  "engines": {
76
- "node": ">=16.0.0 <23.0.0"
76
+ "node": ">=16.0.0"
77
77
  },
78
78
  "dependencies": {
79
79
  "systeminformation": "^5.30.7"
package/server.cjs CHANGED
@@ -61,10 +61,12 @@ const HOST = process.env.HOST || '127.0.0.1';
61
61
  // ─────────────────────────────────────────────
62
62
  // Load from both package pages AND user's working directory pages (user overrides package)
63
63
  const CWD = process.cwd();
64
+ // When run via npx/bin, LOBSTERBOARD_PKG_DIR tells us where the package is
65
+ const PKG_DIR = process.env.LOBSTERBOARD_PKG_DIR || __dirname;
64
66
  const USER_PAGES_DIR = path.join(CWD, 'pages');
65
- const PKG_PAGES_DIR = path.join(__dirname, 'pages');
67
+ const PKG_PAGES_DIR = path.join(PKG_DIR, 'pages');
66
68
  const PAGES_DIRS = [PKG_PAGES_DIR]; // Package pages first
67
- if (CWD !== __dirname && fs.existsSync(USER_PAGES_DIR)) {
69
+ if (CWD !== PKG_DIR && fs.existsSync(USER_PAGES_DIR)) {
68
70
  PAGES_DIRS.push(USER_PAGES_DIR); // User pages override
69
71
  }
70
72
  // For backwards compat, PAGES_DIR points to first available (used for _shared)
@@ -366,9 +368,50 @@ const MIME_TYPES = {
366
368
  '.map': 'application/json' // For sourcemaps
367
369
  };
368
370
 
369
- const CONFIG_FILE = path.join(__dirname, 'config.json');
370
- const AUTH_FILE = path.join(__dirname, 'auth.json');
371
- const SECRETS_FILE = path.join(__dirname, 'secrets.json');
371
+ // User config files — stored in working directory (survives npm updates)
372
+ const CONFIG_FILE = path.join(CWD, 'config.json');
373
+ const AUTH_FILE = path.join(CWD, 'auth.json');
374
+ const SECRETS_FILE = path.join(CWD, 'secrets.json');
375
+
376
+ // ─────────────────────────────────────────────
377
+ // Migration: copy data from package dir to user dir (v0.6.2+)
378
+ // ─────────────────────────────────────────────
379
+ function migrateUserData() {
380
+ const filesToMigrate = ['config.json', 'auth.json', 'secrets.json', 'todos.json', 'notes.json'];
381
+ const dirsToMigrate = ['data'];
382
+ let migrated = [];
383
+
384
+ for (const file of filesToMigrate) {
385
+ const userPath = path.join(CWD, file);
386
+ const pkgPath = path.join(PKG_DIR, file);
387
+ if (!fs.existsSync(userPath) && fs.existsSync(pkgPath)) {
388
+ try {
389
+ fs.copyFileSync(pkgPath, userPath);
390
+ migrated.push(file);
391
+ } catch (e) { /* ignore */ }
392
+ }
393
+ }
394
+
395
+ for (const dir of dirsToMigrate) {
396
+ const userDir = path.join(CWD, dir);
397
+ const pkgDir = path.join(PKG_DIR, dir);
398
+ if (!fs.existsSync(userDir) && fs.existsSync(pkgDir)) {
399
+ try {
400
+ fs.cpSync(pkgDir, userDir, { recursive: true });
401
+ migrated.push(dir + '/');
402
+ } catch (e) { /* ignore */ }
403
+ }
404
+ }
405
+
406
+ if (migrated.length > 0) {
407
+ console.log(`📦 Migrated data to working directory: ${migrated.join(', ')}`);
408
+ }
409
+ }
410
+
411
+ // Run migration on startup
412
+ if (CWD !== PKG_DIR) {
413
+ migrateUserData();
414
+ }
372
415
 
373
416
  // ─────────────────────────────────────────────
374
417
  // Server-side Session Authentication
@@ -1699,7 +1742,7 @@ const aiUsageCache = {
1699
1742
  const AI_CACHE_TTL_MS = 300000; // 5 minutes cache
1700
1743
 
1701
1744
  // Persistent file cache (survives restarts)
1702
- const AI_CACHE_FILE = path.join(__dirname, 'data', 'ai-usage-cache.json');
1745
+ const AI_CACHE_FILE = path.join(CWD, 'data', 'ai-usage-cache.json');
1703
1746
 
1704
1747
  function loadPersistentCache() {
1705
1748
  try {
@@ -1892,7 +1935,7 @@ const server = http.createServer(async (req, res) => {
1892
1935
  // ─────────────────────────────────────────────
1893
1936
  // Server Profiles API (for remote LobsterBoard Agent connections)
1894
1937
  // ─────────────────────────────────────────────
1895
- const SERVERS_FILE = path.join(__dirname, 'data', 'servers.json');
1938
+ const SERVERS_FILE = path.join(CWD, 'data', 'servers.json');
1896
1939
 
1897
1940
  function loadServers() {
1898
1941
  try {
@@ -2411,7 +2454,7 @@ const server = http.createServer(async (req, res) => {
2411
2454
 
2412
2455
  // GET/POST /api/todos - Read/write todo list
2413
2456
  if (pathname === '/api/todos') {
2414
- const todosFile = path.join(__dirname, 'todos.json');
2457
+ const todosFile = path.join(CWD, 'todos.json');
2415
2458
  if (req.method === 'GET') {
2416
2459
  fs.readFile(todosFile, 'utf8', (err, data) => {
2417
2460
  if (err) {
@@ -2447,7 +2490,7 @@ const server = http.createServer(async (req, res) => {
2447
2490
 
2448
2491
  // GET/POST /api/notes - Read/write notes content
2449
2492
  if (pathname === '/api/notes') {
2450
- const notesFile = path.join(__dirname, 'notes.json');
2493
+ const notesFile = path.join(CWD, 'notes.json');
2451
2494
  if (req.method === 'GET') {
2452
2495
  fs.readFile(notesFile, 'utf8', (err, data) => {
2453
2496
  if (err) {