@stacksjs/bun-router 0.0.21 → 0.0.23
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 +1 -1
- package/dist/index.js +78 -9
- package/package.json +1 -1
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -3074,7 +3074,19 @@ function findPrebuiltView(stxFilePath, viewsDir) {
|
|
|
3074
3074
|
}
|
|
3075
3075
|
return null;
|
|
3076
3076
|
}
|
|
3077
|
-
|
|
3077
|
+
function parseCookies(header) {
|
|
3078
|
+
const jar = {};
|
|
3079
|
+
for (const part of String(header ?? "").split(";")) {
|
|
3080
|
+
const cut = part.indexOf("=");
|
|
3081
|
+
if (cut < 0)
|
|
3082
|
+
continue;
|
|
3083
|
+
try {
|
|
3084
|
+
jar[part.slice(0, cut).trim()] = decodeURIComponent(part.slice(cut + 1).trim());
|
|
3085
|
+
} catch {}
|
|
3086
|
+
}
|
|
3087
|
+
return jar;
|
|
3088
|
+
}
|
|
3089
|
+
async function renderStxFile(filePath, viewsDir, data, routingConfig, request2) {
|
|
3078
3090
|
const stxModule = "@stacksjs/stx";
|
|
3079
3091
|
const stx = await import(stxModule);
|
|
3080
3092
|
if (!stx.processDirectives || !stx.extractVariables) {
|
|
@@ -3085,11 +3097,42 @@ async function renderStxFile(filePath, viewsDir, data, routingConfig) {
|
|
|
3085
3097
|
const scriptContent = scriptMatch ? scriptMatch[1] : "";
|
|
3086
3098
|
let templateContent = scriptMatch ? content.replace(/<script\s+server\s*>[\s\S]*?<\/script>/i, "") : content;
|
|
3087
3099
|
templateContent = templateContent.replace(/<script\s+client\s*>/gi, "<script>");
|
|
3100
|
+
const asked = { status: 200, headers: {} };
|
|
3101
|
+
const headerBag = data.headers ?? {};
|
|
3102
|
+
const cookieHeader = String(headerBag.cookie ?? headerBag.Cookie ?? "");
|
|
3103
|
+
const requestUrl = String(data.url ?? "");
|
|
3104
|
+
const search = requestUrl.includes("?") ? requestUrl.slice(requestUrl.indexOf("?")) : "";
|
|
3105
|
+
const serveContext = {
|
|
3106
|
+
url: requestUrl,
|
|
3107
|
+
path: String(data.path ?? ""),
|
|
3108
|
+
search,
|
|
3109
|
+
host: String(headerBag.host ?? ""),
|
|
3110
|
+
cookieHeader,
|
|
3111
|
+
cookies: parseCookies(cookieHeader),
|
|
3112
|
+
ip: "",
|
|
3113
|
+
locale: null,
|
|
3114
|
+
params: data.params ?? {},
|
|
3115
|
+
method: String(data.method ?? "GET"),
|
|
3116
|
+
request: request2
|
|
3117
|
+
};
|
|
3088
3118
|
const context = {
|
|
3089
3119
|
__filename: filePath,
|
|
3090
3120
|
__dirname: dirname(filePath),
|
|
3091
3121
|
props: data,
|
|
3092
|
-
...data
|
|
3122
|
+
...data,
|
|
3123
|
+
__stxServeContext: serveContext,
|
|
3124
|
+
setResponseStatus: (status) => {
|
|
3125
|
+
if (Number.isInteger(status) && status >= 100 && status <= 599)
|
|
3126
|
+
asked.status = status;
|
|
3127
|
+
},
|
|
3128
|
+
notFound: (status = 404) => {
|
|
3129
|
+
asked.status = Number.isInteger(status) && status >= 400 && status <= 599 ? status : 404;
|
|
3130
|
+
},
|
|
3131
|
+
setResponseHeader: (name, value) => {
|
|
3132
|
+
if (name)
|
|
3133
|
+
asked.headers[String(name)] = String(value);
|
|
3134
|
+
},
|
|
3135
|
+
definePageMeta: () => {}
|
|
3093
3136
|
};
|
|
3094
3137
|
if (scriptContent) {
|
|
3095
3138
|
await stx.extractVariables(scriptContent, context, filePath);
|
|
@@ -3103,7 +3146,14 @@ async function renderStxFile(filePath, viewsDir, data, routingConfig) {
|
|
|
3103
3146
|
layoutsDir: resolvedLayoutsDir,
|
|
3104
3147
|
partialsDir: resolvedPartialsDir
|
|
3105
3148
|
};
|
|
3106
|
-
|
|
3149
|
+
const html = await stx.processDirectives(templateContent, context, filePath, config2, new Set);
|
|
3150
|
+
const recordedStatus = Number(context.__stxResponseStatus);
|
|
3151
|
+
const recordedHeaders = context.__stxResponseHeaders;
|
|
3152
|
+
return {
|
|
3153
|
+
html,
|
|
3154
|
+
status: Number.isInteger(recordedStatus) && recordedStatus >= 100 && recordedStatus <= 599 ? recordedStatus : asked.status,
|
|
3155
|
+
headers: { ...asked.headers, ...recordedHeaders ?? {} }
|
|
3156
|
+
};
|
|
3107
3157
|
}
|
|
3108
3158
|
function createViewHandler(filePath, viewsDir, config2, queryPreservationConfig) {
|
|
3109
3159
|
return async (req) => {
|
|
@@ -3133,11 +3183,11 @@ function createViewHandler(filePath, viewsDir, config2, queryPreservationConfig)
|
|
|
3133
3183
|
});
|
|
3134
3184
|
}
|
|
3135
3185
|
if (filePath.endsWith(".stx")) {
|
|
3136
|
-
|
|
3137
|
-
html = applyQueryPreservation(html);
|
|
3186
|
+
const rendered = await renderStxFile(filePath, viewsDir, data, config2, req);
|
|
3187
|
+
const html = applyQueryPreservation(rendered.html);
|
|
3138
3188
|
return new Response(html, {
|
|
3139
|
-
status:
|
|
3140
|
-
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
3189
|
+
status: rendered.status,
|
|
3190
|
+
headers: { "Content-Type": "text/html; charset=utf-8", ...rendered.headers }
|
|
3141
3191
|
});
|
|
3142
3192
|
}
|
|
3143
3193
|
let content = await Bun.file(filePath).text();
|
|
@@ -6752,6 +6802,12 @@ class RouteTrie {
|
|
|
6752
6802
|
type: "wildcard",
|
|
6753
6803
|
value: "*"
|
|
6754
6804
|
});
|
|
6805
|
+
} else if (/^\{[^{}/]+\}\*$/.test(part)) {
|
|
6806
|
+
segments.push({
|
|
6807
|
+
type: "wildcard",
|
|
6808
|
+
value: part,
|
|
6809
|
+
paramName: part.slice(1, part.indexOf("}"))
|
|
6810
|
+
});
|
|
6755
6811
|
} else if (part.startsWith("{") && part.endsWith("}")) {
|
|
6756
6812
|
const paramPart = part.slice(1, -1);
|
|
6757
6813
|
const [paramName, pattern] = paramPart.split(":");
|
|
@@ -6837,6 +6893,7 @@ class RouteTrie {
|
|
|
6837
6893
|
case "wildcard":
|
|
6838
6894
|
if (!node.wildcardChild) {
|
|
6839
6895
|
node.wildcardChild = new TrieNode;
|
|
6896
|
+
node.wildcardChild.paramName = segment.paramName ?? null;
|
|
6840
6897
|
}
|
|
6841
6898
|
this.insertRoute(node.wildcardChild, compiled, segmentIndex + 1);
|
|
6842
6899
|
break;
|
|
@@ -6886,7 +6943,7 @@ class RouteTrie {
|
|
|
6886
6943
|
if (node.wildcardChild) {
|
|
6887
6944
|
const compiled = node.wildcardChild.getRoute(method);
|
|
6888
6945
|
if (compiled) {
|
|
6889
|
-
params.wildcard = segments.slice(segmentIndex).join("/");
|
|
6946
|
+
params[node.wildcardChild.paramName ?? "wildcard"] = segments.slice(segmentIndex).join("/");
|
|
6890
6947
|
return {
|
|
6891
6948
|
route: compiled.route,
|
|
6892
6949
|
params,
|
|
@@ -7029,8 +7086,18 @@ class RouteCompiler {
|
|
|
7029
7086
|
}
|
|
7030
7087
|
}
|
|
7031
7088
|
convertToURLPattern(path, constraints) {
|
|
7089
|
+
let staticPath = path;
|
|
7090
|
+
let catchAll = null;
|
|
7091
|
+
const namedCatchAll = staticPath.match(/\{([^{}/]+)\}\*$/);
|
|
7092
|
+
if (namedCatchAll) {
|
|
7093
|
+
catchAll = namedCatchAll[1];
|
|
7094
|
+
staticPath = staticPath.slice(0, namedCatchAll.index);
|
|
7095
|
+
} else if (staticPath.endsWith("*")) {
|
|
7096
|
+
catchAll = "wildcard";
|
|
7097
|
+
staticPath = staticPath.slice(0, -1);
|
|
7098
|
+
}
|
|
7032
7099
|
const paramTokens = [];
|
|
7033
|
-
const withTokens =
|
|
7100
|
+
const withTokens = staticPath.replace(/\{([^}]+)\}/g, (_m, inner) => {
|
|
7034
7101
|
paramTokens.push(inner);
|
|
7035
7102
|
return `\x00${paramTokens.length - 1}\x00`;
|
|
7036
7103
|
});
|
|
@@ -7047,6 +7114,8 @@ class RouteCompiler {
|
|
|
7047
7114
|
const leadingSlash = token.startsWith("/") ? "/" : "";
|
|
7048
7115
|
return isOptional ? `(?:${leadingSlash}${group})?` : `${leadingSlash}${group}`;
|
|
7049
7116
|
});
|
|
7117
|
+
if (catchAll !== null)
|
|
7118
|
+
regexPattern += `(?<${catchAll}>${constraints?.[catchAll] ?? ".+"})`;
|
|
7050
7119
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
7051
7120
|
return {
|
|
7052
7121
|
exec: (pathname) => {
|