wukong-gitlog-cli 1.0.5 → 1.0.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.0.6](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.5...v1.0.6) (2025-11-29)
6
+
7
+
8
+ ### Features
9
+
10
+ * 🎸 auto open ([380e013](https://github.com/tomatobybike/wukong-gitlog-cli/commit/380e01386300342b5b4009f4ddf5463a19cf1be8))
11
+
5
12
  ### [1.0.5](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.4...v1.0.5) (2025-11-29)
6
13
 
7
14
  ### [1.0.4](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.3...v1.0.4) (2025-11-29)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wukong-gitlog-cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Advanced Git commit log exporter with Excel/JSON/TXT output, grouping, stats and CLI.",
5
5
  "keywords": [
6
6
  "git",
package/src/server.mjs CHANGED
@@ -1,8 +1,9 @@
1
- import http from 'http';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import chalk from 'chalk';
5
- import { fileURLToPath } from 'url';
1
+ import chalk from 'chalk'
2
+ import { exec } from 'child_process'
3
+ import fs from 'fs'
4
+ import http from 'http'
5
+ import path from 'path'
6
+ import { fileURLToPath } from 'url'
6
7
 
7
8
  const mime = new Map([
8
9
  ['.html', 'text/html; charset=utf-8'],
@@ -14,74 +15,116 @@ const mime = new Map([
14
15
  ['.png', 'image/png'],
15
16
  ['.jpg', 'image/jpeg'],
16
17
  ['.jpeg', 'image/jpeg'],
17
- ['.map', 'application/json; charset=utf-8'],
18
- ]);
18
+ ['.map', 'application/json; charset=utf-8']
19
+ ])
20
+
21
+ // --------------------------------
22
+ // 打开浏览器(跨平台)
23
+ // --------------------------------
24
+ function openBrowser(url) {
25
+ const { platform } = process
26
+
27
+ let cmd
28
+ if (platform === 'win32') {
29
+ cmd = `start "" "${url}"`
30
+ } else if (platform === 'darwin') {
31
+ cmd = `open "${url}"`
32
+ } else {
33
+ cmd = `xdg-open "${url}"`
34
+ }
35
+
36
+ exec(cmd, (err) => {
37
+ if (err) {
38
+ console.log(chalk.yellow(`Failed to auto-open browser: ${err.message}`))
39
+ }
40
+ })
41
+ }
19
42
 
20
43
  // eslint-disable-next-line default-param-last
21
44
  export function startServer(port = 3000, outputDir) {
22
45
  // 解析包根目录,确保 web 资源在全局安装后也能找到
23
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
- const pkgRoot = path.resolve(__dirname, '..');
25
- const webRoot = path.resolve(pkgRoot, 'web');
26
- const dataRoot = outputDir ? path.resolve(outputDir) : path.resolve(process.cwd(), 'output');
46
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
47
+ const pkgRoot = path.resolve(__dirname, '..')
48
+ const webRoot = path.resolve(pkgRoot, 'web')
49
+ const dataRoot = outputDir
50
+ ? path.resolve(outputDir)
51
+ : path.resolve(process.cwd(), 'output')
27
52
 
28
53
  // warn if web directory or data directory doesn't exist
29
54
  if (!fs.existsSync(webRoot)) {
30
- console.warn(chalk.yellow(`Warning: web/ directory not found at ${webRoot}. Server will still run but no UI will be available.`));
55
+ console.warn(
56
+ chalk.yellow(
57
+ `Warning: web/ directory not found at ${webRoot}. Server will still run but no UI will be available.`
58
+ )
59
+ )
31
60
  }
32
61
  if (!fs.existsSync(dataRoot)) {
33
- console.warn(chalk.yellow(`Warning: output data directory not found at ${dataRoot}. Server will still run but data endpoints (/data/) may 404.`));
62
+ console.warn(
63
+ chalk.yellow(
64
+ `Warning: output data directory not found at ${dataRoot}. Server will still run but data endpoints (/data/) may 404.`
65
+ )
66
+ )
34
67
  }
35
68
 
36
69
  const server = http.createServer((req, res) => {
37
70
  try {
38
71
  // Normalize URL path
39
- const u = new URL(req.url, `http://localhost`);
40
- let pathname = decodeURIComponent(u.pathname);
72
+ const u = new URL(req.url, `http://localhost`)
73
+ let pathname = decodeURIComponent(u.pathname)
41
74
 
42
75
  // Serve data files under /data/* mapped to dataRoot/data/*
43
76
  if (pathname.startsWith('/data/')) {
44
- const relative = pathname.replace(/^\/data\//, '');
45
- const fileLocal = path.join(dataRoot, 'data', relative);
77
+ const relative = pathname.replace(/^\/data\//, '')
78
+ const fileLocal = path.join(dataRoot, 'data', relative)
46
79
  if (fs.existsSync(fileLocal) && fs.statSync(fileLocal).isFile()) {
47
- const ext = path.extname(fileLocal).toLowerCase();
48
- res.setHeader('Content-Type', mime.get(ext) || 'application/octet-stream');
49
- res.setHeader('Access-Control-Allow-Origin', '*');
50
- const stream = fs.createReadStream(fileLocal);
51
- stream.pipe(res);
52
- return;
80
+ const ext = path.extname(fileLocal).toLowerCase()
81
+ res.setHeader(
82
+ 'Content-Type',
83
+ mime.get(ext) || 'application/octet-stream'
84
+ )
85
+ res.setHeader('Access-Control-Allow-Origin', '*')
86
+ const stream = fs.createReadStream(fileLocal)
87
+ stream.pipe(res)
88
+ return
53
89
  }
54
90
  }
55
91
 
56
92
  // Resolve web assets
57
- if (pathname === '/') pathname = '/index.html';
58
- const fileLocal = path.join(webRoot, pathname);
93
+ if (pathname === '/') pathname = '/index.html'
94
+ const fileLocal = path.join(webRoot, pathname)
59
95
  if (fs.existsSync(fileLocal) && fs.statSync(fileLocal).isFile()) {
60
- const ext = path.extname(fileLocal).toLowerCase();
61
- res.setHeader('Content-Type', mime.get(ext) || 'application/octet-stream');
62
- const stream = fs.createReadStream(fileLocal);
63
- stream.pipe(res);
64
- return;
96
+ const ext = path.extname(fileLocal).toLowerCase()
97
+ res.setHeader(
98
+ 'Content-Type',
99
+ mime.get(ext) || 'application/octet-stream'
100
+ )
101
+ const stream = fs.createReadStream(fileLocal)
102
+ stream.pipe(res)
103
+ return
65
104
  }
66
105
 
67
106
  // file not found
68
- res.statusCode = 404;
69
- res.setHeader('Content-Type', 'text/plain; charset=utf-8');
70
- res.end('Not Found');
107
+ res.statusCode = 404
108
+ res.setHeader('Content-Type', 'text/plain; charset=utf-8')
109
+ res.end('Not Found')
71
110
  } catch (err) {
72
- res.statusCode = 500;
73
- res.end('Server error');
111
+ res.statusCode = 500
112
+ res.end('Server error')
74
113
  }
75
- });
114
+ })
76
115
 
77
116
  return new Promise((resolve, reject) => {
78
- server.on('error', (err) => reject(err));
117
+ server.on('error', (err) => reject(err))
79
118
  server.listen(port, () => {
80
- console.log(chalk.green(`Server started at http://localhost:${port}`));
81
- console.log(chalk.green(`Serving web/ and output/data/`));
82
- resolve(server);
83
- });
84
- });
119
+ const url = `http://localhost:${port}`
120
+ console.log(chalk.green(`Server started at ${url}`))
121
+ console.log(chalk.green(`Serving web/ and output/data/`))
122
+
123
+ // ====== 自动打开浏览器 ======
124
+ openBrowser(url)
125
+ resolve(server)
126
+ })
127
+ })
85
128
  }
86
129
 
87
- export default startServer;
130
+ export default startServer