rouzer 5.2.2 → 5.3.1

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/README.md CHANGED
@@ -59,7 +59,7 @@ Import the primary API from the root package and declare routes through the HTTP
59
59
  subpath:
60
60
 
61
61
  ```ts
62
- import { $error, $type, chain, createClient, createRouter } from 'rouzer'
62
+ import { $error, $type, chain, createClient, createRouter, metadata } from 'rouzer'
63
63
  import * as http from 'rouzer/http'
64
64
  ```
65
65
 
@@ -181,6 +181,29 @@ await client.upload(file, { headers: { 'content-type': file.type } })
181
181
  Server handlers for raw-body routes read from `ctx.request` directly with Fetch
182
182
  APIs such as `arrayBuffer()`, `blob()`, `formData()`, or `text()`.
183
183
 
184
+ ### Route metadata
185
+
186
+ Use `metadata(...)` to attach optional runtime metadata to HTTP resources or
187
+ actions. Metadata does not affect routing, validation, client typing, or handler
188
+ behavior; it is preserved on route nodes for generated clients, CLIs, docs, and
189
+ route inspectors.
190
+
191
+ ```ts
192
+ export const sessions = http.resource('sessions', {
193
+ ...metadata({
194
+ description: 'Daemon-managed session control.',
195
+ }),
196
+ list: http.post('list', {
197
+ ...metadata({
198
+ description: 'Lists daemon-managed sessions and pagination state.',
199
+ }),
200
+ response: $type<SessionList>(),
201
+ }),
202
+ })
203
+ ```
204
+
205
+ The constructed nodes expose metadata as `node.metadata`.
206
+
184
207
  ### Client lifecycle hooks
185
208
 
186
209
  Pass `clientHook` to observe generated client action calls without wrapping the
package/dist/http.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RoutePattern } from '@remix-run/route-pattern';
2
+ import { type RouteMetadata } from './metadata.js';
2
3
  import type { RawBodySchema, RouteSchema } from './types/schema.js';
3
4
  /** HTTP methods supported by Rouzer action declarations. */
4
5
  export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
@@ -17,6 +18,8 @@ export type HttpAction<P extends string = string, T extends RouteSchema = RouteS
17
18
  method: M;
18
19
  /** Request validation and optional response type schema. */
19
20
  schema: T;
21
+ /** Optional runtime metadata for generated tooling. */
22
+ metadata?: RouteMetadata;
20
23
  };
21
24
  /**
22
25
  * Path-scoped namespace in an HTTP route tree.
@@ -31,6 +34,8 @@ export type HttpResource<P extends string = string, TChildren extends HttpRouteT
31
34
  path: RoutePattern<P>;
32
35
  /** Child resources and actions exposed below this resource. */
33
36
  children: TChildren;
37
+ /** Optional runtime metadata for generated tooling. */
38
+ metadata?: RouteMetadata;
34
39
  };
35
40
  /** Node type accepted inside an HTTP route tree. */
36
41
  export type HttpNode = HttpAction | HttpResource;
@@ -38,6 +43,7 @@ export type HttpNode = HttpAction | HttpResource;
38
43
  export type HttpRouteTree = {
39
44
  [key: string]: HttpNode;
40
45
  };
46
+ type StringKeys<T> = Pick<T, Extract<keyof T, string>>;
41
47
  /**
42
48
  * Declare an HTTP resource namespace.
43
49
  *
@@ -45,7 +51,7 @@ export type HttpRouteTree = {
45
51
  * property names are API names only; they do not affect the URL unless the child
46
52
  * is another resource or an action with an explicit path.
47
53
  */
48
- export declare function resource<const P extends string, const TChildren extends HttpRouteTree>(path: P, children: TChildren): HttpResource<P, TChildren>;
54
+ export declare function resource<const P extends string, const TChildren extends HttpRouteTree>(path: P, children: TChildren): HttpResource<P, StringKeys<TChildren>>;
49
55
  /** Declare a GET action, optionally with an action-local path segment. */
50
56
  export declare function get<const P extends string, const T extends RouteSchema>(path: P, schema: T): HttpAction<P, T, 'GET'>;
51
57
  export declare function get<const T extends RouteSchema>(schema: T): HttpAction<'', T, 'GET'>;
package/dist/http.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RoutePattern } from '@remix-run/route-pattern';
2
+ import { getRouteMetadata, stripRouteMetadata, } from './metadata.js';
2
3
  /**
3
4
  * Declare an HTTP resource namespace.
4
5
  *
@@ -7,10 +8,12 @@ import { RoutePattern } from '@remix-run/route-pattern';
7
8
  * is another resource or an action with an explicit path.
8
9
  */
9
10
  export function resource(path, children) {
11
+ const metadata = getRouteMetadata(children);
10
12
  return {
11
13
  kind: 'resource',
12
14
  path: RoutePattern.parse(path),
13
- children,
15
+ children: stripRouteMetadata(children),
16
+ metadata,
14
17
  };
15
18
  }
16
19
  export function get(pathOrSchema, schema) {
@@ -47,5 +50,12 @@ function action(method, pathOrSchema, schema) {
47
50
  ? RoutePattern.parse(pathOrSchema)
48
51
  : undefined;
49
52
  schema ??= typeof pathOrSchema === 'string' ? {} : pathOrSchema;
50
- return { kind: 'action', path, method, schema };
53
+ const metadata = getRouteMetadata(schema);
54
+ return {
55
+ kind: 'action',
56
+ path,
57
+ method,
58
+ schema: stripRouteMetadata(schema),
59
+ metadata,
60
+ };
51
61
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './client/index.js';
2
+ export { metadata, type RouteMetadata } from './metadata.js';
2
3
  export * from './response.js';
3
4
  export * from './type.js';
4
5
  export * from './server/router.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './client/index.js';
2
+ export { metadata } from './metadata.js';
2
3
  export * from './response.js';
3
4
  export * from './type.js';
4
5
  export * from './server/router.js';
@@ -0,0 +1,13 @@
1
+ declare const routeMetadataKey: unique symbol;
2
+ /** Runtime metadata attached to Rouzer route nodes. */
3
+ export type RouteMetadata = {
4
+ /** Short label for generated indexes, clients, CLIs, or docs. */
5
+ summary?: string;
6
+ /** Human-readable route description for generated tooling. */
7
+ description?: string;
8
+ };
9
+ /** Attach runtime metadata to a route declaration. */
10
+ export declare function metadata(value: RouteMetadata): object;
11
+ export declare function getRouteMetadata(value: unknown): RouteMetadata | undefined;
12
+ export declare function stripRouteMetadata<T extends object>(value: T): Omit<T, typeof routeMetadataKey>;
13
+ export {};
@@ -0,0 +1,14 @@
1
+ const routeMetadataKey = Symbol('rouzer.metadata');
2
+ /** Attach runtime metadata to a route declaration. */
3
+ export function metadata(value) {
4
+ return { [routeMetadataKey]: value };
5
+ }
6
+ export function getRouteMetadata(value) {
7
+ return typeof value === 'object' && value !== null
8
+ ? value[routeMetadataKey]
9
+ : undefined;
10
+ }
11
+ export function stripRouteMetadata(value) {
12
+ const { [routeMetadataKey]: _metadata, ...rest } = value;
13
+ return rest;
14
+ }
package/docs/context.md CHANGED
@@ -72,6 +72,29 @@ paths are joined, so the examples above expose `profiles/:id`, `profiles/:id`,
72
72
  and `profiles/:id/posts`. Path params from parent resources are accumulated into
73
73
  child action types.
74
74
 
75
+ Use the root `metadata(...)` helper to attach optional runtime metadata to
76
+ resources or actions without changing route matching, validation, client typing,
77
+ or handler behavior:
78
+
79
+ ```ts
80
+ import { metadata } from 'rouzer'
81
+
82
+ export const sessions = http.resource('sessions', {
83
+ ...metadata({
84
+ description: 'Daemon-managed session control.',
85
+ }),
86
+ list: http.post('list', {
87
+ ...metadata({
88
+ description: 'Lists daemon-managed sessions and pagination state.',
89
+ }),
90
+ response: $type<SessionList>(),
91
+ }),
92
+ })
93
+ ```
94
+
95
+ Constructed route nodes expose metadata through `node.metadata` for generated
96
+ clients, CLIs, docs, and route inspectors.
97
+
75
98
  Patterns are parsed by `@remix-run/route-pattern` v0.21. Params can be inferred
76
99
  from patterns such as `hello/:name`, `v:major.:minor`,
77
100
  `api(/v:major(.:minor))`, `assets/*path`, and `search?q`. Full URL patterns such
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rouzer",
3
- "version": "5.2.2",
3
+ "version": "5.3.1",
4
4
  "packageManager": "pnpm@11.5.1",
5
5
  "type": "module",
6
6
  "exports": {