@expressots/core 4.0.0-preview.1 → 4.0.0-preview.3

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.
Files changed (134) hide show
  1. package/LICENSE.md +21 -21
  2. package/README.md +66 -66
  3. package/lib/CHANGELOG.md +774 -774
  4. package/lib/README.md +66 -66
  5. package/lib/cjs/application/application-factory.js +6 -0
  6. package/lib/cjs/application/bootstrap.js +117 -213
  7. package/lib/cjs/config/define-config.js +1 -1
  8. package/lib/cjs/config/env-field-builders.js +47 -0
  9. package/lib/cjs/config/index.js +7 -1
  10. package/lib/cjs/framework-version.js +10 -0
  11. package/lib/cjs/lazy-loading/index.js +5 -1
  12. package/lib/cjs/lazy-loading/lazy-module-helpers.js +49 -0
  13. package/lib/cjs/middleware/index.js +8 -9
  14. package/lib/cjs/middleware/middleware-service.js +68 -12
  15. package/lib/cjs/middleware/presets-standalone.js +93 -0
  16. package/lib/cjs/provider/db-in-memory/adapter/in-memory.adapter.js +23 -0
  17. package/lib/cjs/provider/db-in-memory/index.js +11 -1
  18. package/lib/cjs/provider/db-in-memory/query/query-engine.js +28 -0
  19. package/lib/cjs/provider/db-in-memory/schema/decorators.js +18 -0
  20. package/lib/cjs/provider/db-in-memory/storage/index.js +3 -1
  21. package/lib/cjs/provider/db-in-memory/storage/memory-store.js +72 -1
  22. package/lib/cjs/provider/logger/logger.banner.js +40 -31
  23. package/lib/cjs/provider/logger/logger.config.js +11 -1
  24. package/lib/cjs/provider/logger/logger.formatter.js +22 -1
  25. package/lib/cjs/provider/logger/logger.provider.js +59 -9
  26. package/lib/cjs/provider/logger/transports/console.transport.js +69 -6
  27. package/lib/cjs/provider/logger/transports/file.transport.js +27 -18
  28. package/lib/cjs/provider/logger/utils/log-levels.js +6 -5
  29. package/lib/cjs/provider/validation/adapters/index.js +12 -5
  30. package/lib/cjs/provider/validation/adapters/yup.adapter.js +118 -0
  31. package/lib/cjs/provider/validation/adapters/zod.adapter.js +137 -0
  32. package/lib/cjs/provider/validation/index.js +5 -1
  33. package/lib/cjs/render/adapters/react-adapter.js +14 -14
  34. package/lib/cjs/render/features/type-generator.js +30 -30
  35. package/lib/cjs/render/features/view-debugger.js +75 -55
  36. package/lib/cjs/testing/fluent-request.js +7 -0
  37. package/lib/cjs/testing/snapshot-request.js +2 -0
  38. package/lib/cjs/types/application/application-factory.d.ts +6 -0
  39. package/lib/cjs/types/application/bootstrap.d.ts +196 -24
  40. package/lib/cjs/types/config/config.interfaces.d.ts +7 -1
  41. package/lib/cjs/types/config/env-field-builders.d.ts +39 -0
  42. package/lib/cjs/types/config/index.d.ts +1 -1
  43. package/lib/cjs/types/framework-version.d.ts +7 -0
  44. package/lib/cjs/types/lazy-loading/index.d.ts +1 -0
  45. package/lib/cjs/types/lazy-loading/lazy-module-helpers.d.ts +42 -0
  46. package/lib/cjs/types/middleware/index.d.ts +1 -1
  47. package/lib/cjs/types/middleware/middleware-service.d.ts +21 -0
  48. package/lib/cjs/types/middleware/presets-standalone.d.ts +75 -0
  49. package/lib/cjs/types/provider/db-in-memory/adapter/in-memory.adapter.d.ts +2 -0
  50. package/lib/cjs/types/provider/db-in-memory/index.d.ts +9 -1
  51. package/lib/cjs/types/provider/db-in-memory/query/query-engine.d.ts +14 -1
  52. package/lib/cjs/types/provider/db-in-memory/schema/decorators.d.ts +14 -0
  53. package/lib/cjs/types/provider/db-in-memory/storage/index.d.ts +1 -1
  54. package/lib/cjs/types/provider/db-in-memory/storage/memory-store.d.ts +34 -0
  55. package/lib/cjs/types/provider/logger/logger.banner.d.ts +1 -1
  56. package/lib/cjs/types/provider/logger/logger.config.d.ts +7 -0
  57. package/lib/cjs/types/provider/logger/logger.formatter.d.ts +10 -0
  58. package/lib/cjs/types/provider/logger/logger.provider.d.ts +32 -1
  59. package/lib/cjs/types/provider/logger/transports/console.transport.d.ts +7 -0
  60. package/lib/cjs/types/provider/logger/utils/log-levels.d.ts +3 -3
  61. package/lib/cjs/types/provider/validation/adapters/index.d.ts +7 -4
  62. package/lib/cjs/types/provider/validation/adapters/yup.adapter.d.ts +65 -0
  63. package/lib/cjs/types/provider/validation/adapters/zod.adapter.d.ts +84 -0
  64. package/lib/cjs/types/provider/validation/index.d.ts +1 -1
  65. package/lib/cjs/types/render/features/view-debugger.d.ts +10 -0
  66. package/lib/cjs/types/testing/testing.interfaces.d.ts +31 -6
  67. package/lib/esm/application/application-factory.js +6 -0
  68. package/lib/esm/application/bootstrap.js +117 -213
  69. package/lib/esm/config/define-config.js +1 -1
  70. package/lib/esm/config/env-field-builders.js +48 -0
  71. package/lib/esm/config/index.js +6 -1
  72. package/lib/esm/framework-version.js +7 -0
  73. package/lib/esm/lazy-loading/index.js +2 -0
  74. package/lib/esm/lazy-loading/lazy-module-helpers.js +45 -0
  75. package/lib/esm/middleware/index.js +3 -2
  76. package/lib/esm/middleware/middleware-service.js +68 -12
  77. package/lib/esm/middleware/presets-standalone.js +87 -0
  78. package/lib/esm/provider/db-in-memory/adapter/in-memory.adapter.js +23 -0
  79. package/lib/esm/provider/db-in-memory/index.js +9 -1
  80. package/lib/esm/provider/db-in-memory/query/query-engine.js +28 -0
  81. package/lib/esm/provider/db-in-memory/schema/decorators.js +18 -0
  82. package/lib/esm/provider/db-in-memory/storage/index.js +1 -1
  83. package/lib/esm/provider/db-in-memory/storage/memory-store.js +75 -0
  84. package/lib/esm/provider/logger/logger.banner.js +40 -31
  85. package/lib/esm/provider/logger/logger.config.js +12 -2
  86. package/lib/esm/provider/logger/logger.formatter.js +22 -1
  87. package/lib/esm/provider/logger/logger.provider.js +61 -10
  88. package/lib/esm/provider/logger/transports/console.transport.js +69 -6
  89. package/lib/esm/provider/logger/transports/file.transport.js +27 -18
  90. package/lib/esm/provider/logger/utils/log-levels.js +6 -5
  91. package/lib/esm/provider/validation/adapters/index.js +7 -4
  92. package/lib/esm/provider/validation/adapters/yup.adapter.js +111 -0
  93. package/lib/esm/provider/validation/adapters/zod.adapter.js +130 -0
  94. package/lib/esm/provider/validation/index.js +1 -1
  95. package/lib/esm/render/adapters/react-adapter.js +14 -14
  96. package/lib/esm/render/features/type-generator.js +30 -30
  97. package/lib/esm/render/features/view-debugger.js +75 -55
  98. package/lib/esm/testing/fluent-request.js +7 -0
  99. package/lib/esm/testing/snapshot-request.js +2 -0
  100. package/lib/esm/types/application/application-factory.d.ts +6 -0
  101. package/lib/esm/types/application/bootstrap.d.ts +196 -24
  102. package/lib/esm/types/config/config.interfaces.d.ts +7 -1
  103. package/lib/esm/types/config/env-field-builders.d.ts +39 -0
  104. package/lib/esm/types/config/index.d.ts +1 -1
  105. package/lib/esm/types/framework-version.d.ts +7 -0
  106. package/lib/esm/types/lazy-loading/index.d.ts +1 -0
  107. package/lib/esm/types/lazy-loading/lazy-module-helpers.d.ts +42 -0
  108. package/lib/esm/types/middleware/index.d.ts +1 -1
  109. package/lib/esm/types/middleware/middleware-service.d.ts +21 -0
  110. package/lib/esm/types/middleware/presets-standalone.d.ts +75 -0
  111. package/lib/esm/types/provider/db-in-memory/adapter/in-memory.adapter.d.ts +2 -0
  112. package/lib/esm/types/provider/db-in-memory/index.d.ts +9 -1
  113. package/lib/esm/types/provider/db-in-memory/query/query-engine.d.ts +14 -1
  114. package/lib/esm/types/provider/db-in-memory/schema/decorators.d.ts +14 -0
  115. package/lib/esm/types/provider/db-in-memory/storage/index.d.ts +1 -1
  116. package/lib/esm/types/provider/db-in-memory/storage/memory-store.d.ts +34 -0
  117. package/lib/esm/types/provider/logger/logger.banner.d.ts +1 -1
  118. package/lib/esm/types/provider/logger/logger.config.d.ts +7 -0
  119. package/lib/esm/types/provider/logger/logger.formatter.d.ts +10 -0
  120. package/lib/esm/types/provider/logger/logger.provider.d.ts +32 -1
  121. package/lib/esm/types/provider/logger/transports/console.transport.d.ts +7 -0
  122. package/lib/esm/types/provider/logger/utils/log-levels.d.ts +3 -3
  123. package/lib/esm/types/provider/validation/adapters/index.d.ts +7 -4
  124. package/lib/esm/types/provider/validation/adapters/yup.adapter.d.ts +65 -0
  125. package/lib/esm/types/provider/validation/adapters/zod.adapter.d.ts +84 -0
  126. package/lib/esm/types/provider/validation/index.d.ts +1 -1
  127. package/lib/esm/types/render/features/view-debugger.d.ts +10 -0
  128. package/lib/esm/types/testing/testing.interfaces.d.ts +31 -6
  129. package/lib/package.json +23 -8
  130. package/package.json +23 -8
  131. package/lib/cjs/middleware/middleware-presets.js +0 -294
  132. package/lib/cjs/types/middleware/middleware-presets.d.ts +0 -90
  133. package/lib/esm/middleware/middleware-presets.js +0 -286
  134. package/lib/esm/types/middleware/middleware-presets.d.ts +0 -90
@@ -102,6 +102,24 @@ export declare class EntityNotFoundError extends Error {
102
102
  id: string;
103
103
  constructor(entityName: string, id: string);
104
104
  }
105
+ /**
106
+ * Error thrown when a table reaches its configured record limit.
107
+ * @public API
108
+ */
109
+ export declare class MaxRecordsExceededError extends Error {
110
+ tableName: string;
111
+ limit: number;
112
+ constructor(tableName: string, limit: number);
113
+ }
114
+ /**
115
+ * Error thrown when entity validation fails (when `@Entity({ validate: true })`).
116
+ * @public API
117
+ */
118
+ export declare class EntityValidationError extends Error {
119
+ tableName: string;
120
+ field: string;
121
+ constructor(tableName: string, field: string, message?: string);
122
+ }
105
123
  /**
106
124
  * Error thrown when an entity already exists.
107
125
  * @public API
@@ -143,6 +161,8 @@ export interface MemoryStoreOptions {
143
161
  timestamps?: boolean;
144
162
  /** Enable soft deletes */
145
163
  softDelete?: boolean;
164
+ /** Maximum number of records allowed in the table (0 = unlimited) */
165
+ maxRecordsPerTable?: number;
146
166
  }
147
167
  /**
148
168
  * High-performance in-memory storage for a single table/collection.
@@ -175,12 +195,26 @@ export declare class MemoryStore<T extends IEntity> {
175
195
  private autoGenerateFields;
176
196
  /** Default values */
177
197
  private defaultValues;
198
+ /** Maximum number of records allowed (0 = unlimited) */
199
+ private maxRecords;
200
+ /** Enable runtime validation (from @Entity({ validate: true })) */
201
+ private validate;
202
+ /** Fields that must be present and non-null when validation is enabled */
203
+ private requiredFields;
178
204
  constructor(tableName: string, options?: MemoryStoreOptions);
179
205
  /**
180
206
  * Load schema metadata from decorators.
181
207
  * @private
182
208
  */
183
209
  private loadSchemaMetadata;
210
+ /**
211
+ * Validate an entity against the schema (only when `validate` is enabled).
212
+ * Ensures required fields (primary key + unique, excluding @Nullable) are
213
+ * present and non-null.
214
+ * @private
215
+ * @throws ValidationError when a required field is missing or null
216
+ */
217
+ private validateEntity;
184
218
  /**
185
219
  * Apply auto-generation and defaults to entity.
186
220
  * @private
@@ -72,7 +72,7 @@ export declare class BannerGenerator {
72
72
  */
73
73
  private displayFullBanner;
74
74
  /**
75
- * Display compact banner.
75
+ * Display compact banner using structured log format (cloud-friendly).
76
76
  */
77
77
  private displayCompactBanner;
78
78
  /**
@@ -50,6 +50,13 @@ export interface LoggerConfig {
50
50
  }
51
51
  /**
52
52
  * Default logger configuration.
53
+ *
54
+ * Honours `process.env.LOG_LEVEL` when set so that any logs emitted
55
+ * BEFORE the application's `globalConfiguration()` runs (e.g. interceptor
56
+ * registration during container construction) are gated by the user's
57
+ * desired log level instead of the development default of `DEBUG`.
58
+ * Falls back to `DEBUG` in development and `INFO` in production.
59
+ *
53
60
  * @public API
54
61
  */
55
62
  export declare function getDefaultLoggerConfig(): LoggerConfig;
@@ -9,6 +9,16 @@ export interface FormatOptions {
9
9
  redact?: boolean;
10
10
  /** Custom redactor instance (uses global if not provided) */
11
11
  redactor?: Redactor;
12
+ /**
13
+ * Emit ANSI color escape codes. When false, the formatted output is
14
+ * post-processed to strip every ANSI escape. Defaults to true (colored).
15
+ *
16
+ * Disable this for non-TTY consumers like cloud log viewers (Azure
17
+ * App Service, AWS CloudWatch, Heroku, Kubernetes, etc.) and Studio's
18
+ * Live Logs panel, all of which display the raw text without
19
+ * interpreting terminal escape sequences.
20
+ */
21
+ colors?: boolean;
12
22
  }
13
23
  /**
14
24
  * Format log entry for development (human-readable, colored).
@@ -12,7 +12,7 @@ import { LogQueryOptions, LogQuery, QueryStats } from "./logger.query.js";
12
12
  * - Automatic context detection (class/method names)
13
13
  * - Request-scoped context via AsyncLocalStorage
14
14
  * - Child logger creation with inherited context
15
- * - Multiple log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
15
+ * - Multiple log levels (ALL, DEBUG, INFO, WARN, ERROR, FATAL, SILENT)
16
16
  * - Pluggable transports (console, file, HTTP)
17
17
  * @public API
18
18
  */
@@ -26,11 +26,42 @@ declare class Logger implements IProvider {
26
26
  private groupingManager;
27
27
  private healthMonitor;
28
28
  private queryManager;
29
+ /**
30
+ * Module-level overrides applied by `Logger.configure(...)` on top of the
31
+ * built-in defaults. Used by the constructor of every future `Logger`
32
+ * instance so application-wide config (e.g. log level, transports) can be
33
+ * set once before bootstrap, before any DI container exists.
34
+ */
35
+ private static defaultOverrides;
29
36
  name: string;
30
37
  version: string;
31
38
  author: string;
32
39
  repo: string;
33
40
  constructor();
41
+ /**
42
+ * Configure the default LoggerConfig used by every future `Logger`
43
+ * instance constructed in this process.
44
+ *
45
+ * Use this from application config files **before** bootstrap so the DI
46
+ * container's Logger picks up the correct level / transports / grouping /
47
+ * health / redaction settings without needing to inject and reconfigure it.
48
+ * Calls are merged: later calls override earlier ones, but unspecified
49
+ * keys keep their previously-set values.
50
+ *
51
+ * Already-constructed Logger instances are NOT mutated by this call —
52
+ * use the instance method `logger.configure(...)` to update a live one.
53
+ *
54
+ * @param config - Partial configuration to merge with the defaults.
55
+ * @public API
56
+ */
57
+ static configure(config: Partial<LoggerConfig>): void;
58
+ /**
59
+ * Reset the module-level overrides set by `Logger.configure`. Useful in
60
+ * tests to undo cross-test pollution.
61
+ *
62
+ * @public API
63
+ */
64
+ static resetConfigure(): void;
34
65
  /**
35
66
  * Configure the logger.
36
67
  * @param config - Partial configuration to merge with defaults
@@ -32,6 +32,13 @@ export declare class ConsoleTransport implements ILogTransport {
32
32
  });
33
33
  /**
34
34
  * Create a console transport optimized for development.
35
+ *
36
+ * Colors are auto-detected: they're emitted when stdout is a TTY
37
+ * (your terminal) and disabled when stdout is piped or captured by
38
+ * a cloud log collector (Azure App Service, AWS CloudWatch, Heroku,
39
+ * Docker, Kubernetes, etc.). Respects the standard `NO_COLOR` and
40
+ * `FORCE_COLOR` environment variables.
41
+ *
35
42
  * @param redact - Enable redaction (default: false for development)
36
43
  * @returns ConsoleTransport configured for development
37
44
  * @public API
@@ -4,8 +4,8 @@
4
4
  * @public API
5
5
  */
6
6
  export declare enum LogLevel {
7
- /** Ultra-detailed diagnostic information (function entry/exit) */
8
- TRACE = 0,
7
+ /** Show all logs (ultra-detailed diagnostic information, function entry/exit) */
8
+ ALL = 0,
9
9
  /** Detailed diagnostic information for debugging */
10
10
  DEBUG = 1,
11
11
  /** General informational messages */
@@ -23,7 +23,7 @@ export declare enum LogLevel {
23
23
  * String representation of log levels for backward compatibility.
24
24
  * @public API
25
25
  */
26
- export type LogLevelString = "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL" | "SILENT" | "NONE";
26
+ export type LogLevelString = "ALL" | "TRACE" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL" | "SILENT" | "NONE";
27
27
  /**
28
28
  * Legacy log level for backward compatibility.
29
29
  * Maps to INFO level.
@@ -2,9 +2,12 @@
2
2
  * Validation Adapters
3
3
  * @module @expressots/core/validation/adapters
4
4
  *
5
- * Built-in adapters for validation libraries.
6
- * Additional adapters (Zod, Yup, Joi) available as separate packages:
7
- * - @expressots/validator-zod
8
- * - @expressots/validator-yup
5
+ * Built-in adapters for validation libraries. The validation libraries
6
+ * themselves (`class-validator`, `zod`, `yup`) are *optional peer
7
+ * dependencies* — install only the one(s) you actually use.
8
+ *
9
+ * Additional Joi adapter is on the roadmap.
9
10
  */
10
11
  export { ClassValidatorAdapter } from "./class-validator.adapter.js";
12
+ export { ZodValidatorAdapter, createZodValidator } from "./zod.adapter.js";
13
+ export { YupValidatorAdapter, createYupValidator } from "./yup.adapter.js";
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Yup Validation Adapter
3
+ * @module @expressots/core/validation
4
+ *
5
+ * Built-in adapter for the [yup](https://github.com/jquense/yup) validation
6
+ * library. `yup` is declared as an *optional* peer dependency: install it
7
+ * explicitly (`npm i yup`) to enable this adapter.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import * as yup from "yup";
12
+ * import { validationRegistry, createYupValidator } from "@expressots/core";
13
+ *
14
+ * validationRegistry.register(createYupValidator());
15
+ *
16
+ * const CreateUserSchema = yup.object({
17
+ * email: yup.string().email().required(),
18
+ * age: yup.number().integer().min(18).required(),
19
+ * });
20
+ *
21
+ * @controller("/users")
22
+ * class UsersController {
23
+ * @Post("/")
24
+ * create(@body(CreateUserSchema) input: yup.InferType<typeof CreateUserSchema>) {
25
+ * // input is fully typed and validated
26
+ * }
27
+ * }
28
+ * ```
29
+ */
30
+ import { IValidationAdapter, ValidationOptions, ValidationResult } from "../validation.interface.js";
31
+ /** Subset of yup's surface we depend on, structurally typed. */
32
+ interface YupLikeSchema {
33
+ readonly __isYupSchema__?: boolean;
34
+ validate?(data: unknown, options?: YupOptions): Promise<unknown>;
35
+ validateSync?(data: unknown, options?: YupOptions): unknown;
36
+ cast?(data: unknown, options?: YupOptions): unknown;
37
+ }
38
+ interface YupOptions {
39
+ abortEarly?: boolean;
40
+ stripUnknown?: boolean;
41
+ context?: unknown;
42
+ }
43
+ /**
44
+ * Adapter for [yup](https://github.com/jquense/yup). Detects yup schemas at
45
+ * runtime by checking for the `__isYupSchema__` brand or the presence of a
46
+ * `validate` + `cast` method pair.
47
+ *
48
+ * @public API
49
+ */
50
+ export declare class YupValidatorAdapter implements IValidationAdapter<YupLikeSchema> {
51
+ readonly name = "yup";
52
+ readonly priority = 80;
53
+ canHandle(schema: unknown): boolean;
54
+ validate(data: unknown, schema: YupLikeSchema, options?: ValidationOptions): Promise<ValidationResult>;
55
+ transform(data: unknown, schema: YupLikeSchema): Promise<unknown>;
56
+ private mapIssues;
57
+ }
58
+ /**
59
+ * Convenience factory matching the `createXxxValidator` naming used by the
60
+ * other adapters. Equivalent to `new YupValidatorAdapter()`.
61
+ *
62
+ * @public API
63
+ */
64
+ export declare function createYupValidator(): YupValidatorAdapter;
65
+ export {};
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Zod Validation Adapter
3
+ * @module @expressots/core/validation
4
+ *
5
+ * Built-in adapter for the [zod](https://zod.dev) validation library.
6
+ * `zod` is declared as an *optional* peer dependency: install it explicitly
7
+ * (`npm i zod`) to enable this adapter; otherwise validation falls back to
8
+ * the next registered adapter.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { z } from "zod";
13
+ * import { validationRegistry, ZodValidatorAdapter, createZodValidator } from "@expressots/core";
14
+ *
15
+ * validationRegistry.register(createZodValidator());
16
+ *
17
+ * const CreateUserSchema = z.object({
18
+ * email: z.string().email(),
19
+ * age: z.number().int().min(18),
20
+ * });
21
+ *
22
+ * @controller("/users")
23
+ * class UsersController {
24
+ * @Post("/")
25
+ * create(@body(CreateUserSchema) input: z.infer<typeof CreateUserSchema>) {
26
+ * // input is fully typed and validated
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ import { IValidationAdapter, ValidationOptions, ValidationResult } from "../validation.interface.js";
32
+ /**
33
+ * Minimal structural typing for the subset of zod we actually call. We cannot
34
+ * import zod directly from core (it is an optional peer), but we type the
35
+ * schema we receive as `unknown` and refine via the runtime `canHandle` check.
36
+ */
37
+ interface ZodLikeSchema {
38
+ readonly _def?: unknown;
39
+ parse?(data: unknown): unknown;
40
+ parseAsync?(data: unknown): Promise<unknown>;
41
+ safeParseAsync?(data: unknown): Promise<{
42
+ success: boolean;
43
+ data?: unknown;
44
+ error?: {
45
+ issues: Array<ZodIssue>;
46
+ };
47
+ }>;
48
+ safeParse?(data: unknown): {
49
+ success: boolean;
50
+ data?: unknown;
51
+ error?: {
52
+ issues: Array<ZodIssue>;
53
+ };
54
+ };
55
+ }
56
+ interface ZodIssue {
57
+ path: Array<string | number>;
58
+ message: string;
59
+ code?: string;
60
+ received?: unknown;
61
+ }
62
+ /**
63
+ * Adapter for [zod](https://zod.dev). Picks up any zod schema (`z.object`,
64
+ * `z.string`, ...) at runtime by structural detection — no compile-time
65
+ * dependency on `zod` is required.
66
+ *
67
+ * @public API
68
+ */
69
+ export declare class ZodValidatorAdapter implements IValidationAdapter<ZodLikeSchema> {
70
+ readonly name = "zod";
71
+ readonly priority = 90;
72
+ canHandle(schema: unknown): boolean;
73
+ validate(data: unknown, schema: ZodLikeSchema, _options?: ValidationOptions): Promise<ValidationResult>;
74
+ transform(data: unknown, schema: ZodLikeSchema): Promise<unknown>;
75
+ private mapIssues;
76
+ }
77
+ /**
78
+ * Convenience factory matching the `createXxxValidator` naming used by the
79
+ * other adapters. Equivalent to `new ZodValidatorAdapter()`.
80
+ *
81
+ * @public API
82
+ */
83
+ export declare function createZodValidator(): ZodValidatorAdapter;
84
+ export {};
@@ -16,4 +16,4 @@ export { ValidationRegistry } from "./validation-registry.js";
16
16
  export { SmartFieldDetector } from "./smart-field-detector.js";
17
17
  export { HelpfulErrorFormatter, type ErrorFormat, type FormattedErrorResponse, } from "./helpful-error-formatter.js";
18
18
  export { getParameterType, getAllParameterTypes, getClassProperties, hasClassValidatorDecorators, isZodSchema, isClassConstructor, detectSchemaType, type InferredTypeInfo, type InferredPropertyInfo, } from "./type-inference.js";
19
- export { ClassValidatorAdapter } from "./adapters/index.js";
19
+ export { ClassValidatorAdapter, ZodValidatorAdapter, createZodValidator, YupValidatorAdapter, createYupValidator, } from "./adapters/index.js";
@@ -27,6 +27,16 @@ export declare class ViewDebugger {
27
27
  * Handle the view preview endpoint.
28
28
  */
29
29
  private handlePreviewEndpoint;
30
+ /**
31
+ * Normalise the `view` route param across Express 4 and 5.
32
+ *
33
+ * Express 4 / path-to-regexp v6 captured `/__views/preview/:view(*)`
34
+ * as a single string. Express 5 / path-to-regexp v8 changed the
35
+ * named-splat capture to `string[]` (one entry per slash-separated
36
+ * segment). The view engine needs the slash-joined form, so we always
37
+ * collapse the array shape back to that.
38
+ */
39
+ private resolveViewParam;
30
40
  /**
31
41
  * Handle the view info endpoint.
32
42
  */
@@ -345,13 +345,15 @@ export interface FluentRequest {
345
345
  */
346
346
  expect<T>(assertion: (response: FluentResponse<T>) => void): FluentRequest;
347
347
  /**
348
- * Execute the request and return the response.
348
+ * Execute the request and return the response. Body type defaults to
349
+ * `any` for ergonomic test code — see {@link FluentResponse} for the
350
+ * rationale and how to opt into strict typing via `<T>`.
349
351
  */
350
- execute<T = unknown>(): Promise<FluentResponse<T>>;
352
+ execute<T = any>(): Promise<FluentResponse<T>>;
351
353
  /**
352
354
  * Alias for execute().
353
355
  */
354
- end<T = unknown>(): Promise<FluentResponse<T>>;
356
+ end<T = any>(): Promise<FluentResponse<T>>;
355
357
  }
356
358
  /**
357
359
  * Time assertion options for performance testing.
@@ -372,8 +374,30 @@ export interface TimeAssertion {
372
374
  }
373
375
  /**
374
376
  * Fluent response object.
377
+ *
378
+ * The body type defaults to `any` rather than `unknown` — this is a
379
+ * deliberate ergonomics call for a *test-time* HTTP client API.
380
+ *
381
+ * Tests written against ExpressoTS controllers usually look like:
382
+ *
383
+ * const r = await testApp.request.get("/users/1").execute();
384
+ * expect(r.body.id).toBe(1);
385
+ *
386
+ * With `body: unknown` (the type-safe default), every property access
387
+ * trips TS18046 and forces every test to either pass an inline generic
388
+ * (`.execute<{ id: number }>()`) or cast (`(r.body as { id: number })`).
389
+ * That's the right default for *production* code where you don't
390
+ * actually know the response shape — but in a test, the fixture _is_
391
+ * the type contract: the test file already encodes the expected shape
392
+ * in its assertions, so the type check is redundant noise.
393
+ *
394
+ * Users who want strict typing can still parameterise: the generic
395
+ * is preserved on `request.execute<T>()` and on `FluentResponse<T>`
396
+ * itself, so opting into a typed body remains a single keystroke
397
+ * (`.execute<UserDto>()`). This mirrors how `supertest` and `axios`
398
+ * default — both publish `body: any` for the same reason.
375
399
  */
376
- export interface FluentResponse<T = unknown> {
400
+ export interface FluentResponse<T = any> {
377
401
  /**
378
402
  * Response status code.
379
403
  */
@@ -387,7 +411,8 @@ export interface FluentResponse<T = unknown> {
387
411
  */
388
412
  headers: Record<string, string>;
389
413
  /**
390
- * Parsed response body.
414
+ * Parsed response body. Defaults to `any` — see the interface
415
+ * docstring for the rationale and how to opt into strict typing.
391
416
  */
392
417
  body: T;
393
418
  /**
@@ -487,7 +512,7 @@ export interface SnapshotRequest {
487
512
  expectContentType(type: string | RegExp): SnapshotRequest;
488
513
  expectBodyPath(path: string, expected: unknown): SnapshotRequest;
489
514
  expect<T>(assertion: (response: FluentResponse<T>) => void): SnapshotRequest;
490
- execute<T = unknown>(): Promise<FluentResponse<T>>;
515
+ execute<T = any>(): Promise<FluentResponse<T>>;
491
516
  /**
492
517
  * Assert response matches snapshot.
493
518
  */
@@ -119,6 +119,12 @@ export class AppFactory {
119
119
  *
120
120
  * @throws {Error} If webServerType is not a valid constructor
121
121
  *
122
+ * @deprecated Use `bootstrap()` from `@expressots/core` instead. `bootstrap()`
123
+ * additionally handles environment file loading, port configuration,
124
+ * graceful shutdown, the startup banner, and configuration validation.
125
+ * `AppFactory.create()` will keep working for advanced use cases but is
126
+ * scheduled for removal in a future major release.
127
+ *
122
128
  * @public API
123
129
  */
124
130
  static async create(webServerType) {