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.
Files changed (242) hide show
  1. package/CHANGELOG.md +87 -210
  2. package/README.md +391 -2249
  3. package/dist/DslBuilder-DQDN0ZxZ.d.cts +341 -0
  4. package/dist/DslBuilder-DkLaOo9Q.d.ts +341 -0
  5. package/dist/Validator-C7GsVQOH.d.cts +192 -0
  6. package/dist/Validator-hFWKGxir.d.ts +192 -0
  7. package/dist/index.cjs +6594 -0
  8. package/dist/index.d.cts +1145 -0
  9. package/dist/index.d.ts +1145 -0
  10. package/dist/index.js +6528 -0
  11. package/dist/plugin-CIKtTMtS.d.cts +246 -0
  12. package/dist/plugin-CIKtTMtS.d.ts +246 -0
  13. package/dist/plugins/custom-format.cjs +3802 -0
  14. package/dist/plugins/custom-format.d.cts +12 -0
  15. package/dist/plugins/custom-format.d.ts +12 -0
  16. package/dist/plugins/custom-format.js +3772 -0
  17. package/dist/plugins/custom-type-example.cjs +3795 -0
  18. package/dist/plugins/custom-type-example.d.cts +8 -0
  19. package/dist/plugins/custom-type-example.d.ts +8 -0
  20. package/dist/plugins/custom-type-example.js +3765 -0
  21. package/dist/plugins/custom-validator.cjs +146 -0
  22. package/dist/plugins/custom-validator.d.cts +10 -0
  23. package/dist/plugins/custom-validator.d.ts +10 -0
  24. package/dist/plugins/custom-validator.js +121 -0
  25. package/docs/FEATURE-INDEX.md +102 -68
  26. package/docs/add-custom-locale.md +48 -35
  27. package/docs/add-keyword.md +24 -0
  28. package/docs/api-reference.md +396 -154
  29. package/docs/api.md +13 -0
  30. package/docs/best-practices-project-structure.md +19 -10
  31. package/docs/best-practices.md +93 -53
  32. package/docs/cache-manager.md +23 -15
  33. package/docs/compile.md +45 -0
  34. package/docs/conditional-api.md +40 -11
  35. package/docs/custom-extensions-guide.md +80 -152
  36. package/docs/design-philosophy.md +76 -71
  37. package/docs/doc-index.md +324 -0
  38. package/docs/dsl-syntax.md +69 -19
  39. package/docs/dynamic-locale.md +24 -14
  40. package/docs/enum.md +12 -5
  41. package/docs/error-handling.md +53 -44
  42. package/docs/export-guide.md +47 -8
  43. package/docs/export-limitations.md +27 -11
  44. package/docs/faq.md +86 -67
  45. package/docs/frontend-i18n-guide.md +26 -12
  46. package/docs/i18n-user-guide.md +60 -47
  47. package/docs/i18n.md +51 -32
  48. package/docs/index.md +48 -0
  49. package/docs/json-schema-basics.md +40 -0
  50. package/docs/label-vs-description.md +12 -3
  51. package/docs/markdown-exporter.md +15 -6
  52. package/docs/mongodb-exporter.md +11 -4
  53. package/docs/multi-language.md +26 -0
  54. package/docs/multi-type-support.md +26 -33
  55. package/docs/mysql-exporter.md +9 -2
  56. package/docs/number-operators.md +12 -5
  57. package/docs/optional-marker-guide.md +28 -23
  58. package/docs/performance-guide.md +49 -0
  59. package/docs/plugin-system.md +205 -366
  60. package/docs/plugin-type-registration.md +34 -0
  61. package/docs/postgresql-exporter.md +9 -2
  62. package/docs/public/favicon.svg +5 -0
  63. package/docs/quick-start.md +37 -363
  64. package/docs/runtime-locale-support.md +20 -9
  65. package/docs/schema-helper.md +10 -5
  66. package/docs/schema-utils-advanced-issues.md +23 -0
  67. package/docs/schema-utils-best-practices.md +20 -0
  68. package/docs/schema-utils-chaining.md +7 -0
  69. package/docs/schema-utils.md +76 -42
  70. package/docs/security-checklist.md +20 -0
  71. package/docs/string-extensions.md +17 -9
  72. package/docs/troubleshooting.md +36 -21
  73. package/docs/type-converter.md +41 -50
  74. package/docs/type-reference.md +38 -15
  75. package/docs/typescript-guide.md +53 -42
  76. package/docs/union-type-guide.md +11 -1
  77. package/docs/union-types.md +10 -3
  78. package/docs/validate-async.md +36 -25
  79. package/docs/validate-batch.md +49 -0
  80. package/docs/validate-dsl-object-support.md +33 -28
  81. package/docs/validate.md +36 -16
  82. package/docs/validation-guide.md +25 -7
  83. package/docs/validator.md +39 -0
  84. package/package.json +85 -27
  85. package/plugins/custom-format.cjs +8 -0
  86. package/plugins/custom-type-example.cjs +8 -0
  87. package/plugins/custom-validator.cjs +8 -0
  88. package/src/adapters/DslAdapter.ts +111 -0
  89. package/src/adapters/index.ts +1 -0
  90. package/src/config/constants.ts +83 -0
  91. package/src/config/index.ts +2 -0
  92. package/src/config/patterns.ts +77 -0
  93. package/src/core/CacheManager.ts +159 -0
  94. package/src/core/ConditionalBuilder.ts +382 -0
  95. package/src/core/ConditionalRuntime.ts +28 -0
  96. package/src/core/ConditionalValidator.ts +255 -0
  97. package/src/core/DslBuilder.ts +677 -0
  98. package/src/core/ErrorCodes.ts +38 -0
  99. package/src/core/ErrorFormatter.ts +271 -0
  100. package/src/core/JSONSchemaCore.ts +65 -0
  101. package/src/core/Locale.ts +187 -0
  102. package/src/core/MessageTemplate.ts +42 -0
  103. package/src/core/ObjectDslBuilder.ts +64 -0
  104. package/src/core/PluginManager.ts +326 -0
  105. package/src/core/StringExtensions.ts +140 -0
  106. package/src/core/TemplateEngine.ts +44 -0
  107. package/src/core/Validator.ts +448 -0
  108. package/src/errors/I18nError.ts +159 -0
  109. package/src/errors/ValidationError.ts +105 -0
  110. package/src/exporters/BaseExporter.ts +60 -0
  111. package/src/exporters/MarkdownExporter.ts +305 -0
  112. package/src/exporters/MongoDBExporter.ts +126 -0
  113. package/src/exporters/MySQLExporter.ts +155 -0
  114. package/src/exporters/PostgreSQLExporter.ts +222 -0
  115. package/src/exporters/index.ts +18 -0
  116. package/src/index.ts +633 -0
  117. package/{lib/locales/en-US.js → src/locales/en-US.ts} +21 -37
  118. package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +63 -16
  119. package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +74 -27
  120. package/src/locales/index.ts +103 -0
  121. package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +59 -17
  122. package/src/locales/types.ts +156 -0
  123. package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +21 -38
  124. package/src/parser/ConstraintParser.ts +101 -0
  125. package/src/parser/DslParser.ts +470 -0
  126. package/src/parser/SchemaCompiler.ts +66 -0
  127. package/src/parser/TypeRegistry.ts +250 -0
  128. package/src/parser/index.ts +6 -0
  129. package/src/plugins/custom-format.ts +126 -0
  130. package/src/plugins/custom-type-example.ts +108 -0
  131. package/src/plugins/custom-validator.ts +140 -0
  132. package/src/types/conditional.ts +28 -0
  133. package/src/types/config.ts +59 -0
  134. package/src/types/dsl.ts +131 -0
  135. package/src/types/error.ts +60 -0
  136. package/src/types/index.ts +17 -0
  137. package/src/types/infer.ts +128 -0
  138. package/src/types/plugin.ts +58 -0
  139. package/src/types/safe-regex.d.ts +9 -0
  140. package/src/types/schema.ts +66 -0
  141. package/src/types/validate.ts +71 -0
  142. package/src/utils/SchemaHelper.ts +196 -0
  143. package/src/utils/SchemaUtils.ts +346 -0
  144. package/src/utils/TypeConverter.ts +215 -0
  145. package/src/utils/index.ts +10 -0
  146. package/src/validators/CustomKeywords.ts +477 -0
  147. package/.eslintignore +0 -11
  148. package/.eslintrc.json +0 -27
  149. package/CONTRIBUTING.md +0 -368
  150. package/STATUS.md +0 -491
  151. package/changelogs/v1.0.0.md +0 -328
  152. package/changelogs/v1.0.9.md +0 -367
  153. package/changelogs/v1.1.0.md +0 -389
  154. package/changelogs/v1.1.1.md +0 -308
  155. package/changelogs/v1.1.2.md +0 -183
  156. package/changelogs/v1.1.3.md +0 -161
  157. package/changelogs/v1.1.4.md +0 -432
  158. package/changelogs/v1.1.5.md +0 -493
  159. package/changelogs/v1.1.6.md +0 -211
  160. package/changelogs/v1.1.8.md +0 -376
  161. package/changelogs/v1.2.3.md +0 -124
  162. package/docs/INDEX.md +0 -252
  163. package/docs/issues-resolved-summary.md +0 -196
  164. package/docs/performance-benchmark-report.md +0 -179
  165. package/docs/performance-quick-reference.md +0 -123
  166. package/docs/user-questions-answered.md +0 -353
  167. package/docs/validation-rules-v1.0.2.md +0 -1608
  168. package/examples/README.md +0 -81
  169. package/examples/array-dsl-example.js +0 -227
  170. package/examples/conditional-example.js +0 -288
  171. package/examples/conditional-non-object.js +0 -129
  172. package/examples/conditional-validate-example.js +0 -321
  173. package/examples/custom-extension.js +0 -85
  174. package/examples/dsl-match-example.js +0 -74
  175. package/examples/dsl-style.js +0 -118
  176. package/examples/dynamic-locale-configuration.js +0 -348
  177. package/examples/dynamic-locale-example.js +0 -287
  178. package/examples/enum.examples.js +0 -324
  179. package/examples/export-demo.js +0 -130
  180. package/examples/express-integration.js +0 -376
  181. package/examples/i18n-error-handling-complete.js +0 -381
  182. package/examples/i18n-error-handling-quickstart.md +0 -0
  183. package/examples/i18n-error.examples.js +0 -181
  184. package/examples/i18n-full-demo.js +0 -301
  185. package/examples/i18n-memory-safety.examples.js +0 -268
  186. package/examples/markdown-export.js +0 -71
  187. package/examples/middleware-usage.js +0 -93
  188. package/examples/new-features-comparison.js +0 -315
  189. package/examples/password-reset/README.md +0 -153
  190. package/examples/password-reset/schema.js +0 -26
  191. package/examples/password-reset/test.js +0 -101
  192. package/examples/plugin-system.examples.js +0 -205
  193. package/examples/schema-utils-chaining.examples.js +0 -250
  194. package/examples/simple-example.js +0 -122
  195. package/examples/slug.examples.js +0 -179
  196. package/examples/string-extensions.js +0 -297
  197. package/examples/union-type-example.js +0 -127
  198. package/examples/union-types-example.js +0 -77
  199. package/examples/user-registration/README.md +0 -156
  200. package/examples/user-registration/routes.js +0 -92
  201. package/examples/user-registration/schema.js +0 -150
  202. package/examples/user-registration/server.js +0 -74
  203. package/index.d.ts +0 -3540
  204. package/index.js +0 -457
  205. package/index.mjs +0 -60
  206. package/lib/adapters/DslAdapter.js +0 -871
  207. package/lib/adapters/index.js +0 -20
  208. package/lib/config/constants.js +0 -286
  209. package/lib/config/patterns/common.js +0 -47
  210. package/lib/config/patterns/creditCard.js +0 -9
  211. package/lib/config/patterns/idCard.js +0 -9
  212. package/lib/config/patterns/index.js +0 -9
  213. package/lib/config/patterns/licensePlate.js +0 -4
  214. package/lib/config/patterns/passport.js +0 -4
  215. package/lib/config/patterns/phone.js +0 -9
  216. package/lib/config/patterns/postalCode.js +0 -5
  217. package/lib/core/CacheManager.js +0 -376
  218. package/lib/core/ConditionalBuilder.js +0 -503
  219. package/lib/core/DslBuilder.js +0 -1400
  220. package/lib/core/ErrorCodes.js +0 -233
  221. package/lib/core/ErrorFormatter.js +0 -445
  222. package/lib/core/JSONSchemaCore.js +0 -347
  223. package/lib/core/Locale.js +0 -130
  224. package/lib/core/MessageTemplate.js +0 -98
  225. package/lib/core/PluginManager.js +0 -448
  226. package/lib/core/StringExtensions.js +0 -240
  227. package/lib/core/Validator.js +0 -654
  228. package/lib/errors/I18nError.js +0 -328
  229. package/lib/errors/ValidationError.js +0 -191
  230. package/lib/exporters/MarkdownExporter.js +0 -420
  231. package/lib/exporters/MongoDBExporter.js +0 -162
  232. package/lib/exporters/MySQLExporter.js +0 -212
  233. package/lib/exporters/PostgreSQLExporter.js +0 -289
  234. package/lib/exporters/index.js +0 -24
  235. package/lib/locales/index.js +0 -8
  236. package/lib/utils/LRUCache.js +0 -174
  237. package/lib/utils/SchemaHelper.js +0 -240
  238. package/lib/utils/SchemaUtils.js +0 -445
  239. package/lib/utils/TypeConverter.js +0 -245
  240. package/lib/utils/index.js +0 -13
  241. package/lib/validators/CustomKeywords.js +0 -616
  242. package/lib/validators/index.js +0 -11
@@ -0,0 +1,1145 @@
1
+ import { V as Validator } from './Validator-C7GsVQOH.cjs';
2
+ export { C as CacheManager } from './Validator-C7GsVQOH.cjs';
3
+ import { J as JSONSchema, V as ValidationResult, E as ErrorMessages, a as ValidationErrorItem, P as Plugin, H as HookFn, b as ErrorCodeMap, D as DslConfigOptions } from './plugin-CIKtTMtS.cjs';
4
+ export { C as CacheConfig, C as CacheOptions, I as I18nConfig, S as SchemaIOOptions, c as ValidateOptions, d as ValidatorOptions } from './plugin-CIKtTMtS.cjs';
5
+ import { I as IConditionalBuilder, D as DslBuilder, a as IDslBuilder, b as DslDefinition, c as DslConditionMarker } from './DslBuilder-DQDN0ZxZ.cjs';
6
+ export { d as DslErrorNamespace, e as DslField, f as DslFn, g as DslIfFn, h as DslInput } from './DslBuilder-DQDN0ZxZ.cjs';
7
+ import { EventEmitter } from 'node:events';
8
+ import { Ajv } from 'ajv';
9
+
10
+ /**
11
+ * JSONSchemaCore — v1 compatibility facade.
12
+ *
13
+ * The v2 internals have been split into DslParser / SchemaCompiler / Validator; this class
14
+ * restores the commonly-used chainable entry points from the v1 public API so that users
15
+ * who import from the main entry point do not encounter errors.
16
+ */
17
+ declare class JSONSchemaCore {
18
+ schema: JSONSchema;
19
+ constructor(schema?: JSONSchema);
20
+ type(typeName: string): this;
21
+ property(name: string, schema: JSONSchema): this;
22
+ properties(properties: Record<string, JSONSchema>): this;
23
+ required(fields: string[] | string): this;
24
+ format(formatName: string): this;
25
+ pattern(pattern: RegExp | string): this;
26
+ items(schema: JSONSchema): this;
27
+ toSchema(): JSONSchema;
28
+ getSchema(): JSONSchema;
29
+ validate(data: unknown): ReturnType<Validator['validate']>;
30
+ }
31
+
32
+ /**
33
+ * ConditionalBuilder — chainable condition builder.
34
+ *
35
+ * v2 fixes:
36
+ * C-03: assert() throws ValidationError instead of plain Error
37
+ * C-Y01: elseIf semantics correct
38
+ * C-Y02: build() as toSchema() alias (IConditionalBuilder interface compat)
39
+ */
40
+
41
+ type ConditionFn = (data: unknown) => boolean;
42
+ declare class ConditionalBuilder implements IConditionalBuilder {
43
+ private _conditions;
44
+ private _elseSchema;
45
+ constructor();
46
+ if(conditionFn: ConditionFn | string): this;
47
+ and(conditionFn: ConditionFn): this;
48
+ /**
49
+ * require(field) — v1 compat: require the specified field to be truthy.
50
+ * Equivalent to .and(data => Boolean(data[field])).
51
+ * BC-5 fix.
52
+ */
53
+ require(field: string): this;
54
+ or(conditionFn: ConditionFn): this;
55
+ elseIf(conditionFn: ConditionFn): this;
56
+ message(msg: string): this;
57
+ then(schema: string | JSONSchema | null): this;
58
+ else(schema: string | JSONSchema | null): this;
59
+ /**
60
+ * Produce a schema object carrying serialisable conditional metadata plus non-enumerable runtime state.
61
+ */
62
+ toSchema(): JSONSchema;
63
+ /**
64
+ * build() — alias for toSchema() (IConditionalBuilder interface compat).
65
+ */
66
+ build(): JSONSchema;
67
+ private readonly _validatorCache;
68
+ private static readonly _VALIDATOR_CACHE_MAX;
69
+ validate(data: unknown, options?: Record<string, unknown>): ValidationResult<unknown>;
70
+ validateAsync(data: unknown, options?: Record<string, unknown>): Promise<ValidationResult<unknown>>;
71
+ /**
72
+ * assert() — synchronous assertion; throws ValidationError on failure (fixes C-03: v1 threw plain Error).
73
+ * Evaluates conditions synchronously without going through Validator (which is async).
74
+ */
75
+ assert(data: unknown, options?: Record<string, unknown>): unknown;
76
+ check(data: unknown): boolean;
77
+ static start(conditionFn: ConditionFn | string): ConditionalBuilder;
78
+ private _evaluateCondition;
79
+ private _getValidator;
80
+ private _getConstructorOptions;
81
+ private _getValidatorCacheKey;
82
+ private _normalizeOptionValue;
83
+ }
84
+
85
+ /**
86
+ * ObjectDslBuilder — v1 compat: dsl(object) returns a chainable builder.
87
+ *
88
+ * BC-2 fix: in v1, the schema returned by dsl({...}) / parseObject() supported .strict() /
89
+ * .requireAll() and other chain decorators, and implemented the toSchema() duck-type interface
90
+ * (Validator passes through internal schema). After v2 refactor, parseObject() returned plain
91
+ * JSONSchema, losing all chain API. This class wraps the DslParser.parseObject() result and
92
+ * exposes v1-equivalent chain methods:
93
+ * - toSchema() — return internal JSONSchema (Validator duck-type entry point)
94
+ * - toJsonSchema() — return clean JSON Schema (internal schema-dsl keywords stripped)
95
+ * - strict() — disallow extra properties
96
+ * - requireAll() — require all defined properties to be present
97
+ * - toString() — serialize to JSON string
98
+ */
99
+
100
+ declare class ObjectDslBuilder {
101
+ readonly _isDslBuilder: true;
102
+ readonly _isObjectDsl: true;
103
+ private _schema;
104
+ constructor(schema: JSONSchema);
105
+ /** Return internal JSONSchema (Validator.validate() duck-type entry point). */
106
+ toSchema(): JSONSchema;
107
+ /** Return clean JSON Schema (internal schema-dsl keywords stripped; safe for serialization or external tools). */
108
+ toJsonSchema(): JSONSchema;
109
+ toString(): string;
110
+ /**
111
+ * strict() — disallow extra properties (v1 compat).
112
+ * Equivalent to setting strictSchema: true on the compiled schema.
113
+ */
114
+ strict(): this;
115
+ /**
116
+ * requireAll() — require all defined properties to be present (v1 compat).
117
+ * Equivalent to setting requiredAll: true on the compiled schema.
118
+ */
119
+ requireAll(): this;
120
+ }
121
+
122
+ /**
123
+ * LocaleKey — union type of all locale message keys (118 keys)
124
+ *
125
+ * TypeScript compile-time completeness enforcement: every locale file must implement
126
+ * the LocaleMessages interface; adding a new key causes a compiler error in all locales.
127
+ */
128
+ /** A message is either a plain string or an object with code (v1.1.5+ format) */
129
+ type LocaleMessage = string | {
130
+ code: string | number;
131
+ message: string;
132
+ };
133
+
134
+ interface LocaleResolvedMessage {
135
+ code: string | number;
136
+ message: string;
137
+ }
138
+ declare class Locale {
139
+ private static _currentLocale;
140
+ private static _customMessages;
141
+ /** v1 compat: expose custom messages */
142
+ static get customMessages(): Record<string, LocaleMessage>;
143
+ /** v1 compat: expose all locales as { locale: messages } map */
144
+ static get locales(): Record<string, Record<string, LocaleMessage>>;
145
+ static setLocale(locale: string): void;
146
+ static getLocale(): string;
147
+ static setMessages(messages: Record<string, LocaleMessage>): void;
148
+ static addLocale(locale: string, messages: Record<string, LocaleMessage>): void;
149
+ static getAvailableLocales(): string[];
150
+ static isSupportedLocale(locale: string): boolean;
151
+ /**
152
+ * Get a resolved message (v1 compat: returns { code, message } on hit).
153
+ *
154
+ * Priority: custom messages > locale pack > key itself.
155
+ */
156
+ static getMessage(type: string, customMessages?: Record<string, LocaleMessage>, locale?: string | null): LocaleResolvedMessage | string;
157
+ /**
158
+ * Get the final message text (used internally by v2 to avoid "[object Object]" in message field).
159
+ */
160
+ static getMessageText(type: string, customMessages?: Record<string, LocaleMessage>, locale?: string | null): string;
161
+ /**
162
+ * Get raw message config (used by I18nError; may include a numeric code).
163
+ */
164
+ static getMessageConfig(type: string, customMessages?: Record<string, LocaleMessage>, locale?: string | null): LocaleMessage;
165
+ /**
166
+ * Get the full message table for the given locale (built-in + custom).
167
+ */
168
+ static getMessages(locale?: string): Record<string, LocaleMessage>;
169
+ /**
170
+ * Reset to defaults (for testing).
171
+ */
172
+ static reset(): void;
173
+ private static _normalizeResolvedMessage;
174
+ private static _resolveMessage;
175
+ private static _isLocaleKey;
176
+ }
177
+
178
+ type AjvRawError = {
179
+ keyword: string;
180
+ instancePath: string;
181
+ schemaPath?: string;
182
+ params: Record<string, unknown>;
183
+ message?: string;
184
+ data?: unknown;
185
+ parentSchema?: Record<string, unknown>;
186
+ schema?: unknown;
187
+ };
188
+ /**
189
+ * Error formatter.
190
+ * Delegates template interpolation to TemplateEngine.renderTemplate() (fix CORE-03).
191
+ * Maintains full v1 API compatibility.
192
+ */
193
+ declare class ErrorFormatter {
194
+ private messages;
195
+ private _locale;
196
+ private readonly _constructorCustomMessages;
197
+ constructor(locale?: string, messages?: ErrorMessages | Record<string, LocaleMessage | string | undefined>);
198
+ get locale(): string;
199
+ /**
200
+ * Format a single error object → message string (v1 API).
201
+ */
202
+ format(error: AjvRawError | Record<string, unknown>, locale?: string): string;
203
+ /**
204
+ * Format an AJV raw error array → ValidationErrorItem[].
205
+ *
206
+ * @param alreadyMerged - when true, customMessages is already a fully merged locale+custom result;
207
+ * skip `{ ...this.messages, ...customMessages }` spread (avoids 100+ key cold-spread overhead).
208
+ */
209
+ formatDetailed(errors: AjvRawError[], locale?: string, customMessages?: ErrorMessages, alreadyMerged?: boolean): ValidationErrorItem[];
210
+ /**
211
+ * Format a single error entry into a ValidationErrorItem.
212
+ */
213
+ private _formatOne;
214
+ setLocale(locale: string): void;
215
+ addMessage(type: string, template: string): void;
216
+ addMessages(messages: ErrorMessages): void;
217
+ }
218
+
219
+ /**
220
+ * MessageTemplate — wraps a template string for rendering.
221
+ * Delegates to TemplateEngine.renderTemplate() (fix CORE-03).
222
+ * Maintains full v1 API compatibility (constructor + render + static render + static renderBatch).
223
+ */
224
+ declare class MessageTemplate {
225
+ private readonly template;
226
+ constructor(template: string);
227
+ /**
228
+ * Render the template with the given context.
229
+ */
230
+ render(context?: Record<string, unknown>): string;
231
+ /**
232
+ * Statically render a template string with the given context.
233
+ */
234
+ static render(template: string, context?: Record<string, unknown>): string;
235
+ /**
236
+ * Statically render multiple templates in batch.
237
+ */
238
+ static renderBatch(templates: Record<string, string>, context?: Record<string, unknown>): Record<string, string>;
239
+ }
240
+
241
+ /**
242
+ * Unified template engine.
243
+ *
244
+ * Merges the two rendering implementations from v1 — MessageTemplate.render() and
245
+ * ErrorFormatter._interpolate() — into a single pipeline.
246
+ * Fixes the CORE-03 template injection vulnerability (single-pass replacement so that
247
+ * substituted values are never expanded a second time).
248
+ *
249
+ * Supports two placeholder formats:
250
+ * {{#key}} ← all v1 locale files use this format (must remain compatible)
251
+ * {key} ← recommended format for v2 message templates
252
+ */
253
+ /**
254
+ * Render a template string by replacing placeholders with corresponding values from params.
255
+ *
256
+ * @param template - Template string, e.g. "{{#label}} must be at least {{#min}} characters"
257
+ * @param params - Substitution parameter object
258
+ * @returns Rendered string; placeholders with no matching key are kept as-is (aids debugging)
259
+ *
260
+ * @example
261
+ * renderTemplate('{{#label}} is required', { label: 'Email' })
262
+ * // → 'Email is required'
263
+ *
264
+ * renderTemplate('{field} must be {min}~{max}', { field: 'age', min: 18, max: 65 })
265
+ * // → 'age must be 18~65'
266
+ */
267
+ declare function renderTemplate(template: string, params: Record<string, unknown>): string;
268
+
269
+ /**
270
+ * PluginManager — plugin registration and hook execution.
271
+ *
272
+ * Full v1 compatible API:
273
+ * - hooks : public hooks Map; supports any hook name
274
+ * - EventEmitter compat: on / once / off / emit / removeListener / removeAllListeners
275
+ * - unhook(name, fn): remove a specific hook handler
276
+ * - runHook(name, ...args): pass arbitrary args, collect return values
277
+ * - install(core, name?, opts?): supports named + options install for a single plugin
278
+ * - install / uninstall pass through context
279
+ * - has / get / list / clear / size / uninstall (alias)
280
+ */
281
+ declare class PluginManager extends EventEmitter {
282
+ readonly plugins: Map<string, Plugin>;
283
+ /**
284
+ * Public hooks Map (v1 compat: pluginManager.hooks.get('hookName')).
285
+ * Supports any string name, not limited to built-in HookName values.
286
+ */
287
+ readonly hooks: Map<string, Array<HookFn>>;
288
+ /** v1 compat context (passed to plugin install / uninstall). */
289
+ readonly context: {
290
+ plugins: Map<string, Plugin>;
291
+ hooks: Map<string, Array<HookFn>>;
292
+ };
293
+ /** Per-plugin hook references (used for automatic cleanup on unregister). */
294
+ private readonly _pluginHooks;
295
+ private _installedCore;
296
+ /** Built-in hook names (pre-initialized on construction). */
297
+ private static readonly BUILTIN_HOOKS;
298
+ /** Legacy v1 lifecycle hook names. */
299
+ private static readonly LEGACY_HOOKS;
300
+ constructor();
301
+ /**
302
+ * Register a plugin.
303
+ */
304
+ register(plugin: Plugin): this;
305
+ /**
306
+ * Add a hook callback (supports any name, not limited to built-in HookName).
307
+ */
308
+ hook(name: string, fn: HookFn): this;
309
+ /**
310
+ * Remove a specific hook handler (v1 compat: unhook).
311
+ */
312
+ unhook(name: string, fn: HookFn): this;
313
+ /**
314
+ * Run the specified hook.
315
+ * - Args are passed directly to each handler (v1 compat: runHook(name, arg1, arg2, ...)).
316
+ * - Returns an array of all handler return values.
317
+ * - If a handler throws, emits 'hook:error' and runs onError (does not interrupt remaining handlers).
318
+ */
319
+ runHook(name: string, ...args: unknown[]): Promise<unknown[]>;
320
+ /**
321
+ * Install plugins.
322
+ *
323
+ * Supports two call forms (v1 compat):
324
+ * install(core) — install all registered plugins
325
+ * install(core, pluginName, options?) — install the named plugin, merging plugin.options + options
326
+ */
327
+ install(core: unknown, pluginName?: string, extraOptions?: Record<string, unknown>): this;
328
+ private _installPlugin;
329
+ /**
330
+ * Unregister a plugin (v2 primary method).
331
+ * - Automatically cleans up all hooks registered by this plugin.
332
+ * - Emits 'plugin:uninstalled' event.
333
+ */
334
+ unregister(name: string, coreInstance?: unknown): this;
335
+ /** v1 compat: check whether a plugin is registered. */
336
+ has(name: string): boolean;
337
+ /** v1 compat: get a single plugin or the full plugins Map. */
338
+ get(name?: string): Plugin | Map<string, Plugin> | undefined;
339
+ /** v1 compat: list all plugin metadata. */
340
+ list(): Array<{
341
+ name: string;
342
+ version?: string;
343
+ description?: string;
344
+ }>;
345
+ /** v1 compat: clear all plugins (including hook cleanup). */
346
+ clear(coreInstance?: unknown): this;
347
+ /** v1 compat: uninstall a plugin (alias for unregister). */
348
+ uninstall(name: string, coreInstance?: unknown): this;
349
+ get pluginCount(): number;
350
+ /** v1 compat: plugin count (alias for pluginCount). */
351
+ get size(): number;
352
+ private _ensureHook;
353
+ private _addPluginHook;
354
+ private _runHookSync;
355
+ }
356
+
357
+ /**
358
+ * Type definition (structure of each entry in TypeRegistry)
359
+ */
360
+ interface TypeDefinition {
361
+ /** Base JSON Schema fragment for this type */
362
+ baseSchema: Partial<JSONSchema>;
363
+ /** Custom messages associated with this type (e.g., error key for phone type) */
364
+ customMessages?: Record<string, string>;
365
+ /** Whether this type uses a pattern (keys are standard JSON Schema fields, not stripped in toJsonSchema) */
366
+ isPattern?: boolean;
367
+ }
368
+ /**
369
+ * TypeRegistry — unified type registration and resolution
370
+ *
371
+ * Replaces the three inconsistent type lists in v1 (fixes DB-01/DB-02/DA-01)
372
+ */
373
+ declare const TypeRegistry: {
374
+ /**
375
+ * Resolve a type name to its TypeDefinition.
376
+ * Built-in types take priority; custom types may override non-primitive built-ins.
377
+ */
378
+ readonly resolve: (typeName: string) => TypeDefinition;
379
+ /**
380
+ * Register a custom type (delegated from DslBuilder.registerType)
381
+ */
382
+ readonly register: (name: string, def: TypeDefinition | Partial<JSONSchema>) => void;
383
+ /**
384
+ * Register a dynamic type (factory function invoked on every resolve call)
385
+ */
386
+ readonly registerDynamic: (name: string, factory: () => JSONSchema) => void;
387
+ /**
388
+ * Unregister a custom type
389
+ */
390
+ readonly unregister: (name: string) => void;
391
+ /**
392
+ * Clear all custom and dynamic types (primarily for testing; called by DslBuilder.clearCustomTypes).
393
+ * Built-in types are unaffected.
394
+ */
395
+ readonly clearCustomTypes: () => void;
396
+ /**
397
+ * Enable or disable strict mode for type resolution.
398
+ * In strict mode, resolving an unknown type throws instead of warning and falling back to string.
399
+ */
400
+ readonly setStrict: (flag: boolean) => void;
401
+ /**
402
+ * Check whether a type is registered (built-in or custom)
403
+ */
404
+ readonly has: (typeName: string) => boolean;
405
+ /**
406
+ * Return an iterator over all registered types (built-in + custom; custom overrides same-name built-in)
407
+ * BC-4 compat: consumed by the DslAdapter.typeMap getter
408
+ */
409
+ readonly entries: () => IterableIterator<[string, TypeDefinition]>;
410
+ /**
411
+ * Return the internal key set (used to strip non-standard fields during toJsonSchema)
412
+ */
413
+ readonly getInternalKeys: () => ReadonlySet<string>;
414
+ /**
415
+ * Strip internal keys from a schema and return a clean JSON Schema.
416
+ *
417
+ * Special case for exactLength: translated to standard minLength + maxLength
418
+ * instead of being stripped. This preserves v1 DslBuilder string:N behavior
419
+ * (output {minLength:N, maxLength:N}) while keeping AJV's exactLength Unicode
420
+ * code-point counting advantage internally (CK-Y04).
421
+ */
422
+ readonly toJsonSchema: (schema: JSONSchema) => JSONSchema;
423
+ };
424
+
425
+ /**
426
+ * ValidationError — error class thrown when validateAsync() fails.
427
+ * Fixes v1 bug: malformed message format when errors array is empty.
428
+ */
429
+ declare class ValidationError extends Error {
430
+ readonly name: "ValidationError";
431
+ readonly errors: ValidationErrorItem[];
432
+ readonly data: unknown;
433
+ readonly statusCode: number;
434
+ constructor(errors: ValidationErrorItem[], data?: unknown, statusCode?: number);
435
+ toJSON(): {
436
+ error: string;
437
+ message: string;
438
+ statusCode: number;
439
+ details: Array<{
440
+ field: string | null;
441
+ message: string;
442
+ keyword: string;
443
+ params?: Record<string, unknown>;
444
+ }>;
445
+ };
446
+ getFieldError(field: string): ValidationErrorItem | null;
447
+ getFieldErrors(): Record<string, string>;
448
+ hasFieldError(field: string): boolean;
449
+ getErrorCount(): number;
450
+ }
451
+
452
+ type ParamsOrLocale = Record<string, unknown> | string | null | undefined;
453
+ /**
454
+ * Internationalised error class.
455
+ * Maintains full v1 API compatibility: create / throw / assert / is / toJSON / toString
456
+ */
457
+ declare class I18nError extends Error {
458
+ readonly name: "I18nError";
459
+ readonly originalKey: string;
460
+ readonly code: string | number;
461
+ readonly params: Record<string, unknown>;
462
+ readonly statusCode: number;
463
+ readonly locale: string | null;
464
+ constructor(key: string, params?: Record<string, unknown>, statusCode?: number, locale?: string | null,
465
+ /** Internal: pre-resolved message template, bypasses Locale lookup (used to decouple init ordering). */
466
+ _resolvedTemplate?: string, _resolvedCode?: string | number);
467
+ /** Factory method — create an error instance. */
468
+ static create(code: string, paramsOrLocale?: ParamsOrLocale, statusCode?: number, locale?: string): I18nError;
469
+ /** Factory method — create and throw an error. */
470
+ static throw(code: string, paramsOrLocale?: ParamsOrLocale, statusCode?: number, locale?: string): never;
471
+ /** Assert — throw when condition is falsy. */
472
+ static assert(condition: unknown, code: string, paramsOrLocale?: ParamsOrLocale, statusCode?: number, locale?: string): asserts condition;
473
+ /** Check whether the error matches the given code or original key. */
474
+ is(codeOrKey: string | number): boolean;
475
+ toJSON(): {
476
+ error: string;
477
+ originalKey: string;
478
+ code: string | number;
479
+ message: string;
480
+ params: Record<string, unknown>;
481
+ statusCode: number;
482
+ locale: string | null;
483
+ };
484
+ toString(): string;
485
+ }
486
+
487
+ /**
488
+ * StringExtensions — opt-in String.prototype chainable DSL extensions.
489
+ *
490
+ * v2 fixes:
491
+ * S-01/S-02: array-driven symmetric install/uninstall (v1 uninstall was missing `format` and
492
+ * `phoneNumber`). All method names are now maintained in the EXTENSION_METHODS
493
+ * array so both operations are guaranteed to be in sync.
494
+ *
495
+ * @example
496
+ * import { installStringExtensions } from 'schema-dsl'
497
+ * installStringExtensions(dsl)
498
+ * // Then you can use:
499
+ * 'email!'.label('Email address').messages({ format: 'Invalid format' })
500
+ * 'string:3-32!'.username('medium')
501
+ */
502
+
503
+ type DslFn = (dslStr: string) => DslBuilder;
504
+ /**
505
+ * Install String.prototype extensions.
506
+ * @param dslFunction - dsl() function (converts a string to a DslBuilder instance)
507
+ */
508
+ declare function installStringExtensions$1(dslFunction: DslFn): void;
509
+ /**
510
+ * Uninstall String.prototype extensions (useful for tests or clean-up).
511
+ * S-01/S-02 fix: uses EXTENSION_METHODS array to guarantee perfect symmetry with install.
512
+ */
513
+ declare function uninstallStringExtensions(): void;
514
+
515
+ /**
516
+ * BaseExporter — Base interface and abstract class for all exporters.
517
+ *
518
+ * Provides a unified abstract export() method signature; each exporter subclass implements it.
519
+ */
520
+
521
+ interface ExporterOptions {
522
+ [key: string]: unknown;
523
+ }
524
+ declare abstract class BaseExporter<TOptions extends ExporterOptions = ExporterOptions> {
525
+ protected options: TOptions;
526
+ constructor(options?: Partial<TOptions>);
527
+ /**
528
+ * Export a JSON Schema to the target format.
529
+ * Each subclass must implement this method.
530
+ */
531
+ abstract export(...args: unknown[]): unknown;
532
+ /**
533
+ * Assert that the input JSON Schema is a valid object-type schema.
534
+ * @throws Error if invalid.
535
+ */
536
+ protected _assertObjectSchema(jsonSchema: unknown, label?: string): asserts jsonSchema is JSONSchema & {
537
+ type: 'object';
538
+ };
539
+ /**
540
+ * Escape SQL single quotes (generic utility).
541
+ */
542
+ protected _escapeString(str: string): string;
543
+ /**
544
+ * Detect the primary key column name in a schema (id / _id preferred).
545
+ */
546
+ protected _detectPrimaryKey(schema: JSONSchema): string | null;
547
+ }
548
+
549
+ /**
550
+ * MongoDBExporter — Export JSON Schema as a MongoDB $jsonSchema validation schema.
551
+ */
552
+
553
+ interface MongoDBExporterOptions extends ExporterOptions {
554
+ /** Whether to use strict mode (validationLevel: 'strict' vs 'moderate'). */
555
+ strict: boolean;
556
+ }
557
+ interface MongoDBValidationSchema {
558
+ $jsonSchema: Record<string, unknown>;
559
+ }
560
+ interface MongoDBCreateCommand {
561
+ collectionName: string;
562
+ options: {
563
+ validator: MongoDBValidationSchema;
564
+ validationLevel: 'strict' | 'moderate';
565
+ validationAction: 'error' | 'warn';
566
+ };
567
+ }
568
+ declare class MongoDBExporter extends BaseExporter<MongoDBExporterOptions> {
569
+ constructor(options?: Partial<MongoDBExporterOptions>);
570
+ /**
571
+ * Convert a JSON Schema to a MongoDB $jsonSchema validation schema.
572
+ */
573
+ export(jsonSchema: unknown): MongoDBValidationSchema;
574
+ /**
575
+ * Generate a db.createCollection() command object.
576
+ */
577
+ generateCreateCommand(collectionName: string, jsonSchema: JSONSchema): MongoDBCreateCommand;
578
+ /**
579
+ * Generate an executable MongoDB command string.
580
+ */
581
+ generateCommand(collectionName: string, jsonSchema: JSONSchema): string;
582
+ /**
583
+ * Static quick-export shorthand.
584
+ */
585
+ static export(jsonSchema: JSONSchema): MongoDBValidationSchema;
586
+ private _convertSchema;
587
+ }
588
+
589
+ /**
590
+ * MySQLExporter — Export JSON Schema as a MySQL CREATE TABLE DDL statement.
591
+ *
592
+ * v2 fixes:
593
+ * _escapeString uses standard SQL single-quote escaping (`'` → `''`)
594
+ * _convertColumn passes the full schema object to TypeConverter.toMySQLType (includes maxLength etc.)
595
+ */
596
+
597
+ interface MySQLExporterOptions extends ExporterOptions {
598
+ engine: string;
599
+ charset: string;
600
+ collate: string;
601
+ }
602
+ interface GenerateIndexOptions {
603
+ name?: string;
604
+ unique?: boolean;
605
+ }
606
+ declare class MySQLExporter extends BaseExporter<MySQLExporterOptions> {
607
+ constructor(options?: Partial<MySQLExporterOptions>);
608
+ /**
609
+ * Export as a MySQL CREATE TABLE statement.
610
+ */
611
+ export(tableName: string, jsonSchema: JSONSchema): string;
612
+ /**
613
+ * Generate a CREATE INDEX statement.
614
+ */
615
+ generateIndex(tableName: string, columnName: string, options?: GenerateIndexOptions): string;
616
+ /**
617
+ * Static quick-export shorthand.
618
+ */
619
+ static export(tableName: string, jsonSchema: JSONSchema): string;
620
+ private _quoteIdent;
621
+ private _convertProperties;
622
+ private _convertColumn;
623
+ private _resolveColumnType;
624
+ private _formatDefaultValue;
625
+ }
626
+
627
+ /**
628
+ * PostgreSQLExporter — Export JSON Schema as a PostgreSQL CREATE TABLE DDL statement.
629
+ *
630
+ * v2 fixes:
631
+ * Identifiers are escaped with double quotes (`"identifier"` format) instead of v1's unescaped raw identifiers.
632
+ * Column comments use the fully-qualified `"schema"."table"."column"` format.
633
+ */
634
+
635
+ interface PostgreSQLExporterOptions extends ExporterOptions {
636
+ /** PostgreSQL schema name (default: public). */
637
+ schema: string;
638
+ /** Whether to wrap identifiers in double quotes (default false — compatible with v1 behaviour). */
639
+ quoteIdentifiers?: boolean;
640
+ }
641
+ interface GeneratePgIndexOptions {
642
+ name?: string;
643
+ unique?: boolean;
644
+ method?: 'btree' | 'hash' | 'gin' | 'gist';
645
+ }
646
+ declare class PostgreSQLExporter extends BaseExporter<PostgreSQLExporterOptions> {
647
+ constructor(options?: Partial<PostgreSQLExporterOptions>);
648
+ /**
649
+ * Export as a PostgreSQL CREATE TABLE statement.
650
+ */
651
+ export(tableName: string, jsonSchema: JSONSchema): string;
652
+ /**
653
+ * Generate a CREATE INDEX statement.
654
+ */
655
+ generateIndex(tableName: string, columnName: string, options?: GeneratePgIndexOptions): string;
656
+ /**
657
+ * Static quick-export shorthand.
658
+ */
659
+ static export(tableName: string, jsonSchema: JSONSchema): string;
660
+ /** Conditionally wrap a PG identifier in double quotes (when quoteIdentifiers=true). */
661
+ private _quoteIdent;
662
+ private _convertProperties;
663
+ private _convertColumn;
664
+ private _resolveColumnType;
665
+ private _generateCheckConstraints;
666
+ private _formatDefaultValue;
667
+ private _generateColumnComments;
668
+ }
669
+
670
+ /**
671
+ * MarkdownExporter — Export JSON Schema as human-readable Markdown documentation.
672
+ *
673
+ * v2 fix:
674
+ * EX-01: required check prefers prop._required, then falls back to schema.required?.includes(key)
675
+ * (v1 already had this logic; v2 preserves it with stronger type safety)
676
+ *
677
+ * @version 2.0.0
678
+ */
679
+
680
+ interface MarkdownExporterOptions extends ExporterOptions {
681
+ title?: string;
682
+ locale?: 'zh-CN' | 'en-US' | 'ja-JP' | 'fr-FR' | 'es-ES';
683
+ includeExample?: boolean;
684
+ includeDescription?: boolean;
685
+ }
686
+ declare class MarkdownExporter extends BaseExporter<MarkdownExporterOptions> {
687
+ constructor(options?: Partial<MarkdownExporterOptions>);
688
+ /**
689
+ * Export as a Markdown document.
690
+ */
691
+ export(schema: JSONSchema, options?: Partial<MarkdownExporterOptions>): string;
692
+ /**
693
+ * Static method: export directly without instantiation.
694
+ */
695
+ static export(schema: JSONSchema, options?: Partial<MarkdownExporterOptions>): string;
696
+ private static _i18nFields;
697
+ private static _i18nTypes;
698
+ private static _i18nConstraints;
699
+ private static _i18nRules;
700
+ private static _generateFieldsTable;
701
+ private static _escapeTableCell;
702
+ private static _formatType;
703
+ private static _formatConstraints;
704
+ private static _getDescription;
705
+ private static _generateExample;
706
+ private static _buildExample;
707
+ private static _getExampleValue;
708
+ private static _generateConstraintsSection;
709
+ }
710
+
711
+ /**
712
+ * src/exporters/index.ts — Unified re-export for all exporters
713
+ */
714
+
715
+ type _exporters_BaseExporter<TOptions extends ExporterOptions = ExporterOptions> = BaseExporter<TOptions>;
716
+ declare const _exporters_BaseExporter: typeof BaseExporter;
717
+ type _exporters_ExporterOptions = ExporterOptions;
718
+ type _exporters_GenerateIndexOptions = GenerateIndexOptions;
719
+ type _exporters_GeneratePgIndexOptions = GeneratePgIndexOptions;
720
+ type _exporters_MarkdownExporter = MarkdownExporter;
721
+ declare const _exporters_MarkdownExporter: typeof MarkdownExporter;
722
+ type _exporters_MarkdownExporterOptions = MarkdownExporterOptions;
723
+ type _exporters_MongoDBCreateCommand = MongoDBCreateCommand;
724
+ type _exporters_MongoDBExporter = MongoDBExporter;
725
+ declare const _exporters_MongoDBExporter: typeof MongoDBExporter;
726
+ type _exporters_MongoDBExporterOptions = MongoDBExporterOptions;
727
+ type _exporters_MongoDBValidationSchema = MongoDBValidationSchema;
728
+ type _exporters_MySQLExporter = MySQLExporter;
729
+ declare const _exporters_MySQLExporter: typeof MySQLExporter;
730
+ type _exporters_MySQLExporterOptions = MySQLExporterOptions;
731
+ type _exporters_PostgreSQLExporter = PostgreSQLExporter;
732
+ declare const _exporters_PostgreSQLExporter: typeof PostgreSQLExporter;
733
+ type _exporters_PostgreSQLExporterOptions = PostgreSQLExporterOptions;
734
+ declare namespace _exporters {
735
+ export { _exporters_BaseExporter as BaseExporter, type _exporters_ExporterOptions as ExporterOptions, type _exporters_GenerateIndexOptions as GenerateIndexOptions, type _exporters_GeneratePgIndexOptions as GeneratePgIndexOptions, _exporters_MarkdownExporter as MarkdownExporter, type _exporters_MarkdownExporterOptions as MarkdownExporterOptions, type _exporters_MongoDBCreateCommand as MongoDBCreateCommand, _exporters_MongoDBExporter as MongoDBExporter, type _exporters_MongoDBExporterOptions as MongoDBExporterOptions, type _exporters_MongoDBValidationSchema as MongoDBValidationSchema, _exporters_MySQLExporter as MySQLExporter, type _exporters_MySQLExporterOptions as MySQLExporterOptions, _exporters_PostgreSQLExporter as PostgreSQLExporter, type _exporters_PostgreSQLExporterOptions as PostgreSQLExporterOptions };
736
+ }
737
+
738
+ /**
739
+ * TypeConverter — Schema type conversion utilities (static methods).
740
+ *
741
+ * Maps JSON Schema types to target-format types:
742
+ * - JSON Schema type
743
+ * - MongoDB BSON type
744
+ * - MySQL column type
745
+ * - PostgreSQL column type
746
+ *
747
+ * Also includes format helpers: normalizePropertyName, formatToRegex, mergeSchemas, extractConstraints.
748
+ */
749
+
750
+ type JSType = string | string[];
751
+ declare class TypeConverter {
752
+ static toJSONSchemaType(nativeType: string): string;
753
+ static toMongoDBType(jsonSchemaType: JSType): string;
754
+ static toMySQLType(jsonSchemaType: JSType, schema?: JSONSchema): string;
755
+ static toPostgreSQLType(jsonSchemaType: JSType, schema?: JSONSchema): string;
756
+ static normalizePropertyName(name: string): string;
757
+ static formatToRegex(format: string): RegExp | null;
758
+ static mergeSchemas(...schemas: JSONSchema[]): JSONSchema;
759
+ static extractConstraints(schema: JSONSchema): Record<string, unknown>;
760
+ }
761
+
762
+ /**
763
+ * SchemaHelper — Schema utility functions.
764
+ *
765
+ * Common helpers for JSON Schema structure manipulation:
766
+ * isValidSchema, generateSchemaId, cloneSchema, flattenSchema,
767
+ * getFieldPaths, extractRequiredFields, compareSchemas, simplifySchema,
768
+ * isValidPropertyName, getSchemaComplexity, summarizeSchema
769
+ */
770
+
771
+ declare class SchemaHelper {
772
+ /**
773
+ * Check whether the value is a valid JSON Schema (must contain at least one of: type / properties / items / $ref).
774
+ */
775
+ static isValidSchema(schema: unknown): schema is JSONSchema;
776
+ /**
777
+ * Generate a content-hash-based unique ID for a schema.
778
+ */
779
+ static generateSchemaId(schema: JSONSchema): string;
780
+ /**
781
+ * Deep-clone a schema via JSON serialisation (Function/RegExp fields are not preserved).
782
+ */
783
+ static cloneSchema(schema: JSONSchema): JSONSchema;
784
+ /**
785
+ * Flatten a nested schema into dot-separated path form.
786
+ * @param prefix - Property path prefix.
787
+ */
788
+ static flattenSchema(schema: JSONSchema, prefix?: string): Record<string, JSONSchema>;
789
+ /**
790
+ * Get all field paths in a schema (including nested object and array paths).
791
+ */
792
+ static getFieldPaths(schema: JSONSchema): string[];
793
+ /**
794
+ * Extract all required fields from a schema (including nested paths).
795
+ */
796
+ static extractRequiredFields(schema: JSONSchema): string[];
797
+ /**
798
+ * Shallow-compare two schemas for equality (via JSON serialisation).
799
+ */
800
+ static compareSchemas(schema1: JSONSchema, schema2: JSONSchema): boolean;
801
+ /**
802
+ * Simplify a schema by removing $schema, empty properties, and empty required arrays.
803
+ */
804
+ static simplifySchema(schema: JSONSchema): JSONSchema;
805
+ /**
806
+ * Validate that a property name is legal (letters/digits/underscores/hyphens; must start with a letter or underscore).
807
+ */
808
+ static isValidPropertyName(name: string): boolean;
809
+ /**
810
+ * Get the maximum nesting depth (complexity) of a schema.
811
+ */
812
+ static getSchemaComplexity(schema: JSONSchema): number;
813
+ /**
814
+ * Generate a summary of schema metadata.
815
+ */
816
+ static summarizeSchema(schema: JSONSchema): {
817
+ type: string;
818
+ fieldCount: number;
819
+ requiredCount: number;
820
+ complexity: number;
821
+ hasNested: boolean;
822
+ fields: string[];
823
+ };
824
+ }
825
+
826
+ /**
827
+ * SchemaUtils — Advanced schema operations (reuse, merge, extend, performance monitoring)
828
+ *
829
+ * v2 note: v1's extend/validateBatch used require('../adapters/DslAdapter'),
830
+ * v2 uses dynamic import or accepts pre-compiled schema directly (avoids circular deps)
831
+ */
832
+
833
+ interface ChainableSchema extends JSONSchema {
834
+ _isChainable: true;
835
+ partial(fields?: string[]): ChainableSchema;
836
+ pick(fields: string[]): ChainableSchema;
837
+ omit(fields: string[]): ChainableSchema;
838
+ extend(extensions: Record<string, unknown>): ChainableSchema;
839
+ }
840
+ declare class SchemaUtils {
841
+ /**
842
+ * Create a reusable schema factory.
843
+ * @example const emailField = SchemaUtils.reusable(() => dsl('email!').label('email'))
844
+ */
845
+ static reusable<T>(factory: () => T): () => T;
846
+ /**
847
+ * Create a schema fragment library.
848
+ * @example const fields = SchemaUtils.createLibrary({ email: () => dsl('email!') })
849
+ */
850
+ static createLibrary<T extends Record<string, () => unknown>>(fragments: T): T;
851
+ /**
852
+ * Extend a schema (like inheritance) — merges extension fields into the base schema.
853
+ */
854
+ static extend(baseSchema: JSONSchema, extensions: JSONSchema | Record<string, unknown>): ChainableSchema;
855
+ /**
856
+ * Pick a subset of fields from a schema.
857
+ */
858
+ static pick(schema: JSONSchema, fields: string[]): ChainableSchema;
859
+ /**
860
+ * Omit fields from a schema.
861
+ */
862
+ static omit(schema: JSONSchema, fields: string[]): ChainableSchema;
863
+ /**
864
+ * Make all fields optional (removes required).
865
+ * @param fields - optional; only process these fields (others remain unchanged)
866
+ */
867
+ static partial(schema: JSONSchema, fields?: string[] | null): ChainableSchema;
868
+ /**
869
+ * Wrap a Validator instance with performance monitoring.
870
+ */
871
+ static withPerformance<V extends {
872
+ validate: (...args: unknown[]) => unknown;
873
+ }>(validator: V): V;
874
+ /**
875
+ * Batch validate using a pre-compiled Ajv validate function.
876
+ */
877
+ static validateBatch(schema: JSONSchema, dataArray: unknown[], ajvInstance: {
878
+ compile: (schema: JSONSchema) => (data: unknown) => boolean;
879
+ } & {
880
+ errors?: unknown;
881
+ }): {
882
+ results: Array<{
883
+ index: number;
884
+ valid: boolean;
885
+ errors: unknown;
886
+ data: unknown;
887
+ }>;
888
+ summary: {
889
+ total: number;
890
+ valid: number;
891
+ invalid: number;
892
+ duration: number;
893
+ averageTime: number;
894
+ };
895
+ };
896
+ static toMarkdown(schema: JSONSchema, options?: {
897
+ title?: string;
898
+ }): string;
899
+ static clone(schema: JSONSchema): JSONSchema;
900
+ /**
901
+ * toHTML — v1 compat: export schema as HTML document
902
+ */
903
+ static toHTML(schema: JSONSchema, options?: {
904
+ title?: string;
905
+ }): string;
906
+ private static _mergeProperties;
907
+ private static _deleteRequired;
908
+ private static _clone;
909
+ private static _makeChainable;
910
+ private static _extractSchema;
911
+ }
912
+
913
+ /**
914
+ * CustomKeywords — AJV custom keyword registrar
915
+ *
916
+ * Fixes:
917
+ * CK-01: internally uses getMessageText() to obtain strings, avoiding v1 compat objects
918
+ * that serialized as "[object Object]"
919
+ * CK-02: regex keyword error messages use locale keys instead of concatenating raw messages
920
+ * CK-Y04: exactLength uses Unicode code-point counting ([...str].length) instead of
921
+ * str.length, correctly handling emoji and multi-byte characters
922
+ */
923
+ declare class CustomKeywords {
924
+ /**
925
+ * Register all custom keywords on an AJV instance
926
+ */
927
+ static registerAll(ajv: Ajv): void;
928
+ static registerMetadataKeywords(ajv: Ajv): void;
929
+ static registerCustomValidatorsKeyword(ajv: Ajv): void;
930
+ private static _isUnsafePattern;
931
+ static registerRegexKeyword(ajv: Ajv): void;
932
+ static registerFunctionKeyword(ajv: Ajv): void;
933
+ static registerStringValidators(ajv: Ajv): void;
934
+ static registerNumberValidators(ajv: Ajv): void;
935
+ static registerObjectValidators(ajv: Ajv): void;
936
+ private static _deepEqual;
937
+ static registerArrayValidators(ajv: Ajv): void;
938
+ static registerDateValidators(ajv: Ajv): void;
939
+ }
940
+
941
+ /**
942
+ * Global constants.
943
+ * Fixes:
944
+ * CF-01 IPv4 regex too permissive → replaced with RFC-compliant standard regex
945
+ * CF-02 IPv6 regex did not support compressed notation → replaced with full RFC 5952 compatible regex
946
+ */
947
+ declare const VALIDATION: {
948
+ readonly MAX_RECURSION_DEPTH: 100;
949
+ readonly MAX_ARRAY_SIZE: 100000;
950
+ readonly MAX_STRING_LENGTH: 1000000;
951
+ readonly MAX_OBJECT_KEYS: 10000;
952
+ readonly DEFAULT_TIMEOUT: 5000;
953
+ readonly REGEX_TIMEOUT: 100;
954
+ readonly CUSTOM_VALIDATOR_TIMEOUT: 1000;
955
+ };
956
+ declare const CACHE: {
957
+ readonly ENABLED: true;
958
+ readonly SCHEMA_CACHE: {
959
+ readonly MAX_SIZE: 5000;
960
+ readonly TTL: 3600000;
961
+ readonly STRATEGY: "LRU";
962
+ };
963
+ readonly STATS_ENABLED: true;
964
+ };
965
+ declare const PATTERN_IPV4: RegExp;
966
+ declare const PATTERN_IPV6: RegExp;
967
+ declare const FORMATS: {
968
+ readonly BUILT_IN: readonly ["email", "url", "uri", "uuid", "ipv4", "ipv6", "hostname", "date", "date-time", "time", "regex", "json"];
969
+ readonly PATTERNS: {
970
+ readonly email: RegExp;
971
+ readonly uuid: RegExp;
972
+ readonly ipv4: RegExp;
973
+ readonly ipv6: RegExp;
974
+ readonly hostname: RegExp;
975
+ readonly dateTime: RegExp;
976
+ readonly date: RegExp;
977
+ readonly time: RegExp;
978
+ };
979
+ };
980
+ declare const PLUGINS: {
981
+ readonly MAX_PLUGINS: 50;
982
+ readonly NAMING_CONVENTION: RegExp;
983
+ };
984
+
985
+ declare const _CONSTANTS_CACHE: typeof CACHE;
986
+ declare const _CONSTANTS_FORMATS: typeof FORMATS;
987
+ declare const _CONSTANTS_PATTERN_IPV4: typeof PATTERN_IPV4;
988
+ declare const _CONSTANTS_PATTERN_IPV6: typeof PATTERN_IPV6;
989
+ declare const _CONSTANTS_PLUGINS: typeof PLUGINS;
990
+ declare const _CONSTANTS_VALIDATION: typeof VALIDATION;
991
+ declare namespace _CONSTANTS {
992
+ export { _CONSTANTS_CACHE as CACHE, _CONSTANTS_FORMATS as FORMATS, _CONSTANTS_PATTERN_IPV4 as PATTERN_IPV4, _CONSTANTS_PATTERN_IPV6 as PATTERN_IPV6, _CONSTANTS_PLUGINS as PLUGINS, _CONSTANTS_VALIDATION as VALIDATION };
993
+ }
994
+
995
+ /**
996
+ * Error code constants.
997
+ * Defines all built-in error codes used by ErrorFormatter and Locale.
998
+ */
999
+ declare const ErrorCodes: ErrorCodeMap;
1000
+
1001
+ /**
1002
+ * Built-in regex validation patterns (migrated from v1 lib/config/patterns/ to a single TypeScript file)
1003
+ */
1004
+ interface PatternConfig {
1005
+ pattern: RegExp;
1006
+ min?: number;
1007
+ max?: number;
1008
+ key: string;
1009
+ }
1010
+ declare const PATTERNS: {
1011
+ phone: Record<string, PatternConfig>;
1012
+ idCard: Record<string, PatternConfig>;
1013
+ creditCard: Record<string, PatternConfig>;
1014
+ licensePlate: Record<string, PatternConfig>;
1015
+ postalCode: Record<string, PatternConfig>;
1016
+ passport: Record<string, PatternConfig>;
1017
+ common: Record<string, PatternConfig>;
1018
+ };
1019
+
1020
+ type StripMarker<S extends string> = S extends `${infer Base}!` | `${infer Base}?` ? Base : S;
1021
+ type KnownDslType = 'string' | 'email' | 'url' | 'uri' | 'uuid' | 'ipv4' | 'ipv6' | 'ip' | 'hostname' | 'date' | 'datetime' | 'time' | 'binary' | 'objectId' | 'hexColor' | 'macAddress' | 'cron' | 'slug' | 'chineseName' | 'chinese' | 'emailDomain' | 'alphanum' | 'lower' | 'upper' | 'json' | 'port' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null' | 'any';
1022
+ type InferPipeMember<S extends string> = StripMarker<S> extends KnownDslType ? InferDslString<S> : StripMarker<S>;
1023
+ type SplitPipe<S extends string> = S extends `${infer Head}|${infer Tail}` ? InferPipeMember<Head> | SplitPipe<Tail> : InferPipeMember<S>;
1024
+ type RequiredDslKeys<T extends Record<string, unknown>> = {
1025
+ [K in keyof T]: K extends string ? K extends `${infer Name}!` ? Name : T[K] extends `${string}!` ? K : never : never;
1026
+ }[keyof T];
1027
+ type CleanDslKey<K> = K extends `${infer Name}!` | `${infer Name}?` ? Name : K;
1028
+ type InferJsonSchemaProperties<Properties, RequiredKeys extends PropertyKey> = {
1029
+ [K in keyof Properties as K extends RequiredKeys ? K : never]-?: InferSchema<Properties[K]>;
1030
+ } & {
1031
+ [K in keyof Properties as K extends RequiredKeys ? never : K]?: InferSchema<Properties[K]>;
1032
+ };
1033
+ type InferDslProperties<T extends Record<string, unknown>, RequiredKeys extends PropertyKey = RequiredDslKeys<T>> = {
1034
+ [K in keyof T as CleanDslKey<K> extends RequiredKeys ? CleanDslKey<K> : never]-?: InferSchema<T[K]>;
1035
+ } & {
1036
+ [K in keyof T as CleanDslKey<K> extends RequiredKeys ? never : CleanDslKey<K>]?: InferSchema<T[K]>;
1037
+ };
1038
+ type InferDslString<T extends string> = StripMarker<T> extends `types:${infer Rest}` ? SplitPipe<Rest> : StripMarker<T> extends `enum:${infer Values}` ? SplitPipe<Values> : StripMarker<T> extends `array<${infer Item}>` ? InferDslString<Item>[] : StripMarker<T> extends `${infer Base}:${string}` ? InferDslString<Base> : StripMarker<T> extends 'number' | 'integer' | 'port' ? number : StripMarker<T> extends 'boolean' ? boolean : StripMarker<T> extends 'object' ? Record<string, unknown> : StripMarker<T> extends 'array' ? unknown[] : StripMarker<T> extends 'null' ? null : StripMarker<T> extends 'any' ? unknown : StripMarker<T> extends `${string}|${string}` ? SplitPipe<StripMarker<T>> : string;
1039
+ type InferJsonSchema<T> = T extends {
1040
+ oneOf: readonly (infer Variant)[];
1041
+ } ? InferSchema<Variant> : T extends {
1042
+ anyOf: readonly (infer Variant)[];
1043
+ } ? InferSchema<Variant> : T extends {
1044
+ enum: readonly (infer Value)[];
1045
+ } ? Value : T extends {
1046
+ type: 'object';
1047
+ properties: infer Properties;
1048
+ required?: readonly (infer RequiredKey)[];
1049
+ } ? InferJsonSchemaProperties<Properties, Extract<RequiredKey, keyof Properties>> : T extends {
1050
+ type: 'array';
1051
+ items: infer Item;
1052
+ } ? InferSchema<Item>[] : T extends {
1053
+ type: 'number' | 'integer';
1054
+ } ? number : T extends {
1055
+ type: 'boolean';
1056
+ } ? boolean : T extends {
1057
+ type: 'null';
1058
+ } ? null : T extends {
1059
+ type: 'object';
1060
+ } ? Record<string, unknown> : T extends {
1061
+ type: 'array';
1062
+ } ? unknown[] : T extends {
1063
+ type: 'string';
1064
+ } ? string : unknown;
1065
+ type InferDslDefinition<T extends Record<string, unknown>> = InferDslProperties<T>;
1066
+ type InferSchema<T> = T extends string ? InferDslString<T> : T extends {
1067
+ type: unknown;
1068
+ } | {
1069
+ properties: unknown;
1070
+ } | {
1071
+ oneOf: unknown;
1072
+ } | {
1073
+ anyOf: unknown;
1074
+ } | {
1075
+ enum: unknown;
1076
+ } ? InferJsonSchema<T> : T extends Record<string, unknown> ? InferDslDefinition<T> : unknown;
1077
+
1078
+ /**
1079
+ * schema-dsl v2 — main entry point
1080
+ *
1081
+ * Fix IX-01: VERSION is read dynamically from package.json instead of being hard-coded
1082
+ *
1083
+ * @module schema-dsl
1084
+ * @version 2.0.0
1085
+ */
1086
+ declare const VERSION: string;
1087
+
1088
+ declare const CONSTANTS: typeof _CONSTANTS;
1089
+ declare const exporters: typeof _exporters;
1090
+ declare function _dslConfig(options?: Partial<DslConfigOptions>): void;
1091
+ declare function _getDefaultValidator(): InstanceType<typeof Validator>;
1092
+
1093
+ /**
1094
+ * Reset the default Validator singleton (useful for cleaning up state in test environments)
1095
+ */
1096
+ declare function resetDefaultValidator(): void;
1097
+ /**
1098
+ * Reset global runtime state that may leak across tests, workers, or tenants.
1099
+ */
1100
+ declare function resetRuntimeState(): void;
1101
+ /**
1102
+ * Convenience validate function (uses the default Validator singleton).
1103
+ * Automatically coerces string → number when options.coerce !== false.
1104
+ */
1105
+ declare function validate<T = unknown>(schema: JSONSchema | DslDefinition | IDslBuilder | IConditionalBuilder, data: T, options?: Record<string, unknown>): ValidationResult<T>;
1106
+ /**
1107
+ * Convenience async validate function
1108
+ */
1109
+ declare function validateAsync<T = unknown>(schema: JSONSchema | DslDefinition | IDslBuilder | IConditionalBuilder, data: T, options?: Record<string, unknown>): Promise<T>;
1110
+ /**
1111
+ * dsl — main API entry point
1112
+ *
1113
+ * @example
1114
+ * // String DSL → DslBuilder (chainable)
1115
+ * const builder = dsl('email!').label('Email address')
1116
+ *
1117
+ * @example
1118
+ * // Object DSL → JSON Schema
1119
+ * const schema = dsl({ email: 'email!', name: 'string:2-32!' })
1120
+ */
1121
+ declare const dsl: {
1122
+ (def: string): IDslBuilder;
1123
+ (def: DslDefinition): JSONSchema;
1124
+ config: (options?: Partial<DslConfigOptions>) => void;
1125
+ if: {
1126
+ (condition: string, thenSchema: unknown, elseSchema?: unknown): DslConditionMarker;
1127
+ (condition: (data: unknown) => boolean): ReturnType<typeof ConditionalBuilder.start>;
1128
+ };
1129
+ _if: {
1130
+ (condition: string, thenSchema: unknown, elseSchema?: unknown): DslConditionMarker;
1131
+ (condition: (data: unknown) => boolean): ReturnType<typeof ConditionalBuilder.start>;
1132
+ };
1133
+ match: (value: unknown, cases: Record<string, unknown>) => DslConditionMarker;
1134
+ error: {
1135
+ create: typeof I18nError.create;
1136
+ throw: typeof I18nError.throw;
1137
+ assert: typeof I18nError.assert;
1138
+ [key: string]: unknown;
1139
+ };
1140
+ };
1141
+
1142
+ declare const config: typeof _dslConfig;
1143
+ declare function installStringExtensions(dslFunction?: Parameters<typeof installStringExtensions$1>[0]): void;
1144
+
1145
+ export { BaseExporter, CACHE, CONSTANTS, ConditionalBuilder, CustomKeywords, DslBuilder, DslConditionMarker, DslConfigOptions, DslDefinition, ErrorCodes, ErrorFormatter, type ExporterOptions, FORMATS, I18nError, IConditionalBuilder, IDslBuilder, type InferDslDefinition, type InferDslString, type InferJsonSchema, type InferSchema, JSONSchema, JSONSchemaCore, Locale, MarkdownExporter, type MarkdownExporterOptions, MessageTemplate, MongoDBExporter, type MongoDBExporterOptions, MySQLExporter, type MySQLExporterOptions, ObjectDslBuilder, PATTERNS, PATTERN_IPV4, PATTERN_IPV6, PluginManager, PostgreSQLExporter, type PostgreSQLExporterOptions, SchemaHelper, SchemaUtils, TypeConverter, TypeRegistry, VALIDATION, VERSION, ValidationError, ValidationErrorItem, ValidationResult, Validator, config, dsl as default, dsl, exporters, _getDefaultValidator as getDefaultValidator, installStringExtensions, renderTemplate, resetDefaultValidator, resetRuntimeState, uninstallStringExtensions, validate, validateAsync };