Skip to content

Commit fce51ab

Browse files
committed
feat: watch mode
1 parent a70c208 commit fce51ab

File tree

7 files changed

+380
-4
lines changed

7 files changed

+380
-4
lines changed

build.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,13 @@ export default defineConfig({
77
input: ['./src/index.ts', './src/cli.ts', './src/config.ts'],
88
},
99
],
10+
// Example watch configuration
11+
watch: {
12+
enabled: false, // Set to true to enable watch mode by default
13+
include: ['src/**/*'],
14+
exclude: ['src/**/*.test.ts', 'src/**/*.spec.ts'],
15+
delay: 100,
16+
ignoreInitial: false,
17+
watchNewFiles: true,
18+
},
1019
})

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
},
3333
"dependencies": {
3434
"c12": "^3.0.4",
35+
"chokidar": "^4.0.3",
3536
"consola": "^3.4.2",
3637
"defu": "^6.1.4",
3738
"exsolve": "^1.0.5",

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/build.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,56 @@ import prettyBytes from 'pretty-bytes'
1414
import { rolldownBuild } from './builders/bundle'
1515
import { transformDir } from './builders/transform'
1616
import { analyzeDir, fmtPath } from './utils'
17+
import { startWatch } from './watch'
1718

1819
/**
1920
* Build dist/ from src/
2021
*/
2122
export async function build(config: BuildConfig): Promise<void> {
22-
const start = Date.now()
23+
// const start = Date.now()
2324

2425
const pkgDir = normalizePath(config.cwd)
2526
const pkg = await readJSON(join(pkgDir, 'package.json')).catch(() => ({}))
2627
const ctx: BuildContext = { pkg, pkgDir }
2728

29+
// Check if watch mode is enabled
30+
if (config.watch?.enabled) {
31+
consola.log(
32+
`👀 Starting watch mode for \`${ctx.pkg.name || '<no name>'}\` (\`${ctx.pkgDir}\`)`,
33+
)
34+
35+
// Perform initial build
36+
await performBuild(config, ctx)
37+
38+
// Start watching
39+
const stopWatch = await startWatch(config, ctx, build)
40+
41+
// Handle graceful shutdown
42+
const cleanup = () => {
43+
consola.info('🛑 Stopping watch mode...')
44+
stopWatch()
45+
process.exit(0)
46+
}
47+
48+
process.on('SIGINT', cleanup)
49+
process.on('SIGTERM', cleanup)
50+
51+
// Keep the process alive
52+
return new Promise(() => {}) // Never resolves, keeps watching
53+
}
54+
2855
consola.log(
2956
`📦 Building \`${ctx.pkg.name || '<no name>'}\` (\`${ctx.pkgDir}\`)`,
3057
)
3158

59+
await performBuild(config, ctx)
60+
}
61+
62+
/**
63+
* Perform the actual build process
64+
*/
65+
async function performBuild(config: BuildConfig, ctx: BuildContext): Promise<void> {
66+
const start = Date.now()
3267
const hooks = config.hooks || {}
3368

3469
await hooks.start?.(ctx)
@@ -55,10 +90,10 @@ export async function build(config: BuildConfig): Promise<void> {
5590
)
5691
}
5792
entry = { ...entry }
58-
entry.outDir = normalizePath(entry.outDir || 'dist', pkgDir)
93+
entry.outDir = normalizePath(entry.outDir || 'dist', ctx.pkgDir)
5994
entry.input = Array.isArray(entry.input)
60-
? entry.input.map(p => normalizePath(p, pkgDir))
61-
: normalizePath(entry.input, pkgDir)
95+
? entry.input.map(p => normalizePath(p, ctx.pkgDir))
96+
: normalizePath(entry.input, ctx.pkgDir)
6297
return entry
6398
})
6499

src/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ const args = parseArgs({
2020
type: 'boolean',
2121
default: false,
2222
},
23+
watch: {
24+
type: 'boolean',
25+
default: false,
26+
},
2327
},
2428
})
2529

@@ -59,4 +63,5 @@ await build({
5963
cwd: args.values.dir,
6064
...config,
6165
entries,
66+
watch: args.values.watch ? { enabled: true, ...config.watch } : config.watch,
6267
})

src/types.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,53 @@ export interface BuildHooks {
111111
) => void | Promise<void>
112112
}
113113

114+
export interface WatchOptions {
115+
/**
116+
* Enable watch mode.
117+
*
118+
* Defaults to `false` if not provided.
119+
*/
120+
enabled?: boolean
121+
122+
/**
123+
* Glob patterns for files to watch.
124+
*
125+
* Defaults to watching all source files if not provided.
126+
*/
127+
include?: string[]
128+
129+
/**
130+
* Glob patterns for files to ignore.
131+
*
132+
* Defaults to common ignore patterns if not provided.
133+
*/
134+
exclude?: string[]
135+
136+
/**
137+
* Delay in milliseconds before rebuilding after a file change.
138+
*
139+
* Defaults to `100` if not provided.
140+
*/
141+
delay?: number
142+
143+
/**
144+
* Whether to ignore the initial build when starting watch mode.
145+
*
146+
* Defaults to `false` if not provided.
147+
*/
148+
ignoreInitial?: boolean
149+
150+
/**
151+
* Whether to watch for new files being added.
152+
*
153+
* Defaults to `true` if not provided.
154+
*/
155+
watchNewFiles?: boolean
156+
}
157+
114158
export interface BuildConfig {
115159
cwd?: string | URL
116160
entries?: (BuildEntry | string)[]
117161
hooks?: BuildHooks
162+
watch?: WatchOptions
118163
}

0 commit comments

Comments
 (0)