@b9g/libuild 0.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.
@@ -0,0 +1,800 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/libuild.ts
31
+ var libuild_exports = {};
32
+ __export(libuild_exports, {
33
+ build: () => build2,
34
+ publish: () => publish,
35
+ transformSrcToDist: () => transformSrcToDist
36
+ });
37
+ module.exports = __toCommonJS(libuild_exports);
38
+ var FS2 = __toESM(require("fs/promises"), 1);
39
+ var Path2 = __toESM(require("path"), 1);
40
+ var import_child_process = require("child_process");
41
+ var ESBuild = __toESM(require("esbuild"), 1);
42
+ var TS = __toESM(require("typescript"), 1);
43
+
44
+ // src/umd-plugin.ts
45
+ var FS = __toESM(require("fs/promises"), 1);
46
+ var Path = __toESM(require("path"), 1);
47
+ var import_magic_string = __toESM(require("magic-string"), 1);
48
+ function umdPlugin(options) {
49
+ return {
50
+ name: "umd-wrapper",
51
+ setup(build3) {
52
+ build3.onEnd(async (result) => {
53
+ if (result.errors.length > 0)
54
+ return;
55
+ const outputDir = build3.initialOptions.outdir;
56
+ if (outputDir) {
57
+ const files = await FS.readdir(outputDir);
58
+ for (const file of files) {
59
+ if (file.endsWith(".js") && !file.endsWith(".js.map")) {
60
+ await wrapWithUmd(Path.join(outputDir, file), options.globalName);
61
+ }
62
+ }
63
+ }
64
+ });
65
+ }
66
+ };
67
+ }
68
+ async function wrapWithUmd(filePath, globalName) {
69
+ const code = await FS.readFile(filePath, "utf-8");
70
+ const ms = new import_magic_string.default(code);
71
+ const sourcemapComment = code.match(/\/\/# sourceMappingURL=.+$/m);
72
+ if (sourcemapComment) {
73
+ const index = code.lastIndexOf(sourcemapComment[0]);
74
+ ms.remove(index, index + sourcemapComment[0].length);
75
+ }
76
+ const exportsMatch = code.match(/\nmodule\.exports\s*=\s*([^;]+);?\s*$/);
77
+ if (exportsMatch) {
78
+ const index = code.lastIndexOf(exportsMatch[0]);
79
+ ms.overwrite(index, index + exportsMatch[0].length, `
80
+ return ${exportsMatch[1]};`);
81
+ }
82
+ const umdHeader = `(function (root, factory) {
83
+ if (typeof define === 'function' && define.amd) {
84
+ // AMD
85
+ define([], factory);
86
+ } else if (typeof module === 'object' && module.exports) {
87
+ // CommonJS
88
+ module.exports = factory();
89
+ } else {
90
+ // Browser globals
91
+ root.${globalName} = factory();
92
+ }
93
+ }(typeof self !== 'undefined' ? self : this, function () {
94
+ `;
95
+ const umdFooter = `
96
+ }));`;
97
+ ms.prepend(umdHeader);
98
+ ms.append(umdFooter);
99
+ const result = ms.toString();
100
+ const map = ms.generateMap({
101
+ file: Path.basename(filePath),
102
+ source: Path.basename(filePath).replace(".js", ".ts"),
103
+ includeContent: true
104
+ });
105
+ await FS.writeFile(filePath, result);
106
+ await FS.writeFile(filePath + ".map", map.toString());
107
+ await FS.writeFile(filePath, result + `
108
+ //# sourceMappingURL=${Path.basename(filePath)}.map`);
109
+ }
110
+
111
+ // src/libuild.ts
112
+ function isValidEntrypoint(filename) {
113
+ if (!filename.endsWith(".ts") && !filename.endsWith(".js"))
114
+ return false;
115
+ if (filename.endsWith(".d.ts"))
116
+ return false;
117
+ if (filename.startsWith("_"))
118
+ return false;
119
+ if (filename.startsWith("."))
120
+ return false;
121
+ return true;
122
+ }
123
+ async function findEntryPoints(srcDir) {
124
+ const files = await FS2.readdir(srcDir);
125
+ return files.filter(isValidEntrypoint).map((file) => Path2.basename(file, Path2.extname(file))).sort();
126
+ }
127
+ async function detectMainEntry(pkg, entries) {
128
+ if (pkg.exports && pkg.exports["."]) {
129
+ const dotExport = pkg.exports["."];
130
+ let importPath;
131
+ if (typeof dotExport === "string") {
132
+ importPath = dotExport;
133
+ } else if (typeof dotExport === "object" && dotExport.import) {
134
+ importPath = dotExport.import;
135
+ }
136
+ if (importPath) {
137
+ const match = importPath.match(/\.\/src\/([^.]+)/);
138
+ if (match && entries.includes(match[1])) {
139
+ return match[1];
140
+ }
141
+ }
142
+ }
143
+ if (pkg.main && typeof pkg.main === "string") {
144
+ const mainBase = Path2.basename(pkg.main, Path2.extname(pkg.main));
145
+ if (entries.includes(mainBase)) {
146
+ return mainBase;
147
+ }
148
+ }
149
+ if (entries.includes("index")) {
150
+ return "index";
151
+ }
152
+ if (entries.length === 1) {
153
+ return entries[0];
154
+ }
155
+ const pkgNameParts = pkg.name.split("/");
156
+ const pkgName = pkgNameParts[pkgNameParts.length - 1];
157
+ if (!pkgName) {
158
+ throw new Error(`Invalid package name: ${pkg.name}`);
159
+ }
160
+ if (entries.includes(pkgName)) {
161
+ return pkgName;
162
+ }
163
+ return entries[0];
164
+ }
165
+ function checkIfExportIsStale(exportKey, exportValue, entries) {
166
+ if (exportKey === "./package.json" || typeof exportValue === "string" && (exportValue === "./package.json" || exportValue.endsWith("/package.json"))) {
167
+ return false;
168
+ }
169
+ let entryName;
170
+ let hasInvalidPath = false;
171
+ if (typeof exportValue === "string") {
172
+ if (exportValue.match(/\.\/src\/.*\/.*\.(ts|js)$/)) {
173
+ hasInvalidPath = true;
174
+ } else {
175
+ const match = exportValue.match(/\.\/src\/([^/]+)\.(ts|js)$/);
176
+ if (match) {
177
+ const filename = match[1] + "." + match[2];
178
+ if (!isValidEntrypoint(filename)) {
179
+ hasInvalidPath = true;
180
+ } else {
181
+ entryName = match[1];
182
+ }
183
+ }
184
+ }
185
+ } else if (typeof exportValue === "object" && exportValue !== null) {
186
+ const importPath = exportValue.import || exportValue.require;
187
+ if (typeof importPath === "string") {
188
+ if (importPath.match(/\.\/src\/.*\/.*\.(ts|js|cjs)$/)) {
189
+ hasInvalidPath = true;
190
+ } else {
191
+ const match = importPath.match(/\.\/src\/([^/]+)\.(ts|js|cjs)$/);
192
+ if (match) {
193
+ const filename = match[1] + "." + match[2].replace("cjs", "js");
194
+ if (!isValidEntrypoint(filename)) {
195
+ hasInvalidPath = true;
196
+ } else {
197
+ entryName = match[1];
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+ if (!entryName && !hasInvalidPath && exportKey.startsWith("./") && exportKey !== ".") {
204
+ const keyName = exportKey.slice(2).replace(/\.js$/, "");
205
+ if (keyName && !keyName.includes("/")) {
206
+ entryName = keyName;
207
+ }
208
+ }
209
+ if (hasInvalidPath) {
210
+ return false;
211
+ }
212
+ return entryName ? !entries.includes(entryName) : false;
213
+ }
214
+ function generateExports(entries, mainEntry, options, existingExports = {}) {
215
+ const exports2 = {};
216
+ const staleExports = [];
217
+ function createExportEntry(entry) {
218
+ const exportEntry = {
219
+ types: `./src/${entry}.d.ts`,
220
+ import: `./src/${entry}.js`
221
+ };
222
+ if (options.formats.cjs) {
223
+ exportEntry.require = `./src/${entry}.cjs`;
224
+ }
225
+ return exportEntry;
226
+ }
227
+ function expandExistingExport(existing, entryFromPath) {
228
+ var _a;
229
+ if (typeof existing === "string") {
230
+ if (existing === "./package.json" || existing.endsWith("/package.json")) {
231
+ return existing;
232
+ }
233
+ const match = existing.match(/\.\/src\/([^/]+\.(?:ts|js))$/);
234
+ if (match) {
235
+ const filename = match[1];
236
+ if (!isValidEntrypoint(filename)) {
237
+ throw new Error(`Export path '${existing}' references '${filename}' which is not a valid entrypoint. Valid entrypoints cannot start with '_' or '.' and must be .ts/.js files in src/.`);
238
+ }
239
+ const entry = Path2.basename(filename, Path2.extname(filename));
240
+ return options.formats.cjs ? {
241
+ types: `./src/${entry}.d.ts`,
242
+ import: existing,
243
+ require: `./src/${entry}.cjs`
244
+ } : {
245
+ types: `./src/${entry}.d.ts`,
246
+ import: existing
247
+ };
248
+ }
249
+ if (entryFromPath) {
250
+ return options.formats.cjs ? {
251
+ types: `./src/${entryFromPath}.d.ts`,
252
+ import: existing,
253
+ require: `./src/${entryFromPath}.cjs`
254
+ } : {
255
+ types: `./src/${entryFromPath}.d.ts`,
256
+ import: existing
257
+ };
258
+ }
259
+ throw new Error(`Export path '${existing}' must point to a valid entrypoint in src/ (e.g., './src/utils.js'). Nested directories and internal files (starting with '_' or '.') are not allowed.`);
260
+ } else if (typeof existing === "object" && existing !== null) {
261
+ if (options.formats.cjs && !existing.require && existing.import) {
262
+ const match = (_a = existing.import) == null ? void 0 : _a.match(/\.\/src\/([^/]+\.(?:ts|js))$/);
263
+ if (match) {
264
+ const filename = match[1];
265
+ if (!isValidEntrypoint(filename)) {
266
+ throw new Error(`Export import path '${existing.import}' references '${filename}' which is not a valid entrypoint. Valid entrypoints cannot start with '_' or '.' and must be .ts/.js files in src/.`);
267
+ }
268
+ const entry = Path2.basename(filename, Path2.extname(filename));
269
+ return {
270
+ ...existing,
271
+ types: existing.types || `./src/${entry}.d.ts`,
272
+ require: `./src/${entry}.cjs`
273
+ };
274
+ }
275
+ if (entryFromPath) {
276
+ return {
277
+ ...existing,
278
+ types: existing.types || `./src/${entryFromPath}.d.ts`,
279
+ require: `./src/${entryFromPath}.cjs`
280
+ };
281
+ }
282
+ throw new Error(`Export import path '${existing.import}' must point to a valid entrypoint in src/ (e.g., './src/utils.js'). Nested directories and internal files are not allowed.`);
283
+ }
284
+ return {
285
+ types: existing.types || `./src/${entryFromPath}.d.ts`,
286
+ ...existing
287
+ };
288
+ }
289
+ return existing;
290
+ }
291
+ for (const [key, value] of Object.entries(existingExports)) {
292
+ const isStale = checkIfExportIsStale(key, value, entries);
293
+ if (isStale) {
294
+ staleExports.push(key);
295
+ } else {
296
+ exports2[key] = expandExistingExport(value);
297
+ }
298
+ }
299
+ if (!exports2["."]) {
300
+ exports2["."] = createExportEntry(mainEntry);
301
+ } else {
302
+ exports2["."] = expandExistingExport(exports2["."], mainEntry);
303
+ }
304
+ for (const entry of entries) {
305
+ if (entry === "umd")
306
+ continue;
307
+ const key = `./${entry}`;
308
+ if (!exports2[key]) {
309
+ exports2[key] = createExportEntry(entry);
310
+ } else {
311
+ exports2[key] = expandExistingExport(exports2[key], entry);
312
+ }
313
+ if (!exports2[`${key}.js`]) {
314
+ exports2[`${key}.js`] = exports2[key];
315
+ }
316
+ if (entry === "jsx-runtime") {
317
+ if (!exports2["./jsx-dev-runtime"]) {
318
+ exports2["./jsx-dev-runtime"] = exports2[key];
319
+ }
320
+ if (!exports2["./jsx-dev-runtime.js"]) {
321
+ exports2["./jsx-dev-runtime.js"] = exports2[key];
322
+ }
323
+ }
324
+ }
325
+ if (options.formats.umd && !exports2["./umd"]) {
326
+ exports2["./umd"] = {
327
+ require: "./src/umd.js"
328
+ };
329
+ if (!exports2["./umd.js"]) {
330
+ exports2["./umd.js"] = exports2["./umd"];
331
+ }
332
+ }
333
+ if (!exports2["./package.json"]) {
334
+ exports2["./package.json"] = "./package.json";
335
+ }
336
+ return { exports: exports2, staleExports };
337
+ }
338
+ function transformSrcToDist(value) {
339
+ if (typeof value === "string") {
340
+ if (value.startsWith("src/") || value === "src") {
341
+ return "./" + value;
342
+ }
343
+ return value;
344
+ } else if (Array.isArray(value)) {
345
+ return value.map(transformSrcToDist);
346
+ } else if (typeof value === "object" && value !== null) {
347
+ const transformed = {};
348
+ for (const [key, val] of Object.entries(value)) {
349
+ transformed[key] = transformSrcToDist(val);
350
+ }
351
+ return transformed;
352
+ }
353
+ return value;
354
+ }
355
+ function fixExportsForDist(obj) {
356
+ if (typeof obj === "string") {
357
+ if (obj.includes("/dist/") && obj.includes("/src/")) {
358
+ const match = obj.match(/.*\/src\/(.*)$/);
359
+ if (match) {
360
+ return `./src/${match[1]}`;
361
+ }
362
+ }
363
+ if (obj.startsWith("./dist/src/")) {
364
+ return obj.replace("./dist/src/", "./src/");
365
+ }
366
+ if (obj.includes("/dist/") && obj.endsWith("/package.json")) {
367
+ return "./package.json";
368
+ }
369
+ return obj;
370
+ } else if (Array.isArray(obj)) {
371
+ return obj.map(fixExportsForDist);
372
+ } else if (typeof obj === "object" && obj !== null) {
373
+ const fixed = {};
374
+ for (const [key, val] of Object.entries(obj)) {
375
+ if (key === "files" && Array.isArray(val)) {
376
+ fixed[key] = val.filter((file) => file !== "dist/" && file !== "dist").concat(val.includes("dist/") || val.includes("dist") ? ["src/"] : []);
377
+ } else {
378
+ fixed[key] = fixExportsForDist(val);
379
+ }
380
+ }
381
+ return fixed;
382
+ }
383
+ return obj;
384
+ }
385
+ function cleanPackageJSON(pkg, mainEntry, options) {
386
+ const cleaned = {
387
+ name: pkg.name,
388
+ version: pkg.version
389
+ };
390
+ const fieldsToKeep = [
391
+ "description",
392
+ "keywords",
393
+ "author",
394
+ "contributors",
395
+ "maintainers",
396
+ "license",
397
+ "repository",
398
+ "bugs",
399
+ "homepage",
400
+ "funding",
401
+ "bin",
402
+ "scripts",
403
+ "dependencies",
404
+ "peerDependencies",
405
+ "optionalDependencies",
406
+ "bundledDependencies",
407
+ "engines",
408
+ "cpu",
409
+ "os",
410
+ "type",
411
+ "types",
412
+ "files",
413
+ "sideEffects",
414
+ "browserslist"
415
+ ];
416
+ const pathFields = ["files", "types", "scripts"];
417
+ for (const field of fieldsToKeep) {
418
+ if (pkg[field] !== void 0) {
419
+ if (field === "scripts") {
420
+ const npmLifecycleScripts = ["postinstall", "preinstall", "install", "preuninstall", "postuninstall", "shrinkwrap"];
421
+ const filteredScripts = {};
422
+ for (const [scriptName, scriptValue] of Object.entries(pkg[field] || {})) {
423
+ if (npmLifecycleScripts.includes(scriptName)) {
424
+ filteredScripts[scriptName] = scriptValue;
425
+ }
426
+ }
427
+ if (Object.keys(filteredScripts).length > 0) {
428
+ cleaned[field] = transformSrcToDist(filteredScripts);
429
+ }
430
+ } else if (field === "bin") {
431
+ cleaned[field] = transformSrcToDist(pkg[field]);
432
+ } else if (pathFields.includes(field)) {
433
+ cleaned[field] = transformSrcToDist(pkg[field]);
434
+ } else {
435
+ cleaned[field] = pkg[field];
436
+ }
437
+ }
438
+ }
439
+ if (!cleaned.type) {
440
+ cleaned.type = "module";
441
+ }
442
+ if (options.formats.cjs) {
443
+ cleaned.main = `src/${mainEntry}.cjs`;
444
+ }
445
+ cleaned.module = `src/${mainEntry}.js`;
446
+ cleaned.types = `src/${mainEntry}.d.ts`;
447
+ return cleaned;
448
+ }
449
+ async function fileExists(filePath) {
450
+ try {
451
+ await FS2.access(filePath);
452
+ return true;
453
+ } catch {
454
+ return false;
455
+ }
456
+ }
457
+ async function build2(cwd, save = false) {
458
+ console.log("Building with libuild...");
459
+ const srcDir = Path2.join(cwd, "src");
460
+ const distDir = Path2.join(cwd, "dist");
461
+ const distSrcDir = Path2.join(distDir, "src");
462
+ if (!await fileExists(srcDir)) {
463
+ throw new Error("No src/ directory found");
464
+ }
465
+ const pkgPath = Path2.join(cwd, "package.json");
466
+ const pkg = JSON.parse(await FS2.readFile(pkgPath, "utf-8"));
467
+ if (!pkg.private) {
468
+ console.warn("\u26A0\uFE0F WARNING: Root package.json is not private - this could lead to accidental publishing of development package.json");
469
+ console.warn(" Consider setting 'private: true' in your root package.json");
470
+ }
471
+ const gitignorePath = Path2.join(cwd, ".gitignore");
472
+ if (await fileExists(gitignorePath)) {
473
+ const gitignoreContent = await FS2.readFile(gitignorePath, "utf-8");
474
+ const isDistIgnored = gitignoreContent.includes("dist/") || gitignoreContent.includes("/dist") || gitignoreContent.includes("dist\n") || gitignoreContent.includes("dist\r\n");
475
+ if (!isDistIgnored) {
476
+ console.warn("\u26A0\uFE0F WARNING: dist/ directory is not in .gitignore - built files should not be committed");
477
+ console.warn(" Add 'dist/' to your .gitignore file");
478
+ }
479
+ }
480
+ const entries = await findEntryPoints(srcDir);
481
+ if (entries.length === 0) {
482
+ throw new Error("No entry points found in src/");
483
+ }
484
+ const options = {
485
+ formats: {
486
+ esm: true,
487
+ // Always build ESM
488
+ cjs: !!pkg.main,
489
+ // Generate CJS only if main field exists
490
+ umd: entries.includes("umd")
491
+ }
492
+ };
493
+ const mainEntry = await detectMainEntry(pkg, entries);
494
+ console.log(" Found entries:", entries.join(", "));
495
+ console.log(" Main entry:", mainEntry);
496
+ if (options.formats.cjs) {
497
+ console.log(" Formats: ESM, CJS" + (options.formats.umd ? ", UMD" : ""));
498
+ } else {
499
+ console.log(" Formats: ESM" + (options.formats.umd ? ", UMD" : "") + " (no main field - CJS disabled)");
500
+ }
501
+ if (await fileExists(distDir)) {
502
+ await FS2.rm(distDir, { recursive: true });
503
+ }
504
+ await FS2.mkdir(distDir, { recursive: true });
505
+ const entryPoints = [];
506
+ const umdEntries = [];
507
+ for (const entry of entries) {
508
+ const entryPath = Path2.join(srcDir, `${entry}.ts`);
509
+ const jsEntryPath = Path2.join(srcDir, `${entry}.js`);
510
+ const actualPath = await fileExists(entryPath) ? entryPath : jsEntryPath;
511
+ if (!await fileExists(actualPath)) {
512
+ throw new Error(`Entry point file not found: ${actualPath}. Expected ${entry}.ts or ${entry}.js in src/ directory.`);
513
+ }
514
+ if (entry === "umd") {
515
+ umdEntries.push(actualPath);
516
+ } else {
517
+ entryPoints.push(actualPath);
518
+ }
519
+ }
520
+ if (entryPoints.length > 0) {
521
+ console.log(` Building ${entryPoints.length} entries (ESM)...`);
522
+ await ESBuild.build({
523
+ entryPoints,
524
+ outdir: distSrcDir,
525
+ format: "esm",
526
+ entryNames: "[name]",
527
+ outExtension: { ".js": ".js" },
528
+ bundle: true,
529
+ splitting: true,
530
+ // Enable shared chunk extraction
531
+ minify: false,
532
+ sourcemap: true,
533
+ external: Object.keys(pkg.dependencies || {}),
534
+ platform: "node",
535
+ target: "node16"
536
+ });
537
+ if (options.formats.cjs) {
538
+ console.log(` Building ${entryPoints.length} entries (CJS)...`);
539
+ await ESBuild.build({
540
+ entryPoints,
541
+ outdir: distSrcDir,
542
+ format: "cjs",
543
+ entryNames: "[name]",
544
+ outExtension: { ".js": ".cjs" },
545
+ bundle: true,
546
+ minify: false,
547
+ sourcemap: true,
548
+ external: Object.keys(pkg.dependencies || {}),
549
+ platform: "node",
550
+ target: "node16"
551
+ // Note: CJS doesn't support splitting, but building together still helps with consistency
552
+ });
553
+ }
554
+ }
555
+ for (const umdPath of umdEntries) {
556
+ const entry = Path2.basename(umdPath, Path2.extname(umdPath));
557
+ console.log(` Building ${entry} (UMD)...`);
558
+ const globalName = pkg.name.includes("/") ? pkg.name.split("/").pop().replace(/-/g, "").charAt(0).toUpperCase() + pkg.name.split("/").pop().replace(/-/g, "").slice(1) : pkg.name.replace(/-/g, "").charAt(0).toUpperCase() + pkg.name.replace(/-/g, "").slice(1);
559
+ await ESBuild.build({
560
+ entryPoints: [umdPath],
561
+ outdir: distSrcDir,
562
+ format: "cjs",
563
+ entryNames: "[name]",
564
+ bundle: true,
565
+ minify: false,
566
+ sourcemap: true,
567
+ external: Object.keys(pkg.dependencies || {}),
568
+ platform: "node",
569
+ target: "node16",
570
+ plugins: [umdPlugin({ globalName })]
571
+ });
572
+ }
573
+ console.log(" Generating TypeScript declarations...");
574
+ const allTsFiles = [...entryPoints, ...umdEntries].filter((file) => file.endsWith(".ts"));
575
+ if (allTsFiles.length > 0) {
576
+ const compilerOptions = {
577
+ declaration: true,
578
+ emitDeclarationOnly: true,
579
+ outDir: distSrcDir,
580
+ rootDir: srcDir,
581
+ skipLibCheck: true,
582
+ esModuleInterop: true,
583
+ target: TS.ScriptTarget.ES2020,
584
+ module: TS.ModuleKind.ESNext
585
+ };
586
+ const program = TS.createProgram(allTsFiles, compilerOptions);
587
+ const emitResult = program.emit();
588
+ if (emitResult.diagnostics.length > 0) {
589
+ const diagnostics = TS.formatDiagnosticsWithColorAndContext(emitResult.diagnostics, {
590
+ getCanonicalFileName: (path) => path,
591
+ getCurrentDirectory: () => cwd,
592
+ getNewLine: () => "\n"
593
+ });
594
+ throw new Error(`TypeScript declaration generation failed:
595
+ ${diagnostics}`);
596
+ }
597
+ }
598
+ for (const entry of entries) {
599
+ if (entry === "umd")
600
+ continue;
601
+ const jsPath = Path2.join(distSrcDir, `${entry}.js`);
602
+ const dtsPath = Path2.join(distSrcDir, `${entry}.d.ts`);
603
+ if (await fileExists(jsPath) && await fileExists(dtsPath)) {
604
+ const content = await FS2.readFile(jsPath, "utf-8");
605
+ await FS2.writeFile(jsPath, `/// <reference types="./${entry}.d.ts" />
606
+ ${content}`);
607
+ }
608
+ }
609
+ const autoDiscoveredFiles = [];
610
+ console.log(" Generating package.json...");
611
+ const cleanedPkg = cleanPackageJSON(pkg, mainEntry, options);
612
+ const exportsResult = generateExports(entries, mainEntry, options, pkg.exports);
613
+ cleanedPkg.exports = fixExportsForDist(exportsResult.exports);
614
+ if (exportsResult.staleExports.length > 0) {
615
+ console.warn(`\u26A0\uFE0F WARNING: Found ${exportsResult.staleExports.length} stale export(s) pointing to missing src/ files:`);
616
+ for (const staleExport of exportsResult.staleExports) {
617
+ console.warn(` - ${staleExport}`);
618
+ }
619
+ if (save) {
620
+ console.log(" Removing stale exports from root package.json (--save mode)");
621
+ } else {
622
+ console.warn(" Use --save to remove these from root package.json");
623
+ }
624
+ }
625
+ if (cleanedPkg.files && Array.isArray(cleanedPkg.files)) {
626
+ for (const autoFile of autoDiscoveredFiles) {
627
+ if (!cleanedPkg.files.includes(autoFile)) {
628
+ cleanedPkg.files.push(autoFile);
629
+ }
630
+ }
631
+ }
632
+ const fixedDistPkg = fixExportsForDist(cleanedPkg);
633
+ await FS2.writeFile(
634
+ Path2.join(distDir, "package.json"),
635
+ JSON.stringify(fixedDistPkg, null, 2) + "\n"
636
+ );
637
+ const defaultFilesToCopy = ["README.md", "LICENSE", "CHANGELOG.md"];
638
+ for (const file of defaultFilesToCopy) {
639
+ const srcPath = Path2.join(cwd, file);
640
+ if (await fileExists(srcPath)) {
641
+ console.log(` Copying ${file}...`);
642
+ await FS2.copyFile(srcPath, Path2.join(distDir, file));
643
+ }
644
+ }
645
+ const commonFiles = ["README.md", "LICENSE", "CHANGELOG.md", "COPYING", "AUTHORS"];
646
+ if (pkg.files && Array.isArray(pkg.files)) {
647
+ for (const commonFile of commonFiles) {
648
+ const commonPath = Path2.join(cwd, commonFile);
649
+ if (await fileExists(commonPath) && !pkg.files.includes(commonFile)) {
650
+ console.log(` Auto-discovered ${commonFile}, adding to files field...`);
651
+ pkg.files.push(commonFile);
652
+ autoDiscoveredFiles.push(commonFile);
653
+ }
654
+ }
655
+ }
656
+ if (pkg.files && Array.isArray(pkg.files)) {
657
+ console.log(" Copying files from package.json files field...");
658
+ for (const pattern of pkg.files) {
659
+ if (typeof pattern === "string" && (pattern.includes("src") || pattern.includes("dist"))) {
660
+ continue;
661
+ }
662
+ if (typeof pattern === "string") {
663
+ const srcPath = Path2.join(cwd, pattern);
664
+ const destPath = Path2.join(distDir, pattern);
665
+ if (await fileExists(srcPath)) {
666
+ const stat2 = await FS2.stat(srcPath);
667
+ if (stat2.isDirectory()) {
668
+ console.log(` Copying directory ${pattern}/...`);
669
+ await FS2.mkdir(Path2.dirname(destPath), { recursive: true });
670
+ await FS2.cp(srcPath, destPath, { recursive: true });
671
+ } else {
672
+ console.log(` Copying ${pattern}...`);
673
+ await FS2.mkdir(Path2.dirname(destPath), { recursive: true });
674
+ await FS2.copyFile(srcPath, destPath);
675
+ }
676
+ } else if (pattern.includes("*")) {
677
+ const baseDir = pattern.split("*")[0].replace(/\/$/, "");
678
+ if (baseDir && await fileExists(Path2.join(cwd, baseDir))) {
679
+ console.log(` Copying pattern ${pattern}...`);
680
+ const baseSrcPath = Path2.join(cwd, baseDir);
681
+ const baseDestPath = Path2.join(distDir, baseDir);
682
+ await FS2.mkdir(Path2.dirname(baseDestPath), { recursive: true });
683
+ await FS2.cp(baseSrcPath, baseDestPath, { recursive: true });
684
+ } else {
685
+ throw new Error(`Pattern base directory not found for "${pattern}". Expected directory: ${Path2.join(cwd, baseDir)}`);
686
+ }
687
+ } else {
688
+ throw new Error(`File specified in files field not found: ${srcPath}. Remove "${pattern}" from package.json files field or create the file.`);
689
+ }
690
+ } else {
691
+ throw new Error(`Invalid files field entry: ${JSON.stringify(pattern)}. Files field entries must be strings.`);
692
+ }
693
+ }
694
+ }
695
+ if (save) {
696
+ console.log(" Updating root package.json...");
697
+ const rootPkg2 = { ...pkg };
698
+ rootPkg2.private = true;
699
+ if (options.formats.cjs) {
700
+ rootPkg2.main = `./dist/src/${mainEntry}.cjs`;
701
+ }
702
+ rootPkg2.module = `./dist/src/${mainEntry}.js`;
703
+ rootPkg2.types = `./dist/src/${mainEntry}.d.ts`;
704
+ if (rootPkg2.typings && typeof rootPkg2.typings === "string") {
705
+ rootPkg2.typings = rootPkg2.typings.startsWith("./dist/") ? rootPkg2.typings : "./" + Path2.join("dist", rootPkg2.typings);
706
+ }
707
+ const rootExports = {};
708
+ for (const [key, value] of Object.entries(cleanedPkg.exports)) {
709
+ if (typeof value === "string") {
710
+ rootExports[key] = value.startsWith("./dist/") ? value : `./dist${value.startsWith(".") ? value.slice(1) : value}`;
711
+ } else if (typeof value === "object" && value !== null) {
712
+ rootExports[key] = {};
713
+ for (const [subKey, subValue] of Object.entries(value)) {
714
+ if (typeof subValue === "string") {
715
+ rootExports[key][subKey] = subValue.startsWith("./dist/") ? subValue : `./dist${subValue.startsWith(".") ? subValue.slice(1) : subValue}`;
716
+ }
717
+ }
718
+ }
719
+ }
720
+ rootPkg2.exports = rootExports;
721
+ if (rootPkg2.bin) {
722
+ if (typeof rootPkg2.bin === "string") {
723
+ if (!rootPkg2.bin.startsWith("./dist/")) {
724
+ rootPkg2.bin = "./" + Path2.join("dist", rootPkg2.bin);
725
+ }
726
+ } else {
727
+ for (const [name, binPath] of Object.entries(rootPkg2.bin)) {
728
+ if (typeof binPath === "string" && !binPath.startsWith("./dist/")) {
729
+ rootPkg2.bin[name] = "./" + Path2.join("dist", binPath);
730
+ }
731
+ }
732
+ }
733
+ }
734
+ if (pkg.files !== void 0) {
735
+ if (!rootPkg2.files) {
736
+ rootPkg2.files = [];
737
+ } else if (!Array.isArray(rootPkg2.files)) {
738
+ rootPkg2.files = [rootPkg2.files];
739
+ }
740
+ for (const autoFile of autoDiscoveredFiles) {
741
+ if (!rootPkg2.files.includes(autoFile)) {
742
+ rootPkg2.files.push(autoFile);
743
+ }
744
+ }
745
+ if (!rootPkg2.files.includes("dist/") && !rootPkg2.files.includes("dist")) {
746
+ rootPkg2.files.push("dist/");
747
+ }
748
+ }
749
+ await FS2.writeFile(pkgPath, JSON.stringify(rootPkg2, null, 2) + "\n");
750
+ } else {
751
+ console.log(" Skipping root package.json update (use --save to enable)");
752
+ }
753
+ console.log("\nBuild complete!");
754
+ console.log(`
755
+ Output: ${distDir}`);
756
+ console.log(`
757
+ Entries: ${entries.length}`);
758
+ if (options.formats.cjs) {
759
+ console.log(`
760
+ Formats: ESM, CJS${options.formats.umd ? ", UMD" : ""}`);
761
+ } else {
762
+ console.log(`
763
+ Formats: ESM${options.formats.umd ? ", UMD" : ""}`);
764
+ }
765
+ let rootPkg = pkg;
766
+ if (save) {
767
+ rootPkg = JSON.parse(await FS2.readFile(pkgPath, "utf-8"));
768
+ }
769
+ return { distPkg: fixedDistPkg, rootPkg };
770
+ }
771
+ async function publish(cwd, save = true) {
772
+ await build2(cwd, save);
773
+ console.log("\nPublishing to npm...");
774
+ const distDir = Path2.join(cwd, "dist");
775
+ const distPkgPath = Path2.join(distDir, "package.json");
776
+ if (!await fileExists(distPkgPath)) {
777
+ throw new Error("No dist/package.json found. Run 'libuild build' first.");
778
+ }
779
+ const proc = (0, import_child_process.spawn)("npm", ["publish"], {
780
+ cwd: distDir,
781
+ stdio: "inherit"
782
+ });
783
+ const exitCode = await new Promise((resolve) => {
784
+ proc.on("close", resolve);
785
+ });
786
+ if (exitCode === 0) {
787
+ const distPkg = JSON.parse(await FS2.readFile(distPkgPath, "utf-8"));
788
+ console.log(`
789
+ Published ${distPkg.name}@${distPkg.version}!`);
790
+ } else {
791
+ throw new Error("npm publish failed");
792
+ }
793
+ }
794
+ // Annotate the CommonJS export names for ESM import in node:
795
+ 0 && (module.exports = {
796
+ build,
797
+ publish,
798
+ transformSrcToDist
799
+ });
800
+ //# sourceMappingURL=libuild.cjs.map