susee 2.0.4 → 2.1.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/README.md +160 -428
- package/dist/cli/index.d.mts +2 -0
- package/dist/cli/index.mjs +989 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/index.cjs +689 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +92 -0
- package/package.json +2 -4
- package/bin/susee +0 -3
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import readline from 'node:readline/promises';
|
|
5
|
+
import tcolor from '@suseejs/color';
|
|
6
|
+
import ts6 from '@suseejs/ts6';
|
|
7
|
+
import { LogTimer, logError, logInfo, suseeBundler } from '@suseejs/susee_bundler';
|
|
8
|
+
import { minify } from 'oxc-minify';
|
|
9
|
+
//src/cli/init.ts
|
|
10
|
+
const tsFileText = `
|
|
11
|
+
import type { SuSeeConfig } from "susee";
|
|
12
|
+
const config: SuSeeConfig = {
|
|
13
|
+
// Array of entry point objects.
|
|
14
|
+
// ----------------------------
|
|
15
|
+
entryPoints: [
|
|
16
|
+
// You can add more entry points for different export paths.
|
|
17
|
+
// NOTE: duplicate export paths are not allowed.
|
|
18
|
+
// --------------------------------------------
|
|
19
|
+
{
|
|
20
|
+
// (required) Entry file path.
|
|
21
|
+
entry: "src/index.ts", // replace with your entry file
|
|
22
|
+
// (required) Export path for this entry.
|
|
23
|
+
exportPath: ".", // "." stands for the main export path and can be set to "./foo", "./bar", etc.
|
|
24
|
+
// (optional) Output module formats ["commonjs"] or ["esm", "commonjs"], default: ["esm"].
|
|
25
|
+
// Uncomment the following line to edit.
|
|
26
|
+
//format: ["esm"],
|
|
27
|
+
// (optional) Custom tsconfig.json path, default: undefined.
|
|
28
|
+
// Uncomment the following line to edit.
|
|
29
|
+
//tsconfigFilePath: undefined,
|
|
30
|
+
// (optional)Lint checks to run on the bundled output.
|
|
31
|
+
// Uncomment the following line to edit.
|
|
32
|
+
//checks:{ checkAnonymous: false, checkDefaultExports: false, checkNpmInstalled: false }.
|
|
33
|
+
// (optional) Minify the bundled output.
|
|
34
|
+
// Pass true for default minification, or an object with custom MinifyOptions.
|
|
35
|
+
// Uncomment the following line to edit.
|
|
36
|
+
//minify: false,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
// NOTE: the following options apply to all entry points.
|
|
40
|
+
// ----------------------------------------------------------
|
|
41
|
+
// (optional) Output directory, default: dist.
|
|
42
|
+
// Uncomment the following line to edit.
|
|
43
|
+
//outDir: "dist",
|
|
44
|
+
// (optional) Allow susee to update your package.json, default: false.
|
|
45
|
+
// Uncomment the following line to edit.
|
|
46
|
+
//allowUpdatePackageJson: false,
|
|
47
|
+
};
|
|
48
|
+
export default config;
|
|
49
|
+
`.trim();
|
|
50
|
+
const jsFileText = `
|
|
51
|
+
/**
|
|
52
|
+
* @type {import("susee").SuSeeConfig}
|
|
53
|
+
*/
|
|
54
|
+
const config = {
|
|
55
|
+
// Array of entry point objects.
|
|
56
|
+
// ----------------------------
|
|
57
|
+
entryPoints: [
|
|
58
|
+
// You can add more entry points for different export paths.
|
|
59
|
+
// NOTE: duplicate export paths are not allowed.
|
|
60
|
+
// --------------------------------------------
|
|
61
|
+
{
|
|
62
|
+
// (required) Entry file path.
|
|
63
|
+
entry: "src/index.ts", // replace with your entry file
|
|
64
|
+
// (required) Export path for this entry.
|
|
65
|
+
exportPath: ".", // "." stands for the main export path and can be set to "./foo", "./bar", etc.
|
|
66
|
+
// (optional) Output module formats ["commonjs"] or ["esm", "commonjs"], default: ["esm"].
|
|
67
|
+
// Uncomment the following line to edit.
|
|
68
|
+
//format: ["esm"],
|
|
69
|
+
// (optional) Custom tsconfig.json path, default: undefined.
|
|
70
|
+
// Uncomment the following line to edit.
|
|
71
|
+
//tsconfigFilePath: undefined,
|
|
72
|
+
// (optional)Lint checks to run on the bundled output.
|
|
73
|
+
// Uncomment the following line to edit.
|
|
74
|
+
//checks:{ checkAnonymous: false, checkDefaultExports: false, checkNpmInstalled: false }.
|
|
75
|
+
// (optional) Minify the bundled output.
|
|
76
|
+
// Pass true for default minification, or an object with custom MinifyOptions.
|
|
77
|
+
// Uncomment the following line to edit.
|
|
78
|
+
//minify: false,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
// NOTE: the following options apply to all entry points.
|
|
82
|
+
// ----------------------------------------------------------
|
|
83
|
+
// (optional) Output directory, default: dist.
|
|
84
|
+
// Uncomment the following line to edit.
|
|
85
|
+
//outDir: "dist",
|
|
86
|
+
// (optional) Allow susee to update your package.json, default: false.
|
|
87
|
+
// Uncomment the following line to edit.
|
|
88
|
+
//allowUpdatePackageJson: false,
|
|
89
|
+
};
|
|
90
|
+
export default config;
|
|
91
|
+
`.trim();
|
|
92
|
+
async function getPackageType() {
|
|
93
|
+
const pkgPath = path.resolve(process.cwd(), 'package.json');
|
|
94
|
+
const _pkg = await fs.promises.readFile(pkgPath, 'utf8');
|
|
95
|
+
const pkg = JSON.parse(_pkg);
|
|
96
|
+
return pkg.type === 'module' ? 'esm' : 'commonjs';
|
|
97
|
+
}
|
|
98
|
+
async function cliInit() {
|
|
99
|
+
const rl = readline.createInterface({
|
|
100
|
+
input: process.stdin,
|
|
101
|
+
output: process.stdout
|
|
102
|
+
});
|
|
103
|
+
const is_ts = await rl.question('Is TypeScript Project(y/n) : ');
|
|
104
|
+
const isTs = !!(is_ts === 'y' || is_ts === 'Y' || is_ts === '');
|
|
105
|
+
rl.close();
|
|
106
|
+
let configFile = '';
|
|
107
|
+
let str = '';
|
|
108
|
+
if (isTs) {
|
|
109
|
+
configFile = 'susee.config.ts';
|
|
110
|
+
str = tsFileText;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
str = jsFileText;
|
|
114
|
+
const pkgType = await getPackageType();
|
|
115
|
+
switch (pkgType) {
|
|
116
|
+
case 'commonjs':
|
|
117
|
+
configFile = 'susee.config.mjs';
|
|
118
|
+
break;
|
|
119
|
+
case 'esm':
|
|
120
|
+
configFile = 'susee.config.js';
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const configFilePath = path.resolve(process.cwd(), configFile);
|
|
125
|
+
if (fs.existsSync(configFilePath))
|
|
126
|
+
await fs.promises.unlink(configFilePath);
|
|
127
|
+
await fs.promises.writeFile(configFilePath, str);
|
|
128
|
+
logInfo(`Done! Susee config file ${configFile} is created at project root.`);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Finds the path of the susee.config file if it exists.
|
|
132
|
+
* It checks for the existence of "susee.config.ts", "susee.config.js", and "susee.config.mjs" in the current working directory.
|
|
133
|
+
* The first file found is returned.
|
|
134
|
+
* @returns {string | undefined} - path to the susee.config file or undefined if it does not exist.
|
|
135
|
+
*/
|
|
136
|
+
const getSuseeConfigPath = () => {
|
|
137
|
+
const fileNames = [
|
|
138
|
+
'susee.config.ts',
|
|
139
|
+
'susee.config.js',
|
|
140
|
+
'susee.config.mjs'
|
|
141
|
+
];
|
|
142
|
+
let configFile;
|
|
143
|
+
for (const file of fileNames) {
|
|
144
|
+
const filePath = path.resolve(process.cwd(), file);
|
|
145
|
+
if (fs.existsSync(filePath)) {
|
|
146
|
+
configFile = filePath;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return configFile;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Checks if the given entries have at least one entry and if there are any duplicate export paths.
|
|
154
|
+
* If there are no entries, it will exit with code 1 and print an error message.
|
|
155
|
+
* If there are any duplicate export paths, it will exit with code 1 and print an error message.
|
|
156
|
+
* It will also check if each entry file exists, if not, it will exit with code 1 and print an error message.
|
|
157
|
+
* @param {EntryPoint[]} entries - array of entry points
|
|
158
|
+
*/
|
|
159
|
+
function checkEntries(entries) {
|
|
160
|
+
if (entries.length < 1) {
|
|
161
|
+
const info = 'At least one entry required';
|
|
162
|
+
const cause = 'No entry found in susee.config file or build options';
|
|
163
|
+
logError(info, cause, true);
|
|
164
|
+
}
|
|
165
|
+
const objectStore = {};
|
|
166
|
+
const duplicateExportPaths = [];
|
|
167
|
+
for (const obj of entries) {
|
|
168
|
+
const value = obj.exportPath;
|
|
169
|
+
if (objectStore[value]) {
|
|
170
|
+
duplicateExportPaths.push(`"${value}"`);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
objectStore[value] = true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (duplicateExportPaths.length > 0) {
|
|
177
|
+
const info = 'Found duplicated export paths/path';
|
|
178
|
+
const cause = `Duplicate export paths/path (${duplicateExportPaths.join(',')}) found in your susee.config file or build options , that will error for bundled output`;
|
|
179
|
+
logError(info, cause, true);
|
|
180
|
+
}
|
|
181
|
+
for (const obj of entries) {
|
|
182
|
+
if (!fs.existsSync(path.resolve(process.cwd(), obj.entry))) {
|
|
183
|
+
const info = 'Entry file error';
|
|
184
|
+
const cause = `Entry file ${obj.entry} dose not exists.`;
|
|
185
|
+
logError(info, cause, true);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Generates normalized build options from the user config.
|
|
191
|
+
* It validates entry points, applies default values, removes duplicate formats,
|
|
192
|
+
* resolves the output directory for each export path, and keeps duplicate declaration handling fail-fast.
|
|
193
|
+
* @param {SuSeeConfig} config - raw susee configuration object.
|
|
194
|
+
* @returns {BuildOptions} normalized build options for the compiler.
|
|
195
|
+
*/
|
|
196
|
+
function generateBuildOptions(config) {
|
|
197
|
+
const outDir = config.outDir ?? 'dist';
|
|
198
|
+
const points = [];
|
|
199
|
+
checkEntries(config.entryPoints);
|
|
200
|
+
for (const ent of config.entryPoints) {
|
|
201
|
+
const entry = ent.entry;
|
|
202
|
+
const exportPath = ent.exportPath;
|
|
203
|
+
const format = ent.format ? [...new Set(ent.format)] : ['esm'];
|
|
204
|
+
const tsconfigFilePath = ent.tsconfigFilePath ?? undefined;
|
|
205
|
+
const outputDirectoryPath = ent.exportPath === '.' ? outDir : `${outDir}${ent.exportPath.slice(1)}`;
|
|
206
|
+
const checks = {
|
|
207
|
+
checkAnonymous: ent.checks?.checkAnonymous ?? false,
|
|
208
|
+
checkDefaultExports: ent.checks?.checkDefaultExports ?? false,
|
|
209
|
+
checkNpmInstalled: ent.checks?.checkNpmInstalled ?? false
|
|
210
|
+
};
|
|
211
|
+
const minify = ent.minify ?? false;
|
|
212
|
+
points.push({
|
|
213
|
+
entry,
|
|
214
|
+
exportPath,
|
|
215
|
+
format,
|
|
216
|
+
outputDirectoryPath,
|
|
217
|
+
tsconfigFilePath,
|
|
218
|
+
checks,
|
|
219
|
+
minify
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
buildEntryPoints: points,
|
|
224
|
+
updatePackage: config.allowUpdatePackageJson ?? false,
|
|
225
|
+
outDir
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Loads the susee config file from the current working directory and converts it into build options.
|
|
230
|
+
* If no supported config file is found, it returns `undefined`.
|
|
231
|
+
* @returns {Promise<BuildOptions | undefined>} normalized build options or undefined when no config file exists.
|
|
232
|
+
*/
|
|
233
|
+
async function finalSuseeConfig() {
|
|
234
|
+
const configPath = getSuseeConfigPath();
|
|
235
|
+
if (configPath) {
|
|
236
|
+
const _default = await import(configPath);
|
|
237
|
+
const config = _default.default;
|
|
238
|
+
return generateBuildOptions(config);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function fail(message) {
|
|
242
|
+
const info = message;
|
|
243
|
+
const cause = '';
|
|
244
|
+
logError(info, cause, true);
|
|
245
|
+
}
|
|
246
|
+
function isFile(entry) {
|
|
247
|
+
const exts = [
|
|
248
|
+
'.js',
|
|
249
|
+
'.ts',
|
|
250
|
+
'.mts',
|
|
251
|
+
'.mjs',
|
|
252
|
+
'.cjs',
|
|
253
|
+
'.cts',
|
|
254
|
+
'.tsx',
|
|
255
|
+
'.jsx'
|
|
256
|
+
];
|
|
257
|
+
return exts.includes(path.extname(entry));
|
|
258
|
+
}
|
|
259
|
+
function isEmptyObject(entry) {
|
|
260
|
+
return typeof entry === 'object' && !Array.isArray(entry) && Object.keys(entry).length === 0;
|
|
261
|
+
}
|
|
262
|
+
function parseBooleanFlag(flag, value) {
|
|
263
|
+
if (value === 'true')
|
|
264
|
+
return true;
|
|
265
|
+
if (value === 'false')
|
|
266
|
+
return false;
|
|
267
|
+
fail(`Type of ${flag} must be boolean.`);
|
|
268
|
+
}
|
|
269
|
+
function parseArgs(argv) {
|
|
270
|
+
const opts = {};
|
|
271
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
272
|
+
const argument = argv[index];
|
|
273
|
+
if (index === 0 && !argument.startsWith('--') && isFile(argument)) {
|
|
274
|
+
opts.entry = argument;
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const [flag, inlineValue] = argument.split('=', 2);
|
|
278
|
+
const nextValue = argv[index + 1];
|
|
279
|
+
const value = inlineValue ?? nextValue;
|
|
280
|
+
switch (flag) {
|
|
281
|
+
case '--entry':
|
|
282
|
+
if (!value || value.startsWith('--'))
|
|
283
|
+
fail('Entry point required.');
|
|
284
|
+
if (opts.entry && isFile(opts.entry))
|
|
285
|
+
fail('Entry point already exists.');
|
|
286
|
+
opts.entry = value;
|
|
287
|
+
if (inlineValue === undefined) {
|
|
288
|
+
index += 1;
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
case '--outdir':
|
|
292
|
+
if (!value || value.startsWith('--'))
|
|
293
|
+
fail('Output directory required.');
|
|
294
|
+
opts.outDir = value;
|
|
295
|
+
if (inlineValue === undefined) {
|
|
296
|
+
index += 1;
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
case '--format':
|
|
300
|
+
if (value !== 'cjs' && value !== 'commonjs' && value !== 'esm') {
|
|
301
|
+
fail('Format must be cjs, commonjs, esm, both.');
|
|
302
|
+
}
|
|
303
|
+
opts.format = value === 'cjs' || value === 'commonjs' ? ['commonjs'] : value === 'esm' ? ['esm'] : value === 'both' ? ['commonjs', 'esm'] : undefined;
|
|
304
|
+
if (inlineValue === undefined) {
|
|
305
|
+
index += 1;
|
|
306
|
+
}
|
|
307
|
+
break;
|
|
308
|
+
case '--tsconfig':
|
|
309
|
+
if (!value || value.startsWith('--'))
|
|
310
|
+
fail('Tsconfig path required.');
|
|
311
|
+
opts.tsconfig = value;
|
|
312
|
+
if (inlineValue === undefined) {
|
|
313
|
+
index += 1;
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
case '--allow-update':
|
|
317
|
+
if (inlineValue !== undefined) {
|
|
318
|
+
opts.allowUpdate = parseBooleanFlag('allow update', inlineValue);
|
|
319
|
+
}
|
|
320
|
+
else if (nextValue === 'true' || nextValue === 'false') {
|
|
321
|
+
opts.allowUpdate = parseBooleanFlag('allow update', nextValue);
|
|
322
|
+
index += 1;
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
opts.allowUpdate = true;
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
case '--check':
|
|
329
|
+
if (inlineValue !== undefined) {
|
|
330
|
+
opts.check = parseBooleanFlag('check', inlineValue);
|
|
331
|
+
}
|
|
332
|
+
else if (nextValue === 'true' || nextValue === 'false') {
|
|
333
|
+
opts.check = parseBooleanFlag('check', nextValue);
|
|
334
|
+
index += 1;
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
opts.check = true;
|
|
338
|
+
}
|
|
339
|
+
break;
|
|
340
|
+
case '--minify':
|
|
341
|
+
if (inlineValue !== undefined) {
|
|
342
|
+
opts.minify = parseBooleanFlag('minify', inlineValue);
|
|
343
|
+
}
|
|
344
|
+
else if (nextValue === 'true' || nextValue === 'false') {
|
|
345
|
+
opts.minify = parseBooleanFlag('minify', nextValue);
|
|
346
|
+
index += 1;
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
opts.minify = true;
|
|
350
|
+
}
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return opts;
|
|
355
|
+
}
|
|
356
|
+
function cliConfig(argv) {
|
|
357
|
+
const cliOpts = parseArgs(argv);
|
|
358
|
+
if (isEmptyObject(cliOpts))
|
|
359
|
+
return undefined;
|
|
360
|
+
const point = {
|
|
361
|
+
entry: cliOpts.entry ?? '',
|
|
362
|
+
exportPath: '.',
|
|
363
|
+
format: cliOpts.format ?? ['esm'],
|
|
364
|
+
tsconfigFilePath: cliOpts.tsconfig ?? undefined,
|
|
365
|
+
minify: cliOpts.minify ?? false,
|
|
366
|
+
checks: {
|
|
367
|
+
checkAnonymous: cliOpts.check ? true : false,
|
|
368
|
+
checkDefaultExports: cliOpts.check ? true : false,
|
|
369
|
+
checkNpmInstalled: cliOpts.check ? true : false
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
if (point.entry === '')
|
|
373
|
+
return undefined;
|
|
374
|
+
const config = {
|
|
375
|
+
entryPoints: [point],
|
|
376
|
+
outDir: cliOpts.outDir ?? 'dist',
|
|
377
|
+
allowUpdatePackageJson: cliOpts.allowUpdate ?? false
|
|
378
|
+
};
|
|
379
|
+
return config;
|
|
380
|
+
}
|
|
381
|
+
//src/cli/print_help.ts
|
|
382
|
+
function printHelp() {
|
|
383
|
+
console.log(`Susee CLI.
|
|
384
|
+
Usage:
|
|
385
|
+
susee build Build using susee.config.{ts,js,mjs}
|
|
386
|
+
susee init Generate susee.config.{ts,js,mjs}
|
|
387
|
+
susee --help Show this message
|
|
388
|
+
susee build <entry> [options] Build from a single entry file
|
|
389
|
+
Options:
|
|
390
|
+
--entry <path> Entry file (optional if provided as positional <entry>)
|
|
391
|
+
--outdir <path> Output directory. (default to "dist")
|
|
392
|
+
--format <cjs|commonjs|esm> Output module format. (default to ["esm"])
|
|
393
|
+
--tsconfig <path> Custom tsconfig path. (default to undefined)
|
|
394
|
+
--allow-update[=true|false] Enable package.json update. (default to false)
|
|
395
|
+
--minify[=true|false] Enable minify to output JS code.(default to false)
|
|
396
|
+
--check[=true|false] Enable minify to output JS code.(default to false)
|
|
397
|
+
Notes:
|
|
398
|
+
Duplicate top-level declarations fail the build with file and location output.
|
|
399
|
+
Rename conflicting declarations in source files before bundling.
|
|
400
|
+
Examples:
|
|
401
|
+
susee build src/index.ts --outdir dist
|
|
402
|
+
susee build src/index.ts --format commonjs
|
|
403
|
+
susee build --entry src/index.ts --format esm --tsconfig tsconfig.build.json
|
|
404
|
+
susee build src/index.ts --profile
|
|
405
|
+
`);
|
|
406
|
+
}
|
|
407
|
+
//src/helpers/files.ts
|
|
408
|
+
var files;
|
|
409
|
+
(function (files_1) {
|
|
410
|
+
const root = process.cwd();
|
|
411
|
+
function resolvePath(pathStr) {
|
|
412
|
+
return path.resolve(root, pathStr);
|
|
413
|
+
}
|
|
414
|
+
files_1.resolvePath = resolvePath;
|
|
415
|
+
function relativePath(pathStr) {
|
|
416
|
+
return path.relative(root, pathStr);
|
|
417
|
+
}
|
|
418
|
+
files_1.relativePath = relativePath;
|
|
419
|
+
function joinPath(...paths) {
|
|
420
|
+
return path.join(...paths);
|
|
421
|
+
}
|
|
422
|
+
files_1.joinPath = joinPath;
|
|
423
|
+
function existsPath(pathStr) {
|
|
424
|
+
return fs.existsSync(resolvePath(pathStr));
|
|
425
|
+
}
|
|
426
|
+
files_1.existsPath = existsPath;
|
|
427
|
+
async function deleteFile(filePath) {
|
|
428
|
+
if (existsPath(filePath)) {
|
|
429
|
+
await fs.promises.unlink(filePath);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
files_1.deleteFile = deleteFile;
|
|
433
|
+
async function readFile(filePath) {
|
|
434
|
+
if (!existsPath(filePath)) {
|
|
435
|
+
console.error(tcolor.magenta(`> ${filePath} does not exists `));
|
|
436
|
+
process.exit(1);
|
|
437
|
+
}
|
|
438
|
+
filePath = resolvePath(filePath);
|
|
439
|
+
const readContent = await fs.promises.readFile(filePath);
|
|
440
|
+
return {
|
|
441
|
+
str: readContent.toString('utf8'),
|
|
442
|
+
bytes: readContent.byteLength
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
files_1.readFile = readFile;
|
|
446
|
+
async function readJsonFile(filePath) {
|
|
447
|
+
const read = await readFile(filePath);
|
|
448
|
+
return JSON.parse(read.str);
|
|
449
|
+
}
|
|
450
|
+
files_1.readJsonFile = readJsonFile;
|
|
451
|
+
async function createDirectory(dirPath) {
|
|
452
|
+
dirPath = resolvePath(dirPath);
|
|
453
|
+
if (!existsPath(dirPath)) {
|
|
454
|
+
await fs.promises.mkdir(dirPath, { recursive: true });
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
files_1.createDirectory = createDirectory;
|
|
458
|
+
function parentPath(filePath) {
|
|
459
|
+
return path.dirname(resolvePath(filePath));
|
|
460
|
+
}
|
|
461
|
+
files_1.parentPath = parentPath;
|
|
462
|
+
async function writeFile(filePath, content) {
|
|
463
|
+
if (existsPath(filePath))
|
|
464
|
+
await deleteFile(filePath);
|
|
465
|
+
await createDirectory(parentPath(filePath));
|
|
466
|
+
filePath = resolvePath(filePath);
|
|
467
|
+
await fs.promises.writeFile(filePath, content);
|
|
468
|
+
}
|
|
469
|
+
files_1.writeFile = writeFile;
|
|
470
|
+
async function clearFolder(folderPath) {
|
|
471
|
+
folderPath = resolvePath(folderPath);
|
|
472
|
+
try {
|
|
473
|
+
const entries = await fs.promises.readdir(folderPath, { withFileTypes: true });
|
|
474
|
+
await Promise.all(entries.map((entry) => fs.promises.rm(path.join(folderPath, entry.name), { recursive: true })));
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
// biome-ignore lint/suspicious/noExplicitAny: error code
|
|
478
|
+
if (error.code !== 'ENOENT') {
|
|
479
|
+
throw error;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
files_1.clearFolder = clearFolder;
|
|
484
|
+
// -------------------------------------------------------------------------------------------//
|
|
485
|
+
const isCjs = (files) => files.commonjs && files.commonjsTypes;
|
|
486
|
+
const isEsm = (files) => files.esm && files.esmTypes;
|
|
487
|
+
function getExports(files, exportPath) {
|
|
488
|
+
return isCjs(files) && isEsm(files) ? { [exportPath]: {
|
|
489
|
+
import: {
|
|
490
|
+
types: `./${path.relative(process.cwd(), files.esmTypes)}`,
|
|
491
|
+
default: `./${path.relative(process.cwd(), files.esm)}`
|
|
492
|
+
},
|
|
493
|
+
require: {
|
|
494
|
+
types: `./${path.relative(process.cwd(), files.commonjsTypes)}`,
|
|
495
|
+
default: `./${path.relative(process.cwd(), files.commonjs)}`
|
|
496
|
+
}
|
|
497
|
+
} } : isCjs(files) && !isEsm(files) ? { [exportPath]: { require: {
|
|
498
|
+
types: `./${path.relative(process.cwd(), files.commonjsTypes)}`,
|
|
499
|
+
default: `./${path.relative(process.cwd(), files.commonjs)}`
|
|
500
|
+
} } } : !isCjs(files) && isEsm(files) ? { [exportPath]: { import: {
|
|
501
|
+
types: `./${path.relative(process.cwd(), files.esmTypes)}`,
|
|
502
|
+
default: `./${path.relative(process.cwd(), files.esm)}`
|
|
503
|
+
} } } : {};
|
|
504
|
+
}
|
|
505
|
+
async function writePackageJson(files, exportPath) {
|
|
506
|
+
let isMain = true;
|
|
507
|
+
if (exportPath !== '.') {
|
|
508
|
+
isMain = false;
|
|
509
|
+
}
|
|
510
|
+
const pkgFile = resolvePath('package.json');
|
|
511
|
+
const pkgtext = await readJsonFile(pkgFile);
|
|
512
|
+
let { name, version, description, main, module, type, types, exports, ...rest } = pkgtext;
|
|
513
|
+
type = 'module';
|
|
514
|
+
let _main = {};
|
|
515
|
+
let _module = {};
|
|
516
|
+
let _types = {};
|
|
517
|
+
let _exports = {};
|
|
518
|
+
if (isMain) {
|
|
519
|
+
_main = files.main ? { main: path.relative(process.cwd(), files.main) } : {};
|
|
520
|
+
_module = files.module ? { module: path.relative(process.cwd(), files.module) } : {};
|
|
521
|
+
_types = files.types ? { types: path.relative(process.cwd(), files.types) } : {};
|
|
522
|
+
_exports = { exports: { ...getExports(files, exportPath) } };
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
_main = main ? { main } : {};
|
|
526
|
+
_module = module ? { module } : {};
|
|
527
|
+
_types = types ? { types } : {};
|
|
528
|
+
const normalizedExports = exports && typeof exports === 'object' && !Array.isArray(exports) ? { ...exports } : {};
|
|
529
|
+
_exports = { exports: {
|
|
530
|
+
...normalizedExports,
|
|
531
|
+
...getExports(files, exportPath)
|
|
532
|
+
} };
|
|
533
|
+
}
|
|
534
|
+
const pkgJson = {
|
|
535
|
+
name,
|
|
536
|
+
version,
|
|
537
|
+
description,
|
|
538
|
+
type,
|
|
539
|
+
..._main,
|
|
540
|
+
..._types,
|
|
541
|
+
..._module,
|
|
542
|
+
..._exports,
|
|
543
|
+
...rest
|
|
544
|
+
};
|
|
545
|
+
await writeFile(pkgFile, JSON.stringify(pkgJson, null, 2));
|
|
546
|
+
}
|
|
547
|
+
files_1.writePackageJson = writePackageJson;
|
|
548
|
+
})(files || (files = {}));
|
|
549
|
+
/**
|
|
550
|
+
* Normalizes TypeScript compiler options when JSX compilation is requested.
|
|
551
|
+
*
|
|
552
|
+
* For JSX input, this validates that the source imports either React runtime
|
|
553
|
+
* modules or the configured `jsxImportSource` runtime package. When validation
|
|
554
|
+
* passes, it enables DOM libs and defaults `jsx` to `ReactJSX` if unset.
|
|
555
|
+
*
|
|
556
|
+
* @param {string} sourceCode - Source text to inspect for JSX runtime imports.
|
|
557
|
+
* @param {ts6.CompilerOptions} compilerOptions - User-provided compiler options.
|
|
558
|
+
* @param {boolean} isJsx - Whether JSX mode is enabled for this compilation.
|
|
559
|
+
* @returns {ts6.CompilerOptions} Compiler options to pass into program creation.
|
|
560
|
+
*/
|
|
561
|
+
function jsxCompilerOptions(sourceCode, compilerOptions, isJsx) {
|
|
562
|
+
if (!isJsx) {
|
|
563
|
+
return compilerOptions;
|
|
564
|
+
}
|
|
565
|
+
const reactRegexp = /import\s+(?:.*?)\s+from\s+(?:"react"|"react\/.*"|"react-dom\/.*"|"react-dom")/gm;
|
|
566
|
+
if (!reactRegexp.test(sourceCode)) {
|
|
567
|
+
if (!compilerOptions.jsxImportSource) {
|
|
568
|
+
console.error('[jsx-runtime-error]:\nJSX syntax found in bundled code,but its not react runtime,you need to be set jsxImportSource in tsconfig.');
|
|
569
|
+
process.exit(1);
|
|
570
|
+
}
|
|
571
|
+
const txt = compilerOptions.jsxImportSource;
|
|
572
|
+
const pattern = `import\\s+(?:.*?)\\s+from\\s+("${txt}"|"${txt}\\/.*")`;
|
|
573
|
+
const re = new RegExp(pattern, 'gm');
|
|
574
|
+
if (!re.test(sourceCode)) {
|
|
575
|
+
console.error('[jsx-runtime-mismatch-error]:\nJSX syntax found in bundled code,but its not react runtime and jsx-runtime from bundled code and jsxImportSource from tsconfig are mismatched.`');
|
|
576
|
+
process.exit(1);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
// oxlint-disable-next-line no-unused-vars
|
|
580
|
+
const { jsx, lib, ...rest } = compilerOptions;
|
|
581
|
+
const _jsx = jsx ?? ts6.JsxEmit.ReactJSX;
|
|
582
|
+
return {
|
|
583
|
+
lib: [
|
|
584
|
+
'dom',
|
|
585
|
+
'dom.iterable',
|
|
586
|
+
'esnext'
|
|
587
|
+
],
|
|
588
|
+
jsx: _jsx,
|
|
589
|
+
...rest
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Creates a ts.CompilerHost that can be used with the typescript compiler.
|
|
594
|
+
* This host is designed to be used with in-memory compilation and will
|
|
595
|
+
* return the source file for the given fileName and will write all output
|
|
596
|
+
* files to the createdFiles object.
|
|
597
|
+
* @param {string} sourceCode - the source code to compile
|
|
598
|
+
* @param {string} fileName - the name of the file to compile
|
|
599
|
+
* @returns {{createdFiles: Record<string, string>, host: ts.CompilerHost}}
|
|
600
|
+
*/
|
|
601
|
+
function createHost(sourceCode, fileName) {
|
|
602
|
+
const createdFiles = {};
|
|
603
|
+
const host = {
|
|
604
|
+
getSourceFile: (file, languageVersion) => {
|
|
605
|
+
if (file === fileName) {
|
|
606
|
+
return ts6.createSourceFile(file, sourceCode, languageVersion);
|
|
607
|
+
}
|
|
608
|
+
return undefined;
|
|
609
|
+
},
|
|
610
|
+
writeFile: (fileName, contents) => {
|
|
611
|
+
createdFiles[fileName] = contents;
|
|
612
|
+
},
|
|
613
|
+
getDefaultLibFileName: (options) => ts6.getDefaultLibFilePath(options),
|
|
614
|
+
getCurrentDirectory: () => '',
|
|
615
|
+
getDirectories: () => [],
|
|
616
|
+
fileExists: (file) => file === fileName,
|
|
617
|
+
readFile: (file) => file === fileName ? sourceCode : undefined,
|
|
618
|
+
getCanonicalFileName: (file) => file,
|
|
619
|
+
useCaseSensitiveFileNames: () => true,
|
|
620
|
+
getNewLine: () => '\n'
|
|
621
|
+
};
|
|
622
|
+
return {
|
|
623
|
+
createdFiles,
|
|
624
|
+
host
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
function suseeCompiler({ sourceCode, fileName, compilerOptions, isJsx = false }) {
|
|
628
|
+
compilerOptions = jsxCompilerOptions(sourceCode, compilerOptions, isJsx);
|
|
629
|
+
// create host
|
|
630
|
+
const _host = createHost(sourceCode, fileName);
|
|
631
|
+
const createdFiles = _host.createdFiles;
|
|
632
|
+
const host = _host.host;
|
|
633
|
+
const program = ts6.createProgram([fileName], compilerOptions, host);
|
|
634
|
+
program.emit();
|
|
635
|
+
let dts;
|
|
636
|
+
let map;
|
|
637
|
+
let code = '';
|
|
638
|
+
let file_name = '';
|
|
639
|
+
let out_dir = '';
|
|
640
|
+
for (const key of Object.keys(createdFiles)) {
|
|
641
|
+
if (key.endsWith('.js'))
|
|
642
|
+
code = createdFiles[key];
|
|
643
|
+
if (key.endsWith('.d.ts'))
|
|
644
|
+
dts = createdFiles[key];
|
|
645
|
+
if (key.endsWith('.js.map'))
|
|
646
|
+
map = createdFiles[key];
|
|
647
|
+
file_name = path.basename(key).split('.')[0];
|
|
648
|
+
out_dir = path.dirname(key);
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
code,
|
|
652
|
+
file_name,
|
|
653
|
+
out_dir,
|
|
654
|
+
dts,
|
|
655
|
+
map
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
//src/compiler/tsoptions.ts
|
|
659
|
+
/**
|
|
660
|
+
* Get the path of the configuration file.
|
|
661
|
+
* If customConfigPath is provided and exists, use it.
|
|
662
|
+
* If customConfigPath is not provided or does not exist, use the default configuration file.
|
|
663
|
+
* @param {string | undefined} customConfigPath path of the custom configuration file.
|
|
664
|
+
* @returns {string | undefined} path of the configuration file or undefined if customConfigPath does not exist.
|
|
665
|
+
*/
|
|
666
|
+
function getTsConfigPath(customConfigPath) {
|
|
667
|
+
let config_path;
|
|
668
|
+
if (customConfigPath) {
|
|
669
|
+
if (!ts6.sys.fileExists(ts6.sys.resolvePath(customConfigPath))) {
|
|
670
|
+
console.error(`> ${tcolor.magenta(`Given custom file ${customConfigPath} does not exists`)}`);
|
|
671
|
+
ts6.sys.exit(1);
|
|
672
|
+
}
|
|
673
|
+
config_path = customConfigPath;
|
|
674
|
+
return config_path;
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
config_path = ts6.findConfigFile(ts6.sys.getCurrentDirectory(), ts6.sys.fileExists);
|
|
678
|
+
return config_path;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Get the TypeScript compiler options for susee bundler.
|
|
683
|
+
* @param {string | undefined} customConfigPath path of the custom configuration file.
|
|
684
|
+
*/
|
|
685
|
+
function getCompilerOptions(customConfigPath) {
|
|
686
|
+
let tsconfig_opts;
|
|
687
|
+
const config_path = getTsConfigPath(customConfigPath);
|
|
688
|
+
if (config_path) {
|
|
689
|
+
const config = ts6.readConfigFile(config_path, ts6.sys.readFile);
|
|
690
|
+
const basePath = path.dirname(config_path);
|
|
691
|
+
const parsed = ts6.parseJsonConfigFileContent(config.config, ts6.sys, basePath);
|
|
692
|
+
tsconfig_opts = { ...parsed.options };
|
|
693
|
+
}
|
|
694
|
+
const commonjs = (out_dir) => {
|
|
695
|
+
const _out = out_dir ? out_dir : 'dist';
|
|
696
|
+
if (tsconfig_opts !== undefined) {
|
|
697
|
+
// oxlint-disable-next-line no-unused-vars
|
|
698
|
+
const { rootDir, outDir, module, allowJs, declarationDir, ...rest } = tsconfig_opts;
|
|
699
|
+
return {
|
|
700
|
+
outDir: _out,
|
|
701
|
+
module: ts6.ModuleKind.CommonJS,
|
|
702
|
+
allowJs: true,
|
|
703
|
+
...rest
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
return {
|
|
708
|
+
outDir: _out,
|
|
709
|
+
module: ts6.ModuleKind.CommonJS,
|
|
710
|
+
target: ts6.ScriptTarget.Latest
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
const esm = (out_dir) => {
|
|
715
|
+
const _out = out_dir ? out_dir : 'dist';
|
|
716
|
+
if (tsconfig_opts !== undefined) {
|
|
717
|
+
// oxlint-disable-next-line no-unused-vars
|
|
718
|
+
const { rootDir, outDir, module, allowJs, declarationDir, ...rest } = tsconfig_opts;
|
|
719
|
+
return {
|
|
720
|
+
outDir: _out,
|
|
721
|
+
module: ts6.ModuleKind.ES2020,
|
|
722
|
+
allowJs: true,
|
|
723
|
+
...rest
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
return {
|
|
728
|
+
outDir: _out,
|
|
729
|
+
module: ts6.ModuleKind.ES2020,
|
|
730
|
+
target: ts6.ScriptTarget.Latest
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
const defaultOptions = ts6.getDefaultCompilerOptions;
|
|
735
|
+
return {
|
|
736
|
+
commonjs,
|
|
737
|
+
esm,
|
|
738
|
+
defaultOptions
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
//src/bundler.ts
|
|
742
|
+
function bundler(point) {
|
|
743
|
+
const bundledCodeCache = new WeakMap();
|
|
744
|
+
const root = process.cwd();
|
|
745
|
+
let bundledCode = bundledCodeCache.get(point);
|
|
746
|
+
if (!bundledCode) {
|
|
747
|
+
bundledCode = suseeBundler(point.entry, root, point.checks).bundledCode;
|
|
748
|
+
bundledCodeCache.set(point, bundledCode);
|
|
749
|
+
}
|
|
750
|
+
return bundledCode;
|
|
751
|
+
}
|
|
752
|
+
//src/helpers/minify.ts
|
|
753
|
+
async function oxcMinify(fileName, code, point) {
|
|
754
|
+
const options = typeof point.minify === 'object' && typeof point.minify !== 'boolean' ? point.minify.options : undefined;
|
|
755
|
+
const result = await minify(fileName, code, options);
|
|
756
|
+
return result.code;
|
|
757
|
+
}
|
|
758
|
+
//src/compiler/index.ts
|
|
759
|
+
//import { utils } from "../helpers/utilities.js";
|
|
760
|
+
/**
|
|
761
|
+
* Checks if the given code string contains JSX syntax.
|
|
762
|
+
* @param code The content of the file as a string.
|
|
763
|
+
* @returns true if the file contains JSX, false otherwise.
|
|
764
|
+
*/
|
|
765
|
+
function isJsxContent(code) {
|
|
766
|
+
const sourceFile = ts6.createSourceFile('file.tsx', code, ts6.ScriptTarget.Latest,
|
|
767
|
+
/*setParentNodes*/
|
|
768
|
+
true, ts6.ScriptKind.TSX);
|
|
769
|
+
let containsJsx = false;
|
|
770
|
+
function visitor(node) {
|
|
771
|
+
// Check for JSX Elements, Self Closing Elements, or JSX Fragments
|
|
772
|
+
if (ts6.isJsxElement(node) || ts6.isJsxSelfClosingElement(node) || ts6.isJsxFragment(node)) {
|
|
773
|
+
containsJsx = true;
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
ts6.forEachChild(node, visitor);
|
|
777
|
+
}
|
|
778
|
+
visitor(sourceFile);
|
|
779
|
+
return containsJsx;
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Compiler for the JavaScript API.
|
|
783
|
+
* It bundles each configured entry point, emits CommonJS and ESM outputs,
|
|
784
|
+
* and optionally updates package export metadata.
|
|
785
|
+
*/
|
|
786
|
+
class Compiler {
|
|
787
|
+
_files;
|
|
788
|
+
_object;
|
|
789
|
+
/**
|
|
790
|
+
* Creates a compiler instance with normalized build options.
|
|
791
|
+
* @param {BuildOptions} object - build options generated from the susee config.
|
|
792
|
+
*/
|
|
793
|
+
constructor(object) {
|
|
794
|
+
this._object = object;
|
|
795
|
+
this._files = {
|
|
796
|
+
commonjs: undefined,
|
|
797
|
+
commonjsTypes: undefined,
|
|
798
|
+
esm: undefined,
|
|
799
|
+
esmTypes: undefined,
|
|
800
|
+
main: undefined,
|
|
801
|
+
module: undefined,
|
|
802
|
+
types: undefined
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
_update() {
|
|
806
|
+
return this._object.updatePackage;
|
|
807
|
+
}
|
|
808
|
+
async _commonjs(point, bundledCode) {
|
|
809
|
+
const isMain = point.exportPath === '.';
|
|
810
|
+
const opts = getCompilerOptions(point.tsconfigFilePath);
|
|
811
|
+
const compilerOptions = opts.commonjs(point.outputDirectoryPath);
|
|
812
|
+
const is_jsx = isJsxContent(bundledCode);
|
|
813
|
+
const compiled = suseeCompiler({
|
|
814
|
+
sourceCode: bundledCode,
|
|
815
|
+
fileName: point.entry,
|
|
816
|
+
compilerOptions,
|
|
817
|
+
isJsx: is_jsx
|
|
818
|
+
});
|
|
819
|
+
let compiledCode = compiled.code;
|
|
820
|
+
const mainFilePath = files.joinPath(compiled.out_dir, `${compiled.file_name}.cjs`);
|
|
821
|
+
const dtsFilePath = files.joinPath(compiled.out_dir, `${compiled.file_name}.d.cts`);
|
|
822
|
+
const mapFilePath = files.joinPath(compiled.out_dir, `${compiled.file_name}.cjs.map`);
|
|
823
|
+
// replace source mapping url
|
|
824
|
+
compiledCode = compiledCode.replace(new RegExp(`${compiled.file_name}.js.map`, 'gm'), `${compiled.file_name}.cjs.map`);
|
|
825
|
+
if (point.minify) {
|
|
826
|
+
compiledCode = await oxcMinify(`${compiled.file_name}.cjs`, compiledCode, point);
|
|
827
|
+
}
|
|
828
|
+
// if allow update create file object
|
|
829
|
+
if (this._update()) {
|
|
830
|
+
this._files.commonjs = mainFilePath;
|
|
831
|
+
if (compiled.dts) {
|
|
832
|
+
this._files.commonjsTypes = dtsFilePath;
|
|
833
|
+
}
|
|
834
|
+
if (isMain && point.format.includes('commonjs')) {
|
|
835
|
+
if (this._files.commonjs)
|
|
836
|
+
this._files.main = this._files.commonjs;
|
|
837
|
+
if (this._files.commonjsTypes)
|
|
838
|
+
this._files.types = this._files.commonjsTypes;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
await files.writeFile(mainFilePath, compiledCode);
|
|
842
|
+
if (compiled.dts)
|
|
843
|
+
await files.writeFile(dtsFilePath, compiled.dts);
|
|
844
|
+
if (compiled.map)
|
|
845
|
+
await files.writeFile(mapFilePath, compiled.map);
|
|
846
|
+
}
|
|
847
|
+
async _esm(point, bundledCode) {
|
|
848
|
+
const isMain = point.exportPath === '.';
|
|
849
|
+
const opts = getCompilerOptions(point.tsconfigFilePath);
|
|
850
|
+
const compilerOptions = opts.esm(point.outputDirectoryPath);
|
|
851
|
+
const is_jsx = isJsxContent(bundledCode);
|
|
852
|
+
const compiled = suseeCompiler({
|
|
853
|
+
sourceCode: bundledCode,
|
|
854
|
+
fileName: point.entry,
|
|
855
|
+
compilerOptions,
|
|
856
|
+
isJsx: is_jsx
|
|
857
|
+
});
|
|
858
|
+
let compiledCode = compiled.code;
|
|
859
|
+
const mainFilePath = files.joinPath(compiled.out_dir, `${compiled.file_name}.mjs`);
|
|
860
|
+
const dtsFilePath = files.joinPath(compiled.out_dir, `${compiled.file_name}.d.mts`);
|
|
861
|
+
const mapFilePath = files.joinPath(compiled.out_dir, `${compiled.file_name}.mjs.map`);
|
|
862
|
+
compiledCode = compiledCode.replace(new RegExp(`${compiled.file_name}.js.map`, 'gm'), `${compiled.file_name}.mjs.map`);
|
|
863
|
+
if (point.minify) {
|
|
864
|
+
compiledCode = await oxcMinify(`${compiled.file_name}.mjs`, compiledCode, point);
|
|
865
|
+
}
|
|
866
|
+
if (this._update()) {
|
|
867
|
+
this._files.esm = mainFilePath;
|
|
868
|
+
if (compiled.dts) {
|
|
869
|
+
this._files.esmTypes = dtsFilePath;
|
|
870
|
+
}
|
|
871
|
+
if (isMain && this._files.esm) {
|
|
872
|
+
this._files.module = this._files.esm;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
await files.writeFile(mainFilePath, compiledCode);
|
|
876
|
+
if (compiled.dts)
|
|
877
|
+
await files.writeFile(dtsFilePath, compiled.dts);
|
|
878
|
+
if (compiled.map)
|
|
879
|
+
await files.writeFile(mapFilePath, compiled.map);
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Clears the output directory and compiles all configured entry points.
|
|
883
|
+
* It also updates package.json export fields when package updates are enabled.
|
|
884
|
+
* @returns {Promise<void>}
|
|
885
|
+
*/
|
|
886
|
+
async compile() {
|
|
887
|
+
await files.clearFolder(this._object.outDir);
|
|
888
|
+
for (const point of this._object.buildEntryPoints) {
|
|
889
|
+
const bundleCode = bundler(point);
|
|
890
|
+
for (const format of point.format) {
|
|
891
|
+
switch (format) {
|
|
892
|
+
case 'commonjs':
|
|
893
|
+
await this._commonjs(point, bundleCode);
|
|
894
|
+
if (this._update()) {
|
|
895
|
+
await files.writePackageJson(this._files, point.exportPath);
|
|
896
|
+
}
|
|
897
|
+
break;
|
|
898
|
+
case 'esm':
|
|
899
|
+
await this._esm(point, bundleCode);
|
|
900
|
+
if (this._update()) {
|
|
901
|
+
await files.writePackageJson(this._files, point.exportPath);
|
|
902
|
+
}
|
|
903
|
+
break;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
//src/build.ts
|
|
910
|
+
/**
|
|
911
|
+
* Run a Susee build.
|
|
912
|
+
*
|
|
913
|
+
* Resolution order:
|
|
914
|
+
* 1. Use `options` when provided.
|
|
915
|
+
* 2. Otherwise try loading root config via `finalSuseeConfig()`.
|
|
916
|
+
*
|
|
917
|
+
* If neither source is available, this logs an error and exits with code 1.
|
|
918
|
+
*/
|
|
919
|
+
async function build(options) {
|
|
920
|
+
const buildTime = new LogTimer();
|
|
921
|
+
let buildOptions = {};
|
|
922
|
+
const _buildOptions = await finalSuseeConfig();
|
|
923
|
+
if (!options && !_buildOptions) {
|
|
924
|
+
const info = 'Required build options or susee config file at root.You can use `npx susee init` to create susee config file at root';
|
|
925
|
+
const cause = 'No build options or susee config file at root.';
|
|
926
|
+
logError(info, cause, true);
|
|
927
|
+
}
|
|
928
|
+
if (options) {
|
|
929
|
+
buildOptions = generateBuildOptions(options);
|
|
930
|
+
}
|
|
931
|
+
else if (_buildOptions) {
|
|
932
|
+
buildOptions = _buildOptions;
|
|
933
|
+
}
|
|
934
|
+
const compiler = new Compiler(buildOptions);
|
|
935
|
+
await compiler.compile();
|
|
936
|
+
buildTime.buildTime();
|
|
937
|
+
}
|
|
938
|
+
//src/cli/index.ts
|
|
939
|
+
async function getPackageVersion() {
|
|
940
|
+
const pkgPath = path.resolve(process.cwd(), 'package.json');
|
|
941
|
+
const _pkg = await fs.promises.readFile(pkgPath, 'utf8');
|
|
942
|
+
const pkg = JSON.parse(_pkg);
|
|
943
|
+
return pkg.version;
|
|
944
|
+
}
|
|
945
|
+
function errorLog() {
|
|
946
|
+
printHelp();
|
|
947
|
+
const info = 'Unknown CLI usage';
|
|
948
|
+
const cause = '';
|
|
949
|
+
logError(info, cause, true);
|
|
950
|
+
}
|
|
951
|
+
async function cliBuild() {
|
|
952
|
+
const args = process.argv.slice(2);
|
|
953
|
+
const version = await getPackageVersion();
|
|
954
|
+
if (args.length === 0) {
|
|
955
|
+
errorLog();
|
|
956
|
+
}
|
|
957
|
+
else if (args.length === 1) {
|
|
958
|
+
const arg0 = args[0];
|
|
959
|
+
switch (arg0) {
|
|
960
|
+
case 'build':
|
|
961
|
+
await build();
|
|
962
|
+
break;
|
|
963
|
+
case 'init':
|
|
964
|
+
await cliInit();
|
|
965
|
+
break;
|
|
966
|
+
case '--version':
|
|
967
|
+
case '-v':
|
|
968
|
+
logInfo(`susee v${version}`);
|
|
969
|
+
break;
|
|
970
|
+
case '--help':
|
|
971
|
+
case '-h':
|
|
972
|
+
printHelp();
|
|
973
|
+
break;
|
|
974
|
+
default:
|
|
975
|
+
printHelp();
|
|
976
|
+
break;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
else if (args.length > 1 && args[0] === 'build') {
|
|
980
|
+
const restArgs = args.slice(1);
|
|
981
|
+
const config = cliConfig(restArgs);
|
|
982
|
+
await build(config);
|
|
983
|
+
}
|
|
984
|
+
else {
|
|
985
|
+
errorLog();
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
cliBuild();
|
|
989
|
+
//# sourceMappingURL=index.mjs.map
|