@stacksjs/stx 0.2.120 → 0.2.121

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.
@@ -9,6 +9,19 @@
9
9
  * - `import { ... } from '@composables'` (handled by transformStoreImports)
10
10
  */
11
11
  export declare function hasUserImports(code: string): boolean;
12
+ /**
13
+ * Run one client bundle build at a time.
14
+ *
15
+ * Bun.build can return transient "Unseekable reading file" failures when
16
+ * separate builds concurrently traverse the same linked workspace dependency.
17
+ * Dashboard renders commonly compile the layout and page controllers together,
18
+ * so distinct content hashes still share much of their dependency graph.
19
+ *
20
+ * Cache reads remain concurrent and identical builds still share one promise.
21
+ * Only cold Bun.build work is queued, and a rejected task cannot stall the next
22
+ * build.
23
+ */
24
+ export declare function queueClientBundleBuild<T>(task: () => Promise<T>): Promise<T>;
12
25
  export declare function bundleClientScript(code: string, filePath: string, options?: {
13
26
  projectRoot?: string
14
27
  minify?: boolean
@@ -98,10 +98,27 @@ function createBundlePlugin(projectRoot, templateDir, tmpEntry, inputFiles) {
98
98
  console.warn(`[stx:bundler] could not resolve ${args.path[0]}/ import:`, args.path);
99
99
  return { path: resolved };
100
100
  });
101
+ build.onLoad({ filter: /\.(?:[cm]?[jt]sx?|json)$/ }, (args) => {
102
+ const extension = path.extname(args.path).toLowerCase(), loader = extension === ".json" ? "json" : extension === ".tsx" ? "tsx" : extension === ".jsx" ? "jsx" : extension === ".ts" || extension === ".mts" || extension === ".cts" ? "ts" : "js";
103
+ inputFiles.add(args.path);
104
+ return {
105
+ contents: fs.readFileSync(args.path, "utf8"),
106
+ loader
107
+ };
108
+ });
101
109
  }
102
110
  };
103
111
  }
104
- const inFlightBundles = new Map;
112
+ const inFlightBundles = new Map, CLIENT_BUNDLE_QUEUE = Symbol.for("stx.client-bundle-build-queue");
113
+ export function queueClientBundleBuild(task) {
114
+ const shared = globalThis, result = (shared[CLIENT_BUNDLE_QUEUE] ?? Promise.resolve()).then(task, task);
115
+ shared[CLIENT_BUNDLE_QUEUE] = result.then(() => {
116
+ return;
117
+ }, () => {
118
+ return;
119
+ });
120
+ return result;
121
+ }
105
122
  export async function bundleClientScript(code, filePath, options = {}) {
106
123
  const projectRoot = options.projectRoot || process.cwd(), minify = options.minify ?? !1, cacheDir = options.cacheDir || stateDir(projectRoot, "bundle-cache"), hasher = new Bun.CryptoHasher("md5");
107
124
  hasher.update(`${BUNDLE_CACHE_VERSION}\x00${code}\x00${filePath}`);
@@ -136,7 +153,7 @@ export async function bundleClientScript(code, filePath, options = {}) {
136
153
  const running = inFlightBundles.get(hash);
137
154
  if (running)
138
155
  return await running;
139
- const build = buildBundle(code, filePath, { projectRoot, minify, cacheDir, hash, cachePath, depsPath });
156
+ const build = queueClientBundleBuild(() => buildBundle(code, filePath, { projectRoot, minify, cacheDir, hash, cachePath, depsPath }));
140
157
  inFlightBundles.set(hash, build);
141
158
  try {
142
159
  return await build;
@@ -58,7 +58,13 @@ function extractClientMethods(source, file) {
58
58
  for (const script of scripts) {
59
59
  if (!/\bclient\b/i.test(script[1]) || /\bcomponent\b|\bstx:component\b/i.test(script[1]))
60
60
  continue;
61
- const code = script[2], functionPattern = /(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(([^)]*)\)\s*\{/g;
61
+ let code;
62
+ try {
63
+ code = new Bun.Transpiler({ loader: "ts" }).transformSync(script[2]);
64
+ } catch (error) {
65
+ throw Error(`${file}: failed to transpile <script client> (${error.message})`);
66
+ }
67
+ const functionPattern = /(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(([^)]*)\)\s*\{/g;
62
68
  let match;
63
69
  while (match = functionPattern.exec(code)) {
64
70
  const name = match[1];
@@ -673,17 +679,29 @@ ${components.map((component) => `import type { ${component.name}Props } from './
673
679
  let bundle;
674
680
  if (config.bundle !== !1) {
675
681
  bundle = path.join(outputDir, "bundle.js");
676
- const result = await Bun.build({
677
- entrypoints: [path.join(outputDir, "index.js")],
678
- outdir: outputDir,
679
- naming: "bundle.js",
680
- target: "browser",
681
- format: "esm",
682
- minify: config.minify ?? !0,
683
- sourcemap: config.sourcemap || "none"
684
- });
685
- if (!result.success)
686
- throw AggregateError(result.logs, "Failed to bundle component library");
682
+ let result;
683
+ try {
684
+ result = await Bun.build({
685
+ entrypoints: [path.join(outputDir, "index.js")],
686
+ outdir: outputDir,
687
+ naming: "bundle.js",
688
+ target: "browser",
689
+ format: "esm",
690
+ minify: config.minify ?? !0,
691
+ sourcemap: config.sourcemap || "none"
692
+ });
693
+ } catch (error) {
694
+ const logs = error instanceof AggregateError ? error.errors : [error], details = logs.map((log) => String(log).trim()).filter(Boolean).join(`
695
+ `);
696
+ throw AggregateError(logs, `Failed to bundle component library${details ? `
697
+ ${details}` : ""}`);
698
+ }
699
+ if (!result.success) {
700
+ const details = result.logs.map((log) => String(log).trim()).filter(Boolean).join(`
701
+ `);
702
+ throw AggregateError(result.logs, `Failed to bundle component library${details ? `
703
+ ${details}` : ""}`);
704
+ }
687
705
  files.push(bundle);
688
706
  if (config.sourcemap === "external")
689
707
  files.push(`${bundle}.map`);