bun-plugin-stx 0.2.318 → 0.2.320

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/serve.d.ts CHANGED
@@ -60,6 +60,27 @@ export declare function buildDynamicRouteRegexes(fileRouteBase: string): RegExp[
60
60
  * - `[...rest]` catch-all → -10000 (always last)
61
61
  */
62
62
  export declare function routeSpecificity(fileRouteBase: string): number;
63
+ /**
64
+ * A discovered page's path relative to the page root holding it, and that
65
+ * root's position in `patterns`.
66
+ *
67
+ * Specificity has to be measured on the relative path. Measured on the whole
68
+ * path, a root's own directory segments count as static segments, so a page
69
+ * under a deeper root outranks the same route under a shallower one: Stacks
70
+ * passes `['resources/views', '<framework>/defaults/resources/views']`, and a
71
+ * framework default `password/reset/[token].stx` beat the app's own file at
72
+ * the same path purely because its root sits more directories down.
73
+ */
74
+ export declare function pageRootOf(filePath: string, patterns: string[]): { relative: string, root: number };
75
+ /**
76
+ * Order dynamic route files the way `getRoute` tries them: most specific
77
+ * route first (see {@link routeSpecificity}), and between equally specific
78
+ * routes, the earlier page root first. Earlier roots are the overrides - an
79
+ * app's own views are listed before the framework defaults they replace - so
80
+ * a tie must never go to the later root. Discovery order breaks any remaining
81
+ * tie, which keeps the order deterministic.
82
+ */
83
+ export declare function orderDynamicRouteFiles(files: string[], patterns: string[]): string[];
63
84
  /**
64
85
  * True when a request path is for a STATIC ASSET (a non-page file extension like
65
86
  * `.jpg`/`.css`/`.js`) rather than a page. Used so a catch-all page can never
package/dist/serve.js CHANGED
@@ -8919,6 +8919,18 @@ function routeSpecificity(fileRouteBase) {
8919
8919
  }
8920
8920
  return score;
8921
8921
  }
8922
+ function pageRootOf(filePath, patterns) {
8923
+ const normalized = filePath.replace(/^\.\//, "").replace(/\\/g, "/");
8924
+ for (let root = 0;root < patterns.length; root++) {
8925
+ const base = patterns[root].replace(/\\/g, "/").replace(/\/$/, "");
8926
+ if (normalized.startsWith(`${base}/`))
8927
+ return { relative: normalized.slice(base.length + 1), root };
8928
+ }
8929
+ return { relative: normalized, root: patterns.length };
8930
+ }
8931
+ function orderDynamicRouteFiles(files, patterns) {
8932
+ return files.map((file, index) => ({ file, index, ...pageRootOf(file, patterns) })).sort((a, b) => routeSpecificity(b.relative) - routeSpecificity(a.relative) || a.root - b.root || a.index - b.index).map((entry) => entry.file);
8933
+ }
8922
8934
  function isStaticAssetPath(requestPath) {
8923
8935
  return /\.[a-z0-9]+$/i.test(requestPath) && !/\.(?:stx|md|html)$/i.test(requestPath);
8924
8936
  }
@@ -9491,21 +9503,32 @@ function __stxOverlay(errs){
9491
9503
  const src = await nodeFs.readFile(file, "utf-8");
9492
9504
  const meta = src.match(/definePageMeta\s*\(\s*\{[\s\S]*?\}\s*\)/);
9493
9505
  if (!meta)
9494
- return;
9506
+ return [];
9495
9507
  const mw = meta[0].match(/middleware\s*:\s*(\[[^\]]*\]|['"][^'"]+['"])/);
9496
9508
  if (!mw)
9497
- return;
9498
- const names = mw[1].startsWith("[") ? Array.from(mw[1].matchAll(/['"]([^'"]+)['"]/g)).map((m) => m[1]) : [mw[1].replace(/['"]/g, "")];
9499
- if (names.length === 0)
9500
- return;
9509
+ return [];
9510
+ return mw[1].startsWith("[") ? Array.from(mw[1].matchAll(/['"]([^'"]+)['"]/g)).map((m) => m[1]) : [mw[1].replace(/['"]/g, "")];
9511
+ } catch {
9512
+ return [];
9513
+ }
9514
+ }
9515
+ async function indexPageMiddleware(files) {
9516
+ pageMiddlewareByPath.clear();
9517
+ pageMiddlewarePatterns.length = 0;
9518
+ const detected = await Promise.all(files.map((f) => detectPageMiddleware(f)));
9519
+ const middlewareOf = new Map(files.map((f, i) => [f, detected[i]]));
9520
+ const dynamic = [];
9521
+ for (const file of files) {
9501
9522
  const urlPath = urlPathFromFile(file);
9502
- if (urlPath.includes("[")) {
9503
- const { re, names: paramNames } = compileRoutePattern(urlPath);
9504
- pageMiddlewarePatterns.push({ re, names: paramNames, middleware: names });
9505
- } else {
9506
- pageMiddlewareByPath.set(urlPath, names);
9507
- }
9508
- } catch {}
9523
+ if (urlPath.includes("["))
9524
+ dynamic.push(file);
9525
+ else if (!pageMiddlewareByPath.has(urlPath))
9526
+ pageMiddlewareByPath.set(urlPath, middlewareOf.get(file) ?? []);
9527
+ }
9528
+ for (const file of orderDynamicRouteFiles(dynamic, patterns)) {
9529
+ const { re, names } = compileRoutePattern(urlPathFromFile(file));
9530
+ pageMiddlewarePatterns.push({ re, names, middleware: middlewareOf.get(file) ?? [] });
9531
+ }
9509
9532
  }
9510
9533
  function resolveRouteMiddleware(path) {
9511
9534
  const exact = pageMiddlewareByPath.get(path);
@@ -9739,9 +9762,7 @@ function __stxOverlay(errs){
9739
9762
  const kept = files.filter((f) => !isExcludedPage(f));
9740
9763
  sourceFiles = kept;
9741
9764
  rebuildDiscoveredPagePaths(kept);
9742
- pageMiddlewareByPath.clear();
9743
- pageMiddlewarePatterns.length = 0;
9744
- await Promise.all(kept.map((f) => detectPageMiddleware(f)));
9765
+ await indexPageMiddleware(kept);
9745
9766
  try {
9746
9767
  const { Router } = await import("./chunk-37vp8yms.js");
9747
9768
  const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
@@ -10111,8 +10132,8 @@ function __stxOverlay(errs){
10111
10132
  if (isAssetRequest)
10112
10133
  return false;
10113
10134
  return true;
10114
- }).sort((a, b) => routeSpecificity(b) - routeSpecificity(a));
10115
- for (const filePath of dynamicFiles) {
10135
+ });
10136
+ for (const filePath of orderDynamicRouteFiles(dynamicFiles, patterns)) {
10116
10137
  const normalizedFilePath = filePath.replace(/^\.\//, "").replace(/\\/g, "/");
10117
10138
  let relativeFilePath = normalizedFilePath;
10118
10139
  for (const pattern of patterns) {
@@ -11204,7 +11225,9 @@ export {
11204
11225
  render404Page,
11205
11226
  publicFileExists,
11206
11227
  projectUsesImageBuiltins,
11228
+ pageRootOf,
11207
11229
  pageExcluder,
11230
+ orderDynamicRouteFiles,
11208
11231
  isStaticAssetPath,
11209
11232
  isRenderableCacheCandidate,
11210
11233
  isRenderFailure,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-plugin-stx",
3
3
  "type": "module",
4
- "version": "0.2.318",
4
+ "version": "0.2.320",
5
5
  "description": "A Bun plugin that allows for using Laravel Blade-like syntax.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",