@stacksjs/server 0.70.319 → 0.70.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/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from './controllers/base';
3
3
  export * from './imports';
4
4
  export * from './maintenance';
5
5
  export * from './proxy';
6
+ export * from './redirects';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{config as server}from"./config";export*from"./controllers/base";export*from"./imports";export*from"./maintenance";export*from"./proxy";
1
+ export{config as server}from"./config";export*from"./controllers/base";export*from"./imports";export*from"./maintenance";export*from"./proxy";export*from"./redirects";
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Normalise app configuration into the map the resolver reads.
3
+ *
4
+ * Resolved once at boot rather than per request: `@stacksjs/config` fills in
5
+ * overrides asynchronously, so a per-request read would answer differently
6
+ * depending on how far boot had got.
7
+ *
8
+ * Invalid entries are dropped rather than thrown on. A malformed redirect
9
+ * should not stop a site from booting, and the one that matters — a rule that
10
+ * points at itself, which would loop the browser until it gives up — is caught
11
+ * here rather than in production.
12
+ */
13
+ export declare function resolveRedirectRules(input?: RedirectConfig): RedirectRules;
14
+ /**
15
+ * The response for a redirected path, or undefined to carry on routing.
16
+ *
17
+ * Matching is exact on the normalised path. Prefix and pattern rules are
18
+ * deliberately not supported: a redirect table is read by whoever is debugging
19
+ * a URL at two in the morning, and every wildcard in it is a thing they have
20
+ * to simulate in their head to know what a given path does.
21
+ */
22
+ export declare function resolveRedirect(url: URL, rules?: RedirectRules): Response | undefined;
23
+ /**
24
+ * A one-line summary for the dev server's boot output.
25
+ *
26
+ * Same reasoning as `describeApiProxyRules`: a redirect you did not expect is
27
+ * very hard to diagnose when the rule that caused it is invisible.
28
+ */
29
+ export declare function describeRedirectRules(rules: RedirectRules): string;
30
+ /** Permanent unless the app says otherwise: these describe moved pages. */
31
+ export declare const DEFAULT_REDIRECT_STATUS: 301;
32
+ export declare interface RedirectTarget {
33
+ to: string
34
+ status?: number
35
+ preserveQuery?: boolean
36
+ }
37
+ export declare interface RedirectRule {
38
+ from: string
39
+ to: string
40
+ status: number
41
+ preserveQuery: boolean
42
+ }
43
+ /** What an app writes in `config/server.ts` under `redirects`. */
44
+ export type RedirectConfig = Record<string, string | RedirectTarget>;
45
+ export type RedirectRules = Map<string, RedirectRule>;
@@ -0,0 +1 @@
1
+ const PROTECTED_PREFIX="/api/";export const DEFAULT_REDIRECT_STATUS=301;function normalizePath(value){const path=String(value).trim();if(!path.startsWith("/"))return"";return path.length>1&&path.endsWith("/")?path.replace(/\/+$/,""):path}export function resolveRedirectRules(input={}){const rules=new Map;for(const[rawFrom,rawTarget]of Object.entries(input??{})){const from=normalizePath(rawFrom);if(!from)continue;if(from===PROTECTED_PREFIX.slice(0,-1)||from.startsWith(PROTECTED_PREFIX))continue;const target=typeof rawTarget==="string"?{to:rawTarget}:rawTarget,to=String(target?.to??"").trim();if(!to)continue;if(!/^https?:\/\//i.test(to)&&normalizePath(to)===from)continue;rules.set(from,{from,to,status:Number(target?.status)||DEFAULT_REDIRECT_STATUS,preserveQuery:target?.preserveQuery!==!1})}return rules}export function resolveRedirect(url,rules){if(!rules?.size)return;const rule=rules.get(normalizePath(url.pathname));if(!rule)return;let location=rule.to;if(rule.preserveQuery&&url.search)location+=location.includes("?")?`&${url.search.slice(1)}`:url.search;return new Response(null,{status:rule.status,headers:{Location:location,"Cache-Control":rule.status===301||rule.status===308?"public, max-age=3600":"no-store"}})}export function describeRedirectRules(rules){if(!rules.size)return"none";const shown=[...rules.values()].slice(0,3).map((rule)=>`${rule.from} \u2192 ${rule.to}`),rest=rules.size-shown.length;return rest>0?`${shown.join(", ")} (+${rest} more)`:shown.join(", ")}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/server",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.319",
5
+ "version": "0.70.320",
6
6
  "description": "Local development and production-ready.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -58,11 +58,11 @@
58
58
  "prepublishOnly": "bun run build"
59
59
  },
60
60
  "devDependencies": {
61
- "@stacksjs/config": "0.70.319",
61
+ "@stacksjs/config": "0.70.320",
62
62
  "better-dx": "^0.2.17",
63
- "@stacksjs/path": "0.70.319",
64
- "@stacksjs/router": "0.70.319",
65
- "@stacksjs/validation": "0.70.319"
63
+ "@stacksjs/path": "0.70.320",
64
+ "@stacksjs/router": "0.70.320",
65
+ "@stacksjs/validation": "0.70.320"
66
66
  },
67
67
  "dependencies": {
68
68
  "bun-plugin-auto-imports": "^0.4.0"