metal-orm 1.1.11 → 1.1.16
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/README.md +758 -769
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +100 -96
- package/scripts/generate-entities/schema.mjs +122 -122
- package/scripts/generate-entities/tree-detection.mjs +92 -92
- package/scripts/inflection/pt-br.mjs +468 -468
- package/scripts/run-eslint.mjs +33 -34
- package/scripts/show-sql-seed.sql +102 -0
- package/scripts/show-sql.mjs +321 -325
- package/src/codegen/naming-strategy.ts +54 -54
- package/src/codegen/typescript.ts +482 -482
- package/src/core/ast/adapters.ts +1 -1
- package/src/core/ast/builders.ts +123 -123
- package/src/core/ast/expression-builders.ts +745 -745
- package/src/core/ast/expression-nodes.ts +304 -304
- package/src/core/ast/expression-visitor.ts +212 -212
- package/src/core/ast/expression.ts +20 -20
- package/src/core/ast/helpers.ts +14 -14
- package/src/core/ast/join.ts +18 -18
- package/src/core/ast/query.ts +200 -200
- package/src/core/ddl/dialects/base-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/render-reference.test.ts +70 -70
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -1
- package/src/core/ddl/introspect/catalogs/index.ts +5 -5
- package/src/core/ddl/introspect/catalogs/postgres.ts +146 -146
- package/src/core/ddl/introspect/context.ts +15 -15
- package/src/core/ddl/introspect/functions/postgres.ts +35 -35
- package/src/core/ddl/introspect/registry.ts +40 -40
- package/src/core/ddl/introspect/run-select.ts +35 -35
- package/src/core/ddl/introspect/utils.ts +56 -56
- package/src/core/ddl/naming-strategy.ts +16 -16
- package/src/core/ddl/schema-dialect.ts +56 -56
- package/src/core/ddl/schema-diff.ts +234 -234
- package/src/core/ddl/schema-generator.ts +1 -1
- package/src/core/ddl/schema-introspect.ts +25 -25
- package/src/core/ddl/sql-writing.ts +171 -171
- package/src/core/dialect/abstract.ts +541 -541
- package/src/core/dialect/base/cte-compiler.ts +33 -33
- package/src/core/dialect/base/function-table-formatter.ts +103 -103
- package/src/core/dialect/base/groupby-compiler.ts +21 -21
- package/src/core/dialect/base/join-compiler.ts +25 -25
- package/src/core/dialect/base/orderby-compiler.ts +35 -35
- package/src/core/dialect/base/pagination-strategy.ts +32 -32
- package/src/core/dialect/base/returning-strategy.ts +57 -57
- package/src/core/dialect/base/sql-dialect.ts +294 -294
- package/src/core/dialect/dialect-factory.ts +91 -91
- package/src/core/dialect/mssql/functions.ts +120 -120
- package/src/core/dialect/mssql/index.ts +317 -317
- package/src/core/dialect/mysql/functions.ts +103 -103
- package/src/core/dialect/mysql/index.ts +105 -105
- package/src/core/dialect/postgres/functions.ts +108 -108
- package/src/core/dialect/postgres/index.ts +91 -91
- package/src/core/dialect/sqlite/functions.ts +129 -129
- package/src/core/dialect/sqlite/index.ts +67 -67
- package/src/core/driver/database-driver.ts +19 -19
- package/src/core/driver/mssql-driver.ts +23 -23
- package/src/core/driver/mysql-driver.ts +23 -23
- package/src/core/driver/postgres-driver.ts +23 -23
- package/src/core/driver/sqlite-driver.ts +23 -23
- package/src/core/execution/db-executor.ts +92 -92
- package/src/core/execution/executors/better-sqlite3-executor.ts +90 -90
- package/src/core/execution/executors/mssql-executor.ts +184 -184
- package/src/core/execution/executors/mysql-executor.ts +88 -88
- package/src/core/execution/executors/postgres-executor.ts +26 -26
- package/src/core/execution/executors/sqlite-executor.ts +42 -42
- package/src/core/execution/pooling/pool-types.ts +30 -30
- package/src/core/execution/pooling/pool.ts +275 -275
- package/src/core/functions/array.ts +35 -35
- package/src/core/functions/control-flow.ts +79 -79
- package/src/core/functions/datetime.ts +237 -237
- package/src/core/functions/json.ts +70 -70
- package/src/core/functions/numeric.ts +297 -297
- package/src/core/functions/text.ts +334 -334
- package/src/core/functions/types.ts +33 -33
- package/src/core/hydration/types.ts +51 -51
- package/src/core/sql/sql-operator-config.ts +39 -39
- package/src/core/sql/sql.ts +152 -152
- package/src/decorators/column-decorator.ts +87 -87
- package/src/decorators/decorator-metadata.ts +143 -143
- package/src/decorators/entity.ts +93 -93
- package/src/decorators/index.ts +39 -39
- package/src/decorators/relations.ts +231 -231
- package/src/decorators/transformers/built-in/string-transformers.ts +231 -231
- package/src/decorators/transformers/transformer-decorators.ts +134 -134
- package/src/decorators/transformers/transformer-executor.ts +171 -171
- package/src/decorators/transformers/transformer-metadata.ts +73 -73
- package/src/decorators/validators/built-in/br-cep-validator.ts +55 -55
- package/src/decorators/validators/built-in/br-cnpj-validator.ts +105 -105
- package/src/decorators/validators/built-in/br-cpf-validator.ts +103 -103
- package/src/decorators/validators/country-validator-registry.ts +64 -64
- package/src/decorators/validators/country-validators-decorators.ts +203 -203
- package/src/decorators/validators/country-validators.ts +105 -105
- package/src/decorators/validators/validator-metadata.ts +59 -59
- package/src/dto/dto-types.ts +226 -226
- package/src/dto/filter-types.ts +141 -141
- package/src/dto/index.ts +95 -95
- package/src/dto/openapi/generators/base.ts +29 -29
- package/src/dto/openapi/generators/column.ts +37 -37
- package/src/dto/openapi/generators/dto.ts +91 -91
- package/src/dto/openapi/generators/filter.ts +75 -75
- package/src/dto/openapi/generators/nested-dto.ts +618 -618
- package/src/dto/openapi/generators/pagination.ts +111 -111
- package/src/dto/openapi/generators/relation-filter.ts +228 -228
- package/src/dto/openapi/index.ts +12 -12
- package/src/dto/openapi/types.ts +101 -101
- package/src/dto/openapi/utilities.ts +95 -95
- package/src/dto/pagination-utils.ts +150 -150
- package/src/dto/transform.ts +197 -197
- package/src/index.ts +86 -86
- package/src/orm/als.ts +58 -58
- package/src/orm/domain-event-bus.ts +119 -119
- package/src/orm/entity-context.ts +86 -86
- package/src/orm/entity-materializer.ts +159 -159
- package/src/orm/entity-meta.ts +97 -97
- package/src/orm/entity-registry.ts +39 -39
- package/src/orm/entity-relation-cache.ts +39 -39
- package/src/orm/execute.ts +194 -194
- package/src/orm/execution-context.ts +18 -18
- package/src/orm/hydration-context.ts +26 -26
- package/src/orm/hydration.ts +112 -112
- package/src/orm/identity-map.ts +61 -61
- package/src/orm/interceptor-pipeline.ts +16 -16
- package/src/orm/lazy-batch/belongs-to-many.ts +119 -119
- package/src/orm/lazy-batch/belongs-to.ts +108 -108
- package/src/orm/lazy-batch/has-many.ts +69 -69
- package/src/orm/lazy-batch/has-one.ts +68 -68
- package/src/orm/lazy-batch/shared.ts +125 -125
- package/src/orm/orm-session.ts +620 -620
- package/src/orm/orm.ts +34 -34
- package/src/orm/pooled-executor-factory.ts +121 -121
- package/src/orm/query-logger.ts +40 -40
- package/src/orm/relation-change-processor.ts +420 -420
- package/src/orm/relations/belongs-to.ts +143 -143
- package/src/orm/relations/has-many.ts +204 -204
- package/src/orm/relations/has-one.ts +174 -174
- package/src/orm/relations/many-to-many.ts +288 -288
- package/src/orm/relations/morph-many.ts +156 -156
- package/src/orm/relations/morph-one.ts +151 -151
- package/src/orm/relations/morph-to.ts +162 -162
- package/src/orm/runtime-types.ts +92 -92
- package/src/orm/save-graph.ts +561 -561
- package/src/orm/transaction-runner.ts +24 -24
- package/src/orm/unit-of-work.ts +426 -426
- package/src/query/index.ts +69 -69
- package/src/query/target.ts +46 -46
- package/src/query-builder/column-selector.ts +81 -81
- package/src/query-builder/delete.ts +141 -141
- package/src/query-builder/insert-query-state.ts +149 -149
- package/src/query-builder/insert.ts +117 -117
- package/src/query-builder/query-ast-service.ts +287 -287
- package/src/query-builder/query-resolution.ts +78 -78
- package/src/query-builder/raw-column-parser.ts +38 -38
- package/src/query-builder/relation-filter-utils.ts +153 -153
- package/src/query-builder/relation-join-planner.ts +10 -10
- package/src/query-builder/relation-manager.ts +87 -87
- package/src/query-builder/relation-projection-helper.ts +102 -102
- package/src/query-builder/relation-types.ts +9 -9
- package/src/query-builder/relation-utils.ts +15 -15
- package/src/query-builder/select/cte-facet.ts +40 -40
- package/src/query-builder/select/from-facet.ts +80 -80
- package/src/query-builder/select/join-facet.ts +62 -62
- package/src/query-builder/select/predicate-facet.ts +104 -104
- package/src/query-builder/select/projection-facet.ts +70 -70
- package/src/query-builder/select/relation-facet.ts +81 -81
- package/src/query-builder/select/setop-facet.ts +36 -36
- package/src/query-builder/select-helpers.ts +1 -1
- package/src/query-builder/select-query-builder-deps.ts +130 -130
- package/src/query-builder/select-query-state.ts +207 -207
- package/src/query-builder/update.ts +151 -151
- package/src/schema/column-types.ts +322 -322
- package/src/schema/table-guards.ts +37 -37
- package/src/schema/table.ts +281 -281
- package/src/tree/index.ts +13 -13
- package/src/tree/nested-set-strategy.ts +545 -545
- package/src/tree/tree-decorator.ts +397 -397
- package/src/tree/tree-manager.ts +754 -754
- package/src/tree/tree-query.ts +427 -427
- package/src/tree/tree-types.ts +299 -299
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import type { ColumnType } from '../../schema/column-types.js';
|
|
2
|
-
|
|
3
|
-
// Transform context provides metadata about the transformation
|
|
4
|
-
export interface TransformContext {
|
|
5
|
-
entityName: string;
|
|
6
|
-
propertyName: string;
|
|
7
|
-
columnType: ColumnType;
|
|
8
|
-
isUpdate: boolean;
|
|
9
|
-
originalValue?: unknown;
|
|
10
|
-
autoTransform: boolean; // Whether auto-correction is enabled
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Auto-transform result for validators that can fix data
|
|
14
|
-
export interface AutoTransformResult<T = unknown> {
|
|
15
|
-
success: boolean;
|
|
16
|
-
correctedValue?: T;
|
|
17
|
-
message?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Base transformer interface
|
|
21
|
-
export interface PropertyTransformer<TInput = unknown, TOutput = unknown> {
|
|
22
|
-
readonly name: string;
|
|
23
|
-
transform(value: TInput, context: TransformContext): TOutput;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Validator interface (read-only, throws on failure)
|
|
27
|
-
export interface PropertyValidator<T = unknown> {
|
|
28
|
-
readonly name: string;
|
|
29
|
-
validate(value: T, context: TransformContext): ValidationResult;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Sanitizer interface (mutates, never throws)
|
|
33
|
-
export interface PropertySanitizer<T = unknown> {
|
|
34
|
-
readonly name: string;
|
|
35
|
-
sanitize(value: T, context: TransformContext): T;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Combined transformer that can validate and transform
|
|
39
|
-
export interface CompositeTransformer<TInput = unknown, TOutput = unknown>
|
|
40
|
-
extends PropertyTransformer<TInput, TOutput>,
|
|
41
|
-
PropertyValidator<TInput> {}
|
|
42
|
-
|
|
43
|
-
// Extended validator interface with auto-transform capability
|
|
44
|
-
export interface AutoTransformableValidator<T = unknown> extends PropertyValidator<T> {
|
|
45
|
-
/**
|
|
46
|
-
* Attempts to automatically correct an invalid value.
|
|
47
|
-
* Returns undefined if auto-correction is not possible.
|
|
48
|
-
*/
|
|
49
|
-
autoTransform?(value: T, context: TransformContext): AutoTransformResult<T>;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Validation result
|
|
53
|
-
export interface ValidationResult {
|
|
54
|
-
isValid: boolean;
|
|
55
|
-
error?: string;
|
|
56
|
-
message?: string;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Transformer metadata stored during decoration phase
|
|
60
|
-
export interface TransformerMetadata {
|
|
61
|
-
propertyName: string;
|
|
62
|
-
transformers: PropertyTransformer[];
|
|
63
|
-
validators: PropertyValidator[];
|
|
64
|
-
sanitizers: PropertySanitizer[];
|
|
65
|
-
executionOrder: 'before-save' | 'after-load' | 'both';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Transformer configuration options
|
|
69
|
-
export interface TransformerConfig {
|
|
70
|
-
auto?: boolean; // Enable auto-transform mode (default: false)
|
|
71
|
-
execute?: 'before-save' | 'after-load' | 'both'; // When to execute (default: 'both')
|
|
72
|
-
stopOnFirstError?: boolean; // Stop validation on first error (default: false)
|
|
73
|
-
}
|
|
1
|
+
import type { ColumnType } from '../../schema/column-types.js';
|
|
2
|
+
|
|
3
|
+
// Transform context provides metadata about the transformation
|
|
4
|
+
export interface TransformContext {
|
|
5
|
+
entityName: string;
|
|
6
|
+
propertyName: string;
|
|
7
|
+
columnType: ColumnType;
|
|
8
|
+
isUpdate: boolean;
|
|
9
|
+
originalValue?: unknown;
|
|
10
|
+
autoTransform: boolean; // Whether auto-correction is enabled
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Auto-transform result for validators that can fix data
|
|
14
|
+
export interface AutoTransformResult<T = unknown> {
|
|
15
|
+
success: boolean;
|
|
16
|
+
correctedValue?: T;
|
|
17
|
+
message?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Base transformer interface
|
|
21
|
+
export interface PropertyTransformer<TInput = unknown, TOutput = unknown> {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
transform(value: TInput, context: TransformContext): TOutput;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Validator interface (read-only, throws on failure)
|
|
27
|
+
export interface PropertyValidator<T = unknown> {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
validate(value: T, context: TransformContext): ValidationResult;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Sanitizer interface (mutates, never throws)
|
|
33
|
+
export interface PropertySanitizer<T = unknown> {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
sanitize(value: T, context: TransformContext): T;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Combined transformer that can validate and transform
|
|
39
|
+
export interface CompositeTransformer<TInput = unknown, TOutput = unknown>
|
|
40
|
+
extends PropertyTransformer<TInput, TOutput>,
|
|
41
|
+
PropertyValidator<TInput> {}
|
|
42
|
+
|
|
43
|
+
// Extended validator interface with auto-transform capability
|
|
44
|
+
export interface AutoTransformableValidator<T = unknown> extends PropertyValidator<T> {
|
|
45
|
+
/**
|
|
46
|
+
* Attempts to automatically correct an invalid value.
|
|
47
|
+
* Returns undefined if auto-correction is not possible.
|
|
48
|
+
*/
|
|
49
|
+
autoTransform?(value: T, context: TransformContext): AutoTransformResult<T>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Validation result
|
|
53
|
+
export interface ValidationResult {
|
|
54
|
+
isValid: boolean;
|
|
55
|
+
error?: string;
|
|
56
|
+
message?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Transformer metadata stored during decoration phase
|
|
60
|
+
export interface TransformerMetadata {
|
|
61
|
+
propertyName: string;
|
|
62
|
+
transformers: PropertyTransformer[];
|
|
63
|
+
validators: PropertyValidator[];
|
|
64
|
+
sanitizers: PropertySanitizer[];
|
|
65
|
+
executionOrder: 'before-save' | 'after-load' | 'both';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Transformer configuration options
|
|
69
|
+
export interface TransformerConfig {
|
|
70
|
+
auto?: boolean; // Enable auto-transform mode (default: false)
|
|
71
|
+
execute?: 'before-save' | 'after-load' | 'both'; // When to execute (default: 'both')
|
|
72
|
+
stopOnFirstError?: boolean; // Stop validation on first error (default: false)
|
|
73
|
+
}
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import type { CountryValidator, ValidationOptions, ValidationResult, AutoCorrectionResult } from '../country-validators.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Brazilian CEP validator
|
|
5
|
-
* Format: XXXXX-XXX (8 digits)
|
|
6
|
-
*/
|
|
7
|
-
export class CEPValidator implements CountryValidator<string> {
|
|
8
|
-
readonly countryCode = 'BR';
|
|
9
|
-
readonly identifierType = 'cep';
|
|
10
|
-
readonly name = 'br-cep';
|
|
11
|
-
|
|
12
|
-
validate(value: string, options: ValidationOptions = {}): ValidationResult {
|
|
13
|
-
const normalized = this.normalize(value);
|
|
14
|
-
|
|
15
|
-
// Validate format
|
|
16
|
-
if (!/^\d{8}$/.test(normalized)) {
|
|
17
|
-
return {
|
|
18
|
-
isValid: false,
|
|
19
|
-
error: options.errorMessage || 'CEP must contain exactly 8 numeric digits'
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
isValid: true,
|
|
25
|
-
normalizedValue: normalized,
|
|
26
|
-
formattedValue: this.format(value)
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
normalize(value: string): string {
|
|
31
|
-
return value.replace(/[^0-9]/g, '');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
format(value: string): string {
|
|
35
|
-
const normalized = this.normalize(value);
|
|
36
|
-
if (normalized.length !== 8) return value;
|
|
37
|
-
return normalized.replace(/(\d{5})(\d{3})/, '$1-$2');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
autoCorrect(value: string): AutoCorrectionResult<string> {
|
|
41
|
-
const normalized = this.normalize(value);
|
|
42
|
-
|
|
43
|
-
if (normalized.length === 8) {
|
|
44
|
-
return { success: true, correctedValue: this.format(normalized) };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (normalized.length < 8) {
|
|
48
|
-
const padded = normalized.padEnd(8, '0');
|
|
49
|
-
return { success: true, correctedValue: this.format(padded) };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const truncated = normalized.slice(0, 8);
|
|
53
|
-
return { success: true, correctedValue: this.format(truncated) };
|
|
54
|
-
}
|
|
55
|
-
}
|
|
1
|
+
import type { CountryValidator, ValidationOptions, ValidationResult, AutoCorrectionResult } from '../country-validators.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Brazilian CEP validator
|
|
5
|
+
* Format: XXXXX-XXX (8 digits)
|
|
6
|
+
*/
|
|
7
|
+
export class CEPValidator implements CountryValidator<string> {
|
|
8
|
+
readonly countryCode = 'BR';
|
|
9
|
+
readonly identifierType = 'cep';
|
|
10
|
+
readonly name = 'br-cep';
|
|
11
|
+
|
|
12
|
+
validate(value: string, options: ValidationOptions = {}): ValidationResult {
|
|
13
|
+
const normalized = this.normalize(value);
|
|
14
|
+
|
|
15
|
+
// Validate format
|
|
16
|
+
if (!/^\d{8}$/.test(normalized)) {
|
|
17
|
+
return {
|
|
18
|
+
isValid: false,
|
|
19
|
+
error: options.errorMessage || 'CEP must contain exactly 8 numeric digits'
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
isValid: true,
|
|
25
|
+
normalizedValue: normalized,
|
|
26
|
+
formattedValue: this.format(value)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
normalize(value: string): string {
|
|
31
|
+
return value.replace(/[^0-9]/g, '');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
format(value: string): string {
|
|
35
|
+
const normalized = this.normalize(value);
|
|
36
|
+
if (normalized.length !== 8) return value;
|
|
37
|
+
return normalized.replace(/(\d{5})(\d{3})/, '$1-$2');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
autoCorrect(value: string): AutoCorrectionResult<string> {
|
|
41
|
+
const normalized = this.normalize(value);
|
|
42
|
+
|
|
43
|
+
if (normalized.length === 8) {
|
|
44
|
+
return { success: true, correctedValue: this.format(normalized) };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (normalized.length < 8) {
|
|
48
|
+
const padded = normalized.padEnd(8, '0');
|
|
49
|
+
return { success: true, correctedValue: this.format(padded) };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const truncated = normalized.slice(0, 8);
|
|
53
|
+
return { success: true, correctedValue: this.format(truncated) };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
import type { CountryValidator, ValidationOptions, ValidationResult, AutoCorrectionResult } from '../country-validators.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Brazilian CNPJ validator
|
|
5
|
-
* Format: XX.XXX.XXX/XXXX-XX (14 digits)
|
|
6
|
-
* Checksum: Mod 11 algorithm
|
|
7
|
-
*/
|
|
8
|
-
export class CNPJValidator implements CountryValidator<string> {
|
|
9
|
-
readonly countryCode = 'BR';
|
|
10
|
-
readonly identifierType = 'cnpj';
|
|
11
|
-
readonly name = 'br-cnpj';
|
|
12
|
-
|
|
13
|
-
validate(value: string, options: ValidationOptions = {}): ValidationResult {
|
|
14
|
-
const normalized = this.normalize(value);
|
|
15
|
-
|
|
16
|
-
// Validate format
|
|
17
|
-
if (!/^\d{14}$/.test(normalized)) {
|
|
18
|
-
return {
|
|
19
|
-
isValid: false,
|
|
20
|
-
error: options.errorMessage || 'CNPJ must contain exactly 14 numeric digits'
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Check for known invalid CNPJs
|
|
25
|
-
if (this.isKnownInvalid(normalized) && options.strict !== false) {
|
|
26
|
-
return {
|
|
27
|
-
isValid: false,
|
|
28
|
-
error: options.errorMessage || 'Invalid CNPJ number'
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Validate checksum
|
|
33
|
-
if (!this.validateChecksum(normalized)) {
|
|
34
|
-
return {
|
|
35
|
-
isValid: false,
|
|
36
|
-
error: options.errorMessage || 'Invalid CNPJ checksum'
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
isValid: true,
|
|
42
|
-
normalizedValue: normalized,
|
|
43
|
-
formattedValue: this.format(value)
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
normalize(value: string): string {
|
|
48
|
-
return value.replace(/[^0-9]/g, '');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
format(value: string): string {
|
|
52
|
-
const normalized = this.normalize(value);
|
|
53
|
-
if (normalized.length !== 14) return value;
|
|
54
|
-
return normalized.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, '$1.$2.$3/$4-$5');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
autoCorrect(value: string): AutoCorrectionResult<string> {
|
|
58
|
-
const normalized = this.normalize(value);
|
|
59
|
-
|
|
60
|
-
if (normalized.length === 14) {
|
|
61
|
-
return { success: true, correctedValue: this.format(normalized) };
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (normalized.length < 14) {
|
|
65
|
-
const padded = normalized.padEnd(14, '0');
|
|
66
|
-
return { success: true, correctedValue: this.format(padded) };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const truncated = normalized.slice(0, 14);
|
|
70
|
-
return { success: true, correctedValue: this.format(truncated) };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private isKnownInvalid(cnpj: string): boolean {
|
|
74
|
-
// Check for CNPJs with all digits the same (e.g., 00.000.000/0000-00)
|
|
75
|
-
return /^(\d)\1{13}$/.test(cnpj);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private validateChecksum(cnpj: string): boolean {
|
|
79
|
-
const digits = cnpj.split('').map(Number);
|
|
80
|
-
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
81
|
-
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
82
|
-
|
|
83
|
-
// Calculate first check digit
|
|
84
|
-
let sum = 0;
|
|
85
|
-
for (let i = 0; i < 12; i++) {
|
|
86
|
-
sum += digits[i] * weights1[i];
|
|
87
|
-
}
|
|
88
|
-
let check1 = sum % 11;
|
|
89
|
-
check1 = check1 < 2 ? 0 : 11 - check1;
|
|
90
|
-
|
|
91
|
-
if (check1 !== digits[12]) {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Calculate second check digit
|
|
96
|
-
sum = 0;
|
|
97
|
-
for (let i = 0; i < 13; i++) {
|
|
98
|
-
sum += digits[i] * weights2[i];
|
|
99
|
-
}
|
|
100
|
-
let check2 = sum % 11;
|
|
101
|
-
check2 = check2 < 2 ? 0 : 11 - check2;
|
|
102
|
-
|
|
103
|
-
return check2 === digits[13];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
1
|
+
import type { CountryValidator, ValidationOptions, ValidationResult, AutoCorrectionResult } from '../country-validators.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Brazilian CNPJ validator
|
|
5
|
+
* Format: XX.XXX.XXX/XXXX-XX (14 digits)
|
|
6
|
+
* Checksum: Mod 11 algorithm
|
|
7
|
+
*/
|
|
8
|
+
export class CNPJValidator implements CountryValidator<string> {
|
|
9
|
+
readonly countryCode = 'BR';
|
|
10
|
+
readonly identifierType = 'cnpj';
|
|
11
|
+
readonly name = 'br-cnpj';
|
|
12
|
+
|
|
13
|
+
validate(value: string, options: ValidationOptions = {}): ValidationResult {
|
|
14
|
+
const normalized = this.normalize(value);
|
|
15
|
+
|
|
16
|
+
// Validate format
|
|
17
|
+
if (!/^\d{14}$/.test(normalized)) {
|
|
18
|
+
return {
|
|
19
|
+
isValid: false,
|
|
20
|
+
error: options.errorMessage || 'CNPJ must contain exactly 14 numeric digits'
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Check for known invalid CNPJs
|
|
25
|
+
if (this.isKnownInvalid(normalized) && options.strict !== false) {
|
|
26
|
+
return {
|
|
27
|
+
isValid: false,
|
|
28
|
+
error: options.errorMessage || 'Invalid CNPJ number'
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Validate checksum
|
|
33
|
+
if (!this.validateChecksum(normalized)) {
|
|
34
|
+
return {
|
|
35
|
+
isValid: false,
|
|
36
|
+
error: options.errorMessage || 'Invalid CNPJ checksum'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
isValid: true,
|
|
42
|
+
normalizedValue: normalized,
|
|
43
|
+
formattedValue: this.format(value)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
normalize(value: string): string {
|
|
48
|
+
return value.replace(/[^0-9]/g, '');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
format(value: string): string {
|
|
52
|
+
const normalized = this.normalize(value);
|
|
53
|
+
if (normalized.length !== 14) return value;
|
|
54
|
+
return normalized.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, '$1.$2.$3/$4-$5');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
autoCorrect(value: string): AutoCorrectionResult<string> {
|
|
58
|
+
const normalized = this.normalize(value);
|
|
59
|
+
|
|
60
|
+
if (normalized.length === 14) {
|
|
61
|
+
return { success: true, correctedValue: this.format(normalized) };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (normalized.length < 14) {
|
|
65
|
+
const padded = normalized.padEnd(14, '0');
|
|
66
|
+
return { success: true, correctedValue: this.format(padded) };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const truncated = normalized.slice(0, 14);
|
|
70
|
+
return { success: true, correctedValue: this.format(truncated) };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private isKnownInvalid(cnpj: string): boolean {
|
|
74
|
+
// Check for CNPJs with all digits the same (e.g., 00.000.000/0000-00)
|
|
75
|
+
return /^(\d)\1{13}$/.test(cnpj);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private validateChecksum(cnpj: string): boolean {
|
|
79
|
+
const digits = cnpj.split('').map(Number);
|
|
80
|
+
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
81
|
+
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
82
|
+
|
|
83
|
+
// Calculate first check digit
|
|
84
|
+
let sum = 0;
|
|
85
|
+
for (let i = 0; i < 12; i++) {
|
|
86
|
+
sum += digits[i] * weights1[i];
|
|
87
|
+
}
|
|
88
|
+
let check1 = sum % 11;
|
|
89
|
+
check1 = check1 < 2 ? 0 : 11 - check1;
|
|
90
|
+
|
|
91
|
+
if (check1 !== digits[12]) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Calculate second check digit
|
|
96
|
+
sum = 0;
|
|
97
|
+
for (let i = 0; i < 13; i++) {
|
|
98
|
+
sum += digits[i] * weights2[i];
|
|
99
|
+
}
|
|
100
|
+
let check2 = sum % 11;
|
|
101
|
+
check2 = check2 < 2 ? 0 : 11 - check2;
|
|
102
|
+
|
|
103
|
+
return check2 === digits[13];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -1,103 +1,103 @@
|
|
|
1
|
-
import type { CountryValidator, ValidationOptions, ValidationResult, AutoCorrectionResult } from '../country-validators.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Brazilian CPF validator
|
|
5
|
-
* Format: XXX.XXX.XXX-XX (11 digits)
|
|
6
|
-
* Checksum: Mod 11 algorithm
|
|
7
|
-
*/
|
|
8
|
-
export class CPFValidator implements CountryValidator<string> {
|
|
9
|
-
readonly countryCode = 'BR';
|
|
10
|
-
readonly identifierType = 'cpf';
|
|
11
|
-
readonly name = 'br-cpf';
|
|
12
|
-
|
|
13
|
-
validate(value: string, options: ValidationOptions = {}): ValidationResult {
|
|
14
|
-
const normalized = this.normalize(value);
|
|
15
|
-
|
|
16
|
-
// Validate format
|
|
17
|
-
if (!/^\d{11}$/.test(normalized)) {
|
|
18
|
-
return {
|
|
19
|
-
isValid: false,
|
|
20
|
-
error: options.errorMessage || 'CPF must contain exactly 11 numeric digits'
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Check for known invalid CPFs
|
|
25
|
-
if (this.isKnownInvalid(normalized) && options.strict !== false) {
|
|
26
|
-
return {
|
|
27
|
-
isValid: false,
|
|
28
|
-
error: options.errorMessage || 'Invalid CPF number'
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Validate checksum
|
|
33
|
-
if (!this.validateChecksum(normalized)) {
|
|
34
|
-
return {
|
|
35
|
-
isValid: false,
|
|
36
|
-
error: options.errorMessage || 'Invalid CPF checksum'
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
isValid: true,
|
|
42
|
-
normalizedValue: normalized,
|
|
43
|
-
formattedValue: this.format(value)
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
normalize(value: string): string {
|
|
48
|
-
return value.replace(/[^0-9]/g, '');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
format(value: string): string {
|
|
52
|
-
const normalized = this.normalize(value);
|
|
53
|
-
if (normalized.length !== 11) return value;
|
|
54
|
-
return normalized.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
autoCorrect(value: string): AutoCorrectionResult<string> {
|
|
58
|
-
const normalized = this.normalize(value);
|
|
59
|
-
|
|
60
|
-
if (normalized.length === 11) {
|
|
61
|
-
return { success: true, correctedValue: this.format(normalized) };
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (normalized.length < 11) {
|
|
65
|
-
const padded = normalized.padEnd(11, '0');
|
|
66
|
-
return { success: true, correctedValue: this.format(padded) };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const truncated = normalized.slice(0, 11);
|
|
70
|
-
return { success: true, correctedValue: this.format(truncated) };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private isKnownInvalid(cpf: string): boolean {
|
|
74
|
-
// Check for CPFs with all digits the same (e.g., 111.111.111-11)
|
|
75
|
-
return /^(\d)\1{10}$/.test(cpf);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private validateChecksum(cpf: string): boolean {
|
|
79
|
-
const digits = cpf.split('').map(Number);
|
|
80
|
-
|
|
81
|
-
// Calculate first check digit
|
|
82
|
-
let sum = 0;
|
|
83
|
-
for (let i = 0; i < 9; i++) {
|
|
84
|
-
sum += digits[i] * (10 - i);
|
|
85
|
-
}
|
|
86
|
-
let check1 = sum % 11;
|
|
87
|
-
check1 = check1 < 2 ? 0 : 11 - check1;
|
|
88
|
-
|
|
89
|
-
if (check1 !== digits[9]) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Calculate second check digit
|
|
94
|
-
sum = 0;
|
|
95
|
-
for (let i = 0; i < 10; i++) {
|
|
96
|
-
sum += digits[i] * (11 - i);
|
|
97
|
-
}
|
|
98
|
-
let check2 = sum % 11;
|
|
99
|
-
check2 = check2 < 2 ? 0 : 11 - check2;
|
|
100
|
-
|
|
101
|
-
return check2 === digits[10];
|
|
102
|
-
}
|
|
103
|
-
}
|
|
1
|
+
import type { CountryValidator, ValidationOptions, ValidationResult, AutoCorrectionResult } from '../country-validators.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Brazilian CPF validator
|
|
5
|
+
* Format: XXX.XXX.XXX-XX (11 digits)
|
|
6
|
+
* Checksum: Mod 11 algorithm
|
|
7
|
+
*/
|
|
8
|
+
export class CPFValidator implements CountryValidator<string> {
|
|
9
|
+
readonly countryCode = 'BR';
|
|
10
|
+
readonly identifierType = 'cpf';
|
|
11
|
+
readonly name = 'br-cpf';
|
|
12
|
+
|
|
13
|
+
validate(value: string, options: ValidationOptions = {}): ValidationResult {
|
|
14
|
+
const normalized = this.normalize(value);
|
|
15
|
+
|
|
16
|
+
// Validate format
|
|
17
|
+
if (!/^\d{11}$/.test(normalized)) {
|
|
18
|
+
return {
|
|
19
|
+
isValid: false,
|
|
20
|
+
error: options.errorMessage || 'CPF must contain exactly 11 numeric digits'
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Check for known invalid CPFs
|
|
25
|
+
if (this.isKnownInvalid(normalized) && options.strict !== false) {
|
|
26
|
+
return {
|
|
27
|
+
isValid: false,
|
|
28
|
+
error: options.errorMessage || 'Invalid CPF number'
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Validate checksum
|
|
33
|
+
if (!this.validateChecksum(normalized)) {
|
|
34
|
+
return {
|
|
35
|
+
isValid: false,
|
|
36
|
+
error: options.errorMessage || 'Invalid CPF checksum'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
isValid: true,
|
|
42
|
+
normalizedValue: normalized,
|
|
43
|
+
formattedValue: this.format(value)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
normalize(value: string): string {
|
|
48
|
+
return value.replace(/[^0-9]/g, '');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
format(value: string): string {
|
|
52
|
+
const normalized = this.normalize(value);
|
|
53
|
+
if (normalized.length !== 11) return value;
|
|
54
|
+
return normalized.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
autoCorrect(value: string): AutoCorrectionResult<string> {
|
|
58
|
+
const normalized = this.normalize(value);
|
|
59
|
+
|
|
60
|
+
if (normalized.length === 11) {
|
|
61
|
+
return { success: true, correctedValue: this.format(normalized) };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (normalized.length < 11) {
|
|
65
|
+
const padded = normalized.padEnd(11, '0');
|
|
66
|
+
return { success: true, correctedValue: this.format(padded) };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const truncated = normalized.slice(0, 11);
|
|
70
|
+
return { success: true, correctedValue: this.format(truncated) };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private isKnownInvalid(cpf: string): boolean {
|
|
74
|
+
// Check for CPFs with all digits the same (e.g., 111.111.111-11)
|
|
75
|
+
return /^(\d)\1{10}$/.test(cpf);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private validateChecksum(cpf: string): boolean {
|
|
79
|
+
const digits = cpf.split('').map(Number);
|
|
80
|
+
|
|
81
|
+
// Calculate first check digit
|
|
82
|
+
let sum = 0;
|
|
83
|
+
for (let i = 0; i < 9; i++) {
|
|
84
|
+
sum += digits[i] * (10 - i);
|
|
85
|
+
}
|
|
86
|
+
let check1 = sum % 11;
|
|
87
|
+
check1 = check1 < 2 ? 0 : 11 - check1;
|
|
88
|
+
|
|
89
|
+
if (check1 !== digits[9]) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Calculate second check digit
|
|
94
|
+
sum = 0;
|
|
95
|
+
for (let i = 0; i < 10; i++) {
|
|
96
|
+
sum += digits[i] * (11 - i);
|
|
97
|
+
}
|
|
98
|
+
let check2 = sum % 11;
|
|
99
|
+
check2 = check2 < 2 ? 0 : 11 - check2;
|
|
100
|
+
|
|
101
|
+
return check2 === digits[10];
|
|
102
|
+
}
|
|
103
|
+
}
|