@veloxts/router 0.8.0 → 0.8.2

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/types.d.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import type { BaseContext } from '@veloxts/core';
10
10
  import type { HttpMethod } from '@veloxts/validation';
11
+ import type { PipelineStep } from './procedure/pipeline.js';
11
12
  import type { ResourceSchema } from './resource/schema.js';
12
13
  /**
13
14
  * Procedure operation types
@@ -16,14 +17,6 @@ import type { ResourceSchema } from './resource/schema.js';
16
17
  * - mutation: Write operations (maps to POST/PUT/DELETE in REST)
17
18
  */
18
19
  export type ProcedureType = 'query' | 'mutation';
19
- /**
20
- * HTTP methods supported by the REST adapter
21
- *
22
- * Full REST support: GET, POST, PUT, PATCH, DELETE
23
- *
24
- * @see {@link PROCEDURE_METHOD_MAP} for naming convention mapping
25
- */
26
- export type { HttpMethod };
27
20
  /**
28
21
  * Maps procedure naming conventions to HTTP methods
29
22
  *
@@ -40,6 +33,14 @@ export type { HttpMethod };
40
33
  * - deleteUser -> DELETE
41
34
  */
42
35
  export { PROCEDURE_METHOD_MAP } from '@veloxts/validation';
36
+ /**
37
+ * HTTP methods supported by the REST adapter
38
+ *
39
+ * Full REST support: GET, POST, PUT, PATCH, DELETE
40
+ *
41
+ * @see {@link PROCEDURE_METHOD_MAP} for naming convention mapping
42
+ */
43
+ export type { HttpMethod };
43
44
  /**
44
45
  * Extended context type that can be augmented by middleware
45
46
  *
@@ -106,6 +107,24 @@ export interface GuardLike<TContext = unknown> {
106
107
  /** HTTP status code on failure (default: 403) */
107
108
  statusCode?: number;
108
109
  }
110
+ /**
111
+ * Policy action reference interface for declarative authorization
112
+ *
113
+ * This interface is compatible with @veloxts/auth's PolicyActionRef but doesn't
114
+ * create a hard dependency. Any object matching this shape can be used as a policy
115
+ * action in the procedure builder.
116
+ *
117
+ * @template TUser - The user type the policy operates on
118
+ * @template TResource - The resource type the policy checks against
119
+ */
120
+ export interface PolicyActionLike<TUser = unknown, TResource = unknown, TResourceName extends string = string> {
121
+ /** The name of the action (e.g., 'update', 'delete') */
122
+ readonly actionName: string;
123
+ /** The name of the resource this policy applies to (e.g., 'Post') */
124
+ readonly resourceName: TResourceName;
125
+ /** Execute the policy check for this action */
126
+ readonly check: (user: TUser, resource?: TResource) => boolean | Promise<boolean>;
127
+ }
109
128
  /**
110
129
  * Result returned by the next() function in middleware
111
130
  *
@@ -264,6 +283,19 @@ export interface ParentResourceChain {
264
283
  */
265
284
  readonly parents: readonly ParentResourceConfig[];
266
285
  }
286
+ /**
287
+ * Options for database transaction wrapping
288
+ *
289
+ * Controls isolation level and timeout when `.transactional()` is used
290
+ * on a procedure. These options are forwarded directly to Prisma's
291
+ * `$transaction()` method.
292
+ */
293
+ export interface TransactionalOptions {
294
+ /** Transaction isolation level (forwarded to Prisma) */
295
+ isolationLevel?: 'ReadUncommitted' | 'ReadCommitted' | 'RepeatableRead' | 'Serializable' | 'Snapshot';
296
+ /** Transaction timeout in milliseconds */
297
+ timeout?: number;
298
+ }
267
299
  /**
268
300
  * Compiled procedure with all metadata and handlers
269
301
  *
@@ -274,8 +306,9 @@ export interface ParentResourceChain {
274
306
  * @template TOutput - The handler output type
275
307
  * @template TContext - The context type
276
308
  * @template TType - The procedure type literal ('query' or 'mutation')
309
+ * @template TErrors - Union of domain error types this procedure can throw (defaults to never)
277
310
  */
278
- export interface CompiledProcedure<TInput = unknown, TOutput = unknown, TContext extends BaseContext = BaseContext, TType extends ProcedureType = ProcedureType> {
311
+ export interface CompiledProcedure<TInput = unknown, TOutput = unknown, TContext extends BaseContext = BaseContext, TType extends ProcedureType = ProcedureType, TErrors = never> {
279
312
  /** Whether this is a query or mutation */
280
313
  readonly type: TType;
281
314
  /** The procedure handler function */
@@ -383,13 +416,119 @@ export interface CompiledProcedure<TInput = unknown, TOutput = unknown, TContext
383
416
  * @internal
384
417
  */
385
418
  readonly _handlerMap?: Readonly<Record<string, ProcedureHandler<TInput, TOutput, TContext>>>;
419
+ /**
420
+ * Error classes that this procedure declares it may throw
421
+ *
422
+ * Populated by `.throws()` on the procedure builder. Used for OpenAPI
423
+ * error response generation and client-side error narrowing.
424
+ *
425
+ * @internal
426
+ */
427
+ readonly errorClasses?: ReadonlyArray<new (data: Record<string, unknown>) => unknown>;
428
+ /**
429
+ * Whether the handler should be wrapped in a database transaction
430
+ *
431
+ * Set by `.transactional()` on the procedure builder. When true,
432
+ * `executeProcedure` wraps the handler in `ctx.db.$transaction()`.
433
+ */
434
+ readonly transactional?: boolean;
435
+ /**
436
+ * Options for the database transaction (isolation level, timeout)
437
+ *
438
+ * Forwarded to `ctx.db.$transaction()` as the second argument.
439
+ */
440
+ readonly transactionalOptions?: TransactionalOptions;
441
+ /**
442
+ * Domain events to emit after successful handler execution
443
+ *
444
+ * Populated by `.emits()` on the procedure builder. Each entry holds
445
+ * the event class constructor and an optional mapper that transforms
446
+ * the handler result into the event's data payload.
447
+ *
448
+ * Events fire AFTER the handler returns (post-commit when transactional).
449
+ * Emission errors are caught and logged — they never fail the request.
450
+ */
451
+ readonly emittedEvents?: ReadonlyArray<{
452
+ eventClass: {
453
+ new (data: Record<string, unknown>, options?: {
454
+ correlationId?: string;
455
+ }): unknown;
456
+ readonly name: string;
457
+ };
458
+ mapper?: (result: unknown) => Record<string, unknown>;
459
+ }>;
460
+ /**
461
+ * Pipeline steps declared via .through()
462
+ *
463
+ * When present, the pipeline executor runs these steps in order
464
+ * BEFORE the handler. Each step's output becomes the next step's
465
+ * input, and the final step's output is passed to the handler.
466
+ *
467
+ * If a step fails, revert actions for completed steps run in
468
+ * reverse order (compensation pattern).
469
+ */
470
+ readonly pipelineSteps?: ReadonlyArray<PipelineStep>;
471
+ /**
472
+ * Policy action reference for declarative authorization
473
+ *
474
+ * When set via `.policy()`, the procedure executor checks the policy
475
+ * action against the current user and (optionally) a resource from
476
+ * the context. The resource is looked up by lowercase resource name
477
+ * (e.g., `PostPolicy` → `ctx.post`).
478
+ *
479
+ * If the check fails, a ForbiddenError is thrown.
480
+ *
481
+ * @example
482
+ * ```typescript
483
+ * procedure()
484
+ * .guard(authenticated)
485
+ * .policy(PostPolicy.update)
486
+ * .mutation(handler)
487
+ * ```
488
+ */
489
+ readonly policyAction?: PolicyActionLike;
490
+ /**
491
+ * Post-handler hooks registered via `.useAfter()`
492
+ *
493
+ * When present, these hooks run after the handler succeeds (and after
494
+ * event emission). Errors in hooks are caught and logged — they never
495
+ * fail the request. Hooks cannot modify the result.
496
+ */
497
+ readonly afterHandlers?: ReadonlyArray<AfterHandler>;
498
+ /**
499
+ * Phantom type holder for error types — not used at runtime
500
+ *
501
+ * Preserves the TErrors union through the type system so that
502
+ * `InferProcedureErrors<T>` can extract it. Never set at runtime.
503
+ *
504
+ * @internal
505
+ */
506
+ readonly _errors?: TErrors;
386
507
  }
508
+ /**
509
+ * Post-handler hook function signature
510
+ *
511
+ * Runs after the handler returns successfully. Receives the validated
512
+ * input, the handler result, and the request context. Return value
513
+ * is ignored — hooks cannot modify the result.
514
+ *
515
+ * Useful for side effects like audit logging, cache invalidation, and metrics.
516
+ *
517
+ * @template TInput - The validated input type
518
+ * @template TOutput - The handler result type
519
+ * @template TContext - The context type
520
+ */
521
+ export type AfterHandler<TInput = unknown, TOutput = unknown, TContext = unknown> = (params: {
522
+ input: TInput;
523
+ result: TOutput;
524
+ ctx: TContext;
525
+ }) => void | Promise<void>;
387
526
  /**
388
527
  * Record of named procedures
389
528
  *
390
529
  * NOTE: Uses `any` for variance compatibility - see ProcedureDefinitions for explanation.
391
530
  */
392
- export type ProcedureRecord = Record<string, CompiledProcedure<any, any, any, any>>;
531
+ export type ProcedureRecord = Record<string, CompiledProcedure<any, any, any, any, any>>;
393
532
  /**
394
533
  * Procedure collection with namespace
395
534
  *
@@ -420,6 +559,13 @@ export type InferProcedureContext<T> = T extends CompiledProcedure<unknown, unkn
420
559
  * Extracts the type (query/mutation) from a compiled procedure
421
560
  */
422
561
  export type InferProcedureType<T> = T extends CompiledProcedure<unknown, unknown, BaseContext, infer TType> ? TType : never;
562
+ /**
563
+ * Extracts the error types from a compiled procedure
564
+ *
565
+ * Returns the union of domain error types declared via `.throws()`.
566
+ * Returns `never` if no errors are declared.
567
+ */
568
+ export type InferProcedureErrors<T> = T extends CompiledProcedure<unknown, unknown, BaseContext, ProcedureType, infer E> ? E : never;
423
569
  /**
424
570
  * Extracts procedure types from a collection
425
571
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veloxts/router",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Procedure definitions with tRPC and REST routing for VeloxTS framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -37,17 +37,17 @@
37
37
  }
38
38
  },
39
39
  "dependencies": {
40
- "@trpc/server": "11.10.0",
41
- "fastify": "5.7.4",
42
- "@veloxts/validation": "0.8.0",
43
- "@veloxts/core": "0.8.0"
40
+ "@trpc/server": "11.12.0",
41
+ "fastify": "5.8.2",
42
+ "@veloxts/core": "0.8.2",
43
+ "@veloxts/validation": "0.8.2"
44
44
  },
45
45
  "devDependencies": {
46
- "@vitest/coverage-v8": "4.0.18",
47
- "esbuild": "0.27.3",
46
+ "@vitest/coverage-v8": "4.1.0",
47
+ "esbuild": "0.27.4",
48
48
  "typescript": "5.9.3",
49
49
  "vite": "7.3.1",
50
- "vitest": "4.0.18",
50
+ "vitest": "4.1.0",
51
51
  "zod": "4.3.6"
52
52
  },
53
53
  "peerDependencies": {