@crab-dev/wake 0.1.2 → 0.1.3

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
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3
4
+
5
+ - Improved the npm development-server terminal panel with Rust CLI-aligned styling, startup timing, rebuild progress, diagnostics, and color controls.
6
+
3
7
  ## 0.1.2
4
8
 
5
9
  - Updated the npm release pipeline for private GitHub repositories while preserving immutable tarball audits.
@@ -0,0 +1,77 @@
1
+ const RESET = '\x1b[0m'
2
+ const BOLD = '\x1b[1m'
3
+ const DIM = '\x1b[2m'
4
+ const RED = '\x1b[31m'
5
+ const GREEN = '\x1b[32m'
6
+ const YELLOW = '\x1b[33m'
7
+ const CYAN = '\x1b[36m'
8
+ const MAGENTA_BOLD = '\x1b[1;35m'
9
+
10
+ export function supportsColor(stream = process.stderr, env = process.env) {
11
+ return stream.isTTY === true && !Object.hasOwn(env, 'NO_COLOR')
12
+ }
13
+
14
+ export function createUi(color = supportsColor()) {
15
+ const wrap = (code, text) => color ? `${code}${text}${RESET}` : String(text)
16
+ return {
17
+ accent: (text) => wrap(CYAN, text),
18
+ bold: (text) => wrap(BOLD, text),
19
+ brand: (text) => wrap(MAGENTA_BOLD, text),
20
+ dim: (text) => wrap(DIM, text),
21
+ error: (text) => wrap(RED, text),
22
+ ok: (text) => wrap(GREEN, text),
23
+ warn: (text) => wrap(YELLOW, text),
24
+ }
25
+ }
26
+
27
+ export function humanDuration(durationMs) {
28
+ const milliseconds = Math.max(1, Number(durationMs) || 0)
29
+ if (milliseconds < 1_000) return `${milliseconds.toFixed(0)}ms`
30
+ if (milliseconds < 60_000) return `${(milliseconds / 1_000).toFixed(2)}s`
31
+ const seconds = milliseconds / 1_000
32
+ return `${Math.floor(seconds / 60)}m${(seconds % 60).toFixed(1)}s`
33
+ }
34
+
35
+ export function formatBanner(ui, command, currentVersion) {
36
+ return [
37
+ '',
38
+ ` ${ui.warn('⚡')} ${ui.brand('wake')} ${ui.dim(`v${currentVersion}`)} ${ui.dim(command)}`,
39
+ '',
40
+ ]
41
+ }
42
+
43
+ export function formatServerReady(ui, url, durationMs) {
44
+ return [
45
+ ` ${ui.ok('✓')} ${ui.bold('开发服务器已就绪')} ${ui.dim('·')} ${ui.accent(humanDuration(durationMs))}`,
46
+ '',
47
+ ` ${ui.dim('Local')} ${ui.accent(url)}`,
48
+ ` ${ui.dim('提示')} ${ui.dim('按')} ${ui.bold('Ctrl-C')} ${ui.dim('退出')}`,
49
+ '',
50
+ ]
51
+ }
52
+
53
+ export function observeServer(server, ui, output = console) {
54
+ const onRebuildStart = (event) => {
55
+ const count = event.changedPaths?.length || 0
56
+ const detail = count > 0 ? `检测到 ${count} 个文件变更,正在重建…` : '正在重建…'
57
+ output.log(` ${ui.warn('↻')} ${ui.dim(detail)}`)
58
+ }
59
+ const onRebuilt = (event) => {
60
+ output.log(
61
+ ` ${ui.ok('✓')} ${ui.bold('热重建')} ${ui.dim('·')} ${ui.accent(`${event.modules} 模块`)} ${ui.dim('·')} ${ui.accent(humanDuration(event.durationMs))}`,
62
+ )
63
+ }
64
+ const onDiagnostic = (diagnostic) => {
65
+ const code = diagnostic.code ? `[${diagnostic.code}] ` : ''
66
+ output.error(` ${ui.error('✗')} ${ui.bold('构建失败')} ${code}${diagnostic.message}`)
67
+ }
68
+
69
+ server.on('rebuildStart', onRebuildStart)
70
+ server.on('rebuilt', onRebuilt)
71
+ server.on('diagnostic', onDiagnostic)
72
+ return () => {
73
+ server.off('rebuildStart', onRebuildStart)
74
+ server.off('rebuilt', onRebuilt)
75
+ server.off('diagnostic', onDiagnostic)
76
+ }
77
+ }
package/bin/wake.mjs CHANGED
@@ -9,6 +9,13 @@ import {
9
9
  version,
10
10
  } from '../index.mjs'
11
11
  import { parse, tokenize } from '../experimental.mjs'
12
+ import {
13
+ createUi,
14
+ formatBanner,
15
+ formatServerReady,
16
+ observeServer,
17
+ supportsColor,
18
+ } from './terminal.mjs'
12
19
 
13
20
  const HELP = `Wake ${version()}
14
21
 
@@ -20,6 +27,9 @@ Usage:
20
27
  wake parse <file>
21
28
  wake tokenize <file>
22
29
  wake --version
30
+
31
+ Options:
32
+ --no-color Disable terminal colors
23
33
  `
24
34
 
25
35
  function takeOption(args, name) {
@@ -52,10 +62,17 @@ function printResult(result) {
52
62
  if (result.outputDir) console.log(`wake: output ${result.outputDir}`)
53
63
  }
54
64
 
55
- async function runServer(factory, options) {
65
+ function printLines(lines) {
66
+ for (const line of lines) console.log(line)
67
+ }
68
+
69
+ async function runServer(factory, options, command, ui) {
56
70
  const controller = new AbortController()
71
+ printLines(formatBanner(ui, command, version()))
72
+ const startedAt = performance.now()
57
73
  const server = await factory({ ...options, signal: controller.signal })
58
- console.log(`wake: listening on ${server.url}`)
74
+ printLines(formatServerReady(ui, server.url, performance.now() - startedAt))
75
+ const stopObserving = observeServer(server, ui)
59
76
 
60
77
  let stopping = false
61
78
  const stop = async (signal) => {
@@ -68,13 +85,23 @@ async function runServer(factory, options) {
68
85
  process.exitCode = signal === 'SIGINT' ? 130 : 143
69
86
  }
70
87
  }
71
- process.once('SIGINT', () => void stop('SIGINT'))
72
- process.once('SIGTERM', () => void stop('SIGTERM'))
73
- await server.waitUntilClosed()
88
+ const onSigint = () => void stop('SIGINT')
89
+ const onSigterm = () => void stop('SIGTERM')
90
+ process.once('SIGINT', onSigint)
91
+ process.once('SIGTERM', onSigterm)
92
+ try {
93
+ await server.waitUntilClosed()
94
+ } finally {
95
+ stopObserving()
96
+ process.off('SIGINT', onSigint)
97
+ process.off('SIGTERM', onSigterm)
98
+ }
74
99
  }
75
100
 
76
101
  export async function runCli(argv = process.argv.slice(2)) {
77
102
  const args = [...argv]
103
+ const noColor = takeFlag(args, '--no-color')
104
+ const ui = createUi(!noColor && supportsColor())
78
105
  if (takeFlag(args, '--version') || takeFlag(args, '-V')) {
79
106
  console.log(version())
80
107
  return 0
@@ -105,7 +132,7 @@ export async function runCli(argv = process.argv.slice(2)) {
105
132
  options.open = takeFlag(args, '--open')
106
133
  if (args[0]) options.cwd = args.shift()
107
134
  if (args.length) throw new Error(`unknown dev arguments: ${args.join(' ')}`)
108
- await runServer(startDevServer, options)
135
+ await runServer(startDevServer, options, 'dev', ui)
109
136
  return process.exitCode || 0
110
137
  }
111
138
 
@@ -125,7 +152,7 @@ export async function runCli(argv = process.argv.slice(2)) {
125
152
  return 0
126
153
  }
127
154
  if (action === 'dev') {
128
- await runServer(startDocsDevServer, options)
155
+ await runServer(startDocsDevServer, options, 'docs dev', ui)
129
156
  return process.exitCode || 0
130
157
  }
131
158
  throw new Error('docs requires build or dev')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crab-dev/wake",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Wake native web build tools for Node.js",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "repository": {
@@ -45,11 +45,11 @@
45
45
  "node": ">=22.14 <27"
46
46
  },
47
47
  "optionalDependencies": {
48
- "@crab-dev/wake-win32-x64-msvc": "0.1.2",
49
- "@crab-dev/wake-linux-x64-gnu": "0.1.2",
50
- "@crab-dev/wake-linux-arm64-gnu": "0.1.2",
51
- "@crab-dev/wake-darwin-x64": "0.1.2",
52
- "@crab-dev/wake-darwin-arm64": "0.1.2"
48
+ "@crab-dev/wake-win32-x64-msvc": "0.1.3",
49
+ "@crab-dev/wake-linux-x64-gnu": "0.1.3",
50
+ "@crab-dev/wake-linux-arm64-gnu": "0.1.3",
51
+ "@crab-dev/wake-darwin-x64": "0.1.3",
52
+ "@crab-dev/wake-darwin-arm64": "0.1.3"
53
53
  },
54
54
  "publishConfig": {
55
55
  "access": "public",