mdboard 1.0.0 → 1.2.0
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/api.js +752 -0
- package/bin.js +56 -0
- package/config.js +73 -0
- package/defaults.json +43 -0
- package/index.html +865 -137
- package/init.js +45 -4
- package/package.json +9 -2
- package/scanner.js +491 -0
- package/server.js +269 -542
- package/watcher.js +131 -0
- package/workspace.js +220 -0
- package/yaml.js +129 -0
package/bin.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
const path = require('path');
|
|
3
4
|
const args = process.argv.slice(2);
|
|
5
|
+
|
|
6
|
+
// Pre-process --config and --workspace flags before dispatching commands
|
|
7
|
+
for (let i = 0; i < args.length; i++) {
|
|
8
|
+
if (args[i] === '--config' && args[i + 1]) {
|
|
9
|
+
process.env.MDBOARD_CONFIG = path.resolve(args[i + 1]);
|
|
10
|
+
}
|
|
11
|
+
if (args[i] === '--workspace' && args[i + 1]) {
|
|
12
|
+
process.env.MDBOARD_WORKSPACE = path.resolve(args[i + 1]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
const command = args[0];
|
|
5
17
|
|
|
6
18
|
if (command === '--version' || command === '-v') {
|
|
@@ -19,11 +31,45 @@ if (command === 'init') {
|
|
|
19
31
|
} else if (command === 'help') {
|
|
20
32
|
printHelp();
|
|
21
33
|
process.exit(0);
|
|
34
|
+
} else if (command === 'cache') {
|
|
35
|
+
handleCache();
|
|
22
36
|
} else {
|
|
23
37
|
// Default: start server. Pass all args through.
|
|
24
38
|
require('./server.js');
|
|
25
39
|
}
|
|
26
40
|
|
|
41
|
+
function handleCache() {
|
|
42
|
+
const subCmd = args[1];
|
|
43
|
+
const { listCache, cleanCache, CACHE_DIR } = require('./workspace');
|
|
44
|
+
|
|
45
|
+
if (subCmd === 'list') {
|
|
46
|
+
const entries = listCache();
|
|
47
|
+
if (entries.length === 0) {
|
|
48
|
+
console.log('\n No cached remote repos.\n Cache dir: ' + CACHE_DIR + '\n');
|
|
49
|
+
} else {
|
|
50
|
+
console.log('\n Cached remote repos (' + CACHE_DIR + '):\n');
|
|
51
|
+
entries.forEach(function(e) { console.log(' ' + e); });
|
|
52
|
+
console.log('');
|
|
53
|
+
}
|
|
54
|
+
} else if (subCmd === 'clean') {
|
|
55
|
+
const ok = cleanCache();
|
|
56
|
+
if (ok) {
|
|
57
|
+
console.log('\n Cache cleaned successfully.\n');
|
|
58
|
+
} else {
|
|
59
|
+
console.log('\n No cache to clean or error occurred.\n');
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
console.log(`
|
|
63
|
+
mdboard cache — Manage remote source cache
|
|
64
|
+
|
|
65
|
+
Subcommands:
|
|
66
|
+
mdboard cache list List cached remote repos
|
|
67
|
+
mdboard cache clean Remove all cached repos
|
|
68
|
+
`);
|
|
69
|
+
}
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
|
|
27
73
|
function printHelp() {
|
|
28
74
|
console.log(`
|
|
29
75
|
mdboard — Git-based project management dashboard
|
|
@@ -31,16 +77,26 @@ function printHelp() {
|
|
|
31
77
|
Usage:
|
|
32
78
|
mdboard Start the dashboard server
|
|
33
79
|
mdboard init Scaffold a new project/ directory
|
|
80
|
+
mdboard cache list|clean Manage remote source cache
|
|
34
81
|
mdboard --version Print version
|
|
35
82
|
mdboard --help Show this help
|
|
36
83
|
|
|
37
84
|
Server options:
|
|
38
85
|
--project <path> Workspace root directory (default: cwd)
|
|
39
86
|
--port <number> Server port (default: 3333)
|
|
87
|
+
--config <path> Path to mdboard.json config file
|
|
88
|
+
--workspace <path> Path to workspace.json
|
|
89
|
+
|
|
90
|
+
Multi-repo workspace:
|
|
91
|
+
Create a workspace.json in your project root to manage
|
|
92
|
+
multiple repositories from a single dashboard.
|
|
40
93
|
|
|
41
94
|
Examples:
|
|
42
95
|
npx mdboard Start dashboard in current directory
|
|
43
96
|
npx mdboard init Create project/ with templates
|
|
44
97
|
npx mdboard --port 4000 Start on port 4000
|
|
98
|
+
npx mdboard --workspace ./workspace.json
|
|
99
|
+
npx mdboard cache list Show cached remote repos
|
|
100
|
+
npx mdboard cache clean Clear remote cache
|
|
45
101
|
`);
|
|
46
102
|
}
|
package/config.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mdboard — Configuration loader
|
|
3
|
+
*
|
|
4
|
+
* Resolution order (highest priority first):
|
|
5
|
+
* 1. Explicit path via --config / MDBOARD_CONFIG
|
|
6
|
+
* 2. <projectDir>/project/mdboard.json (per-project)
|
|
7
|
+
* 3. <projectDir>/mdboard.json (workspace)
|
|
8
|
+
* 4. ~/.config/mdboard/mdboard.json (global)
|
|
9
|
+
* 5. defaults.json (built-in)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const os = require('os');
|
|
15
|
+
|
|
16
|
+
const defaults = require('./defaults.json');
|
|
17
|
+
|
|
18
|
+
function deepMerge(target, source) {
|
|
19
|
+
const result = { ...target };
|
|
20
|
+
for (const key of Object.keys(source)) {
|
|
21
|
+
const sv = source[key];
|
|
22
|
+
const tv = target[key];
|
|
23
|
+
if (sv && typeof sv === 'object' && !Array.isArray(sv) && tv && typeof tv === 'object' && !Array.isArray(tv)) {
|
|
24
|
+
result[key] = deepMerge(tv, sv);
|
|
25
|
+
} else {
|
|
26
|
+
result[key] = sv;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function tryReadJson(filePath) {
|
|
33
|
+
try {
|
|
34
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
35
|
+
return JSON.parse(raw);
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function loadConfig(projectDir, explicitPath) {
|
|
42
|
+
const candidates = [];
|
|
43
|
+
|
|
44
|
+
if (explicitPath) {
|
|
45
|
+
candidates.push(path.resolve(explicitPath));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (projectDir) {
|
|
49
|
+
candidates.push(path.join(projectDir, 'project', 'mdboard.json'));
|
|
50
|
+
candidates.push(path.join(projectDir, 'mdboard.json'));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const globalPath = path.join(os.homedir(), '.config', 'mdboard', 'mdboard.json');
|
|
54
|
+
candidates.push(globalPath);
|
|
55
|
+
|
|
56
|
+
let userConfig = null;
|
|
57
|
+
let configPath = null;
|
|
58
|
+
|
|
59
|
+
for (const p of candidates) {
|
|
60
|
+
const data = tryReadJson(p);
|
|
61
|
+
if (data) {
|
|
62
|
+
userConfig = data;
|
|
63
|
+
configPath = p;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const config = userConfig ? deepMerge(defaults, userConfig) : { ...defaults };
|
|
69
|
+
config._path = configPath;
|
|
70
|
+
return config;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = { loadConfig, deepMerge };
|
package/defaults.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"entities": {
|
|
3
|
+
"milestone": { "singular": "Milestone", "plural": "Milestones", "dir": "milestones" },
|
|
4
|
+
"epic": { "singular": "Epic", "plural": "Epics", "dir": "epics" },
|
|
5
|
+
"task": { "singular": "Task", "plural": "Tasks", "dir": "backlog", "prefix": "TASK", "legacyPrefixes": ["FEAT"] },
|
|
6
|
+
"sprint": { "singular": "Sprint", "plural": "Sprints", "dir": "sprints" }
|
|
7
|
+
},
|
|
8
|
+
"statuses": {
|
|
9
|
+
"task": [
|
|
10
|
+
{ "key": "backlog", "label": "Backlog", "color": "#5A5A63", "icon": "dashed-circle" },
|
|
11
|
+
{ "key": "todo", "label": "Todo", "color": "#8B8B93", "icon": "circle" },
|
|
12
|
+
{ "key": "in-progress", "label": "In Progress", "color": "#D4A72C", "icon": "half-circle" },
|
|
13
|
+
{ "key": "in-review", "label": "In Review", "color": "#8B5CF6", "icon": "three-quarter-circle" },
|
|
14
|
+
{ "key": "done", "label": "Done", "color": "#2EA043", "icon": "check-circle" },
|
|
15
|
+
{ "key": "blocked", "label": "Blocked", "color": "#DA3633", "icon": "x-circle" },
|
|
16
|
+
{ "key": "cancelled", "label": "Cancelled", "color": "#5A5A63", "icon": "slash-circle" }
|
|
17
|
+
],
|
|
18
|
+
"milestone": [
|
|
19
|
+
{ "key": "planned", "label": "Planned", "color": "#8B8B93" },
|
|
20
|
+
{ "key": "active", "label": "Active", "color": "#5B6EF5" },
|
|
21
|
+
{ "key": "completed", "label": "Completed", "color": "#2EA043" }
|
|
22
|
+
],
|
|
23
|
+
"epic": [
|
|
24
|
+
{ "key": "active", "label": "Active", "color": "#5B6EF5" },
|
|
25
|
+
{ "key": "completed", "label": "Completed", "color": "#2EA043" },
|
|
26
|
+
{ "key": "blocked", "label": "Blocked", "color": "#DA3633" }
|
|
27
|
+
],
|
|
28
|
+
"sprint": [
|
|
29
|
+
{ "key": "planned", "label": "Planned", "color": "#8B8B93" },
|
|
30
|
+
{ "key": "active", "label": "Active", "color": "#5B6EF5" },
|
|
31
|
+
{ "key": "completed", "label": "Completed", "color": "#2EA043" },
|
|
32
|
+
{ "key": "cancelled", "label": "Cancelled", "color": "#DA3633" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"boardColumns": ["backlog", "todo", "in-progress", "in-review", "done"],
|
|
36
|
+
"priorities": [
|
|
37
|
+
{ "key": "urgent", "label": "Urgent", "color": "#F97316", "bars": 4 },
|
|
38
|
+
{ "key": "high", "label": "High", "color": "#F97316", "bars": 3 },
|
|
39
|
+
{ "key": "medium", "label": "Medium", "color": "#D4A72C", "bars": 2 },
|
|
40
|
+
{ "key": "low", "label": "Low", "color": "#5B6EF5", "bars": 1 }
|
|
41
|
+
],
|
|
42
|
+
"completedStatus": "done"
|
|
43
|
+
}
|