robuild 0.1.6 → 0.1.8

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,3 @@
1
+ import { n as performBuild, t as build } from "./build-CGYlmT8l.mjs";
2
+
3
+ export { performBuild };
@@ -12,8 +12,8 @@ import { existsSync, promises, readFileSync, readdirSync, statSync, writeFileSyn
12
12
  import { fileURLToPath, pathToFileURL } from "node:url";
13
13
  import { gzipSync } from "node:zlib";
14
14
  import { minify } from "oxc-minify";
15
- import { consola } from "consola";
16
15
  import { createHash } from "node:crypto";
16
+ import { consola } from "consola";
17
17
  import { glob } from "glob";
18
18
  import MagicString from "magic-string";
19
19
  import { transform } from "oxc-transform";
@@ -21,95 +21,6 @@ import { glob as glob$1 } from "tinyglobby";
21
21
  import { exec } from "node:child_process";
22
22
  import { promisify } from "node:util";
23
23
 
24
- //#region src/core/logger.ts
25
- /**
26
- * Logger instance with configurable log level
27
- */
28
- var Logger = class {
29
- level = "info";
30
- warningCount = 0;
31
- errorCount = 0;
32
- constructor(level = "info") {
33
- this.level = level;
34
- this.updateConsolaLevel();
35
- }
36
- setLevel(level) {
37
- this.level = level;
38
- this.updateConsolaLevel();
39
- }
40
- updateConsolaLevel() {
41
- consola.level = {
42
- silent: 0,
43
- error: 1,
44
- warn: 2,
45
- info: 3,
46
- verbose: 4
47
- }[this.level];
48
- }
49
- silent(message, ...args) {
50
- consola.log(message, ...args);
51
- }
52
- error(message, ...args) {
53
- this.errorCount++;
54
- consola.error(message, ...args);
55
- }
56
- warn(message, ...args) {
57
- this.warningCount++;
58
- consola.warn(message, ...args);
59
- }
60
- info(message, ...args) {
61
- consola.info(message, ...args);
62
- }
63
- verbose(message, ...args) {
64
- if (this.level === "verbose") consola.debug(message, ...args);
65
- }
66
- success(message, ...args) {
67
- consola.success(message, ...args);
68
- }
69
- log(message, ...args) {
70
- consola.log(message, ...args);
71
- }
72
- /**
73
- * Debug output - only visible with INSPECT_BUILD env var
74
- */
75
- debug(message, ...args) {
76
- if (process.env.INSPECT_BUILD) consola.log(message, ...args);
77
- }
78
- getWarningCount() {
79
- return this.warningCount;
80
- }
81
- getErrorCount() {
82
- return this.errorCount;
83
- }
84
- resetCounts() {
85
- this.warningCount = 0;
86
- this.errorCount = 0;
87
- }
88
- shouldFailOnWarnings(failOnWarn) {
89
- return failOnWarn && this.warningCount > 0;
90
- }
91
- };
92
- const logger = new Logger();
93
- /**
94
- * Configure global logger
95
- */
96
- function configureLogger(level) {
97
- logger.setLevel(level);
98
- }
99
- /**
100
- * Reset warning and error counts
101
- */
102
- function resetLogCounts() {
103
- logger.resetCounts();
104
- }
105
- /**
106
- * Check if build should fail due to warnings
107
- */
108
- function shouldFailOnWarnings(failOnWarn) {
109
- return logger.shouldFailOnWarnings(failOnWarn);
110
- }
111
-
112
- //#endregion
113
24
  //#region src/utils/extensions.ts
114
25
  /**
115
26
  * Get file extension for a given format (with leading dot).
@@ -356,14 +267,16 @@ function analyzeDir(dir) {
356
267
  throw error;
357
268
  }
358
269
  }
270
+ /**
271
+ * Calculate size metrics for a built file.
272
+ * Reads the file directly from disk instead of rebuilding with rolldown.
273
+ *
274
+ * @param dir - The output directory
275
+ * @param entry - The entry filename
276
+ * @returns Size metrics (raw, minified, gzipped)
277
+ */
359
278
  async function distSize(dir, entry) {
360
- const { output } = await (await rolldown({
361
- input: join(dir, entry),
362
- plugins: [],
363
- platform: "neutral",
364
- external: (id) => id[0] !== "." && !id.startsWith(dir)
365
- })).generate({ codeSplitting: false });
366
- const code = output[0].code;
279
+ const code = readFileSync(join(dir, entry), "utf-8");
367
280
  const { code: minified } = await minify(entry, code);
368
281
  return {
369
282
  size: Buffer.byteLength(code),
@@ -371,32 +284,17 @@ async function distSize(dir, entry) {
371
284
  minGzipSize: gzipSync(minified).length
372
285
  };
373
286
  }
374
- async function sideEffectSize(dir, entry) {
375
- const { output } = await (await rolldown({
376
- input: "#entry",
377
- platform: "neutral",
378
- external: (id) => id[0] !== "." && !id.startsWith(dir),
379
- plugins: [{
380
- name: "virtual-entry",
381
- async resolveId(id, importer, opts) {
382
- if (id === "#entry") return { id };
383
- const resolved = await this.resolve(id, importer, opts);
384
- if (!resolved) return null;
385
- resolved.moduleSideEffects = null;
386
- return resolved;
387
- },
388
- load(id) {
389
- if (id === "#entry") return `import * as _lib from "${join(dir, entry)}";`;
390
- }
391
- }]
392
- })).generate({ codeSplitting: false });
393
- if (process.env.INSPECT_BUILD) {
394
- logger.debug("---------[side effects]---------");
395
- logger.debug(entry);
396
- logger.debug(output[0].code);
397
- logger.debug("-------------------------------");
398
- }
399
- return Buffer.byteLength(output[0].code.trim());
287
+ /**
288
+ * Calculate side effect size.
289
+ * For now, returns 0 as calculating true side effects requires complex analysis.
290
+ * This avoids the expensive rolldown rebuild that was causing performance issues.
291
+ *
292
+ * @param _dir - The output directory (unused)
293
+ * @param _entry - The entry filename (unused)
294
+ * @returns Side effect size (always 0 for now)
295
+ */
296
+ async function sideEffectSize(_dir, _entry) {
297
+ return 0;
400
298
  }
401
299
 
402
300
  //#endregion
@@ -541,6 +439,272 @@ function resolveExternalConfig(ctx, options) {
541
439
  return externalDeps;
542
440
  }
543
441
 
442
+ //#endregion
443
+ //#region src/features/css/index.ts
444
+ /**
445
+ * Default CSS bundle file name when splitting is disabled.
446
+ */
447
+ const defaultCssBundleName = "style.css";
448
+ /**
449
+ * Resolve CSS options with defaults.
450
+ */
451
+ function resolveCssOptions(options = {}) {
452
+ return {
453
+ splitting: options.splitting ?? true,
454
+ fileName: options.fileName ?? defaultCssBundleName,
455
+ lightningcss: options.lightningcss ?? false
456
+ };
457
+ }
458
+
459
+ //#endregion
460
+ //#region src/utils/lightningcss.ts
461
+ /**
462
+ * Converts esbuild target (which is also used by Rolldown) to Lightning CSS targets.
463
+ *
464
+ * @see https://esbuild.github.io/api/#target
465
+ * @see https://github.com/rolldown/rolldown/blob/v1.0.0-beta.8/packages/rolldown/src/binding.d.ts#L1429-L1431
466
+ * @see https://lightningcss.dev/transpilation.html
467
+ *
468
+ * @param target - Array of esbuild-format target strings (e.g., ['chrome90', 'firefox88'])
469
+ * @returns LightningCSS targets object or undefined if no valid targets found
470
+ */
471
+ function esbuildTargetToLightningCSS(target) {
472
+ let targets;
473
+ const matches = [...target.join(" ").toLowerCase().matchAll(TARGET_REGEX)];
474
+ for (const match of matches) {
475
+ const browser = ESBUILD_LIGHTNINGCSS_MAPPING[match[1]];
476
+ if (!browser) continue;
477
+ const version = match[2];
478
+ const versionInt = parseVersion(version);
479
+ if (versionInt == null) continue;
480
+ targets = targets || {};
481
+ targets[browser] = versionInt;
482
+ }
483
+ return targets;
484
+ }
485
+ const TARGET_REGEX = /([a-z]+)(\d+(?:\.\d+)*)/g;
486
+ /**
487
+ * A mapping from the name in the esbuild target format to the browser name in
488
+ * Lightning CSS targets format.
489
+ */
490
+ const ESBUILD_LIGHTNINGCSS_MAPPING = {
491
+ chrome: "chrome",
492
+ edge: "edge",
493
+ firefox: "firefox",
494
+ ie: "ie",
495
+ ios: "ios_saf",
496
+ opera: "opera",
497
+ safari: "safari"
498
+ };
499
+ /**
500
+ * Parse version string to LightningCSS version integer format.
501
+ *
502
+ * The version is encoded as: (major << 16) | (minor << 8) | patch
503
+ *
504
+ * @see https://github.com/parcel-bundler/lightningcss/blob/v1.29.3/node/browserslistToTargets.js#L35-L46
505
+ */
506
+ function parseVersion(version) {
507
+ const [major, minor = 0, patch = 0] = version.split("-")[0].split(".").map((v) => Number.parseInt(v, 10));
508
+ if (Number.isNaN(major) || Number.isNaN(minor) || Number.isNaN(patch)) return null;
509
+ return major << 16 | minor << 8 | patch;
510
+ }
511
+
512
+ //#endregion
513
+ //#region src/features/css/lightningcss.ts
514
+ /**
515
+ * Create a LightningCSS plugin for CSS minification and transformation.
516
+ *
517
+ * Uses `unplugin-lightningcss` for modern CSS processing with:
518
+ * - Automatic vendor prefixing
519
+ * - Syntax lowering based on target browsers
520
+ * - Minification
521
+ *
522
+ * @param options - Plugin options
523
+ * @returns Rolldown plugin or undefined if unplugin-lightningcss is not installed
524
+ */
525
+ async function createLightningCSSPlugin(options = {}) {
526
+ const LightningCSS = await import("unplugin-lightningcss/rolldown").catch(() => void 0);
527
+ if (!LightningCSS) return void 0;
528
+ const targetArray = options.target ? Array.isArray(options.target) ? options.target : [options.target] : void 0;
529
+ const targets = targetArray && esbuildTargetToLightningCSS(targetArray);
530
+ return LightningCSS.default({ options: targets ? { targets } : {} });
531
+ }
532
+
533
+ //#endregion
534
+ //#region src/features/css/splitting.ts
535
+ /**
536
+ * Regular expression to match CSS files.
537
+ */
538
+ const RE_CSS = /\.css$/;
539
+ /**
540
+ * CSS Code Split Plugin
541
+ *
542
+ * When css.splitting is false, this plugin merges all CSS files into a single file.
543
+ * When css.splitting is true (default), CSS code splitting is preserved.
544
+ *
545
+ * Based on Vite's implementation.
546
+ */
547
+ function createCssCodeSplitPlugin(config) {
548
+ const { splitting, fileName } = config;
549
+ if (splitting) return;
550
+ return {
551
+ name: "robuild:css:splitting",
552
+ generateBundle(_outputOptions, bundle) {
553
+ const chunks = Object.values(bundle);
554
+ const cssAssets = /* @__PURE__ */ new Map();
555
+ for (const asset of chunks) if (asset.type === "asset" && typeof asset.source === "string" && RE_CSS.test(asset.fileName)) cssAssets.set(asset.fileName, asset.source);
556
+ if (!cssAssets.size) return;
557
+ const chunkCSSMap = /* @__PURE__ */ new Map();
558
+ for (const chunk of chunks) {
559
+ if (chunk.type !== "chunk") continue;
560
+ for (const moduleId of chunk.moduleIds) if (RE_CSS.test(moduleId)) {
561
+ if (!chunkCSSMap.has(chunk.fileName)) chunkCSSMap.set(chunk.fileName, []);
562
+ break;
563
+ }
564
+ }
565
+ for (const cssFileName of cssAssets.keys()) {
566
+ const cssBaseName = normalizeCssFileName(cssFileName);
567
+ for (const chunkFileName of chunkCSSMap.keys()) if (normalizeChunkFileName(chunkFileName) === cssBaseName || chunkFileName.startsWith(`${cssBaseName}-`)) {
568
+ chunkCSSMap.get(chunkFileName).push(cssFileName);
569
+ break;
570
+ }
571
+ }
572
+ let extractedCss = "";
573
+ const collected = /* @__PURE__ */ new Set();
574
+ const dynamicImports = /* @__PURE__ */ new Set();
575
+ function collect(chunk) {
576
+ if (!chunk || chunk.type !== "chunk" || collected.has(chunk)) return;
577
+ collected.add(chunk);
578
+ chunk.imports.forEach((importName) => {
579
+ collect(bundle[importName]);
580
+ });
581
+ chunk.dynamicImports.forEach((importName) => {
582
+ dynamicImports.add(importName);
583
+ });
584
+ const files = chunkCSSMap.get(chunk.fileName);
585
+ if (files && files.length > 0) for (const filename of files) extractedCss += cssAssets.get(filename) ?? "";
586
+ }
587
+ for (const chunk of chunks) if (chunk.type === "chunk" && chunk.isEntry) collect(chunk);
588
+ for (const chunkName of dynamicImports) collect(bundle[chunkName]);
589
+ if (extractedCss) {
590
+ for (const cssFileName of cssAssets.keys()) delete bundle[cssFileName];
591
+ this.emitFile({
592
+ type: "asset",
593
+ source: extractedCss,
594
+ fileName,
595
+ originalFileName: defaultCssBundleName
596
+ });
597
+ }
598
+ }
599
+ };
600
+ }
601
+ const RE_CSS_HASH = /-[\w-]+\.css$/;
602
+ const RE_CHUNK_HASH = /-[\w-]+\.(m?js|cjs)$/;
603
+ const RE_CHUNK_EXT = /\.(m?js|cjs)$/;
604
+ /**
605
+ * Normalize CSS file name by removing hash pattern and extension.
606
+ * e.g., "async-DcjEOEdU.css" -> "async"
607
+ */
608
+ function normalizeCssFileName(cssFileName) {
609
+ return cssFileName.replace(RE_CSS_HASH, "").replace(RE_CSS, "");
610
+ }
611
+ /**
612
+ * Normalize chunk file name by removing hash pattern and extension.
613
+ * e.g., "async-CvIfFAic.mjs" -> "async"
614
+ */
615
+ function normalizeChunkFileName(chunkFileName) {
616
+ return chunkFileName.replace(RE_CHUNK_HASH, "").replace(RE_CHUNK_EXT, "");
617
+ }
618
+
619
+ //#endregion
620
+ //#region src/core/logger.ts
621
+ /**
622
+ * Logger instance with configurable log level
623
+ */
624
+ var Logger = class {
625
+ level = "info";
626
+ warningCount = 0;
627
+ errorCount = 0;
628
+ constructor(level = "info") {
629
+ this.level = level;
630
+ this.updateConsolaLevel();
631
+ }
632
+ setLevel(level) {
633
+ this.level = level;
634
+ this.updateConsolaLevel();
635
+ }
636
+ updateConsolaLevel() {
637
+ consola.level = {
638
+ silent: 0,
639
+ error: 1,
640
+ warn: 2,
641
+ info: 3,
642
+ verbose: 4
643
+ }[this.level];
644
+ }
645
+ silent(message, ...args) {
646
+ consola.log(message, ...args);
647
+ }
648
+ error(message, ...args) {
649
+ this.errorCount++;
650
+ consola.error(message, ...args);
651
+ }
652
+ warn(message, ...args) {
653
+ this.warningCount++;
654
+ consola.warn(message, ...args);
655
+ }
656
+ info(message, ...args) {
657
+ consola.info(message, ...args);
658
+ }
659
+ verbose(message, ...args) {
660
+ if (this.level === "verbose") consola.debug(message, ...args);
661
+ }
662
+ success(message, ...args) {
663
+ consola.success(message, ...args);
664
+ }
665
+ log(message, ...args) {
666
+ consola.log(message, ...args);
667
+ }
668
+ /**
669
+ * Debug output - only visible with INSPECT_BUILD env var
670
+ */
671
+ debug(message, ...args) {
672
+ if (process.env.INSPECT_BUILD) consola.log(message, ...args);
673
+ }
674
+ getWarningCount() {
675
+ return this.warningCount;
676
+ }
677
+ getErrorCount() {
678
+ return this.errorCount;
679
+ }
680
+ resetCounts() {
681
+ this.warningCount = 0;
682
+ this.errorCount = 0;
683
+ }
684
+ shouldFailOnWarnings(failOnWarn) {
685
+ return failOnWarn && this.warningCount > 0;
686
+ }
687
+ };
688
+ const logger = new Logger();
689
+ /**
690
+ * Configure global logger
691
+ */
692
+ function configureLogger(level) {
693
+ logger.setLevel(level);
694
+ }
695
+ /**
696
+ * Reset warning and error counts
697
+ */
698
+ function resetLogCounts() {
699
+ logger.resetCounts();
700
+ }
701
+ /**
702
+ * Check if build should fail due to warnings
703
+ */
704
+ function shouldFailOnWarnings(failOnWarn) {
705
+ return logger.shouldFailOnWarnings(failOnWarn);
706
+ }
707
+
544
708
  //#endregion
545
709
  //#region src/plugins/builtin/glob-import.ts
546
710
  /**
@@ -1105,6 +1269,17 @@ async function rolldownBuild(ctx, entry, hooks, config) {
1105
1269
  logger.warn("Install it with: pnpm add -D rolldown-plugin-wasm");
1106
1270
  }
1107
1271
  }
1272
+ const cssOptions = resolveCssOptions(config?.css);
1273
+ if (cssOptions.lightningcss) {
1274
+ const lightningPlugin = await createLightningCSSPlugin({ target });
1275
+ if (lightningPlugin) rolldownPlugins.push(lightningPlugin);
1276
+ else {
1277
+ logger.warn("LightningCSS is enabled but unplugin-lightningcss is not installed.");
1278
+ logger.warn("Install it with: pnpm add -D unplugin-lightningcss lightningcss");
1279
+ }
1280
+ }
1281
+ const cssSplitPlugin = createCssCodeSplitPlugin(cssOptions);
1282
+ if (cssSplitPlugin) rolldownPlugins.push(cssSplitPlugin);
1108
1283
  rolldownPlugins.push(...pluginManager.getRolldownPlugins());
1109
1284
  const moduleTypes = {};
1110
1285
  if (entry.loaders) for (const [ext, config] of Object.entries(entry.loaders)) moduleTypes[ext] = config.loader;
@@ -1130,13 +1305,15 @@ async function rolldownBuild(ctx, entry, hooks, config) {
1130
1305
  plugins: [...rolldownPlugins, ...Array.isArray(userPlugins) ? userPlugins : userPlugins ? [userPlugins] : []]
1131
1306
  };
1132
1307
  await hooks.rolldownConfig?.(baseRolldownConfig, ctx);
1133
- const allOutputEntries = [];
1134
1308
  const filePathMap = /* @__PURE__ */ new Map();
1135
- for (const format of formats) {
1309
+ const buildFormat = async (format) => {
1136
1310
  const extension = getFormatExtension(format, platform, entry.fixedExtension);
1137
1311
  const formatConfig = { ...baseRolldownConfig };
1138
1312
  if (entry.dts !== false && (format === "es" || format === "esm" || format === "module")) {
1139
- const dtsPlugins = dts({ ...entry.dts });
1313
+ const dtsPlugins = dts({
1314
+ cwd: ctx.pkgDir,
1315
+ ...typeof entry.dts === "object" ? entry.dts : {}
1316
+ });
1140
1317
  formatConfig.plugins = [...Array.isArray(formatConfig.plugins) ? formatConfig.plugins : [formatConfig.plugins], ...Array.isArray(dtsPlugins) ? dtsPlugins : [dtsPlugins]];
1141
1318
  }
1142
1319
  const res = await rolldown(formatConfig);
@@ -1187,6 +1364,7 @@ async function rolldownBuild(ctx, entry, hooks, config) {
1187
1364
  }
1188
1365
  return Array.from(deps).sort();
1189
1366
  };
1367
+ const formatOutputEntries = [];
1190
1368
  for (const chunk of output) {
1191
1369
  if (chunk.type !== "chunk" || !chunk.isEntry) continue;
1192
1370
  if (chunk.fileName.endsWith("ts")) continue;
@@ -1205,7 +1383,7 @@ async function rolldownBuild(ctx, entry, hooks, config) {
1205
1383
  finalFilePath = hashedFilePath;
1206
1384
  }
1207
1385
  filePathMap.set(finalFileName, finalFilePath);
1208
- allOutputEntries.push({
1386
+ formatOutputEntries.push({
1209
1387
  format,
1210
1388
  name: finalFileName,
1211
1389
  exports: chunk.exports,
@@ -1214,7 +1392,9 @@ async function rolldownBuild(ctx, entry, hooks, config) {
1214
1392
  sideEffectSize: await sideEffectSize(formatOutDir, finalFileName)
1215
1393
  });
1216
1394
  }
1217
- }
1395
+ return formatOutputEntries;
1396
+ };
1397
+ const allOutputEntries = (await Promise.all(formats.map(buildFormat))).flat();
1218
1398
  if (entry.dtsOnly) {
1219
1399
  const jsFilesToDelete = [];
1220
1400
  for (const outputEntry of allOutputEntries) {
@@ -1840,7 +2020,7 @@ function createBuildResult(entries, startTime) {
1840
2020
  * Perform watch build using rolldown's built-in watch mode
1841
2021
  */
1842
2022
  async function performWatchBuild(config, ctx, startTime) {
1843
- const { performBuild } = await import("./build-CelwCERM.mjs");
2023
+ const { performBuild } = await import("./build-Bw6PbOSI.mjs");
1844
2024
  await performBuild(config, ctx, startTime);
1845
2025
  const bundleEntries = (config.entries || []).filter((entry) => {
1846
2026
  if (typeof entry === "string") return !entry.endsWith("/");
@@ -2042,7 +2222,7 @@ async function performBuild(config, ctx, startTime) {
2042
2222
  await hooks.entries?.(entries, ctx);
2043
2223
  const outDirs = [];
2044
2224
  for (const outDir of entries.map((e) => e.outDir).sort()) if (!outDirs.some((dir) => outDir.startsWith(dir))) outDirs.push(outDir);
2045
- for (const entry of entries) await (entry.type === "bundle" ? rolldownBuild(ctx, entry, hooks, config) : transformDir(ctx, entry));
2225
+ await Promise.all(entries.map((entry) => entry.type === "bundle" ? rolldownBuild(ctx, entry, hooks, config) : transformDir(ctx, entry)));
2046
2226
  await hooks.end?.(ctx);
2047
2227
  if (config.exports?.enabled) {
2048
2228
  const packageExports = generatePackageExports({
@@ -2067,4 +2247,4 @@ async function readJSON(specifier) {
2067
2247
  }
2068
2248
 
2069
2249
  //#endregion
2070
- export { createBrowserShimsPlugin as a, SHEBANG_RE as c, shebangPlugin as d, nodeProtocolPlugin as f, logger as g, configureLogger as h, DEFAULT_SHIMS_CONFIG as i, hasShebang as l, hasGlobImports as m, performBuild as n, createNodeShimsPlugin as o, createGlobImportPlugin as p, createSkipNodeModulesPlugin as r, createShimsPlugin as s, build as t, makeExecutable as u };
2250
+ export { createCssCodeSplitPlugin as _, createBrowserShimsPlugin as a, resolveCssOptions as b, SHEBANG_RE as c, shebangPlugin as d, nodeProtocolPlugin as f, logger as g, configureLogger as h, DEFAULT_SHIMS_CONFIG as i, hasShebang as l, hasGlobImports as m, performBuild as n, createNodeShimsPlugin as o, createGlobImportPlugin as p, createSkipNodeModulesPlugin as r, createShimsPlugin as s, build as t, makeExecutable as u, createLightningCSSPlugin as v, esbuildTargetToLightningCSS as y };
@@ -2,7 +2,7 @@
2
2
  var package_default = {
3
3
  name: "robuild",
4
4
  type: "module",
5
- version: "0.1.6",
5
+ version: "0.1.8",
6
6
  packageManager: "pnpm@10.11.1",
7
7
  description: "Zero-config ESM/TS package builder. Powered by Rolldown and Oxc",
8
8
  license: "MIT",
@@ -49,6 +49,7 @@ var package_default = {
49
49
  "consola": "^3.4.2",
50
50
  "exsolve": "^1.0.8",
51
51
  "glob": "^13.0.6",
52
+ "jiti": "^2.6.1",
52
53
  "js-yaml": "^4.1.1",
53
54
  "magic-string": "^0.30.21",
54
55
  "minimatch": "^10.2.2",
@@ -70,10 +71,12 @@ var package_default = {
70
71
  "esno": "^4.8.0",
71
72
  "git-cz": "^4.9.0",
72
73
  "husky": "^9.1.7",
74
+ "lightningcss": "^1.31.1",
73
75
  "lint-staged": "^16.2.7",
74
76
  "oxlint": "^1.49.0",
75
77
  "rolldown-plugin-wasm": "^0.2.1",
76
78
  "turbo": "^2.8.10",
79
+ "unplugin-lightningcss": "^0.4.5",
77
80
  "vitepress": "^1.6.4",
78
81
  "vitepress-plugin-group-icons": "^1.7.1",
79
82
  "vitest": "^4.0.18"
package/dist/cli.mjs CHANGED
@@ -1,11 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { g as logger, h as configureLogger, t as build } from "./_chunks/build-rD4AllYV.mjs";
2
+ import { g as logger, h as configureLogger, t as build } from "./_chunks/build-CGYlmT8l.mjs";
3
+ import module from "node:module";
3
4
  import { colors } from "consola/utils";
4
5
  import process from "node:process";
5
6
  import { loadConfig } from "c12";
6
7
  import { cac } from "cac";
7
8
 
8
9
  //#region src/cli.ts
10
+ try {
11
+ module.enableCompileCache?.();
12
+ } catch {}
9
13
  const pkg = await import("../package.json", { with: { type: "json" } });
10
14
  const cli = cac("robuild");
11
15
  cli.version(pkg.default.version).help();
package/dist/config.d.mts CHANGED
@@ -4,6 +4,45 @@ import { Options } from "rolldown-plugin-dts";
4
4
  import { MinifyOptions as MinifyOptions$1 } from "oxc-minify";
5
5
  import { TransformOptions } from "oxc-transform";
6
6
 
7
+ //#region src/features/css/index.d.ts
8
+ /**
9
+ * CSS processing configuration options for robuild.
10
+ *
11
+ * Provides control over how CSS files are bundled and output.
12
+ */
13
+ interface CssOptions {
14
+ /**
15
+ * Enable/disable CSS code splitting.
16
+ *
17
+ * When set to `false`, all CSS in the entire project will be extracted into a single CSS file.
18
+ * When set to `true`, CSS imported in async JS chunks will be preserved as separate chunks.
19
+ *
20
+ * @default true
21
+ */
22
+ splitting?: boolean;
23
+ /**
24
+ * Specify the name of the combined CSS file when splitting is disabled.
25
+ *
26
+ * @default 'style.css'
27
+ */
28
+ fileName?: string;
29
+ /**
30
+ * Enable LightningCSS for CSS minification and transformation.
31
+ *
32
+ * LightningCSS provides modern CSS processing with automatic vendor prefixing
33
+ * and syntax lowering based on the target browsers.
34
+ *
35
+ * Requires `unplugin-lightningcss` to be installed as a peer dependency.
36
+ *
37
+ * @default false
38
+ */
39
+ lightningcss?: boolean;
40
+ }
41
+ /**
42
+ * Resolve CSS options with defaults.
43
+ */
44
+ declare function resolveCssOptions(options?: CssOptions): Required<CssOptions>;
45
+ //#endregion
7
46
  //#region src/types.d.ts
8
47
  /**
9
48
  * Target platform
@@ -12,7 +51,15 @@ type Platform = 'browser' | 'node' | 'neutral';
12
51
  /**
13
52
  * Target ES version
14
53
  */
15
- type Target = 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020' | 'es2021' | 'es2022' | 'esnext';
54
+ type EsTarget = 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020' | 'es2021' | 'es2022' | 'esnext';
55
+ /**
56
+ * Browser target for CSS vendor prefixing (e.g., 'chrome60', 'firefox60', 'safari11')
57
+ */
58
+ type BrowserTarget = string;
59
+ /**
60
+ * Build target - ES version or browser targets for CSS processing
61
+ */
62
+ type Target = EsTarget | BrowserTarget[];
16
63
  interface CopyEntry {
17
64
  from: string;
18
65
  to: string;
@@ -443,7 +490,7 @@ interface RobuildPluginContext {
443
490
  outDir: string;
444
491
  format: ModuleFormat | ModuleFormat[];
445
492
  platform: Platform;
446
- target: string;
493
+ target: Target;
447
494
  }
448
495
  /**
449
496
  * Plugin factory function type
@@ -814,6 +861,25 @@ interface BuildConfig {
814
861
  * Package exports generation configuration.
815
862
  */
816
863
  exports?: ExportsConfig;
864
+ /**
865
+ * CSS processing configuration.
866
+ *
867
+ * Controls how CSS files are bundled and processed.
868
+ *
869
+ * @example
870
+ * ```ts
871
+ * {
872
+ * css: {
873
+ * // Merge all CSS into a single file
874
+ * splitting: false,
875
+ * fileName: 'bundle.css',
876
+ * // Enable LightningCSS for modern CSS processing
877
+ * lightningcss: true,
878
+ * }
879
+ * }
880
+ * ```
881
+ */
882
+ css?: CssOptions;
817
883
  }
818
884
  interface ExportsConfig {
819
885
  /**
@@ -845,4 +911,4 @@ interface ExportsConfig {
845
911
  //#region src/config.d.ts
846
912
  declare function defineConfig(config: BuildConfig): BuildConfig;
847
913
  //#endregion
848
- export { ExportsConfig as a, LoaderType as c, RobuildPluginFactory as d, ShimsConfig as f, BundleEntry as i, RobuildPlugin as l, BuildConfig as n, GlobImportOptions as o, TransformEntry as p, BuildEntry as r, LoaderConfig as s, defineConfig as t, RobuildPluginContext as u };
914
+ export { ExportsConfig as a, LoaderType as c, RobuildPluginFactory as d, ShimsConfig as f, resolveCssOptions as g, CssOptions as h, BundleEntry as i, RobuildPlugin as l, TransformEntry as m, BuildConfig as n, GlobImportOptions as o, Target as p, BuildEntry as r, LoaderConfig as s, defineConfig as t, RobuildPluginContext as u };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
- import { a as ExportsConfig, c as LoaderType, d as RobuildPluginFactory, f as ShimsConfig, i as BundleEntry, l as RobuildPlugin, n as BuildConfig, o as GlobImportOptions, p as TransformEntry, r as BuildEntry, s as LoaderConfig, t as defineConfig, u as RobuildPluginContext } from "./config.mjs";
1
+ import { a as ExportsConfig, c as LoaderType, d as RobuildPluginFactory, f as ShimsConfig, g as resolveCssOptions, h as CssOptions, i as BundleEntry, l as RobuildPlugin, m as TransformEntry, n as BuildConfig, o as GlobImportOptions, p as Target, r as BuildEntry, s as LoaderConfig, t as defineConfig, u as RobuildPluginContext } from "./config.mjs";
2
2
  import { Plugin } from "rolldown";
3
+ import { Targets } from "lightningcss";
3
4
 
4
5
  //#region src/build.d.ts
5
6
  /**
@@ -209,4 +210,49 @@ declare class RobuildPluginManager {
209
210
  updateContext(updates: Partial<RobuildPluginContext>): void;
210
211
  }
211
212
  //#endregion
212
- export { type BuildConfig, type BuildEntry, type BundleEntry, DEFAULT_LOADERS, DEFAULT_SHIMS_CONFIG, type ExportsConfig, type RobuildPlugin, RobuildPluginManager, SHEBANG_RE, type TransformEntry, build, combinePlugins, createBrowserShimsPlugin, createCjsDefaultPlugin, createGlobImportPlugin, createLoadPlugin, createLoaderPlugin, createNodeShimsPlugin, createPluginFactory, createResolvePlugin, createRobuildPlugin, createShimsPlugin, createSkipNodeModulesPlugin, createTransformPlugin, defineConfig, extendRolldownPlugin, getLoaderForFile, hasGlobImports, hasShebang, makeExecutable, nodePolyfillsPlugin, nodeProtocolPlugin, shebangPlugin, textPlugin, urlPlugin, virtualPlugin };
213
+ //#region src/features/css/lightningcss.d.ts
214
+ interface LightningCSSPluginOptions {
215
+ /**
216
+ * Target browsers for CSS transformation.
217
+ * Uses esbuild-style target format (e.g., ['chrome90', 'firefox88']).
218
+ */
219
+ target?: Target | string[];
220
+ }
221
+ /**
222
+ * Create a LightningCSS plugin for CSS minification and transformation.
223
+ *
224
+ * Uses `unplugin-lightningcss` for modern CSS processing with:
225
+ * - Automatic vendor prefixing
226
+ * - Syntax lowering based on target browsers
227
+ * - Minification
228
+ *
229
+ * @param options - Plugin options
230
+ * @returns Rolldown plugin or undefined if unplugin-lightningcss is not installed
231
+ */
232
+ declare function createLightningCSSPlugin(options?: LightningCSSPluginOptions): Promise<Plugin | undefined>;
233
+ //#endregion
234
+ //#region src/features/css/splitting.d.ts
235
+ /**
236
+ * CSS Code Split Plugin
237
+ *
238
+ * When css.splitting is false, this plugin merges all CSS files into a single file.
239
+ * When css.splitting is true (default), CSS code splitting is preserved.
240
+ *
241
+ * Based on Vite's implementation.
242
+ */
243
+ declare function createCssCodeSplitPlugin(config: Pick<Required<CssOptions>, 'splitting' | 'fileName'>): Plugin | undefined;
244
+ //#endregion
245
+ //#region src/utils/lightningcss.d.ts
246
+ /**
247
+ * Converts esbuild target (which is also used by Rolldown) to Lightning CSS targets.
248
+ *
249
+ * @see https://esbuild.github.io/api/#target
250
+ * @see https://github.com/rolldown/rolldown/blob/v1.0.0-beta.8/packages/rolldown/src/binding.d.ts#L1429-L1431
251
+ * @see https://lightningcss.dev/transpilation.html
252
+ *
253
+ * @param target - Array of esbuild-format target strings (e.g., ['chrome90', 'firefox88'])
254
+ * @returns LightningCSS targets object or undefined if no valid targets found
255
+ */
256
+ declare function esbuildTargetToLightningCSS(target: string[]): Targets | undefined;
257
+ //#endregion
258
+ export { type BuildConfig, type BuildEntry, type BundleEntry, type CssOptions, DEFAULT_LOADERS, DEFAULT_SHIMS_CONFIG, type ExportsConfig, type LightningCSSPluginOptions, type RobuildPlugin, RobuildPluginManager, SHEBANG_RE, type TransformEntry, build, combinePlugins, createBrowserShimsPlugin, createCjsDefaultPlugin, createCssCodeSplitPlugin, createGlobImportPlugin, createLightningCSSPlugin, createLoadPlugin, createLoaderPlugin, createNodeShimsPlugin, createPluginFactory, createResolvePlugin, createRobuildPlugin, createShimsPlugin, createSkipNodeModulesPlugin, createTransformPlugin, defineConfig, esbuildTargetToLightningCSS, extendRolldownPlugin, getLoaderForFile, hasGlobImports, hasShebang, makeExecutable, nodePolyfillsPlugin, nodeProtocolPlugin, resolveCssOptions, shebangPlugin, textPlugin, urlPlugin, virtualPlugin };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as createBrowserShimsPlugin, c as SHEBANG_RE, d as shebangPlugin, f as nodeProtocolPlugin, g as logger, i as DEFAULT_SHIMS_CONFIG, l as hasShebang, m as hasGlobImports, o as createNodeShimsPlugin, p as createGlobImportPlugin, r as createSkipNodeModulesPlugin, s as createShimsPlugin, t as build, u as makeExecutable } from "./_chunks/build-rD4AllYV.mjs";
1
+ import { _ as createCssCodeSplitPlugin, a as createBrowserShimsPlugin, b as resolveCssOptions, c as SHEBANG_RE, d as shebangPlugin, f as nodeProtocolPlugin, g as logger, i as DEFAULT_SHIMS_CONFIG, l as hasShebang, m as hasGlobImports, o as createNodeShimsPlugin, p as createGlobImportPlugin, r as createSkipNodeModulesPlugin, s as createShimsPlugin, t as build, u as makeExecutable, v as createLightningCSSPlugin, y as esbuildTargetToLightningCSS } from "./_chunks/build-CGYlmT8l.mjs";
2
2
  import { t as RobuildPluginManager } from "./_chunks/manager-uQxDLzY6.mjs";
3
3
  import { t as defineConfig } from "./_chunks/config-BlC5U5aX.mjs";
4
4
  import { extname } from "node:path";
@@ -486,4 +486,4 @@ function combinePlugins(name, plugins) {
486
486
  }
487
487
 
488
488
  //#endregion
489
- export { DEFAULT_LOADERS, DEFAULT_SHIMS_CONFIG, RobuildPluginManager, SHEBANG_RE, build, combinePlugins, createBrowserShimsPlugin, createCjsDefaultPlugin, createGlobImportPlugin, createLoadPlugin, createLoaderPlugin, createNodeShimsPlugin, createPluginFactory, createResolvePlugin, createRobuildPlugin, createShimsPlugin, createSkipNodeModulesPlugin, createTransformPlugin, defineConfig, extendRolldownPlugin, getLoaderForFile, hasGlobImports, hasShebang, makeExecutable, nodePolyfillsPlugin, nodeProtocolPlugin, shebangPlugin, textPlugin, urlPlugin, virtualPlugin };
489
+ export { DEFAULT_LOADERS, DEFAULT_SHIMS_CONFIG, RobuildPluginManager, SHEBANG_RE, build, combinePlugins, createBrowserShimsPlugin, createCjsDefaultPlugin, createCssCodeSplitPlugin, createGlobImportPlugin, createLightningCSSPlugin, createLoadPlugin, createLoaderPlugin, createNodeShimsPlugin, createPluginFactory, createResolvePlugin, createRobuildPlugin, createShimsPlugin, createSkipNodeModulesPlugin, createTransformPlugin, defineConfig, esbuildTargetToLightningCSS, extendRolldownPlugin, getLoaderForFile, hasGlobImports, hasShebang, makeExecutable, nodePolyfillsPlugin, nodeProtocolPlugin, resolveCssOptions, shebangPlugin, textPlugin, urlPlugin, virtualPlugin };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "robuild",
3
3
  "type": "module",
4
- "version": "0.1.6",
4
+ "version": "0.1.8",
5
5
  "packageManager": "pnpm@10.11.1",
6
6
  "description": "Zero-config ESM/TS package builder. Powered by Rolldown and Oxc",
7
7
  "license": "MIT",
@@ -50,6 +50,7 @@
50
50
  "consola": "^3.4.2",
51
51
  "exsolve": "^1.0.8",
52
52
  "glob": "^13.0.6",
53
+ "jiti": "^2.6.1",
53
54
  "js-yaml": "^4.1.1",
54
55
  "magic-string": "^0.30.21",
55
56
  "minimatch": "^10.2.2",
@@ -71,10 +72,12 @@
71
72
  "esno": "^4.8.0",
72
73
  "git-cz": "^4.9.0",
73
74
  "husky": "^9.1.7",
75
+ "lightningcss": "^1.31.1",
74
76
  "lint-staged": "^16.2.7",
75
77
  "oxlint": "^1.49.0",
76
78
  "rolldown-plugin-wasm": "^0.2.1",
77
79
  "turbo": "^2.8.10",
80
+ "unplugin-lightningcss": "^0.4.5",
78
81
  "vitepress": "^1.6.4",
79
82
  "vitepress-plugin-group-icons": "^1.7.1",
80
83
  "vitest": "^4.0.18"
@@ -1,3 +0,0 @@
1
- import { n as performBuild, t as build } from "./build-rD4AllYV.mjs";
2
-
3
- export { performBuild };