@roots/bud-compiler 6.13.1 → 6.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +8 -6
- package/lib/index.js +3 -6
- package/lib/service.d.ts +49 -0
- package/lib/{compiler.service.js → service.js} +109 -81
- package/package.json +12 -23
- package/src/index.ts +9 -6
- package/src/service.tsx +269 -0
- package/lib/compiler.service.d.ts +0 -42
- package/lib/types.d.ts +0 -4
- package/lib/types.js +0 -4
- package/src/compiler.service.tsx +0 -252
- package/src/compiler.test.ts +0 -67
- package/src/types.ts +0 -3
package/lib/index.d.ts
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
/**
|
2
|
-
*
|
2
|
+
* @roots/bud-compiler
|
3
3
|
*
|
4
4
|
* @see https://bud.js.org
|
5
5
|
* @see https://github.com/roots/bud
|
6
|
-
*
|
7
|
-
* @packageDocumentation
|
8
6
|
*/
|
9
|
-
import { Compiler } from './
|
10
|
-
|
11
|
-
|
7
|
+
import { Compiler } from './service.js';
|
8
|
+
declare module '@roots/bud-framework' {
|
9
|
+
interface Services {
|
10
|
+
compiler: Compiler;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
export { Compiler as default };
|
package/lib/index.js
CHANGED
@@ -1,13 +1,10 @@
|
|
1
1
|
// Copyright © Roots Software Foundation LLC
|
2
2
|
// Licensed under the MIT license.
|
3
3
|
/**
|
4
|
-
*
|
4
|
+
* @roots/bud-compiler
|
5
5
|
*
|
6
6
|
* @see https://bud.js.org
|
7
7
|
* @see https://github.com/roots/bud
|
8
|
-
*
|
9
|
-
* @packageDocumentation
|
10
8
|
*/
|
11
|
-
import { Compiler } from './
|
12
|
-
|
13
|
-
export default Compiler;
|
9
|
+
import { Compiler } from './service.js';
|
10
|
+
export { Compiler as default };
|
package/lib/service.d.ts
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
import type { Compiler as BudCompiler } from '@roots/bud-framework';
|
2
|
+
import type { Bud } from '@roots/bud-framework';
|
3
|
+
import type { MultiCompiler, MultiStats, Stats, StatsError, Webpack } from '@roots/bud-framework/config';
|
4
|
+
import type { ErrorWithSourceFile } from '@roots/bud-support/open';
|
5
|
+
import { Service } from '@roots/bud-framework/service';
|
6
|
+
import { type BudHandler } from '@roots/bud-support/errors';
|
7
|
+
import webpack from '@roots/bud-support/webpack';
|
8
|
+
/**
|
9
|
+
* {@link BudCompiler} implementation
|
10
|
+
*/
|
11
|
+
export declare class Compiler extends Service implements BudCompiler {
|
12
|
+
/**
|
13
|
+
* {@link BudCompiler.compilationStats}
|
14
|
+
*/
|
15
|
+
compilationStats: BudCompiler[`compilationStats`];
|
16
|
+
/**
|
17
|
+
* {@link BudCompiler.config}
|
18
|
+
*/
|
19
|
+
config: BudCompiler[`config`];
|
20
|
+
/**
|
21
|
+
* {@link BudCompiler.implementation}
|
22
|
+
*/
|
23
|
+
implementation: BudCompiler[`implementation`] & typeof Webpack;
|
24
|
+
/**
|
25
|
+
* {@link BudCompiler.instance}
|
26
|
+
*/
|
27
|
+
instance: BudCompiler[`instance`];
|
28
|
+
/**
|
29
|
+
* {@link BudCompiler.stats}
|
30
|
+
*/
|
31
|
+
stats: BudCompiler[`stats`];
|
32
|
+
/**
|
33
|
+
* {@link BudCompiler.compile}
|
34
|
+
*/
|
35
|
+
compile(bud: Bud): Promise<MultiCompiler>;
|
36
|
+
/**
|
37
|
+
* {@link BudCompiler.onError}
|
38
|
+
*/
|
39
|
+
onError(error: BudHandler | webpack.WebpackError): void;
|
40
|
+
/**
|
41
|
+
* {@link BudCompiler.onStats}
|
42
|
+
*/
|
43
|
+
onStats(stats: Stats & MultiStats): void;
|
44
|
+
/**
|
45
|
+
* {@link Service.register}
|
46
|
+
*/
|
47
|
+
register?(bud: Bud): Promise<any>;
|
48
|
+
sourceErrors?(errors: Array<StatsError>): Array<ErrorWithSourceFile | StatsError>;
|
49
|
+
}
|
@@ -1,112 +1,104 @@
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
3
|
-
import
|
3
|
+
import { cpus } from 'node:os';
|
4
|
+
import process from 'node:process';
|
5
|
+
import { pathToFileURL } from 'node:url';
|
6
|
+
import { Error } from '@roots/bud-dashboard/components/error';
|
4
7
|
import { Service } from '@roots/bud-framework/service';
|
5
8
|
import { bind } from '@roots/bud-support/decorators/bind';
|
6
|
-
import { BudError
|
9
|
+
import { BudError } from '@roots/bud-support/errors';
|
7
10
|
import { duration } from '@roots/bud-support/human-readable';
|
8
|
-
import
|
11
|
+
import { render } from '@roots/bud-support/ink';
|
9
12
|
import stripAnsi from '@roots/bud-support/strip-ansi';
|
10
|
-
import
|
11
|
-
import webpack from 'webpack';
|
13
|
+
import webpack from '@roots/bud-support/webpack';
|
12
14
|
/**
|
13
|
-
*
|
15
|
+
* {@link BudCompiler} implementation
|
14
16
|
*/
|
15
17
|
export class Compiler extends Service {
|
16
18
|
/**
|
17
|
-
*
|
19
|
+
* {@link BudCompiler.compilationStats}
|
20
|
+
*/
|
21
|
+
compilationStats;
|
22
|
+
/**
|
23
|
+
* {@link BudCompiler.config}
|
18
24
|
*/
|
19
25
|
config = [];
|
20
26
|
/**
|
21
|
-
*
|
27
|
+
* {@link BudCompiler.implementation}
|
22
28
|
*/
|
23
29
|
implementation;
|
24
30
|
/**
|
25
|
-
*
|
31
|
+
* {@link BudCompiler.instance}
|
26
32
|
*/
|
27
33
|
instance;
|
28
34
|
/**
|
29
|
-
*
|
35
|
+
* {@link BudCompiler.stats}
|
30
36
|
*/
|
31
37
|
stats;
|
32
38
|
/**
|
33
|
-
*
|
39
|
+
* {@link BudCompiler.compile}
|
34
40
|
*/
|
35
|
-
async compile() {
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
catch (error) {
|
46
|
-
throw error;
|
47
|
-
}
|
48
|
-
}));
|
49
|
-
await this.app.hooks.fire(`compiler.before`, this.app);
|
41
|
+
async compile(bud) {
|
42
|
+
this.config = !bud.hasChildren
|
43
|
+
? [await bud.build.make()]
|
44
|
+
: await Promise.all(Object.values(bud.children).map(async (child) => await child.build.make().catch(error => {
|
45
|
+
throw error;
|
46
|
+
})));
|
47
|
+
this.config.parallelism = Math.min(cpus().length - 1, 1);
|
48
|
+
await bud.hooks.fire(`compiler.before`, bud).catch(error => {
|
49
|
+
throw error;
|
50
|
+
});
|
50
51
|
this.logger.timeEnd(`initialize`);
|
51
|
-
this.
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
this.app.dashboard.updateStatus(`compiling`);
|
53
|
+
try {
|
54
|
+
this.instance = this.implementation(this.config);
|
55
|
+
}
|
56
|
+
catch (error) {
|
57
|
+
throw BudError.normalize(error);
|
58
|
+
}
|
59
|
+
this.instance.hooks.done.tap(bud.label, (stats) => {
|
60
|
+
this.onStats(stats);
|
61
|
+
bud.hooks.fire(`compiler.done`, bud, this.stats).catch(error => {
|
62
|
+
throw error;
|
63
|
+
});
|
56
64
|
});
|
57
|
-
await this.app.hooks.fire(`compiler.after`, this.app);
|
58
65
|
return this.instance;
|
59
66
|
}
|
60
67
|
/**
|
61
|
-
*
|
68
|
+
* {@link BudCompiler.onError}
|
62
69
|
*/
|
63
|
-
|
70
|
+
onError(error) {
|
64
71
|
process.exitCode = 1;
|
65
|
-
|
66
|
-
this.app.
|
67
|
-
this.app.
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
});
|
74
|
-
}
|
75
|
-
catch (error) {
|
76
|
-
this.logger.error(error);
|
77
|
-
}
|
78
|
-
try {
|
79
|
-
Ink.render(_jsx(App.Error, { error: new CompilerError(error.message, {
|
80
|
-
props: {
|
81
|
-
details: `This error was thrown by the webpack compiler itself. It is not the same as a syntax error. It is likely a missing or unresolvable build dependency.`,
|
82
|
-
docs: new URL(`https://bud.js.org/`),
|
83
|
-
issues: new URL(`https://github.com/roots/bud/search?q=is:issue+"compiler" in:title`),
|
84
|
-
stack: error.stack,
|
85
|
-
thrownBy: `webpack`,
|
86
|
-
},
|
87
|
-
}) }));
|
72
|
+
this.app.server?.appliedMiddleware?.hot?.publish({ error });
|
73
|
+
this.app.notifier?.notify({
|
74
|
+
group: this.app.label,
|
75
|
+
message: error.message,
|
76
|
+
subtitle: error.name,
|
77
|
+
});
|
78
|
+
if (`isBudError` in error) {
|
79
|
+
render(_jsx(Error, { error: error }));
|
88
80
|
}
|
89
|
-
|
90
|
-
|
81
|
+
else {
|
82
|
+
render(_jsx(Error, { error: BudError.normalize(error) }));
|
91
83
|
}
|
92
84
|
}
|
93
85
|
/**
|
94
|
-
*
|
86
|
+
* {@link BudCompiler.onStats}
|
95
87
|
*/
|
96
|
-
|
88
|
+
onStats(stats) {
|
97
89
|
const makeNoticeTitle = (child) => this.app.label !== child.name
|
98
90
|
? `${this.app.label} (${child.name})`
|
99
91
|
: child.name;
|
100
|
-
this.stats = stats
|
101
|
-
|
102
|
-
|
92
|
+
this.stats = stats;
|
93
|
+
this.compilationStats = stats.toJson(statsOptions);
|
94
|
+
this.app.dashboard.updateStats(this.compilationStats);
|
103
95
|
if (stats.hasErrors()) {
|
104
96
|
process.exitCode = 1;
|
105
|
-
this.
|
97
|
+
this.compilationStats.children = this.compilationStats.children?.map(child => ({
|
106
98
|
...child,
|
107
99
|
errors: this.sourceErrors(child.errors),
|
108
100
|
}));
|
109
|
-
this.
|
101
|
+
this.compilationStats.children
|
110
102
|
?.filter(child => child.errorsCount > 0)
|
111
103
|
.forEach(child => {
|
112
104
|
try {
|
@@ -127,7 +119,7 @@ export class Compiler extends Service {
|
|
127
119
|
}
|
128
120
|
});
|
129
121
|
}
|
130
|
-
this.
|
122
|
+
this.compilationStats.children
|
131
123
|
?.filter(child => child.errorsCount === 0)
|
132
124
|
.forEach(child => {
|
133
125
|
try {
|
@@ -146,33 +138,38 @@ export class Compiler extends Service {
|
|
146
138
|
this.logger.error(error);
|
147
139
|
}
|
148
140
|
});
|
149
|
-
await statsUpdate;
|
150
141
|
}
|
151
142
|
/**
|
152
|
-
*
|
143
|
+
* {@link Service.register}
|
153
144
|
*/
|
145
|
+
async register(bud) {
|
146
|
+
this.implementation = await bud.module
|
147
|
+
.import(`@roots/bud-support/webpack`, import.meta.url)
|
148
|
+
.catch(error => {
|
149
|
+
throw BudError.normalize(error);
|
150
|
+
});
|
151
|
+
}
|
154
152
|
sourceErrors(errors) {
|
155
153
|
if (!errors || !errors.length)
|
156
154
|
return [];
|
157
155
|
try {
|
158
156
|
const parseError = (error) => {
|
159
157
|
let file;
|
160
|
-
const modules = this.stats.children.flatMap(child => child.modules);
|
161
158
|
const moduleIdent = error.moduleId ?? error.moduleName;
|
162
|
-
const module =
|
163
|
-
|
159
|
+
const module = this.compilationStats.children
|
160
|
+
.flatMap(child => child?.modules)
|
161
|
+
.find(module => module?.id === moduleIdent || module?.name === moduleIdent);
|
162
|
+
if (!module)
|
164
163
|
return error;
|
165
|
-
}
|
166
164
|
if (module.nameForCondition) {
|
167
165
|
file = module.nameForCondition;
|
168
166
|
}
|
169
167
|
else if (module.name) {
|
170
168
|
file = this.app.path(`@src`, module.name);
|
171
169
|
}
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
return { ...error, file, name: module.name ?? error.name };
|
170
|
+
return !file
|
171
|
+
? { ...error, name: module.name ?? error.name }
|
172
|
+
: { ...error, file, name: module.name ?? error.name };
|
176
173
|
};
|
177
174
|
return errors?.map(parseError).filter(Boolean);
|
178
175
|
}
|
@@ -185,24 +182,55 @@ export class Compiler extends Service {
|
|
185
182
|
__decorate([
|
186
183
|
bind,
|
187
184
|
__metadata("design:type", Function),
|
188
|
-
__metadata("design:paramtypes", []),
|
185
|
+
__metadata("design:paramtypes", [Function]),
|
189
186
|
__metadata("design:returntype", Promise)
|
190
187
|
], Compiler.prototype, "compile", null);
|
191
188
|
__decorate([
|
192
189
|
bind,
|
193
190
|
__metadata("design:type", Function),
|
194
|
-
__metadata("design:paramtypes", [
|
195
|
-
__metadata("design:returntype",
|
191
|
+
__metadata("design:paramtypes", [Object]),
|
192
|
+
__metadata("design:returntype", void 0)
|
196
193
|
], Compiler.prototype, "onError", null);
|
197
194
|
__decorate([
|
198
195
|
bind,
|
199
196
|
__metadata("design:type", Function),
|
200
197
|
__metadata("design:paramtypes", [Function]),
|
201
|
-
__metadata("design:returntype",
|
198
|
+
__metadata("design:returntype", void 0)
|
202
199
|
], Compiler.prototype, "onStats", null);
|
200
|
+
__decorate([
|
201
|
+
bind,
|
202
|
+
__metadata("design:type", Function),
|
203
|
+
__metadata("design:paramtypes", [Function]),
|
204
|
+
__metadata("design:returntype", Promise)
|
205
|
+
], Compiler.prototype, "register", null);
|
203
206
|
__decorate([
|
204
207
|
bind,
|
205
208
|
__metadata("design:type", Function),
|
206
209
|
__metadata("design:paramtypes", [Array]),
|
207
210
|
__metadata("design:returntype", Array)
|
208
211
|
], Compiler.prototype, "sourceErrors", null);
|
212
|
+
const statsOptions = {
|
213
|
+
all: false,
|
214
|
+
children: {
|
215
|
+
all: false,
|
216
|
+
assets: true,
|
217
|
+
cached: true,
|
218
|
+
cachedAssets: true,
|
219
|
+
cachedModules: true,
|
220
|
+
entrypoints: true,
|
221
|
+
errorDetails: false,
|
222
|
+
errors: true,
|
223
|
+
errorsCount: true,
|
224
|
+
errorStack: false,
|
225
|
+
hash: true,
|
226
|
+
modules: true,
|
227
|
+
name: true,
|
228
|
+
outputPath: true,
|
229
|
+
reasons: false,
|
230
|
+
runtime: true,
|
231
|
+
timings: true,
|
232
|
+
warnings: true,
|
233
|
+
warningsCount: true,
|
234
|
+
},
|
235
|
+
name: true,
|
236
|
+
};
|
package/package.json
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
{
|
2
2
|
"name": "@roots/bud-compiler",
|
3
|
-
"version": "6.
|
3
|
+
"version": "6.14.0",
|
4
4
|
"description": "Compilation handler",
|
5
5
|
"engines": {
|
6
6
|
"node": ">=16"
|
7
7
|
},
|
8
8
|
"contributors": [
|
9
9
|
{
|
10
|
-
"name": "Kelly Mears",
|
11
10
|
"email": "developers@tinypixel.dev",
|
11
|
+
"name": "Kelly Mears",
|
12
12
|
"url": "https://github.com/kellymears"
|
13
13
|
},
|
14
14
|
{
|
15
|
-
"name": "Ben Word",
|
16
15
|
"email": "ben@benword.com",
|
16
|
+
"name": "Ben Word",
|
17
17
|
"url": "https://github.com/retlehs"
|
18
18
|
},
|
19
19
|
{
|
@@ -21,8 +21,8 @@
|
|
21
21
|
"url": "https://github.com/QWp6t"
|
22
22
|
},
|
23
23
|
{
|
24
|
-
"name": "Brandon",
|
25
24
|
"email": "brandon@tendency.me",
|
25
|
+
"name": "Brandon",
|
26
26
|
"url": "https://github.com/Log1x"
|
27
27
|
}
|
28
28
|
],
|
@@ -49,40 +49,29 @@
|
|
49
49
|
],
|
50
50
|
"type": "module",
|
51
51
|
"exports": {
|
52
|
-
".":
|
53
|
-
"import": "./lib/index.js",
|
54
|
-
"default": "./lib/index.js"
|
55
|
-
},
|
56
|
-
"./types": {
|
57
|
-
"import": "./lib/types.js",
|
58
|
-
"default": "./lib/types.js"
|
59
|
-
}
|
52
|
+
".": "./lib/index.js"
|
60
53
|
},
|
61
54
|
"typesVersions": {
|
62
55
|
"*": {
|
63
56
|
".": [
|
64
57
|
"./lib/index.d.ts"
|
65
|
-
],
|
66
|
-
"types": [
|
67
|
-
"./lib/types.d.ts"
|
68
58
|
]
|
69
59
|
}
|
70
60
|
},
|
71
61
|
"types": "./lib/index.d.ts",
|
72
62
|
"module": "./lib/index.js",
|
73
63
|
"devDependencies": {
|
74
|
-
"@roots/bud-api": "6.
|
64
|
+
"@roots/bud-api": "6.14.0",
|
75
65
|
"@skypack/package-check": "0.2.2",
|
76
|
-
"@types/node": "18.16.
|
77
|
-
"@types/react": "18.2.
|
66
|
+
"@types/node": "18.16.18",
|
67
|
+
"@types/react": "18.2.14"
|
78
68
|
},
|
79
69
|
"dependencies": {
|
80
|
-
"@roots/bud-dashboard": "6.
|
81
|
-
"@roots/bud-framework": "6.
|
82
|
-
"@roots/bud-support": "6.
|
70
|
+
"@roots/bud-dashboard": "6.14.0",
|
71
|
+
"@roots/bud-framework": "6.14.0",
|
72
|
+
"@roots/bud-support": "6.14.0",
|
83
73
|
"react": "18.2.0",
|
84
|
-
"tslib": "2.
|
85
|
-
"webpack": "5.86.0"
|
74
|
+
"tslib": "2.6.0"
|
86
75
|
},
|
87
76
|
"volta": {
|
88
77
|
"extends": "../../../package.json"
|
package/src/index.ts
CHANGED
@@ -2,15 +2,18 @@
|
|
2
2
|
// Licensed under the MIT license.
|
3
3
|
|
4
4
|
/**
|
5
|
-
*
|
5
|
+
* @roots/bud-compiler
|
6
6
|
*
|
7
7
|
* @see https://bud.js.org
|
8
8
|
* @see https://github.com/roots/bud
|
9
|
-
*
|
10
|
-
* @packageDocumentation
|
11
9
|
*/
|
12
10
|
|
13
|
-
import {Compiler} from './
|
14
|
-
|
11
|
+
import {Compiler} from './service.js'
|
12
|
+
|
13
|
+
declare module '@roots/bud-framework' {
|
14
|
+
interface Services {
|
15
|
+
compiler: Compiler
|
16
|
+
}
|
17
|
+
}
|
15
18
|
|
16
|
-
export default
|
19
|
+
export {Compiler as default}
|
package/src/service.tsx
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
import type {Compiler as BudCompiler} from '@roots/bud-framework'
|
2
|
+
import type {Bud} from '@roots/bud-framework'
|
3
|
+
import type {
|
4
|
+
MultiCompiler,
|
5
|
+
MultiStats,
|
6
|
+
Stats,
|
7
|
+
StatsCompilation,
|
8
|
+
StatsError,
|
9
|
+
Webpack,
|
10
|
+
} from '@roots/bud-framework/config'
|
11
|
+
import type {
|
12
|
+
ErrorWithSourceFile,
|
13
|
+
SourceFile,
|
14
|
+
} from '@roots/bud-support/open'
|
15
|
+
|
16
|
+
import {cpus} from 'node:os'
|
17
|
+
import process from 'node:process'
|
18
|
+
import {pathToFileURL} from 'node:url'
|
19
|
+
|
20
|
+
import {Error} from '@roots/bud-dashboard/components/error'
|
21
|
+
import {Service} from '@roots/bud-framework/service'
|
22
|
+
import {bind} from '@roots/bud-support/decorators/bind'
|
23
|
+
import {BudError, type BudHandler} from '@roots/bud-support/errors'
|
24
|
+
import {duration} from '@roots/bud-support/human-readable'
|
25
|
+
import {render} from '@roots/bud-support/ink'
|
26
|
+
import stripAnsi from '@roots/bud-support/strip-ansi'
|
27
|
+
import webpack from '@roots/bud-support/webpack'
|
28
|
+
|
29
|
+
/**
|
30
|
+
* {@link BudCompiler} implementation
|
31
|
+
*/
|
32
|
+
export class Compiler extends Service implements BudCompiler {
|
33
|
+
/**
|
34
|
+
* {@link BudCompiler.compilationStats}
|
35
|
+
*/
|
36
|
+
public compilationStats: BudCompiler[`compilationStats`]
|
37
|
+
|
38
|
+
/**
|
39
|
+
* {@link BudCompiler.config}
|
40
|
+
*/
|
41
|
+
public config: BudCompiler[`config`] = []
|
42
|
+
|
43
|
+
/**
|
44
|
+
* {@link BudCompiler.implementation}
|
45
|
+
*/
|
46
|
+
public implementation: BudCompiler[`implementation`] & typeof Webpack
|
47
|
+
|
48
|
+
/**
|
49
|
+
* {@link BudCompiler.instance}
|
50
|
+
*/
|
51
|
+
public instance: BudCompiler[`instance`]
|
52
|
+
|
53
|
+
/**
|
54
|
+
* {@link BudCompiler.stats}
|
55
|
+
*/
|
56
|
+
public stats: BudCompiler[`stats`]
|
57
|
+
|
58
|
+
/**
|
59
|
+
* {@link BudCompiler.compile}
|
60
|
+
*/
|
61
|
+
@bind
|
62
|
+
public async compile(bud: Bud): Promise<MultiCompiler> {
|
63
|
+
this.config = !bud.hasChildren
|
64
|
+
? [await bud.build.make()]
|
65
|
+
: await Promise.all(
|
66
|
+
Object.values(bud.children).map(
|
67
|
+
async (child: Bud) =>
|
68
|
+
await child.build.make().catch(error => {
|
69
|
+
throw error
|
70
|
+
}),
|
71
|
+
),
|
72
|
+
)
|
73
|
+
this.config.parallelism = Math.min(cpus().length - 1, 1)
|
74
|
+
|
75
|
+
await bud.hooks.fire(`compiler.before`, bud).catch(error => {
|
76
|
+
throw error
|
77
|
+
})
|
78
|
+
|
79
|
+
this.logger.timeEnd(`initialize`)
|
80
|
+
this.app.dashboard.updateStatus(`compiling`)
|
81
|
+
|
82
|
+
try {
|
83
|
+
this.instance = this.implementation(this.config)
|
84
|
+
} catch (error) {
|
85
|
+
throw BudError.normalize(error)
|
86
|
+
}
|
87
|
+
|
88
|
+
this.instance.hooks.done.tap(bud.label, (stats: any) => {
|
89
|
+
this.onStats(stats)
|
90
|
+
|
91
|
+
bud.hooks.fire(`compiler.done`, bud, this.stats).catch(error => {
|
92
|
+
throw error
|
93
|
+
})
|
94
|
+
})
|
95
|
+
|
96
|
+
return this.instance
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* {@link BudCompiler.onError}
|
101
|
+
*/
|
102
|
+
@bind
|
103
|
+
public onError(error: BudHandler | webpack.WebpackError) {
|
104
|
+
process.exitCode = 1
|
105
|
+
|
106
|
+
this.app.server?.appliedMiddleware?.hot?.publish({error})
|
107
|
+
|
108
|
+
this.app.notifier?.notify({
|
109
|
+
group: this.app.label,
|
110
|
+
message: error.message,
|
111
|
+
subtitle: error.name,
|
112
|
+
})
|
113
|
+
|
114
|
+
if (`isBudError` in error) {
|
115
|
+
render(<Error error={error} />)
|
116
|
+
} else {
|
117
|
+
render(<Error error={BudError.normalize(error)} />)
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
/**
|
122
|
+
* {@link BudCompiler.onStats}
|
123
|
+
*/
|
124
|
+
@bind
|
125
|
+
public onStats(stats: Stats & MultiStats) {
|
126
|
+
const makeNoticeTitle = (child: StatsCompilation) =>
|
127
|
+
this.app.label !== child.name
|
128
|
+
? `${this.app.label} (${child.name})`
|
129
|
+
: child.name
|
130
|
+
|
131
|
+
this.stats = stats
|
132
|
+
|
133
|
+
this.compilationStats = stats.toJson(statsOptions)
|
134
|
+
|
135
|
+
this.app.dashboard.updateStats(this.compilationStats)
|
136
|
+
|
137
|
+
if (stats.hasErrors()) {
|
138
|
+
process.exitCode = 1
|
139
|
+
|
140
|
+
this.compilationStats.children = this.compilationStats.children?.map(
|
141
|
+
child => ({
|
142
|
+
...child,
|
143
|
+
errors: this.sourceErrors(child.errors),
|
144
|
+
}),
|
145
|
+
)
|
146
|
+
|
147
|
+
this.compilationStats.children
|
148
|
+
?.filter(child => child.errorsCount > 0)
|
149
|
+
.forEach(child => {
|
150
|
+
try {
|
151
|
+
const error = child.errors?.shift()
|
152
|
+
if (!error) return
|
153
|
+
|
154
|
+
this.app.notifier.notify({
|
155
|
+
group: `${this.app.label}-${child.name}`,
|
156
|
+
message: stripAnsi(error.message),
|
157
|
+
open: error.file ? pathToFileURL(error.file) : ``,
|
158
|
+
subtitle: error.file ? `Error in ${error.name}` : error.name,
|
159
|
+
title: makeNoticeTitle(child),
|
160
|
+
})
|
161
|
+
this.app.notifier.openEditor(error.file)
|
162
|
+
} catch (error) {
|
163
|
+
this.logger.error(error)
|
164
|
+
}
|
165
|
+
})
|
166
|
+
}
|
167
|
+
|
168
|
+
this.compilationStats.children
|
169
|
+
?.filter(child => child.errorsCount === 0)
|
170
|
+
.forEach(child => {
|
171
|
+
try {
|
172
|
+
this.app.notifier.notify({
|
173
|
+
group: `${this.app.label}-${child.name}`,
|
174
|
+
message: child.modules
|
175
|
+
? `${child.modules.length} modules compiled in ${duration(
|
176
|
+
child.time,
|
177
|
+
)}`
|
178
|
+
: `Compiled in ${duration(child.time)}`,
|
179
|
+
open: this.app.server?.publicUrl.href,
|
180
|
+
subtitle: `Build successful`,
|
181
|
+
title: makeNoticeTitle(child),
|
182
|
+
})
|
183
|
+
|
184
|
+
this.app.notifier.openBrowser(this.app.server?.publicUrl.href)
|
185
|
+
} catch (error) {
|
186
|
+
this.logger.error(error)
|
187
|
+
}
|
188
|
+
})
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* {@link Service.register}
|
193
|
+
*/
|
194
|
+
@bind
|
195
|
+
public override async register?(bud: Bud): Promise<any> {
|
196
|
+
this.implementation = await bud.module
|
197
|
+
.import(`@roots/bud-support/webpack`, import.meta.url)
|
198
|
+
.catch(error => {
|
199
|
+
throw BudError.normalize(error)
|
200
|
+
})
|
201
|
+
}
|
202
|
+
|
203
|
+
@bind
|
204
|
+
public sourceErrors?(
|
205
|
+
errors: Array<StatsError>,
|
206
|
+
): Array<ErrorWithSourceFile | StatsError> {
|
207
|
+
if (!errors || !errors.length) return []
|
208
|
+
|
209
|
+
try {
|
210
|
+
const parseError = (
|
211
|
+
error: StatsError,
|
212
|
+
): ErrorWithSourceFile | StatsError => {
|
213
|
+
let file: SourceFile[`file`] | undefined
|
214
|
+
|
215
|
+
const moduleIdent = error.moduleId ?? error.moduleName
|
216
|
+
|
217
|
+
const module = this.compilationStats.children
|
218
|
+
.flatMap(child => child?.modules)
|
219
|
+
.find(
|
220
|
+
module =>
|
221
|
+
module?.id === moduleIdent || module?.name === moduleIdent,
|
222
|
+
)
|
223
|
+
|
224
|
+
if (!module) return error
|
225
|
+
|
226
|
+
if (module.nameForCondition) {
|
227
|
+
file = module.nameForCondition
|
228
|
+
} else if (module.name) {
|
229
|
+
file = this.app.path(`@src`, module.name)
|
230
|
+
}
|
231
|
+
|
232
|
+
return !file
|
233
|
+
? {...error, name: module.name ?? error.name}
|
234
|
+
: {...error, file, name: module.name ?? error.name}
|
235
|
+
}
|
236
|
+
|
237
|
+
return errors?.map(parseError).filter(Boolean)
|
238
|
+
} catch (error) {
|
239
|
+
this.app.warn(`error parsing errors`, error)
|
240
|
+
return []
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
const statsOptions = {
|
246
|
+
all: false,
|
247
|
+
children: {
|
248
|
+
all: false,
|
249
|
+
assets: true,
|
250
|
+
cached: true,
|
251
|
+
cachedAssets: true,
|
252
|
+
cachedModules: true,
|
253
|
+
entrypoints: true,
|
254
|
+
errorDetails: false,
|
255
|
+
errors: true,
|
256
|
+
errorsCount: true,
|
257
|
+
errorStack: false,
|
258
|
+
hash: true,
|
259
|
+
modules: true,
|
260
|
+
name: true,
|
261
|
+
outputPath: true,
|
262
|
+
reasons: false,
|
263
|
+
runtime: true,
|
264
|
+
timings: true,
|
265
|
+
warnings: true,
|
266
|
+
warningsCount: true,
|
267
|
+
},
|
268
|
+
name: true,
|
269
|
+
}
|
@@ -1,42 +0,0 @@
|
|
1
|
-
import type { MultiCompiler, MultiStats, StatsError } from '@roots/bud-framework/config';
|
2
|
-
import type { Compiler as Contract } from '@roots/bud-framework/services';
|
3
|
-
import type { ErrorWithSourceFile } from '@roots/bud-support/open';
|
4
|
-
import { Service } from '@roots/bud-framework/service';
|
5
|
-
import webpack from 'webpack';
|
6
|
-
/**
|
7
|
-
* Wepback compilation controller class
|
8
|
-
*/
|
9
|
-
export declare class Compiler extends Service implements Contract.Service {
|
10
|
-
/**
|
11
|
-
* Configuration
|
12
|
-
*/
|
13
|
-
config: Contract.Service[`config`];
|
14
|
-
/**
|
15
|
-
* Compiler implementation
|
16
|
-
*/
|
17
|
-
implementation: typeof webpack;
|
18
|
-
/**
|
19
|
-
* Compiler instance
|
20
|
-
*/
|
21
|
-
instance: Contract.Service[`instance`];
|
22
|
-
/**
|
23
|
-
* Compilation stats
|
24
|
-
*/
|
25
|
-
stats: Contract.Service[`stats`];
|
26
|
-
/**
|
27
|
-
* Initiates compilation
|
28
|
-
*/
|
29
|
-
compile(): Promise<MultiCompiler>;
|
30
|
-
/**
|
31
|
-
* Compiler error event
|
32
|
-
*/
|
33
|
-
onError(error: Error): Promise<void>;
|
34
|
-
/**
|
35
|
-
* Stats handler
|
36
|
-
*/
|
37
|
-
onStats(stats: MultiStats): Promise<void>;
|
38
|
-
/**
|
39
|
-
* Parse errors from webpack stats
|
40
|
-
*/
|
41
|
-
sourceErrors(errors: Array<StatsError>): Array<ErrorWithSourceFile | StatsError>;
|
42
|
-
}
|
package/lib/types.d.ts
DELETED
package/lib/types.js
DELETED
package/src/compiler.service.tsx
DELETED
@@ -1,252 +0,0 @@
|
|
1
|
-
import type {Bud} from '@roots/bud-framework'
|
2
|
-
import type {
|
3
|
-
MultiCompiler,
|
4
|
-
MultiStats,
|
5
|
-
StatsCompilation,
|
6
|
-
StatsError,
|
7
|
-
} from '@roots/bud-framework/config'
|
8
|
-
import type {Compiler as Contract} from '@roots/bud-framework/services'
|
9
|
-
import type {
|
10
|
-
ErrorWithSourceFile,
|
11
|
-
SourceFile,
|
12
|
-
} from '@roots/bud-support/open'
|
13
|
-
|
14
|
-
import * as App from '@roots/bud-dashboard/app'
|
15
|
-
import {Service} from '@roots/bud-framework/service'
|
16
|
-
import {bind} from '@roots/bud-support/decorators/bind'
|
17
|
-
import {BudError, CompilerError} from '@roots/bud-support/errors'
|
18
|
-
import {duration} from '@roots/bud-support/human-readable'
|
19
|
-
import * as Ink from '@roots/bud-support/ink'
|
20
|
-
import stripAnsi from '@roots/bud-support/strip-ansi'
|
21
|
-
import {pathToFileURL} from 'node:url'
|
22
|
-
import webpack from 'webpack'
|
23
|
-
|
24
|
-
/**
|
25
|
-
* Wepback compilation controller class
|
26
|
-
*/
|
27
|
-
export class Compiler extends Service implements Contract.Service {
|
28
|
-
/**
|
29
|
-
* Configuration
|
30
|
-
*/
|
31
|
-
public config: Contract.Service[`config`] = []
|
32
|
-
|
33
|
-
/**
|
34
|
-
* Compiler implementation
|
35
|
-
*/
|
36
|
-
public implementation: typeof webpack
|
37
|
-
|
38
|
-
/**
|
39
|
-
* Compiler instance
|
40
|
-
*/
|
41
|
-
public instance: Contract.Service[`instance`]
|
42
|
-
|
43
|
-
/**
|
44
|
-
* Compilation stats
|
45
|
-
*/
|
46
|
-
public stats: Contract.Service[`stats`]
|
47
|
-
|
48
|
-
/**
|
49
|
-
* Initiates compilation
|
50
|
-
*/
|
51
|
-
@bind
|
52
|
-
public async compile(): Promise<MultiCompiler> {
|
53
|
-
const compilerPath = await this.app.module.resolve(
|
54
|
-
`webpack`,
|
55
|
-
import.meta.url,
|
56
|
-
)
|
57
|
-
this.implementation = await this.app.module.import(
|
58
|
-
compilerPath,
|
59
|
-
import.meta.url,
|
60
|
-
)
|
61
|
-
this.logger.log(`imported webpack`, this.implementation.version)
|
62
|
-
|
63
|
-
this.config = !this.app.hasChildren
|
64
|
-
? [await this.app.build.make()]
|
65
|
-
: await Promise.all(
|
66
|
-
Object.values(this.app.children).map(async (child: Bud) => {
|
67
|
-
try {
|
68
|
-
return await child.build.make()
|
69
|
-
} catch (error) {
|
70
|
-
throw error
|
71
|
-
}
|
72
|
-
}),
|
73
|
-
)
|
74
|
-
|
75
|
-
await this.app.hooks.fire(`compiler.before`, this.app)
|
76
|
-
|
77
|
-
this.logger.timeEnd(`initialize`)
|
78
|
-
|
79
|
-
this.logger.await(`compilation`)
|
80
|
-
|
81
|
-
this.instance = this.implementation(this.config)
|
82
|
-
this.instance.hooks.done.tap(this.app.label, async (stats: any) => {
|
83
|
-
await this.onStats(stats)
|
84
|
-
await this.app.hooks.fire(`compiler.close`, this.app)
|
85
|
-
})
|
86
|
-
|
87
|
-
await this.app.hooks.fire(`compiler.after`, this.app)
|
88
|
-
|
89
|
-
return this.instance
|
90
|
-
}
|
91
|
-
|
92
|
-
/**
|
93
|
-
* Compiler error event
|
94
|
-
*/
|
95
|
-
@bind
|
96
|
-
public async onError(error: Error) {
|
97
|
-
process.exitCode = 1
|
98
|
-
|
99
|
-
await this.app.hooks.fire(`compiler.error`, error)
|
100
|
-
|
101
|
-
this.app.isDevelopment &&
|
102
|
-
this.app.server.appliedMiddleware?.hot?.publish({error})
|
103
|
-
|
104
|
-
try {
|
105
|
-
this.app.notifier.notify({
|
106
|
-
group: this.app.label,
|
107
|
-
message: error.message,
|
108
|
-
subtitle: error.name,
|
109
|
-
})
|
110
|
-
} catch (error) {
|
111
|
-
this.logger.error(error)
|
112
|
-
}
|
113
|
-
|
114
|
-
try {
|
115
|
-
Ink.render(
|
116
|
-
<App.Error
|
117
|
-
error={
|
118
|
-
new CompilerError(error.message, {
|
119
|
-
props: {
|
120
|
-
details: `This error was thrown by the webpack compiler itself. It is not the same as a syntax error. It is likely a missing or unresolvable build dependency.`,
|
121
|
-
docs: new URL(`https://bud.js.org/`),
|
122
|
-
issues: new URL(
|
123
|
-
`https://github.com/roots/bud/search?q=is:issue+"compiler" in:title`,
|
124
|
-
),
|
125
|
-
stack: error.stack,
|
126
|
-
thrownBy: `webpack`,
|
127
|
-
},
|
128
|
-
})
|
129
|
-
}
|
130
|
-
/>,
|
131
|
-
)
|
132
|
-
} catch (error) {
|
133
|
-
throw BudError.normalize(error)
|
134
|
-
}
|
135
|
-
}
|
136
|
-
|
137
|
-
/**
|
138
|
-
* Stats handler
|
139
|
-
*/
|
140
|
-
@bind
|
141
|
-
public async onStats(stats: MultiStats) {
|
142
|
-
const makeNoticeTitle = (child: StatsCompilation) =>
|
143
|
-
this.app.label !== child.name
|
144
|
-
? `${this.app.label} (${child.name})`
|
145
|
-
: child.name
|
146
|
-
|
147
|
-
this.stats = stats.toJson(this.app.hooks.filter(`build.stats`))
|
148
|
-
|
149
|
-
await this.app.hooks.fire(`compiler.stats`, stats)
|
150
|
-
|
151
|
-
const statsUpdate = this.app.dashboard.update(stats)
|
152
|
-
|
153
|
-
if (stats.hasErrors()) {
|
154
|
-
process.exitCode = 1
|
155
|
-
|
156
|
-
this.stats.children = this.stats.children?.map(child => ({
|
157
|
-
...child,
|
158
|
-
errors: this.sourceErrors(child.errors),
|
159
|
-
}))
|
160
|
-
|
161
|
-
this.stats.children
|
162
|
-
?.filter(child => child.errorsCount > 0)
|
163
|
-
.forEach(child => {
|
164
|
-
try {
|
165
|
-
const error = child.errors?.shift()
|
166
|
-
if (!error) return
|
167
|
-
|
168
|
-
this.app.notifier.notify({
|
169
|
-
group: `${this.app.label}-${child.name}`,
|
170
|
-
message: stripAnsi(error.message),
|
171
|
-
open: error.file ? pathToFileURL(error.file) : ``,
|
172
|
-
subtitle: error.file ? `Error in ${error.name}` : error.name,
|
173
|
-
title: makeNoticeTitle(child),
|
174
|
-
})
|
175
|
-
this.app.notifier.openEditor(error.file)
|
176
|
-
} catch (error) {
|
177
|
-
this.logger.error(error)
|
178
|
-
}
|
179
|
-
})
|
180
|
-
}
|
181
|
-
|
182
|
-
this.stats.children
|
183
|
-
?.filter(child => child.errorsCount === 0)
|
184
|
-
.forEach(child => {
|
185
|
-
try {
|
186
|
-
this.app.notifier.notify({
|
187
|
-
group: `${this.app.label}-${child.name}`,
|
188
|
-
message: child.modules
|
189
|
-
? `${child.modules.length} modules compiled in ${duration(
|
190
|
-
child.time,
|
191
|
-
)}`
|
192
|
-
: `Compiled in ${duration(child.time)}`,
|
193
|
-
open: this.app.server?.publicUrl.href,
|
194
|
-
subtitle: `Build successful`,
|
195
|
-
title: makeNoticeTitle(child),
|
196
|
-
})
|
197
|
-
this.app.notifier.openBrowser(this.app.server?.publicUrl.href)
|
198
|
-
} catch (error) {
|
199
|
-
this.logger.error(error)
|
200
|
-
}
|
201
|
-
})
|
202
|
-
|
203
|
-
await statsUpdate
|
204
|
-
}
|
205
|
-
|
206
|
-
/**
|
207
|
-
* Parse errors from webpack stats
|
208
|
-
*/
|
209
|
-
@bind
|
210
|
-
public sourceErrors(
|
211
|
-
errors: Array<StatsError>,
|
212
|
-
): Array<ErrorWithSourceFile | StatsError> {
|
213
|
-
if (!errors || !errors.length) return []
|
214
|
-
|
215
|
-
try {
|
216
|
-
const parseError = (
|
217
|
-
error: StatsError,
|
218
|
-
): ErrorWithSourceFile | StatsError => {
|
219
|
-
let file: SourceFile[`file`] | undefined
|
220
|
-
|
221
|
-
const modules = this.stats.children.flatMap(child => child.modules)
|
222
|
-
const moduleIdent = error.moduleId ?? error.moduleName
|
223
|
-
|
224
|
-
const module = modules.find(
|
225
|
-
module =>
|
226
|
-
module?.id === moduleIdent || module?.name === moduleIdent,
|
227
|
-
)
|
228
|
-
|
229
|
-
if (!module) {
|
230
|
-
return error
|
231
|
-
}
|
232
|
-
|
233
|
-
if (module.nameForCondition) {
|
234
|
-
file = module.nameForCondition
|
235
|
-
} else if (module.name) {
|
236
|
-
file = this.app.path(`@src`, module.name)
|
237
|
-
}
|
238
|
-
|
239
|
-
if (!file) {
|
240
|
-
return error
|
241
|
-
}
|
242
|
-
|
243
|
-
return {...error, file, name: module.name ?? error.name}
|
244
|
-
}
|
245
|
-
|
246
|
-
return errors?.map(parseError).filter(Boolean)
|
247
|
-
} catch (error) {
|
248
|
-
this.app.warn(`error parsing errors`, error)
|
249
|
-
return []
|
250
|
-
}
|
251
|
-
}
|
252
|
-
}
|
package/src/compiler.test.ts
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
import {Bud, factory} from '@repo/test-kit'
|
2
|
-
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
3
|
-
|
4
|
-
import Compiler from './index.js'
|
5
|
-
|
6
|
-
describe(`@roots/bud-compiler`, function () {
|
7
|
-
let bud: Bud
|
8
|
-
let compiler: Compiler
|
9
|
-
|
10
|
-
beforeEach(async () => {
|
11
|
-
vi.clearAllMocks()
|
12
|
-
|
13
|
-
bud = await factory({mode: `development`})
|
14
|
-
compiler = new Compiler(() => bud)
|
15
|
-
})
|
16
|
-
|
17
|
-
it(`has compile fn`, () => {
|
18
|
-
expect(compiler.compile).toBeInstanceOf(Function)
|
19
|
-
})
|
20
|
-
|
21
|
-
it(`should call logger.log`, async () => {
|
22
|
-
const logSpy = vi.spyOn(compiler.logger, `log`)
|
23
|
-
await compiler.compile()
|
24
|
-
expect(logSpy).toHaveBeenCalled()
|
25
|
-
})
|
26
|
-
|
27
|
-
it(`should have config with array length 1`, async () => {
|
28
|
-
await compiler.compile()
|
29
|
-
expect(compiler.config).toHaveLength(1)
|
30
|
-
})
|
31
|
-
|
32
|
-
it(`should have config with array length 2 when hasChildren is true`, async () => {
|
33
|
-
// @ts-ignore
|
34
|
-
await bud.make(`foo`)
|
35
|
-
await bud.make(`bar`)
|
36
|
-
|
37
|
-
compiler.app.children = {
|
38
|
-
foo: compiler.app,
|
39
|
-
bar: compiler.app,
|
40
|
-
}
|
41
|
-
|
42
|
-
await compiler.compile()
|
43
|
-
expect(compiler.config).toHaveLength(2)
|
44
|
-
})
|
45
|
-
|
46
|
-
it(`should set done tap`, async () => {
|
47
|
-
try {
|
48
|
-
await compiler.compile()
|
49
|
-
expect(compiler.instance.hooks.done.tap).toHaveBeenCalledWith(
|
50
|
-
`MOCK-dev-handle`,
|
51
|
-
compiler.onStats,
|
52
|
-
)
|
53
|
-
} catch (e) {}
|
54
|
-
})
|
55
|
-
|
56
|
-
it(`has onStats fn`, () => {
|
57
|
-
expect(compiler.onStats).toBeInstanceOf(Function)
|
58
|
-
})
|
59
|
-
|
60
|
-
it(`has error handler`, () => {
|
61
|
-
expect(compiler.onError).toBeInstanceOf(Function)
|
62
|
-
})
|
63
|
-
|
64
|
-
it(`has close handler`, () => {
|
65
|
-
expect(compiler.onError).toBeInstanceOf(Function)
|
66
|
-
})
|
67
|
-
})
|
package/src/types.ts
DELETED