schema-dsl 1.2.4 → 2.0.0
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/CHANGELOG.md +87 -210
- package/README.md +391 -2249
- package/dist/DslBuilder-DQDN0ZxZ.d.cts +341 -0
- package/dist/DslBuilder-DkLaOo9Q.d.ts +341 -0
- package/dist/Validator-C7GsVQOH.d.cts +192 -0
- package/dist/Validator-hFWKGxir.d.ts +192 -0
- package/dist/index.cjs +6594 -0
- package/dist/index.d.cts +1145 -0
- package/dist/index.d.ts +1145 -0
- package/dist/index.js +6528 -0
- package/dist/plugin-CIKtTMtS.d.cts +246 -0
- package/dist/plugin-CIKtTMtS.d.ts +246 -0
- package/dist/plugins/custom-format.cjs +3802 -0
- package/dist/plugins/custom-format.d.cts +12 -0
- package/dist/plugins/custom-format.d.ts +12 -0
- package/dist/plugins/custom-format.js +3772 -0
- package/dist/plugins/custom-type-example.cjs +3795 -0
- package/dist/plugins/custom-type-example.d.cts +8 -0
- package/dist/plugins/custom-type-example.d.ts +8 -0
- package/dist/plugins/custom-type-example.js +3765 -0
- package/dist/plugins/custom-validator.cjs +146 -0
- package/dist/plugins/custom-validator.d.cts +10 -0
- package/dist/plugins/custom-validator.d.ts +10 -0
- package/dist/plugins/custom-validator.js +121 -0
- package/docs/FEATURE-INDEX.md +102 -68
- package/docs/add-custom-locale.md +48 -35
- package/docs/add-keyword.md +24 -0
- package/docs/api-reference.md +396 -154
- package/docs/api.md +13 -0
- package/docs/best-practices-project-structure.md +19 -10
- package/docs/best-practices.md +93 -53
- package/docs/cache-manager.md +23 -15
- package/docs/compile.md +45 -0
- package/docs/conditional-api.md +40 -11
- package/docs/custom-extensions-guide.md +80 -152
- package/docs/design-philosophy.md +76 -71
- package/docs/doc-index.md +324 -0
- package/docs/dsl-syntax.md +69 -19
- package/docs/dynamic-locale.md +24 -14
- package/docs/enum.md +12 -5
- package/docs/error-handling.md +53 -44
- package/docs/export-guide.md +47 -8
- package/docs/export-limitations.md +27 -11
- package/docs/faq.md +86 -67
- package/docs/frontend-i18n-guide.md +26 -12
- package/docs/i18n-user-guide.md +60 -47
- package/docs/i18n.md +51 -32
- package/docs/index.md +48 -0
- package/docs/json-schema-basics.md +40 -0
- package/docs/label-vs-description.md +12 -3
- package/docs/markdown-exporter.md +15 -6
- package/docs/mongodb-exporter.md +11 -4
- package/docs/multi-language.md +26 -0
- package/docs/multi-type-support.md +26 -33
- package/docs/mysql-exporter.md +9 -2
- package/docs/number-operators.md +12 -5
- package/docs/optional-marker-guide.md +28 -23
- package/docs/performance-guide.md +49 -0
- package/docs/plugin-system.md +205 -366
- package/docs/plugin-type-registration.md +34 -0
- package/docs/postgresql-exporter.md +9 -2
- package/docs/public/favicon.svg +5 -0
- package/docs/quick-start.md +37 -363
- package/docs/runtime-locale-support.md +20 -9
- package/docs/schema-helper.md +10 -5
- package/docs/schema-utils-advanced-issues.md +23 -0
- package/docs/schema-utils-best-practices.md +20 -0
- package/docs/schema-utils-chaining.md +7 -0
- package/docs/schema-utils.md +76 -42
- package/docs/security-checklist.md +20 -0
- package/docs/string-extensions.md +17 -9
- package/docs/troubleshooting.md +36 -21
- package/docs/type-converter.md +41 -50
- package/docs/type-reference.md +38 -15
- package/docs/typescript-guide.md +53 -42
- package/docs/union-type-guide.md +11 -1
- package/docs/union-types.md +10 -3
- package/docs/validate-async.md +36 -25
- package/docs/validate-batch.md +49 -0
- package/docs/validate-dsl-object-support.md +33 -28
- package/docs/validate.md +36 -16
- package/docs/validation-guide.md +25 -7
- package/docs/validator.md +39 -0
- package/package.json +85 -27
- package/plugins/custom-format.cjs +8 -0
- package/plugins/custom-type-example.cjs +8 -0
- package/plugins/custom-validator.cjs +8 -0
- package/src/adapters/DslAdapter.ts +111 -0
- package/src/adapters/index.ts +1 -0
- package/src/config/constants.ts +83 -0
- package/src/config/index.ts +2 -0
- package/src/config/patterns.ts +77 -0
- package/src/core/CacheManager.ts +159 -0
- package/src/core/ConditionalBuilder.ts +382 -0
- package/src/core/ConditionalRuntime.ts +28 -0
- package/src/core/ConditionalValidator.ts +255 -0
- package/src/core/DslBuilder.ts +677 -0
- package/src/core/ErrorCodes.ts +38 -0
- package/src/core/ErrorFormatter.ts +271 -0
- package/src/core/JSONSchemaCore.ts +65 -0
- package/src/core/Locale.ts +187 -0
- package/src/core/MessageTemplate.ts +42 -0
- package/src/core/ObjectDslBuilder.ts +64 -0
- package/src/core/PluginManager.ts +326 -0
- package/src/core/StringExtensions.ts +140 -0
- package/src/core/TemplateEngine.ts +44 -0
- package/src/core/Validator.ts +448 -0
- package/src/errors/I18nError.ts +159 -0
- package/src/errors/ValidationError.ts +105 -0
- package/src/exporters/BaseExporter.ts +60 -0
- package/src/exporters/MarkdownExporter.ts +305 -0
- package/src/exporters/MongoDBExporter.ts +126 -0
- package/src/exporters/MySQLExporter.ts +155 -0
- package/src/exporters/PostgreSQLExporter.ts +222 -0
- package/src/exporters/index.ts +18 -0
- package/src/index.ts +633 -0
- package/{lib/locales/en-US.js → src/locales/en-US.ts} +21 -37
- package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +63 -16
- package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +74 -27
- package/src/locales/index.ts +103 -0
- package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +59 -17
- package/src/locales/types.ts +156 -0
- package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +21 -38
- package/src/parser/ConstraintParser.ts +101 -0
- package/src/parser/DslParser.ts +470 -0
- package/src/parser/SchemaCompiler.ts +66 -0
- package/src/parser/TypeRegistry.ts +250 -0
- package/src/parser/index.ts +6 -0
- package/src/plugins/custom-format.ts +126 -0
- package/src/plugins/custom-type-example.ts +108 -0
- package/src/plugins/custom-validator.ts +140 -0
- package/src/types/conditional.ts +28 -0
- package/src/types/config.ts +59 -0
- package/src/types/dsl.ts +131 -0
- package/src/types/error.ts +60 -0
- package/src/types/index.ts +17 -0
- package/src/types/infer.ts +128 -0
- package/src/types/plugin.ts +58 -0
- package/src/types/safe-regex.d.ts +9 -0
- package/src/types/schema.ts +66 -0
- package/src/types/validate.ts +71 -0
- package/src/utils/SchemaHelper.ts +196 -0
- package/src/utils/SchemaUtils.ts +346 -0
- package/src/utils/TypeConverter.ts +215 -0
- package/src/utils/index.ts +10 -0
- package/src/validators/CustomKeywords.ts +477 -0
- package/.eslintignore +0 -11
- package/.eslintrc.json +0 -27
- package/CONTRIBUTING.md +0 -368
- package/STATUS.md +0 -491
- package/changelogs/v1.0.0.md +0 -328
- package/changelogs/v1.0.9.md +0 -367
- package/changelogs/v1.1.0.md +0 -389
- package/changelogs/v1.1.1.md +0 -308
- package/changelogs/v1.1.2.md +0 -183
- package/changelogs/v1.1.3.md +0 -161
- package/changelogs/v1.1.4.md +0 -432
- package/changelogs/v1.1.5.md +0 -493
- package/changelogs/v1.1.6.md +0 -211
- package/changelogs/v1.1.8.md +0 -376
- package/changelogs/v1.2.3.md +0 -124
- package/docs/INDEX.md +0 -252
- package/docs/issues-resolved-summary.md +0 -196
- package/docs/performance-benchmark-report.md +0 -179
- package/docs/performance-quick-reference.md +0 -123
- package/docs/user-questions-answered.md +0 -353
- package/docs/validation-rules-v1.0.2.md +0 -1608
- package/examples/README.md +0 -81
- package/examples/array-dsl-example.js +0 -227
- package/examples/conditional-example.js +0 -288
- package/examples/conditional-non-object.js +0 -129
- package/examples/conditional-validate-example.js +0 -321
- package/examples/custom-extension.js +0 -85
- package/examples/dsl-match-example.js +0 -74
- package/examples/dsl-style.js +0 -118
- package/examples/dynamic-locale-configuration.js +0 -348
- package/examples/dynamic-locale-example.js +0 -287
- package/examples/enum.examples.js +0 -324
- package/examples/export-demo.js +0 -130
- package/examples/express-integration.js +0 -376
- package/examples/i18n-error-handling-complete.js +0 -381
- package/examples/i18n-error-handling-quickstart.md +0 -0
- package/examples/i18n-error.examples.js +0 -181
- package/examples/i18n-full-demo.js +0 -301
- package/examples/i18n-memory-safety.examples.js +0 -268
- package/examples/markdown-export.js +0 -71
- package/examples/middleware-usage.js +0 -93
- package/examples/new-features-comparison.js +0 -315
- package/examples/password-reset/README.md +0 -153
- package/examples/password-reset/schema.js +0 -26
- package/examples/password-reset/test.js +0 -101
- package/examples/plugin-system.examples.js +0 -205
- package/examples/schema-utils-chaining.examples.js +0 -250
- package/examples/simple-example.js +0 -122
- package/examples/slug.examples.js +0 -179
- package/examples/string-extensions.js +0 -297
- package/examples/union-type-example.js +0 -127
- package/examples/union-types-example.js +0 -77
- package/examples/user-registration/README.md +0 -156
- package/examples/user-registration/routes.js +0 -92
- package/examples/user-registration/schema.js +0 -150
- package/examples/user-registration/server.js +0 -74
- package/index.d.ts +0 -3540
- package/index.js +0 -457
- package/index.mjs +0 -60
- package/lib/adapters/DslAdapter.js +0 -871
- package/lib/adapters/index.js +0 -20
- package/lib/config/constants.js +0 -286
- package/lib/config/patterns/common.js +0 -47
- package/lib/config/patterns/creditCard.js +0 -9
- package/lib/config/patterns/idCard.js +0 -9
- package/lib/config/patterns/index.js +0 -9
- package/lib/config/patterns/licensePlate.js +0 -4
- package/lib/config/patterns/passport.js +0 -4
- package/lib/config/patterns/phone.js +0 -9
- package/lib/config/patterns/postalCode.js +0 -5
- package/lib/core/CacheManager.js +0 -376
- package/lib/core/ConditionalBuilder.js +0 -503
- package/lib/core/DslBuilder.js +0 -1400
- package/lib/core/ErrorCodes.js +0 -233
- package/lib/core/ErrorFormatter.js +0 -445
- package/lib/core/JSONSchemaCore.js +0 -347
- package/lib/core/Locale.js +0 -130
- package/lib/core/MessageTemplate.js +0 -98
- package/lib/core/PluginManager.js +0 -448
- package/lib/core/StringExtensions.js +0 -240
- package/lib/core/Validator.js +0 -654
- package/lib/errors/I18nError.js +0 -328
- package/lib/errors/ValidationError.js +0 -191
- package/lib/exporters/MarkdownExporter.js +0 -420
- package/lib/exporters/MongoDBExporter.js +0 -162
- package/lib/exporters/MySQLExporter.js +0 -212
- package/lib/exporters/PostgreSQLExporter.js +0 -289
- package/lib/exporters/index.js +0 -24
- package/lib/locales/index.js +0 -8
- package/lib/utils/LRUCache.js +0 -174
- package/lib/utils/SchemaHelper.js +0 -240
- package/lib/utils/SchemaUtils.js +0 -445
- package/lib/utils/TypeConverter.js +0 -245
- package/lib/utils/index.js +0 -13
- package/lib/validators/CustomKeywords.js +0 -616
- package/lib/validators/index.js +0 -11
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ErrorMessages } from './error.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cache configuration options.
|
|
5
|
+
* @alias CacheConfig — v1 BC alias exported from index
|
|
6
|
+
*/
|
|
7
|
+
export interface CacheOptions {
|
|
8
|
+
/** Maximum number of cache entries (default 5000). */
|
|
9
|
+
maxSize?: number
|
|
10
|
+
/** Cache TTL in milliseconds (0 = no expiry). */
|
|
11
|
+
ttl?: number
|
|
12
|
+
/** Whether caching is enabled. */
|
|
13
|
+
enabled?: boolean
|
|
14
|
+
/** Whether statistics are enabled (default true). */
|
|
15
|
+
statsEnabled?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* I18n configuration type.
|
|
20
|
+
*/
|
|
21
|
+
export type I18nConfig =
|
|
22
|
+
| string // Path to locale directory (Node >=18: .js/.cjs/.json/.jsonc/.json5)
|
|
23
|
+
| Record<string, ErrorMessages> // Inline locale bundle
|
|
24
|
+
| { localesPath: string } // Locale directory — object form (Node >=18: .js/.cjs/.json/.jsonc/.json5)
|
|
25
|
+
| { locales: Record<string, ErrorMessages> } // v1/doc-compatible wrapper
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* dsl.config() options.
|
|
29
|
+
*/
|
|
30
|
+
export interface DslConfigOptions {
|
|
31
|
+
/** Internationalisation config. */
|
|
32
|
+
i18n?: I18nConfig
|
|
33
|
+
/** Cache config. */
|
|
34
|
+
cache?: CacheOptions
|
|
35
|
+
/** Custom validation rule extensions. */
|
|
36
|
+
patterns?: {
|
|
37
|
+
phone?: Record<string, RegExp>
|
|
38
|
+
idCard?: Record<string, RegExp>
|
|
39
|
+
creditCard?: Record<string, RegExp>
|
|
40
|
+
[key: string]: Record<string, RegExp> | undefined
|
|
41
|
+
}
|
|
42
|
+
/** Default locale (default 'en-US'). */
|
|
43
|
+
defaultLocale?: string
|
|
44
|
+
/** Strict type resolution: throw on unknown types instead of warn + fallback to string. */
|
|
45
|
+
strict?: boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* ValidatorOptions (Validator class constructor parameters).
|
|
50
|
+
*/
|
|
51
|
+
export interface ValidatorOptions {
|
|
52
|
+
allErrors?: boolean
|
|
53
|
+
verbose?: boolean
|
|
54
|
+
strict?: boolean
|
|
55
|
+
coerceTypes?: boolean | 'array'
|
|
56
|
+
removeAdditional?: boolean | 'all' | 'failing'
|
|
57
|
+
useDefaults?: boolean
|
|
58
|
+
cache?: boolean | CacheOptions
|
|
59
|
+
}
|
package/src/types/dsl.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { JSONSchema } from './schema.js'
|
|
2
|
+
import type { DslConfigOptions } from './config.js'
|
|
3
|
+
import type { IConditionalBuilder } from './conditional.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DslBuilder interface definition (chainable API shape).
|
|
7
|
+
* Implementation class is in src/core/DslBuilder.ts (Phase 7).
|
|
8
|
+
*/
|
|
9
|
+
export interface IDslBuilder {
|
|
10
|
+
// ── Core constraint methods ──────────────────────────────────
|
|
11
|
+
min(n: number): this
|
|
12
|
+
max(n: number): this
|
|
13
|
+
label(text: string): this
|
|
14
|
+
description(text: string): this
|
|
15
|
+
pattern(regex: RegExp | string, message?: string): this
|
|
16
|
+
enum(...values: unknown[]): this
|
|
17
|
+
optional(): this
|
|
18
|
+
required(): this
|
|
19
|
+
default(value: unknown): this
|
|
20
|
+
error(messages: Record<string, string>): this
|
|
21
|
+
messages(msgs: Record<string, string>): this
|
|
22
|
+
format(fmt: string): this
|
|
23
|
+
custom(validatorFn: (value: unknown) => unknown): this
|
|
24
|
+
|
|
25
|
+
// ── String validators ────────────────────────────────────────
|
|
26
|
+
length(n: number): this
|
|
27
|
+
alphanum(): this
|
|
28
|
+
trim(): this
|
|
29
|
+
lowercase(): this
|
|
30
|
+
uppercase(): this
|
|
31
|
+
ip(): this
|
|
32
|
+
base64(): this
|
|
33
|
+
jwt(): this
|
|
34
|
+
json(): this
|
|
35
|
+
domain(): this
|
|
36
|
+
slug(): this
|
|
37
|
+
after(date: string): this
|
|
38
|
+
before(date: string): this
|
|
39
|
+
dateGreater(date: string): this
|
|
40
|
+
dateLess(date: string): this
|
|
41
|
+
dateFormat(fmt: string): this
|
|
42
|
+
username(preset?: string | { minLength?: number; maxLength?: number; allowUnderscore?: boolean; allowNumber?: boolean }): this
|
|
43
|
+
password(preset?: string): this
|
|
44
|
+
phone(country?: string): this
|
|
45
|
+
phoneNumber(country?: string): this
|
|
46
|
+
idCard(country?: string): this
|
|
47
|
+
creditCard(type?: string): this
|
|
48
|
+
licensePlate(country?: string): this
|
|
49
|
+
postalCode(country?: string): this
|
|
50
|
+
passport(country?: string): this
|
|
51
|
+
|
|
52
|
+
// ── Number validators ────────────────────────────────────────
|
|
53
|
+
precision(n: number): this
|
|
54
|
+
multiple(n: number): this
|
|
55
|
+
port(): this
|
|
56
|
+
|
|
57
|
+
// ── Object validators ────────────────────────────────────────
|
|
58
|
+
requireAll(): this
|
|
59
|
+
strict(): this
|
|
60
|
+
|
|
61
|
+
// ── Array validators ─────────────────────────────────────────
|
|
62
|
+
noSparse(): this
|
|
63
|
+
includesRequired(items: unknown[]): this
|
|
64
|
+
|
|
65
|
+
// ── Output ───────────────────────────────────────────────────
|
|
66
|
+
toJsonSchema(): JSONSchema
|
|
67
|
+
toSchema(): JSONSchema
|
|
68
|
+
toString(): string
|
|
69
|
+
|
|
70
|
+
// ── Internal marker ──────────────────────────────────────────
|
|
71
|
+
readonly _isDslBuilder: true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* DSL object definition (key → field mapping).
|
|
76
|
+
* ⚠️ Must be an interface rather than a type alias to support recursive DslField ↔ DslDefinition references.
|
|
77
|
+
*/
|
|
78
|
+
export interface DslDefinition {
|
|
79
|
+
[key: string]: DslField
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* v1 conditional field marker (created by dsl.if / dsl.match; compiled to allOf conditional schema during parseObject).
|
|
84
|
+
*/
|
|
85
|
+
export interface DslConditionMarker {
|
|
86
|
+
_isIf?: true
|
|
87
|
+
_isMatch?: true
|
|
88
|
+
condition?: string
|
|
89
|
+
field?: string
|
|
90
|
+
then?: unknown
|
|
91
|
+
else?: unknown
|
|
92
|
+
map?: Record<string, unknown>
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* DSL field type (recursive definition).
|
|
97
|
+
* String | DslBuilder instance | nested object.
|
|
98
|
+
*/
|
|
99
|
+
export type DslField = string | IDslBuilder | DslDefinition | DslConditionMarker
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* DslBuilder constructor input (string or nested definition).
|
|
103
|
+
*/
|
|
104
|
+
export type DslInput = string | DslDefinition
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* if/conditional function types.
|
|
108
|
+
*/
|
|
109
|
+
export type DslIfFn = (condition: (data: unknown) => boolean) => IConditionalBuilder
|
|
110
|
+
export type DslFieldIfFn = (condition: string, thenSchema: unknown, elseSchema?: unknown) => DslConditionMarker
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* dsl.error namespace.
|
|
114
|
+
*/
|
|
115
|
+
export interface DslErrorNamespace {
|
|
116
|
+
readonly [code: string]: string
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* DslFn interface (function overloads + namespace attachments).
|
|
121
|
+
* ⚠️ Uses function overloads rather than union return types to ensure TypeScript type narrowing works correctly.
|
|
122
|
+
*/
|
|
123
|
+
export interface DslFn {
|
|
124
|
+
(def: string): IDslBuilder
|
|
125
|
+
(def: DslDefinition): JSONSchema
|
|
126
|
+
config: (options?: Partial<DslConfigOptions>) => void
|
|
127
|
+
if: DslIfFn & DslFieldIfFn
|
|
128
|
+
_if: DslIfFn & DslFieldIfFn
|
|
129
|
+
match: (value: unknown, cases: Record<string, unknown>) => DslConditionMarker
|
|
130
|
+
error: DslErrorNamespace
|
|
131
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error message templates (custom validation error copy).
|
|
3
|
+
*/
|
|
4
|
+
export interface ErrorMessages {
|
|
5
|
+
// Length / range (v1.0.3+ recommends min/max over minLength/maximum etc.)
|
|
6
|
+
min?: string
|
|
7
|
+
max?: string
|
|
8
|
+
minLength?: string
|
|
9
|
+
maxLength?: string
|
|
10
|
+
minimum?: string
|
|
11
|
+
maximum?: string
|
|
12
|
+
minItems?: string
|
|
13
|
+
maxItems?: string
|
|
14
|
+
// Types
|
|
15
|
+
type?: string
|
|
16
|
+
string?: string
|
|
17
|
+
number?: string
|
|
18
|
+
integer?: string
|
|
19
|
+
boolean?: string
|
|
20
|
+
array?: string
|
|
21
|
+
object?: string
|
|
22
|
+
// Formats
|
|
23
|
+
email?: string
|
|
24
|
+
url?: string
|
|
25
|
+
date?: string
|
|
26
|
+
dateTime?: string
|
|
27
|
+
uuid?: string
|
|
28
|
+
ipv4?: string
|
|
29
|
+
ipv6?: string
|
|
30
|
+
// Other
|
|
31
|
+
pattern?: string
|
|
32
|
+
format?: string
|
|
33
|
+
required?: string
|
|
34
|
+
enum?: string
|
|
35
|
+
uniqueItems?: string
|
|
36
|
+
// Custom keywords
|
|
37
|
+
exactLength?: string
|
|
38
|
+
phone?: string
|
|
39
|
+
idCard?: string
|
|
40
|
+
creditCard?: string
|
|
41
|
+
// Extensible
|
|
42
|
+
[key: string]: string | undefined
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Error code constant type (shape of the ErrorCodes object).
|
|
47
|
+
*/
|
|
48
|
+
export interface ErrorCodeMap {
|
|
49
|
+
// Validation errors
|
|
50
|
+
VALIDATION_ERROR: 'VALIDATION_ERROR'
|
|
51
|
+
INVALID_SCHEMA: 'INVALID_SCHEMA'
|
|
52
|
+
// Config errors
|
|
53
|
+
INVALID_CONFIG: 'INVALID_CONFIG'
|
|
54
|
+
INVALID_LOCALE: 'INVALID_LOCALE'
|
|
55
|
+
// Plugin errors
|
|
56
|
+
PLUGIN_INSTALL_ERROR: 'PLUGIN_INSTALL_ERROR'
|
|
57
|
+
PLUGIN_NOT_FOUND: 'PLUGIN_NOT_FOUND'
|
|
58
|
+
// Extensible
|
|
59
|
+
[key: string]: string
|
|
60
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// --- Core types ---
|
|
2
|
+
export type { JSONSchema, SchemaIOOptions } from './schema.js'
|
|
3
|
+
export type {
|
|
4
|
+
DslFn,
|
|
5
|
+
DslField,
|
|
6
|
+
DslDefinition,
|
|
7
|
+
DslInput,
|
|
8
|
+
IDslBuilder,
|
|
9
|
+
DslIfFn,
|
|
10
|
+
DslErrorNamespace,
|
|
11
|
+
} from './dsl.js'
|
|
12
|
+
export type { ValidateOptions, ValidationResult, ValidationErrorItem, AjvError } from './validate.js'
|
|
13
|
+
export type { DslConfigOptions, I18nConfig, CacheOptions, ValidatorOptions } from './config.js'
|
|
14
|
+
export type { ErrorMessages, ErrorCodeMap } from './error.js'
|
|
15
|
+
export type { Plugin, HookFn, HookName, HookContext, PluginManagerOptions } from './plugin.js'
|
|
16
|
+
export type { IConditionalBuilder } from './conditional.js'
|
|
17
|
+
export type { InferSchema, InferJsonSchema, InferDslDefinition, InferDslString } from './infer.js'
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
type StripMarker<S extends string> = S extends `${infer Base}!` | `${infer Base}?` ? Base : S
|
|
2
|
+
|
|
3
|
+
type KnownDslType =
|
|
4
|
+
| 'string'
|
|
5
|
+
| 'email'
|
|
6
|
+
| 'url'
|
|
7
|
+
| 'uri'
|
|
8
|
+
| 'uuid'
|
|
9
|
+
| 'ipv4'
|
|
10
|
+
| 'ipv6'
|
|
11
|
+
| 'ip'
|
|
12
|
+
| 'hostname'
|
|
13
|
+
| 'date'
|
|
14
|
+
| 'datetime'
|
|
15
|
+
| 'time'
|
|
16
|
+
| 'binary'
|
|
17
|
+
| 'objectId'
|
|
18
|
+
| 'hexColor'
|
|
19
|
+
| 'macAddress'
|
|
20
|
+
| 'cron'
|
|
21
|
+
| 'slug'
|
|
22
|
+
| 'chineseName'
|
|
23
|
+
| 'chinese'
|
|
24
|
+
| 'emailDomain'
|
|
25
|
+
| 'alphanum'
|
|
26
|
+
| 'lower'
|
|
27
|
+
| 'upper'
|
|
28
|
+
| 'json'
|
|
29
|
+
| 'port'
|
|
30
|
+
| 'number'
|
|
31
|
+
| 'integer'
|
|
32
|
+
| 'boolean'
|
|
33
|
+
| 'object'
|
|
34
|
+
| 'array'
|
|
35
|
+
| 'null'
|
|
36
|
+
| 'any'
|
|
37
|
+
|
|
38
|
+
type InferPipeMember<S extends string> = StripMarker<S> extends KnownDslType ? InferDslString<S> : StripMarker<S>
|
|
39
|
+
|
|
40
|
+
type SplitPipe<S extends string> = S extends `${infer Head}|${infer Tail}`
|
|
41
|
+
? InferPipeMember<Head> | SplitPipe<Tail>
|
|
42
|
+
: InferPipeMember<S>
|
|
43
|
+
|
|
44
|
+
type RequiredDslKeys<T extends Record<string, unknown>> = {
|
|
45
|
+
[K in keyof T]: K extends string
|
|
46
|
+
? K extends `${infer Name}!`
|
|
47
|
+
? Name
|
|
48
|
+
: T[K] extends `${string}!`
|
|
49
|
+
? K
|
|
50
|
+
: never
|
|
51
|
+
: never
|
|
52
|
+
}[keyof T]
|
|
53
|
+
|
|
54
|
+
type CleanDslKey<K> = K extends `${infer Name}!` | `${infer Name}?` ? Name : K
|
|
55
|
+
|
|
56
|
+
type InferJsonSchemaProperties<Properties, RequiredKeys extends PropertyKey> =
|
|
57
|
+
& {
|
|
58
|
+
[K in keyof Properties as K extends RequiredKeys ? K : never]-?: InferSchema<Properties[K]>
|
|
59
|
+
}
|
|
60
|
+
& {
|
|
61
|
+
[K in keyof Properties as K extends RequiredKeys ? never : K]?: InferSchema<Properties[K]>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
type InferDslProperties<T extends Record<string, unknown>, RequiredKeys extends PropertyKey = RequiredDslKeys<T>> =
|
|
65
|
+
& {
|
|
66
|
+
[K in keyof T as CleanDslKey<K> extends RequiredKeys ? CleanDslKey<K> : never]-?: InferSchema<T[K]>
|
|
67
|
+
}
|
|
68
|
+
& {
|
|
69
|
+
[K in keyof T as CleanDslKey<K> extends RequiredKeys ? never : CleanDslKey<K>]?: InferSchema<T[K]>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type InferDslString<T extends string> = StripMarker<T> extends `types:${infer Rest}`
|
|
73
|
+
? SplitPipe<Rest>
|
|
74
|
+
: StripMarker<T> extends `enum:${infer Values}`
|
|
75
|
+
? SplitPipe<Values>
|
|
76
|
+
: StripMarker<T> extends `array<${infer Item}>`
|
|
77
|
+
? InferDslString<Item>[]
|
|
78
|
+
: StripMarker<T> extends `${infer Base}:${string}`
|
|
79
|
+
? InferDslString<Base>
|
|
80
|
+
: StripMarker<T> extends 'number' | 'integer' | 'port'
|
|
81
|
+
? number
|
|
82
|
+
: StripMarker<T> extends 'boolean'
|
|
83
|
+
? boolean
|
|
84
|
+
: StripMarker<T> extends 'object'
|
|
85
|
+
? Record<string, unknown>
|
|
86
|
+
: StripMarker<T> extends 'array'
|
|
87
|
+
? unknown[]
|
|
88
|
+
: StripMarker<T> extends 'null'
|
|
89
|
+
? null
|
|
90
|
+
: StripMarker<T> extends 'any'
|
|
91
|
+
? unknown
|
|
92
|
+
: StripMarker<T> extends `${string}|${string}`
|
|
93
|
+
? SplitPipe<StripMarker<T>>
|
|
94
|
+
: string
|
|
95
|
+
|
|
96
|
+
export type InferJsonSchema<T> = T extends { oneOf: readonly (infer Variant)[] }
|
|
97
|
+
? InferSchema<Variant>
|
|
98
|
+
: T extends { anyOf: readonly (infer Variant)[] }
|
|
99
|
+
? InferSchema<Variant>
|
|
100
|
+
: T extends { enum: readonly (infer Value)[] }
|
|
101
|
+
? Value
|
|
102
|
+
: T extends { type: 'object'; properties: infer Properties; required?: readonly (infer RequiredKey)[] }
|
|
103
|
+
? InferJsonSchemaProperties<Properties, Extract<RequiredKey, keyof Properties>>
|
|
104
|
+
: T extends { type: 'array'; items: infer Item }
|
|
105
|
+
? InferSchema<Item>[]
|
|
106
|
+
: T extends { type: 'number' | 'integer' }
|
|
107
|
+
? number
|
|
108
|
+
: T extends { type: 'boolean' }
|
|
109
|
+
? boolean
|
|
110
|
+
: T extends { type: 'null' }
|
|
111
|
+
? null
|
|
112
|
+
: T extends { type: 'object' }
|
|
113
|
+
? Record<string, unknown>
|
|
114
|
+
: T extends { type: 'array' }
|
|
115
|
+
? unknown[]
|
|
116
|
+
: T extends { type: 'string' }
|
|
117
|
+
? string
|
|
118
|
+
: unknown
|
|
119
|
+
|
|
120
|
+
export type InferDslDefinition<T extends Record<string, unknown>> = InferDslProperties<T>
|
|
121
|
+
|
|
122
|
+
export type InferSchema<T> = T extends string
|
|
123
|
+
? InferDslString<T>
|
|
124
|
+
: T extends { type: unknown } | { properties: unknown } | { oneOf: unknown } | { anyOf: unknown } | { enum: unknown }
|
|
125
|
+
? InferJsonSchema<T>
|
|
126
|
+
: T extends Record<string, unknown>
|
|
127
|
+
? InferDslDefinition<T>
|
|
128
|
+
: unknown
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in hook names (pipeline execution phases).
|
|
3
|
+
*/
|
|
4
|
+
export type HookName =
|
|
5
|
+
| 'beforeParse'
|
|
6
|
+
| 'afterParse'
|
|
7
|
+
| 'beforeCompile'
|
|
8
|
+
| 'afterCompile'
|
|
9
|
+
| 'beforeValidate'
|
|
10
|
+
| 'afterValidate'
|
|
11
|
+
| 'onError'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Hook function type (accepts arbitrary arguments; compatible with v1 custom hook names).
|
|
15
|
+
*/
|
|
16
|
+
export type HookFn = (...args: unknown[]) => unknown | Promise<unknown>
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Hook context (passed to built-in hooks).
|
|
20
|
+
*/
|
|
21
|
+
export interface HookContext {
|
|
22
|
+
/** Current hook phase. */
|
|
23
|
+
hook: HookName
|
|
24
|
+
/** Data being processed. */
|
|
25
|
+
data?: unknown
|
|
26
|
+
/** DSL definition. */
|
|
27
|
+
schema?: unknown
|
|
28
|
+
/** Additional metadata. */
|
|
29
|
+
meta?: Record<string, unknown>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Plugin interface (backwards-compatible with v1).
|
|
34
|
+
*/
|
|
35
|
+
export interface Plugin {
|
|
36
|
+
/** Plugin name. */
|
|
37
|
+
name: string
|
|
38
|
+
/** Plugin version. */
|
|
39
|
+
version?: string
|
|
40
|
+
/** Plugin description. */
|
|
41
|
+
description?: string
|
|
42
|
+
/** Plugin options (passed as the second argument to install). */
|
|
43
|
+
options?: Record<string, unknown>
|
|
44
|
+
/** Plugin hook map (supports arbitrary hook names for v1 compatibility). */
|
|
45
|
+
hooks?: Record<string, HookFn>
|
|
46
|
+
/** Install method. */
|
|
47
|
+
install?(core: unknown, options?: unknown, context?: unknown): void
|
|
48
|
+
/** Uninstall method (optional). */
|
|
49
|
+
uninstall?(core?: unknown, context?: unknown): void
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* PluginManager configuration.
|
|
54
|
+
*/
|
|
55
|
+
export interface PluginManagerOptions {
|
|
56
|
+
/** Whether hooks are executed asynchronously (default true). */
|
|
57
|
+
async?: boolean
|
|
58
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema Draft 7 type definitions.
|
|
3
|
+
* Includes schema-dsl internal keys (prefixed with _; stripped by toJsonSchema()).
|
|
4
|
+
*/
|
|
5
|
+
import type { ErrorMessages } from './error.js'
|
|
6
|
+
|
|
7
|
+
export interface JSONSchema {
|
|
8
|
+
// --- Standard JSON Schema Draft 7 fields ---
|
|
9
|
+
type?: string | string[]
|
|
10
|
+
properties?: Record<string, JSONSchema>
|
|
11
|
+
required?: string[]
|
|
12
|
+
minLength?: number
|
|
13
|
+
maxLength?: number
|
|
14
|
+
minimum?: number
|
|
15
|
+
maximum?: number
|
|
16
|
+
exclusiveMinimum?: number | boolean
|
|
17
|
+
exclusiveMaximum?: number | boolean
|
|
18
|
+
multipleOf?: number
|
|
19
|
+
pattern?: string
|
|
20
|
+
format?: string
|
|
21
|
+
enum?: unknown[]
|
|
22
|
+
const?: unknown
|
|
23
|
+
items?: JSONSchema | JSONSchema[]
|
|
24
|
+
minItems?: number
|
|
25
|
+
maxItems?: number
|
|
26
|
+
uniqueItems?: boolean
|
|
27
|
+
additionalProperties?: boolean | JSONSchema
|
|
28
|
+
allOf?: JSONSchema[]
|
|
29
|
+
anyOf?: JSONSchema[]
|
|
30
|
+
oneOf?: JSONSchema[]
|
|
31
|
+
not?: JSONSchema
|
|
32
|
+
if?: JSONSchema
|
|
33
|
+
then?: JSONSchema
|
|
34
|
+
else?: JSONSchema
|
|
35
|
+
title?: string
|
|
36
|
+
description?: string
|
|
37
|
+
default?: unknown
|
|
38
|
+
examples?: unknown[]
|
|
39
|
+
$ref?: string
|
|
40
|
+
$schema?: string
|
|
41
|
+
$id?: string
|
|
42
|
+
definitions?: Record<string, JSONSchema>
|
|
43
|
+
$defs?: Record<string, JSONSchema>
|
|
44
|
+
|
|
45
|
+
// --- schema-dsl internal keys (used during parsing; stripped on output) ---
|
|
46
|
+
_label?: string
|
|
47
|
+
_customMessages?: Record<string, string>
|
|
48
|
+
_description?: string
|
|
49
|
+
_required?: boolean
|
|
50
|
+
|
|
51
|
+
// Allows custom keyword extensions (AJV custom keywords)
|
|
52
|
+
[key: string]: unknown
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* SchemaIO configuration options (backwards-compatible with v1).
|
|
57
|
+
*/
|
|
58
|
+
export interface SchemaIOOptions {
|
|
59
|
+
allErrors?: boolean
|
|
60
|
+
verbose?: boolean
|
|
61
|
+
messages?: ErrorMessages
|
|
62
|
+
locale?: string
|
|
63
|
+
cache?: boolean
|
|
64
|
+
cacheSize?: number
|
|
65
|
+
[key: string]: unknown
|
|
66
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation options.
|
|
3
|
+
*/
|
|
4
|
+
import type { CacheOptions } from './config.js'
|
|
5
|
+
import type { ErrorMessages } from './error.js'
|
|
6
|
+
|
|
7
|
+
export interface ValidateOptions {
|
|
8
|
+
/** Whether to format errors (default true). */
|
|
9
|
+
format?: boolean
|
|
10
|
+
/** Whether to return all errors (default false — only the first). */
|
|
11
|
+
allErrors?: boolean
|
|
12
|
+
/** Dynamically specify a locale (e.g. 'zh-CN', 'en-US', 'ja-JP', 'es-ES', 'fr-FR'). */
|
|
13
|
+
locale?: string
|
|
14
|
+
/** Custom error messages. */
|
|
15
|
+
messages?: ErrorMessages
|
|
16
|
+
/** Whether to enable smart type coercion (auto-converts string → number etc.). */
|
|
17
|
+
smartCoerce?: boolean
|
|
18
|
+
/** Whether to remove additional properties. */
|
|
19
|
+
removeAdditional?: boolean | 'all' | 'failing'
|
|
20
|
+
/** Whether to enable caching. */
|
|
21
|
+
cache?: boolean | CacheOptions
|
|
22
|
+
/** Whether to enable strict mode. */
|
|
23
|
+
strict?: boolean
|
|
24
|
+
[key: string]: unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Validation result.
|
|
29
|
+
*/
|
|
30
|
+
export interface ValidationResult<T = unknown> {
|
|
31
|
+
/** Whether validation passed. */
|
|
32
|
+
valid: boolean
|
|
33
|
+
/** Snapshot of the data after validation (returned on both success and failure; useful for locating input on failure). */
|
|
34
|
+
data?: T
|
|
35
|
+
/** Error list (empty array on success; detailed errors on failure). */
|
|
36
|
+
errors?: ValidationErrorItem[]
|
|
37
|
+
/** First error message (convenience accessor). */
|
|
38
|
+
errorMessage?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Validation error item (element of ValidationResult.errors).
|
|
43
|
+
*/
|
|
44
|
+
export interface ValidationErrorItem {
|
|
45
|
+
/** Error message. */
|
|
46
|
+
message: string
|
|
47
|
+
/** Error field path (dot-separated, e.g. 'user.email'). */
|
|
48
|
+
path: string
|
|
49
|
+
/** Validation keyword (min, max, email, pattern, etc.). */
|
|
50
|
+
keyword: string
|
|
51
|
+
/** Validation parameters. */
|
|
52
|
+
params?: Record<string, unknown>
|
|
53
|
+
/** Alias for path (backwards compatibility). */
|
|
54
|
+
field?: string
|
|
55
|
+
/** Alias for keyword (backwards-compatible with v1 err.type). */
|
|
56
|
+
type?: string | undefined
|
|
57
|
+
/** Expected type (backwards-compatible with v1 err.expected; only present for type errors). */
|
|
58
|
+
expected?: string | undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Raw AJV error object type (internal use).
|
|
63
|
+
*/
|
|
64
|
+
export interface AjvError {
|
|
65
|
+
keyword: string
|
|
66
|
+
instancePath: string
|
|
67
|
+
schemaPath: string
|
|
68
|
+
params: Record<string, unknown>
|
|
69
|
+
message?: string
|
|
70
|
+
data?: unknown
|
|
71
|
+
}
|