@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.
- package/LICENSE.md +21 -21
- package/README.md +66 -66
- package/lib/CHANGELOG.md +774 -774
- package/lib/README.md +66 -66
- package/lib/cjs/application/application-factory.js +6 -0
- package/lib/cjs/application/bootstrap.js +117 -213
- package/lib/cjs/config/define-config.js +1 -1
- package/lib/cjs/config/env-field-builders.js +47 -0
- package/lib/cjs/config/index.js +7 -1
- package/lib/cjs/framework-version.js +10 -0
- package/lib/cjs/lazy-loading/index.js +5 -1
- package/lib/cjs/lazy-loading/lazy-module-helpers.js +49 -0
- package/lib/cjs/middleware/index.js +8 -9
- package/lib/cjs/middleware/middleware-service.js +68 -12
- package/lib/cjs/middleware/presets-standalone.js +93 -0
- package/lib/cjs/provider/db-in-memory/adapter/in-memory.adapter.js +23 -0
- package/lib/cjs/provider/db-in-memory/index.js +11 -1
- package/lib/cjs/provider/db-in-memory/query/query-engine.js +28 -0
- package/lib/cjs/provider/db-in-memory/schema/decorators.js +18 -0
- package/lib/cjs/provider/db-in-memory/storage/index.js +3 -1
- package/lib/cjs/provider/db-in-memory/storage/memory-store.js +72 -1
- package/lib/cjs/provider/logger/logger.banner.js +40 -31
- package/lib/cjs/provider/logger/logger.config.js +11 -1
- package/lib/cjs/provider/logger/logger.formatter.js +22 -1
- package/lib/cjs/provider/logger/logger.provider.js +59 -9
- package/lib/cjs/provider/logger/transports/console.transport.js +69 -6
- package/lib/cjs/provider/logger/transports/file.transport.js +27 -18
- package/lib/cjs/provider/logger/utils/log-levels.js +6 -5
- package/lib/cjs/provider/validation/adapters/index.js +12 -5
- package/lib/cjs/provider/validation/adapters/yup.adapter.js +118 -0
- package/lib/cjs/provider/validation/adapters/zod.adapter.js +137 -0
- package/lib/cjs/provider/validation/index.js +5 -1
- package/lib/cjs/render/adapters/react-adapter.js +14 -14
- package/lib/cjs/render/features/type-generator.js +30 -30
- package/lib/cjs/render/features/view-debugger.js +75 -55
- package/lib/cjs/testing/fluent-request.js +7 -0
- package/lib/cjs/testing/snapshot-request.js +2 -0
- package/lib/cjs/types/application/application-factory.d.ts +6 -0
- package/lib/cjs/types/application/bootstrap.d.ts +196 -24
- package/lib/cjs/types/config/config.interfaces.d.ts +7 -1
- package/lib/cjs/types/config/env-field-builders.d.ts +39 -0
- package/lib/cjs/types/config/index.d.ts +1 -1
- package/lib/cjs/types/framework-version.d.ts +7 -0
- package/lib/cjs/types/lazy-loading/index.d.ts +1 -0
- package/lib/cjs/types/lazy-loading/lazy-module-helpers.d.ts +42 -0
- package/lib/cjs/types/middleware/index.d.ts +1 -1
- package/lib/cjs/types/middleware/middleware-service.d.ts +21 -0
- package/lib/cjs/types/middleware/presets-standalone.d.ts +75 -0
- package/lib/cjs/types/provider/db-in-memory/adapter/in-memory.adapter.d.ts +2 -0
- package/lib/cjs/types/provider/db-in-memory/index.d.ts +9 -1
- package/lib/cjs/types/provider/db-in-memory/query/query-engine.d.ts +14 -1
- package/lib/cjs/types/provider/db-in-memory/schema/decorators.d.ts +14 -0
- package/lib/cjs/types/provider/db-in-memory/storage/index.d.ts +1 -1
- package/lib/cjs/types/provider/db-in-memory/storage/memory-store.d.ts +34 -0
- package/lib/cjs/types/provider/logger/logger.banner.d.ts +1 -1
- package/lib/cjs/types/provider/logger/logger.config.d.ts +7 -0
- package/lib/cjs/types/provider/logger/logger.formatter.d.ts +10 -0
- package/lib/cjs/types/provider/logger/logger.provider.d.ts +32 -1
- package/lib/cjs/types/provider/logger/transports/console.transport.d.ts +7 -0
- package/lib/cjs/types/provider/logger/utils/log-levels.d.ts +3 -3
- package/lib/cjs/types/provider/validation/adapters/index.d.ts +7 -4
- package/lib/cjs/types/provider/validation/adapters/yup.adapter.d.ts +65 -0
- package/lib/cjs/types/provider/validation/adapters/zod.adapter.d.ts +84 -0
- package/lib/cjs/types/provider/validation/index.d.ts +1 -1
- package/lib/cjs/types/render/features/view-debugger.d.ts +10 -0
- package/lib/cjs/types/testing/testing.interfaces.d.ts +31 -6
- package/lib/esm/application/application-factory.js +6 -0
- package/lib/esm/application/bootstrap.js +117 -213
- package/lib/esm/config/define-config.js +1 -1
- package/lib/esm/config/env-field-builders.js +48 -0
- package/lib/esm/config/index.js +6 -1
- package/lib/esm/framework-version.js +7 -0
- package/lib/esm/lazy-loading/index.js +2 -0
- package/lib/esm/lazy-loading/lazy-module-helpers.js +45 -0
- package/lib/esm/middleware/index.js +3 -2
- package/lib/esm/middleware/middleware-service.js +68 -12
- package/lib/esm/middleware/presets-standalone.js +87 -0
- package/lib/esm/provider/db-in-memory/adapter/in-memory.adapter.js +23 -0
- package/lib/esm/provider/db-in-memory/index.js +9 -1
- package/lib/esm/provider/db-in-memory/query/query-engine.js +28 -0
- package/lib/esm/provider/db-in-memory/schema/decorators.js +18 -0
- package/lib/esm/provider/db-in-memory/storage/index.js +1 -1
- package/lib/esm/provider/db-in-memory/storage/memory-store.js +75 -0
- package/lib/esm/provider/logger/logger.banner.js +40 -31
- package/lib/esm/provider/logger/logger.config.js +12 -2
- package/lib/esm/provider/logger/logger.formatter.js +22 -1
- package/lib/esm/provider/logger/logger.provider.js +61 -10
- package/lib/esm/provider/logger/transports/console.transport.js +69 -6
- package/lib/esm/provider/logger/transports/file.transport.js +27 -18
- package/lib/esm/provider/logger/utils/log-levels.js +6 -5
- package/lib/esm/provider/validation/adapters/index.js +7 -4
- package/lib/esm/provider/validation/adapters/yup.adapter.js +111 -0
- package/lib/esm/provider/validation/adapters/zod.adapter.js +130 -0
- package/lib/esm/provider/validation/index.js +1 -1
- package/lib/esm/render/adapters/react-adapter.js +14 -14
- package/lib/esm/render/features/type-generator.js +30 -30
- package/lib/esm/render/features/view-debugger.js +75 -55
- package/lib/esm/testing/fluent-request.js +7 -0
- package/lib/esm/testing/snapshot-request.js +2 -0
- package/lib/esm/types/application/application-factory.d.ts +6 -0
- package/lib/esm/types/application/bootstrap.d.ts +196 -24
- package/lib/esm/types/config/config.interfaces.d.ts +7 -1
- package/lib/esm/types/config/env-field-builders.d.ts +39 -0
- package/lib/esm/types/config/index.d.ts +1 -1
- package/lib/esm/types/framework-version.d.ts +7 -0
- package/lib/esm/types/lazy-loading/index.d.ts +1 -0
- package/lib/esm/types/lazy-loading/lazy-module-helpers.d.ts +42 -0
- package/lib/esm/types/middleware/index.d.ts +1 -1
- package/lib/esm/types/middleware/middleware-service.d.ts +21 -0
- package/lib/esm/types/middleware/presets-standalone.d.ts +75 -0
- package/lib/esm/types/provider/db-in-memory/adapter/in-memory.adapter.d.ts +2 -0
- package/lib/esm/types/provider/db-in-memory/index.d.ts +9 -1
- package/lib/esm/types/provider/db-in-memory/query/query-engine.d.ts +14 -1
- package/lib/esm/types/provider/db-in-memory/schema/decorators.d.ts +14 -0
- package/lib/esm/types/provider/db-in-memory/storage/index.d.ts +1 -1
- package/lib/esm/types/provider/db-in-memory/storage/memory-store.d.ts +34 -0
- package/lib/esm/types/provider/logger/logger.banner.d.ts +1 -1
- package/lib/esm/types/provider/logger/logger.config.d.ts +7 -0
- package/lib/esm/types/provider/logger/logger.formatter.d.ts +10 -0
- package/lib/esm/types/provider/logger/logger.provider.d.ts +32 -1
- package/lib/esm/types/provider/logger/transports/console.transport.d.ts +7 -0
- package/lib/esm/types/provider/logger/utils/log-levels.d.ts +3 -3
- package/lib/esm/types/provider/validation/adapters/index.d.ts +7 -4
- package/lib/esm/types/provider/validation/adapters/yup.adapter.d.ts +65 -0
- package/lib/esm/types/provider/validation/adapters/zod.adapter.d.ts +84 -0
- package/lib/esm/types/provider/validation/index.d.ts +1 -1
- package/lib/esm/types/render/features/view-debugger.d.ts +10 -0
- package/lib/esm/types/testing/testing.interfaces.d.ts +31 -6
- package/lib/package.json +23 -8
- package/package.json +23 -8
- package/lib/cjs/middleware/middleware-presets.js +0 -294
- package/lib/cjs/types/middleware/middleware-presets.d.ts +0 -90
- package/lib/esm/middleware/middleware-presets.js +0 -286
- 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
|
|
@@ -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 (
|
|
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
|
-
/**
|
|
8
|
-
|
|
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
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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 =
|
|
352
|
+
execute<T = any>(): Promise<FluentResponse<T>>;
|
|
351
353
|
/**
|
|
352
354
|
* Alias for execute().
|
|
353
355
|
*/
|
|
354
|
-
end<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 =
|
|
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 =
|
|
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) {
|