@b9g/libuild 0.1.11 → 0.1.13
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/CHANGELOG.md +25 -0
- package/package.json +1 -1
- package/src/cli.cjs +38 -2
- package/src/cli.js +40 -3
- package/src/libuild.cjs +357 -67
- package/src/libuild.js +365 -67
package/src/libuild.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
/// <reference types="./libuild.d.ts" />
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined")
|
|
6
|
+
return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
9
|
+
|
|
2
10
|
// src/libuild.ts
|
|
3
11
|
import * as FS3 from "fs/promises";
|
|
4
12
|
import * as Path3 from "path";
|
|
@@ -67,6 +75,21 @@ function externalEntrypointsPlugin(options) {
|
|
|
67
75
|
};
|
|
68
76
|
}
|
|
69
77
|
});
|
|
78
|
+
build3.onResolve({ filter: /^\.\.\/(?:src|bin)\// }, (args) => {
|
|
79
|
+
const withoutExt = args.path.replace(/\.(ts|js)$/, "");
|
|
80
|
+
const match = withoutExt.match(/^\.\.\/(?:src|bin)\/(.+)$/);
|
|
81
|
+
if (match) {
|
|
82
|
+
const entryName = match[1];
|
|
83
|
+
if (externalEntries.includes(entryName)) {
|
|
84
|
+
const dir = withoutExt.match(/^(\.\.\/(?:src|bin))\//)?.[1];
|
|
85
|
+
return {
|
|
86
|
+
path: `${dir}/${entryName}${outputExtension}`,
|
|
87
|
+
external: true
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return void 0;
|
|
92
|
+
});
|
|
70
93
|
}
|
|
71
94
|
};
|
|
72
95
|
}
|
|
@@ -92,27 +115,34 @@ function dtsPlugin(options) {
|
|
|
92
115
|
let TS;
|
|
93
116
|
try {
|
|
94
117
|
TS = await import("typescript");
|
|
95
|
-
} catch {
|
|
118
|
+
} catch (error) {
|
|
96
119
|
return;
|
|
97
120
|
}
|
|
98
121
|
const tsFiles = entryFiles.filter((file) => {
|
|
99
122
|
if (!file.endsWith(".ts"))
|
|
100
123
|
return false;
|
|
101
124
|
return options.entryPoints.some((entryPoint) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
125
|
+
try {
|
|
126
|
+
const fs = __require("fs");
|
|
127
|
+
const normalizedEntry = fs.realpathSync(Path2.resolve(entryPoint));
|
|
128
|
+
const normalizedFile = fs.realpathSync(Path2.resolve(file));
|
|
129
|
+
return normalizedEntry === normalizedFile;
|
|
130
|
+
} catch {
|
|
131
|
+
const normalizedEntry = Path2.resolve(entryPoint);
|
|
132
|
+
const normalizedFile = Path2.resolve(file);
|
|
133
|
+
return normalizedEntry === normalizedFile;
|
|
134
|
+
}
|
|
105
135
|
});
|
|
106
136
|
});
|
|
107
137
|
if (tsFiles.length === 0) {
|
|
108
138
|
return;
|
|
109
139
|
}
|
|
110
140
|
try {
|
|
141
|
+
await FS2.mkdir(options.outDir, { recursive: true });
|
|
111
142
|
const compilerOptions = {
|
|
112
143
|
declaration: true,
|
|
113
144
|
emitDeclarationOnly: true,
|
|
114
145
|
outDir: options.outDir,
|
|
115
|
-
rootDir: options.rootDir,
|
|
116
146
|
skipLibCheck: true,
|
|
117
147
|
esModuleInterop: true,
|
|
118
148
|
target: TS.ScriptTarget.ES2020,
|
|
@@ -187,6 +217,38 @@ ${content}`;
|
|
|
187
217
|
}
|
|
188
218
|
|
|
189
219
|
// src/libuild.ts
|
|
220
|
+
function generateRuntimeBanner(pkg) {
|
|
221
|
+
const prefersBun = pkg.engines?.bun !== void 0;
|
|
222
|
+
if (prefersBun) {
|
|
223
|
+
return '//bin/true; exec "$({ [ "${npm_config_user_agent#bun/}" != "$npm_config_user_agent" ] || true; } && command -v bun || command -v node)" "$0" "$@"';
|
|
224
|
+
} else {
|
|
225
|
+
return '//bin/true; exec "$([ "${npm_config_user_agent#bun/}" != "$npm_config_user_agent" ] && command -v bun || command -v node)" "$0" "$@"';
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
async function processJavaScriptExecutable(filePath, runtimeBanner) {
|
|
229
|
+
try {
|
|
230
|
+
const contents = await FS3.readFile(filePath, "utf8");
|
|
231
|
+
const lines = contents.split("\n");
|
|
232
|
+
let modified = false;
|
|
233
|
+
if (lines[0]?.startsWith("#!")) {
|
|
234
|
+
const existingShebang = lines[0];
|
|
235
|
+
if (existingShebang.includes("python") || existingShebang.includes("bash") || !existingShebang.includes("node") && !existingShebang.includes("bun") && !existingShebang.includes("sh")) {
|
|
236
|
+
console.warn(`\u26A0\uFE0F WARNING: ${filePath} has non-JavaScript shebang but is a JS file. Adding dual runtime support.`);
|
|
237
|
+
}
|
|
238
|
+
lines[0] = "#!/usr/bin/env sh";
|
|
239
|
+
lines.splice(1, 0, runtimeBanner);
|
|
240
|
+
modified = true;
|
|
241
|
+
} else {
|
|
242
|
+
lines.unshift("#!/usr/bin/env sh", runtimeBanner);
|
|
243
|
+
modified = true;
|
|
244
|
+
}
|
|
245
|
+
if (modified) {
|
|
246
|
+
await FS3.writeFile(filePath, lines.join("\n"));
|
|
247
|
+
}
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.warn(`\u26A0\uFE0F WARNING: Could not process executable ${filePath}: ${error.message}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
190
252
|
function isValidEntrypoint(filename) {
|
|
191
253
|
if (!filename.endsWith(".ts") && !filename.endsWith(".js"))
|
|
192
254
|
return false;
|
|
@@ -213,6 +275,22 @@ async function findEntrypoints(srcDir) {
|
|
|
213
275
|
return isValidEntrypoint(dirent.name);
|
|
214
276
|
}).map((dirent) => Path3.basename(dirent.name, Path3.extname(dirent.name))).sort();
|
|
215
277
|
}
|
|
278
|
+
async function findBinEntrypoints(binDir) {
|
|
279
|
+
try {
|
|
280
|
+
const files = await FS3.readdir(binDir, { withFileTypes: true });
|
|
281
|
+
return files.filter((dirent) => {
|
|
282
|
+
if (dirent.isDirectory()) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
return isValidEntrypoint(dirent.name);
|
|
286
|
+
}).map((dirent) => Path3.basename(dirent.name, Path3.extname(dirent.name))).sort();
|
|
287
|
+
} catch (error) {
|
|
288
|
+
if (error.code === "ENOENT") {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
216
294
|
function detectMainEntry(pkg, entries) {
|
|
217
295
|
function extractEntryFromPath(path) {
|
|
218
296
|
const match = path.match(/\.\/src\/([^.]+)/);
|
|
@@ -310,18 +388,38 @@ function checkIfExportIsStale(exportKey, exportValue, entries) {
|
|
|
310
388
|
}
|
|
311
389
|
return entryName ? !entries.includes(entryName) : false;
|
|
312
390
|
}
|
|
313
|
-
function generateExports(entries, mainEntry, options, existingExports = {}) {
|
|
391
|
+
async function generateExports(entries, mainEntry, options, existingExports = {}, distDir, allBinEntries = []) {
|
|
314
392
|
const exports = {};
|
|
315
393
|
const staleExports = [];
|
|
316
|
-
function createExportEntry(entry) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
394
|
+
async function createExportEntry(entry) {
|
|
395
|
+
if (entry.startsWith("bin/")) {
|
|
396
|
+
const binEntry = entry.replace("bin/", "");
|
|
397
|
+
const exportEntry = {
|
|
398
|
+
import: `./bin/${binEntry}.js`
|
|
399
|
+
};
|
|
400
|
+
if (distDir) {
|
|
401
|
+
const dtsPath = Path3.join(distDir, "bin", `${binEntry}.d.ts`);
|
|
402
|
+
if (await fileExists(dtsPath)) {
|
|
403
|
+
exportEntry.types = `./bin/${binEntry}.d.ts`;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return exportEntry;
|
|
407
|
+
} else {
|
|
408
|
+
const exportEntry = {
|
|
409
|
+
import: `./src/${entry}.js`
|
|
410
|
+
};
|
|
411
|
+
if (distDir) {
|
|
412
|
+
const dtsPath = Path3.join(distDir, "src", `${entry}.d.ts`);
|
|
413
|
+
const exists = await fileExists(dtsPath);
|
|
414
|
+
if (exists) {
|
|
415
|
+
exportEntry.types = `./src/${entry}.d.ts`;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (options.formats.cjs) {
|
|
419
|
+
exportEntry.require = `./src/${entry}.cjs`;
|
|
420
|
+
}
|
|
421
|
+
return exportEntry;
|
|
323
422
|
}
|
|
324
|
-
return exportEntry;
|
|
325
423
|
}
|
|
326
424
|
function expandExistingExport(existing, entryFromPath) {
|
|
327
425
|
if (typeof existing === "string") {
|
|
@@ -395,7 +493,7 @@ function generateExports(entries, mainEntry, options, existingExports = {}) {
|
|
|
395
493
|
}
|
|
396
494
|
}
|
|
397
495
|
if (!exports["."]) {
|
|
398
|
-
exports["."] = createExportEntry(mainEntry);
|
|
496
|
+
exports["."] = await createExportEntry(mainEntry);
|
|
399
497
|
} else {
|
|
400
498
|
exports["."] = expandExistingExport(exports["."], mainEntry);
|
|
401
499
|
}
|
|
@@ -404,7 +502,7 @@ function generateExports(entries, mainEntry, options, existingExports = {}) {
|
|
|
404
502
|
continue;
|
|
405
503
|
const key = `./${entry}`;
|
|
406
504
|
if (!exports[key]) {
|
|
407
|
-
exports[key] = createExportEntry(entry);
|
|
505
|
+
exports[key] = await createExportEntry(entry);
|
|
408
506
|
} else {
|
|
409
507
|
exports[key] = expandExistingExport(exports[key], entry);
|
|
410
508
|
}
|
|
@@ -457,13 +555,30 @@ async function validateSingleBinPath(binPath, fieldName, cwd, save) {
|
|
|
457
555
|
if (save) {
|
|
458
556
|
return;
|
|
459
557
|
}
|
|
460
|
-
if (binPath.startsWith("dist/src/") || binPath.startsWith("./dist/src/")) {
|
|
558
|
+
if (binPath.startsWith("dist/src/") || binPath.startsWith("./dist/src/") || binPath.startsWith("dist/bin/") || binPath.startsWith("./dist/bin/")) {
|
|
461
559
|
const fullPath2 = Path3.join(cwd, binPath);
|
|
462
560
|
const distExists = await fileExists(fullPath2);
|
|
463
561
|
if (distExists) {
|
|
464
562
|
return;
|
|
465
563
|
}
|
|
466
|
-
|
|
564
|
+
let srcPath;
|
|
565
|
+
let sourceDir;
|
|
566
|
+
if (binPath.startsWith("./dist/src/")) {
|
|
567
|
+
srcPath = binPath.replace("./dist/src/", "src/");
|
|
568
|
+
sourceDir = "src";
|
|
569
|
+
} else if (binPath.startsWith("dist/src/")) {
|
|
570
|
+
srcPath = binPath.replace("dist/src/", "src/");
|
|
571
|
+
sourceDir = "src";
|
|
572
|
+
} else if (binPath.startsWith("./dist/bin/")) {
|
|
573
|
+
srcPath = binPath.replace("./dist/bin/", "bin/");
|
|
574
|
+
sourceDir = "bin";
|
|
575
|
+
} else if (binPath.startsWith("dist/bin/")) {
|
|
576
|
+
srcPath = binPath.replace("dist/bin/", "bin/");
|
|
577
|
+
sourceDir = "bin";
|
|
578
|
+
} else {
|
|
579
|
+
srcPath = binPath;
|
|
580
|
+
sourceDir = "src";
|
|
581
|
+
}
|
|
467
582
|
const basePath = srcPath.replace(/\.(js|cjs|mjs)$/, "");
|
|
468
583
|
const tsPath = Path3.join(cwd, basePath + ".ts");
|
|
469
584
|
const jsPath = Path3.join(cwd, basePath + ".js");
|
|
@@ -490,7 +605,16 @@ async function validateSingleBinPath(binPath, fieldName, cwd, save) {
|
|
|
490
605
|
if (pathExists) {
|
|
491
606
|
return;
|
|
492
607
|
}
|
|
493
|
-
if (binPath.startsWith("src/") || binPath.startsWith("./src/")) {
|
|
608
|
+
if (binPath.startsWith("src/") || binPath.startsWith("./src/") || binPath.startsWith("bin/") || binPath.startsWith("./bin/")) {
|
|
609
|
+
let normalizedPath = binPath.startsWith("./") ? binPath.slice(2) : binPath;
|
|
610
|
+
if (normalizedPath.startsWith("src/")) {
|
|
611
|
+
const srcRelativePath = normalizedPath.replace("src/", "");
|
|
612
|
+
if (srcRelativePath.includes("/")) {
|
|
613
|
+
console.warn(`\u26A0\uFE0F WARNING: ${fieldName} field points to "${binPath}" which is in a subdirectory of src/.`);
|
|
614
|
+
console.warn(` libuild only auto-detects top-level src/ files as entrypoints.`);
|
|
615
|
+
console.warn(` Consider moving the file to the top-level src/ directory or use the bin/ directory for executables.`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
494
618
|
const basePath = fullPath.replace(/\.(js|cjs|mjs)$/, "");
|
|
495
619
|
const tsPath = basePath + ".ts";
|
|
496
620
|
const jsPath = basePath + ".js";
|
|
@@ -515,10 +639,19 @@ function transformBinPaths(value) {
|
|
|
515
639
|
if (value.startsWith("dist/src/")) {
|
|
516
640
|
return value.replace("dist/", "");
|
|
517
641
|
}
|
|
642
|
+
if (value.startsWith("./dist/bin/")) {
|
|
643
|
+
return value.replace("./dist/", "");
|
|
644
|
+
}
|
|
645
|
+
if (value.startsWith("dist/bin/")) {
|
|
646
|
+
return value.replace("dist/", "");
|
|
647
|
+
}
|
|
518
648
|
if (value.startsWith("./src/")) {
|
|
519
649
|
return value.replace("./", "");
|
|
520
650
|
}
|
|
521
|
-
if (value.startsWith("
|
|
651
|
+
if (value.startsWith("./bin/")) {
|
|
652
|
+
return value.replace("./", "");
|
|
653
|
+
}
|
|
654
|
+
if (value.startsWith("src/") || value === "src" || value.startsWith("bin/") || value === "bin") {
|
|
522
655
|
return value;
|
|
523
656
|
}
|
|
524
657
|
return value;
|
|
@@ -563,6 +696,60 @@ function fixExportsForDist(obj) {
|
|
|
563
696
|
}
|
|
564
697
|
return obj;
|
|
565
698
|
}
|
|
699
|
+
async function setExecutablePermissions(filePath) {
|
|
700
|
+
try {
|
|
701
|
+
await FS3.chmod(filePath, 493);
|
|
702
|
+
} catch (error) {
|
|
703
|
+
console.warn(`\u26A0\uFE0F WARNING: Could not set executable permissions for ${filePath}: ${error.message}`);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
async function makeFilesExecutable(pkg, cwd, allBinEntries, runtimeBanner) {
|
|
707
|
+
const filesToMakeExecutable = [];
|
|
708
|
+
const filesToProcessForDualRuntime = [];
|
|
709
|
+
const distDir = Path3.join(cwd, "dist");
|
|
710
|
+
if (pkg.bin) {
|
|
711
|
+
if (typeof pkg.bin === "string") {
|
|
712
|
+
const fullPath = Path3.join(distDir, pkg.bin);
|
|
713
|
+
filesToMakeExecutable.push(fullPath);
|
|
714
|
+
if (pkg.bin.endsWith(".js")) {
|
|
715
|
+
filesToProcessForDualRuntime.push(fullPath);
|
|
716
|
+
}
|
|
717
|
+
} else if (typeof pkg.bin === "object") {
|
|
718
|
+
for (const binPath of Object.values(pkg.bin)) {
|
|
719
|
+
if (typeof binPath === "string") {
|
|
720
|
+
const fullPath = Path3.join(distDir, binPath);
|
|
721
|
+
filesToMakeExecutable.push(fullPath);
|
|
722
|
+
if (binPath.endsWith(".js")) {
|
|
723
|
+
filesToProcessForDualRuntime.push(fullPath);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
const binDirFiles = /* @__PURE__ */ new Set();
|
|
730
|
+
for (const binEntryInfo of allBinEntries) {
|
|
731
|
+
const baseDir = binEntryInfo.source === "src" ? "dist/src/bin" : "dist/bin";
|
|
732
|
+
const jsPath = Path3.join(cwd, baseDir, `${binEntryInfo.name}.js`);
|
|
733
|
+
const cjsPath = Path3.join(cwd, baseDir, `${binEntryInfo.name}.cjs`);
|
|
734
|
+
binDirFiles.add(jsPath);
|
|
735
|
+
if (!filesToMakeExecutable.includes(jsPath)) {
|
|
736
|
+
filesToMakeExecutable.push(jsPath);
|
|
737
|
+
}
|
|
738
|
+
if (!filesToMakeExecutable.includes(cjsPath)) {
|
|
739
|
+
filesToMakeExecutable.push(cjsPath);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
for (const filePath of filesToProcessForDualRuntime) {
|
|
743
|
+
if (await fileExists(filePath) && !binDirFiles.has(filePath)) {
|
|
744
|
+
await processJavaScriptExecutable(filePath, runtimeBanner);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
for (const filePath of filesToMakeExecutable) {
|
|
748
|
+
if (await fileExists(filePath)) {
|
|
749
|
+
await setExecutablePermissions(filePath);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
566
753
|
async function resolveWorkspaceDependencies(dependencies, cwd) {
|
|
567
754
|
if (!dependencies)
|
|
568
755
|
return void 0;
|
|
@@ -622,7 +809,7 @@ async function resolveWorkspaceVersion(packageName, workspaceSpec, cwd) {
|
|
|
622
809
|
return workspaceSpec;
|
|
623
810
|
}
|
|
624
811
|
}
|
|
625
|
-
async function cleanPackageJSON(pkg, mainEntry, options, cwd) {
|
|
812
|
+
async function cleanPackageJSON(pkg, mainEntry, options, cwd, distDir) {
|
|
626
813
|
const cleaned = {
|
|
627
814
|
name: pkg.name,
|
|
628
815
|
version: pkg.version
|
|
@@ -687,7 +874,13 @@ async function cleanPackageJSON(pkg, mainEntry, options, cwd) {
|
|
|
687
874
|
cleaned.main = `src/${mainEntry}.cjs`;
|
|
688
875
|
}
|
|
689
876
|
cleaned.module = `src/${mainEntry}.js`;
|
|
690
|
-
|
|
877
|
+
if (distDir) {
|
|
878
|
+
const dtsPath = Path3.join(distDir, "src", `${mainEntry}.d.ts`);
|
|
879
|
+
const exists = await fileExists(dtsPath);
|
|
880
|
+
if (exists) {
|
|
881
|
+
cleaned.types = `src/${mainEntry}.d.ts`;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
691
884
|
return cleaned;
|
|
692
885
|
}
|
|
693
886
|
async function fileExists(filePath) {
|
|
@@ -739,9 +932,19 @@ async function build2(cwd, save = false) {
|
|
|
739
932
|
console.warn(" Add 'dist/' to your .gitignore file");
|
|
740
933
|
}
|
|
741
934
|
}
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
|
|
935
|
+
const binDir = Path3.join(cwd, "bin");
|
|
936
|
+
const srcEntries = await findEntrypoints(srcDir);
|
|
937
|
+
const binEntries = await findBinEntrypoints(binDir);
|
|
938
|
+
const allBinEntries = binEntries.map((entry) => ({ name: entry, source: "top-level" }));
|
|
939
|
+
const entries = [
|
|
940
|
+
...srcEntries,
|
|
941
|
+
...allBinEntries.map((entry) => `bin/${entry.name}`)
|
|
942
|
+
];
|
|
943
|
+
if (srcEntries.length === 0 && allBinEntries.length === 0) {
|
|
944
|
+
throw new Error("No entry points found in src/ or bin/");
|
|
945
|
+
}
|
|
946
|
+
if (allBinEntries.length > 0) {
|
|
947
|
+
console.info(` Found bin entries: ${allBinEntries.map((entry) => entry.name).join(", ")}`);
|
|
745
948
|
}
|
|
746
949
|
const options = {
|
|
747
950
|
formats: {
|
|
@@ -752,7 +955,7 @@ async function build2(cwd, save = false) {
|
|
|
752
955
|
umd: entries.includes("umd")
|
|
753
956
|
}
|
|
754
957
|
};
|
|
755
|
-
const mainEntry = detectMainEntry(pkg,
|
|
958
|
+
const mainEntry = detectMainEntry(pkg, srcEntries);
|
|
756
959
|
console.info(" Found entries:", entries.join(", "));
|
|
757
960
|
console.info(" Main entry:", mainEntry);
|
|
758
961
|
if (options.formats.cjs) {
|
|
@@ -783,11 +986,29 @@ async function build2(cwd, save = false) {
|
|
|
783
986
|
const entryPoints = [];
|
|
784
987
|
const umdEntries = [];
|
|
785
988
|
for (const entry of entries) {
|
|
786
|
-
|
|
787
|
-
|
|
989
|
+
let entryPath;
|
|
990
|
+
let jsEntryPath;
|
|
991
|
+
let sourceDir;
|
|
992
|
+
if (entry.startsWith("bin/")) {
|
|
993
|
+
const binEntryName = entry.replace("bin/", "");
|
|
994
|
+
const binEntryInfo = allBinEntries.find((binEntry) => binEntry.name === binEntryName);
|
|
995
|
+
if (binEntryInfo?.source === "src") {
|
|
996
|
+
entryPath = Path3.join(srcDir, "bin", `${binEntryName}.ts`);
|
|
997
|
+
jsEntryPath = Path3.join(srcDir, "bin", `${binEntryName}.js`);
|
|
998
|
+
sourceDir = "src/bin/";
|
|
999
|
+
} else {
|
|
1000
|
+
entryPath = Path3.join(binDir, `${binEntryName}.ts`);
|
|
1001
|
+
jsEntryPath = Path3.join(binDir, `${binEntryName}.js`);
|
|
1002
|
+
sourceDir = "bin/";
|
|
1003
|
+
}
|
|
1004
|
+
} else {
|
|
1005
|
+
entryPath = Path3.join(srcDir, `${entry}.ts`);
|
|
1006
|
+
jsEntryPath = Path3.join(srcDir, `${entry}.js`);
|
|
1007
|
+
sourceDir = "src/";
|
|
1008
|
+
}
|
|
788
1009
|
const actualPath = await fileExists(entryPath) ? entryPath : jsEntryPath;
|
|
789
1010
|
if (!await fileExists(actualPath)) {
|
|
790
|
-
throw new Error(`Entry point file not found: ${actualPath}. Expected ${entry}.ts or ${entry}.js in
|
|
1011
|
+
throw new Error(`Entry point file not found: ${actualPath}. Expected ${entry.replace("bin/", "")}.ts or ${entry.replace("bin/", "")}.js in ${sourceDir} directory.`);
|
|
791
1012
|
}
|
|
792
1013
|
if (entry === "umd") {
|
|
793
1014
|
umdEntries.push(actualPath);
|
|
@@ -795,58 +1016,107 @@ async function build2(cwd, save = false) {
|
|
|
795
1016
|
entryPoints.push(actualPath);
|
|
796
1017
|
}
|
|
797
1018
|
}
|
|
1019
|
+
const srcEntryPoints = entryPoints.filter((path) => path.includes(srcDir));
|
|
1020
|
+
const binEntryPoints = entryPoints.filter((path) => path.includes(binDir));
|
|
1021
|
+
const distBinDir = Path3.join(distDir, "bin");
|
|
1022
|
+
if (binEntryPoints.length > 0) {
|
|
1023
|
+
await FS3.mkdir(distBinDir, { recursive: true });
|
|
1024
|
+
}
|
|
798
1025
|
if (entryPoints.length > 0) {
|
|
799
|
-
|
|
1026
|
+
console.info(` Building ${entryPoints.length} entries (ESM)...`);
|
|
1027
|
+
const srcEntryNames = srcEntryPoints.map((path) => {
|
|
800
1028
|
const name = Path3.basename(path, Path3.extname(path));
|
|
801
1029
|
return name;
|
|
802
1030
|
});
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
outdir: distSrcDir,
|
|
807
|
-
format: "esm",
|
|
808
|
-
outExtension: { ".js": ".js" },
|
|
809
|
-
bundle: true,
|
|
810
|
-
minify: false,
|
|
811
|
-
sourcemap: false,
|
|
812
|
-
external: externalDeps,
|
|
813
|
-
platform: "node",
|
|
814
|
-
target: "node18",
|
|
815
|
-
packages: "external",
|
|
816
|
-
supported: { "import-attributes": true },
|
|
817
|
-
plugins: [
|
|
818
|
-
externalEntrypointsPlugin({
|
|
819
|
-
entryNames,
|
|
820
|
-
outputExtension: ".js"
|
|
821
|
-
}),
|
|
822
|
-
dtsPlugin({
|
|
823
|
-
outDir: distSrcDir,
|
|
824
|
-
rootDir: srcDir,
|
|
825
|
-
entryPoints
|
|
826
|
-
})
|
|
827
|
-
]
|
|
1031
|
+
const binEntryNames = binEntryPoints.map((path) => {
|
|
1032
|
+
const name = Path3.basename(path, Path3.extname(path));
|
|
1033
|
+
return name;
|
|
828
1034
|
});
|
|
829
|
-
|
|
830
|
-
|
|
1035
|
+
const allESMEntryPoints = [...srcEntryPoints, ...binEntryPoints];
|
|
1036
|
+
const allEntryNames = [...srcEntryNames, ...binEntryNames];
|
|
1037
|
+
if (allESMEntryPoints.length > 0) {
|
|
831
1038
|
await ESBuild.build({
|
|
832
|
-
entryPoints,
|
|
833
|
-
outdir:
|
|
834
|
-
|
|
835
|
-
|
|
1039
|
+
entryPoints: allESMEntryPoints,
|
|
1040
|
+
outdir: distDir,
|
|
1041
|
+
outbase: cwd,
|
|
1042
|
+
// Preserve src/ and bin/ directory structure
|
|
1043
|
+
format: "esm",
|
|
1044
|
+
outExtension: { ".js": ".js" },
|
|
836
1045
|
bundle: true,
|
|
837
1046
|
minify: false,
|
|
838
1047
|
sourcemap: false,
|
|
839
1048
|
external: externalDeps,
|
|
840
1049
|
platform: "node",
|
|
841
1050
|
target: "node18",
|
|
1051
|
+
packages: "external",
|
|
842
1052
|
supported: { "import-attributes": true },
|
|
843
1053
|
plugins: [
|
|
844
1054
|
externalEntrypointsPlugin({
|
|
845
|
-
entryNames,
|
|
846
|
-
outputExtension: ".
|
|
847
|
-
})
|
|
1055
|
+
entryNames: allEntryNames,
|
|
1056
|
+
outputExtension: ".js"
|
|
1057
|
+
}),
|
|
1058
|
+
// Generate TypeScript declarations for src entries
|
|
1059
|
+
...srcEntryPoints.length > 0 ? [dtsPlugin({
|
|
1060
|
+
outDir: distSrcDir,
|
|
1061
|
+
rootDir: srcDir,
|
|
1062
|
+
entryPoints: srcEntryPoints
|
|
1063
|
+
})] : [],
|
|
1064
|
+
// Generate TypeScript declarations for bin entries
|
|
1065
|
+
...binEntryPoints.length > 0 ? [dtsPlugin({
|
|
1066
|
+
outDir: distBinDir,
|
|
1067
|
+
rootDir: binDir,
|
|
1068
|
+
entryPoints: binEntryPoints
|
|
1069
|
+
})] : []
|
|
848
1070
|
]
|
|
849
1071
|
});
|
|
1072
|
+
if (binEntryPoints.length > 0) {
|
|
1073
|
+
const runtimeBanner = generateRuntimeBanner(pkg);
|
|
1074
|
+
for (const binEntryName of binEntryNames) {
|
|
1075
|
+
const outputPath = Path3.join(distBinDir, `${binEntryName}.js`);
|
|
1076
|
+
await processJavaScriptExecutable(outputPath, runtimeBanner);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
if (options.formats.cjs) {
|
|
1081
|
+
console.info(` Building ${entryPoints.length} entries (CJS)...`);
|
|
1082
|
+
if (srcEntryPoints.length > 0) {
|
|
1083
|
+
try {
|
|
1084
|
+
await ESBuild.build({
|
|
1085
|
+
entryPoints: srcEntryPoints,
|
|
1086
|
+
outdir: distSrcDir,
|
|
1087
|
+
format: "cjs",
|
|
1088
|
+
outExtension: { ".js": ".cjs" },
|
|
1089
|
+
bundle: true,
|
|
1090
|
+
minify: false,
|
|
1091
|
+
sourcemap: false,
|
|
1092
|
+
external: externalDeps,
|
|
1093
|
+
platform: "node",
|
|
1094
|
+
target: "node18",
|
|
1095
|
+
supported: { "import-attributes": true },
|
|
1096
|
+
plugins: [
|
|
1097
|
+
externalEntrypointsPlugin({
|
|
1098
|
+
entryNames: srcEntryNames,
|
|
1099
|
+
outputExtension: ".cjs"
|
|
1100
|
+
})
|
|
1101
|
+
]
|
|
1102
|
+
});
|
|
1103
|
+
} catch (error) {
|
|
1104
|
+
const errorMessage = error.message || "";
|
|
1105
|
+
const hasErrorsArray = error.errors && Array.isArray(error.errors);
|
|
1106
|
+
const isTLAError = errorMessage.includes('Top-level await is currently not supported with the "cjs" output format') || hasErrorsArray && error.errors.some((e) => e.text && e.text.includes('Top-level await is currently not supported with the "cjs" output format'));
|
|
1107
|
+
if (isTLAError) {
|
|
1108
|
+
console.info(`
|
|
1109
|
+
\u26A0\uFE0F Top-level await detected - CommonJS generation disabled`);
|
|
1110
|
+
console.info(` Top-level await is incompatible with CommonJS format`);
|
|
1111
|
+
console.info(` Building ESM-only (Node.js 14+ and modern bundlers supported)`);
|
|
1112
|
+
console.info(` To permanently disable CJS: remove "main" field from package.json
|
|
1113
|
+
`);
|
|
1114
|
+
options.formats.cjs = false;
|
|
1115
|
+
} else {
|
|
1116
|
+
throw error;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
850
1120
|
}
|
|
851
1121
|
}
|
|
852
1122
|
for (const umdPath of umdEntries) {
|
|
@@ -869,8 +1139,8 @@ async function build2(cwd, save = false) {
|
|
|
869
1139
|
}
|
|
870
1140
|
const autoDiscoveredFiles = [];
|
|
871
1141
|
console.info(" Generating package.json...");
|
|
872
|
-
const cleanedPkg = await cleanPackageJSON(pkg, mainEntry, options, cwd);
|
|
873
|
-
const exportsResult = generateExports(entries, mainEntry, options, pkg.exports);
|
|
1142
|
+
const cleanedPkg = await cleanPackageJSON(pkg, mainEntry, options, cwd, distDir);
|
|
1143
|
+
const exportsResult = await generateExports(entries, mainEntry, options, pkg.exports, distDir, allBinEntries);
|
|
874
1144
|
cleanedPkg.exports = fixExportsForDist(exportsResult.exports);
|
|
875
1145
|
if (exportsResult.staleExports.length > 0) {
|
|
876
1146
|
console.warn(`\u26A0\uFE0F WARNING: Found ${exportsResult.staleExports.length} stale export(s) pointing to missing src/ files:`);
|
|
@@ -971,7 +1241,10 @@ async function build2(cwd, save = false) {
|
|
|
971
1241
|
rootPkg2.main = `./dist/src/${mainEntry}.cjs`;
|
|
972
1242
|
}
|
|
973
1243
|
rootPkg2.module = `./dist/src/${mainEntry}.js`;
|
|
974
|
-
|
|
1244
|
+
const dtsPath = Path3.join(distDir, "src", `${mainEntry}.d.ts`);
|
|
1245
|
+
if (await fileExists(dtsPath)) {
|
|
1246
|
+
rootPkg2.types = `./dist/src/${mainEntry}.d.ts`;
|
|
1247
|
+
}
|
|
975
1248
|
if (rootPkg2.typings && typeof rootPkg2.typings === "string") {
|
|
976
1249
|
rootPkg2.typings = rootPkg2.typings.startsWith("./dist/") ? rootPkg2.typings : "./" + Path3.join("dist", rootPkg2.typings);
|
|
977
1250
|
}
|
|
@@ -1002,6 +1275,27 @@ async function build2(cwd, save = false) {
|
|
|
1002
1275
|
}
|
|
1003
1276
|
}
|
|
1004
1277
|
rootPkg2.exports = rootExports;
|
|
1278
|
+
if (allBinEntries.length > 0) {
|
|
1279
|
+
const generatedBin = {};
|
|
1280
|
+
for (const binEntryInfo of allBinEntries) {
|
|
1281
|
+
const binPath = binEntryInfo.source === "src" ? `./dist/src/bin/${binEntryInfo.name}.js` : `./dist/bin/${binEntryInfo.name}.js`;
|
|
1282
|
+
const fullPath = Path3.join(cwd, binPath);
|
|
1283
|
+
if (await fileExists(fullPath)) {
|
|
1284
|
+
generatedBin[binEntryInfo.name] = binPath;
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
if (Object.keys(generatedBin).length > 0) {
|
|
1288
|
+
if (rootPkg2.bin) {
|
|
1289
|
+
if (typeof rootPkg2.bin === "string") {
|
|
1290
|
+
const existingName = pkg.name?.split("/").pop() || "cli";
|
|
1291
|
+
rootPkg2.bin = { [existingName]: rootPkg2.bin };
|
|
1292
|
+
}
|
|
1293
|
+
rootPkg2.bin = { ...rootPkg2.bin, ...generatedBin };
|
|
1294
|
+
} else {
|
|
1295
|
+
rootPkg2.bin = generatedBin;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1005
1299
|
if (rootPkg2.bin) {
|
|
1006
1300
|
if (typeof rootPkg2.bin === "string") {
|
|
1007
1301
|
const distPath = rootPkg2.bin.startsWith("./dist/") ? rootPkg2.bin : rootPkg2.bin.startsWith("dist/") ? "./" + rootPkg2.bin : "./" + Path3.join("dist", rootPkg2.bin);
|
|
@@ -1064,6 +1358,10 @@ async function build2(cwd, save = false) {
|
|
|
1064
1358
|
if (save) {
|
|
1065
1359
|
rootPkg = JSON.parse(await FS3.readFile(pkgPath, "utf-8"));
|
|
1066
1360
|
}
|
|
1361
|
+
if (allBinEntries.length > 0 || fixedDistPkg.bin) {
|
|
1362
|
+
const runtimeBanner = generateRuntimeBanner(pkg);
|
|
1363
|
+
await makeFilesExecutable(fixedDistPkg, cwd, allBinEntries, runtimeBanner);
|
|
1364
|
+
}
|
|
1067
1365
|
return { distPkg: fixedDistPkg, rootPkg };
|
|
1068
1366
|
}
|
|
1069
1367
|
async function publish(cwd, save = true, extraArgs = []) {
|