@stone-js/validation 0.8.9 → 0.8.11
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/adapters/standardSchema.d.ts +3 -3
- package/dist/adapters/zod.d.ts +3 -3
- package/dist/declarations.d.ts +3 -3
- package/dist/decorators/Validation.d.ts +1 -1
- package/dist/decorators/ValidationSchema.d.ts +22 -12
- package/dist/index.d.ts +4 -4
- package/dist/index.js +59 -39
- package/dist/schema.d.ts +5 -5
- package/package.json +4 -4
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NativeSchema, StandardSchemaV1 } from '../declarations.js';
|
|
2
2
|
/**
|
|
3
3
|
* Adapts a [Standard Schema](https://standardschema.dev) (Zod 3.24+, Valibot, ArkType, …) to the
|
|
4
|
-
* Stone.js {@link
|
|
4
|
+
* Stone.js {@link NativeSchema} contract. Only the synchronous path is supported here; an
|
|
5
5
|
* async schema throws a clear {@link ValidationError} so the misuse is obvious.
|
|
6
6
|
*
|
|
7
7
|
* @param schema - The Standard Schema.
|
|
8
8
|
* @returns A Stone.js validation schema.
|
|
9
9
|
*/
|
|
10
|
-
export declare function fromStandard<T>(schema: StandardSchemaV1<T>):
|
|
10
|
+
export declare function fromStandard<T>(schema: StandardSchemaV1<T>): NativeSchema<T>;
|
|
11
11
|
/**
|
|
12
12
|
* Whether a value implements the Standard Schema v1 contract.
|
|
13
13
|
*
|
package/dist/adapters/zod.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NativeSchema, ZodLikeSchema } from '../declarations.js';
|
|
2
2
|
/**
|
|
3
3
|
* Adapts a Zod-style schema (anything exposing a synchronous `safeParse`) to the Stone.js
|
|
4
|
-
* {@link
|
|
4
|
+
* {@link NativeSchema} contract. Structural — never imports Zod, so it works with any
|
|
5
5
|
* compatible engine and keeps the module dependency-free.
|
|
6
6
|
*
|
|
7
7
|
* @param schema - The Zod-like schema.
|
|
8
8
|
* @returns A Stone.js validation schema.
|
|
9
9
|
*/
|
|
10
|
-
export declare function fromZod<T>(schema: ZodLikeSchema<T>):
|
|
10
|
+
export declare function fromZod<T>(schema: ZodLikeSchema<T>): NativeSchema<T>;
|
|
11
11
|
/**
|
|
12
12
|
* Whether a value looks like a Zod-style schema.
|
|
13
13
|
*
|
package/dist/declarations.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type ValidationResult<T> = {
|
|
|
29
29
|
* implement the Standard Schema spec, or expose `safeParse`), so you write the schema once and
|
|
30
30
|
* use it identically on the backend and the frontend.
|
|
31
31
|
*/
|
|
32
|
-
export interface
|
|
32
|
+
export interface NativeSchema<T = unknown> {
|
|
33
33
|
/** Validate a value, returning a normalised result. */
|
|
34
34
|
validate: (data: unknown) => ValidationResult<T>;
|
|
35
35
|
}
|
|
@@ -76,10 +76,10 @@ export type ZodSafeParseResult<T> = {
|
|
|
76
76
|
};
|
|
77
77
|
};
|
|
78
78
|
/**
|
|
79
|
-
* Anything that can be resolved into a {@link
|
|
79
|
+
* Anything that can be resolved into a {@link NativeSchema}: a native Stone.js schema, a
|
|
80
80
|
* Standard Schema, or a Zod-like schema.
|
|
81
81
|
*/
|
|
82
|
-
export type SchemaInput<T = unknown> =
|
|
82
|
+
export type SchemaInput<T = unknown> = NativeSchema<T> | StandardSchemaV1<T> | ZodLikeSchema<T>;
|
|
83
83
|
/**
|
|
84
84
|
* The telemetry-free validation service contract.
|
|
85
85
|
*/
|
|
@@ -21,7 +21,7 @@ export interface ValidationDecoratorOptions extends ValidationConfig {
|
|
|
21
21
|
* ```typescript
|
|
22
22
|
* import { Validation } from '@stone-js/validation'
|
|
23
23
|
*
|
|
24
|
-
* @Validation({
|
|
24
|
+
* @Validation({ schemas: { listQuery: ListQuerySchema } })
|
|
25
25
|
* @StoneApp({ name: 'my-app' })
|
|
26
26
|
* export class Application {}
|
|
27
27
|
* ```
|
|
@@ -1,18 +1,28 @@
|
|
|
1
|
+
import { ClassType } from '@stone-js/core';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Declare a class as a rule set.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
* @ValidationSchema('createUser')
|
|
6
|
-
* export class CreateUserSchema implements IValidationSchema { rules () { … } }
|
|
7
|
-
* ```
|
|
5
|
+
* Three statements in one, which is why nothing has to be wired by hand:
|
|
8
6
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* 1. **It is a service.** The container builds it, as a singleton, so its constructor is auto-wired
|
|
8
|
+
* like any other class: a repository, a client, a translator, whatever it destructures is resolved
|
|
9
|
+
* for it. That is what lets a rule set depend on the application instead of on constants.
|
|
10
|
+
* 2. **It is reachable by name.** The alias is bound as `schema:<name>`, prefixed on purpose: an
|
|
11
|
+
* application is free to bind its own service under a plain word, and a declaration named after a
|
|
12
|
+
* domain concept must not compete for that name.
|
|
13
|
+
* 3. **It activates the module.** The blueprint comes with the decorator, so declaring this is the
|
|
14
|
+
* whole setup, and a route naming it resolves to this class.
|
|
13
15
|
*
|
|
14
|
-
* @param alias - The name
|
|
15
|
-
* discovery middleware fills in, since it is the one holding the class.
|
|
16
|
+
* @param alias - The name a route refers to it by. Defaults to the class name.
|
|
16
17
|
* @returns A class decorator.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* @ValidationSchema('createUser')
|
|
22
|
+
* export class CreateUser {
|
|
23
|
+
* constructor (private readonly users: UserRepository) {}
|
|
24
|
+
* rules (): RouteValidationRules { return { body: { email: { rules: 'email' } } } }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
17
27
|
*/
|
|
18
|
-
export declare const ValidationSchema: (alias?: string) => ClassDecorator;
|
|
28
|
+
export declare const ValidationSchema: <T extends ClassType = ClassType>(alias?: string) => ClassDecorator;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
export * from './ValidationServiceProvider.js';
|
|
2
|
-
export * from './Validator.js';
|
|
3
1
|
export * from './adapters/standardSchema.js';
|
|
4
2
|
export * from './adapters/zod.js';
|
|
5
3
|
export * from './declarations.js';
|
|
4
|
+
export * from './decorators/constants.js';
|
|
6
5
|
export * from './decorators/Validate.js';
|
|
7
6
|
export * from './decorators/Validation.js';
|
|
8
7
|
export * from './decorators/ValidationSchema.js';
|
|
9
|
-
export * from './decorators/constants.js';
|
|
10
8
|
export * from './errors/ValidationError.js';
|
|
11
9
|
export * from './middleware/BlueprintMiddleware.js';
|
|
12
|
-
export * from './middleware/ValidateRouteMiddleware.js';
|
|
13
10
|
export * from './middleware/validate.js';
|
|
11
|
+
export * from './middleware/ValidateRouteMiddleware.js';
|
|
14
12
|
export * from './options/ValidationBlueprint.js';
|
|
15
13
|
export * from './schema.js';
|
|
16
14
|
export * from './schemaClass.js';
|
|
17
15
|
export * from './sources.js';
|
|
18
16
|
export * from './validateEvent.js';
|
|
17
|
+
export * from './ValidationServiceProvider.js';
|
|
18
|
+
export * from './Validator.js';
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { IntegrationError, hasMetadata, getMetadata, classDecoratorLegacyWrapper, addBlueprint,
|
|
1
|
+
import { IntegrationError, methodDecoratorLegacyWrapper, addMetadata, hasMetadata, getMetadata, classDecoratorLegacyWrapper, addBlueprint, setMetadata, SERVICE_KEY } from '@stone-js/core';
|
|
2
2
|
import { cloneValue } from '@stone-js/config';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Adapts a Zod-style schema (anything exposing a synchronous `safeParse`) to the Stone.js
|
|
6
|
-
* {@link
|
|
6
|
+
* {@link NativeSchema} contract. Structural — never imports Zod, so it works with any
|
|
7
7
|
* compatible engine and keeps the module dependency-free.
|
|
8
8
|
*
|
|
9
9
|
* @param schema - The Zod-like schema.
|
|
@@ -71,7 +71,7 @@ class ValidationError extends IntegrationError {
|
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
73
|
* Adapts a [Standard Schema](https://standardschema.dev) (Zod 3.24+, Valibot, ArkType, …) to the
|
|
74
|
-
* Stone.js {@link
|
|
74
|
+
* Stone.js {@link NativeSchema} contract. Only the synchronous path is supported here; an
|
|
75
75
|
* async schema throws a clear {@link ValidationError} so the misuse is obvious.
|
|
76
76
|
*
|
|
77
77
|
* @param schema - The Standard Schema.
|
|
@@ -110,7 +110,7 @@ function isStandardSchema(value) {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/**
|
|
113
|
-
* Normalises any supported schema input into a Stone.js {@link
|
|
113
|
+
* Normalises any supported schema input into a Stone.js {@link NativeSchema}.
|
|
114
114
|
*
|
|
115
115
|
* Resolution order: a Standard Schema (`~standard`) is preferred (canonical, covers Zod 3.24+,
|
|
116
116
|
* Valibot, ArkType), then a Zod-like `safeParse`, then a native Stone.js schema (`validate`).
|
|
@@ -132,7 +132,7 @@ function resolveSchema(input) {
|
|
|
132
132
|
throw new ValidationError('Unrecognised validation schema: expected a Standard Schema, a Zod-like schema, or a Stone.js schema.', { issues: [] });
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
|
-
* Whether a value is already a native Stone.js {@link
|
|
135
|
+
* Whether a value is already a native Stone.js {@link NativeSchema}.
|
|
136
136
|
*
|
|
137
137
|
* @param value - The value to test.
|
|
138
138
|
* @returns True when it exposes a `validate` function.
|
|
@@ -407,6 +407,30 @@ const VALIDATE_KEY = '@stone-js/validation/validate';
|
|
|
407
407
|
*/
|
|
408
408
|
const VALIDATION_SCHEMA_KEY = '@stone-js/validation/schema';
|
|
409
409
|
|
|
410
|
+
/**
|
|
411
|
+
* Method decorator: declare what a handler accepts.
|
|
412
|
+
*
|
|
413
|
+
* ```ts
|
|
414
|
+
* @Validate(CreateUserSchema) // the body
|
|
415
|
+
* @Validate({ body: CreateUserSchema, query: Page }) // several sources
|
|
416
|
+
* @Validate('createUser') // a registered schema class
|
|
417
|
+
* ```
|
|
418
|
+
*
|
|
419
|
+
* This knows nothing about the router, and that is the point: the declaration is recorded on the
|
|
420
|
+
* handler itself, under this module's own key, so validation runs the same in a routed application,
|
|
421
|
+
* a single-handler service, a CLI command or the browser. When a router *is* in play you may instead
|
|
422
|
+
* put it on the route (`@Post('/users', { validation: … })`), which keeps the method uncluttered and
|
|
423
|
+
* puts everything a route does in one place; both forms end up in the same middleware.
|
|
424
|
+
*
|
|
425
|
+
* @param validation - What the handler accepts.
|
|
426
|
+
* @returns A method decorator.
|
|
427
|
+
*/
|
|
428
|
+
const Validate = (validation) => {
|
|
429
|
+
return methodDecoratorLegacyWrapper((_target, context) => {
|
|
430
|
+
addMetadata(context, VALIDATE_KEY, { action: context.name, validation });
|
|
431
|
+
});
|
|
432
|
+
};
|
|
433
|
+
|
|
410
434
|
/**
|
|
411
435
|
* Route middleware: validates what a route declared, before its handler runs.
|
|
412
436
|
*
|
|
@@ -652,7 +676,7 @@ const validationBlueprint = {
|
|
|
652
676
|
* ```typescript
|
|
653
677
|
* import { Validation } from '@stone-js/validation'
|
|
654
678
|
*
|
|
655
|
-
* @Validation({
|
|
679
|
+
* @Validation({ schemas: { listQuery: ListQuerySchema } })
|
|
656
680
|
* @StoneApp({ name: 'my-app' })
|
|
657
681
|
* export class Application {}
|
|
658
682
|
* ```
|
|
@@ -669,48 +693,44 @@ const Validation = (options = {}) => {
|
|
|
669
693
|
};
|
|
670
694
|
|
|
671
695
|
/**
|
|
672
|
-
*
|
|
696
|
+
* Declare a class as a rule set.
|
|
673
697
|
*
|
|
674
|
-
*
|
|
675
|
-
* @Validate(CreateUserSchema) // the body
|
|
676
|
-
* @Validate({ body: CreateUserSchema, query: Page }) // several sources
|
|
677
|
-
* @Validate('createUser') // a registered schema class
|
|
678
|
-
* ```
|
|
698
|
+
* Three statements in one, which is why nothing has to be wired by hand:
|
|
679
699
|
*
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
*
|
|
684
|
-
*
|
|
700
|
+
* 1. **It is a service.** The container builds it, as a singleton, so its constructor is auto-wired
|
|
701
|
+
* like any other class: a repository, a client, a translator, whatever it destructures is resolved
|
|
702
|
+
* for it. That is what lets a rule set depend on the application instead of on constants.
|
|
703
|
+
* 2. **It is reachable by name.** The alias is bound as `schema:<name>`, prefixed on purpose: an
|
|
704
|
+
* application is free to bind its own service under a plain word, and a declaration named after a
|
|
705
|
+
* domain concept must not compete for that name.
|
|
706
|
+
* 3. **It activates the module.** The blueprint comes with the decorator, so declaring this is the
|
|
707
|
+
* whole setup, and a route naming it resolves to this class.
|
|
685
708
|
*
|
|
686
|
-
* @param
|
|
687
|
-
* @returns A
|
|
688
|
-
*/
|
|
689
|
-
const Validate = (validation) => {
|
|
690
|
-
return methodDecoratorLegacyWrapper((_target, context) => {
|
|
691
|
-
addMetadata(context, VALIDATE_KEY, { action: context.name, validation });
|
|
692
|
-
});
|
|
693
|
-
};
|
|
694
|
-
|
|
695
|
-
/**
|
|
696
|
-
* Class decorator: register a schema class under a name.
|
|
709
|
+
* @param alias - The name a route refers to it by. Defaults to the class name.
|
|
710
|
+
* @returns A class decorator.
|
|
697
711
|
*
|
|
712
|
+
* @example
|
|
698
713
|
* ```ts
|
|
699
714
|
* @ValidationSchema('createUser')
|
|
700
|
-
* export class
|
|
715
|
+
* export class CreateUser {
|
|
716
|
+
* constructor (private readonly users: UserRepository) {}
|
|
717
|
+
* rules (): RouteValidationRules { return { body: { email: { rules: 'email' } } } }
|
|
718
|
+
* }
|
|
701
719
|
* ```
|
|
702
|
-
*
|
|
703
|
-
* Routes and handlers then refer to it by name (`@Validate('createUser')`), so schemas live in their
|
|
704
|
-
* own files, organised however the application likes, and nothing has to be imported at the route.
|
|
705
|
-
* The class is resolved by the container, so its constructor receives services and `rules()` can use
|
|
706
|
-
* them.
|
|
707
|
-
*
|
|
708
|
-
* @param alias - The name the schema is registered under. Defaults to the class name, which the
|
|
709
|
-
* discovery middleware fills in, since it is the one holding the class.
|
|
710
|
-
* @returns A class decorator.
|
|
711
720
|
*/
|
|
712
721
|
const ValidationSchema = (alias) => {
|
|
713
|
-
return
|
|
722
|
+
return classDecoratorLegacyWrapper((target, context) => {
|
|
723
|
+
const name = alias ?? target.name;
|
|
724
|
+
setMetadata(context, VALIDATION_SCHEMA_KEY, { alias: name });
|
|
725
|
+
setMetadata(context, SERVICE_KEY, { singleton: true, isClass: true, alias: `schema:${name}` });
|
|
726
|
+
addBlueprint(target, context, validationBlueprint, {
|
|
727
|
+
stone: {
|
|
728
|
+
validation: {
|
|
729
|
+
schemas: { [name]: target }
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
});
|
|
714
734
|
};
|
|
715
735
|
|
|
716
736
|
/**
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NativeSchema, SchemaInput } from './declarations.js';
|
|
2
2
|
/**
|
|
3
|
-
* Normalises any supported schema input into a Stone.js {@link
|
|
3
|
+
* Normalises any supported schema input into a Stone.js {@link NativeSchema}.
|
|
4
4
|
*
|
|
5
5
|
* Resolution order: a Standard Schema (`~standard`) is preferred (canonical, covers Zod 3.24+,
|
|
6
6
|
* Valibot, ArkType), then a Zod-like `safeParse`, then a native Stone.js schema (`validate`).
|
|
@@ -9,11 +9,11 @@ import { SchemaInput, ValidationSchema } from './declarations.js';
|
|
|
9
9
|
* @returns A Stone.js validation schema.
|
|
10
10
|
* @throws {ValidationError} When the input is not a recognisable schema.
|
|
11
11
|
*/
|
|
12
|
-
export declare function resolveSchema<T>(input: SchemaInput<T>):
|
|
12
|
+
export declare function resolveSchema<T>(input: SchemaInput<T>): NativeSchema<T>;
|
|
13
13
|
/**
|
|
14
|
-
* Whether a value is already a native Stone.js {@link
|
|
14
|
+
* Whether a value is already a native Stone.js {@link NativeSchema}.
|
|
15
15
|
*
|
|
16
16
|
* @param value - The value to test.
|
|
17
17
|
* @returns True when it exposes a `validate` function.
|
|
18
18
|
*/
|
|
19
|
-
export declare function isNativeSchema<T>(value: unknown): value is
|
|
19
|
+
export declare function isNativeSchema<T>(value: unknown): value is NativeSchema<T>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stone-js/validation",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.11",
|
|
4
4
|
"description": "Framework-agnostic input validation for Stone.js. Define a schema once (Zod, Valibot, ArkType — anything Standard Schema) and validate it identically on the backend and the frontend.",
|
|
5
5
|
"author": "Mr. Stone <evensstone@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"node": ">=18.17.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@stone-js/core": "0.8.
|
|
43
|
+
"@stone-js/core": "0.8.11"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@commitlint/cli": "^19.8.1",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"typescript": "^5.6.3",
|
|
63
63
|
"vitest": "^3.2.4",
|
|
64
64
|
"zod": "^3.24.1",
|
|
65
|
-
"@stone-js/core": "0.8.
|
|
65
|
+
"@stone-js/core": "0.8.11"
|
|
66
66
|
},
|
|
67
67
|
"ts-standard": {
|
|
68
68
|
"globals": [
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@stone-js/config": "0.8.
|
|
78
|
+
"@stone-js/config": "0.8.11"
|
|
79
79
|
},
|
|
80
80
|
"scripts": {
|
|
81
81
|
"lint": "ts-standard src",
|