@stacksjs/router 0.72.91 → 0.72.93
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 +3 -2
- package/dist/index.js +1 -1
- package/dist/route-loader.d.ts +6 -0
- package/dist/route-loader.js +1 -1
- package/package.json +11 -11
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import './request-augmentation';
|
|
|
4
4
|
export type { StacksRequestExtensions, StacksRequestMacros, StacksRequestMarkers } from './request-augmentation';
|
|
5
5
|
export type { BootHook } from './stacks-router';
|
|
6
6
|
export type { MiddlewareConfig, Request } from './middleware';
|
|
7
|
+
// Export route loader
|
|
8
|
+
export type { RootMountedAppRoute } from './route-loader';
|
|
7
9
|
// Export route registry types — owned here rather than in app/Routes.ts
|
|
8
10
|
// so the path doesn't depend on a 5-level relative reach across the
|
|
9
11
|
// framework defaults tree (stacksjs/stacks#1863, T-10).
|
|
@@ -31,8 +33,7 @@ export { assertRouteMiddlewareResolvable,
|
|
|
31
33
|
export { cacheRequestQuery, clearCurrentRequest, getCurrentRequest, getTraceId, request, runWithRequest, setCurrentRequest, withTraceId } from './request-context';
|
|
32
34
|
// Export Middleware class for defining route middleware
|
|
33
35
|
export { Middleware } from './middleware';
|
|
34
|
-
|
|
35
|
-
export { loadRoutes } from './route-loader';
|
|
36
|
+
export { listRootMountedAppRoutes, loadRoutes } from './route-loader';
|
|
36
37
|
// Export error handler utilities
|
|
37
38
|
export {
|
|
38
39
|
clearTrackedQueries,
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var {require}=import.meta;import"./request-augmentation";export*from"@stacksjs/bun-router";export{assertRouteMiddlewareResolvable,configureViewDirectories,clearCsrfModuleCache,clearMiddlewareCache,createStacksRouter,disableViewRouting,findUnresolvableRouteMiddleware,installMiddlewareHotReload,resetBootHooks,route,runBootHooks,serve,serverResponse,url,warnOnMultipleRouterInstances}from"./stacks-router";export{cacheRequestQuery,clearCurrentRequest,getCurrentRequest,getTraceId,request,runWithRequest,setCurrentRequest,withTraceId}from"./request-context";export{Middleware}from"./middleware";export{loadRoutes}from"./route-loader";export{clearTrackedQueries,createErrorResponse,createMiddlewareErrorResponse,createNotFoundResponse,createValidationErrorResponse,getQueryShapeCounts,trackQuery}from"./error-handler";export{listNamedRoutes,listRegisteredRoutes,routeParams}from"./stacks-router";export{isRouterAction,wrapAction}from"./stacks-router";export{createTypedRouter}from"./typed-router";export{clearRouteModelBindings,defineRouteModelBinding,resolveRouteModel,routeModelBindings,setRouteModelFallback}from"./route-model-binding";export{isApiRequest,JSON_CONTENT_TYPE}from"./api-shape";export{rateLimit,rateLimitStatus,clearRateLimit}from"./rate-limit";export{PathParamError,safePathParam,sanitizePathParam}from"./path-sanitize";export{checkApplicationHealth,runHealthProbes}from"./health";export{stream}from"./stacks-router";export{signedUrl,signUrl,verifySignedUrl,verifySignedUrlMiddleware}from"./signed-url";export{EncryptedSessionStore}from"./encrypted-session-store";export{createSessionStore,createStacksSessionStore,DatabaseSessionStore,FileSessionStore,MemorySessionStore,RedisSessionStore}from"./session-factory";import("@stacksjs/database").then(({setQueryTracker})=>{if(typeof setQueryTracker==="function"){const{trackQuery}=require("./error-handler");setQueryTracker(trackQuery)}}).catch(()=>{});
|
|
1
|
+
var {require}=import.meta;import"./request-augmentation";export*from"@stacksjs/bun-router";export{assertRouteMiddlewareResolvable,configureViewDirectories,clearCsrfModuleCache,clearMiddlewareCache,createStacksRouter,disableViewRouting,findUnresolvableRouteMiddleware,installMiddlewareHotReload,resetBootHooks,route,runBootHooks,serve,serverResponse,url,warnOnMultipleRouterInstances}from"./stacks-router";export{cacheRequestQuery,clearCurrentRequest,getCurrentRequest,getTraceId,request,runWithRequest,setCurrentRequest,withTraceId}from"./request-context";export{Middleware}from"./middleware";export{listRootMountedAppRoutes,loadRoutes}from"./route-loader";export{clearTrackedQueries,createErrorResponse,createMiddlewareErrorResponse,createNotFoundResponse,createValidationErrorResponse,getQueryShapeCounts,trackQuery}from"./error-handler";export{listNamedRoutes,listRegisteredRoutes,routeParams}from"./stacks-router";export{isRouterAction,wrapAction}from"./stacks-router";export{createTypedRouter}from"./typed-router";export{clearRouteModelBindings,defineRouteModelBinding,resolveRouteModel,routeModelBindings,setRouteModelFallback}from"./route-model-binding";export{isApiRequest,JSON_CONTENT_TYPE}from"./api-shape";export{rateLimit,rateLimitStatus,clearRateLimit}from"./rate-limit";export{PathParamError,safePathParam,sanitizePathParam}from"./path-sanitize";export{checkApplicationHealth,runHealthProbes}from"./health";export{stream}from"./stacks-router";export{signedUrl,signUrl,verifySignedUrl,verifySignedUrlMiddleware}from"./signed-url";export{EncryptedSessionStore}from"./encrypted-session-store";export{createSessionStore,createStacksSessionStore,DatabaseSessionStore,FileSessionStore,MemorySessionStore,RedisSessionStore}from"./session-factory";import("@stacksjs/database").then(({setQueryTracker})=>{if(typeof setQueryTracker==="function"){const{trackQuery}=require("./error-handler");setQueryTracker(trackQuery)}}).catch(()=>{});
|
package/dist/route-loader.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RouteRegistry } from './route-types';
|
|
2
|
+
export declare function listRootMountedAppRoutes(): readonly RootMountedAppRoute[];
|
|
2
3
|
/**
|
|
3
4
|
* Load all routes from the registry
|
|
4
5
|
*/
|
|
@@ -99,4 +100,9 @@ export declare const DEFAULT_ROUTE_BUNDLES: readonly ['auth', 'dashboard', 'emai
|
|
|
99
100
|
export declare const OPT_IN_ROUTE_BUNDLES: readonly ['social'];
|
|
100
101
|
/** Where {@link loadFrameworkRoutes} leaves the selection for bootstrap.ts. */
|
|
101
102
|
export declare const DEFAULT_ROUTE_BUNDLES_KEY: '__stacksDefaultRouteBundles';
|
|
103
|
+
export declare interface RootMountedAppRoute {
|
|
104
|
+
method: string
|
|
105
|
+
path: string
|
|
106
|
+
file: string
|
|
107
|
+
}
|
|
102
108
|
export type DefaultRouteBundle = typeof DEFAULT_ROUTE_BUNDLES[number] | typeof OPT_IN_ROUTE_BUNDLES[number];
|
package/dist/route-loader.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{log}from"@stacksjs/logging";import{route}from"./stacks-router";const NO_PREFIX_KEYS=["web"];export async function loadRoutes(registry){for(const[key,definition]of Object.entries(registry)){const config=normalizeDefinition(definition),prefix=config.prefix!==void 0?config.prefix?config.prefix.startsWith("/")?config.prefix:`/${config.prefix}`:void 0:NO_PREFIX_KEYS.includes(key)?void 0:`/${key}`,middleware=normalizeMiddleware(config.middleware);log.debug(`[route-loader] Loading: ${config.path} prefix=${prefix||"/"} middleware=[${middleware.join(", ")}]`);try{if(prefix||middleware.length>0)await route.group({prefix,middleware:middleware.length>0?middleware:void 0},async()=>{await importRouteFile(config.path)});else await importRouteFile(config.path)}catch(error){const message=error instanceof Error?error.message:String(error);console.error(`[Routes] Failed to load route file '${config.path}': ${message}`);throw Error(`Route loading failed for '${config.path}': ${message}`)}}await loadFrameworkRoutes()}export const DEFAULT_ROUTE_BUNDLES=["auth","dashboard","email","forms"],OPT_IN_ROUTE_BUNDLES=["social"],DEFAULT_ROUTE_BUNDLES_KEY="__stacksDefaultRouteBundles";export function resolveDefaultRouteBundles(env=process.env){return resolveDefaultRouteBundlesWithDiagnostics(env).bundles}export function resolveDefaultRouteBundlesWithDiagnostics(env=process.env){const all=()=>new Set(DEFAULT_ROUTE_BUNDLES),raw=env.STACKS_DEFAULT_ROUTES;if(raw!==void 0){const names=raw.split(",").map((name)=>name.trim().toLowerCase()).filter(Boolean);if(names.length===0||names.includes("none"))return{bundles:new Set,unknown:[],explicit:!0};if(names.includes("all"))return{bundles:all(),unknown:[],explicit:!0};const bundles=new Set,unknown=[];for(const name of names)if(DEFAULT_ROUTE_BUNDLES.includes(name)||OPT_IN_ROUTE_BUNDLES.includes(name))bundles.add(name);else unknown.push(name);return{bundles,unknown,explicit:!0}}if(env.STACKS_SKIP_DEFAULT_ROUTES==="1")return{bundles:new Set,unknown:[],explicit:!0};return{bundles:all(),unknown:[],explicit:!1}}async function loadFrameworkRoutes(){const{bundles,unknown,explicit}=resolveDefaultRouteBundlesWithDiagnostics();for(const name of unknown)log.warn(`[Routes] STACKS_DEFAULT_ROUTES lists unknown bundle "${name}" - known bundles are ${DEFAULT_ROUTE_BUNDLES.join(", ")}.`);if(bundles.size===0)return;globalThis[DEFAULT_ROUTE_BUNDLES_KEY]={bundles,explicit};try{try{const{overridesReady}=await import("@stacksjs/config");await overridesReady}catch{}const{frameworkPath}=await import("@stacksjs/path"),bootstrapPath=frameworkPath("defaults/bootstrap.ts");if(await Bun.file(bootstrapPath).exists())await import(bootstrapPath)}catch(error){const message=error instanceof Error?error.message:String(error);if(!message.includes("Cannot find module")&&!message.includes("MODULE_NOT_FOUND"))console.error(`[Routes] Failed to load framework bootstrap: ${message}`)}}function assertSafeRouteName(routeName){if(typeof routeName!=="string"||routeName.length===0)throw Error("[route-loader] Invalid route path: empty or non-string");if(routeName.includes("\x00"))throw Error("[route-loader] Invalid route path: null byte");let decoded;try{decoded=decodeURIComponent(routeName)}catch{throw Error("[route-loader] Invalid route path: malformed URL encoding")}const cleanPath=decoded.replace(/\.ts$/,"");if(cleanPath.startsWith("/")||/^[A-Za-z]:[\\/]/.test(cleanPath))throw Error(`[route-loader] Invalid route path: absolute paths not allowed (${cleanPath})`);if(cleanPath.split(/[/\\]/).some((s)=>s===".."))throw Error(`[route-loader] Invalid route path: '..' segment not allowed (${cleanPath})`);return cleanPath}async function importRouteFile(routeName){const cleanPath=assertSafeRouteName(routeName),{projectPath}=await import("@stacksjs/path");await import(projectPath(`routes/${cleanPath}`))}function normalizeDefinition(def){if(typeof def==="string")return{path:def};return def}function normalizeMiddleware(middleware){if(!middleware)return[];if(typeof middleware==="string")return[middleware];return middleware}
|
|
1
|
+
import{log}from"@stacksjs/logging";import{route}from"./stacks-router";const NO_PREFIX_KEYS=["web"],rootMountedAppRoutes=[];export function listRootMountedAppRoutes(){return rootMountedAppRoutes}export async function loadRoutes(registry){for(const[key,definition]of Object.entries(registry)){const config=normalizeDefinition(definition),prefix=config.prefix!==void 0?config.prefix?config.prefix.startsWith("/")?config.prefix:`/${config.prefix}`:void 0:NO_PREFIX_KEYS.includes(key)?void 0:`/${key}`,middleware=normalizeMiddleware(config.middleware);log.debug(`[route-loader] Loading: ${config.path} prefix=${prefix||"/"} middleware=[${middleware.join(", ")}]`);try{if(prefix||middleware.length>0)await route.group({prefix,middleware:middleware.length>0?middleware:void 0},async()=>{await importRouteFile(config.path)});else{const before=registeredRouteKeys();await importRouteFile(config.path);for(const entry of currentRouteTable()){const method=String(entry.method??"").toUpperCase(),path=String(entry.path??"");if(!method||!path||before.has(`${method} ${path}`))continue;rootMountedAppRoutes.push({method,path,file:`routes/${config.path}.ts`})}}}catch(error){const message=error instanceof Error?error.message:String(error);console.error(`[Routes] Failed to load route file '${config.path}': ${message}`);throw Error(`Route loading failed for '${config.path}': ${message}`)}}await loadFrameworkRoutes()}export const DEFAULT_ROUTE_BUNDLES=["auth","dashboard","email","forms"],OPT_IN_ROUTE_BUNDLES=["social"],DEFAULT_ROUTE_BUNDLES_KEY="__stacksDefaultRouteBundles";export function resolveDefaultRouteBundles(env=process.env){return resolveDefaultRouteBundlesWithDiagnostics(env).bundles}export function resolveDefaultRouteBundlesWithDiagnostics(env=process.env){const all=()=>new Set(DEFAULT_ROUTE_BUNDLES),raw=env.STACKS_DEFAULT_ROUTES;if(raw!==void 0){const names=raw.split(",").map((name)=>name.trim().toLowerCase()).filter(Boolean);if(names.length===0||names.includes("none"))return{bundles:new Set,unknown:[],explicit:!0};if(names.includes("all"))return{bundles:all(),unknown:[],explicit:!0};const bundles=new Set,unknown=[];for(const name of names)if(DEFAULT_ROUTE_BUNDLES.includes(name)||OPT_IN_ROUTE_BUNDLES.includes(name))bundles.add(name);else unknown.push(name);return{bundles,unknown,explicit:!0}}if(env.STACKS_SKIP_DEFAULT_ROUTES==="1")return{bundles:new Set,unknown:[],explicit:!0};return{bundles:all(),unknown:[],explicit:!1}}async function loadFrameworkRoutes(){const{bundles,unknown,explicit}=resolveDefaultRouteBundlesWithDiagnostics();for(const name of unknown)log.warn(`[Routes] STACKS_DEFAULT_ROUTES lists unknown bundle "${name}" - known bundles are ${DEFAULT_ROUTE_BUNDLES.join(", ")}.`);if(bundles.size===0)return;globalThis[DEFAULT_ROUTE_BUNDLES_KEY]={bundles,explicit};try{try{const{overridesReady}=await import("@stacksjs/config");await overridesReady}catch{}const{frameworkPath}=await import("@stacksjs/path"),bootstrapPath=frameworkPath("defaults/bootstrap.ts");if(await Bun.file(bootstrapPath).exists())await import(bootstrapPath)}catch(error){const message=error instanceof Error?error.message:String(error);if(!message.includes("Cannot find module")&&!message.includes("MODULE_NOT_FOUND"))console.error(`[Routes] Failed to load framework bootstrap: ${message}`)}}function assertSafeRouteName(routeName){if(typeof routeName!=="string"||routeName.length===0)throw Error("[route-loader] Invalid route path: empty or non-string");if(routeName.includes("\x00"))throw Error("[route-loader] Invalid route path: null byte");let decoded;try{decoded=decodeURIComponent(routeName)}catch{throw Error("[route-loader] Invalid route path: malformed URL encoding")}const cleanPath=decoded.replace(/\.ts$/,"");if(cleanPath.startsWith("/")||/^[A-Za-z]:[\\/]/.test(cleanPath))throw Error(`[route-loader] Invalid route path: absolute paths not allowed (${cleanPath})`);if(cleanPath.split(/[/\\]/).some((s)=>s===".."))throw Error(`[route-loader] Invalid route path: '..' segment not allowed (${cleanPath})`);return cleanPath}async function importRouteFile(routeName){const cleanPath=assertSafeRouteName(routeName),{projectPath}=await import("@stacksjs/path");await import(projectPath(`routes/${cleanPath}`))}function normalizeDefinition(def){if(typeof def==="string")return{path:def};return def}function normalizeMiddleware(middleware){if(!middleware)return[];if(typeof middleware==="string")return[middleware];return middleware}function currentRouteTable(){return route.routes??[]}function registeredRouteKeys(){const keys=new Set;for(const entry of currentRouteTable())keys.add(`${String(entry.method??"").toUpperCase()} ${String(entry.path??"")}`);return keys}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/router",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.72.
|
|
5
|
+
"version": "0.72.93",
|
|
6
6
|
"description": "The Stacks framework router.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -61,19 +61,19 @@
|
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@stacksjs/bun-router": "^0.1.8",
|
|
64
|
-
"@stacksjs/collections": "0.72.
|
|
64
|
+
"@stacksjs/collections": "0.72.93",
|
|
65
65
|
"ts-rate-limiter": "^0.4.2"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@stacksjs/actions": "0.72.
|
|
69
|
-
"@stacksjs/config": "0.72.
|
|
68
|
+
"@stacksjs/actions": "0.72.93",
|
|
69
|
+
"@stacksjs/config": "0.72.93",
|
|
70
70
|
"better-dx": "^0.2.24",
|
|
71
|
-
"@stacksjs/error-handling": "0.72.
|
|
72
|
-
"@stacksjs/logging": "0.72.
|
|
73
|
-
"@stacksjs/orm": "0.72.
|
|
74
|
-
"@stacksjs/path": "0.72.
|
|
75
|
-
"@stacksjs/storage": "0.72.
|
|
76
|
-
"@stacksjs/types": "0.72.
|
|
77
|
-
"@stacksjs/validation": "0.72.
|
|
71
|
+
"@stacksjs/error-handling": "0.72.93",
|
|
72
|
+
"@stacksjs/logging": "0.72.93",
|
|
73
|
+
"@stacksjs/orm": "0.72.93",
|
|
74
|
+
"@stacksjs/path": "0.72.93",
|
|
75
|
+
"@stacksjs/storage": "0.72.93",
|
|
76
|
+
"@stacksjs/types": "0.72.93",
|
|
77
|
+
"@stacksjs/validation": "0.72.93"
|
|
78
78
|
}
|
|
79
79
|
}
|