@nasti-toolchain/nasti 1.3.10 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ var __export = (target, all) => {
9
9
  };
10
10
 
11
11
  // src/config/defaults.ts
12
- var defaultResolve, defaultServer, defaultBuild, defaults;
12
+ var defaultResolve, defaultServer, defaultBuild, defaultElectron, defaults;
13
13
  var init_defaults = __esm({
14
14
  "src/config/defaults.ts"() {
15
15
  "use strict";
@@ -37,14 +37,29 @@ var init_defaults = __esm({
37
37
  rolldownOptions: {},
38
38
  emptyOutDir: true
39
39
  };
40
+ defaultElectron = {
41
+ main: "src/electron/main.ts",
42
+ preload: "src/electron/preload.ts",
43
+ renderer: "index.html",
44
+ nodeTarget: "node22",
45
+ mainFormat: "cjs",
46
+ preloadFormat: "cjs",
47
+ electronPath: "",
48
+ electronArgs: [],
49
+ autoRestart: true,
50
+ minVersion: 41,
51
+ external: ["electron"]
52
+ };
40
53
  defaults = {
41
54
  root: ".",
42
55
  base: "/",
43
56
  mode: "development",
57
+ target: "web",
44
58
  framework: "auto",
45
59
  resolve: defaultResolve,
46
60
  server: defaultServer,
47
61
  build: defaultBuild,
62
+ electron: defaultElectron,
48
63
  plugins: [],
49
64
  envPrefix: ["NASTI_", "VITE_"],
50
65
  logLevel: "info"
@@ -123,6 +138,7 @@ async function resolveConfig(inlineConfig = {}, command) {
123
138
  root,
124
139
  base: merged.base ?? defaults.base,
125
140
  mode: command === "build" ? "production" : "development",
141
+ target: merged.target ?? defaults.target,
126
142
  framework: merged.framework ?? defaults.framework,
127
143
  command,
128
144
  resolve: {
@@ -135,6 +151,7 @@ async function resolveConfig(inlineConfig = {}, command) {
135
151
  plugins: [],
136
152
  server: { ...defaults.server, ...merged.server },
137
153
  build: { ...defaults.build, ...merged.build },
154
+ electron: { ...defaults.electron, ...merged.electron },
138
155
  envPrefix: Array.isArray(merged.envPrefix) ? merged.envPrefix : merged.envPrefix ? [merged.envPrefix] : [...defaults.envPrefix],
139
156
  logLevel: merged.logLevel ?? defaults.logLevel
140
157
  };
@@ -749,8 +766,8 @@ async function bundlePackageAsEsm(entryFile) {
749
766
  return esmBundleCache.get(entryFile);
750
767
  }
751
768
  async function doBundlePackage(entryFile) {
752
- const { rolldown: rolldown2 } = await import("rolldown");
753
- const bundle = await rolldown2({
769
+ const { rolldown: rolldown4 } = await import("rolldown");
770
+ const bundle = await rolldown4({
754
771
  input: entryFile,
755
772
  // 仅将其他 npm 包外部化;相对路径(包内部文件)全部内联打包
756
773
  external: (id) => {
@@ -799,8 +816,8 @@ function rewriteExternalRequires(code) {
799
816
  }
800
817
  async function injectCjsNamedExports(code, entryFile) {
801
818
  try {
802
- const { createRequire: createRequire2 } = await import("module");
803
- const req = createRequire2(entryFile);
819
+ const { createRequire: createRequire3 } = await import("module");
820
+ const req = createRequire3(entryFile);
804
821
  const cjsExports = req(entryFile);
805
822
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
806
823
  const namedKeys = Object.keys(cjsExports).filter(
@@ -1423,10 +1440,11 @@ async function createServer(inlineConfig = {}) {
1423
1440
  let currentPort = finalPort;
1424
1441
  const onListening = () => {
1425
1442
  const actualPort = httpServer.address()?.port ?? currentPort;
1443
+ config.server.port = actualPort;
1426
1444
  const localUrl = `http://localhost:${actualPort}`;
1427
1445
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1428
1446
  console.log();
1429
- console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.3.10"}`));
1447
+ console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.4.0"}`));
1430
1448
  console.log();
1431
1449
  console.log(` ${pc.green(">")} Local: ${pc.cyan(localUrl)}`);
1432
1450
  if (networkUrl) {
@@ -1488,6 +1506,45 @@ var init_server = __esm({
1488
1506
  }
1489
1507
  });
1490
1508
 
1509
+ // src/plugins/electron.ts
1510
+ import { builtinModules } from "module";
1511
+ function electronPlugin(config) {
1512
+ const external = /* @__PURE__ */ new Set([
1513
+ ...ELECTRON_MODULES,
1514
+ ...NODE_BUILTINS,
1515
+ ...config.electron.external ?? []
1516
+ ]);
1517
+ return {
1518
+ name: "nasti:electron",
1519
+ enforce: "pre",
1520
+ resolveId(source) {
1521
+ if (external.has(source)) {
1522
+ return { id: source, external: true };
1523
+ }
1524
+ if (source.startsWith("electron/")) {
1525
+ return { id: source, external: true };
1526
+ }
1527
+ return null;
1528
+ }
1529
+ };
1530
+ }
1531
+ var NODE_BUILTINS, ELECTRON_MODULES;
1532
+ var init_electron = __esm({
1533
+ "src/plugins/electron.ts"() {
1534
+ "use strict";
1535
+ NODE_BUILTINS = /* @__PURE__ */ new Set([
1536
+ ...builtinModules,
1537
+ ...builtinModules.map((m) => `node:${m}`)
1538
+ ]);
1539
+ ELECTRON_MODULES = /* @__PURE__ */ new Set([
1540
+ "electron",
1541
+ "electron/main",
1542
+ "electron/common",
1543
+ "electron/renderer"
1544
+ ]);
1545
+ }
1546
+ });
1547
+
1491
1548
  // src/build/index.ts
1492
1549
  var build_exports = {};
1493
1550
  __export(build_exports, {
@@ -1500,7 +1557,7 @@ import pc2 from "picocolors";
1500
1557
  async function build(inlineConfig = {}) {
1501
1558
  const config = await resolveConfig(inlineConfig, "build");
1502
1559
  const startTime = performance.now();
1503
- console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.3.10"}`));
1560
+ console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.4.0"}`));
1504
1561
  console.log(pc2.dim(` root: ${config.root}`));
1505
1562
  console.log(pc2.dim(` mode: ${config.mode}`));
1506
1563
  const outDir = path10.resolve(config.root, config.build.outDir);
@@ -1645,9 +1702,353 @@ var init_build = __esm({
1645
1702
  }
1646
1703
  });
1647
1704
 
1705
+ // src/build/electron.ts
1706
+ var electron_exports = {};
1707
+ __export(electron_exports, {
1708
+ buildElectron: () => buildElectron,
1709
+ detectInstalledElectron: () => detectInstalledElectron,
1710
+ normalizePreload: () => normalizePreload
1711
+ });
1712
+ import path11 from "path";
1713
+ import fs9 from "fs";
1714
+ import { rolldown as rolldown2 } from "rolldown";
1715
+ import pc3 from "picocolors";
1716
+ async function buildElectron(inlineConfig = {}) {
1717
+ const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
1718
+ const startTime = performance.now();
1719
+ assertElectronVersion(config);
1720
+ console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.4.0"}`));
1721
+ console.log(pc3.dim(` root: ${config.root}`));
1722
+ console.log(pc3.dim(` mode: ${config.mode}`));
1723
+ console.log(pc3.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
1724
+ const outDir = path11.resolve(config.root, config.build.outDir);
1725
+ if (config.build.emptyOutDir && fs9.existsSync(outDir)) {
1726
+ fs9.rmSync(outDir, { recursive: true, force: true });
1727
+ }
1728
+ fs9.mkdirSync(outDir, { recursive: true });
1729
+ const rendererOutDir = path11.join(outDir, "renderer");
1730
+ const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
1731
+ await build2({
1732
+ ...inlineConfig,
1733
+ target: "web",
1734
+ build: {
1735
+ ...inlineConfig.build,
1736
+ outDir: rendererOutDir,
1737
+ emptyOutDir: false
1738
+ }
1739
+ });
1740
+ const mainEntry = path11.resolve(config.root, config.electron.main);
1741
+ if (!fs9.existsSync(mainEntry)) {
1742
+ throw new Error(
1743
+ `Electron main entry not found: ${config.electron.main}
1744
+ \u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
1745
+ );
1746
+ }
1747
+ const mainFile = await bundleNode(config, mainEntry, {
1748
+ outFile: outFileName(outDir, "main", config.electron.mainFormat),
1749
+ format: config.electron.mainFormat,
1750
+ label: "main"
1751
+ });
1752
+ const preloadEntries = normalizePreload(config.electron.preload, config.root);
1753
+ const preloadFiles = [];
1754
+ for (const entry of preloadEntries) {
1755
+ if (!fs9.existsSync(entry)) {
1756
+ console.warn(pc3.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
1757
+ continue;
1758
+ }
1759
+ const base = path11.basename(entry).replace(/\.[^.]+$/, "");
1760
+ const out = outFileName(outDir, base, config.electron.preloadFormat);
1761
+ await bundleNode(config, entry, {
1762
+ outFile: out,
1763
+ format: config.electron.preloadFormat,
1764
+ label: `preload (${base})`
1765
+ });
1766
+ preloadFiles.push(out);
1767
+ }
1768
+ const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
1769
+ console.log(pc3.green(`
1770
+ \u2713 Electron build complete in ${elapsed}s`));
1771
+ console.log(pc3.dim(` renderer: ${path11.relative(config.root, rendererOutDir)}/`));
1772
+ console.log(pc3.dim(` main: ${path11.relative(config.root, mainFile)}`));
1773
+ for (const pf of preloadFiles) {
1774
+ console.log(pc3.dim(` preload: ${path11.relative(config.root, pf)}`));
1775
+ }
1776
+ console.log();
1777
+ return { rendererOutDir, mainFile, preloadFiles };
1778
+ }
1779
+ async function bundleNode(config, entry, opts) {
1780
+ const env = loadEnv(config.mode, config.root, config.envPrefix);
1781
+ const envDefine = {
1782
+ ...buildEnvDefine(env, config.mode),
1783
+ __ELECTRON__: "true",
1784
+ __NASTI_TARGET__: JSON.stringify("electron")
1785
+ };
1786
+ const oxcTransformPlugin = {
1787
+ name: "nasti:oxc-transform",
1788
+ transform(code, id) {
1789
+ if (!shouldTransform(id)) return null;
1790
+ const result = transformCode(id, code, {
1791
+ sourcemap: !!config.build.sourcemap,
1792
+ jsxRuntime: "automatic",
1793
+ jsxImportSource: config.framework === "vue" ? "vue" : "react"
1794
+ });
1795
+ return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
1796
+ }
1797
+ };
1798
+ const bundle = await rolldown2({
1799
+ input: entry,
1800
+ define: envDefine,
1801
+ platform: "node",
1802
+ plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)],
1803
+ ...config.build.rolldownOptions
1804
+ });
1805
+ fs9.mkdirSync(path11.dirname(opts.outFile), { recursive: true });
1806
+ await bundle.write({
1807
+ file: opts.outFile,
1808
+ format: opts.format === "cjs" ? "cjs" : "esm",
1809
+ sourcemap: !!config.build.sourcemap,
1810
+ minify: !!config.build.minify,
1811
+ inlineDynamicImports: true
1812
+ });
1813
+ await bundle.close();
1814
+ console.log(pc3.dim(` \u2713 ${opts.label} \u2192 ${path11.relative(config.root, opts.outFile)}`));
1815
+ return opts.outFile;
1816
+ }
1817
+ function outFileName(outDir, base, format) {
1818
+ const ext = format === "cjs" ? ".cjs" : ".mjs";
1819
+ return path11.join(outDir, base + ext);
1820
+ }
1821
+ function normalizePreload(preload, root) {
1822
+ const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
1823
+ return list.map((p) => path11.resolve(root, p));
1824
+ }
1825
+ function assertElectronVersion(config) {
1826
+ const min = config.electron.minVersion;
1827
+ const installed = detectInstalledElectron(config.root);
1828
+ if (installed && installed < min) {
1829
+ console.warn(
1830
+ pc3.yellow(
1831
+ ` \u26A0 \u68C0\u6D4B\u5230 Electron ${installed}\uFF0CNasti \u8981\u6C42 \u2265 ${min}\u3002\u65E7\u7248\u672C\u53EF\u80FD\u7F3A\u5C11 ESM \u4E3B\u8FDB\u7A0B\u652F\u6301\u3002`
1832
+ )
1833
+ );
1834
+ }
1835
+ }
1836
+ function detectInstalledElectron(root) {
1837
+ try {
1838
+ const pkgPath = path11.resolve(root, "node_modules/electron/package.json");
1839
+ if (!fs9.existsSync(pkgPath)) return null;
1840
+ const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
1841
+ const major = parseInt(String(pkg.version).split(".")[0], 10);
1842
+ return Number.isFinite(major) ? major : null;
1843
+ } catch {
1844
+ return null;
1845
+ }
1846
+ }
1847
+ var init_electron2 = __esm({
1848
+ "src/build/electron.ts"() {
1849
+ "use strict";
1850
+ init_config();
1851
+ init_resolve();
1852
+ init_electron();
1853
+ init_transformer();
1854
+ init_env();
1855
+ }
1856
+ });
1857
+
1858
+ // src/server/electron-dev.ts
1859
+ var electron_dev_exports = {};
1860
+ __export(electron_dev_exports, {
1861
+ startElectronDev: () => startElectronDev
1862
+ });
1863
+ import path12 from "path";
1864
+ import fs10 from "fs";
1865
+ import { createRequire as createRequire2 } from "module";
1866
+ import { spawn } from "child_process";
1867
+ import chokidar from "chokidar";
1868
+ import pc4 from "picocolors";
1869
+ import { rolldown as rolldown3 } from "rolldown";
1870
+ async function startElectronDev(inlineConfig = {}) {
1871
+ const { noSpawn, ...rest } = inlineConfig;
1872
+ const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
1873
+ warnElectronVersion(config);
1874
+ console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.4.0"}`));
1875
+ const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
1876
+ const server = await createServer2({ ...rest, target: "electron" });
1877
+ await server.listen();
1878
+ const devUrl = `http://localhost:${server.config.server.port}/`;
1879
+ console.log(pc4.dim(` renderer: ${devUrl}`));
1880
+ const stageDir = path12.resolve(config.root, ".nasti");
1881
+ fs10.mkdirSync(stageDir, { recursive: true });
1882
+ const mainEntry = path12.resolve(config.root, config.electron.main);
1883
+ const preloadEntries = normalizePreload(config.electron.preload, config.root);
1884
+ const builtMainFile = path12.join(stageDir, "main" + extFor(config.electron.mainFormat));
1885
+ const builtPreloadFiles = [];
1886
+ const compileAll = async () => {
1887
+ await compileNode(config, mainEntry, {
1888
+ outFile: builtMainFile,
1889
+ format: config.electron.mainFormat,
1890
+ devUrl
1891
+ });
1892
+ builtPreloadFiles.length = 0;
1893
+ for (const entry of preloadEntries) {
1894
+ if (!fs10.existsSync(entry)) continue;
1895
+ const base = path12.basename(entry).replace(/\.[^.]+$/, "");
1896
+ const out = path12.join(stageDir, base + extFor(config.electron.preloadFormat));
1897
+ await compileNode(config, entry, {
1898
+ outFile: out,
1899
+ format: config.electron.preloadFormat,
1900
+ devUrl
1901
+ });
1902
+ builtPreloadFiles.push(out);
1903
+ }
1904
+ };
1905
+ await compileAll();
1906
+ if (noSpawn) {
1907
+ console.log(pc4.dim(" (noSpawn) \u5DF2\u7F16\u8BD1\u4E3B/preload\uFF0C\u8DF3\u8FC7\u542F\u52A8 Electron\u3002"));
1908
+ return;
1909
+ }
1910
+ const electronBin = resolveElectronBinary(config);
1911
+ if (!electronBin) {
1912
+ console.warn(
1913
+ pc4.yellow(
1914
+ " \u26A0 \u672A\u627E\u5230 Electron \u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u8BF7\u5148\u5B89\u88C5\uFF1Anpm install -D electron\n \u5DF2\u7F16\u8BD1\u4E3B/preload \u81F3 .nasti/\uFF0C\u53EF\u624B\u52A8\u8FD0\u884C\u3002"
1915
+ )
1916
+ );
1917
+ return;
1918
+ }
1919
+ let child = null;
1920
+ const spawnElectron = () => {
1921
+ const args = [builtMainFile, ...config.electron.electronArgs];
1922
+ child = spawn(electronBin, args, {
1923
+ stdio: "inherit",
1924
+ env: { ...process.env, NASTI_DEV_SERVER_URL: devUrl, NASTI_TARGET: "electron" }
1925
+ });
1926
+ child.on("exit", (code) => {
1927
+ if (code !== null && child && child.__nastiKilled !== true) {
1928
+ console.log(pc4.dim(` Electron exited (${code}).`));
1929
+ process.exit(code ?? 0);
1930
+ }
1931
+ });
1932
+ };
1933
+ spawnElectron();
1934
+ if (config.electron.autoRestart) {
1935
+ const watchTargets = [mainEntry, ...preloadEntries].filter(fs10.existsSync);
1936
+ const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
1937
+ let restarting = null;
1938
+ watcher.on("all", async () => {
1939
+ if (restarting) return;
1940
+ restarting = (async () => {
1941
+ console.log(pc4.cyan("\n \u267B \u4E3B/preload \u53D8\u66F4\uFF0C\u91CD\u542F Electron..."));
1942
+ try {
1943
+ if (child && !child.killed) {
1944
+ ;
1945
+ child.__nastiKilled = true;
1946
+ const dying = child;
1947
+ await new Promise((resolve) => {
1948
+ const timer = setTimeout(() => resolve(), 3e3);
1949
+ dying.once("exit", () => {
1950
+ clearTimeout(timer);
1951
+ resolve();
1952
+ });
1953
+ dying.kill();
1954
+ });
1955
+ }
1956
+ await compileAll();
1957
+ spawnElectron();
1958
+ } finally {
1959
+ restarting = null;
1960
+ }
1961
+ })();
1962
+ });
1963
+ }
1964
+ }
1965
+ function extFor(format) {
1966
+ return format === "cjs" ? ".cjs" : ".mjs";
1967
+ }
1968
+ async function compileNode(config, entry, opts) {
1969
+ const env = loadEnv(config.mode, config.root, config.envPrefix);
1970
+ const envDefine = {
1971
+ ...buildEnvDefine(env, config.mode),
1972
+ __ELECTRON__: "true",
1973
+ __NASTI_TARGET__: JSON.stringify("electron"),
1974
+ __NASTI_DEV_SERVER_URL__: JSON.stringify(opts.devUrl)
1975
+ };
1976
+ const oxcTransformPlugin = {
1977
+ name: "nasti:oxc-transform",
1978
+ transform(code, id) {
1979
+ if (!shouldTransform(id)) return null;
1980
+ const result = transformCode(id, code, {
1981
+ sourcemap: !!config.build.sourcemap,
1982
+ jsxRuntime: "automatic",
1983
+ jsxImportSource: config.framework === "vue" ? "vue" : "react"
1984
+ });
1985
+ return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
1986
+ }
1987
+ };
1988
+ const bundle = await rolldown3({
1989
+ input: entry,
1990
+ transform: { define: envDefine },
1991
+ platform: "node",
1992
+ plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
1993
+ });
1994
+ fs10.mkdirSync(path12.dirname(opts.outFile), { recursive: true });
1995
+ await bundle.write({
1996
+ file: opts.outFile,
1997
+ format: opts.format === "cjs" ? "cjs" : "esm",
1998
+ sourcemap: false,
1999
+ minify: false,
2000
+ inlineDynamicImports: true
2001
+ });
2002
+ await bundle.close();
2003
+ }
2004
+ function resolveElectronBinary(config) {
2005
+ if (config.electron.electronPath && fs10.existsSync(config.electron.electronPath)) {
2006
+ return config.electron.electronPath;
2007
+ }
2008
+ try {
2009
+ const require2 = createRequire2(path12.resolve(config.root, "package.json"));
2010
+ const pathFile = require2.resolve("electron");
2011
+ const electronModule = require2(pathFile);
2012
+ if (typeof electronModule === "string" && fs10.existsSync(electronModule)) {
2013
+ return electronModule;
2014
+ }
2015
+ } catch {
2016
+ }
2017
+ return null;
2018
+ }
2019
+ function warnElectronVersion(config) {
2020
+ const installed = detectInstalledElectron(config.root);
2021
+ if (installed === null) {
2022
+ console.warn(
2023
+ pc4.yellow(
2024
+ ` \u26A0 \u672A\u68C0\u6D4B\u5230 Electron\uFF0C\u8BF7\u5B89\u88C5\uFF1Anpm install -D electron@^${config.electron.minVersion}`
2025
+ )
2026
+ );
2027
+ return;
2028
+ }
2029
+ if (installed < config.electron.minVersion) {
2030
+ console.warn(
2031
+ pc4.yellow(
2032
+ ` \u26A0 Electron ${installed} \u4F4E\u4E8E Nasti \u8981\u6C42\u7684 ${config.electron.minVersion}\uFF0C\u67D0\u4E9B\u7279\u6027\uFF08\u5982 ESM \u4E3B\u8FDB\u7A0B\uFF09\u4E0D\u53EF\u7528\u3002`
2033
+ )
2034
+ );
2035
+ }
2036
+ }
2037
+ var init_electron_dev = __esm({
2038
+ "src/server/electron-dev.ts"() {
2039
+ "use strict";
2040
+ init_config();
2041
+ init_electron();
2042
+ init_resolve();
2043
+ init_transformer();
2044
+ init_env();
2045
+ init_electron2();
2046
+ }
2047
+ });
2048
+
1648
2049
  // src/cli.ts
1649
2050
  import { cac } from "cac";
1650
- import pc3 from "picocolors";
2051
+ import pc5 from "picocolors";
1651
2052
  var cli = cac("nasti");
1652
2053
  cli.command("[root]", "Start dev server").alias("dev").option("--port <port>", "Port number", { default: 3e3 }).option("--host [host]", "Hostname").option("--open [path]", "Open browser on startup").option("--mode <mode>", "Set env mode").action(async (root, options) => {
1653
2054
  try {
@@ -1663,56 +2064,114 @@ cli.command("[root]", "Start dev server").alias("dev").option("--port <port>", "
1663
2064
  });
1664
2065
  await server.listen();
1665
2066
  } catch (err) {
1666
- console.error(pc3.red(`
2067
+ console.error(pc5.red(`
1667
2068
  Error starting dev server:
1668
2069
  ${err.message}
1669
2070
  `));
1670
- if (err.stack) console.error(pc3.dim(err.stack));
2071
+ if (err.stack) console.error(pc5.dim(err.stack));
1671
2072
  process.exit(1);
1672
2073
  }
1673
2074
  });
1674
- cli.command("build [root]", "Build for production").option("--outDir <dir>", "Output directory", { default: "dist" }).option("--sourcemap", "Generate source map").option("--minify", "Minify output", { default: true }).option("--mode <mode>", "Set env mode").action(async (root, options) => {
2075
+ cli.command("build [root]", "Build for production").option("--outDir <dir>", "Output directory", { default: "dist" }).option("--sourcemap", "Generate source map").option("--minify", "Minify output", { default: true }).option("--mode <mode>", "Set env mode").option("--target <target>", "Build target: web | electron", { default: "web" }).action(async (root, options) => {
1675
2076
  try {
1676
- const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
1677
- await build2({
2077
+ const target = options.target;
2078
+ if (target !== "web" && target !== "electron") {
2079
+ throw new Error(`Invalid --target "${target}". Expected "web" or "electron".`);
2080
+ }
2081
+ const inline = {
1678
2082
  root: root ?? ".",
1679
2083
  mode: options.mode ?? "production",
2084
+ target,
1680
2085
  build: {
1681
2086
  outDir: options.outDir,
1682
2087
  sourcemap: options.sourcemap,
1683
2088
  minify: options.minify
1684
2089
  }
1685
- });
2090
+ };
2091
+ if (target === "electron") {
2092
+ const { buildElectron: buildElectron2 } = await Promise.resolve().then(() => (init_electron2(), electron_exports));
2093
+ await buildElectron2(inline);
2094
+ } else {
2095
+ const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
2096
+ await build2(inline);
2097
+ }
1686
2098
  } catch (err) {
1687
- console.error(pc3.red(`
2099
+ console.error(pc5.red(`
1688
2100
  Build failed:
1689
2101
  ${err.message}
1690
2102
  `));
1691
- if (err.stack) console.error(pc3.dim(err.stack));
2103
+ if (err.stack) console.error(pc5.dim(err.stack));
2104
+ process.exit(1);
2105
+ }
2106
+ });
2107
+ cli.command("electron [root]", "Start Electron dev mode (requires electron ^41)").alias("electron-dev").option("--port <port>", "Renderer dev server port", { default: 3e3 }).option("--host [host]", "Hostname").option("--mode <mode>", "Set env mode").option("--no-spawn", "Compile main/preload but do not spawn Electron").option("--no-restart", "Disable auto-restart on main/preload changes").action(async (root, options) => {
2108
+ try {
2109
+ const { startElectronDev: startElectronDev2 } = await Promise.resolve().then(() => (init_electron_dev(), electron_dev_exports));
2110
+ await startElectronDev2({
2111
+ root: root ?? ".",
2112
+ mode: options.mode ?? "development",
2113
+ target: "electron",
2114
+ server: {
2115
+ port: options.port,
2116
+ host: options.host
2117
+ },
2118
+ electron: {
2119
+ autoRestart: options.restart !== false
2120
+ },
2121
+ noSpawn: options.spawn === false
2122
+ });
2123
+ } catch (err) {
2124
+ console.error(pc5.red(`
2125
+ Electron dev failed:
2126
+ ${err.message}
2127
+ `));
2128
+ if (err.stack) console.error(pc5.dim(err.stack));
2129
+ process.exit(1);
2130
+ }
2131
+ });
2132
+ cli.command("electron-build [root]", "Build Electron app for production").option("--outDir <dir>", "Output directory", { default: "dist" }).option("--sourcemap", "Generate source map").option("--minify", "Minify output", { default: true }).option("--mode <mode>", "Set env mode").action(async (root, options) => {
2133
+ try {
2134
+ const { buildElectron: buildElectron2 } = await Promise.resolve().then(() => (init_electron2(), electron_exports));
2135
+ await buildElectron2({
2136
+ root: root ?? ".",
2137
+ mode: options.mode ?? "production",
2138
+ target: "electron",
2139
+ build: {
2140
+ outDir: options.outDir,
2141
+ sourcemap: options.sourcemap,
2142
+ minify: options.minify
2143
+ }
2144
+ });
2145
+ } catch (err) {
2146
+ console.error(pc5.red(`
2147
+ Electron build failed:
2148
+ ${err.message}
2149
+ `));
2150
+ if (err.stack) console.error(pc5.dim(err.stack));
1692
2151
  process.exit(1);
1693
2152
  }
1694
2153
  });
1695
2154
  cli.command("preview [root]", "Preview production build").option("--port <port>", "Port number", { default: 4173 }).option("--host [host]", "Hostname").option("--outDir <dir>", "Output directory to serve", { default: "dist" }).action(async (root, options) => {
1696
2155
  try {
1697
2156
  const http2 = await import("http");
1698
- const path11 = await import("path");
2157
+ const path13 = await import("path");
1699
2158
  const sirv2 = (await import("sirv")).default;
1700
2159
  const connect2 = (await import("connect")).default;
1701
- const resolvedRoot = path11.resolve(root ?? ".");
1702
- const outDir = path11.resolve(resolvedRoot, options.outDir);
2160
+ const resolvedRoot = path13.resolve(root ?? ".");
2161
+ const outDir = path13.resolve(resolvedRoot, options.outDir);
1703
2162
  const app = connect2();
1704
2163
  app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
1705
2164
  const port = options.port;
1706
2165
  const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
1707
2166
  http2.createServer(app).listen(port, host, () => {
1708
2167
  console.log();
1709
- console.log(pc3.cyan(" \u{1F50D} nasti preview"));
2168
+ console.log(pc5.cyan(" \u{1F50D} nasti preview"));
1710
2169
  console.log();
1711
- console.log(` ${pc3.green("\u279C")} Local: ${pc3.cyan(`http://localhost:${port}`)}`);
2170
+ console.log(` ${pc5.green("\u279C")} Local: ${pc5.cyan(`http://localhost:${port}`)}`);
1712
2171
  console.log();
1713
2172
  });
1714
2173
  } catch (err) {
1715
- console.error(pc3.red(`
2174
+ console.error(pc5.red(`
1716
2175
  Preview failed:
1717
2176
  ${err.message}
1718
2177
  `));
@@ -1720,6 +2179,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
1720
2179
  }
1721
2180
  });
1722
2181
  cli.help();
1723
- cli.version("1.3.10");
2182
+ cli.version("1.4.0");
1724
2183
  cli.parse();
1725
2184
  //# sourceMappingURL=cli.js.map