quickbundle 2.15.0 → 2.16.0-next-dfc95be
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.js +464 -561
- package/package.json +9 -14
package/dist/index.js
CHANGED
|
@@ -1,603 +1,506 @@
|
|
|
1
|
-
import { helpers, termost } from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import json from '@rollup/plugin-json';
|
|
16
|
-
import commonjs from '@rollup/plugin-commonjs';
|
|
17
|
-
import os from 'node:os';
|
|
18
|
-
import { gzipSize } from 'gzip-size';
|
|
1
|
+
import { helpers, termost } from "termost";
|
|
2
|
+
import { gzipSize } from "gzip-size";
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
+
import { rolldown, watch } from "rolldown";
|
|
5
|
+
import url from "@rollup/plugin-url";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import { dts } from "rolldown-plugin-dts";
|
|
8
|
+
import externals from "rollup-plugin-node-externals";
|
|
9
|
+
import decompress from "decompress";
|
|
10
|
+
import { createWriteStream } from "node:fs";
|
|
11
|
+
import { copyFile, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
12
|
+
import { Readable } from "node:stream";
|
|
13
|
+
import { finished } from "node:stream/promises";
|
|
14
|
+
import os from "node:os";
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
//#region package.json
|
|
17
|
+
var name = "quickbundle";
|
|
18
|
+
var version = "2.16.0-next-dfc95be";
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/bundler/build.ts
|
|
22
|
+
const build = async (input) => {
|
|
23
|
+
process.env.NODE_ENV ??= "production";
|
|
24
|
+
const { data: configurations } = input;
|
|
25
|
+
const output = [];
|
|
26
|
+
for (const config of configurations) {
|
|
27
|
+
const initialTime = Date.now();
|
|
28
|
+
const bundle = await rolldown(config);
|
|
29
|
+
if (config.output) {
|
|
30
|
+
const outputEntries = Array.isArray(config.output) ? config.output : [config.output];
|
|
31
|
+
const promises = [];
|
|
32
|
+
for (const outputEntry of outputEntries) {
|
|
33
|
+
const entryFileName = outputEntry.entryFileNames;
|
|
34
|
+
const outputFilePath = join(outputEntry.dir ?? "", typeof entryFileName === "string" ? entryFileName : "");
|
|
35
|
+
if (!outputFilePath) throw new Error("Misconfigured file entry point. Make sure to define an `import`, `require`, or `default` field.");
|
|
36
|
+
promises.push(new Promise((resolve, reject) => {
|
|
37
|
+
bundle.write(outputEntry).then(() => {
|
|
38
|
+
resolve({
|
|
39
|
+
elapsedTime: Date.now() - initialTime,
|
|
40
|
+
filePath: outputFilePath
|
|
41
|
+
});
|
|
42
|
+
}).catch((error) => {
|
|
43
|
+
if (error instanceof Error) reject(error);
|
|
44
|
+
});
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
output.push(...await Promise.all(promises));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return output;
|
|
28
51
|
};
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/helpers.ts
|
|
29
55
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
56
|
+
* Resolve a relative path from the Quickbundle node modules directory.
|
|
57
|
+
* @param paths - Relative paths.
|
|
58
|
+
* @returns The resolved absolute path.
|
|
59
|
+
* @example
|
|
60
|
+
* resolveFromInternalDirectory("dist", "node");
|
|
61
|
+
*/
|
|
62
|
+
const resolveFromInternalDirectory = (...paths) => {
|
|
63
|
+
return resolve(import.meta.dirname, "../", ...paths);
|
|
37
64
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Resolve a relative path from the current working project directory.
|
|
67
|
+
* @param paths - Relative paths.
|
|
68
|
+
* @returns The resolved absolute path.
|
|
69
|
+
* @example
|
|
70
|
+
* resolveFromExternalDirectory("package.json");
|
|
71
|
+
*/
|
|
72
|
+
const resolveFromExternalDirectory = (...paths) => {
|
|
73
|
+
return resolve(process.cwd(), ...paths);
|
|
47
74
|
};
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
75
|
+
const createRegExpMatcher = (regex) => {
|
|
76
|
+
return (value) => {
|
|
77
|
+
return regex.exec(value)?.groups;
|
|
78
|
+
};
|
|
51
79
|
};
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
force: true,
|
|
55
|
-
recursive: true
|
|
56
|
-
});
|
|
80
|
+
const createDirectory = async (path) => {
|
|
81
|
+
await mkdir(path, { recursive: true });
|
|
57
82
|
};
|
|
58
|
-
const
|
|
59
|
-
|
|
83
|
+
const copyFile$1 = async (fromPath, toPath) => {
|
|
84
|
+
await createDirectory(dirname(toPath));
|
|
85
|
+
await copyFile(fromPath, toPath);
|
|
60
86
|
};
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
87
|
+
const removePath = async (path) => {
|
|
88
|
+
await rm(path, {
|
|
89
|
+
force: true,
|
|
90
|
+
recursive: true
|
|
91
|
+
});
|
|
64
92
|
};
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
const { body, ok, status, statusText } = await fetch(url);
|
|
68
|
-
if (!ok) {
|
|
69
|
-
throw new Error(`An error ocurred while downloading \`${url}\`. Received \`${status}\` status code with the following message \`${statusText}\`.`);
|
|
70
|
-
}
|
|
71
|
-
if (!body) {
|
|
72
|
-
throw new Error(`Empty body received while downloading \`${url}\`.`);
|
|
73
|
-
}
|
|
74
|
-
await finished(Readable.fromWeb(body).pipe(createWriteStream(filePath)));
|
|
93
|
+
const readFile$1 = async (filePath) => {
|
|
94
|
+
return readFile(filePath);
|
|
75
95
|
};
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
await decompress(input.path, directoryPath, {
|
|
80
|
-
filter (file) {
|
|
81
|
-
return file.path === targetedArchivePath;
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
await rename(join(directoryPath, targetedArchivePath), join(directoryPath, output.filename));
|
|
96
|
+
const writeFile$1 = async (filePath, content) => {
|
|
97
|
+
await createDirectory(dirname(filePath));
|
|
98
|
+
await writeFile(filePath, content, "utf8");
|
|
85
99
|
};
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}).option({
|
|
93
|
-
key: "sourceMaps",
|
|
94
|
-
name: "source-maps",
|
|
95
|
-
description: "Enable source maps generation",
|
|
96
|
-
defaultValue: false
|
|
97
|
-
});
|
|
100
|
+
const download = async (url, filePath) => {
|
|
101
|
+
await createDirectory(dirname(filePath));
|
|
102
|
+
const { body, ok, status, statusText } = await fetch(url);
|
|
103
|
+
if (!ok) throw new Error(`An error ocurred while downloading \`${url}\`. Received \`${status}\` status code with the following message \`${statusText}\`.`);
|
|
104
|
+
if (!body) throw new Error(`Empty body received while downloading \`${url}\`.`);
|
|
105
|
+
await finished(Readable.fromWeb(body).pipe(createWriteStream(filePath)));
|
|
98
106
|
};
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
107
|
+
const unzip = async (input, output) => {
|
|
108
|
+
const { targetedArchivePath } = input;
|
|
109
|
+
const { directoryPath } = output;
|
|
110
|
+
await decompress(input.path, directoryPath, { filter(file) {
|
|
111
|
+
return file.path === targetedArchivePath;
|
|
112
|
+
} });
|
|
113
|
+
await rename(join(directoryPath, targetedArchivePath), join(directoryPath, output.filename));
|
|
102
114
|
};
|
|
103
|
-
const
|
|
104
|
-
|
|
115
|
+
const createCommand = (program, input) => {
|
|
116
|
+
return program.command(input).option({
|
|
117
|
+
defaultValue: false,
|
|
118
|
+
description: "Enable minification",
|
|
119
|
+
key: "minification",
|
|
120
|
+
name: "minification"
|
|
121
|
+
}).option({
|
|
122
|
+
defaultValue: false,
|
|
123
|
+
description: "Enable source maps generation",
|
|
124
|
+
key: "sourceMaps",
|
|
125
|
+
name: "source-maps"
|
|
126
|
+
});
|
|
105
127
|
};
|
|
106
128
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
onLog
|
|
112
|
-
})));
|
|
113
|
-
let startDuration;
|
|
114
|
-
console.clear();
|
|
115
|
-
watcher.on("event", async (event)=>{
|
|
116
|
-
switch(event.code){
|
|
117
|
-
case "START":
|
|
118
|
-
{
|
|
119
|
-
startDuration = Date.now();
|
|
120
|
-
clearLog("Build in progress…", {
|
|
121
|
-
type: "information"
|
|
122
|
-
});
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
case "BUNDLE_END":
|
|
126
|
-
{
|
|
127
|
-
await event.result.close();
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
case "END":
|
|
131
|
-
{
|
|
132
|
-
const duration = Date.now() - startDuration;
|
|
133
|
-
clearLog(`Build done in ${duration}ms (at ${new Date().toLocaleTimeString()})`, {
|
|
134
|
-
type: "success"
|
|
135
|
-
});
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
case "ERROR":
|
|
139
|
-
{
|
|
140
|
-
const { error } = event;
|
|
141
|
-
clearLog(error.message, {
|
|
142
|
-
type: "error"
|
|
143
|
-
});
|
|
144
|
-
console.error("\n", error);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
};
|
|
150
|
-
const clearLog = (...input)=>{
|
|
151
|
-
console.clear();
|
|
152
|
-
helpers.message(...input);
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/bundler/helpers.ts
|
|
131
|
+
const isRecord = (value) => {
|
|
132
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
153
133
|
};
|
|
154
134
|
|
|
155
|
-
|
|
156
|
-
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/bundler/config.ts
|
|
137
|
+
const PKG = createRequire(import.meta.url)(resolveFromExternalDirectory("package.json"));
|
|
157
138
|
const DEFAULT_OPTIONS = {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
139
|
+
minification: false,
|
|
140
|
+
sourceMaps: false,
|
|
141
|
+
standalone: false
|
|
161
142
|
};
|
|
162
|
-
const createConfiguration = (options = DEFAULT_OPTIONS)=>{
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}),
|
|
177
|
-
metadata: buildableExports
|
|
178
|
-
};
|
|
143
|
+
const createConfiguration = (options = DEFAULT_OPTIONS) => {
|
|
144
|
+
const buildableExports = getBuildableExports(options);
|
|
145
|
+
return {
|
|
146
|
+
data: buildableExports.flatMap((buildableExport) => {
|
|
147
|
+
return [buildableExport.source && createMainConfig({
|
|
148
|
+
...buildableExport,
|
|
149
|
+
source: buildableExport.source
|
|
150
|
+
}, options), buildableExport.source && buildableExport.types && createTypesConfig({
|
|
151
|
+
source: buildableExport.source,
|
|
152
|
+
types: buildableExport.types
|
|
153
|
+
}, options)].filter(Boolean);
|
|
154
|
+
}),
|
|
155
|
+
metadata: buildableExports
|
|
156
|
+
};
|
|
179
157
|
};
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return [
|
|
237
|
-
".",
|
|
238
|
-
singleExport
|
|
239
|
-
];
|
|
240
|
-
}
|
|
241
|
-
singleExport[field] = value;
|
|
242
|
-
}
|
|
243
|
-
return undefined;
|
|
244
|
-
}).reduce((buildableExports, currentExport)=>{
|
|
245
|
-
if (!currentExport) return buildableExports;
|
|
246
|
-
const [exportField, exportValue] = currentExport;
|
|
247
|
-
const conditionalExportFields = Object.keys(exportValue);
|
|
248
|
-
if (!conditionalExportFields.includes("source")) return buildableExports;
|
|
249
|
-
const hasAtLeastOneRequiredField = buildableExportFields.some((entryPointField)=>conditionalExportFields.includes(entryPointField));
|
|
250
|
-
if (hasAtLeastOneRequiredField) {
|
|
251
|
-
buildableExports.push(exportValue);
|
|
252
|
-
return buildableExports;
|
|
253
|
-
}
|
|
254
|
-
throw new Error(`A \`source\` field is defined without an output defined for the \`${exportField}\` export. Make sure to define at least one conditional entry point (including ${buildableExportFields.map((field)=>`\`${field}\``).join(", ")})`);
|
|
255
|
-
}, []);
|
|
256
|
-
if (output.length === 0) {
|
|
257
|
-
throw new Error("No `source` field is set for the targeted package. If a build step is necessary, make sure to configure at least one `source` field in the package `exports` contract. If not, do not execute quickbundle on this package.");
|
|
258
|
-
}
|
|
259
|
-
return output;
|
|
158
|
+
const getBuildableExports = ({ standalone }) => {
|
|
159
|
+
if (standalone) {
|
|
160
|
+
/**
|
|
161
|
+
* Entry-point resolution invariants for standalone target (mostly binaries).
|
|
162
|
+
*/
|
|
163
|
+
if (!PKG.source || !PKG.bin || !PKG.name) 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.");
|
|
164
|
+
const bin = PKG.bin;
|
|
165
|
+
const name = PKG.name;
|
|
166
|
+
const source = PKG.source;
|
|
167
|
+
if (isRecord(bin)) return Object.entries(bin).map((data) => ({
|
|
168
|
+
bin: data[0],
|
|
169
|
+
require: data[1],
|
|
170
|
+
source
|
|
171
|
+
}));
|
|
172
|
+
return [{
|
|
173
|
+
bin: name.replace(/^(@.*?\/)/, ""),
|
|
174
|
+
require: bin,
|
|
175
|
+
source
|
|
176
|
+
}];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Entry-point resolution invariants for non-standalone target (mostly libraries):
|
|
180
|
+
* Following the [package entry-point specification](https://nodejs.org/api/packages.html#package-entry-points),
|
|
181
|
+
* whenever an export object is defined, it take precedence over other classical entry-point fields
|
|
182
|
+
* (such as main, module, and types defined at the root package.json level).
|
|
183
|
+
*/
|
|
184
|
+
if (PKG.main || PKG.module || PKG.types || !PKG.exports) throw new Error("Invalid package entry points contract. Use the recommended [`exports` field](https://nodejs.org/api/packages.html#package-entry-points) instead and, for TypeScript-based projects, update the `tsconfig.json` file to resolve it properly (`moduleResolution` must be set to `Bundler` (or `NodeNext`)).");
|
|
185
|
+
const buildableExportFields = [
|
|
186
|
+
"default",
|
|
187
|
+
"import",
|
|
188
|
+
"require",
|
|
189
|
+
"types"
|
|
190
|
+
];
|
|
191
|
+
let singleExport = void 0;
|
|
192
|
+
const output = Object.entries(PKG.exports).map(([field, value]) => {
|
|
193
|
+
if (isRecord(value)) return [field, value];
|
|
194
|
+
if (["source", ...buildableExportFields].includes(field)) {
|
|
195
|
+
if (!singleExport) {
|
|
196
|
+
singleExport = { [field]: value };
|
|
197
|
+
return [".", singleExport];
|
|
198
|
+
}
|
|
199
|
+
singleExport[field] = value;
|
|
200
|
+
}
|
|
201
|
+
}).reduce((buildableExports, currentExport) => {
|
|
202
|
+
if (!currentExport) return buildableExports;
|
|
203
|
+
const [exportField, exportValue] = currentExport;
|
|
204
|
+
const conditionalExportFields = Object.keys(exportValue);
|
|
205
|
+
if (!conditionalExportFields.includes("source")) return buildableExports;
|
|
206
|
+
if (buildableExportFields.some((entryPointField) => conditionalExportFields.includes(entryPointField))) {
|
|
207
|
+
buildableExports.push(exportValue);
|
|
208
|
+
return buildableExports;
|
|
209
|
+
}
|
|
210
|
+
throw new Error(`A \`source\` field is defined without an output defined for the \`${exportField}\` export. Make sure to define at least one conditional entry point (including ${buildableExportFields.map((field) => `\`${field}\``).join(", ")})`);
|
|
211
|
+
}, []);
|
|
212
|
+
if (output.length === 0) throw new Error("No `source` field is set for the targeted package. If a build step is necessary, make sure to configure at least one `source` field in the package `exports` contract. If not, do not execute quickbundle on this package.");
|
|
213
|
+
return output;
|
|
260
214
|
};
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* As they're not installed consumer side, `devDependencies` are declared as internal dependencies (via the `false` value)
|
|
268
|
-
* and bundled into the dist if and only if imported and not listed as `peerDependencies` (otherwise, they're considered external).
|
|
269
|
-
*/ devDeps: false,
|
|
270
|
-
optDeps: true,
|
|
271
|
-
peerDeps: true
|
|
272
|
-
}),
|
|
273
|
-
commonjs(),
|
|
274
|
-
url(),
|
|
275
|
-
json(),
|
|
276
|
-
...customPlugins
|
|
277
|
-
].filter(Boolean);
|
|
215
|
+
const getFileOutput = (filePath) => {
|
|
216
|
+
return {
|
|
217
|
+
dir: dirname(filePath),
|
|
218
|
+
entryFileNames: basename(filePath)
|
|
219
|
+
};
|
|
278
220
|
};
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
file: esmInput,
|
|
294
|
-
format: "es",
|
|
295
|
-
sourcemap: sourceMaps
|
|
296
|
-
}
|
|
297
|
-
].filter(Boolean);
|
|
298
|
-
return {
|
|
299
|
-
input: entryPoints.source,
|
|
300
|
-
output,
|
|
301
|
-
plugins: getPlugins([
|
|
302
|
-
nodeResolve(),
|
|
303
|
-
swc({
|
|
304
|
-
minify: minification,
|
|
305
|
-
sourceMaps
|
|
306
|
-
})
|
|
307
|
-
], options)
|
|
308
|
-
};
|
|
221
|
+
const getPlugins = (options) => {
|
|
222
|
+
const output = [url()];
|
|
223
|
+
if (!options.standalone) output.push(externals({
|
|
224
|
+
builtins: true,
|
|
225
|
+
deps: true,
|
|
226
|
+
/**
|
|
227
|
+
* As they're not installed consumer side, `devDependencies` are declared as internal dependencies (via the `false` value)
|
|
228
|
+
* and bundled into the dist if and only if imported and not listed as `peerDependencies` (otherwise, they're considered external).
|
|
229
|
+
*/
|
|
230
|
+
devDeps: false,
|
|
231
|
+
optDeps: true,
|
|
232
|
+
peerDeps: true
|
|
233
|
+
}));
|
|
234
|
+
return output;
|
|
309
235
|
};
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
},
|
|
335
|
-
respectExternal: true
|
|
336
|
-
})
|
|
337
|
-
], options)
|
|
338
|
-
};
|
|
236
|
+
const createMainConfig = (entryPoints, options) => {
|
|
237
|
+
const { minification, sourceMaps } = options;
|
|
238
|
+
const cjsInput = entryPoints.require;
|
|
239
|
+
const esmInput = entryPoints.import ?? entryPoints.default;
|
|
240
|
+
if (entryPoints.import && entryPoints.default && entryPoints.import !== entryPoints.default) throw new Error("Both `import` and `default` export fields have been defined but with different values. To preserve proper `default` field resolution on the consumer side (i.e. to target ESM format), make sure to provide the same file path for both fields.");
|
|
241
|
+
const commonOutputConfig = {
|
|
242
|
+
minify: minification,
|
|
243
|
+
sourcemap: sourceMaps
|
|
244
|
+
};
|
|
245
|
+
const output = [cjsInput && {
|
|
246
|
+
...commonOutputConfig,
|
|
247
|
+
...getFileOutput(cjsInput),
|
|
248
|
+
codeSplitting: Boolean(options.standalone),
|
|
249
|
+
format: "cjs"
|
|
250
|
+
}, esmInput && {
|
|
251
|
+
...commonOutputConfig,
|
|
252
|
+
...getFileOutput(esmInput),
|
|
253
|
+
format: "es"
|
|
254
|
+
}].filter(Boolean);
|
|
255
|
+
return {
|
|
256
|
+
input: entryPoints.source,
|
|
257
|
+
output,
|
|
258
|
+
plugins: getPlugins(options)
|
|
259
|
+
};
|
|
339
260
|
};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
handler (context) {
|
|
347
|
-
watch(createConfiguration({
|
|
348
|
-
minification: context.minification,
|
|
349
|
-
sourceMaps: context.sourceMaps,
|
|
350
|
-
standalone: false
|
|
351
|
-
}));
|
|
352
|
-
}
|
|
353
|
-
});
|
|
261
|
+
const createTypesConfig = (entryPoints, options) => {
|
|
262
|
+
return {
|
|
263
|
+
input: entryPoints.source,
|
|
264
|
+
output: [getFileOutput(entryPoints.types)],
|
|
265
|
+
plugins: [...getPlugins(options), dts()]
|
|
266
|
+
};
|
|
354
267
|
};
|
|
355
268
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
269
|
+
//#endregion
|
|
270
|
+
//#region src/commands/build.ts
|
|
271
|
+
const createBuildCommand = (program) => {
|
|
272
|
+
return createCommand(program, {
|
|
273
|
+
description: "Build the source code (production mode)",
|
|
274
|
+
name: "build"
|
|
275
|
+
}).task({
|
|
276
|
+
async handler(context) {
|
|
277
|
+
return build(createConfiguration({
|
|
278
|
+
minification: context.minification,
|
|
279
|
+
sourceMaps: context.sourceMaps,
|
|
280
|
+
standalone: false
|
|
281
|
+
}));
|
|
282
|
+
},
|
|
283
|
+
key: "buildOutput",
|
|
284
|
+
label: "Bundle assets 📦"
|
|
285
|
+
}).task({
|
|
286
|
+
async handler(context) {
|
|
287
|
+
return computeBundleSize(context.buildOutput);
|
|
288
|
+
},
|
|
289
|
+
key: "logInput",
|
|
290
|
+
label: "Generate report 📝",
|
|
291
|
+
skip(context) {
|
|
292
|
+
return context.buildOutput.length === 0;
|
|
293
|
+
}
|
|
294
|
+
}).task({
|
|
295
|
+
handler(context) {
|
|
296
|
+
context.logInput.forEach((item) => {
|
|
297
|
+
helpers.message([`${formatSize(item.rawSize)} raw`, `${formatSize(item.compressedSize)} gzip`].map((message, index) => {
|
|
298
|
+
return index === 0 ? message : ` ${message}`;
|
|
299
|
+
}).join("\n"), {
|
|
300
|
+
label: `${item.filePath} (took ${item.elapsedTime}ms)`,
|
|
301
|
+
lineBreak: {
|
|
302
|
+
end: false,
|
|
303
|
+
start: true
|
|
304
|
+
},
|
|
305
|
+
type: "information"
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
},
|
|
309
|
+
skip(context) {
|
|
310
|
+
return context.buildOutput.length === 0;
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
};
|
|
314
|
+
const computeBundleSize = async (buildOutput) => {
|
|
315
|
+
const computeFileSize = async (buildItemOutput) => {
|
|
316
|
+
const content = await readFile$1(buildItemOutput.filePath);
|
|
317
|
+
const gzSize = await gzipSize(content);
|
|
318
|
+
return {
|
|
319
|
+
...buildItemOutput,
|
|
320
|
+
compressedSize: gzSize,
|
|
321
|
+
rawSize: content.byteLength
|
|
322
|
+
};
|
|
323
|
+
};
|
|
324
|
+
return Promise.all(buildOutput.map(async (item) => computeFileSize(item)));
|
|
325
|
+
};
|
|
326
|
+
const formatSize = (bytes) => {
|
|
327
|
+
const kiloBytes = bytes / 1e3;
|
|
328
|
+
return kiloBytes < 1 ? `${bytes} B` : `${kiloBytes.toFixed(2)} kB`;
|
|
391
329
|
};
|
|
392
330
|
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region src/commands/compile.ts
|
|
393
333
|
const TEMPORARY_PATH = resolveFromInternalDirectory("dist", "tmp");
|
|
394
334
|
const TEMPORARY_DOWNLOAD_PATH = join(TEMPORARY_PATH, "zip");
|
|
395
335
|
const TEMPORARY_RUNTIME_PATH = join(TEMPORARY_PATH, "runtime");
|
|
396
|
-
const createCompileCommand = (program)=>{
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}));
|
|
466
|
-
}
|
|
467
|
-
});
|
|
336
|
+
const createCompileCommand = (program) => {
|
|
337
|
+
return program.command({
|
|
338
|
+
description: "Compiles the source code into a self-contained executable",
|
|
339
|
+
name: "compile"
|
|
340
|
+
}).option({
|
|
341
|
+
defaultValue: "local",
|
|
342
|
+
description: "Set a different cross-compilation target",
|
|
343
|
+
key: "targetInput",
|
|
344
|
+
name: {
|
|
345
|
+
long: "target",
|
|
346
|
+
short: "t"
|
|
347
|
+
}
|
|
348
|
+
}).task({
|
|
349
|
+
handler() {
|
|
350
|
+
return createConfiguration({
|
|
351
|
+
minification: true,
|
|
352
|
+
sourceMaps: false,
|
|
353
|
+
standalone: true
|
|
354
|
+
});
|
|
355
|
+
},
|
|
356
|
+
key: "config",
|
|
357
|
+
label: "Create configuration"
|
|
358
|
+
}).task({
|
|
359
|
+
async handler({ targetInput }) {
|
|
360
|
+
if (targetInput === "local") {
|
|
361
|
+
await copyFile$1(process.execPath, TEMPORARY_RUNTIME_PATH);
|
|
362
|
+
return getOsType(os.type());
|
|
363
|
+
}
|
|
364
|
+
const matchedRuntimeParts = matchRuntimeParts(targetInput);
|
|
365
|
+
if (!matchedRuntimeParts) throw new Error("Invalid `runtime` flag input. The accepted targets are the one listed in https://nodejs.org/download/release/ with the following format `node-vx.y.z-(darwin|linux|win)-(arm64|x64|x86)`.");
|
|
366
|
+
const osType = getOsType(matchedRuntimeParts.os);
|
|
367
|
+
const extension = osType === "windows" ? "zip" : "tar.gz";
|
|
368
|
+
await download(`https://nodejs.org/download/release/${matchedRuntimeParts.version}/${targetInput}.${extension}`, TEMPORARY_DOWNLOAD_PATH);
|
|
369
|
+
await unzip({
|
|
370
|
+
path: TEMPORARY_DOWNLOAD_PATH,
|
|
371
|
+
targetedArchivePath: osType === "windows" ? join(targetInput, "node.exe") : join(targetInput, "bin", "node")
|
|
372
|
+
}, {
|
|
373
|
+
directoryPath: dirname(TEMPORARY_RUNTIME_PATH),
|
|
374
|
+
filename: basename(TEMPORARY_RUNTIME_PATH)
|
|
375
|
+
});
|
|
376
|
+
return osType;
|
|
377
|
+
},
|
|
378
|
+
key: "osType",
|
|
379
|
+
label({ targetInput }) {
|
|
380
|
+
return `Get \`${targetInput}\` runtime`;
|
|
381
|
+
}
|
|
382
|
+
}).task({
|
|
383
|
+
async handler({ config }) {
|
|
384
|
+
await build(config);
|
|
385
|
+
},
|
|
386
|
+
label: "Build"
|
|
387
|
+
}).task({
|
|
388
|
+
async handler({ config, osType }) {
|
|
389
|
+
await Promise.all(config.metadata.map(async ({ bin, require }) => {
|
|
390
|
+
if (!require || !bin) return;
|
|
391
|
+
return compile({
|
|
392
|
+
bin,
|
|
393
|
+
input: require,
|
|
394
|
+
osType
|
|
395
|
+
});
|
|
396
|
+
}));
|
|
397
|
+
},
|
|
398
|
+
label({ config }) {
|
|
399
|
+
return `Compile ${config.metadata.map(({ bin }) => {
|
|
400
|
+
if (!bin) return void 0;
|
|
401
|
+
return `\`${bin}\``;
|
|
402
|
+
}).filter(Boolean).join(", ")}`;
|
|
403
|
+
}
|
|
404
|
+
});
|
|
468
405
|
};
|
|
469
|
-
const getOsType = (input)=>{
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
return "macos";
|
|
480
|
-
}
|
|
481
|
-
case "Linux":
|
|
482
|
-
case "linux":
|
|
483
|
-
{
|
|
484
|
-
return "linux";
|
|
485
|
-
}
|
|
486
|
-
default:
|
|
487
|
-
{
|
|
488
|
-
throw new Error(`Unsupported operating system \`${input}\``);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
406
|
+
const getOsType = (input) => {
|
|
407
|
+
switch (input) {
|
|
408
|
+
case "Darwin":
|
|
409
|
+
case "darwin": return "macos";
|
|
410
|
+
case "Linux":
|
|
411
|
+
case "linux": return "linux";
|
|
412
|
+
case "win":
|
|
413
|
+
case "Windows_NT": return "windows";
|
|
414
|
+
default: throw new Error(`Unsupported operating system \`${input}\``);
|
|
415
|
+
}
|
|
491
416
|
};
|
|
492
417
|
const matchRuntimeParts = createRegExpMatcher(/^node-(?<version>v\d+\.\d+\.\d+)-(?<os>darwin|linux|win)-(?<architecture>arm64|x64|x86)$/);
|
|
493
|
-
const compile = async ({ bin, input, osType })=>{
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
await helpers.exec(`codesign --sign - ${executableFileName}`);
|
|
519
|
-
}
|
|
520
|
-
await Promise.all([
|
|
521
|
-
blobFileName,
|
|
522
|
-
seaConfigFileName,
|
|
523
|
-
TEMPORARY_PATH
|
|
524
|
-
].map(async (path)=>removePath(path)));
|
|
418
|
+
const compile = async ({ bin, input, osType }) => {
|
|
419
|
+
const inputFileName = basename(input);
|
|
420
|
+
const inputDirectory = dirname(input);
|
|
421
|
+
const resolveFromInputDirectory = (...paths) => {
|
|
422
|
+
return resolve(inputDirectory, ...paths);
|
|
423
|
+
};
|
|
424
|
+
const blobFileName = resolveFromInputDirectory(`${inputFileName}.blob`);
|
|
425
|
+
const executableFileName = resolveFromInputDirectory(`${bin}${osType === "windows" ? ".exe" : ""}`);
|
|
426
|
+
const seaConfigFileName = resolveFromInputDirectory(`${inputFileName}.sea-config.json`);
|
|
427
|
+
await writeFile$1(seaConfigFileName, JSON.stringify({
|
|
428
|
+
disableExperimentalSEAWarning: true,
|
|
429
|
+
main: input,
|
|
430
|
+
output: blobFileName,
|
|
431
|
+
useCodeCache: false,
|
|
432
|
+
useSnapshot: false
|
|
433
|
+
}));
|
|
434
|
+
await Promise.all([helpers.exec(`node --experimental-sea-config ${seaConfigFileName}`), copyFile$1(TEMPORARY_RUNTIME_PATH, executableFileName)]);
|
|
435
|
+
if (osType === "macos") await helpers.exec(`codesign --remove-signature ${executableFileName}`);
|
|
436
|
+
await helpers.exec(`npx postject ${executableFileName} NODE_SEA_BLOB ${blobFileName} --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 ${osType === "macos" ? "--macho-segment-name NODE_SEA" : ""}`);
|
|
437
|
+
if (osType === "macos") await helpers.exec(`codesign --sign - ${executableFileName}`);
|
|
438
|
+
await Promise.all([
|
|
439
|
+
blobFileName,
|
|
440
|
+
seaConfigFileName,
|
|
441
|
+
TEMPORARY_PATH
|
|
442
|
+
].map(async (path) => removePath(path)));
|
|
525
443
|
};
|
|
526
444
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
`${formatSize(item.compressedSize)} gzip`
|
|
556
|
-
].map((message, index)=>{
|
|
557
|
-
return index === 0 ? message : ` ${message}`;
|
|
558
|
-
}).join("\n"), {
|
|
559
|
-
label: `${item.filePath} (took ${item.elapsedTime}ms)`,
|
|
560
|
-
lineBreak: {
|
|
561
|
-
end: false,
|
|
562
|
-
start: true
|
|
563
|
-
},
|
|
564
|
-
type: "information"
|
|
565
|
-
});
|
|
566
|
-
});
|
|
567
|
-
},
|
|
568
|
-
skip (context) {
|
|
569
|
-
return context.buildOutput.length === 0;
|
|
570
|
-
}
|
|
571
|
-
});
|
|
572
|
-
};
|
|
573
|
-
const computeBundleSize = async (buildOutput)=>{
|
|
574
|
-
const computeFileSize = async (buildItemOutput)=>{
|
|
575
|
-
const content = await readFile(buildItemOutput.filePath);
|
|
576
|
-
const gzSize = await gzipSize(content);
|
|
577
|
-
return {
|
|
578
|
-
...buildItemOutput,
|
|
579
|
-
compressedSize: gzSize,
|
|
580
|
-
rawSize: content.byteLength
|
|
581
|
-
};
|
|
582
|
-
};
|
|
583
|
-
return Promise.all(buildOutput.map(async (item)=>computeFileSize(item)));
|
|
445
|
+
//#endregion
|
|
446
|
+
//#region src/bundler/watch.ts
|
|
447
|
+
const watch$1 = (input) => {
|
|
448
|
+
process.env.NODE_ENV ??= "development";
|
|
449
|
+
const watcher = watch(input.data);
|
|
450
|
+
let startDuration;
|
|
451
|
+
console.clear();
|
|
452
|
+
watcher.on("event", async (event) => {
|
|
453
|
+
switch (event.code) {
|
|
454
|
+
case "BUNDLE_END":
|
|
455
|
+
await event.result.close();
|
|
456
|
+
break;
|
|
457
|
+
case "END":
|
|
458
|
+
clearLog(`Build done in ${Date.now() - startDuration}ms (at ${(/* @__PURE__ */ new Date()).toLocaleTimeString()})`, { type: "success" });
|
|
459
|
+
return;
|
|
460
|
+
case "ERROR": {
|
|
461
|
+
const { error } = event;
|
|
462
|
+
clearLog(error.message, { type: "error" });
|
|
463
|
+
console.error("\n", error);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
case "START":
|
|
467
|
+
startDuration = Date.now();
|
|
468
|
+
clearLog("Build in progress…", { type: "information" });
|
|
469
|
+
return;
|
|
470
|
+
default: break;
|
|
471
|
+
}
|
|
472
|
+
});
|
|
584
473
|
};
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
474
|
+
const clearLog = (...input) => {
|
|
475
|
+
console.clear();
|
|
476
|
+
helpers.message(...input);
|
|
588
477
|
};
|
|
589
478
|
|
|
590
|
-
|
|
591
|
-
|
|
479
|
+
//#endregion
|
|
480
|
+
//#region src/commands/watch.ts
|
|
481
|
+
const createWatchCommand = (program) => {
|
|
482
|
+
return createCommand(program, {
|
|
483
|
+
description: "Watch and rebuild on any code change (development mode)",
|
|
484
|
+
name: "watch"
|
|
485
|
+
}).task({ handler(context) {
|
|
486
|
+
watch$1(createConfiguration({
|
|
487
|
+
minification: context.minification,
|
|
488
|
+
sourceMaps: context.sourceMaps,
|
|
489
|
+
standalone: false
|
|
490
|
+
}));
|
|
491
|
+
} });
|
|
492
|
+
};
|
|
592
493
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
494
|
+
//#endregion
|
|
495
|
+
//#region src/index.ts
|
|
496
|
+
const createProgram = (...commandBuilders) => {
|
|
497
|
+
const program = termost({
|
|
498
|
+
description: "The zero-configuration transpiler and bundler for the web",
|
|
499
|
+
name,
|
|
500
|
+
version
|
|
501
|
+
});
|
|
502
|
+
for (const commandBuilder of commandBuilders) commandBuilder(program);
|
|
602
503
|
};
|
|
603
504
|
createProgram(createBuildCommand, createWatchCommand, createCompileCommand);
|
|
505
|
+
|
|
506
|
+
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quickbundle",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0-next-dfc95be",
|
|
4
4
|
"description": "The zero-configuration transpiler and bundler for the web",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"library",
|
|
@@ -40,25 +40,20 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@rollup/plugin-commonjs": "^28.0.8",
|
|
44
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
45
|
-
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
46
43
|
"@rollup/plugin-url": "^8.0.2",
|
|
47
|
-
"@swc/core": "^1.13.5",
|
|
48
44
|
"decompress": "^4.2.1",
|
|
49
45
|
"gzip-size": "^7.0.0",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"rollup-plugin-node-externals": "^
|
|
53
|
-
"
|
|
54
|
-
"termost": "^1.8.0"
|
|
46
|
+
"rolldown": "^1.0.1",
|
|
47
|
+
"rolldown-plugin-dts": "^0.25.1",
|
|
48
|
+
"rollup-plugin-node-externals": "^9.0.1",
|
|
49
|
+
"termost": "^1.9.0"
|
|
55
50
|
},
|
|
56
51
|
"devDependencies": {
|
|
57
52
|
"@types/decompress": "4.2.7",
|
|
58
|
-
"@types/node": "
|
|
53
|
+
"@types/node": "24.12.4"
|
|
59
54
|
},
|
|
60
55
|
"peerDependencies": {
|
|
61
|
-
"typescript": "^4.7.0 || ^5.0.0"
|
|
56
|
+
"typescript": "^4.7.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
62
57
|
},
|
|
63
58
|
"peerDependenciesMeta": {
|
|
64
59
|
"typescript": {
|
|
@@ -66,8 +61,8 @@
|
|
|
66
61
|
}
|
|
67
62
|
},
|
|
68
63
|
"scripts": {
|
|
69
|
-
"build": "
|
|
64
|
+
"build": "rolldown --config ./bundler.config.ts",
|
|
70
65
|
"test": "exit 0",
|
|
71
|
-
"watch": "
|
|
66
|
+
"watch": "rolldown --watch --config ./bundler.config.ts"
|
|
72
67
|
}
|
|
73
68
|
}
|