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.
package/bin/lobsterboard.mjs
CHANGED
|
@@ -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
|
-
|
|
13
|
-
env: { ...process.env },
|
|
13
|
+
env: { ...process.env, LOBSTERBOARD_PKG_DIR: packageDir },
|
|
14
14
|
stdio: 'inherit'
|
|
15
15
|
});
|
|
16
16
|
|
package/dist/lobsterboard.css
CHANGED
package/dist/lobsterboard.esm.js
CHANGED
package/dist/lobsterboard.umd.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lobsterboard",
|
|
3
|
-
"version": "0.6.
|
|
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
|
|
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(
|
|
67
|
+
const PKG_PAGES_DIR = path.join(PKG_DIR, 'pages');
|
|
66
68
|
const PAGES_DIRS = [PKG_PAGES_DIR]; // Package pages first
|
|
67
|
-
if (CWD !==
|
|
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
|
-
|
|
370
|
-
const
|
|
371
|
-
const
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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) {
|