@nasti-toolchain/nasti 1.3.9 → 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) => {
@@ -790,7 +807,8 @@ function rewriteExternalRequires(code) {
790
807
  const imports = [];
791
808
  for (const pkg of pkgs) {
792
809
  const safe = pkg.replace(/[^a-zA-Z0-9_$]/g, "_");
793
- imports.push(`import __req_${safe} from "/@modules/${pkg}";`);
810
+ imports.push(`import * as __ns_${safe} from "/@modules/${pkg}";`);
811
+ imports.push(`var __req_${safe} = "default" in __ns_${safe} ? __ns_${safe}["default"] : __ns_${safe};`);
794
812
  result = result.replaceAll(`__require("${pkg}")`, `__req_${safe}`);
795
813
  result = result.replaceAll(`__require('${pkg}')`, `__req_${safe}`);
796
814
  }
@@ -798,8 +816,8 @@ function rewriteExternalRequires(code) {
798
816
  }
799
817
  async function injectCjsNamedExports(code, entryFile) {
800
818
  try {
801
- const { createRequire: createRequire2 } = await import("module");
802
- const req = createRequire2(entryFile);
819
+ const { createRequire: createRequire3 } = await import("module");
820
+ const req = createRequire3(entryFile);
803
821
  const cjsExports = req(entryFile);
804
822
  if (!cjsExports || typeof cjsExports !== "object" && typeof cjsExports !== "function" || Array.isArray(cjsExports)) return code;
805
823
  const namedKeys = Object.keys(cjsExports).filter(
@@ -1422,10 +1440,11 @@ async function createServer(inlineConfig = {}) {
1422
1440
  let currentPort = finalPort;
1423
1441
  const onListening = () => {
1424
1442
  const actualPort = httpServer.address()?.port ?? currentPort;
1443
+ config.server.port = actualPort;
1425
1444
  const localUrl = `http://localhost:${actualPort}`;
1426
1445
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1427
1446
  console.log();
1428
- console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.3.9"}`));
1447
+ console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.4.0"}`));
1429
1448
  console.log();
1430
1449
  console.log(` ${pc.green(">")} Local: ${pc.cyan(localUrl)}`);
1431
1450
  if (networkUrl) {
@@ -1487,6 +1506,45 @@ var init_server = __esm({
1487
1506
  }
1488
1507
  });
1489
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
+
1490
1548
  // src/build/index.ts
1491
1549
  var build_exports = {};
1492
1550
  __export(build_exports, {
@@ -1499,7 +1557,7 @@ import pc2 from "picocolors";
1499
1557
  async function build(inlineConfig = {}) {
1500
1558
  const config = await resolveConfig(inlineConfig, "build");
1501
1559
  const startTime = performance.now();
1502
- console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.3.9"}`));
1560
+ console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.4.0"}`));
1503
1561
  console.log(pc2.dim(` root: ${config.root}`));
1504
1562
  console.log(pc2.dim(` mode: ${config.mode}`));
1505
1563
  const outDir = path10.resolve(config.root, config.build.outDir);
@@ -1644,9 +1702,353 @@ var init_build = __esm({
1644
1702
  }
1645
1703
  });
1646
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
+
1647
2049
  // src/cli.ts
1648
2050
  import { cac } from "cac";
1649
- import pc3 from "picocolors";
2051
+ import pc5 from "picocolors";
1650
2052
  var cli = cac("nasti");
1651
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) => {
1652
2054
  try {
@@ -1662,56 +2064,114 @@ cli.command("[root]", "Start dev server").alias("dev").option("--port <port>", "
1662
2064
  });
1663
2065
  await server.listen();
1664
2066
  } catch (err) {
1665
- console.error(pc3.red(`
2067
+ console.error(pc5.red(`
1666
2068
  Error starting dev server:
1667
2069
  ${err.message}
1668
2070
  `));
1669
- if (err.stack) console.error(pc3.dim(err.stack));
2071
+ if (err.stack) console.error(pc5.dim(err.stack));
1670
2072
  process.exit(1);
1671
2073
  }
1672
2074
  });
1673
- 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) => {
1674
2076
  try {
1675
- const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
1676
- 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 = {
1677
2082
  root: root ?? ".",
1678
2083
  mode: options.mode ?? "production",
2084
+ target,
1679
2085
  build: {
1680
2086
  outDir: options.outDir,
1681
2087
  sourcemap: options.sourcemap,
1682
2088
  minify: options.minify
1683
2089
  }
1684
- });
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
+ }
1685
2098
  } catch (err) {
1686
- console.error(pc3.red(`
2099
+ console.error(pc5.red(`
1687
2100
  Build failed:
1688
2101
  ${err.message}
1689
2102
  `));
1690
- 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));
1691
2151
  process.exit(1);
1692
2152
  }
1693
2153
  });
1694
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) => {
1695
2155
  try {
1696
2156
  const http2 = await import("http");
1697
- const path11 = await import("path");
2157
+ const path13 = await import("path");
1698
2158
  const sirv2 = (await import("sirv")).default;
1699
2159
  const connect2 = (await import("connect")).default;
1700
- const resolvedRoot = path11.resolve(root ?? ".");
1701
- const outDir = path11.resolve(resolvedRoot, options.outDir);
2160
+ const resolvedRoot = path13.resolve(root ?? ".");
2161
+ const outDir = path13.resolve(resolvedRoot, options.outDir);
1702
2162
  const app = connect2();
1703
2163
  app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
1704
2164
  const port = options.port;
1705
2165
  const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
1706
2166
  http2.createServer(app).listen(port, host, () => {
1707
2167
  console.log();
1708
- console.log(pc3.cyan(" \u{1F50D} nasti preview"));
2168
+ console.log(pc5.cyan(" \u{1F50D} nasti preview"));
1709
2169
  console.log();
1710
- console.log(` ${pc3.green("\u279C")} Local: ${pc3.cyan(`http://localhost:${port}`)}`);
2170
+ console.log(` ${pc5.green("\u279C")} Local: ${pc5.cyan(`http://localhost:${port}`)}`);
1711
2171
  console.log();
1712
2172
  });
1713
2173
  } catch (err) {
1714
- console.error(pc3.red(`
2174
+ console.error(pc5.red(`
1715
2175
  Preview failed:
1716
2176
  ${err.message}
1717
2177
  `));
@@ -1719,6 +2179,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
1719
2179
  }
1720
2180
  });
1721
2181
  cli.help();
1722
- cli.version("1.3.9");
2182
+ cli.version("1.4.0");
1723
2183
  cli.parse();
1724
2184
  //# sourceMappingURL=cli.js.map