/
assets-manager.ts
120 lines (105 loc) · 3.39 KB
/
assets-manager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import * as chokidar from 'chokidar';
import { dirname, join, sep } from 'path';
import * as shell from 'shelljs';
import {
ActionOnFile,
Asset,
AssetEntry,
Configuration,
} from '../configuration';
import { copyPathResolve } from './helpers/copy-path-resolve';
import { getValueOrDefault } from './helpers/get-value-or-default';
export class AssetsManager {
private watchAssetsKeyValue: { [key: string]: boolean } = {};
private watchers: chokidar.FSWatcher[] = [];
public closeWatchers() {
this.watchers.forEach((watcher) => watcher.close());
}
public copyAssets(
configuration: Required<Configuration>,
appName: string,
outDir: string,
watchAssetsMode: boolean,
) {
const assets =
getValueOrDefault<Asset[]>(
configuration,
'compilerOptions.assets',
appName,
) || [];
if (assets.length <= 0) {
return;
}
try {
let sourceRoot = getValueOrDefault(configuration, 'sourceRoot', appName);
sourceRoot = join(process.cwd(), sourceRoot);
const filesToCopy = assets.map<AssetEntry>((item) => {
if (typeof item === 'string') {
return {
glob: join(sourceRoot, item),
outDir,
};
}
return {
outDir: item.outDir || outDir,
glob: join(sourceRoot, item.include!),
exclude: item.exclude ? join(sourceRoot, item.exclude) : undefined,
flat: item.flat, // deprecated field
watchAssets: item.watchAssets,
};
});
const isWatchEnabled =
getValueOrDefault<boolean>(
configuration,
'compilerOptions.watchAssets',
appName,
) || watchAssetsMode;
for (const item of filesToCopy) {
const option: ActionOnFile = {
action: 'change',
item,
path: '',
sourceRoot,
watchAssetsMode: isWatchEnabled,
};
// prettier-ignore
const watcher = chokidar
.watch(item.glob, { ignored: item.exclude })
.on('add', (path: string) => this.actionOnFile({ ...option, path, action: 'change' }))
.on('change', (path: string) => this.actionOnFile({ ...option, path, action: 'change' }))
.on('unlink', (path: string) => this.actionOnFile({ ...option, path, action: 'unlink' }));
if (!isWatchEnabled) {
watcher.on('ready', () => watcher.close());
}
this.watchers.push(watcher);
}
} catch (err) {
throw new Error(
`An error occurred during the assets copying process. ${err.message}`,
);
}
}
private actionOnFile(option: ActionOnFile) {
const { action, item, path, sourceRoot, watchAssetsMode } = option;
const isWatchEnabled = watchAssetsMode || item.watchAssets;
// Allow to do action for the first time before check watchMode
if (!isWatchEnabled && this.watchAssetsKeyValue[path]) {
return;
}
// Set path value to true for watching the first time
this.watchAssetsKeyValue[path] = true;
const dest = copyPathResolve(
path,
item.outDir!,
sourceRoot.split(sep).length,
);
// Copy to output dir if file is changed or added
if (action === 'change') {
shell.mkdir('-p', dirname(dest));
shell.cp(path, dest);
} else if (action === 'unlink') {
// Remove from output dir if file is deleted
shell.rm(dest);
}
}
}