@nasti-toolchain/nasti 1.6.5 → 1.7.1

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
@@ -1567,6 +1567,17 @@ function resolvePlugin(config) {
1567
1567
  const aliasEntries = Object.entries(alias).sort(
1568
1568
  ([a], [b]) => b.length - a.length
1569
1569
  );
1570
+ let vueRuntimeEntry = null;
1571
+ if (config.framework === "vue") {
1572
+ try {
1573
+ const vuePkgJson = require2.resolve("vue/package.json", { paths: [config.root] });
1574
+ const vueDir = path6.dirname(vuePkgJson);
1575
+ const mod = JSON.parse(fs6.readFileSync(vuePkgJson, "utf-8")).module;
1576
+ const entry = path6.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
1577
+ if (fs6.existsSync(entry)) vueRuntimeEntry = entry;
1578
+ } catch {
1579
+ }
1580
+ }
1570
1581
  return {
1571
1582
  name: "nasti:resolve",
1572
1583
  enforce: "pre",
@@ -1597,6 +1608,7 @@ function resolvePlugin(config) {
1597
1608
  if (resolved) return resolved;
1598
1609
  }
1599
1610
  if (!source.startsWith("/") && !source.startsWith(".")) {
1611
+ if (vueRuntimeEntry && source === "vue") return vueRuntimeEntry;
1600
1612
  try {
1601
1613
  const resolved = require2.resolve(source, {
1602
1614
  paths: [importer ? path6.dirname(importer) : config.root]
@@ -1681,15 +1693,15 @@ async function loadTailwind(projectRoot) {
1681
1693
  async function compileTailwind(css, fromFile, projectRoot) {
1682
1694
  const { node, oxide } = await loadTailwind(projectRoot);
1683
1695
  const dependencies = [];
1684
- const compiler = await node.compile(css, {
1696
+ const compiler2 = await node.compile(css, {
1685
1697
  base: path7.dirname(fromFile),
1686
1698
  from: fromFile,
1687
1699
  onDependency: (p) => dependencies.push(p)
1688
1700
  });
1689
- const scanner = new oxide.Scanner({ sources: compiler.sources });
1701
+ const scanner = new oxide.Scanner({ sources: compiler2.sources });
1690
1702
  const candidates = scanner.scan();
1691
1703
  return {
1692
- css: compiler.build(candidates),
1704
+ css: compiler2.build(candidates),
1693
1705
  dependencies: [...dependencies, ...scanner.files]
1694
1706
  };
1695
1707
  }
@@ -1871,6 +1883,178 @@ var init_assets = __esm({
1871
1883
  }
1872
1884
  });
1873
1885
 
1886
+ // src/plugins/vue.ts
1887
+ import crypto2 from "crypto";
1888
+ async function loadVueCompiler() {
1889
+ if (compiler) return compiler;
1890
+ try {
1891
+ compiler = await import("@vue/compiler-sfc");
1892
+ return compiler;
1893
+ } catch {
1894
+ return null;
1895
+ }
1896
+ }
1897
+ function vuePlugin(config) {
1898
+ const isDev = config.command === "serve";
1899
+ const descriptorCache = /* @__PURE__ */ new Map();
1900
+ return {
1901
+ name: "nasti:vue",
1902
+ enforce: "pre",
1903
+ async resolveId(source) {
1904
+ if (VUE_QUERY_RE.test(source)) {
1905
+ return source;
1906
+ }
1907
+ return null;
1908
+ },
1909
+ async transform(code, id) {
1910
+ if (!VUE_FILE_RE.test(id) && !VUE_QUERY_RE.test(id)) return null;
1911
+ const sfc = await loadVueCompiler();
1912
+ if (!sfc) {
1913
+ console.warn("[nasti:vue] @vue/compiler-sfc not found. Install it: npm install @vue/compiler-sfc");
1914
+ return null;
1915
+ }
1916
+ if (VUE_QUERY_RE.test(id)) {
1917
+ return handleVueSubBlock(id, sfc, descriptorCache, config);
1918
+ }
1919
+ const { descriptor, errors } = sfc.parse(code, { filename: id });
1920
+ if (errors.length) {
1921
+ console.error(`[nasti:vue] Parse error in ${id}:`, errors[0].message);
1922
+ return null;
1923
+ }
1924
+ descriptorCache.set(id, descriptor);
1925
+ const scopeId = hashId(id);
1926
+ let scriptCode = "";
1927
+ if (descriptor.script || descriptor.scriptSetup) {
1928
+ const compiled = sfc.compileScript(descriptor, {
1929
+ id: scopeId,
1930
+ isProd: !isDev,
1931
+ inlineTemplate: true,
1932
+ // 让 compileScript 产出 `const __sfc__ = ...`(而非默认的 `export default {...}`)。
1933
+ // 否则下方追加的 `__sfc__.render` / `__sfc__.__scopeId` / HMR 记录会引用一个
1934
+ // 不存在的 `__sfc__`,并与 compileScript 自带的 `export default` 形成双重默认导出。
1935
+ genDefaultAs: "__sfc__"
1936
+ });
1937
+ scriptCode = compiled.content;
1938
+ }
1939
+ let templateCode = "";
1940
+ if (descriptor.template && !descriptor.scriptSetup) {
1941
+ const compiled = sfc.compileTemplate({
1942
+ source: descriptor.template.content,
1943
+ filename: id,
1944
+ id: scopeId,
1945
+ compilerOptions: { scopeId: `data-v-${scopeId}` }
1946
+ });
1947
+ templateCode = compiled.code;
1948
+ }
1949
+ let output = scriptCode || "const __sfc__ = {}";
1950
+ if (templateCode) {
1951
+ output += `
1952
+ ${templateCode}
1953
+ `;
1954
+ output += `
1955
+ __sfc__.render = render
1956
+ `;
1957
+ }
1958
+ if (descriptor.styles.length > 0) {
1959
+ for (let i = 0; i < descriptor.styles.length; i++) {
1960
+ const style = descriptor.styles[i];
1961
+ const lang2 = style.lang ?? "css";
1962
+ output += `
1963
+ import "${id}?vue&type=style&index=${i}&lang=${lang2}"
1964
+ `;
1965
+ }
1966
+ }
1967
+ output += `
1968
+ __sfc__.__scopeId = "data-v-${scopeId}"
1969
+ `;
1970
+ if (isDev) {
1971
+ output += `
1972
+ __sfc__.__hmrId = ${JSON.stringify(scopeId)}
1973
+ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
1974
+ __VUE_HMR_RUNTIME__.createRecord(__sfc__.__hmrId, __sfc__)
1975
+ }
1976
+ if (import.meta.hot) {
1977
+ import.meta.hot.accept((mod) => {
1978
+ if (!mod) return
1979
+ const { default: updated } = mod
1980
+ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
1981
+ __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render)
1982
+ }
1983
+ })
1984
+ }
1985
+ `;
1986
+ }
1987
+ output += `
1988
+ export default __sfc__
1989
+ `;
1990
+ const lang = descriptor.scriptSetup?.lang ?? descriptor.script?.lang;
1991
+ if (lang === "ts") {
1992
+ const transpiled = transformCode(`${id}.ts`, output, { sourcemap: false });
1993
+ return { code: transpiled.code };
1994
+ }
1995
+ return { code: output };
1996
+ },
1997
+ handleHotUpdate(ctx) {
1998
+ const { file, modules } = ctx;
1999
+ if (VUE_FILE_RE.test(file)) {
2000
+ for (const mod of modules) {
2001
+ mod.isSelfAccepting = true;
2002
+ }
2003
+ descriptorCache.delete(file);
2004
+ }
2005
+ return modules;
2006
+ }
2007
+ };
2008
+ }
2009
+ async function handleVueSubBlock(id, sfc, cache, config) {
2010
+ const match = id.match(/(.+\.vue)\?vue&type=(\w+)(?:&index=(\d+))?(?:&lang=(\w+))?/);
2011
+ if (!match) return null;
2012
+ const [, filePath, type, indexStr, lang] = match;
2013
+ const descriptor = cache.get(filePath);
2014
+ if (!descriptor) return null;
2015
+ if (type === "style") {
2016
+ const index = parseInt(indexStr ?? "0", 10);
2017
+ const style = descriptor.styles[index];
2018
+ if (!style) return null;
2019
+ const scopeId = hashId(filePath);
2020
+ const result = await sfc.compileStyleAsync({
2021
+ source: style.content,
2022
+ filename: filePath,
2023
+ id: `data-v-${scopeId}`,
2024
+ scoped: style.scoped ?? false
2025
+ });
2026
+ const cssCode = JSON.stringify(result.code);
2027
+ return {
2028
+ code: `
2029
+ const css = ${cssCode};
2030
+ const style = document.createElement('style');
2031
+ style.setAttribute('data-v-${scopeId}', '');
2032
+ style.textContent = css;
2033
+ document.head.appendChild(style);
2034
+
2035
+ if (import.meta.hot) {
2036
+ import.meta.hot.accept();
2037
+ import.meta.hot.prune(() => style.remove());
2038
+ }
2039
+ `
2040
+ };
2041
+ }
2042
+ return null;
2043
+ }
2044
+ function hashId(filename) {
2045
+ return crypto2.createHash("sha256").update(filename).digest("hex").slice(0, 8);
2046
+ }
2047
+ var VUE_FILE_RE, VUE_QUERY_RE, compiler;
2048
+ var init_vue = __esm({
2049
+ "src/plugins/vue.ts"() {
2050
+ "use strict";
2051
+ init_transformer();
2052
+ VUE_FILE_RE = /\.vue$/;
2053
+ VUE_QUERY_RE = /\.vue\?vue&type=(script|template|style)(&index=\d+)?(&lang=\w+)?/;
2054
+ compiler = null;
2055
+ }
2056
+ });
2057
+
1874
2058
  // src/server/index.ts
1875
2059
  var server_exports = {};
1876
2060
  __export(server_exports, {
@@ -1886,6 +2070,7 @@ import pc from "picocolors";
1886
2070
  async function createServer(inlineConfig = {}) {
1887
2071
  const config = await resolveConfig(inlineConfig, "serve");
1888
2072
  const allPlugins = [
2073
+ ...config.framework === "vue" ? [vuePlugin(config)] : [],
1889
2074
  resolvePlugin(config),
1890
2075
  cssPlugin(config),
1891
2076
  assetsPlugin(config),
@@ -1946,7 +2131,7 @@ async function createServer(inlineConfig = {}) {
1946
2131
  const localUrl = `http://localhost:${actualPort}`;
1947
2132
  const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
1948
2133
  console.log();
1949
- console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.6.5"}`));
2134
+ console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.7.1"}`));
1950
2135
  console.log();
1951
2136
  console.log(` ${pc.green(">")} Local: ${pc.cyan(localUrl)}`);
1952
2137
  if (networkUrl) {
@@ -2014,6 +2199,7 @@ var init_server = __esm({
2014
2199
  init_resolve();
2015
2200
  init_css();
2016
2201
  init_assets();
2202
+ init_vue();
2017
2203
  init_html();
2018
2204
  }
2019
2205
  });
@@ -2069,7 +2255,7 @@ import pc2 from "picocolors";
2069
2255
  async function build(inlineConfig = {}) {
2070
2256
  const config = await resolveConfig(inlineConfig, "build");
2071
2257
  const startTime = performance.now();
2072
- console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.6.5"}`));
2258
+ console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.7.1"}`));
2073
2259
  console.log(pc2.dim(` root: ${config.root}`));
2074
2260
  console.log(pc2.dim(` mode: ${config.mode}`));
2075
2261
  const outDir = path11.resolve(config.root, config.build.outDir);
@@ -2102,6 +2288,7 @@ async function build(inlineConfig = {}) {
2102
2288
  throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
2103
2289
  }
2104
2290
  const builtinPlugins = [
2291
+ ...config.framework === "vue" ? [vuePlugin(config)] : [],
2105
2292
  resolvePlugin(config),
2106
2293
  cssPlugin(config),
2107
2294
  assetsPlugin(config)
@@ -2123,11 +2310,17 @@ async function build(inlineConfig = {}) {
2123
2310
  };
2124
2311
  const env = loadEnv(config.mode, config.root, config.envPrefix);
2125
2312
  const envDefine = buildEnvDefine(env, config.mode);
2126
- const existingTransform = config.build.rolldownOptions?.transform;
2127
- const mergedDefine = { ...existingTransform?.define ?? {}, ...envDefine };
2313
+ const { output: userOutput, transform: userTransform, ...restInputOptions } = config.build.rolldownOptions;
2314
+ const vueDefine = config.framework === "vue" ? {
2315
+ __VUE_OPTIONS_API__: "true",
2316
+ __VUE_PROD_DEVTOOLS__: "false",
2317
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "false"
2318
+ } : {};
2319
+ const mergedDefine = { ...vueDefine, ...userTransform?.define ?? {}, ...envDefine };
2128
2320
  const bundle = await rolldown({
2321
+ ...restInputOptions,
2129
2322
  input: entryPoints,
2130
- transform: { ...existingTransform, define: mergedDefine },
2323
+ transform: { ...userTransform, define: mergedDefine },
2131
2324
  plugins: [
2132
2325
  oxcTransformPlugin,
2133
2326
  // 转换 Nasti 插件为 Rolldown 插件格式
@@ -2143,17 +2336,19 @@ async function build(inlineConfig = {}) {
2143
2336
  // manifest/SW writers) rely on for final-stage artifact emission.
2144
2337
  closeBundle: p.closeBundle
2145
2338
  }))
2146
- ],
2147
- ...config.build.rolldownOptions
2339
+ ]
2148
2340
  });
2149
2341
  const { output } = await bundle.write({
2150
- dir: outDir,
2151
2342
  format: "esm",
2152
2343
  sourcemap: !!config.build.sourcemap,
2153
2344
  minify: !!config.build.minify,
2154
2345
  entryFileNames: "assets/[name].[hash].js",
2155
2346
  chunkFileNames: "assets/[name].[hash].js",
2156
- assetFileNames: "assets/[name].[hash][extname]"
2347
+ assetFileNames: "assets/[name].[hash][extname]",
2348
+ // 用户可覆盖默认输出:代码拆分(advancedChunks / codeSplitting)、chunk 命名等
2349
+ ...userOutput,
2350
+ // dir 始终由 Nasti 掌管 —— 下方 HTML 改写依赖固定的产物目录,故放在最后强制生效
2351
+ dir: outDir
2157
2352
  });
2158
2353
  await bundle.close();
2159
2354
  await pluginContainer.buildEnd();
@@ -2213,6 +2408,7 @@ var init_build = __esm({
2213
2408
  init_resolve();
2214
2409
  init_css();
2215
2410
  init_assets();
2411
+ init_vue();
2216
2412
  init_html();
2217
2413
  init_transformer();
2218
2414
  init_env();
@@ -2235,7 +2431,7 @@ async function buildElectron(inlineConfig = {}) {
2235
2431
  const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
2236
2432
  const startTime = performance.now();
2237
2433
  assertElectronVersion(config);
2238
- console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.6.5"}`));
2434
+ console.log(pc3.cyan("\n\u26A1 nasti build (electron)") + pc3.dim(` v${"1.7.1"}`));
2239
2435
  console.log(pc3.dim(` root: ${config.root}`));
2240
2436
  console.log(pc3.dim(` mode: ${config.mode}`));
2241
2437
  console.log(pc3.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
@@ -2313,21 +2509,23 @@ async function bundleNode(config, entry, opts) {
2313
2509
  return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
2314
2510
  }
2315
2511
  };
2316
- const existingTransform = config.build.rolldownOptions?.transform;
2317
- const mergedDefine = { ...existingTransform?.define ?? {}, ...envDefine };
2512
+ const { output: userOutput, transform: userTransform, ...restInputOptions } = config.build.rolldownOptions;
2513
+ const mergedDefine = { ...userTransform?.define ?? {}, ...envDefine };
2318
2514
  const bundle = await rolldown2({
2515
+ ...restInputOptions,
2319
2516
  input: entry,
2320
- transform: { ...existingTransform, define: mergedDefine },
2321
2517
  platform: "node",
2322
- plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)],
2323
- ...config.build.rolldownOptions
2518
+ transform: { ...userTransform, define: mergedDefine },
2519
+ plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
2324
2520
  });
2325
2521
  fs9.mkdirSync(path12.dirname(opts.outFile), { recursive: true });
2326
2522
  await bundle.write({
2327
- file: opts.outFile,
2328
- format: opts.format === "cjs" ? "cjs" : "esm",
2329
2523
  sourcemap: !!config.build.sourcemap,
2330
2524
  minify: !!config.build.minify,
2525
+ // 允许用户微调 output;但主进程 / preload 的单文件约束由下方键强制保证
2526
+ ...userOutput,
2527
+ file: opts.outFile,
2528
+ format: opts.format === "cjs" ? "cjs" : "esm",
2331
2529
  codeSplitting: false
2332
2530
  });
2333
2531
  await bundle.close();
@@ -2391,7 +2589,7 @@ async function startElectronDev(inlineConfig = {}) {
2391
2589
  const { noSpawn, ...rest } = inlineConfig;
2392
2590
  const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
2393
2591
  warnElectronVersion(config);
2394
- console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.6.5"}`));
2592
+ console.log(pc4.cyan("\n\u26A1 nasti electron dev") + pc4.dim(` v${"1.7.1"}`));
2395
2593
  const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
2396
2594
  const server = await createServer2({ ...rest, target: "electron" });
2397
2595
  await server.listen();
@@ -2718,6 +2916,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
2718
2916
  }
2719
2917
  });
2720
2918
  cli.help();
2721
- cli.version("1.6.5");
2919
+ cli.version("1.7.1");
2722
2920
  cli.parse();
2723
2921
  //# sourceMappingURL=cli.js.map