@fishka/express 0.9.14 → 0.9.15

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
@@ -12,56 +12,105 @@ npm install @fishka/express
12
12
 
13
13
  ```typescript
14
14
  import express from 'express';
15
- import { createRouteTable } from '@fishka/express';
15
+ import { createRouteTable, param, toInt } from '@fishka/express';
16
+ import { assertString } from '@fishka/assertions';
16
17
 
17
18
  const app = express();
18
19
  app.use(express.json());
19
20
 
20
21
  const routes = createRouteTable(app);
21
22
 
22
- // GET /users/:id - using function shorthand
23
- routes.get<{ id: string; name: string }>('users/:id', async ctx => ({
24
- id: ctx.params.get('id'),
25
- name: 'John',
26
- }));
23
+ // GET /users/:id - with typed path params
24
+ routes.get('users/:id', {
25
+ $path: { id: param(toInt()) },
26
+ run: async ctx => ({
27
+ id: ctx.path.id, // number - typed from $path
28
+ name: 'John',
29
+ }),
30
+ });
27
31
 
28
- // GET /users - using full endpoint object
29
- routes.get<Array<{ id: string; name: string }>>('users', async () => [
30
- { id: '1', name: 'John' },
31
- { id: '2', name: 'Jane' },
32
+ // GET /users - list all users
33
+ routes.get('users', async () => [
34
+ { id: 1, name: 'John' },
35
+ { id: 2, name: 'Jane' },
32
36
  ]);
33
37
 
34
- // POST /users
35
- routes.post<{ name: string }, { id: string }>('users', {
38
+ // POST /users - with body validation
39
+ routes.post<{ name: string }, { id: number }>('users', {
36
40
  $body: { name: v => assertString(v, 'name required') },
37
- run: async ctx => ({ id: '1' }),
41
+ run: async ctx => ({ id: 1 }),
38
42
  });
39
43
 
40
- // DELETE /users/:id - using function shorthand
41
- routes.delete('users/:id', async () => {
42
- // Delete user logic
43
- });
44
+ // DELETE /users/:id
45
+ routes.delete('users/:id', async () => {});
44
46
 
45
47
  app.listen(3000);
46
48
  ```
47
49
 
48
- ## URL Parameters
50
+ ## URL Parameter Validation
49
51
 
50
- Global validation can be enforced for specific URL parameters (e.g., `:id`, `:orgId`) across all routes.
52
+ Use `param()` to validate and transform path/query parameters. All operators are composable:
51
53
 
52
54
  ```typescript
53
- import { registerUrlParameter } from '@fishka/express';
54
- import { assertString, assertTruthy } from '@fishka/assertions';
55
-
56
- // Register parameters with optional validation
57
- registerUrlParameter('orgId', {
58
- validator: val => {
59
- assertString(val);
60
- assertTruthy(val.startsWith('org-'), 'Invalid Organization ID');
55
+ import { param, toInt, minLength, matches, min, range, oneOf } from '@fishka/express';
56
+
57
+ routes.get('users/:id', {
58
+ $path: {
59
+ id: param(toInt()), // string → number
61
60
  },
61
+ $query: {
62
+ page: param(toInt(), min(1)), // number >= 1
63
+ limit: param(toInt(), range(1, 100)), // number 1-100
64
+ sort: param(oneOf('asc', 'desc')), // enum
65
+ search: param(minLength(3)), // string min 3 chars
66
+ },
67
+ run: async ctx => ({
68
+ id: ctx.path.id, // number
69
+ page: ctx.query.page, // number
70
+ sort: ctx.query.sort, // 'asc' | 'desc'
71
+ }),
62
72
  });
73
+ ```
74
+
75
+ ### Available Operators
76
+
77
+ **Transformations (string → T):**
78
+ - `toInt()` - parse to integer
79
+ - `toNumber()` - parse to number
80
+ - `toBool()` - parse 'true'/'false' to boolean
81
+ - `oneOf('a', 'b')` - enum values
82
+
83
+ **String validators:**
84
+ - `minLength(n)` - minimum length
85
+ - `maxLength(n)` - maximum length
86
+ - `matches(/regex/)` - regex match
87
+ - `trim` - trim whitespace
88
+ - `lowercase` / `uppercase` - case transform
89
+
90
+ **Number validators:**
91
+ - `min(n)` - minimum value
92
+ - `max(n)` - maximum value
93
+ - `range(min, max)` - value range
94
+
95
+ **Generic:**
96
+ - `check(fn, msg)` - custom validation
97
+ - `map(fn)` - transform value
98
+
99
+ ### Optional Parameters
63
100
 
64
- // Now /orgs/:orgId will automatically validate that orgId starts with 'org-'
101
+ Use `optional()` to make parameters optional:
102
+
103
+ ```typescript
104
+ import { optional, param, toInt } from '@fishka/express';
105
+
106
+ routes.get('users', {
107
+ $query: {
108
+ page: optional(param(toInt())), // number | undefined
109
+ },
110
+ run: async ctx => {
111
+ const page = ctx.query.page ?? 1;
112
+ },
113
+ });
65
114
  ```
66
115
 
67
116
  ## Authentication
@@ -110,12 +159,11 @@ assertHttp(user.isAdmin, HTTP_FORBIDDEN, 'Admin access required');
110
159
 
111
160
  ## Complete Example
112
161
 
113
- Here is a full initialization including TLS context, global validation, and proper error handling.
162
+ Full initialization with TLS context, validation, and error handling:
114
163
 
115
164
  ```typescript
116
165
  import express from 'express';
117
- import { createRouteTable, createTlsMiddleware, catchAllMiddleware, registerUrlParameter } from '@fishka/express';
118
- import { assertString, assertTruthy } from '@fishka/assertions';
166
+ import { createRouteTable, createTlsMiddleware, catchAllMiddleware, param, toInt } from '@fishka/express';
119
167
 
120
168
  const app = express();
121
169
 
@@ -125,17 +173,17 @@ app.use(express.json());
125
173
  // 2. Initialize TLS context (Request IDs, etc.)
126
174
  app.use(createTlsMiddleware());
127
175
 
128
- // 3. Register global URL parameters
129
- registerUrlParameter('id', {
130
- validator: val => assertString(val),
131
- });
132
-
133
- // 4. Define routes
176
+ // 3. Define routes with typed parameters
134
177
  const routes = createRouteTable(app);
178
+
135
179
  routes.get('health', async () => ({ status: 'UP' }));
136
180
 
137
- // 5. Error handler - catches middleware/parsing errors
138
- // Can also be mounted per-path: app.use('/api', catchAllMiddleware)
181
+ routes.get('users/:id', {
182
+ $path: { id: param(toInt()) },
183
+ run: async ctx => ({ id: ctx.path.id }),
184
+ });
185
+
186
+ // 4. Error handler - catches middleware/parsing errors
139
187
  app.use(catchAllMiddleware);
140
188
 
141
189
  app.listen(3000);
@@ -1,5 +1,11 @@
1
- import { ValueAssertion } from '@fishka/assertions';
2
- export type UrlTokensValidator = Record<string, ValueAssertion<string>>;
1
+ /** Validator function that validates and returns typed value */
2
+ export type TypeValidator<T> = (value: unknown) => T;
3
+ /** Map of param name to type validator */
4
+ export type TypedValidatorMap = Record<string, TypeValidator<unknown>>;
5
+ /** Infer validated types from validator map */
6
+ export type InferValidated<T extends TypedValidatorMap | undefined> = T extends TypedValidatorMap ? {
7
+ [K in keyof T]: ReturnType<T[K]>;
8
+ } : Record<string, never>;
3
9
  export declare class HttpError extends Error {
4
10
  readonly status: number;
5
11
  readonly details?: Record<string, unknown> | undefined;
@@ -62,22 +68,3 @@ export interface ApiResponse<ResponseEntity = unknown> {
62
68
  }
63
69
  /** Converts an API response value into a standardized ApiResponse structure. */
64
70
  export declare function response<T = unknown>(result: T): ApiResponse<T>;
65
- /** Globally identified URL (path or query) parameter info. */
66
- export interface UrlParameterInfo {
67
- /** Optional global validator for this parameter. */
68
- validator?: ValueAssertion<string>;
69
- /** Description for documentation. */
70
- description?: string;
71
- }
72
- /**
73
- * Default documentation and validation for URL parameters.
74
- * @Internal
75
- */
76
- export declare const URL_PARAMETER_INFO: Record<string, UrlParameterInfo>;
77
- /** Registers a new URL parameter. */
78
- export declare function registerUrlParameter(name: string, info: UrlParameterInfo): void;
79
- /**
80
- * Asserts that the value is a registered URL parameter name.
81
- * @Internal
82
- */
83
- export declare function assertUrlParameter(name: unknown): asserts name is string;
@@ -1,12 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.URL_PARAMETER_INFO = exports.HttpError = void 0;
3
+ exports.HttpError = void 0;
4
4
  exports.assertHttp = assertHttp;
5
5
  exports.response = response;
6
- exports.registerUrlParameter = registerUrlParameter;
7
- exports.assertUrlParameter = assertUrlParameter;
8
6
  const assertions_1 = require("@fishka/assertions");
9
- const http_status_codes_1 = require("./http-status-codes");
10
7
  class HttpError extends Error {
11
8
  constructor(status, message, details) {
12
9
  super(message);
@@ -55,21 +52,4 @@ function assertHttp(value, status, message) {
55
52
  function response(result) {
56
53
  return { result };
57
54
  }
58
- /**
59
- * Default documentation and validation for URL parameters.
60
- * @Internal
61
- */
62
- exports.URL_PARAMETER_INFO = {};
63
- /** Registers a new URL parameter. */
64
- function registerUrlParameter(name, info) {
65
- exports.URL_PARAMETER_INFO[name] = info;
66
- }
67
- /**
68
- * Asserts that the value is a registered URL parameter name.
69
- * @Internal
70
- */
71
- function assertUrlParameter(name) {
72
- assertHttp(typeof name === 'string', http_status_codes_1.HTTP_BAD_REQUEST, 'Url parameter name must be a string');
73
- assertHttp(exports.URL_PARAMETER_INFO[name], http_status_codes_1.HTTP_BAD_REQUEST, `Invalid URL parameter: '${name}'. Please register it using 'registerUrlParameter('${name}', ...)'`);
74
- }
75
55
  //# sourceMappingURL=api.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.types.js","sourceRoot":"","sources":["../../src/api.types.ts"],"names":[],"mappings":";;;AAgDA,gCAEC;AA2BD,4BAEC;AAiBD,oDAEC;AAMD,gDAOC;AA/GD,mDAAkE;AAClE,2DAAuD;AAIvD,MAAa,SAAU,SAAQ,KAAK;IAClC,YACkB,MAAc,EAC9B,OAAe,EACC,OAAiC;QAEjD,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,WAAM,GAAN,MAAM,CAAQ;QAEd,YAAO,GAAP,OAAO,CAA0B;QAGjD,qDAAqD;QACrD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnD,CAAC;CACF;AAVD,8BAUC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,SAAgB,UAAU,CAAC,KAAc,EAAE,MAAc,EAAE,OAAe;IACxE,IAAA,yBAAY,EAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AA0BD,gFAAgF;AAChF,SAAgB,QAAQ,CAAc,MAAS;IAC7C,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC;AAUD;;;GAGG;AACU,QAAA,kBAAkB,GAAqC,EAAE,CAAC;AAEvE,qCAAqC;AACrC,SAAgB,oBAAoB,CAAC,IAAY,EAAE,IAAsB;IACvE,0BAAkB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,IAAa;IAC9C,UAAU,CAAC,OAAO,IAAI,KAAK,QAAQ,EAAE,oCAAgB,EAAE,qCAAqC,CAAC,CAAC;IAC9F,UAAU,CACR,0BAAkB,CAAC,IAAI,CAAC,EACxB,oCAAgB,EAChB,2BAA2B,IAAI,sDAAsD,IAAI,UAAU,CACpG,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"api.types.js","sourceRoot":"","sources":["../../src/api.types.ts"],"names":[],"mappings":";;;AAyDA,gCAEC;AA2BD,4BAEC;AAxFD,mDAAkD;AAclD,MAAa,SAAU,SAAQ,KAAK;IAClC,YACkB,MAAc,EAC9B,OAAe,EACC,OAAiC;QAEjD,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,WAAM,GAAN,MAAM,CAAQ;QAEd,YAAO,GAAP,OAAO,CAA0B;QAGjD,qDAAqD;QACrD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnD,CAAC;CACF;AAVD,8BAUC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,SAAgB,UAAU,CAAC,KAAc,EAAE,MAAc,EAAE,OAAe;IACxE,IAAA,yBAAY,EAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC;AA0BD,gFAAgF;AAChF,SAAgB,QAAQ,CAAc,MAAS;IAC7C,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
@@ -13,3 +13,4 @@ export * from './router';
13
13
  export * from './thread-local/thread-local-storage';
14
14
  export * from './thread-local/thread-local-storage-middleware';
15
15
  export * from './utils/express.utils';
16
+ export * from './utils/type-validators';
package/dist/cjs/index.js CHANGED
@@ -29,4 +29,5 @@ __exportStar(require("./router"), exports);
29
29
  __exportStar(require("./thread-local/thread-local-storage"), exports);
30
30
  __exportStar(require("./thread-local/thread-local-storage-middleware"), exports);
31
31
  __exportStar(require("./utils/express.utils"), exports);
32
+ __exportStar(require("./utils/type-validators"), exports);
32
33
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,uDAAqC;AACrC,oDAAkC;AAClC,oDAAkC;AAClC,8DAA4C;AAC5C,2CAAyB;AACzB,mDAAiC;AACjC,sDAAoC;AACpC,sEAAoD;AACpD,gEAA8C;AAC9C,gDAA8B;AAC9B,2CAAyB;AACzB,sEAAoD;AACpD,iFAA+D;AAC/D,wDAAsC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,uDAAqC;AACrC,oDAAkC;AAClC,oDAAkC;AAClC,8DAA4C;AAC5C,2CAAyB;AACzB,mDAAiC;AACjC,sDAAoC;AACpC,sEAAoD;AACpD,gEAA8C;AAC9C,gDAA8B;AAC9B,2CAAyB;AACzB,sEAAoD;AACpD,iFAA+D;AAC/D,wDAAsC;AACtC,0DAAwC"}
@@ -1,3 +1,4 @@
1
+ import { TypedValidatorMap } from './api.types';
1
2
  import { DeleteEndpoint, GetEndpoint, PatchEndpoint, PostEndpoint, PutEndpoint, RequestContext, ResponseOrValue } from './router';
2
3
  import { ExpressRouter } from './utils/express.utils';
3
4
  /**
@@ -7,12 +8,19 @@ import { ExpressRouter } from './utils/express.utils';
7
8
  export declare class RouteTable {
8
9
  private readonly app;
9
10
  constructor(app: ExpressRouter);
10
- get<T>(path: string, endpoint: GetEndpoint<T> | GetEndpoint<T[]>): this;
11
- get<T>(path: string, run: (ctx: RequestContext) => ResponseOrValue<T> | Promise<ResponseOrValue<T>>): this;
12
- post<Body, Result>(path: string, endpoint: PostEndpoint<Body, Result>): this;
13
- patch<Body, Result>(path: string, endpoint: PatchEndpoint<Body, Result>): this;
14
- put<Body, Result>(path: string, endpoint: PutEndpoint<Body, Result>): this;
15
- delete(path: string, endpoint: DeleteEndpoint): this;
11
+ /** Register GET endpoint with full type inference for path/query params. */
12
+ get<Result, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap>(path: string, endpoint: GetEndpoint<Result, PathParams, QueryParams>): this;
13
+ /** Register GET endpoint with function shorthand. */
14
+ get<Result>(path: string, run: (ctx: RequestContext) => ResponseOrValue<Result> | Promise<ResponseOrValue<Result>>): this;
15
+ /** Register POST endpoint with full type inference for path/query params. */
16
+ post<Body, Result = void, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap>(path: string, endpoint: PostEndpoint<Body, Result, PathParams, QueryParams>): this;
17
+ /** Register PATCH endpoint with full type inference for path/query params. */
18
+ patch<Body, Result = void, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap>(path: string, endpoint: PatchEndpoint<Body, Result, PathParams, QueryParams>): this;
19
+ /** Register PUT endpoint with full type inference for path/query params. */
20
+ put<Body, Result = void, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap>(path: string, endpoint: PutEndpoint<Body, Result, PathParams, QueryParams>): this;
21
+ /** Register DELETE endpoint with full endpoint object. */
22
+ delete<PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap>(path: string, endpoint: DeleteEndpoint<PathParams, QueryParams>): this;
23
+ /** Register DELETE endpoint with function shorthand. */
16
24
  delete(path: string, run: (ctx: RequestContext) => void | Promise<void>): this;
17
25
  }
18
26
  /**
@@ -16,14 +16,17 @@ class RouteTable {
16
16
  (0, router_1.mountGet)(this.app, path, endpoint);
17
17
  return this;
18
18
  }
19
+ /** Register POST endpoint with full type inference for path/query params. */
19
20
  post(path, endpoint) {
20
21
  (0, router_1.mountPost)(this.app, path, endpoint);
21
22
  return this;
22
23
  }
24
+ /** Register PATCH endpoint with full type inference for path/query params. */
23
25
  patch(path, endpoint) {
24
26
  (0, router_1.mountPatch)(this.app, path, endpoint);
25
27
  return this;
26
28
  }
29
+ /** Register PUT endpoint with full type inference for path/query params. */
27
30
  put(path, endpoint) {
28
31
  (0, router_1.mountPut)(this.app, path, endpoint);
29
32
  return this;
@@ -1 +1 @@
1
- {"version":3,"file":"route-table.js","sourceRoot":"","sources":["../../src/route-table.ts"],"names":[],"mappings":";;;AAkEA,4CAEC;AApED,qCAakB;AAGlB;;;GAGG;AACH,MAAa,UAAU;IACrB,YAA6B,GAAkB;QAAlB,QAAG,GAAH,GAAG,CAAe;IAAG,CAAC;IAInD,GAAG,CACD,IAAY,EACZ,aAG+E;QAE/E,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,iBAAQ,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAA0B,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAe,IAAY,EAAE,QAAoC;QACnE,IAAA,kBAAS,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAe,IAAY,EAAE,QAAqC;QACrE,IAAA,mBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAe,IAAY,EAAE,QAAmC;QACjE,IAAA,iBAAQ,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAID,MAAM,CAAC,IAAY,EAAE,aAA+E;QAClG,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,oBAAW,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAvCD,gCAuCC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,GAAkB;IACjD,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"route-table.js","sourceRoot":"","sources":["../../src/route-table.ts"],"names":[],"mappings":";;;AA6GA,4CAEC;AA9GD,qCAakB;AAGlB;;;GAGG;AACH,MAAa,UAAU;IACrB,YAA6B,GAAkB;QAAlB,QAAG,GAAH,GAAG,CAAe;IAAG,CAAC;IAYnD,GAAG,CAKD,IAAY,EACZ,aAEyF;QAEzF,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,iBAAQ,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAgC,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAC7E,IAAI,CAKF,IAAY,EAAE,QAA6D;QAC3E,IAAA,kBAAS,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAA4C,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAKH,IAAY,EAAE,QAA8D;QAC5E,IAAA,mBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAA6C,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4EAA4E;IAC5E,GAAG,CAKD,IAAY,EAAE,QAA4D;QAC1E,IAAA,iBAAQ,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAA2C,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IAWD,MAAM,CAIJ,IAAY,EACZ,aAAwG;QAExG,MAAM,QAAQ,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAC9F,IAAA,oBAAW,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAA0B,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAjFD,gCAiFC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,GAAkB;IACjD,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { Assertion, ObjectAssertion } from '@fishka/assertions';
2
- import { ApiResponse, UrlTokensValidator } from './api.types';
2
+ import { ApiResponse, InferValidated, TypedValidatorMap } from './api.types';
3
3
  import { AuthUser } from './auth/auth.types';
4
4
  import { ExpressRequest, ExpressResponse, ExpressRouter } from './utils/express.utils';
5
5
  /** Express API allows handlers to return a response in the raw form. */
@@ -10,7 +10,7 @@ export type ResponseOrValue<ResponseEntity> = ApiResponse<ResponseEntity> | Resp
10
10
  */
11
11
  export type EndpointMiddleware<Context = RequestContext> = (run: () => Promise<unknown>, context: Context) => Promise<unknown>;
12
12
  /** Generic request context passed to all handlers. Database-agnostic and extensible. */
13
- export interface RequestContext<Body = void> {
13
+ export interface RequestContext<Body = void, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap> {
14
14
  /** Parsed and validated request body (for POST/PATCH/PUT handlers). */
15
15
  body: Body;
16
16
  /** Express Request object. */
@@ -19,18 +19,10 @@ export interface RequestContext<Body = void> {
19
19
  res: ExpressResponse;
20
20
  /** Authenticated user (if any). Populated by auth middleware. */
21
21
  authUser?: AuthUser;
22
- /**
23
- * Generic parameter access with lazy validation.
24
- * Provides type-safe access to URL path and query parameters.
25
- */
26
- params: {
27
- get(key: string): string;
28
- tryGet(key: string): string | undefined;
29
- };
30
- /** Query parameter access. */
31
- query: {
32
- get(key: string): string | undefined;
33
- };
22
+ /** Validated path parameters (typed from $path validators). */
23
+ path: InferValidated<PathParams>;
24
+ /** Validated query parameters (typed from $query validators). */
25
+ query: InferValidated<QueryParams>;
34
26
  /**
35
27
  * Generic state storage for middleware to attach data.
36
28
  * Allows middleware to pass information to handlers and other middleware.
@@ -38,31 +30,31 @@ export interface RequestContext<Body = void> {
38
30
  state: Map<string, unknown>;
39
31
  }
40
32
  /** Base interface with common endpoint properties. */
41
- export interface EndpointBase<Context = RequestContext, Result = unknown> {
42
- /** Path parameter validator. */
43
- $path?: UrlTokensValidator;
44
- /** Query parameter validator. */
45
- $query?: UrlTokensValidator;
33
+ export interface EndpointBase<PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap, Body = void, Result = unknown> {
34
+ /** Path parameter validators (typed). */
35
+ $path?: PathParams;
36
+ /** Query parameter validators (typed). */
37
+ $query?: QueryParams;
46
38
  /** Optional middleware to execute before the handler. */
47
39
  middlewares?: Array<EndpointMiddleware>;
48
40
  /** Handler function. Can be sync or async. */
49
- run: (ctx: Context) => ResponseOrValue<Result> | Promise<ResponseOrValue<Result>>;
41
+ run: (ctx: RequestContext<Body, PathParams, QueryParams>) => ResponseOrValue<Result> | Promise<ResponseOrValue<Result>>;
50
42
  }
51
43
  /** Descriptor for GET list routes. */
52
- export type GetListEndpoint<ResultElementType> = EndpointBase<RequestContext, Array<ResultElementType>>;
44
+ export type GetListEndpoint<ResultElementType, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap> = EndpointBase<PathParams, QueryParams, void, Array<ResultElementType>>;
53
45
  /** Descriptor for GET routes. */
54
- export type GetEndpoint<Result> = EndpointBase<RequestContext, Result>;
46
+ export type GetEndpoint<Result, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap> = EndpointBase<PathParams, QueryParams, void, Result>;
55
47
  /** Descriptor for POST routes. */
56
- export interface PostEndpoint<Body, Result = void> extends EndpointBase<RequestContext<Body>, Result> {
48
+ export interface PostEndpoint<Body, Result = void, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap> extends EndpointBase<PathParams, QueryParams, Body, Result> {
57
49
  /** Request body validator. */
58
50
  $body: Body extends object ? ObjectAssertion<Body> : Assertion<Body>;
59
51
  }
60
52
  /** Same as POST. Used for full object updates. */
61
- export type PutEndpoint<Body, Result = void> = PostEndpoint<Body, Result>;
53
+ export type PutEndpoint<Body, Result = void, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap> = PostEndpoint<Body, Result, PathParams, QueryParams>;
62
54
  /** Same as PUT. While PUT is used for the whole object update, PATCH is used for a partial update. */
63
- export type PatchEndpoint<Body, Result = void> = PutEndpoint<Body, Result>;
55
+ export type PatchEndpoint<Body, Result = void, PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap> = PutEndpoint<Body, Result, PathParams, QueryParams>;
64
56
  /** Descriptor for DELETE routes. */
65
- export type DeleteEndpoint = EndpointBase<RequestContext, void>;
57
+ export type DeleteEndpoint<PathParams extends TypedValidatorMap = TypedValidatorMap, QueryParams extends TypedValidatorMap = TypedValidatorMap> = EndpointBase<PathParams, QueryParams, void, void>;
66
58
  /** Union type for all route registration info objects. */
67
59
  export type RouteRegistrationInfo = ({
68
60
  method: 'get';
@@ -98,51 +98,46 @@ function createRouteHandler(method, endpoint) {
98
98
  }
99
99
  /**
100
100
  * @Internal
101
- * Validates request parameters using custom validators.
101
+ * Validates and builds typed path/query parameters using $path and $query validators.
102
102
  */
103
- function validateUrlParameters(req, { $path, $query, }) {
103
+ function buildValidatedParams(req, $path, $query) {
104
+ const pathResult = {};
105
+ const queryResult = {};
104
106
  try {
105
- for (const key in req.params) {
106
- const value = req.params[key];
107
- // Run Global Validation if registered.
108
- const globalValidator = api_types_1.URL_PARAMETER_INFO[key]?.validator;
109
- if (globalValidator) {
110
- (0, assertions_1.callValueAssertion)(value, globalValidator, `${http_status_codes_1.HTTP_BAD_REQUEST}`);
111
- }
112
- // Run Local Validation.
113
- const validator = $path?.[key];
114
- if (validator) {
115
- (0, assertions_1.callValueAssertion)(value, validator, `${http_status_codes_1.HTTP_BAD_REQUEST}`);
107
+ // Validate path params
108
+ if ($path) {
109
+ for (const [key, validator] of Object.entries($path)) {
110
+ const value = req.params[key];
111
+ pathResult[key] = validator(value);
116
112
  }
117
113
  }
118
- const parsedUrl = url.parse(req.url, true);
119
- for (const key in parsedUrl.query) {
120
- const value = parsedUrl.query[key];
121
- // Global Validation if registered (also applies to query params if names match).
122
- const globalValidator = api_types_1.URL_PARAMETER_INFO[key]?.validator;
123
- if (globalValidator) {
124
- // Query params can be string | string[] | undefined. Global validators usually expect string.
125
- // We only validate if it's a single value or handle array in validator.
126
- // For simplicity, we pass value as is (unknown) to assertion.
127
- (0, assertions_1.callValueAssertion)(value, globalValidator, `${http_status_codes_1.HTTP_BAD_REQUEST}`);
128
- }
129
- const validator = $query?.[key];
130
- if (validator) {
131
- (0, assertions_1.callValueAssertion)(value, validator, `${http_status_codes_1.HTTP_BAD_REQUEST}`);
114
+ // Validate query params
115
+ if ($query) {
116
+ const parsedUrl = url.parse(req.url, true);
117
+ for (const [key, validator] of Object.entries($query)) {
118
+ const rawValue = parsedUrl.query[key];
119
+ const value = Array.isArray(rawValue) ? rawValue[0] : rawValue;
120
+ queryResult[key] = validator(value);
132
121
  }
133
122
  }
134
123
  }
135
124
  catch (error) {
125
+ if (error instanceof api_types_1.HttpError)
126
+ throw error;
136
127
  throw new api_types_1.HttpError(http_status_codes_1.HTTP_BAD_REQUEST, (0, assertions_1.getMessageFromError)(error));
137
128
  }
129
+ return {
130
+ path: pathResult,
131
+ query: queryResult,
132
+ };
138
133
  }
139
134
  /**
140
135
  * @Internal
141
136
  * Runs GET handler with optional middleware.
142
137
  */
143
138
  async function executeGetEndpoint(route, req, res) {
144
- const requestContext = newRequestContext(undefined, req, res);
145
- validateUrlParameters(req, { $path: route.$path, $query: route.$query });
139
+ const validated = buildValidatedParams(req, route.$path, route.$query);
140
+ const requestContext = newRequestContext(undefined, req, res, validated.path, validated.query);
146
141
  return await executeWithMiddleware(() => route.run(requestContext), route.middlewares || [], requestContext);
147
142
  }
148
143
  /**
@@ -150,8 +145,8 @@ async function executeGetEndpoint(route, req, res) {
150
145
  * Runs DELETE handler with optional middleware.
151
146
  */
152
147
  async function executeDeleteEndpoint(route, req, res) {
153
- const requestContext = newRequestContext(undefined, req, res);
154
- validateUrlParameters(req, { $path: route.$path, $query: route.$query });
148
+ const validated = buildValidatedParams(req, route.$path, route.$query);
149
+ const requestContext = newRequestContext(undefined, req, res, validated.path, validated.query);
155
150
  await executeWithMiddleware(() => route.run(requestContext), route.middlewares || [], requestContext);
156
151
  return undefined;
157
152
  }
@@ -165,12 +160,11 @@ async function executeBodyEndpoint(route, req, res) {
165
160
  try {
166
161
  // Handle validation based on whether the validator is an object or function
167
162
  if (typeof validator === 'function') {
168
- // It's a ValueAssertion (function)
169
- (0, assertions_1.callValueAssertion)(apiRequest, validator, `${http_status_codes_1.HTTP_BAD_REQUEST}: request body`);
163
+ // It's a ValueAssertion (function) - call it directly
164
+ validator(apiRequest);
170
165
  }
171
166
  else {
172
167
  // It's an ObjectAssertion - use validateObject
173
- // We strictly assume it is an object because of the type definition (function | object)
174
168
  const objectValidator = validator;
175
169
  const isEmptyValidator = Object.keys(objectValidator).length === 0;
176
170
  const errorMessage = (0, assertions_1.validateObject)(apiRequest, objectValidator, `${http_status_codes_1.HTTP_BAD_REQUEST}: request body`, {
@@ -184,9 +178,8 @@ async function executeBodyEndpoint(route, req, res) {
184
178
  throw error;
185
179
  throw new api_types_1.HttpError(http_status_codes_1.HTTP_BAD_REQUEST, (0, assertions_1.getMessageFromError)(error));
186
180
  }
187
- const requestContext = newRequestContext(apiRequest, req, res);
188
- validateUrlParameters(req, { $path: route.$path, $query: route.$query });
189
- requestContext.body = req.body;
181
+ const validated = buildValidatedParams(req, route.$path, route.$query);
182
+ const requestContext = newRequestContext(apiRequest, req, res, validated.path, validated.query);
190
183
  return await executeWithMiddleware(() => route.run(requestContext), (route.middlewares || []), requestContext);
191
184
  }
192
185
  /**
@@ -208,26 +201,13 @@ async function executeWithMiddleware(run, middlewares, context) {
208
201
  * @Internal
209
202
  * Creates a new RequestContext instance.
210
203
  */
211
- function newRequestContext(requestBody, req, res) {
204
+ function newRequestContext(requestBody, req, res, validatedPath, validatedQuery) {
212
205
  return {
213
206
  body: requestBody,
214
207
  req,
215
208
  res,
216
- params: {
217
- get: (key) => {
218
- const value = req.params[key];
219
- (0, api_types_1.assertHttp)(value, http_status_codes_1.HTTP_BAD_REQUEST, `Path parameter '${key}' not found`);
220
- return value;
221
- },
222
- tryGet: (key) => req.params[key],
223
- },
224
- query: {
225
- get: (key) => {
226
- const parsedUrl = url.parse(req.url, true);
227
- const value = parsedUrl.query[key];
228
- return Array.isArray(value) ? value[0] : value;
229
- },
230
- },
209
+ path: validatedPath,
210
+ query: validatedQuery,
231
211
  state: new Map(),
232
212
  };
233
213
  }
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router.ts"],"names":[],"mappings":"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"}