rouzer 1.0.0-beta.12 → 1.0.0-beta.14

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.
@@ -1,6 +1,5 @@
1
- import type { AdapterRequestContext } from '@hattip/core';
2
1
  import { type Params } from '@remix-run/route-pattern';
3
- import { chain, MiddlewareChain, type MiddlewareContext } from 'alien-middleware';
2
+ import { chain, MiddlewareChain, type HattipContext, type MiddlewareContext } from 'alien-middleware';
4
3
  import * as z from 'zod/mini';
5
4
  import type { InferRouteResponse, MutationMethod, Promisable, QueryMethod, Routes } from '../types.js';
6
5
  export { chain };
@@ -95,7 +94,7 @@ export declare function createRouter<TRoutes extends Routes, TMiddleware extends
95
94
  } ? z.infer<T["path"]> : Params<TRoutes[K]["path"]["source"]>;
96
95
  body: z.infer<T["body"]>;
97
96
  headers: z.infer<T["headers"]>;
98
- }) => Promisable<Response | InferRouteResponse<T>> : never : never : never; }; }) => import("alien-middleware").ApplyMiddleware<TMiddleware, (context: AdapterRequestContext<TMiddleware extends MiddlewareChain<infer T extends {
97
+ }) => Promisable<Response | InferRouteResponse<T>> : never : never : never; }; }) => import("alien-middleware").ApplyMiddleware<TMiddleware, (context: HattipContext<TMiddleware extends MiddlewareChain<infer T extends {
99
98
  initial: {
100
99
  env: object;
101
100
  properties: object;
@@ -105,7 +104,7 @@ export declare function createRouter<TRoutes extends Routes, TMiddleware extends
105
104
  properties: object;
106
105
  };
107
106
  platform: unknown;
108
- }> ? T["platform"] : never> & {
107
+ }> ? T["platform"] : never, any> & {
109
108
  url?: URL | undefined;
110
109
  path?: {} | undefined;
111
110
  }) => Promise<Response | undefined>>;
@@ -23,6 +23,12 @@ export function createRouter(config) {
23
23
  });
24
24
  return (handlers) => middlewares.use(async function (context) {
25
25
  const request = context.request;
26
+ const origin = request.headers.get('Origin');
27
+ if (origin &&
28
+ allowOrigins &&
29
+ !allowOrigins.some(pattern => pattern.test(origin))) {
30
+ return new Response(null, { status: 403 });
31
+ }
26
32
  const url = (context.url ??= new URL(request.url));
27
33
  let method = request.method.toUpperCase();
28
34
  let isPreflight = false;
@@ -47,11 +53,6 @@ export function createRouter(config) {
47
53
  continue;
48
54
  }
49
55
  if (isPreflight) {
50
- const origin = request.headers.get('Origin');
51
- if (allowOrigins &&
52
- !(origin && allowOrigins.some(pattern => pattern.test(origin)))) {
53
- return new Response(null, { status: 403 });
54
- }
55
56
  return new Response(null, {
56
57
  headers: {
57
58
  'Access-Control-Allow-Origin': origin ?? '*',
@@ -60,6 +61,9 @@ export function createRouter(config) {
60
61
  },
61
62
  });
62
63
  }
64
+ if (origin) {
65
+ context.setHeader('Access-Control-Allow-Origin', origin);
66
+ }
63
67
  if (route.path) {
64
68
  const error = parsePathParams(context, enableStringParsing(route.path), match.params);
65
69
  if (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rouzer",
3
- "version": "1.0.0-beta.12",
3
+ "version": "1.0.0-beta.14",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -22,7 +22,7 @@
22
22
  "dependencies": {
23
23
  "@hattip/core": "^0.0.49",
24
24
  "@remix-run/route-pattern": "^0.15.3",
25
- "alien-middleware": "^0.10.2"
25
+ "alien-middleware": "^0.10.3"
26
26
  },
27
27
  "prettier": "@alloc/prettier-config",
28
28
  "license": "MIT",
package/readme.md CHANGED
@@ -39,6 +39,17 @@ The following request parts can be validated with Zod:
39
39
 
40
40
  Zod validation happens on both the server and client.
41
41
 
42
+ ## Route URL patterns
43
+
44
+ Rouzer uses `@remix-run/route-pattern` for matching and generation. Patterns can include:
45
+
46
+ - Pathname-only patterns like `blog/:slug` (default).
47
+ - Full URLs with protocol/hostname/port like `https://:store.shopify.com/orders`.
48
+ - Dynamic segments with `:param` names (valid JS identifiers), including multiple params in one segment like `v:major.:minor`.
49
+ - Optional segments wrapped in parentheses, which can be nested like `api(/v:major(.:minor))`.
50
+ - Wildcards with `*name` (captured) or `*` (uncaptured) for multi-segment paths like `assets/*path` or `files/*`.
51
+ - Query matching with `?` to require parameters or exact values like `search?q` or `search?q=routing`.
52
+
42
53
  ## Server router
43
54
 
44
55
  ```ts
@@ -66,6 +77,34 @@ export const handler = createRouter({
66
77
  })
67
78
  ```
68
79
 
80
+ ## Router options
81
+
82
+ ```ts
83
+ export const handler = createRouter({
84
+ routes,
85
+ middlewares,
86
+ basePath: 'api/',
87
+ cors: {
88
+ allowOrigins: ['example.net', 'https://*.example.com', '*://localhost:3000'],
89
+ },
90
+ debug: process.env.NODE_ENV === 'development',
91
+ })({
92
+ helloRoute: {
93
+ GET(ctx) {
94
+ const message = `Hello, ${ctx.path.name}${ctx.query.excited ? '!' : '.'}`
95
+ return { message }
96
+ },
97
+ },
98
+ })
99
+ ```
100
+
101
+ - `basePath` is prepended to every route (leading/trailing slashes are trimmed).
102
+ - CORS preflight (`OPTIONS`) is handled automatically for matched routes.
103
+ - `cors.allowOrigins` restricts preflight requests to a list of origins (default is to allow any origin).
104
+ - Wildcards are supported for protocol and subdomain; the protocol is optional and defaults to `https`.
105
+ - If you rely on `Cookie` or `Authorization` request headers, you must set
106
+ `Access-Control-Allow-Credentials` in your handler.
107
+
69
108
  ## Client wrapper
70
109
 
71
110
  ```ts