schema-dsl 2.0.0 → 2.0.1

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 (145) hide show
  1. package/CHANGELOG.md +130 -113
  2. package/LICENSE +21 -21
  3. package/README.md +628 -628
  4. package/dist/{DslBuilder-DkLaOo9Q.d.ts → DslBuilder-BIgQOAXp.d.ts} +2 -0
  5. package/dist/{DslBuilder-DQDN0ZxZ.d.cts → DslBuilder-CjHTucNQ.d.cts} +2 -0
  6. package/dist/{Validator-hFWKGxir.d.ts → Validator-CllRdrY0.d.ts} +1 -1
  7. package/dist/{Validator-C7GsVQOH.d.cts → Validator-D6okG9tr.d.cts} +1 -1
  8. package/dist/index.cjs +75 -29
  9. package/dist/index.d.cts +10 -4
  10. package/dist/index.d.ts +10 -4
  11. package/dist/index.js +75 -29
  12. package/dist/plugins/custom-format.cjs +33 -17
  13. package/dist/plugins/custom-format.d.cts +1 -1
  14. package/dist/plugins/custom-format.d.ts +1 -1
  15. package/dist/plugins/custom-format.js +33 -17
  16. package/dist/plugins/custom-type-example.cjs +33 -17
  17. package/dist/plugins/custom-type-example.d.cts +1 -1
  18. package/dist/plugins/custom-type-example.d.ts +1 -1
  19. package/dist/plugins/custom-type-example.js +33 -17
  20. package/dist/plugins/custom-validator.cjs +0 -2
  21. package/dist/plugins/custom-validator.d.cts +1 -1
  22. package/dist/plugins/custom-validator.d.ts +1 -1
  23. package/dist/plugins/custom-validator.js +0 -2
  24. package/docs/FEATURE-INDEX.md +553 -553
  25. package/docs/add-custom-locale.md +496 -496
  26. package/docs/add-keyword.md +24 -24
  27. package/docs/api-reference.md +1047 -1047
  28. package/docs/api.md +13 -13
  29. package/docs/best-practices-project-structure.md +417 -417
  30. package/docs/best-practices.md +712 -712
  31. package/docs/cache-manager.md +344 -344
  32. package/docs/compile.md +45 -45
  33. package/docs/conditional-api.md +1307 -1307
  34. package/docs/custom-extensions-guide.md +339 -339
  35. package/docs/design-philosophy.md +606 -606
  36. package/docs/doc-index.md +324 -324
  37. package/docs/dsl-syntax.md +714 -714
  38. package/docs/dynamic-locale.md +608 -608
  39. package/docs/enum.md +482 -482
  40. package/docs/error-handling.md +1975 -1975
  41. package/docs/export-guide.md +501 -501
  42. package/docs/export-limitations.md +567 -567
  43. package/docs/faq.md +596 -596
  44. package/docs/frontend-i18n-guide.md +307 -307
  45. package/docs/i18n-user-guide.md +487 -487
  46. package/docs/i18n.md +476 -476
  47. package/docs/index.md +48 -48
  48. package/docs/json-schema-basics.md +40 -40
  49. package/docs/label-vs-description.md +271 -271
  50. package/docs/markdown-exporter.md +406 -406
  51. package/docs/mongodb-exporter.md +302 -302
  52. package/docs/multi-language.md +26 -26
  53. package/docs/multi-type-support.md +322 -322
  54. package/docs/mysql-exporter.md +280 -280
  55. package/docs/number-operators.md +449 -449
  56. package/docs/optional-marker-guide.md +326 -326
  57. package/docs/performance-guide.md +49 -49
  58. package/docs/plugin-system.md +381 -381
  59. package/docs/plugin-type-registration.md +34 -34
  60. package/docs/postgresql-exporter.md +311 -311
  61. package/docs/public/favicon.svg +4 -4
  62. package/docs/quick-start.md +435 -435
  63. package/docs/runtime-locale-support.md +532 -532
  64. package/docs/schema-helper.md +345 -345
  65. package/docs/schema-utils-advanced-issues.md +23 -23
  66. package/docs/schema-utils-best-practices.md +20 -20
  67. package/docs/schema-utils-chaining.md +150 -150
  68. package/docs/schema-utils.md +524 -524
  69. package/docs/security-checklist.md +20 -20
  70. package/docs/string-extensions.md +488 -488
  71. package/docs/troubleshooting.md +486 -486
  72. package/docs/type-converter.md +310 -310
  73. package/docs/type-reference.md +242 -242
  74. package/docs/typescript-guide.md +584 -584
  75. package/docs/union-type-guide.md +157 -157
  76. package/docs/union-types.md +284 -284
  77. package/docs/validate-async.md +491 -491
  78. package/docs/validate-batch.md +49 -49
  79. package/docs/validate-dsl-object-support.md +578 -578
  80. package/docs/validate.md +506 -506
  81. package/docs/validation-guide.md +502 -502
  82. package/docs/validator.md +39 -39
  83. package/package.json +131 -131
  84. package/plugins/custom-format.cjs +8 -8
  85. package/plugins/custom-type-example.cjs +8 -8
  86. package/plugins/custom-validator.cjs +8 -8
  87. package/src/adapters/DslAdapter.ts +111 -111
  88. package/src/adapters/index.ts +1 -1
  89. package/src/config/constants.ts +83 -83
  90. package/src/config/index.ts +2 -2
  91. package/src/config/patterns.ts +77 -77
  92. package/src/core/CacheManager.ts +169 -159
  93. package/src/core/ConditionalBuilder.ts +382 -382
  94. package/src/core/ConditionalRuntime.ts +27 -27
  95. package/src/core/ConditionalValidator.ts +254 -254
  96. package/src/core/DslBuilder.ts +687 -677
  97. package/src/core/ErrorCodes.ts +38 -38
  98. package/src/core/ErrorFormatter.ts +271 -271
  99. package/src/core/JSONSchemaCore.ts +65 -65
  100. package/src/core/Locale.ts +187 -187
  101. package/src/core/MessageTemplate.ts +42 -42
  102. package/src/core/ObjectDslBuilder.ts +64 -64
  103. package/src/core/PluginManager.ts +326 -326
  104. package/src/core/StringExtensions.ts +140 -140
  105. package/src/core/TemplateEngine.ts +44 -44
  106. package/src/core/Validator.ts +448 -448
  107. package/src/errors/I18nError.ts +159 -159
  108. package/src/errors/ValidationError.ts +105 -105
  109. package/src/exporters/BaseExporter.ts +60 -60
  110. package/src/exporters/MarkdownExporter.ts +305 -305
  111. package/src/exporters/MongoDBExporter.ts +126 -126
  112. package/src/exporters/MySQLExporter.ts +156 -155
  113. package/src/exporters/PostgreSQLExporter.ts +222 -222
  114. package/src/exporters/index.ts +18 -18
  115. package/src/index.ts +651 -633
  116. package/src/locales/en-US.ts +160 -160
  117. package/src/locales/es-ES.ts +160 -160
  118. package/src/locales/fr-FR.ts +160 -160
  119. package/src/locales/index.ts +103 -103
  120. package/src/locales/ja-JP.ts +160 -160
  121. package/src/locales/types.ts +156 -156
  122. package/src/locales/zh-CN.ts +160 -160
  123. package/src/parser/ConstraintParser.ts +101 -101
  124. package/src/parser/DslParser.ts +470 -470
  125. package/src/parser/SchemaCompiler.ts +66 -66
  126. package/src/parser/TypeRegistry.ts +250 -250
  127. package/src/parser/index.ts +6 -6
  128. package/src/plugins/custom-format.ts +124 -126
  129. package/src/plugins/custom-type-example.ts +106 -108
  130. package/src/plugins/custom-validator.ts +138 -140
  131. package/src/types/conditional.ts +28 -28
  132. package/src/types/config.ts +59 -59
  133. package/src/types/dsl.ts +131 -131
  134. package/src/types/error.ts +60 -60
  135. package/src/types/index.ts +17 -17
  136. package/src/types/infer.ts +127 -127
  137. package/src/types/plugin.ts +58 -58
  138. package/src/types/safe-regex.d.ts +9 -9
  139. package/src/types/schema.ts +66 -66
  140. package/src/types/validate.ts +71 -71
  141. package/src/utils/SchemaHelper.ts +196 -196
  142. package/src/utils/SchemaUtils.ts +365 -346
  143. package/src/utils/TypeConverter.ts +215 -215
  144. package/src/utils/index.ts +10 -10
  145. package/src/validators/CustomKeywords.ts +477 -477
@@ -205,6 +205,8 @@ declare class DslBuilder implements IDslBuilder {
205
205
  * Add regex validation.
206
206
  */
207
207
  pattern(regex: RegExp | string, message?: string): this;
208
+ /** Internal: set pattern without safe-regex check (used by built-in validators with pre-approved patterns). */
209
+ private _setPattern;
208
210
  /**
209
211
  * Custom error messages (IDslBuilder: error; BC alias: messages).
210
212
  */
@@ -205,6 +205,8 @@ declare class DslBuilder implements IDslBuilder {
205
205
  * Add regex validation.
206
206
  */
207
207
  pattern(regex: RegExp | string, message?: string): this;
208
+ /** Internal: set pattern without safe-regex check (used by built-in validators with pre-approved patterns). */
209
+ private _setPattern;
208
210
  /**
209
211
  * Custom error messages (IDslBuilder: error; BC alias: messages).
210
212
  */
@@ -32,7 +32,7 @@ declare class CacheManager {
32
32
  private _enabled;
33
33
  private _maxSize;
34
34
  private _ttl;
35
- private readonly _cache;
35
+ private _cache;
36
36
  private _statsEnabled;
37
37
  private _clears;
38
38
  constructor(options?: {
@@ -32,7 +32,7 @@ declare class CacheManager {
32
32
  private _enabled;
33
33
  private _maxSize;
34
34
  private _ttl;
35
- private readonly _cache;
35
+ private _cache;
36
36
  private _statsEnabled;
37
37
  private _clears;
38
38
  constructor(options?: {
package/dist/index.cjs CHANGED
@@ -146,7 +146,16 @@ var init_CacheManager = __esm({
146
146
  };
147
147
  }
148
148
  set options(opts) {
149
- if (opts.maxSize !== void 0) this._maxSize = opts.maxSize;
149
+ if (opts.maxSize !== void 0 && opts.maxSize !== this._maxSize) {
150
+ this._maxSize = opts.maxSize;
151
+ const oldKeys = this._cache.keys();
152
+ const newCache = new import_cache_hub.MemoryCache({ maxEntries: this._maxSize });
153
+ for (const key of oldKeys) {
154
+ const val = this._cache.get(key);
155
+ if (val !== void 0) newCache.set(key, val);
156
+ }
157
+ this._cache = newCache;
158
+ }
150
159
  if (opts.ttl !== void 0) this._ttl = opts.ttl;
151
160
  if (opts.enabled !== void 0) this._enabled = opts.enabled;
152
161
  if (opts.statsEnabled !== void 0) this._statsEnabled = opts.statsEnabled;
@@ -3280,7 +3289,7 @@ module.exports = __toCommonJS(src_exports);
3280
3289
  // package.json
3281
3290
  var package_default = {
3282
3291
  name: "schema-dsl",
3283
- version: "2.0.0",
3292
+ version: "2.0.1",
3284
3293
  description: "A concise and powerful JSON Schema validation library - DSL syntax + String extensions + convenient validate API",
3285
3294
  main: "./dist/index.cjs",
3286
3295
  module: "./dist/index.js",
@@ -3464,6 +3473,7 @@ var JSONSchemaCore = class {
3464
3473
  init_DslParser();
3465
3474
  init_TypeRegistry();
3466
3475
  init_patterns();
3476
+ var import_safe_regex2 = __toESM(require("safe-regex"), 1);
3467
3477
  var PASSWORD_PATTERNS = {
3468
3478
  weak: /.{6,}/,
3469
3479
  medium: /^(?=.*[a-zA-Z])(?=.*\d).{8,}$/,
@@ -3622,7 +3632,15 @@ var DslBuilder = class _DslBuilder {
3622
3632
  * Add regex validation.
3623
3633
  */
3624
3634
  pattern(regex, message) {
3625
- this._baseSchema.pattern = regex instanceof RegExp ? regex.source : regex;
3635
+ const source = regex instanceof RegExp ? regex.source : regex;
3636
+ if (!(0, import_safe_regex2.default)(source)) {
3637
+ throw new Error(`[schema-dsl] Unsafe regex pattern rejected (potential ReDoS): ${source}`);
3638
+ }
3639
+ return this._setPattern(source, message);
3640
+ }
3641
+ /** Internal: set pattern without safe-regex check (used by built-in validators with pre-approved patterns). */
3642
+ _setPattern(source, message) {
3643
+ this._baseSchema.pattern = source;
3626
3644
  if (message) {
3627
3645
  this._customMessages["string.pattern"] = message;
3628
3646
  }
@@ -3784,25 +3802,25 @@ var DslBuilder = class _DslBuilder {
3784
3802
  domain() {
3785
3803
  this._assertStringType("domain");
3786
3804
  const cfg = PATTERNS.common.domain;
3787
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3805
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3788
3806
  }
3789
3807
  /** String IP address validation (IPv4 or IPv6). */
3790
3808
  ip() {
3791
3809
  this._assertStringType("ip");
3792
3810
  const cfg = PATTERNS.common.ip;
3793
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3811
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3794
3812
  }
3795
3813
  /** String Base64 encoding validation. */
3796
3814
  base64() {
3797
3815
  this._assertStringType("base64");
3798
3816
  const cfg = PATTERNS.common.base64;
3799
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3817
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3800
3818
  }
3801
3819
  /** String JWT token validation. */
3802
3820
  jwt() {
3803
3821
  this._assertStringType("jwt");
3804
3822
  const cfg = PATTERNS.common.jwt;
3805
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3823
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3806
3824
  }
3807
3825
  // ==================== Identity / Pattern Chain Methods ====================
3808
3826
  /** Phone number validation (auto-corrects number → string). */
@@ -3816,7 +3834,7 @@ var DslBuilder = class _DslBuilder {
3816
3834
  if (!cfg) throw new Error(`[schema-dsl] Unsupported country: ${country}`);
3817
3835
  if (cfg.min !== void 0 && !this._baseSchema.minLength) this._baseSchema.minLength = cfg.min;
3818
3836
  if (cfg.max !== void 0 && !this._baseSchema.maxLength) this._baseSchema.maxLength = cfg.max;
3819
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3837
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3820
3838
  }
3821
3839
  /** phone() alias (BC). */
3822
3840
  phoneNumber(country = "cn") {
@@ -3829,35 +3847,35 @@ var DslBuilder = class _DslBuilder {
3829
3847
  if (!cfg) throw new Error(`[schema-dsl] Unsupported country for idCard: ${country}`);
3830
3848
  if (cfg.min !== void 0 && !this._baseSchema.minLength) this._baseSchema.minLength = cfg.min;
3831
3849
  if (cfg.max !== void 0 && !this._baseSchema.maxLength) this._baseSchema.maxLength = cfg.max;
3832
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3850
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3833
3851
  }
3834
3852
  /** URL slug validation. */
3835
3853
  slugChain() {
3836
- return this.pattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).messages({ pattern: "pattern.slug" });
3854
+ return this._setPattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/.source).messages({ pattern: "pattern.slug" });
3837
3855
  }
3838
3856
  /** Credit card number validation. */
3839
3857
  creditCard(type = "visa") {
3840
3858
  const cfg = PATTERNS.creditCard[type.toLowerCase()];
3841
3859
  if (!cfg) throw new Error(`[schema-dsl] Unsupported credit card type: ${type}`);
3842
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3860
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3843
3861
  }
3844
3862
  /** Vehicle license plate validation. */
3845
3863
  licensePlate(country = "cn") {
3846
3864
  const cfg = PATTERNS.licensePlate[country.toLowerCase()];
3847
3865
  if (!cfg) throw new Error(`[schema-dsl] Unsupported country for licensePlate: ${country}`);
3848
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3866
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3849
3867
  }
3850
3868
  /** Postal code validation. */
3851
3869
  postalCode(country = "cn") {
3852
3870
  const cfg = PATTERNS.postalCode[country.toLowerCase()];
3853
3871
  if (!cfg) throw new Error(`[schema-dsl] Unsupported country for postalCode: ${country}`);
3854
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3872
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3855
3873
  }
3856
3874
  /** Passport number validation. */
3857
3875
  passport(country = "cn") {
3858
3876
  const cfg = PATTERNS.passport[country.toLowerCase()];
3859
3877
  if (!cfg) throw new Error(`[schema-dsl] Unsupported country for passport: ${country}`);
3860
- return this.pattern(cfg.pattern).messages({ pattern: cfg.key });
3878
+ return this._setPattern(cfg.pattern.source).messages({ pattern: cfg.key });
3861
3879
  }
3862
3880
  /**
3863
3881
  * Username validation.
@@ -3899,7 +3917,7 @@ var DslBuilder = class _DslBuilder {
3899
3917
  } else {
3900
3918
  pat += "[a-zA-Z]*$";
3901
3919
  }
3902
- return this.pattern(new RegExp(pat)).messages({ pattern: "pattern.username" });
3920
+ return this._setPattern(pat).messages({ pattern: "pattern.username" });
3903
3921
  }
3904
3922
  /**
3905
3923
  * Password strength validation.
@@ -3910,7 +3928,7 @@ var DslBuilder = class _DslBuilder {
3910
3928
  if (!pat) throw new Error(`[schema-dsl] Invalid password strength: ${strength}`);
3911
3929
  if (!this._baseSchema.minLength) this._baseSchema.minLength = PASSWORD_MIN_LENGTHS[strength];
3912
3930
  if (!this._baseSchema.maxLength) this._baseSchema.maxLength = 64;
3913
- return this.pattern(pat).messages({ pattern: `pattern.password.${strength}` });
3931
+ return this._setPattern(pat.source).messages({ pattern: `pattern.password.${strength}` });
3914
3932
  }
3915
3933
  // ==================== Number Chain Methods ====================
3916
3934
  /** Number decimal places limit. */
@@ -5001,7 +5019,7 @@ var TypeConverter = class {
5001
5019
  case "array":
5002
5020
  return "JSON";
5003
5021
  case "null":
5004
- return "NULL";
5022
+ return "TEXT";
5005
5023
  default:
5006
5024
  return "VARCHAR(255)";
5007
5025
  }
@@ -5029,7 +5047,7 @@ var TypeConverter = class {
5029
5047
  case "array":
5030
5048
  return "JSONB";
5031
5049
  case "null":
5032
- return "NULL";
5050
+ return "TEXT";
5033
5051
  default:
5034
5052
  return "TEXT";
5035
5053
  }
@@ -5283,6 +5301,7 @@ var MySQLExporter = class _MySQLExporter extends BaseExporter {
5283
5301
  if (value === null) return "NULL";
5284
5302
  if (type === "string") return `'${this._escapeString(String(value))}'`;
5285
5303
  if (type === "boolean") return value ? "1" : "0";
5304
+ if (typeof value === "object" && value !== null) return `'${this._escapeString(JSON.stringify(value))}'`;
5286
5305
  return String(value);
5287
5306
  }
5288
5307
  };
@@ -5428,7 +5447,7 @@ COMMENT ON TABLE ${fullTableName} IS '${this._escapeString(jsonSchema.descriptio
5428
5447
  if (value === null) return "NULL";
5429
5448
  if (type === "string") return `'${this._escapeString(String(value))}'`;
5430
5449
  if (type === "boolean") return value ? "TRUE" : "FALSE";
5431
- if (type === "object" || type === "array") return `'${JSON.stringify(value)}'::JSONB`;
5450
+ if (type === "object" || type === "array") return `'${this._escapeString(JSON.stringify(value))}'::JSONB`;
5432
5451
  return String(value);
5433
5452
  }
5434
5453
  _generateColumnComments(_fullTableName, tableName, schema) {
@@ -6052,6 +6071,10 @@ var SchemaUtils = class _SchemaUtils {
6052
6071
  }
6053
6072
  /**
6054
6073
  * Batch validate using a pre-compiled Ajv validate function.
6074
+ *
6075
+ * Note: the schema is compiled once per call but not cached between calls.
6076
+ * For repeated batch validation of the same schema, prefer `Validator.validateBatch()`
6077
+ * which benefits from the built-in compile cache and returns typed `ValidationResult[]`.
6055
6078
  */
6056
6079
  static validateBatch(schema, dataArray, ajvInstance) {
6057
6080
  const startTime = Date.now();
@@ -6089,20 +6112,21 @@ var SchemaUtils = class _SchemaUtils {
6089
6112
  md += "|-------|------|----------|-------------|\n";
6090
6113
  for (const [key, prop] of Object.entries(schema.properties)) {
6091
6114
  const required = schema.required?.includes(key) ? "\u2705" : "\u274C";
6092
- const type = prop.type ?? "any";
6115
+ const type = _SchemaUtils._escapeMdCell(prop.type ?? "any");
6093
6116
  const p = prop;
6094
- const label = p["_label"] ?? key;
6095
- md += `| ${key} | ${type} | ${required} | ${label} |
6117
+ const label = _SchemaUtils._escapeMdCell(p["_label"] ?? key);
6118
+ const escapedKey = _SchemaUtils._escapeMdCell(key);
6119
+ md += `| ${escapedKey} | ${type} | ${required} | ${label} |
6096
6120
  `;
6097
6121
  const constraints = [];
6098
6122
  if (prop.minLength) constraints.push(`minLength: ${prop.minLength}`);
6099
6123
  if (prop.maxLength) constraints.push(`maxLength: ${prop.maxLength}`);
6100
6124
  if (prop.minimum !== void 0) constraints.push(`minimum: ${prop.minimum}`);
6101
6125
  if (prop.maximum !== void 0) constraints.push(`maximum: ${prop.maximum}`);
6102
- if (prop.pattern) constraints.push(`pattern: \`${prop.pattern}\``);
6126
+ if (prop.pattern) constraints.push(`pattern: \`${_SchemaUtils._escapeMdCell(String(prop.pattern))}\``);
6103
6127
  if (prop.enum) constraints.push(`enum: ${prop.enum.join(", ")}`);
6104
6128
  if (constraints.length > 0) {
6105
- md += `| | | | ${constraints.join("; ")} |
6129
+ md += `| | | | ${_SchemaUtils._escapeMdCell(constraints.join("; "))} |
6106
6130
  `;
6107
6131
  }
6108
6132
  }
@@ -6117,21 +6141,22 @@ var SchemaUtils = class _SchemaUtils {
6117
6141
  */
6118
6142
  static toHTML(schema, options = {}) {
6119
6143
  const { title = "Schema Documentation" } = options;
6144
+ const safeTitle = _SchemaUtils._escapeHtml(title);
6120
6145
  let html = `<!DOCTYPE html>
6121
6146
  <html>
6122
- <head><meta charset="utf-8"><title>${title}</title></head>
6147
+ <head><meta charset="utf-8"><title>${safeTitle}</title></head>
6123
6148
  <body>
6124
- <h1>${title}</h1>
6149
+ <h1>${safeTitle}</h1>
6125
6150
  `;
6126
6151
  if (schema.properties) {
6127
6152
  html += '<table border="1" cellpadding="4">\n';
6128
6153
  html += "<tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr>\n";
6129
6154
  for (const [key, prop] of Object.entries(schema.properties)) {
6130
6155
  const required = schema.required?.includes(key) ? "\u2705" : "\u274C";
6131
- const type = prop.type ?? "any";
6156
+ const type = _SchemaUtils._escapeHtml(prop.type ?? "any");
6132
6157
  const p = prop;
6133
- const label = p["_label"] ?? key;
6134
- html += `<tr><td>${key}</td><td>${type}</td><td>${required}</td><td>${label}</td></tr>
6158
+ const label = _SchemaUtils._escapeHtml(p["_label"] ?? key);
6159
+ html += `<tr><td>${_SchemaUtils._escapeHtml(key)}</td><td>${type}</td><td>${required}</td><td>${label}</td></tr>
6135
6160
  `;
6136
6161
  }
6137
6162
  html += "</table>\n";
@@ -6140,6 +6165,12 @@ var SchemaUtils = class _SchemaUtils {
6140
6165
  return html;
6141
6166
  }
6142
6167
  // ==================== Private Utilities ====================
6168
+ static _escapeMdCell(str) {
6169
+ return str.replace(/\|/g, "\\|").replace(/\r\n|\r|\n/g, "<br>");
6170
+ }
6171
+ static _escapeHtml(str) {
6172
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
6173
+ }
6143
6174
  static _mergeProperties(base, ext) {
6144
6175
  const result = { ...base };
6145
6176
  for (const [key, extVal] of Object.entries(ext)) {
@@ -6495,10 +6526,25 @@ function _getDefaultValidator() {
6495
6526
  function resetDefaultValidator() {
6496
6527
  _defaultValidator = null;
6497
6528
  }
6529
+ var _INITIAL_PATTERN_KEYS = {
6530
+ phone: new Set(Object.keys(PATTERNS.phone)),
6531
+ idCard: new Set(Object.keys(PATTERNS.idCard)),
6532
+ creditCard: new Set(Object.keys(PATTERNS.creditCard))
6533
+ };
6498
6534
  function resetRuntimeState() {
6499
6535
  resetDefaultValidator();
6500
6536
  DslBuilder.clearCustomTypes();
6501
6537
  Locale.reset();
6538
+ TypeRegistry.setStrict(false);
6539
+ for (const key of Object.keys(PATTERNS.phone)) {
6540
+ if (!_INITIAL_PATTERN_KEYS.phone.has(key)) delete PATTERNS.phone[key];
6541
+ }
6542
+ for (const key of Object.keys(PATTERNS.idCard)) {
6543
+ if (!_INITIAL_PATTERN_KEYS.idCard.has(key)) delete PATTERNS.idCard[key];
6544
+ }
6545
+ for (const key of Object.keys(PATTERNS.creditCard)) {
6546
+ if (!_INITIAL_PATTERN_KEYS.creditCard.has(key)) delete PATTERNS.creditCard[key];
6547
+ }
6502
6548
  }
6503
6549
  function validate(schema, data, options = {}) {
6504
6550
  const normalizedSchema = _normalizeSchemaInput(schema);
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { V as Validator } from './Validator-C7GsVQOH.cjs';
2
- export { C as CacheManager } from './Validator-C7GsVQOH.cjs';
1
+ import { V as Validator } from './Validator-D6okG9tr.cjs';
2
+ export { C as CacheManager } from './Validator-D6okG9tr.cjs';
3
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
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';
5
+ import { I as IConditionalBuilder, D as DslBuilder, a as IDslBuilder, b as DslDefinition, c as DslConditionMarker } from './DslBuilder-CjHTucNQ.cjs';
6
+ export { d as DslErrorNamespace, e as DslField, f as DslFn, g as DslIfFn, h as DslInput } from './DslBuilder-CjHTucNQ.cjs';
7
7
  import { EventEmitter } from 'node:events';
8
8
  import { Ajv } from 'ajv';
9
9
 
@@ -873,6 +873,10 @@ declare class SchemaUtils {
873
873
  }>(validator: V): V;
874
874
  /**
875
875
  * Batch validate using a pre-compiled Ajv validate function.
876
+ *
877
+ * Note: the schema is compiled once per call but not cached between calls.
878
+ * For repeated batch validation of the same schema, prefer `Validator.validateBatch()`
879
+ * which benefits from the built-in compile cache and returns typed `ValidationResult[]`.
876
880
  */
877
881
  static validateBatch(schema: JSONSchema, dataArray: unknown[], ajvInstance: {
878
882
  compile: (schema: JSONSchema) => (data: unknown) => boolean;
@@ -903,6 +907,8 @@ declare class SchemaUtils {
903
907
  static toHTML(schema: JSONSchema, options?: {
904
908
  title?: string;
905
909
  }): string;
910
+ private static _escapeMdCell;
911
+ private static _escapeHtml;
906
912
  private static _mergeProperties;
907
913
  private static _deleteRequired;
908
914
  private static _clone;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { V as Validator } from './Validator-hFWKGxir.js';
2
- export { C as CacheManager } from './Validator-hFWKGxir.js';
1
+ import { V as Validator } from './Validator-CllRdrY0.js';
2
+ export { C as CacheManager } from './Validator-CllRdrY0.js';
3
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.js';
4
4
  export { C as CacheConfig, C as CacheOptions, I as I18nConfig, S as SchemaIOOptions, c as ValidateOptions, d as ValidatorOptions } from './plugin-CIKtTMtS.js';
5
- import { I as IConditionalBuilder, D as DslBuilder, a as IDslBuilder, b as DslDefinition, c as DslConditionMarker } from './DslBuilder-DkLaOo9Q.js';
6
- export { d as DslErrorNamespace, e as DslField, f as DslFn, g as DslIfFn, h as DslInput } from './DslBuilder-DkLaOo9Q.js';
5
+ import { I as IConditionalBuilder, D as DslBuilder, a as IDslBuilder, b as DslDefinition, c as DslConditionMarker } from './DslBuilder-BIgQOAXp.js';
6
+ export { d as DslErrorNamespace, e as DslField, f as DslFn, g as DslIfFn, h as DslInput } from './DslBuilder-BIgQOAXp.js';
7
7
  import { EventEmitter } from 'node:events';
8
8
  import { Ajv } from 'ajv';
9
9
 
@@ -873,6 +873,10 @@ declare class SchemaUtils {
873
873
  }>(validator: V): V;
874
874
  /**
875
875
  * Batch validate using a pre-compiled Ajv validate function.
876
+ *
877
+ * Note: the schema is compiled once per call but not cached between calls.
878
+ * For repeated batch validation of the same schema, prefer `Validator.validateBatch()`
879
+ * which benefits from the built-in compile cache and returns typed `ValidationResult[]`.
876
880
  */
877
881
  static validateBatch(schema: JSONSchema, dataArray: unknown[], ajvInstance: {
878
882
  compile: (schema: JSONSchema) => (data: unknown) => boolean;
@@ -903,6 +907,8 @@ declare class SchemaUtils {
903
907
  static toHTML(schema: JSONSchema, options?: {
904
908
  title?: string;
905
909
  }): string;
910
+ private static _escapeMdCell;
911
+ private static _escapeHtml;
906
912
  private static _mergeProperties;
907
913
  private static _deleteRequired;
908
914
  private static _clone;