@git.zone/tsbundle 2.11.4 → 2.12.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/interfaces/index.d.ts +1 -0
- package/dist_ts/mod_custom/index.d.ts +10 -3
- package/dist_ts/mod_custom/index.js +277 -86
- package/dist_ts/mod_esbuild/index.child.d.ts +4 -8
- package/dist_ts/mod_esbuild/index.child.js +51 -44
- package/dist_ts/mod_esbuild/plugins.d.ts +5 -2
- package/dist_ts/mod_esbuild/plugins.js +5 -3
- package/dist_ts/mod_esbuild/workerplugin.d.ts +12 -0
- package/dist_ts/mod_esbuild/workerplugin.js +254 -0
- package/dist_ts/mod_output/artifactpublisher.d.ts +43 -0
- package/dist_ts/mod_output/artifactpublisher.js +925 -0
- package/dist_ts/mod_output/index.d.ts +1 -0
- package/dist_ts/mod_output/index.js +11 -3
- package/dist_ts/mod_rolldown/index.child.d.ts +4 -2
- package/dist_ts/mod_rolldown/index.child.js +47 -36
- package/dist_ts/mod_rspack/index.child.d.ts +4 -2
- package/dist_ts/mod_rspack/index.child.js +73 -115
- package/dist_ts/plugins.d.ts +3 -1
- package/dist_ts/plugins.js +4 -2
- package/dist_ts/tsbundle.class.tsbundle.js +98 -16
- package/package.json +7 -5
- package/readme.hints.md +20 -4
- package/readme.md +23 -6
- package/third-party-notices.md +29 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/interfaces/index.ts +1 -0
- package/ts/mod_custom/index.ts +347 -96
- package/ts/mod_esbuild/index.child.ts +78 -47
- package/ts/mod_esbuild/plugins.ts +9 -2
- package/ts/mod_esbuild/workerplugin.ts +328 -0
- package/ts/mod_output/artifactpublisher.ts +1185 -0
- package/ts/mod_output/index.ts +10 -2
- package/ts/mod_rolldown/index.child.ts +65 -42
- package/ts/mod_rspack/index.child.ts +95 -127
- package/ts/plugins.ts +3 -1
- package/ts/tsbundle.class.tsbundle.ts +102 -14
package/ts/mod_output/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import * as paths from '../paths.js';
|
|
3
3
|
import * as interfaces from '../interfaces/index.js';
|
|
4
|
+
import { writeFileAtomically } from './artifactpublisher.js';
|
|
4
5
|
|
|
5
6
|
export class Base64TsOutput {
|
|
6
7
|
private files: interfaces.IBase64File[] = [];
|
|
8
|
+
private filePaths = new Set<string>();
|
|
7
9
|
private cwd: string;
|
|
8
10
|
|
|
9
11
|
constructor(cwd: string = paths.cwd) {
|
|
@@ -14,10 +16,15 @@ export class Base64TsOutput {
|
|
|
14
16
|
* Add a file with its content to the output
|
|
15
17
|
*/
|
|
16
18
|
public addFile(filePath: string, content: Buffer | string): void {
|
|
19
|
+
const normalizedPath = plugins.path.posix.normalize(filePath.replace(/\\/g, '/'));
|
|
20
|
+
if (this.filePaths.has(normalizedPath)) {
|
|
21
|
+
throw new Error(`Duplicate base64ts output path: ${normalizedPath}`);
|
|
22
|
+
}
|
|
17
23
|
const contentBuffer = typeof content === 'string' ? Buffer.from(content, 'utf-8') : content;
|
|
18
24
|
const contentBase64 = contentBuffer.toString('base64');
|
|
25
|
+
this.filePaths.add(normalizedPath);
|
|
19
26
|
this.files.push({
|
|
20
|
-
path:
|
|
27
|
+
path: normalizedPath,
|
|
21
28
|
contentBase64,
|
|
22
29
|
});
|
|
23
30
|
}
|
|
@@ -144,7 +151,7 @@ ${filesFormatted}
|
|
|
144
151
|
const outputDir = plugins.path.dirname(absolutePath);
|
|
145
152
|
await plugins.fs.directory(outputDir).create();
|
|
146
153
|
const content = this.generateTypeScript(maxLineLength);
|
|
147
|
-
await
|
|
154
|
+
await writeFileAtomically(absolutePath, content);
|
|
148
155
|
console.log(`Generated base64ts output: ${outputPath}`);
|
|
149
156
|
}
|
|
150
157
|
|
|
@@ -160,5 +167,6 @@ ${filesFormatted}
|
|
|
160
167
|
*/
|
|
161
168
|
public clear(): void {
|
|
162
169
|
this.files = [];
|
|
170
|
+
this.filePaths.clear();
|
|
163
171
|
}
|
|
164
172
|
}
|
|
@@ -2,6 +2,12 @@ import * as plugins from './plugins.js';
|
|
|
2
2
|
import * as paths from '../paths.js';
|
|
3
3
|
import * as interfaces from '../interfaces/index.js';
|
|
4
4
|
import { logger } from '../tsbundle.logging.js';
|
|
5
|
+
import {
|
|
6
|
+
cleanupBuildStage,
|
|
7
|
+
createBuildStage,
|
|
8
|
+
getChunkNamespace,
|
|
9
|
+
publishGeneratedArtifacts,
|
|
10
|
+
} from '../mod_output/artifactpublisher.js';
|
|
5
11
|
|
|
6
12
|
export class TsBundleProcess {
|
|
7
13
|
constructor() {
|
|
@@ -32,59 +38,76 @@ export class TsBundleProcess {
|
|
|
32
38
|
}
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
alias: await this.getAliases(),
|
|
44
|
-
tsconfigFilename: paths.tsconfigPath,
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
|
|
41
|
+
private async build(
|
|
42
|
+
fromArg: string,
|
|
43
|
+
toArg: string,
|
|
44
|
+
argvArg: interfaces.ICliOptions,
|
|
45
|
+
productionArg: boolean,
|
|
46
|
+
): Promise<void> {
|
|
47
|
+
const logicalOutputName = plugins.path.basename(argvArg.chunkOwner || toArg);
|
|
48
|
+
const chunkNamespace = getChunkNamespace(logicalOutputName);
|
|
48
49
|
const outputDir = plugins.path.dirname(toArg);
|
|
49
50
|
const outputFilename = plugins.path.basename(toArg);
|
|
51
|
+
const stage = createBuildStage(outputDir);
|
|
52
|
+
const stageMainPath = plugins.path.join(stage.stageDirectory, outputFilename);
|
|
53
|
+
try {
|
|
54
|
+
const result = await plugins.rolldown({
|
|
55
|
+
input: fromArg,
|
|
56
|
+
resolve: {
|
|
57
|
+
alias: await this.getAliases(),
|
|
58
|
+
tsconfigFilename: paths.tsconfigPath,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
try {
|
|
62
|
+
await result.write({
|
|
63
|
+
dir: stage.stageDirectory,
|
|
64
|
+
entryFileNames: outputFilename,
|
|
65
|
+
chunkFileNames: `chunks/${chunkNamespace}/[name]-[hash].js`,
|
|
66
|
+
assetFileNames: `chunks/${chunkNamespace}/[name]-[hash][extname]`,
|
|
67
|
+
format: 'es',
|
|
68
|
+
sourcemap: argvArg.sourcemap !== false,
|
|
69
|
+
minify: productionArg,
|
|
70
|
+
codeSplitting: false,
|
|
71
|
+
});
|
|
72
|
+
} finally {
|
|
73
|
+
await result.close();
|
|
74
|
+
}
|
|
75
|
+
await publishGeneratedArtifacts({
|
|
76
|
+
sourceDirectory: stage.stageDirectory,
|
|
77
|
+
sourceMainPath: stageMainPath,
|
|
78
|
+
targetPath: toArg,
|
|
79
|
+
logicalOutputName,
|
|
80
|
+
chunkNamespace,
|
|
81
|
+
sourceMapsEnabled: argvArg.sourcemap !== false,
|
|
82
|
+
});
|
|
83
|
+
} finally {
|
|
84
|
+
cleanupBuildStage(stage.stageDirectory, outputDir, stage.marker);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
50
87
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
88
|
+
/**
|
|
89
|
+
* creates a bundle for the test enviroment
|
|
90
|
+
*/
|
|
91
|
+
public async buildTest(
|
|
92
|
+
fromArg: string,
|
|
93
|
+
toArg: string,
|
|
94
|
+
argvArg: interfaces.ICliOptions,
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
await this.build(fromArg, toArg, argvArg, false);
|
|
58
97
|
}
|
|
59
98
|
|
|
60
99
|
/**
|
|
61
100
|
* creates a bundle for the production environment
|
|
62
101
|
*/
|
|
63
|
-
public async buildProduction(
|
|
64
|
-
|
|
102
|
+
public async buildProduction(
|
|
103
|
+
fromArg: string,
|
|
104
|
+
toArg: string,
|
|
105
|
+
argvArg: interfaces.ICliOptions,
|
|
106
|
+
): Promise<void> {
|
|
65
107
|
console.log('rolldown specific:');
|
|
66
108
|
console.log(`from: ${fromArg}`);
|
|
67
109
|
console.log(`to: ${toArg}`);
|
|
68
|
-
|
|
69
|
-
const result = await plugins.rolldown({
|
|
70
|
-
input: fromArg,
|
|
71
|
-
resolve: {
|
|
72
|
-
alias: await this.getAliases(),
|
|
73
|
-
tsconfigFilename: paths.tsconfigPath,
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const outputDir = plugins.path.dirname(toArg);
|
|
78
|
-
const outputFilename = plugins.path.basename(toArg);
|
|
79
|
-
|
|
80
|
-
await result.write({
|
|
81
|
-
dir: outputDir,
|
|
82
|
-
entryFileNames: outputFilename,
|
|
83
|
-
format: 'es',
|
|
84
|
-
sourcemap: argvArg.sourcemap !== false,
|
|
85
|
-
minify: true,
|
|
86
|
-
codeSplitting: false,
|
|
87
|
-
});
|
|
110
|
+
await this.build(fromArg, toArg, argvArg, true);
|
|
88
111
|
}
|
|
89
112
|
}
|
|
90
113
|
|
|
@@ -2,6 +2,12 @@ import * as plugins from './plugins.js';
|
|
|
2
2
|
import * as paths from '../paths.js';
|
|
3
3
|
import * as interfaces from '../interfaces/index.js';
|
|
4
4
|
import { logger } from '../tsbundle.logging.js';
|
|
5
|
+
import {
|
|
6
|
+
cleanupBuildStage,
|
|
7
|
+
createBuildStage,
|
|
8
|
+
getChunkNamespace,
|
|
9
|
+
publishGeneratedArtifacts,
|
|
10
|
+
} from '../mod_output/artifactpublisher.js';
|
|
5
11
|
|
|
6
12
|
export class TsBundleProcess {
|
|
7
13
|
constructor() {
|
|
@@ -36,22 +42,33 @@ export class TsBundleProcess {
|
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
private async build(
|
|
46
|
+
fromArg: string,
|
|
47
|
+
toArg: string,
|
|
48
|
+
argvArg: interfaces.ICliOptions,
|
|
49
|
+
productionArg: boolean,
|
|
50
|
+
): Promise<void> {
|
|
43
51
|
const aliases = await this.getAliases();
|
|
52
|
+
const logicalOutputName = plugins.path.basename(argvArg.chunkOwner || toArg);
|
|
53
|
+
const chunkNamespace = getChunkNamespace(logicalOutputName);
|
|
44
54
|
const outputDir = plugins.path.dirname(toArg);
|
|
45
55
|
const outputFilename = plugins.path.basename(toArg);
|
|
56
|
+
const stage = createBuildStage(outputDir);
|
|
57
|
+
const stageMainPath = plugins.path.join(stage.stageDirectory, outputFilename);
|
|
46
58
|
|
|
47
59
|
const config = {
|
|
48
|
-
mode: 'development' as const,
|
|
60
|
+
mode: productionArg ? 'production' as const : 'development' as const,
|
|
49
61
|
entry: {
|
|
50
62
|
main: fromArg,
|
|
51
63
|
},
|
|
52
64
|
output: {
|
|
53
|
-
path:
|
|
65
|
+
path: stage.stageDirectory,
|
|
54
66
|
filename: outputFilename,
|
|
67
|
+
chunkFilename: `chunks/${chunkNamespace}/[name]-[contenthash].js`,
|
|
68
|
+
assetModuleFilename: `chunks/${chunkNamespace}/[name]-[contenthash][ext]`,
|
|
69
|
+
cssFilename: `chunks/${chunkNamespace}/[name]-[contenthash].css`,
|
|
70
|
+
cssChunkFilename: `chunks/${chunkNamespace}/[name]-[contenthash].css`,
|
|
71
|
+
webassemblyModuleFilename: `chunks/${chunkNamespace}/[hash].module.wasm`,
|
|
55
72
|
module: true,
|
|
56
73
|
library: {
|
|
57
74
|
type: 'module' as const,
|
|
@@ -80,6 +97,12 @@ export class TsBundleProcess {
|
|
|
80
97
|
transform: {
|
|
81
98
|
decoratorVersion: '2022-03',
|
|
82
99
|
},
|
|
100
|
+
...(productionArg ? {
|
|
101
|
+
minify: {
|
|
102
|
+
compress: true,
|
|
103
|
+
mangle: true,
|
|
104
|
+
},
|
|
105
|
+
} : {}),
|
|
83
106
|
},
|
|
84
107
|
},
|
|
85
108
|
},
|
|
@@ -87,139 +110,84 @@ export class TsBundleProcess {
|
|
|
87
110
|
},
|
|
88
111
|
],
|
|
89
112
|
},
|
|
113
|
+
...(productionArg ? {
|
|
114
|
+
optimization: {
|
|
115
|
+
minimize: true,
|
|
116
|
+
concatenateModules: true,
|
|
117
|
+
usedExports: true,
|
|
118
|
+
sideEffects: true,
|
|
119
|
+
},
|
|
120
|
+
} : {}),
|
|
90
121
|
};
|
|
91
122
|
|
|
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
|
-
|
|
123
|
+
try {
|
|
124
|
+
await new Promise<void>((resolve, reject) => {
|
|
125
|
+
plugins.rspack(config, (err, stats) => {
|
|
126
|
+
if (err) {
|
|
127
|
+
console.error(err.stack || err);
|
|
128
|
+
reject(err);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (!stats) {
|
|
132
|
+
reject(new Error('Rspack did not return stats'));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (stats.hasErrors()) {
|
|
137
|
+
console.error(stats.toString());
|
|
138
|
+
reject(new Error('Build failed with errors'));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.log(
|
|
143
|
+
stats.toString({
|
|
144
|
+
colors: true,
|
|
145
|
+
modules: false,
|
|
146
|
+
children: false,
|
|
147
|
+
chunks: false,
|
|
148
|
+
chunkModules: false,
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
119
151
|
|
|
120
|
-
|
|
152
|
+
resolve();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
await publishGeneratedArtifacts({
|
|
156
|
+
sourceDirectory: stage.stageDirectory,
|
|
157
|
+
sourceMainPath: stageMainPath,
|
|
158
|
+
targetPath: toArg,
|
|
159
|
+
logicalOutputName,
|
|
160
|
+
chunkNamespace,
|
|
161
|
+
sourceMapsEnabled: argvArg.sourcemap !== false,
|
|
121
162
|
});
|
|
122
|
-
}
|
|
163
|
+
} finally {
|
|
164
|
+
cleanupBuildStage(stage.stageDirectory, outputDir, stage.marker);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* creates a bundle for the test enviroment
|
|
170
|
+
*/
|
|
171
|
+
public async buildTest(
|
|
172
|
+
fromArg: string,
|
|
173
|
+
toArg: string,
|
|
174
|
+
argvArg: interfaces.ICliOptions,
|
|
175
|
+
): Promise<void> {
|
|
176
|
+
await this.build(fromArg, toArg, argvArg, false);
|
|
123
177
|
}
|
|
124
178
|
|
|
125
179
|
/**
|
|
126
180
|
* creates a bundle for the production environment
|
|
127
181
|
*/
|
|
128
|
-
public async buildProduction(
|
|
182
|
+
public async buildProduction(
|
|
183
|
+
fromArg: string,
|
|
184
|
+
toArg: string,
|
|
185
|
+
argvArg: interfaces.ICliOptions,
|
|
186
|
+
): Promise<void> {
|
|
129
187
|
console.log('rspack specific:');
|
|
130
188
|
console.log(`from: ${fromArg}`);
|
|
131
189
|
console.log(`to: ${toArg}`);
|
|
132
|
-
|
|
133
|
-
const aliases = await this.getAliases();
|
|
134
|
-
const outputDir = plugins.path.dirname(toArg);
|
|
135
|
-
const outputFilename = plugins.path.basename(toArg);
|
|
136
|
-
|
|
137
|
-
const config = {
|
|
138
|
-
mode: 'production' as const,
|
|
139
|
-
entry: {
|
|
140
|
-
main: fromArg,
|
|
141
|
-
},
|
|
142
|
-
output: {
|
|
143
|
-
path: outputDir,
|
|
144
|
-
filename: outputFilename,
|
|
145
|
-
module: true,
|
|
146
|
-
library: {
|
|
147
|
-
type: 'module' as const,
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
devtool: (argvArg.sourcemap === false ? false : 'source-map') as false | 'source-map',
|
|
151
|
-
resolve: {
|
|
152
|
-
alias: aliases,
|
|
153
|
-
extensions: ['.ts', '.tsx', '.js', '.jsx'],
|
|
154
|
-
},
|
|
155
|
-
module: {
|
|
156
|
-
rules: [
|
|
157
|
-
{
|
|
158
|
-
test: /\.tsx?$/,
|
|
159
|
-
exclude: /node_modules/,
|
|
160
|
-
use: {
|
|
161
|
-
loader: 'builtin:swc-loader',
|
|
162
|
-
options: {
|
|
163
|
-
jsc: {
|
|
164
|
-
parser: {
|
|
165
|
-
syntax: 'typescript',
|
|
166
|
-
tsx: true,
|
|
167
|
-
decorators: true,
|
|
168
|
-
},
|
|
169
|
-
target: 'es2022',
|
|
170
|
-
transform: {
|
|
171
|
-
decoratorVersion: '2022-03',
|
|
172
|
-
},
|
|
173
|
-
minify: {
|
|
174
|
-
compress: true,
|
|
175
|
-
mangle: true,
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
type: 'javascript/auto',
|
|
181
|
-
},
|
|
182
|
-
],
|
|
183
|
-
},
|
|
184
|
-
optimization: {
|
|
185
|
-
minimize: true,
|
|
186
|
-
concatenateModules: true,
|
|
187
|
-
usedExports: true,
|
|
188
|
-
sideEffects: true,
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
return new Promise((resolve, reject) => {
|
|
193
|
-
plugins.rspack(config, (err, stats) => {
|
|
194
|
-
if (err) {
|
|
195
|
-
console.error(err.stack || err);
|
|
196
|
-
reject(err);
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
if (!stats) {
|
|
200
|
-
reject(new Error('Rspack did not return stats'));
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (stats.hasErrors()) {
|
|
205
|
-
console.error(stats.toString());
|
|
206
|
-
reject(new Error('Build failed with errors'));
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
console.log(
|
|
211
|
-
stats.toString({
|
|
212
|
-
colors: true,
|
|
213
|
-
modules: false,
|
|
214
|
-
children: false,
|
|
215
|
-
chunks: false,
|
|
216
|
-
chunkModules: false,
|
|
217
|
-
}),
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
resolve(undefined);
|
|
221
|
-
});
|
|
222
|
-
});
|
|
190
|
+
await this.build(fromArg, toArg, argvArg, true);
|
|
223
191
|
}
|
|
224
192
|
}
|
|
225
193
|
|
package/ts/plugins.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// node native
|
|
2
2
|
import * as path from 'path';
|
|
3
|
+
import * as crypto from 'node:crypto';
|
|
3
4
|
import * as fsSync from 'node:fs';
|
|
4
5
|
import * as fsPromises from 'node:fs/promises';
|
|
5
6
|
import * as os from 'node:os';
|
|
7
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
6
8
|
|
|
7
|
-
export { fsPromises, fsSync, os, path };
|
|
9
|
+
export { crypto, delay, fsPromises, fsSync, os, path };
|
|
8
10
|
|
|
9
11
|
// pushrocks scope
|
|
10
12
|
import * as smartconfig from '@push.rocks/smartconfig';
|
|
@@ -9,7 +9,6 @@ export class TsBundle {
|
|
|
9
9
|
toArg: string = './dist_bundle/bundle.js',
|
|
10
10
|
argvArg: interfaces.ICliOptions,
|
|
11
11
|
) {
|
|
12
|
-
const done = plugins.smartpromise.defer();
|
|
13
12
|
const getBundlerPath = () => {
|
|
14
13
|
switch (argvArg.bundler) {
|
|
15
14
|
case 'rolldown':
|
|
@@ -49,20 +48,109 @@ export class TsBundle {
|
|
|
49
48
|
},
|
|
50
49
|
},
|
|
51
50
|
);
|
|
52
|
-
const
|
|
53
|
-
childProcess
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
const startPromise = threadsimple.start();
|
|
52
|
+
const childProcess = threadsimple.threadChildProcess;
|
|
53
|
+
if (!childProcess) {
|
|
54
|
+
await startPromise;
|
|
55
|
+
throw new Error('ThreadSimple.start() did not expose its child process synchronously');
|
|
56
|
+
}
|
|
57
|
+
await new Promise<void>((resolve, reject) => {
|
|
58
|
+
let settled = false;
|
|
59
|
+
let startSettled = false;
|
|
60
|
+
let terminal = false;
|
|
61
|
+
let firstError: Error | undefined;
|
|
62
|
+
let terminationRequested = false;
|
|
63
|
+
let forceKillTimer: ReturnType<typeof setTimeout> | undefined;
|
|
64
|
+
const cleanupListeners = (): void => {
|
|
65
|
+
childProcess.removeListener('error', handleError);
|
|
66
|
+
childProcess.removeListener('exit', handleExit);
|
|
67
|
+
childProcess.removeListener('close', handleClose);
|
|
68
|
+
};
|
|
69
|
+
const clearForceKillTimer = (): void => {
|
|
70
|
+
if (forceKillTimer) {
|
|
71
|
+
clearTimeout(forceKillTimer);
|
|
72
|
+
forceKillTimer = undefined;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const settleIfComplete = (): void => {
|
|
76
|
+
if (settled || !startSettled || !terminal) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
settled = true;
|
|
80
|
+
clearForceKillTimer();
|
|
81
|
+
cleanupListeners();
|
|
82
|
+
if (firstError) {
|
|
83
|
+
reject(firstError);
|
|
84
|
+
} else {
|
|
85
|
+
resolve();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const isChildLive = (): boolean => (
|
|
89
|
+
childProcess.exitCode === null && childProcess.signalCode === null
|
|
90
|
+
);
|
|
91
|
+
const requestTermination = (): void => {
|
|
92
|
+
if (terminationRequested || !childProcess.pid || !isChildLive()) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
terminationRequested = true;
|
|
96
|
+
forceKillTimer = setTimeout(() => {
|
|
97
|
+
if (isChildLive()) {
|
|
98
|
+
try {
|
|
99
|
+
childProcess.kill('SIGKILL');
|
|
100
|
+
} catch {
|
|
101
|
+
// The first child-process failure remains the actionable error.
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}, 5_000);
|
|
105
|
+
try {
|
|
106
|
+
childProcess.kill('SIGTERM');
|
|
107
|
+
} catch {
|
|
108
|
+
// The first child-process failure remains the actionable error.
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const handleError = (errorArg: Error): void => {
|
|
112
|
+
firstError ??= errorArg;
|
|
113
|
+
requestTermination();
|
|
114
|
+
};
|
|
115
|
+
const handleTerminal = (
|
|
116
|
+
statusArg: number | null,
|
|
117
|
+
signalArg: NodeJS.Signals | null,
|
|
118
|
+
): void => {
|
|
119
|
+
if (terminal) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
terminal = true;
|
|
123
|
+
clearForceKillTimer();
|
|
124
|
+
if (!firstError && statusArg !== 0) {
|
|
125
|
+
const exitDetail = statusArg === null ? `signal ${signalArg}` : `exit code ${statusArg}`;
|
|
126
|
+
firstError = new Error(`Bundle build failed with ${exitDetail}`);
|
|
127
|
+
}
|
|
128
|
+
settleIfComplete();
|
|
129
|
+
};
|
|
130
|
+
const handleExit = (statusArg: number | null, signalArg: NodeJS.Signals | null): void => {
|
|
131
|
+
handleTerminal(statusArg, signalArg);
|
|
132
|
+
};
|
|
133
|
+
const handleClose = (statusArg: number | null, signalArg: NodeJS.Signals | null): void => {
|
|
134
|
+
handleTerminal(statusArg, signalArg);
|
|
135
|
+
};
|
|
136
|
+
childProcess.on('error', handleError);
|
|
137
|
+
childProcess.once('exit', handleExit);
|
|
138
|
+
childProcess.once('close', handleClose);
|
|
139
|
+
void startPromise.then(
|
|
140
|
+
() => {
|
|
141
|
+
startSettled = true;
|
|
142
|
+
settleIfComplete();
|
|
143
|
+
},
|
|
144
|
+
(errorArg: unknown) => {
|
|
145
|
+
startSettled = true;
|
|
146
|
+
firstError ??= errorArg instanceof Error ? errorArg : new Error(String(errorArg));
|
|
147
|
+
requestTermination();
|
|
148
|
+
settleIfComplete();
|
|
149
|
+
},
|
|
150
|
+
);
|
|
151
|
+
if (childProcess.exitCode !== null || childProcess.signalCode !== null) {
|
|
152
|
+
handleTerminal(childProcess.exitCode, childProcess.signalCode);
|
|
58
153
|
}
|
|
59
154
|
});
|
|
60
|
-
await done.promise;
|
|
61
|
-
if (argvArg.sourcemap === false) {
|
|
62
|
-
const outputPath = plugins.path.isAbsolute(toArg)
|
|
63
|
-
? toArg
|
|
64
|
-
: plugins.path.resolve(cwdArg, toArg);
|
|
65
|
-
await plugins.fsPromises.rm(`${outputPath}.map`, { force: true });
|
|
66
|
-
}
|
|
67
155
|
}
|
|
68
156
|
}
|