11import '@/utils/helper' ;
22
33import ora from 'ora' ;
4- import { nanoid } from 'nanoid' ;
54import { FileInfo } from './File' ;
65import { GeneratorSource } from './Source' ;
7- import { useEnvVar } from './utils' ;
86import { Hook , HookHelper } from './Hook' ;
7+ import { DirInfo } from './Dir' ;
8+ import np from 'normalize-path' ;
99
1010import type { Ora } from 'ora' ;
1111import type { SourceInfo } from './Source' ;
1212import type { Hooks } from './Hook' ;
1313
14- const { __dir_cache_generator } = useEnvVar ( ) ;
15-
16- /**
17- * src write into dest
18- */
19- export const copyFile = async ( options : {
20- src : string ;
21- dest : string ;
22- hook : Hook ;
23- } ) => {
24- const { src, dest, hook } = options ;
25- if ( ! fs . existsSync ( dest ) ) {
26- fs . copyFileSync ( src , dest ) ;
27- return ;
28- }
29- const srcFile = FileInfo . build ( { pathname : src } ) ;
30- const destFile = FileInfo . build ( {
31- pathname : path . join ( dest , srcFile . filename ) ,
32- } ) ;
33- fs . writeFileSync (
34- destFile . pathname ,
35- hook . hasHook ( 'onMerging' )
36- ? await hook . callHook ( 'onMerging' , { src : srcFile , dest : destFile } )
37- : srcFile . getContent ( ) ,
38- ) ;
39- } ;
40-
41- export const copy = async ( options : {
42- src : string ;
43- dest : string ;
44- hook : Hook ;
45- } ) => {
46- const { src, dest, hook } = options ;
47- const filenameList = fs . readdirSync ( src ) ;
48- fs . ensureDirSync ( dest ) ;
49- for ( const filename of filenameList ) {
50- const srcPath = path . join ( src , filename ) ;
51- const destPath = path . join ( dest , filename ) ;
52- const state = fs . lstatSync ( srcPath ) ;
53- if ( state . isDirectory ( ) ) copy ( { src : srcPath , dest : destPath , hook } ) ;
54- // TODO: should i use less I/O and modify files at memory?
55- else await copyFile ( { src : srcPath , dest, hook } ) ;
56- }
57- } ;
58-
5914export class Generator < N extends string = string > {
60- private hash : string = nanoid ( ) ;
61-
62- private tempPathname : string = path . resolve (
63- __dir_cache_generator ,
64- this . hash ,
65- ) ;
66-
6715 private source : GeneratorSource < N > ;
6816 private target : SourceInfo ;
17+ private targetDirInfo : DirInfo ;
18+ private curInjectDirInfo : DirInfo ;
6919
7020 private baseHook : Hook ;
7121 private injectHookMap : Record < N , Hook > = { } as Record < N , Hook > ;
@@ -79,7 +29,9 @@ export class Generator<N extends string = string> {
7929 const { source, target } = options ;
8030 this . source = source ;
8131 this . target = target ;
82- fs . ensureDirSync ( this . tempPathname ) ;
32+ this . targetDirInfo = DirInfo . build ( {
33+ pathname : this . target . pathname ,
34+ } ) ;
8335 }
8436
8537 public static async build < N extends string = string > ( options : {
@@ -120,6 +72,66 @@ export class Generator<N extends string = string> {
12072 return generator ;
12173 }
12274
75+ /**
76+ * src write into dest
77+ */
78+ private async copyFile ( options : {
79+ src : FileInfo ;
80+ dest : FileInfo ;
81+ hook : Hook ;
82+ } ) {
83+ const { src, dest, hook } = options ;
84+
85+ await hook . callHook ( 'beforeMerge' , {
86+ srcDir : this . curInjectDirInfo ,
87+ destDir : this . targetDirInfo ,
88+ src,
89+ dest,
90+ } ) ;
91+
92+ if ( ! hook . hasHook ( 'onMerging' ) ) {
93+ dest . setContent ( src . getContent ( ) ) ;
94+ } else {
95+ dest . setContent (
96+ await hook . callHook ( 'onMerging' , {
97+ src,
98+ dest,
99+ } ) ,
100+ ) ;
101+ }
102+
103+ await hook . callHook ( 'afterMerge' , {
104+ srcDir : this . curInjectDirInfo ,
105+ destDir : this . targetDirInfo ,
106+ src,
107+ dest,
108+ } ) ;
109+ }
110+
111+ private async copy ( options : { src : DirInfo ; dest : DirInfo ; hook : Hook } ) {
112+ const { src, dest, hook } = options ;
113+ const map = src . getMap ( ) ;
114+ for ( const item of Object . values ( map ) ) {
115+ const destRelPath = np ( path . relative ( src . pathname , item . pathname ) ) ;
116+ if ( item . isDir )
117+ await this . copy ( {
118+ src : item ,
119+ dest : dest . ensure ( destRelPath , {
120+ type : 'dir' ,
121+ } ) ,
122+ hook,
123+ } ) ;
124+ else
125+ await this . copyFile ( {
126+ src : item as unknown as FileInfo ,
127+ dest : dest . ensure ( destRelPath , {
128+ type : 'file' ,
129+ } ) ,
130+ hook,
131+ } ) ;
132+ }
133+ }
134+
123135 private setBaseHook ( hook : Hook ) {
124136 this . baseHook = hook ;
125137 }
@@ -132,10 +144,12 @@ export class Generator<N extends string = string> {
132144 hookName : N ,
133145 ...args : Parameters < Hooks [ N ] >
134146 ) {
147+ this . spinner . stop ( ) ;
135148 await this . baseHook . callHook ( hookName , ...args ) ;
136149 for ( const hook of Object . values < Hook > ( this . injectHookMap ) ) {
137150 await hook . callHook ( hookName , ...args ) ;
138151 }
152+ $ . verbose = false ;
139153 }
140154
141155 private async generateBase ( ) {
@@ -144,11 +158,15 @@ export class Generator<N extends string = string> {
144158 `Generate base - ${ chalk . blueBright ( this . source . baseSource . name ) } ` ,
145159 ) ;
146160
147- copy ( {
148- src : this . source . getBaseFilesPathname ( ) ,
149- dest : this . tempPathname ,
161+ this . curInjectDirInfo = DirInfo . build ( {
162+ pathname : this . source . getBaseFilesPathname ( ) ,
163+ } ) ;
164+ await this . copy ( {
165+ src : this . curInjectDirInfo ,
166+ dest : this . targetDirInfo ,
150167 hook : this . baseHook ,
151168 } ) ;
169+ this . curInjectDirInfo = null ;
152170 }
153171
154172 private async generateInject ( ) {
@@ -157,11 +175,17 @@ export class Generator<N extends string = string> {
157175 `Generate inject - ${ chalk . cyanBright ( injectSourceInfo . name ) } ` ,
158176 ) ;
159177
160- copy ( {
161- src : this . source . getInjectFilesPathnameByName ( injectSourceInfo . name ) ,
162- dest : this . tempPathname ,
178+ this . curInjectDirInfo = DirInfo . build ( {
179+ pathname : this . source . getInjectFilesPathnameByName (
180+ injectSourceInfo . name ,
181+ ) ,
182+ } ) ;
183+ await this . copy ( {
184+ src : this . curInjectDirInfo ,
185+ dest : this . targetDirInfo ,
163186 hook : this . injectHookMap [ injectSourceInfo . name ] ,
164187 } ) ;
188+ this . curInjectDirInfo = null ;
165189 }
166190 }
167191
@@ -184,15 +208,11 @@ export class Generator<N extends string = string> {
184208
185209 public async generate ( ) {
186210 try {
187- await this . callHooks ( 'beforeMerge' ) ;
188211
189212 await this . generateBase ( ) ;
190213 await this . generateInject ( ) ;
191214 await this . output ( ) ;
192215
193- this . spinner . stop ( ) ;
194- await this . callHooks ( 'afterMerge' ) ;
195-
196216 await this . installDeps ( ) ;
197217
198218 this . spinner . succeed (
0 commit comments