metal-orm 1.0.93 → 1.0.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6142,7 +6142,8 @@ var ensureEntityMetadata = (target) => {
6142
6142
  target,
6143
6143
  tableName: target.name || "unknown",
6144
6144
  columns: {},
6145
- relations: {}
6145
+ relations: {},
6146
+ transformers: {}
6146
6147
  };
6147
6148
  metadataMap.set(target, meta);
6148
6149
  }
@@ -6162,6 +6163,10 @@ var addRelationMetadata = (target, propertyKey, relation) => {
6162
6163
  const meta = ensureEntityMetadata(target);
6163
6164
  meta.relations[propertyKey] = relation;
6164
6165
  };
6166
+ var addTransformerMetadata = (target, propertyKey, transformer) => {
6167
+ const meta = ensureEntityMetadata(target);
6168
+ meta.transformers[propertyKey] = transformer;
6169
+ };
6165
6170
  var setEntityTableName = (target, tableName, hooks) => {
6166
6171
  const meta = ensureEntityMetadata(target);
6167
6172
  if (tableName && tableName.length > 0) {
@@ -7522,6 +7527,28 @@ var isTableDef = (value) => {
7522
7527
  return true;
7523
7528
  };
7524
7529
 
7530
+ // src/decorators/decorator-metadata.ts
7531
+ var METADATA_KEY = "metal-orm:decorators";
7532
+ var getOrCreateMetadataBag = (context) => {
7533
+ const metadata = context.metadata || (context.metadata = {});
7534
+ let bag = metadata[METADATA_KEY];
7535
+ if (!bag) {
7536
+ bag = { columns: [], relations: [], transformers: [] };
7537
+ metadata[METADATA_KEY] = bag;
7538
+ }
7539
+ return bag;
7540
+ };
7541
+ var readMetadataBag = (context) => {
7542
+ return context.metadata?.[METADATA_KEY];
7543
+ };
7544
+ var readMetadataBagFromConstructor = (ctor) => {
7545
+ const metadataSymbol = Symbol.metadata;
7546
+ if (!metadataSymbol) return void 0;
7547
+ const metadata = Reflect.get(ctor, metadataSymbol);
7548
+ return metadata?.[METADATA_KEY];
7549
+ };
7550
+ var getDecoratorMetadata = (ctor) => readMetadataBagFromConstructor(ctor);
7551
+
7525
7552
  // src/decorators/bootstrap.ts
7526
7553
  var unwrapTarget = (target) => {
7527
7554
  if (typeof target === "function" && target.prototype === void 0) {
@@ -7618,6 +7645,12 @@ var bootstrapEntities = () => {
7618
7645
  const metas = getAllEntityMetadata();
7619
7646
  const tableMap = /* @__PURE__ */ new Map();
7620
7647
  for (const meta of metas) {
7648
+ const decoratorMetadata = getDecoratorMetadata(meta.target);
7649
+ if (decoratorMetadata?.transformers) {
7650
+ for (const { propertyName, metadata } of decoratorMetadata.transformers) {
7651
+ addTransformerMetadata(meta.target, propertyName, metadata);
7652
+ }
7653
+ }
7621
7654
  const table = buildTableDef(meta);
7622
7655
  tableMap.set(meta.target, table);
7623
7656
  }
@@ -12260,6 +12293,31 @@ var Orm = class {
12260
12293
  }
12261
12294
  };
12262
12295
 
12296
+ // src/orm/column-introspection.ts
12297
+ var getColumnDefFromTarget = (target, column) => {
12298
+ if (typeof target === "function") {
12299
+ const meta = getEntityMetadata(target);
12300
+ if (!meta?.columns) return void 0;
12301
+ return meta.columns[column];
12302
+ }
12303
+ const table = target;
12304
+ return table.columns[column];
12305
+ };
12306
+ var getColumnType = (target, column) => {
12307
+ const col2 = getColumnDefFromTarget(target, column);
12308
+ if (!col2?.type) return void 0;
12309
+ return normalizeColumnType(col2.type);
12310
+ };
12311
+ var getDateKind = (target, column) => {
12312
+ const type = getColumnType(target, column);
12313
+ if (!type) return void 0;
12314
+ if (type === "date") return "date";
12315
+ if (type === "datetime" || type === "timestamp" || type === "timestamptz") {
12316
+ return "date-time";
12317
+ }
12318
+ return void 0;
12319
+ };
12320
+
12263
12321
  // src/orm/jsonify.ts
12264
12322
  var jsonify = (value) => {
12265
12323
  const record = value;
@@ -12271,28 +12329,6 @@ var jsonify = (value) => {
12271
12329
  return result;
12272
12330
  };
12273
12331
 
12274
- // src/decorators/decorator-metadata.ts
12275
- var METADATA_KEY = "metal-orm:decorators";
12276
- var getOrCreateMetadataBag = (context) => {
12277
- const metadata = context.metadata || (context.metadata = {});
12278
- let bag = metadata[METADATA_KEY];
12279
- if (!bag) {
12280
- bag = { columns: [], relations: [] };
12281
- metadata[METADATA_KEY] = bag;
12282
- }
12283
- return bag;
12284
- };
12285
- var readMetadataBag = (context) => {
12286
- return context.metadata?.[METADATA_KEY];
12287
- };
12288
- var readMetadataBagFromConstructor = (ctor) => {
12289
- const metadataSymbol = Symbol.metadata;
12290
- if (!metadataSymbol) return void 0;
12291
- const metadata = Reflect.get(ctor, metadataSymbol);
12292
- return metadata?.[METADATA_KEY];
12293
- };
12294
- var getDecoratorMetadata = (ctor) => readMetadataBagFromConstructor(ctor);
12295
-
12296
12332
  // src/decorators/entity.ts
12297
12333
  var toSnakeCase2 = (value) => {
12298
12334
  return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-z0-9_]+/gi, "_").replace(/__+/g, "_").replace(/^_|_$/g, "").toLowerCase();
@@ -12465,6 +12501,668 @@ function BelongsToMany(options) {
12465
12501
  }));
12466
12502
  }
12467
12503
 
12504
+ // src/decorators/transformers/built-in/string-transformers.ts
12505
+ var TrimTransformer = class {
12506
+ constructor(options = {}) {
12507
+ this.options = options;
12508
+ }
12509
+ name = "trim";
12510
+ sanitize(value) {
12511
+ if (typeof value !== "string") return value;
12512
+ if (this.options.trimAll) {
12513
+ return value.trim();
12514
+ }
12515
+ let result = value;
12516
+ if (this.options.trimStart) {
12517
+ result = result.trimStart();
12518
+ }
12519
+ if (this.options.trimEnd) {
12520
+ result = result.trimEnd();
12521
+ }
12522
+ if (!this.options.trimStart && !this.options.trimEnd && !this.options.trimAll) {
12523
+ result = result.trim();
12524
+ }
12525
+ return result;
12526
+ }
12527
+ };
12528
+ var CaseTransformer = class {
12529
+ constructor(caseType) {
12530
+ this.caseType = caseType;
12531
+ this.name = `case-${caseType}`;
12532
+ }
12533
+ name;
12534
+ sanitize(value) {
12535
+ if (typeof value !== "string") return value;
12536
+ switch (this.caseType) {
12537
+ case "lower":
12538
+ return value.toLowerCase();
12539
+ case "upper":
12540
+ return value.toUpperCase();
12541
+ case "capitalize":
12542
+ return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
12543
+ case "title":
12544
+ return value.split(" ").map(
12545
+ (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
12546
+ ).join(" ");
12547
+ default:
12548
+ return value;
12549
+ }
12550
+ }
12551
+ };
12552
+ var AlphanumericValidator = class {
12553
+ constructor(options = {}) {
12554
+ this.options = options;
12555
+ }
12556
+ name = "alphanumeric";
12557
+ validate(value) {
12558
+ if (typeof value !== "string") {
12559
+ return { isValid: false, error: "Value must be a string" };
12560
+ }
12561
+ const pattern = new RegExp(
12562
+ `^[a-zA-Z0-9${this.options.allowSpaces ? " " : ""}${this.options.allowUnderscores ? "_" : ""}${this.options.allowHyphens ? "-" : ""}]*$`
12563
+ );
12564
+ return pattern.test(value) ? { isValid: true } : { isValid: false, error: "Value must contain only alphanumeric characters" };
12565
+ }
12566
+ autoTransform(value) {
12567
+ if (typeof value !== "string") {
12568
+ return { success: false };
12569
+ }
12570
+ let result = value;
12571
+ result = result.replace(/[^a-zA-Z0-9]/g, (char2) => {
12572
+ if (char2 === " " && this.options.allowSpaces) return " ";
12573
+ if (char2 === "_" && this.options.allowUnderscores) return "_";
12574
+ if (char2 === "-" && this.options.allowHyphens) return "-";
12575
+ return "";
12576
+ });
12577
+ return {
12578
+ success: true,
12579
+ correctedValue: result,
12580
+ message: "Removed non-alphanumeric characters"
12581
+ };
12582
+ }
12583
+ };
12584
+ var EmailValidator = class {
12585
+ constructor(options = {}) {
12586
+ this.options = options;
12587
+ }
12588
+ name = "email";
12589
+ validate(value) {
12590
+ if (typeof value !== "string") {
12591
+ return { isValid: false, error: "Value must be a string" };
12592
+ }
12593
+ const emailPattern = this.options.allowPlus ? /^[^\s@]+@[^\s@]+\.[^\s@]+$/ : /^[^\s@+]+@[^\s@]+\.[^\s@]+$/;
12594
+ if (!emailPattern.test(value)) {
12595
+ return { isValid: false, error: "Value must be a valid email address" };
12596
+ }
12597
+ if (this.options.requireTLD) {
12598
+ const parts = value.split(".");
12599
+ if (parts.length < 3 || parts[parts.length - 1].length < 2) {
12600
+ return { isValid: false, error: "Email must have a valid top-level domain" };
12601
+ }
12602
+ }
12603
+ return { isValid: true };
12604
+ }
12605
+ autoTransform(value) {
12606
+ if (typeof value !== "string") {
12607
+ return { success: false };
12608
+ }
12609
+ let result = value.trim().toLowerCase();
12610
+ if (!this.options.allowPlus) {
12611
+ result = result.replace(/\+.*@/, "@");
12612
+ }
12613
+ return {
12614
+ success: true,
12615
+ correctedValue: result,
12616
+ message: "Trimmed and lowercased email"
12617
+ };
12618
+ }
12619
+ };
12620
+ var LengthValidator = class {
12621
+ constructor(options = {}) {
12622
+ this.options = options;
12623
+ }
12624
+ name = "length";
12625
+ validate(value) {
12626
+ if (typeof value !== "string") {
12627
+ return { isValid: false, error: "Value must be a string" };
12628
+ }
12629
+ if (this.options.exact !== void 0 && value.length !== this.options.exact) {
12630
+ return { isValid: false, error: `Value must be exactly ${this.options.exact} characters long` };
12631
+ }
12632
+ if (this.options.min !== void 0 && value.length < this.options.min) {
12633
+ return { isValid: false, error: `Value must be at least ${this.options.min} characters long` };
12634
+ }
12635
+ if (this.options.max !== void 0 && value.length > this.options.max) {
12636
+ return { isValid: false, error: `Value must be at most ${this.options.max} characters long` };
12637
+ }
12638
+ return { isValid: true };
12639
+ }
12640
+ autoTransform(value) {
12641
+ if (typeof value !== "string") {
12642
+ return { success: false };
12643
+ }
12644
+ let result = value;
12645
+ if (this.options.max !== void 0 && result.length > this.options.max) {
12646
+ result = result.slice(0, this.options.max);
12647
+ }
12648
+ if (this.options.min !== void 0 && result.length < this.options.min) {
12649
+ result = result.padEnd(this.options.min);
12650
+ }
12651
+ return {
12652
+ success: true,
12653
+ correctedValue: result,
12654
+ message: "Adjusted string length"
12655
+ };
12656
+ }
12657
+ };
12658
+ var PatternValidator = class {
12659
+ constructor(options = { pattern: /.*/ }) {
12660
+ this.options = options;
12661
+ }
12662
+ name = "pattern";
12663
+ validate(value) {
12664
+ if (typeof value !== "string") {
12665
+ return { isValid: false, error: "Value must be a string" };
12666
+ }
12667
+ const pattern = new RegExp(this.options.pattern.source, this.options.flags);
12668
+ if (!pattern.test(value)) {
12669
+ return { isValid: false, error: this.options.errorMessage || "Value does not match required pattern" };
12670
+ }
12671
+ return { isValid: true };
12672
+ }
12673
+ autoTransform(value) {
12674
+ if (typeof value !== "string" || !this.options.replacement) {
12675
+ return { success: false };
12676
+ }
12677
+ const pattern = new RegExp(this.options.pattern.source, this.options.flags);
12678
+ const result = value.replace(pattern, this.options.replacement);
12679
+ return {
12680
+ success: true,
12681
+ correctedValue: result,
12682
+ message: "Replaced pattern matches"
12683
+ };
12684
+ }
12685
+ };
12686
+
12687
+ // src/decorators/transformers/transformer-decorators.ts
12688
+ var normalizePropertyName3 = (name) => {
12689
+ if (typeof name === "symbol") {
12690
+ return name.description ?? name.toString();
12691
+ }
12692
+ return name;
12693
+ };
12694
+ var registerTransformerMetadata = (context, metadata) => {
12695
+ const propertyName = normalizePropertyName3(context.name);
12696
+ const bag = getOrCreateMetadataBag(context);
12697
+ let existing = bag.transformers.find((t) => t.propertyName === propertyName);
12698
+ if (!existing) {
12699
+ existing = {
12700
+ propertyName,
12701
+ metadata: {
12702
+ propertyName,
12703
+ transformers: [],
12704
+ validators: [],
12705
+ sanitizers: [],
12706
+ executionOrder: "both"
12707
+ }
12708
+ };
12709
+ bag.transformers.push(existing);
12710
+ }
12711
+ if (metadata.transformers) {
12712
+ existing.metadata.transformers.push(...metadata.transformers);
12713
+ }
12714
+ if (metadata.validators) {
12715
+ existing.metadata.validators.push(...metadata.validators);
12716
+ }
12717
+ if (metadata.sanitizers) {
12718
+ existing.metadata.sanitizers.push(...metadata.sanitizers);
12719
+ }
12720
+ if (metadata.executionOrder) {
12721
+ existing.metadata.executionOrder = metadata.executionOrder;
12722
+ }
12723
+ };
12724
+ function Trim(options) {
12725
+ return function(_value, context) {
12726
+ registerTransformerMetadata(context, {
12727
+ sanitizers: [new TrimTransformer(options)]
12728
+ });
12729
+ };
12730
+ }
12731
+ function Lower() {
12732
+ return function(_value, context) {
12733
+ registerTransformerMetadata(context, {
12734
+ sanitizers: [new CaseTransformer("lower")]
12735
+ });
12736
+ };
12737
+ }
12738
+ function Upper() {
12739
+ return function(_value, context) {
12740
+ registerTransformerMetadata(context, {
12741
+ sanitizers: [new CaseTransformer("upper")]
12742
+ });
12743
+ };
12744
+ }
12745
+ function Capitalize() {
12746
+ return function(_value, context) {
12747
+ registerTransformerMetadata(context, {
12748
+ sanitizers: [new CaseTransformer("capitalize")]
12749
+ });
12750
+ };
12751
+ }
12752
+ function Title() {
12753
+ return function(_value, context) {
12754
+ registerTransformerMetadata(context, {
12755
+ sanitizers: [new CaseTransformer("title")]
12756
+ });
12757
+ };
12758
+ }
12759
+ function Alphanumeric(options) {
12760
+ return function(_value, context) {
12761
+ registerTransformerMetadata(context, {
12762
+ validators: [new AlphanumericValidator(options)]
12763
+ });
12764
+ };
12765
+ }
12766
+ function Email(options) {
12767
+ return function(_value, context) {
12768
+ registerTransformerMetadata(context, {
12769
+ validators: [new EmailValidator(options)]
12770
+ });
12771
+ };
12772
+ }
12773
+ function Length(options) {
12774
+ return function(_value, context) {
12775
+ registerTransformerMetadata(context, {
12776
+ validators: [new LengthValidator(options)]
12777
+ });
12778
+ };
12779
+ }
12780
+ function Pattern(options) {
12781
+ return function(_value, context) {
12782
+ registerTransformerMetadata(context, {
12783
+ validators: [new PatternValidator(options)]
12784
+ });
12785
+ };
12786
+ }
12787
+
12788
+ // src/decorators/validators/country-validator-registry.ts
12789
+ var VALIDATOR_FACTORIES = /* @__PURE__ */ new Map();
12790
+ var registerValidator = (countryCode, identifierType, factory) => {
12791
+ const key = `${countryCode.toLowerCase()}-${identifierType.toLowerCase()}`;
12792
+ if (!countryCode) throw new Error("countryCode is required");
12793
+ if (!identifierType) throw new Error("identifierType is required");
12794
+ if (typeof factory !== "function") {
12795
+ throw new Error("factory must be a function that returns a validator");
12796
+ }
12797
+ VALIDATOR_FACTORIES.set(key, factory);
12798
+ };
12799
+ var resolveValidator = (countryCode, identifierType) => {
12800
+ const key = `${countryCode.toLowerCase()}-${identifierType.toLowerCase()}`;
12801
+ const factory = VALIDATOR_FACTORIES.get(key);
12802
+ return factory ? factory() : void 0;
12803
+ };
12804
+ var getRegisteredValidators = () => {
12805
+ return Array.from(VALIDATOR_FACTORIES.keys());
12806
+ };
12807
+ var hasValidator = (countryCode, identifierType) => {
12808
+ const key = `${countryCode.toLowerCase()}-${identifierType.toLowerCase()}`;
12809
+ return VALIDATOR_FACTORIES.has(key);
12810
+ };
12811
+
12812
+ // src/decorators/validators/built-in/br-cpf-validator.ts
12813
+ var CPFValidator = class {
12814
+ countryCode = "BR";
12815
+ identifierType = "cpf";
12816
+ name = "br-cpf";
12817
+ validate(value, options = {}) {
12818
+ const normalized = this.normalize(value);
12819
+ if (!/^\d{11}$/.test(normalized)) {
12820
+ return {
12821
+ isValid: false,
12822
+ error: options.errorMessage || "CPF must contain exactly 11 numeric digits"
12823
+ };
12824
+ }
12825
+ if (this.isKnownInvalid(normalized) && options.strict !== false) {
12826
+ return {
12827
+ isValid: false,
12828
+ error: options.errorMessage || "Invalid CPF number"
12829
+ };
12830
+ }
12831
+ if (!this.validateChecksum(normalized)) {
12832
+ return {
12833
+ isValid: false,
12834
+ error: options.errorMessage || "Invalid CPF checksum"
12835
+ };
12836
+ }
12837
+ return {
12838
+ isValid: true,
12839
+ normalizedValue: normalized,
12840
+ formattedValue: this.format(value)
12841
+ };
12842
+ }
12843
+ normalize(value) {
12844
+ return value.replace(/[^0-9]/g, "");
12845
+ }
12846
+ format(value) {
12847
+ const normalized = this.normalize(value);
12848
+ if (normalized.length !== 11) return value;
12849
+ return normalized.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4");
12850
+ }
12851
+ autoCorrect(value) {
12852
+ const normalized = this.normalize(value);
12853
+ if (normalized.length === 11) {
12854
+ return { success: true, correctedValue: this.format(normalized) };
12855
+ }
12856
+ if (normalized.length < 11) {
12857
+ const padded = normalized.padEnd(11, "0");
12858
+ return { success: true, correctedValue: this.format(padded) };
12859
+ }
12860
+ const truncated = normalized.slice(0, 11);
12861
+ return { success: true, correctedValue: this.format(truncated) };
12862
+ }
12863
+ isKnownInvalid(cpf) {
12864
+ return /^(\d)\1{10}$/.test(cpf);
12865
+ }
12866
+ validateChecksum(cpf) {
12867
+ const digits = cpf.split("").map(Number);
12868
+ let sum2 = 0;
12869
+ for (let i = 0; i < 9; i++) {
12870
+ sum2 += digits[i] * (10 - i);
12871
+ }
12872
+ let check1 = sum2 % 11;
12873
+ check1 = check1 < 2 ? 0 : 11 - check1;
12874
+ if (check1 !== digits[9]) {
12875
+ return false;
12876
+ }
12877
+ sum2 = 0;
12878
+ for (let i = 0; i < 10; i++) {
12879
+ sum2 += digits[i] * (11 - i);
12880
+ }
12881
+ let check2 = sum2 % 11;
12882
+ check2 = check2 < 2 ? 0 : 11 - check2;
12883
+ return check2 === digits[10];
12884
+ }
12885
+ };
12886
+
12887
+ // src/decorators/validators/built-in/br-cnpj-validator.ts
12888
+ var CNPJValidator = class {
12889
+ countryCode = "BR";
12890
+ identifierType = "cnpj";
12891
+ name = "br-cnpj";
12892
+ validate(value, options = {}) {
12893
+ const normalized = this.normalize(value);
12894
+ if (!/^\d{14}$/.test(normalized)) {
12895
+ return {
12896
+ isValid: false,
12897
+ error: options.errorMessage || "CNPJ must contain exactly 14 numeric digits"
12898
+ };
12899
+ }
12900
+ if (this.isKnownInvalid(normalized) && options.strict !== false) {
12901
+ return {
12902
+ isValid: false,
12903
+ error: options.errorMessage || "Invalid CNPJ number"
12904
+ };
12905
+ }
12906
+ if (!this.validateChecksum(normalized)) {
12907
+ return {
12908
+ isValid: false,
12909
+ error: options.errorMessage || "Invalid CNPJ checksum"
12910
+ };
12911
+ }
12912
+ return {
12913
+ isValid: true,
12914
+ normalizedValue: normalized,
12915
+ formattedValue: this.format(value)
12916
+ };
12917
+ }
12918
+ normalize(value) {
12919
+ return value.replace(/[^0-9]/g, "");
12920
+ }
12921
+ format(value) {
12922
+ const normalized = this.normalize(value);
12923
+ if (normalized.length !== 14) return value;
12924
+ return normalized.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5");
12925
+ }
12926
+ autoCorrect(value) {
12927
+ const normalized = this.normalize(value);
12928
+ if (normalized.length === 14) {
12929
+ return { success: true, correctedValue: this.format(normalized) };
12930
+ }
12931
+ if (normalized.length < 14) {
12932
+ const padded = normalized.padEnd(14, "0");
12933
+ return { success: true, correctedValue: this.format(padded) };
12934
+ }
12935
+ const truncated = normalized.slice(0, 14);
12936
+ return { success: true, correctedValue: this.format(truncated) };
12937
+ }
12938
+ isKnownInvalid(cnpj) {
12939
+ return /^(\d)\1{13}$/.test(cnpj);
12940
+ }
12941
+ validateChecksum(cnpj) {
12942
+ const digits = cnpj.split("").map(Number);
12943
+ const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
12944
+ const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
12945
+ let sum2 = 0;
12946
+ for (let i = 0; i < 12; i++) {
12947
+ sum2 += digits[i] * weights1[i];
12948
+ }
12949
+ let check1 = sum2 % 11;
12950
+ check1 = check1 < 2 ? 0 : 11 - check1;
12951
+ if (check1 !== digits[12]) {
12952
+ return false;
12953
+ }
12954
+ sum2 = 0;
12955
+ for (let i = 0; i < 13; i++) {
12956
+ sum2 += digits[i] * weights2[i];
12957
+ }
12958
+ let check2 = sum2 % 11;
12959
+ check2 = check2 < 2 ? 0 : 11 - check2;
12960
+ return check2 === digits[13];
12961
+ }
12962
+ };
12963
+
12964
+ // src/decorators/validators/built-in/br-cep-validator.ts
12965
+ var CEPValidator = class {
12966
+ countryCode = "BR";
12967
+ identifierType = "cep";
12968
+ name = "br-cep";
12969
+ validate(value, options = {}) {
12970
+ const normalized = this.normalize(value);
12971
+ if (!/^\d{8}$/.test(normalized)) {
12972
+ return {
12973
+ isValid: false,
12974
+ error: options.errorMessage || "CEP must contain exactly 8 numeric digits"
12975
+ };
12976
+ }
12977
+ return {
12978
+ isValid: true,
12979
+ normalizedValue: normalized,
12980
+ formattedValue: this.format(value)
12981
+ };
12982
+ }
12983
+ normalize(value) {
12984
+ return value.replace(/[^0-9]/g, "");
12985
+ }
12986
+ format(value) {
12987
+ const normalized = this.normalize(value);
12988
+ if (normalized.length !== 8) return value;
12989
+ return normalized.replace(/(\d{5})(\d{3})/, "$1-$2");
12990
+ }
12991
+ autoCorrect(value) {
12992
+ const normalized = this.normalize(value);
12993
+ if (normalized.length === 8) {
12994
+ return { success: true, correctedValue: this.format(normalized) };
12995
+ }
12996
+ if (normalized.length < 8) {
12997
+ const padded = normalized.padEnd(8, "0");
12998
+ return { success: true, correctedValue: this.format(padded) };
12999
+ }
13000
+ const truncated = normalized.slice(0, 8);
13001
+ return { success: true, correctedValue: this.format(truncated) };
13002
+ }
13003
+ };
13004
+
13005
+ // src/decorators/validators/country-validators-decorators.ts
13006
+ registerValidator("BR", "cpf", () => new CPFValidator());
13007
+ registerValidator("BR", "cnpj", () => new CNPJValidator());
13008
+ registerValidator("BR", "cep", () => new CEPValidator());
13009
+ var normalizePropertyName4 = (name) => {
13010
+ if (typeof name === "symbol") {
13011
+ return name.description ?? name.toString();
13012
+ }
13013
+ return name;
13014
+ };
13015
+ function CPF(options) {
13016
+ return function(_value, context) {
13017
+ const propertyName = normalizePropertyName4(context.name);
13018
+ const bag = getOrCreateMetadataBag(context);
13019
+ let existing = bag.transformers.find((t) => t.propertyName === propertyName);
13020
+ if (!existing) {
13021
+ existing = {
13022
+ propertyName,
13023
+ metadata: {
13024
+ propertyName,
13025
+ transformers: [],
13026
+ validators: [],
13027
+ sanitizers: [],
13028
+ executionOrder: "both"
13029
+ }
13030
+ };
13031
+ bag.transformers.push(existing);
13032
+ }
13033
+ const validator = new CPFValidator();
13034
+ existing.metadata.validators.push({
13035
+ name: validator.name,
13036
+ validate: (value) => {
13037
+ const result = validator.validate(value, {
13038
+ strict: options?.strict ?? true,
13039
+ errorMessage: options?.errorMessage
13040
+ });
13041
+ return {
13042
+ isValid: result.isValid,
13043
+ error: result.error,
13044
+ message: result.error
13045
+ };
13046
+ },
13047
+ autoTransform: (value) => {
13048
+ const correction = validator.autoCorrect(value);
13049
+ if (correction?.success) {
13050
+ return {
13051
+ success: true,
13052
+ correctedValue: correction.correctedValue,
13053
+ message: correction.message
13054
+ };
13055
+ }
13056
+ return { success: false };
13057
+ }
13058
+ });
13059
+ existing.metadata.sanitizers.push({
13060
+ name: "cpf-formatter",
13061
+ sanitize: (value) => validator.format(value)
13062
+ });
13063
+ };
13064
+ }
13065
+ function CNPJ(options) {
13066
+ return function(_value, context) {
13067
+ const propertyName = normalizePropertyName4(context.name);
13068
+ const bag = getOrCreateMetadataBag(context);
13069
+ let existing = bag.transformers.find((t) => t.propertyName === propertyName);
13070
+ if (!existing) {
13071
+ existing = {
13072
+ propertyName,
13073
+ metadata: {
13074
+ propertyName,
13075
+ transformers: [],
13076
+ validators: [],
13077
+ sanitizers: [],
13078
+ executionOrder: "both"
13079
+ }
13080
+ };
13081
+ bag.transformers.push(existing);
13082
+ }
13083
+ const validator = new CNPJValidator();
13084
+ existing.metadata.validators.push({
13085
+ name: validator.name,
13086
+ validate: (value) => {
13087
+ const result = validator.validate(value, {
13088
+ strict: options?.strict ?? true,
13089
+ errorMessage: options?.errorMessage
13090
+ });
13091
+ return {
13092
+ isValid: result.isValid,
13093
+ error: result.error,
13094
+ message: result.error
13095
+ };
13096
+ },
13097
+ autoTransform: (value) => {
13098
+ const correction = validator.autoCorrect(value);
13099
+ if (correction?.success) {
13100
+ return {
13101
+ success: true,
13102
+ correctedValue: correction.correctedValue,
13103
+ message: correction.message
13104
+ };
13105
+ }
13106
+ return { success: false };
13107
+ }
13108
+ });
13109
+ existing.metadata.sanitizers.push({
13110
+ name: "cnpj-formatter",
13111
+ sanitize: (value) => validator.format(value)
13112
+ });
13113
+ };
13114
+ }
13115
+ function CEP(options) {
13116
+ return function(_value, context) {
13117
+ const propertyName = normalizePropertyName4(context.name);
13118
+ const bag = getOrCreateMetadataBag(context);
13119
+ let existing = bag.transformers.find((t) => t.propertyName === propertyName);
13120
+ if (!existing) {
13121
+ existing = {
13122
+ propertyName,
13123
+ metadata: {
13124
+ propertyName,
13125
+ transformers: [],
13126
+ validators: [],
13127
+ sanitizers: [],
13128
+ executionOrder: "both"
13129
+ }
13130
+ };
13131
+ bag.transformers.push(existing);
13132
+ }
13133
+ const validator = new CEPValidator();
13134
+ existing.metadata.validators.push({
13135
+ name: validator.name,
13136
+ validate: (value) => {
13137
+ const result = validator.validate(value, {
13138
+ strict: options?.strict ?? true,
13139
+ errorMessage: options?.errorMessage
13140
+ });
13141
+ return {
13142
+ isValid: result.isValid,
13143
+ error: result.error,
13144
+ message: result.error
13145
+ };
13146
+ },
13147
+ autoTransform: (value) => {
13148
+ const correction = validator.autoCorrect(value);
13149
+ if (correction?.success) {
13150
+ return {
13151
+ success: true,
13152
+ correctedValue: correction.correctedValue,
13153
+ message: correction.message
13154
+ };
13155
+ }
13156
+ return { success: false };
13157
+ }
13158
+ });
13159
+ existing.metadata.sanitizers.push({
13160
+ name: "cep-formatter",
13161
+ sanitize: (value) => validator.format(value)
13162
+ });
13163
+ };
13164
+ }
13165
+
12468
13166
  // src/core/execution/db-executor.ts
12469
13167
  function rowsToQueryResult(rows) {
12470
13168
  if (rows.length === 0) {
@@ -14279,11 +14977,16 @@ function pagedResponseToOpenApiSchema(itemSchema) {
14279
14977
  };
14280
14978
  }
14281
14979
  export {
14980
+ Alphanumeric,
14282
14981
  AsyncLocalStorage,
14283
14982
  BelongsTo,
14284
14983
  BelongsToMany,
14285
14984
  BigIntTypeStrategy,
14286
14985
  BooleanTypeStrategy,
14986
+ CEP,
14987
+ CNPJ,
14988
+ CPF,
14989
+ Capitalize,
14287
14990
  Column,
14288
14991
  ConstructorMaterializationStrategy,
14289
14992
  DateTimeTypeStrategy,
@@ -14295,6 +14998,7 @@ export {
14295
14998
  DefaultTypeStrategy,
14296
14999
  DeleteQueryBuilder,
14297
15000
  DomainEventBus,
15001
+ Email,
14298
15002
  Entity,
14299
15003
  EntityStatus,
14300
15004
  HasMany,
@@ -14302,9 +15006,12 @@ export {
14302
15006
  InsertQueryBuilder,
14303
15007
  IntegerTypeStrategy,
14304
15008
  InterceptorPipeline,
15009
+ Length,
15010
+ Lower,
14305
15011
  MySqlDialect,
14306
15012
  Orm,
14307
15013
  OrmSession,
15014
+ Pattern,
14308
15015
  Pool,
14309
15016
  PostgresDialect,
14310
15017
  PrimaryKey,
@@ -14315,9 +15022,12 @@ export {
14315
15022
  SqlServerDialect,
14316
15023
  SqliteDialect,
14317
15024
  StringTypeStrategy,
15025
+ Title,
15026
+ Trim,
14318
15027
  TypeMappingService,
14319
15028
  TypeScriptGenerator,
14320
15029
  UpdateQueryBuilder,
15030
+ Upper,
14321
15031
  UuidTypeStrategy,
14322
15032
  abs,
14323
15033
  acos,
@@ -14432,9 +15142,12 @@ export {
14432
15142
  generateSchemaSqlFor,
14433
15143
  getColumn,
14434
15144
  getColumnMap,
15145
+ getColumnType,
15146
+ getDateKind,
14435
15147
  getDecoratorMetadata,
14436
15148
  getDeterministicComponentName,
14437
15149
  getOpenApiVersionForDialect,
15150
+ getRegisteredValidators,
14438
15151
  getSchemaIntrospector,
14439
15152
  getTableDefFromEntity,
14440
15153
  greatest,
@@ -14445,6 +15158,7 @@ export {
14445
15158
  hasNextPage as hasNextPageMeta,
14446
15159
  hasOne,
14447
15160
  hasPrevPage as hasPrevPageMeta,
15161
+ hasValidator,
14448
15162
  hour,
14449
15163
  hydrateRows,
14450
15164
  ifNull,
@@ -14538,6 +15252,7 @@ export {
14538
15252
  registerExpressionDispatcher,
14539
15253
  registerOperandDispatcher,
14540
15254
  registerSchemaIntrospector,
15255
+ registerValidator,
14541
15256
  relationFilterToOpenApiSchema,
14542
15257
  relationLoaderCache,
14543
15258
  renderColumnDefinition,
@@ -14545,6 +15260,7 @@ export {
14545
15260
  repeat,
14546
15261
  replace,
14547
15262
  replaceWithRefs,
15263
+ resolveValidator,
14548
15264
  responseToRef,
14549
15265
  reverse,
14550
15266
  right,