1
1
import { existsSync , promises as fsp } from "node:fs" ;
2
2
import { resolve , relative } from "pathe" ;
3
+ import type { SubscribeCallback } from "@parcel/watcher" ;
3
4
import type { Config , ResolvedConfig } from "./config" ;
4
- import { TransformResult , transform } from "./transform" ;
5
+ import { type TransformResult , transform } from "./transform" ;
5
6
import { loadConfig } from "./config" ;
6
7
7
8
export interface AutomdResult extends TransformResult {
8
- _config : ResolvedConfig ;
9
9
input : string ;
10
10
output : string ;
11
11
}
12
12
13
- export async function automd ( _config : Config = { } ) : Promise < AutomdResult [ ] > {
13
+ export async function automd (
14
+ _config : Config = { } ,
15
+ ) : Promise < { results : AutomdResult [ ] ; _config : ResolvedConfig ; time : number } > {
14
16
const config = await loadConfig ( _config . dir , _config ) ;
15
17
16
18
let inputFiles = config . input ;
@@ -20,40 +22,97 @@ export async function automd(_config: Config = {}): Promise<AutomdResult[]> {
20
22
cwd : config . dir ,
21
23
absolute : false ,
22
24
onlyFiles : true ,
23
- ignore : [ "node_modules" , "dist" , ".*" , ... ( config . ignore || [ ] ) ] ,
25
+ ignore : config . ignore ,
24
26
} ) ;
25
27
} else {
26
28
inputFiles = inputFiles
27
29
. map ( ( i ) => resolve ( config . dir , i ) )
28
30
. filter ( ( i ) => existsSync ( i ) )
29
31
. map ( ( i ) => relative ( config . dir , i ) ) ;
30
32
}
33
+ const multiFiles = inputFiles . length > 1 ;
31
34
32
- return Promise . all (
33
- inputFiles . map ( ( i ) => _automd ( i , config , inputFiles . length > 1 ) ) ,
35
+ const cache : ResultCache = new Map ( ) ;
36
+
37
+ const start = performance . now ( ) ;
38
+ const results = await Promise . all (
39
+ inputFiles . map ( ( i ) => _automd ( i , config , multiFiles , cache ) ) ,
34
40
) ;
41
+ const time = Math . round ( ( performance . now ( ) - start ) * 1000 ) / 1000 ;
42
+
43
+ if ( config . watch ) {
44
+ await _watch ( inputFiles , config , multiFiles , cache ) ;
45
+ }
46
+
47
+ return {
48
+ _config : config ,
49
+ time,
50
+ results,
51
+ } ;
35
52
}
36
53
37
- export async function _automd (
54
+ // -- internal --
55
+
56
+ type ResultCache = Map < string , AutomdResult > ;
57
+
58
+ async function _automd (
38
59
relativeInput : string ,
39
60
config : ResolvedConfig ,
40
- multi : boolean ,
61
+ multiFiles : boolean ,
62
+ cache : ResultCache ,
41
63
) : Promise < AutomdResult > {
42
64
const input = resolve ( config . dir , relativeInput ) ;
43
65
const contents = await fsp . readFile ( input , "utf8" ) ;
44
66
45
- const result = await transform ( contents , config ) ;
67
+ const cachedResult = await cache . get ( input ) ;
68
+ if ( cachedResult ?. contents === contents ) {
69
+ return cachedResult ;
70
+ }
71
+
72
+ const transformResult = await transform ( contents , config ) ;
46
73
47
- const output = multi
74
+ const output = multiFiles
48
75
? resolve ( config . dir , config . output || "." , relativeInput )
49
76
: resolve ( config . dir , config . output || relativeInput ) ;
50
77
51
- await fsp . writeFile ( output , result . contents , "utf8" ) ;
78
+ await fsp . writeFile ( output , transformResult . contents , "utf8" ) ;
52
79
53
- return {
54
- _config : config ,
80
+ const result : AutomdResult = {
55
81
input,
56
82
output,
57
- ...result ,
83
+ ...transformResult ,
84
+ } ;
85
+ cache . set ( input , result ) ;
86
+ return result ;
87
+ }
88
+
89
+ async function _watch (
90
+ inputFiles : string [ ] ,
91
+ config : ResolvedConfig ,
92
+ multiFiles : boolean ,
93
+ cache : ResultCache ,
94
+ ) {
95
+ const watcher = await import ( "@parcel/watcher" ) ;
96
+
97
+ const watchCb : SubscribeCallback = async ( _err , events ) => {
98
+ const filesToUpdate = events
99
+ . map ( ( e ) => relative ( config . dir , e . path ) )
100
+ . filter ( ( p ) => inputFiles . includes ( p ) ) ;
101
+ const start = performance . now ( ) ;
102
+ const results = await Promise . all (
103
+ filesToUpdate . map ( ( f ) => _automd ( f , config , multiFiles , cache ) ) ,
104
+ ) ;
105
+ const time = performance . now ( ) - start ;
106
+ if ( config . onWatch ) {
107
+ config . onWatch ( { results, time } ) ;
108
+ }
58
109
} ;
110
+
111
+ const subscription = await watcher . subscribe ( config . dir , watchCb , {
112
+ ignore : config . ignore ,
113
+ } ) ;
114
+
115
+ process . on ( "SIGINT" , ( ) => {
116
+ subscription . unsubscribe ( ) ;
117
+ } ) ;
59
118
}
0 commit comments