quickbundle 0.0.0-next-71fed0b → 0.0.0-next-180c331
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/index.mjs +129 -58
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { helpers, termost } from 'termost';
|
|
2
2
|
import { readFile as readFile$1 } from 'node:fs/promises';
|
|
3
|
-
import process from 'node:process';
|
|
3
|
+
import process, { chdir } from 'node:process';
|
|
4
4
|
import { watch as watch$1, rollup } from 'rollup';
|
|
5
|
-
import { join } from 'node:path';
|
|
5
|
+
import { join, dirname, basename } from 'node:path';
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
7
|
import { swc } from 'rollup-plugin-swc3';
|
|
8
8
|
import externals from 'rollup-plugin-node-externals';
|
|
@@ -11,8 +11,13 @@ import url from '@rollup/plugin-url';
|
|
|
11
11
|
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
12
12
|
import json from '@rollup/plugin-json';
|
|
13
13
|
import commonjs from '@rollup/plugin-commonjs';
|
|
14
|
+
import os from 'node:os';
|
|
15
|
+
import { writeFileSync } from 'node:fs';
|
|
14
16
|
import { gzipSize } from 'gzip-size';
|
|
15
17
|
|
|
18
|
+
var name = "quickbundle";
|
|
19
|
+
var version = "0.0.0-next-180c331";
|
|
20
|
+
|
|
16
21
|
const CWD = process.cwd();
|
|
17
22
|
|
|
18
23
|
const readFile = readFile$1;
|
|
@@ -37,10 +42,10 @@ const isRecord = (value)=>{
|
|
|
37
42
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38
43
|
};
|
|
39
44
|
|
|
40
|
-
const watch = (
|
|
45
|
+
const watch = (input)=>{
|
|
41
46
|
process.env.NODE_ENV ??= "development";
|
|
42
|
-
const watcher = watch$1(
|
|
43
|
-
...
|
|
47
|
+
const watcher = watch$1(input.data.map((configItem)=>({
|
|
48
|
+
...configItem,
|
|
44
49
|
onLog
|
|
45
50
|
})));
|
|
46
51
|
let startDuration;
|
|
@@ -85,39 +90,48 @@ const clearLog = (...input)=>{
|
|
|
85
90
|
|
|
86
91
|
const require = createRequire(import.meta.url);
|
|
87
92
|
const PKG = require(join(CWD, "./package.json"));
|
|
88
|
-
const
|
|
93
|
+
const createConfiguration = (options = {
|
|
89
94
|
minification: false,
|
|
90
95
|
sourceMaps: false,
|
|
91
96
|
standalone: false
|
|
92
97
|
})=>{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
const buildableExports = getBuildableExports(options);
|
|
99
|
+
return {
|
|
100
|
+
data: buildableExports.flatMap((buildableExport)=>{
|
|
101
|
+
return [
|
|
102
|
+
buildableExport.source && createMainConfig({
|
|
103
|
+
...buildableExport,
|
|
104
|
+
source: buildableExport.source
|
|
105
|
+
}, options),
|
|
106
|
+
buildableExport.source && buildableExport.types && createTypesConfig({
|
|
107
|
+
source: buildableExport.source,
|
|
108
|
+
types: buildableExport.types
|
|
109
|
+
}, options)
|
|
110
|
+
].filter(Boolean);
|
|
111
|
+
}),
|
|
112
|
+
metadata: buildableExports
|
|
113
|
+
};
|
|
105
114
|
};
|
|
115
|
+
// eslint-disable-next-line sonarjs/cyclomatic-complexity
|
|
106
116
|
const getBuildableExports = ({ standalone })=>{
|
|
107
117
|
if (standalone) {
|
|
108
118
|
/**
|
|
109
119
|
* Entry-point resolution invariants for standalone target (mostly binaries).
|
|
110
|
-
*/ if (!PKG.source || !PKG.bin) {
|
|
111
|
-
throw new Error("Invalid package entry points contract. Standalone compilation is enabled but required fields
|
|
120
|
+
*/ if (!PKG.source || !PKG.bin || !PKG.name) {
|
|
121
|
+
throw new Error("Invalid package entry points contract. Standalone compilation is enabled but required fields are missing. Make sure to set `name`, `source`, and `bin` fields.");
|
|
112
122
|
}
|
|
113
123
|
const bin = PKG.bin;
|
|
124
|
+
const name = PKG.name;
|
|
125
|
+
const source = PKG.source;
|
|
114
126
|
return isRecord(bin) ? Object.entries(bin).map((data)=>({
|
|
127
|
+
bin: data[0],
|
|
115
128
|
require: data[1],
|
|
116
|
-
source
|
|
129
|
+
source
|
|
117
130
|
})) : [
|
|
118
131
|
{
|
|
132
|
+
bin: name,
|
|
119
133
|
require: bin,
|
|
120
|
-
source
|
|
134
|
+
source
|
|
121
135
|
}
|
|
122
136
|
];
|
|
123
137
|
}
|
|
@@ -175,15 +189,15 @@ const getBuildableExports = ({ standalone })=>{
|
|
|
175
189
|
}
|
|
176
190
|
return output;
|
|
177
191
|
};
|
|
178
|
-
const getPlugins = (
|
|
192
|
+
const getPlugins = (customPlugins, options)=>{
|
|
179
193
|
return [
|
|
180
|
-
externals({
|
|
194
|
+
!options.standalone && externals({
|
|
181
195
|
builtins: true,
|
|
182
196
|
deps: true,
|
|
183
197
|
/**
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
198
|
+
* As they're not installed consumer side, `devDependencies` are declared as internal dependencies (via the `false` value)
|
|
199
|
+
* and bundled into the dist if and only if imported and not listed as `peerDependencies` (otherwise, they're considered external).
|
|
200
|
+
*/ devDeps: false,
|
|
187
201
|
optDeps: true,
|
|
188
202
|
peerDeps: true
|
|
189
203
|
}),
|
|
@@ -191,7 +205,7 @@ const getPlugins = (...customPlugins)=>{
|
|
|
191
205
|
url(),
|
|
192
206
|
json(),
|
|
193
207
|
...customPlugins
|
|
194
|
-
];
|
|
208
|
+
].filter(Boolean);
|
|
195
209
|
};
|
|
196
210
|
const createMainConfig = (entryPoints, options)=>{
|
|
197
211
|
const { minification, sourceMaps } = options;
|
|
@@ -215,13 +229,16 @@ const createMainConfig = (entryPoints, options)=>{
|
|
|
215
229
|
return {
|
|
216
230
|
input: entryPoints.source,
|
|
217
231
|
output,
|
|
218
|
-
plugins: getPlugins(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
232
|
+
plugins: getPlugins([
|
|
233
|
+
nodeResolve(),
|
|
234
|
+
swc({
|
|
235
|
+
minify: minification,
|
|
236
|
+
sourceMaps
|
|
237
|
+
})
|
|
238
|
+
], options)
|
|
222
239
|
};
|
|
223
240
|
};
|
|
224
|
-
const createTypesConfig = (entryPoints)=>{
|
|
241
|
+
const createTypesConfig = (entryPoints, options)=>{
|
|
225
242
|
return {
|
|
226
243
|
input: entryPoints.source,
|
|
227
244
|
output: [
|
|
@@ -229,23 +246,25 @@ const createTypesConfig = (entryPoints)=>{
|
|
|
229
246
|
file: entryPoints.types
|
|
230
247
|
}
|
|
231
248
|
],
|
|
232
|
-
plugins: getPlugins(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
249
|
+
plugins: getPlugins([
|
|
250
|
+
nodeResolve({
|
|
251
|
+
/**
|
|
252
|
+
* The `exports` conditional fields definition order is important in the `package.json file`.
|
|
253
|
+
* To be resolved first, `types` field must always come first in the package.json exports definition.
|
|
254
|
+
* @see https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#package-json-exports-imports-and-self-referencing.
|
|
255
|
+
*/ exportConditions: [
|
|
256
|
+
"types"
|
|
257
|
+
]
|
|
258
|
+
}),
|
|
259
|
+
dts({
|
|
260
|
+
compilerOptions: {
|
|
261
|
+
incremental: false
|
|
262
|
+
},
|
|
263
|
+
respectExternal: true
|
|
264
|
+
})
|
|
265
|
+
], options)
|
|
246
266
|
};
|
|
247
267
|
};
|
|
248
|
-
createConfigurations();
|
|
249
268
|
|
|
250
269
|
const createWatchCommand = (program)=>{
|
|
251
270
|
return createCommand(program, {
|
|
@@ -253,7 +272,7 @@ const createWatchCommand = (program)=>{
|
|
|
253
272
|
description: "Watch and rebuild on any code change (development mode)"
|
|
254
273
|
}).task({
|
|
255
274
|
handler (context) {
|
|
256
|
-
watch(
|
|
275
|
+
watch(createConfiguration({
|
|
257
276
|
minification: context.minification,
|
|
258
277
|
sourceMaps: context.sourceMaps,
|
|
259
278
|
standalone: false
|
|
@@ -262,8 +281,9 @@ const createWatchCommand = (program)=>{
|
|
|
262
281
|
});
|
|
263
282
|
};
|
|
264
283
|
|
|
265
|
-
const build = async (
|
|
284
|
+
const build = async (input)=>{
|
|
266
285
|
process.env.NODE_ENV ??= "production";
|
|
286
|
+
const { data: configurations } = input;
|
|
267
287
|
const output = [];
|
|
268
288
|
for (const config of configurations){
|
|
269
289
|
const initialTime = Date.now();
|
|
@@ -277,15 +297,15 @@ const build = async (configurations)=>{
|
|
|
277
297
|
];
|
|
278
298
|
const promises = [];
|
|
279
299
|
for (const outputEntry of outputEntries){
|
|
280
|
-
const
|
|
281
|
-
if (!
|
|
300
|
+
const outputFilePath = outputEntry.file ?? outputEntry.dir;
|
|
301
|
+
if (!outputFilePath) {
|
|
282
302
|
throw new Error("Misconfigured file entry point. Make sure to define an `import`, `require`, or `default` field.");
|
|
283
303
|
}
|
|
284
304
|
promises.push(new Promise((resolve, reject)=>{
|
|
285
305
|
bundle.write(outputEntry).then(()=>{
|
|
286
306
|
resolve({
|
|
287
307
|
elapsedTime: Date.now() - initialTime,
|
|
288
|
-
|
|
308
|
+
filePath: outputFilePath
|
|
289
309
|
});
|
|
290
310
|
}).catch((reason)=>{
|
|
291
311
|
reject(reason);
|
|
@@ -298,6 +318,53 @@ const build = async (configurations)=>{
|
|
|
298
318
|
return output;
|
|
299
319
|
};
|
|
300
320
|
|
|
321
|
+
const createCompileCommand = (program)=>{
|
|
322
|
+
return program.command({
|
|
323
|
+
name: "compile",
|
|
324
|
+
description: "Compiles the source code into a self-contained executable"
|
|
325
|
+
}).task({
|
|
326
|
+
async handler () {
|
|
327
|
+
const osType = os.type();
|
|
328
|
+
const isWindowsOS = osType === "Windows_NT";
|
|
329
|
+
const isMacOS = osType === "Darwin";
|
|
330
|
+
const configuration = createConfiguration({
|
|
331
|
+
minification: true,
|
|
332
|
+
sourceMaps: false,
|
|
333
|
+
standalone: true
|
|
334
|
+
});
|
|
335
|
+
await build(configuration);
|
|
336
|
+
for (const { bin, require: filePath } of configuration.metadata){
|
|
337
|
+
if (!filePath || !bin) {
|
|
338
|
+
throw new Error("Invalid configuration output. Missing `filePath` or `bin` field definition.");
|
|
339
|
+
}
|
|
340
|
+
chdir(dirname(filePath));
|
|
341
|
+
const fileName = basename(filePath);
|
|
342
|
+
const blobFileName = `${fileName}.blob`;
|
|
343
|
+
/*
|
|
344
|
+
* TODO: split with several tasks
|
|
345
|
+
*/ const executableFileName = `${bin}${isWindowsOS ? ".exe" : ""}`;
|
|
346
|
+
const seaConfigFileName = `${fileName}.sea-config.json`;
|
|
347
|
+
writeFileSync(seaConfigFileName, JSON.stringify({
|
|
348
|
+
disableExperimentalSEAWarning: true,
|
|
349
|
+
main: fileName,
|
|
350
|
+
output: blobFileName,
|
|
351
|
+
useCodeCache: false,
|
|
352
|
+
useSnapshot: false
|
|
353
|
+
}), "utf-8");
|
|
354
|
+
await helpers.exec(`node --experimental-sea-config ${seaConfigFileName}`);
|
|
355
|
+
await helpers.exec(`node -e "require('fs').copyFileSync(process.execPath, '${executableFileName}')"`);
|
|
356
|
+
if (isMacOS) {
|
|
357
|
+
await helpers.exec(`codesign --remove-signature ${executableFileName}`);
|
|
358
|
+
}
|
|
359
|
+
await helpers.exec(`npx postject ${executableFileName} NODE_SEA_BLOB ${blobFileName} --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 ${isMacOS ? "--macho-segment-name NODE_SEA" : ""}`);
|
|
360
|
+
if (isMacOS) {
|
|
361
|
+
await helpers.exec(`codesign --sign - ${executableFileName}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
};
|
|
367
|
+
|
|
301
368
|
const createBuildCommand = (program)=>{
|
|
302
369
|
return createCommand(program, {
|
|
303
370
|
name: "build",
|
|
@@ -306,7 +373,7 @@ const createBuildCommand = (program)=>{
|
|
|
306
373
|
key: "buildOutput",
|
|
307
374
|
label: "Bundle assets 📦",
|
|
308
375
|
async handler (context) {
|
|
309
|
-
return build(
|
|
376
|
+
return build(createConfiguration({
|
|
310
377
|
minification: context.minification,
|
|
311
378
|
sourceMaps: context.sourceMaps,
|
|
312
379
|
standalone: false
|
|
@@ -330,7 +397,7 @@ const createBuildCommand = (program)=>{
|
|
|
330
397
|
].map((message, index)=>{
|
|
331
398
|
return index === 0 ? message : ` ${message}`;
|
|
332
399
|
}).join("\n"), {
|
|
333
|
-
label: `${item.
|
|
400
|
+
label: `${item.filePath} (took ${item.elapsedTime}ms)`,
|
|
334
401
|
type: "information"
|
|
335
402
|
});
|
|
336
403
|
});
|
|
@@ -342,7 +409,7 @@ const createBuildCommand = (program)=>{
|
|
|
342
409
|
};
|
|
343
410
|
const computeBundleSize = async (buildOutput)=>{
|
|
344
411
|
const computeFileSize = async (buildItemOutput)=>{
|
|
345
|
-
const content = await readFile(buildItemOutput.
|
|
412
|
+
const content = await readFile(buildItemOutput.filePath);
|
|
346
413
|
const gzSize = await gzipSize(content);
|
|
347
414
|
return {
|
|
348
415
|
...buildItemOutput,
|
|
@@ -358,9 +425,13 @@ const formatSize = (bytes)=>{
|
|
|
358
425
|
};
|
|
359
426
|
|
|
360
427
|
const createProgram = (...commandBuilders)=>{
|
|
361
|
-
const program = termost(
|
|
428
|
+
const program = termost({
|
|
429
|
+
name,
|
|
430
|
+
description: "The zero-configuration transpiler and bundler for the web",
|
|
431
|
+
version
|
|
432
|
+
});
|
|
362
433
|
for (const commandBuilder of commandBuilders){
|
|
363
434
|
commandBuilder(program);
|
|
364
435
|
}
|
|
365
436
|
};
|
|
366
|
-
createProgram(createBuildCommand, createWatchCommand);
|
|
437
|
+
createProgram(createBuildCommand, createWatchCommand, createCompileCommand);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quickbundle",
|
|
3
|
-
"version": "0.0.0-next-
|
|
3
|
+
"version": "0.0.0-next-180c331",
|
|
4
4
|
"description": "The zero-configuration transpiler and bundler for the web",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ayoub Adib",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"rollup-plugin-dts": "^6.1.1",
|
|
59
59
|
"rollup-plugin-node-externals": "^7.1.3",
|
|
60
60
|
"rollup-plugin-swc3": "^0.12.1",
|
|
61
|
-
"termost": "^
|
|
61
|
+
"termost": "^1.2.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/node": "22.9.0"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
|
-
"build": "rollup --config ./
|
|
68
|
-
"watch": "rollup --watch --config ./
|
|
67
|
+
"build": "rollup --config ./bundler.config.ts --configPlugin rollup-plugin-swc3",
|
|
68
|
+
"watch": "rollup --watch --config ./bundler.config.ts --configPlugin rollup-plugin-swc3"
|
|
69
69
|
}
|
|
70
70
|
}
|