forked from angular/angular-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathglob-copy-webpack-plugin.ts
More file actions
105 lines (91 loc) · 3.25 KB
/
Copy pathglob-copy-webpack-plugin.ts
File metadata and controls
105 lines (91 loc) · 3.25 KB
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
import * as fs from 'fs';
import * as path from 'path';
import * as glob from 'glob';
import * as denodeify from 'denodeify';
const flattenDeep = require('lodash/flattenDeep');
const globPromise = <any>denodeify(glob);
const statPromise = <any>denodeify(fs.stat);
function isDirectory(path: string) {
try {
return fs.statSync(path).isDirectory();
} catch (_) {
return false;
}
}
interface Asset {
originPath: string;
destinationPath: string;
relativePath: string;
}
export interface Pattern {
glob: string;
input?: string;
output?: string;
}
export interface GlobCopyWebpackPluginOptions {
patterns: (string | Pattern)[];
globOptions: any;
}
// Adds an asset to the compilation assets;
function addAsset(compilation: any, asset: Asset) {
const realPath = path.resolve(asset.originPath, asset.relativePath);
// Make sure that asset keys use forward slashes, otherwise webpack dev server
const servedPath = path.join(asset.destinationPath, asset.relativePath).replace(/\\/g, '/');
// Don't re-add existing assets.
if (compilation.assets[servedPath]) {
return Promise.resolve();
}
// Read file and add it to assets;
return statPromise(realPath)
.then((stat: any) => compilation.assets[servedPath] = {
size: () => stat.size,
source: () => fs.readFileSync(realPath)
});
}
export class GlobCopyWebpackPlugin {
constructor(private options: GlobCopyWebpackPluginOptions) { }
apply(compiler: any): void {
let { patterns, globOptions } = this.options;
const defaultCwd = globOptions.cwd || compiler.options.context;
// Force nodir option, since we can't add dirs to assets.
globOptions.nodir = true;
// Process patterns.
patterns = patterns.map(pattern => {
// Convert all string patterns to Pattern type.
pattern = typeof pattern === 'string' ? { glob: pattern } : pattern;
// Add defaults
// Input is always resolved relative to the defaultCwd (appRoot)
pattern.input = path.resolve(defaultCwd, pattern.input || '');
pattern.output = pattern.output || '';
pattern.glob = pattern.glob || '';
// Convert dir patterns to globs.
if (isDirectory(path.resolve(pattern.input, pattern.glob))) {
pattern.glob = pattern.glob + '/**/*';
}
return pattern;
});
compiler.plugin('emit', (compilation: any, cb: any) => {
// Create an array of promises for each pattern glob
const globs = patterns.map((pattern: Pattern) => new Promise((resolve, reject) =>
// Individual patterns can override cwd
globPromise(pattern.glob, Object.assign({}, globOptions, { cwd: pattern.input }))
// Map the results onto an Asset
.then((globResults: string[]) => globResults.map(res => ({
originPath: pattern.input,
destinationPath: pattern.output,
relativePath: res
})))
.then((asset: Asset) => resolve(asset))
.catch(reject)
));
// Wait for all globs.
Promise.all(globs)
// Flatten results.
.then(assets => flattenDeep(assets))
// Add each asset to the compilation.
.then(assets =>
Promise.all(assets.map((asset: Asset) => addAsset(compilation, asset))))
.then(() => cb());
});
}
}