bun-plugin-stx 0.2.414 → 0.2.416

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.
@@ -0,0 +1,125 @@
1
+ // @bun
2
+ // ../router/src/layout-metadata.ts
3
+ function deriveLayoutGroup(layoutPath) {
4
+ const normalized = layoutPath.replace(/\\/g, "/");
5
+ const segments = normalized.split("/").filter(Boolean);
6
+ const layoutsIndex = segments.lastIndexOf("layouts");
7
+ const layoutSegment = layoutsIndex >= 0 ? segments[layoutsIndex + 1] : segments.at(-1);
8
+ if (!layoutSegment)
9
+ return "app";
10
+ return layoutSegment.replace(/\.stx$/i, "") || "app";
11
+ }
12
+ function extractLayoutMetadata(html) {
13
+ const layoutMeta = html.match(/<meta\b[^>]*name=["']stx-layout["'][^>]*content=["']([^"']+)["'][^>]*>/i);
14
+ const groupMeta = html.match(/<meta\b[^>]*name=["']stx-layout-group["'][^>]*content=["']([^"']+)["'][^>]*>/i);
15
+ const layoutComment = html.match(/<!--\s*stx-layout:\s*([^ ]+)\s*-->/i);
16
+ const layout = layoutMeta?.[1] || layoutComment?.[1] || "";
17
+ return {
18
+ layout,
19
+ group: groupMeta?.[1] || deriveLayoutGroup(layout)
20
+ };
21
+ }
22
+
23
+ // ../router/src/file-requests.ts
24
+ var FILE_REQUEST_EXTENSIONS = Object.freeze([
25
+ "ico",
26
+ "png",
27
+ "jpg",
28
+ "jpeg",
29
+ "gif",
30
+ "webp",
31
+ "avif",
32
+ "svg",
33
+ "bmp",
34
+ "tif",
35
+ "tiff",
36
+ "heic",
37
+ "css",
38
+ "js",
39
+ "mjs",
40
+ "cjs",
41
+ "map",
42
+ "wasm",
43
+ "webmanifest",
44
+ "json",
45
+ "xml",
46
+ "txt",
47
+ "rss",
48
+ "atom",
49
+ "woff",
50
+ "woff2",
51
+ "ttf",
52
+ "otf",
53
+ "eot",
54
+ "mp3",
55
+ "mp4",
56
+ "m4a",
57
+ "m4v",
58
+ "mov",
59
+ "webm",
60
+ "ogg",
61
+ "ogv",
62
+ "oga",
63
+ "wav",
64
+ "flac",
65
+ "avi",
66
+ "mkv",
67
+ "pdf",
68
+ "csv",
69
+ "doc",
70
+ "docx",
71
+ "xls",
72
+ "xlsx",
73
+ "ppt",
74
+ "pptx",
75
+ "rtf",
76
+ "odt",
77
+ "zip",
78
+ "gz",
79
+ "tgz",
80
+ "tar",
81
+ "rar",
82
+ "7z",
83
+ "bz2",
84
+ "xz",
85
+ "php",
86
+ "phtml",
87
+ "asp",
88
+ "aspx",
89
+ "jsp",
90
+ "cgi",
91
+ "env",
92
+ "ini",
93
+ "yml",
94
+ "yaml",
95
+ "toml",
96
+ "sql",
97
+ "bak",
98
+ "old",
99
+ "swp",
100
+ "log",
101
+ "conf",
102
+ "cfg",
103
+ "exe",
104
+ "dmg",
105
+ "pkg",
106
+ "apk",
107
+ "ipa",
108
+ "msi",
109
+ "iso",
110
+ "bin",
111
+ "dll"
112
+ ]);
113
+ var alternation = FILE_REQUEST_EXTENSIONS.flatMap((ext) => ext === ext.toUpperCase() ? [ext] : [ext, ext.toUpperCase()]).join("|");
114
+ var FILE_SEGMENT = new RegExp(`\\.(?:${alternation})$`);
115
+ var FILE_SEGMENT_GUARD = `(?![^/]*\\.(?:${alternation})$)`;
116
+ function isFileRequestPath(pathname) {
117
+ let path = pathname;
118
+ const cut = path.search(/[?#]/);
119
+ if (cut !== -1)
120
+ path = path.slice(0, cut);
121
+ const last = path.slice(path.lastIndexOf("/") + 1);
122
+ return last.length > 0 && FILE_SEGMENT.test(last);
123
+ }
124
+
125
+ export { extractLayoutMetadata, FILE_SEGMENT_GUARD, isFileRequestPath };
@@ -1,4 +1,8 @@
1
1
  // @bun
2
+ import {
3
+ FILE_SEGMENT_GUARD
4
+ } from "./chunk-fqkc01ey.js";
5
+
2
6
  // ../router/src/file-router.ts
3
7
  import fs3 from "fs";
4
8
  import path4 from "path";
@@ -86,7 +90,8 @@ function filePathToPattern(filePath, pagesDir) {
86
90
  route = route.replace(/:\.\.\.([^/]+)/g, ":$1*");
87
91
  return `/${route}`;
88
92
  }
89
- function patternToRegex(pattern) {
93
+ function patternToRegex(pattern, options = {}) {
94
+ const guard = options.page ? FILE_SEGMENT_GUARD : "";
90
95
  const params = [];
91
96
  let regexStr = "";
92
97
  let i = 0;
@@ -95,7 +100,8 @@ function patternToRegex(pattern) {
95
100
  const optional = /^\/:([^/?*]+)\?/.exec(rest);
96
101
  if (optional) {
97
102
  params.push(optional[1]);
98
- regexStr += "(?:/([^/]+))?";
103
+ const last = i + optional[0].length === pattern.length;
104
+ regexStr += `(?:/${last ? guard : ""}([^/]+))?`;
99
105
  i += optional[0].length;
100
106
  continue;
101
107
  }
@@ -109,7 +115,8 @@ function patternToRegex(pattern) {
109
115
  const required = /^:([^/?*]+)/.exec(rest);
110
116
  if (required) {
111
117
  params.push(required[1]);
112
- regexStr += "([^/]+)";
118
+ const last = i + required[0].length === pattern.length;
119
+ regexStr += `${last ? guard : ""}([^/]+)`;
113
120
  i += required[0].length;
114
121
  continue;
115
122
  }
@@ -210,7 +217,7 @@ class Router {
210
217
  if (seenPatterns.has(identity))
211
218
  continue;
212
219
  seenPatterns.add(identity);
213
- const { regex, params } = patternToRegex(pattern);
220
+ const { regex, params } = patternToRegex(pattern, { page: true });
214
221
  const layouts = config.layouts !== false ? resolveLayoutChain(filePath, dir) : [];
215
222
  this.routes.push({
216
223
  pattern,
package/dist/serve.js CHANGED
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
3
  import {
4
- extractLayoutMetadata
5
- } from "./chunk-qcdy1k88.js";
4
+ extractLayoutMetadata,
5
+ FILE_SEGMENT_GUARD,
6
+ isFileRequestPath
7
+ } from "./chunk-fqkc01ey.js";
6
8
 
7
9
  // src/serve.ts
8
10
  var {serve: bunServe, Glob } = globalThis.Bun;
@@ -9003,7 +9005,7 @@ function csrfCookieHeader(token, secure) {
9003
9005
  ].filter(Boolean).join("; ");
9004
9006
  }
9005
9007
  function buildDynamicRouteRegexes(fileRouteBase) {
9006
- const toPattern = (p) => p.replace(/\[\.\.\.([^\]]+)\]/g, "(.+)").replace(/\[([^\]]+)\]/g, "([^/]+)").replace(/\//g, "\\/");
9008
+ const toPattern = (p) => p.replace(/\[\.\.\.([^\]]+)\]/g, "(.+)").replace(/\[([^\]]+)\]/g, (param, _name, offset, whole) => offset + param.length === whole.length ? `${FILE_SEGMENT_GUARD}([^/]+)` : "([^/]+)").replace(/\//g, "\\/");
9007
9009
  const patterns = [new RegExp(`^${toPattern(fileRouteBase)}$`)];
9008
9010
  const noIndex = fileRouteBase.replace(/\/index$/, "");
9009
9011
  if (noIndex !== fileRouteBase)
@@ -9620,7 +9622,7 @@ function __stxOverlay(errs){
9620
9622
  const pageMiddlewarePatterns = [];
9621
9623
  function compileRoutePattern(urlPath) {
9622
9624
  const names = [];
9623
- const re = urlPath.split("/").map((seg) => {
9625
+ const re = urlPath.split("/").map((seg, index, all) => {
9624
9626
  if (!seg)
9625
9627
  return "";
9626
9628
  const catchAll = seg.match(/^\[\.\.\.(.+)\]$/);
@@ -9631,7 +9633,7 @@ function __stxOverlay(errs){
9631
9633
  const param = seg.match(/^\[(.+)\]$/);
9632
9634
  if (param) {
9633
9635
  names.push(param[1]);
9634
- return "([^/]+)";
9636
+ return index === all.length - 1 ? `${FILE_SEGMENT_GUARD}([^/]+)` : "([^/]+)";
9635
9637
  }
9636
9638
  return seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9637
9639
  }).join("/");
@@ -9925,7 +9927,7 @@ function __stxOverlay(errs){
9925
9927
  rebuildDiscoveredPagePaths(kept);
9926
9928
  await indexPageMiddleware(kept);
9927
9929
  try {
9928
- const { Router } = await import("./chunk-jmbnee6y.js");
9930
+ const { Router } = await import("./chunk-zv29b5s3.js");
9929
9931
  const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
9930
9932
  const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName(), exclude: options.exclude });
9931
9933
  if (!options.quiet)
@@ -11243,10 +11245,16 @@ ${trailingPageScripts.join(`
11243
11245
  }
11244
11246
  }
11245
11247
  }
11246
- if (path === "/favicon.ico") {
11248
+ const isProd = isProductionServe();
11249
+ if (path === "/favicon.ico" && !isProd) {
11247
11250
  return new Response(null, { status: 204 });
11248
11251
  }
11249
- const isProd = isProductionServe();
11252
+ if (isFileRequestPath(path)) {
11253
+ return new Response("Not Found", {
11254
+ status: 404,
11255
+ headers: { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" }
11256
+ });
11257
+ }
11250
11258
  for (const custom404 of ["/404", "/errors/404"]) {
11251
11259
  try {
11252
11260
  const customContent = await getRoute(custom404, reqCtx);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-plugin-stx",
3
3
  "type": "module",
4
- "version": "0.2.414",
4
+ "version": "0.2.416",
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",
@@ -74,7 +74,7 @@
74
74
  "typecheck": "bun tsc --noEmit"
75
75
  },
76
76
  "dependencies": {
77
- "@stacksjs/stx": "0.2.414",
78
- "stx-router": "0.2.414"
77
+ "@stacksjs/stx": "0.2.416",
78
+ "stx-router": "0.2.416"
79
79
  }
80
80
  }
@@ -1,23 +0,0 @@
1
- // @bun
2
- // ../router/src/layout-metadata.ts
3
- function deriveLayoutGroup(layoutPath) {
4
- const normalized = layoutPath.replace(/\\/g, "/");
5
- const segments = normalized.split("/").filter(Boolean);
6
- const layoutsIndex = segments.lastIndexOf("layouts");
7
- const layoutSegment = layoutsIndex >= 0 ? segments[layoutsIndex + 1] : segments.at(-1);
8
- if (!layoutSegment)
9
- return "app";
10
- return layoutSegment.replace(/\.stx$/i, "") || "app";
11
- }
12
- function extractLayoutMetadata(html) {
13
- const layoutMeta = html.match(/<meta\b[^>]*name=["']stx-layout["'][^>]*content=["']([^"']+)["'][^>]*>/i);
14
- const groupMeta = html.match(/<meta\b[^>]*name=["']stx-layout-group["'][^>]*content=["']([^"']+)["'][^>]*>/i);
15
- const layoutComment = html.match(/<!--\s*stx-layout:\s*([^ ]+)\s*-->/i);
16
- const layout = layoutMeta?.[1] || layoutComment?.[1] || "";
17
- return {
18
- layout,
19
- group: groupMeta?.[1] || deriveLayoutGroup(layout)
20
- };
21
- }
22
-
23
- export { extractLayoutMetadata };