1-
21import * as Chokidar from 'chokidar'
32import * as Process from 'node:process'
43import * as Crypto from 'node:crypto'
@@ -9,34 +8,104 @@ import { SafeInitCwd } from './utils/safe-init-cwd.js'
98import { Build } from './build-core.js'
109
1110let ProjectRoot = SafeInitCwd ( { Cwd : Process . cwd ( ) , InitCwd : Process . env . INIT_CWD } )
12- const WatchingGlob : string [ ] = [ ] ;
13- [ 'builder/' , 'userscript/' , '' ] . forEach ( Dir => {
11+ const WatchingGlob : string [ ] = [ ]
12+ for ( const Dir of [ 'builder/' , 'userscript/' , '' ] ) {
1413 WatchingGlob . push ( ...Fs . globSync ( `${ ProjectRoot } /${ Dir } source/**/*.ts` ) )
1514 WatchingGlob . push ( ...Fs . globSync ( `${ ProjectRoot } /${ Dir } source/**/*.json` ) )
1615 WatchingGlob . push ( ...Fs . globSync ( `${ ProjectRoot } /${ Dir } source/**/*.txt` ) )
17- } )
16+ }
1817const Watcher = Chokidar . watch ( [ ...WatchingGlob ] , {
1918 ignored : '**/node_modules/**' ,
19+ ignoreInitial : true ,
2020} )
2121
2222let BuildCooldownTimer : NodeJS . Timeout | null = null
23- let ShouldPreventHTTPResponse = false
23+ let ActiveBuildController : AbortController | null = null
24+ let BuildQueue : Promise < void > = Promise . resolve ( )
2425let Version : number = 0
2526let RandomPort = Crypto . randomInt ( 8000 , 8999 )
2627const CoreBuildInstance = new Build ( { Version : `0.0.${ Version } ` , Minify : false , BuildType : 'development' , SubscriptionUrl : `http://localhost:${ RandomPort } /tinyShield.dev.user.js` } )
27- await CoreBuildInstance . Init ( )
28- Watcher . on ( 'all' , async ( WatcherEvent , WatcherPath ) => {
28+
29+ type DebugBuildContext = {
30+ Reason : 'initial' | 'change'
31+ DebounceMs : number
32+ WatcherEvent ?: string
33+ WatcherPath ?: string
34+ }
35+
36+ function EnqueueDebugBuild ( BuildController : AbortController , Context : DebugBuildContext ) {
37+ BuildQueue = BuildQueue . then ( async ( ) => {
38+ try {
39+ await RunDebugBuild ( BuildController , Context )
40+ } catch ( BuildError ) {
41+ if ( BuildController . signal . aborted ) {
42+ return
43+ }
44+
45+ console . error ( 'Debug build failed:' , BuildError )
46+ if ( ActiveBuildController === BuildController ) {
47+ ActiveBuildController = null
48+ }
49+ }
50+ } )
51+ }
52+
53+ function ScheduleDebugBuild ( Context : DebugBuildContext ) {
2954 if ( BuildCooldownTimer ) {
3055 clearTimeout ( BuildCooldownTimer )
56+ BuildCooldownTimer = null
57+ }
58+
59+ ActiveBuildController ?. abort ( )
60+ const BuildController = new AbortController ( )
61+ ActiveBuildController = BuildController
62+
63+ if ( Context . DebounceMs <= 0 ) {
64+ EnqueueDebugBuild ( BuildController , Context )
65+ return
66+ }
67+
68+ BuildCooldownTimer = setTimeout ( ( ) => {
69+ BuildCooldownTimer = null
70+ EnqueueDebugBuild ( BuildController , Context )
71+ } , Context . DebounceMs )
72+ }
73+
74+ async function RunDebugBuild ( BuildController : AbortController , Context : DebugBuildContext ) {
75+ if ( BuildController . signal . aborted ) {
76+ return
3177 }
32- BuildCooldownTimer = setTimeout ( async ( ) => {
78+
79+ if ( Context . Reason === 'initial' ) {
80+ console . log ( 'Starting initial debug build.' )
81+ } else {
82+ const WatcherEvent = Context . WatcherEvent ?? 'unknown'
83+ const WatcherPath = Context . WatcherPath ?? 'unknown'
3384 console . log ( `Detected file change (${ WatcherEvent } ):` , WatcherPath )
34- ShouldPreventHTTPResponse = true
35- await new StandardBuild ( CoreBuildInstance , { Version : `0.0.${ Version } ` , Minify : false , BuildType : 'development' , SubscriptionUrl : `http://localhost:${ RandomPort } /tinyShield.dev.user.js` } ) . Build ( )
36- Version ++
37- ShouldPreventHTTPResponse = false
38- } , 1500 )
85+ }
86+
87+ await new StandardBuild ( CoreBuildInstance , { Version : `0.0.${ Version } ` , Minify : false , BuildType : 'development' , SubscriptionUrl : `http://localhost:${ RandomPort } /tinyShield.dev.user.js` } ) . Build ( )
88+
89+ if ( BuildController . signal . aborted ) {
90+ return
91+ }
92+
93+ Version ++
94+ if ( ActiveBuildController === BuildController ) {
95+ ActiveBuildController = null
96+ }
97+ }
98+
99+ await CoreBuildInstance . Init ( )
100+ Watcher . on ( 'all' , ( WatcherEvent , WatcherPath ) => {
101+ ScheduleDebugBuild ( {
102+ Reason : 'change' ,
103+ DebounceMs : 1500 ,
104+ WatcherEvent,
105+ WatcherPath
106+ } )
39107} )
40108
41- RunDebugServer ( RandomPort , [ 'tinyShield.dev.user.js' ] , ShouldPreventHTTPResponse )
42- console . log ( `Debug HTTP server running on http://localhost:${ RandomPort } /tinyShield.dev.user.js` )
109+ RunDebugServer ( RandomPort , [ 'tinyShield.dev.user.js' ] , ( ) => ActiveBuildController ?. signal ?? null )
110+ console . log ( `Debug HTTP server running on http://localhost:${ RandomPort } /tinyShield.dev.user.js` )
111+ ScheduleDebugBuild ( { Reason : 'initial' , DebounceMs : 0 } )
0 commit comments