chilean-rut-formatter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -0
- package/dist/index.d.mts +119 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Chilean RUT Formatter
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/chilean-rut-formatter)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
High-performance TypeScript library for formatting and validating Chilean RUTs (Rol Único Tributario).
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ✅ **Validate** RUTs using the official Module 11 algorithm
|
|
11
|
+
- ✅ **Format** with customizable options (dots, dashes, case)
|
|
12
|
+
- ✅ **Clean** and sanitize user input
|
|
13
|
+
- ✅ **TypeScript** - Full type definitions included
|
|
14
|
+
- ✅ **Zero dependencies** - Lightweight and fast
|
|
15
|
+
- ✅ **Secure** - Input sanitization and DoS protection
|
|
16
|
+
- ✅ **Tree-shakeable** - ESM and CJS support
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install chilean-rut-formatter
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Validate a RUT
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { validateRut, isValidRut } from 'chilean-rut-formatter';
|
|
30
|
+
|
|
31
|
+
// Full validation with details
|
|
32
|
+
const result = validateRut('12.345.678-5');
|
|
33
|
+
// { isValid: true, rut: '123456785' }
|
|
34
|
+
|
|
35
|
+
const invalid = validateRut('12345678-0');
|
|
36
|
+
// { isValid: false, error: 'Invalid verification digit' }
|
|
37
|
+
|
|
38
|
+
// Simple boolean check
|
|
39
|
+
isValidRut('12.345.678-5'); // true
|
|
40
|
+
isValidRut('12345678-0'); // false
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Format a RUT
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { formatRut } from 'chilean-rut-formatter';
|
|
47
|
+
|
|
48
|
+
// Default: with dots and dash
|
|
49
|
+
formatRut('123456785'); // '12.345.678-5'
|
|
50
|
+
formatRut('12345678K'); // '12.345.678-K'
|
|
51
|
+
|
|
52
|
+
// Custom options
|
|
53
|
+
formatRut('123456785', { dots: false }); // '12345678-5'
|
|
54
|
+
formatRut('123456785', { dash: false }); // '12.345.6785'
|
|
55
|
+
formatRut('12345678K', { uppercase: false }); // '12.345.678-k'
|
|
56
|
+
|
|
57
|
+
// Returns empty string if RUT is invalid
|
|
58
|
+
formatRut('12345678-0'); // ''
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Format Partial Input (Real-time)
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { formatRutPartial } from 'chilean-rut-formatter';
|
|
65
|
+
|
|
66
|
+
// Great for live formatting as user types
|
|
67
|
+
formatRutPartial('1'); // '1'
|
|
68
|
+
formatRutPartial('12'); // '1-2'
|
|
69
|
+
formatRutPartial('12345'); // '1.234-5'
|
|
70
|
+
formatRutPartial('123456789'); // '12.345.678-9'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Clean a RUT
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { cleanRut } from 'chilean-rut-formatter';
|
|
77
|
+
|
|
78
|
+
cleanRut('12.345.678-9'); // '123456789'
|
|
79
|
+
cleanRut('12 345 678-k'); // '12345678K'
|
|
80
|
+
cleanRut(' 12#345$678%9 '); // '123456789'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Calculate Verification Digit
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { calculateVerificationDigit } from 'chilean-rut-formatter';
|
|
87
|
+
|
|
88
|
+
calculateVerificationDigit('12345678'); // '5'
|
|
89
|
+
calculateVerificationDigit('16612277'); // 'K'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### `validateRut(rut: string): ValidationResult`
|
|
95
|
+
|
|
96
|
+
Validates a Chilean RUT and returns detailed result.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
interface ValidationResult {
|
|
100
|
+
isValid: boolean;
|
|
101
|
+
rut?: string; // Cleaned RUT if valid
|
|
102
|
+
error?: string; // Error message if invalid
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `isValidRut(rut: string): boolean`
|
|
107
|
+
|
|
108
|
+
Simple boolean validation check.
|
|
109
|
+
|
|
110
|
+
### `formatRut(rut: string, options?: FormatOptions): string`
|
|
111
|
+
|
|
112
|
+
Formats a valid RUT. Returns empty string if RUT is invalid.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
interface FormatOptions {
|
|
116
|
+
dots?: boolean; // Include dots (default: true)
|
|
117
|
+
dash?: boolean; // Include dash (default: true)
|
|
118
|
+
uppercase?: boolean; // Uppercase K (default: true)
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `formatRutPartial(rut: string, options?: FormatOptions): string`
|
|
123
|
+
|
|
124
|
+
Formats partial RUT input (useful for real-time formatting).
|
|
125
|
+
|
|
126
|
+
### `cleanRut(input: string): string`
|
|
127
|
+
|
|
128
|
+
Removes all non-valid characters from input.
|
|
129
|
+
|
|
130
|
+
### `calculateVerificationDigit(rutBody: string): string`
|
|
131
|
+
|
|
132
|
+
Calculates the verification digit for a RUT body.
|
|
133
|
+
|
|
134
|
+
## Security
|
|
135
|
+
|
|
136
|
+
- **Input Sanitization**: All inputs are cleaned before processing
|
|
137
|
+
- **DoS Protection**: Maximum input length enforced (50 chars)
|
|
138
|
+
- **No eval/Function**: No dynamic code execution
|
|
139
|
+
- **TypeScript Strict Mode**: Full type safety
|
|
140
|
+
|
|
141
|
+
## Performance
|
|
142
|
+
|
|
143
|
+
- **Zero dependencies**: No external library overhead
|
|
144
|
+
- **Pre-compiled regex**: Patterns compiled once at module load
|
|
145
|
+
- **Early returns**: Fast failure for invalid inputs
|
|
146
|
+
- **Minimal allocations**: Optimized for performance
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for formatting a RUT
|
|
3
|
+
*/
|
|
4
|
+
interface FormatOptions {
|
|
5
|
+
/** Include dots as thousand separators (e.g., 12.345.678-9). Default: true */
|
|
6
|
+
dots?: boolean;
|
|
7
|
+
/** Include dash before verification digit. Default: true */
|
|
8
|
+
dash?: boolean;
|
|
9
|
+
/** Use uppercase for 'K' verification digit. Default: true */
|
|
10
|
+
uppercase?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of RUT validation
|
|
14
|
+
*/
|
|
15
|
+
interface ValidationResult {
|
|
16
|
+
/** Whether the RUT is valid */
|
|
17
|
+
isValid: boolean;
|
|
18
|
+
/** Clean RUT string (numbers + verification digit) if valid */
|
|
19
|
+
rut?: string;
|
|
20
|
+
/** Error message if invalid */
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parsed RUT components
|
|
25
|
+
*/
|
|
26
|
+
interface ParsedRut {
|
|
27
|
+
/** RUT body (numbers only, without verification digit) */
|
|
28
|
+
body: string;
|
|
29
|
+
/** Verification digit (0-9 or K) */
|
|
30
|
+
verificationDigit: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Cleans a RUT string by removing all non-valid characters.
|
|
35
|
+
* Keeps only numbers and 'K'/'k'.
|
|
36
|
+
*
|
|
37
|
+
* @param input - Raw RUT input string
|
|
38
|
+
* @returns Cleaned RUT string with only valid characters
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* cleanRut('12.345.678-9') // '123456789'
|
|
42
|
+
* cleanRut('12345678-K') // '12345678K'
|
|
43
|
+
* cleanRut(' 12-345-678.9 ') // '123456789'
|
|
44
|
+
*/
|
|
45
|
+
declare function cleanRut(input: string): string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validates a Chilean RUT (Rol Único Tributario).
|
|
49
|
+
*
|
|
50
|
+
* Uses the official Module 11 algorithm to verify the check digit.
|
|
51
|
+
*
|
|
52
|
+
* @param rut - RUT string to validate (can include dots, dashes, spaces)
|
|
53
|
+
* @returns Validation result with isValid flag and cleaned RUT if valid
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* validateRut('12.345.678-5') // { isValid: true, rut: '123456785' }
|
|
57
|
+
* validateRut('12345678-5') // { isValid: true, rut: '123456785' }
|
|
58
|
+
* validateRut('12345678-0') // { isValid: false, error: 'Invalid verification digit' }
|
|
59
|
+
* validateRut('') // { isValid: false, error: 'RUT is required' }
|
|
60
|
+
*/
|
|
61
|
+
declare function validateRut(rut: string): ValidationResult;
|
|
62
|
+
/**
|
|
63
|
+
* Simple boolean check for RUT validity.
|
|
64
|
+
*
|
|
65
|
+
* @param rut - RUT string to validate
|
|
66
|
+
* @returns true if RUT is valid, false otherwise
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* isValidRut('12.345.678-5') // true
|
|
70
|
+
* isValidRut('12345678-0') // false
|
|
71
|
+
*/
|
|
72
|
+
declare function isValidRut(rut: string): boolean;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Formats a Chilean RUT with the specified options.
|
|
76
|
+
*
|
|
77
|
+
* By default, formats as: 12.345.678-9
|
|
78
|
+
*
|
|
79
|
+
* @param rut - RUT string to format (can include dots, dashes, spaces)
|
|
80
|
+
* @param options - Formatting options
|
|
81
|
+
* @returns Formatted RUT string, or empty string if invalid
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* formatRut('123456785') // '12.345.678-5'
|
|
85
|
+
* formatRut('123456785', { dots: false }) // '12345678-5'
|
|
86
|
+
* formatRut('123456785', { dash: false }) // '12.345.6785'
|
|
87
|
+
* formatRut('12345678K', { uppercase: false }) // '12.345.678-k'
|
|
88
|
+
*/
|
|
89
|
+
declare function formatRut(rut: string, options?: FormatOptions): string;
|
|
90
|
+
/**
|
|
91
|
+
* Formats a RUT without validation (use with caution).
|
|
92
|
+
* Useful when you need to format user input as they type.
|
|
93
|
+
*
|
|
94
|
+
* @param rut - RUT string to format
|
|
95
|
+
* @param options - Formatting options
|
|
96
|
+
* @returns Formatted RUT string
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* formatRutPartial('12345') // '12.345'
|
|
100
|
+
* formatRutPartial('123456789') // '12.345.678-9'
|
|
101
|
+
*/
|
|
102
|
+
declare function formatRutPartial(rut: string, options?: FormatOptions): string;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Calculates the verification digit for a RUT body using Module 11 algorithm.
|
|
106
|
+
*
|
|
107
|
+
* @param rutBody - RUT body (numbers only, without verification digit)
|
|
108
|
+
* @returns Calculated verification digit ('0'-'9' or 'K')
|
|
109
|
+
*/
|
|
110
|
+
declare function calculateVerificationDigit(rutBody: string): string;
|
|
111
|
+
/**
|
|
112
|
+
* Parses a cleaned RUT string into body and verification digit.
|
|
113
|
+
*
|
|
114
|
+
* @param cleanedRut - Cleaned RUT string (only numbers and K)
|
|
115
|
+
* @returns Parsed RUT object or null if invalid format
|
|
116
|
+
*/
|
|
117
|
+
declare function parseRut(cleanedRut: string): ParsedRut | null;
|
|
118
|
+
|
|
119
|
+
export { type FormatOptions, type ParsedRut, type ValidationResult, calculateVerificationDigit, cleanRut, formatRut, formatRutPartial, isValidRut, parseRut, validateRut };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for formatting a RUT
|
|
3
|
+
*/
|
|
4
|
+
interface FormatOptions {
|
|
5
|
+
/** Include dots as thousand separators (e.g., 12.345.678-9). Default: true */
|
|
6
|
+
dots?: boolean;
|
|
7
|
+
/** Include dash before verification digit. Default: true */
|
|
8
|
+
dash?: boolean;
|
|
9
|
+
/** Use uppercase for 'K' verification digit. Default: true */
|
|
10
|
+
uppercase?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of RUT validation
|
|
14
|
+
*/
|
|
15
|
+
interface ValidationResult {
|
|
16
|
+
/** Whether the RUT is valid */
|
|
17
|
+
isValid: boolean;
|
|
18
|
+
/** Clean RUT string (numbers + verification digit) if valid */
|
|
19
|
+
rut?: string;
|
|
20
|
+
/** Error message if invalid */
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parsed RUT components
|
|
25
|
+
*/
|
|
26
|
+
interface ParsedRut {
|
|
27
|
+
/** RUT body (numbers only, without verification digit) */
|
|
28
|
+
body: string;
|
|
29
|
+
/** Verification digit (0-9 or K) */
|
|
30
|
+
verificationDigit: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Cleans a RUT string by removing all non-valid characters.
|
|
35
|
+
* Keeps only numbers and 'K'/'k'.
|
|
36
|
+
*
|
|
37
|
+
* @param input - Raw RUT input string
|
|
38
|
+
* @returns Cleaned RUT string with only valid characters
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* cleanRut('12.345.678-9') // '123456789'
|
|
42
|
+
* cleanRut('12345678-K') // '12345678K'
|
|
43
|
+
* cleanRut(' 12-345-678.9 ') // '123456789'
|
|
44
|
+
*/
|
|
45
|
+
declare function cleanRut(input: string): string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validates a Chilean RUT (Rol Único Tributario).
|
|
49
|
+
*
|
|
50
|
+
* Uses the official Module 11 algorithm to verify the check digit.
|
|
51
|
+
*
|
|
52
|
+
* @param rut - RUT string to validate (can include dots, dashes, spaces)
|
|
53
|
+
* @returns Validation result with isValid flag and cleaned RUT if valid
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* validateRut('12.345.678-5') // { isValid: true, rut: '123456785' }
|
|
57
|
+
* validateRut('12345678-5') // { isValid: true, rut: '123456785' }
|
|
58
|
+
* validateRut('12345678-0') // { isValid: false, error: 'Invalid verification digit' }
|
|
59
|
+
* validateRut('') // { isValid: false, error: 'RUT is required' }
|
|
60
|
+
*/
|
|
61
|
+
declare function validateRut(rut: string): ValidationResult;
|
|
62
|
+
/**
|
|
63
|
+
* Simple boolean check for RUT validity.
|
|
64
|
+
*
|
|
65
|
+
* @param rut - RUT string to validate
|
|
66
|
+
* @returns true if RUT is valid, false otherwise
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* isValidRut('12.345.678-5') // true
|
|
70
|
+
* isValidRut('12345678-0') // false
|
|
71
|
+
*/
|
|
72
|
+
declare function isValidRut(rut: string): boolean;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Formats a Chilean RUT with the specified options.
|
|
76
|
+
*
|
|
77
|
+
* By default, formats as: 12.345.678-9
|
|
78
|
+
*
|
|
79
|
+
* @param rut - RUT string to format (can include dots, dashes, spaces)
|
|
80
|
+
* @param options - Formatting options
|
|
81
|
+
* @returns Formatted RUT string, or empty string if invalid
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* formatRut('123456785') // '12.345.678-5'
|
|
85
|
+
* formatRut('123456785', { dots: false }) // '12345678-5'
|
|
86
|
+
* formatRut('123456785', { dash: false }) // '12.345.6785'
|
|
87
|
+
* formatRut('12345678K', { uppercase: false }) // '12.345.678-k'
|
|
88
|
+
*/
|
|
89
|
+
declare function formatRut(rut: string, options?: FormatOptions): string;
|
|
90
|
+
/**
|
|
91
|
+
* Formats a RUT without validation (use with caution).
|
|
92
|
+
* Useful when you need to format user input as they type.
|
|
93
|
+
*
|
|
94
|
+
* @param rut - RUT string to format
|
|
95
|
+
* @param options - Formatting options
|
|
96
|
+
* @returns Formatted RUT string
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* formatRutPartial('12345') // '12.345'
|
|
100
|
+
* formatRutPartial('123456789') // '12.345.678-9'
|
|
101
|
+
*/
|
|
102
|
+
declare function formatRutPartial(rut: string, options?: FormatOptions): string;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Calculates the verification digit for a RUT body using Module 11 algorithm.
|
|
106
|
+
*
|
|
107
|
+
* @param rutBody - RUT body (numbers only, without verification digit)
|
|
108
|
+
* @returns Calculated verification digit ('0'-'9' or 'K')
|
|
109
|
+
*/
|
|
110
|
+
declare function calculateVerificationDigit(rutBody: string): string;
|
|
111
|
+
/**
|
|
112
|
+
* Parses a cleaned RUT string into body and verification digit.
|
|
113
|
+
*
|
|
114
|
+
* @param cleanedRut - Cleaned RUT string (only numbers and K)
|
|
115
|
+
* @returns Parsed RUT object or null if invalid format
|
|
116
|
+
*/
|
|
117
|
+
declare function parseRut(cleanedRut: string): ParsedRut | null;
|
|
118
|
+
|
|
119
|
+
export { type FormatOptions, type ParsedRut, type ValidationResult, calculateVerificationDigit, cleanRut, formatRut, formatRutPartial, isValidRut, parseRut, validateRut };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var m=/[^0-9kK]/g;function l(t){return typeof t!="string"?"":(t.length>50&&(t=t.slice(0,50)),t.replace(m,"").toUpperCase())}function c(t){let o=[2,3,4,5,6,7],r=0,e=0;for(let a=t.length-1;a>=0;a--){let s=parseInt(t[a],10);r+=s*o[e],e=(e+1)%6;}let n=11-r%11;return n===11?"0":n===10?"K":n.toString()}function u(t){if(t.length<2)return null;let o=t.slice(-1),r=t.slice(0,-1);return !/^\d+$/.test(r)||!/^[0-9K]$/.test(o)?null:{body:r,verificationDigit:o}}var R=2,y=9;function f(t){if(!t||typeof t!="string")return {isValid:false,error:"RUT is required"};let o=l(t);if(o.length<R)return {isValid:false,error:"RUT is too short"};if(o.length>y)return {isValid:false,error:"RUT is too long"};let r=u(o);if(!r)return {isValid:false,error:"Invalid RUT format"};let e=c(r.body);return r.verificationDigit!==e?{isValid:false,error:"Invalid verification digit"}:{isValid:true,rut:o}}function T(t){return f(t).isValid}var p=/\B(?=(\d{3})+(?!\d))/g,d={dots:true,dash:true,uppercase:true};function V(t,o={}){let r={...d,...o},e=l(t),i=u(e);if(!i)return "";let n=c(i.body);if(i.verificationDigit!==n)return "";let a=i.body;r.dots&&(a=i.body.replace(p,"."));let s=i.verificationDigit;r.uppercase||(s=s.toLowerCase());let g=r.dash?"-":"";return `${a}${g}${s}`}function x(t,o={}){let r={...d,...o},e=l(t);if(e.length===0)return "";let i,n;if(e.length>1){let s=e.slice(-1);/[0-9K]/.test(s)?(i=e.slice(0,-1),n=r.uppercase?s:s.toLowerCase()):(i=e,n="");}else i=e,n="";let a=i;if(r.dots&&i.length>0&&(a=i.replace(p,".")),n){let s=r.dash?"-":"";return `${a}${s}${n}`}return a}exports.calculateVerificationDigit=c;exports.cleanRut=l;exports.formatRut=V;exports.formatRutPartial=x;exports.isValidRut=T;exports.parseRut=u;exports.validateRut=f;//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/clean.ts","../src/utils.ts","../src/validate.ts","../src/format.ts"],"names":["CLEAN_REGEX","cleanRut","input","calculateVerificationDigit","rutBody","multipliers","sum","multiplierIndex","i","digit","result","parseRut","cleanedRut","verificationDigit","body","MIN_RUT_LENGTH","MAX_RUT_LENGTH","validateRut","rut","cleaned","parsed","expectedDigit","isValidRut","DOTS_REGEX","DEFAULT_OPTIONS","formatRut","options","opts","formattedBody","dv","separator","formatRutPartial","lastChar"],"mappings":"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","file":"index.js","sourcesContent":["// Pre-compiled regex for maximum performance\nconst CLEAN_REGEX = /[^0-9kK]/g;\n\n// Maximum allowed input length for security (prevents DoS)\nconst MAX_INPUT_LENGTH = 50;\n\n/**\n * Cleans a RUT string by removing all non-valid characters.\n * Keeps only numbers and 'K'/'k'.\n * \n * @param input - Raw RUT input string\n * @returns Cleaned RUT string with only valid characters\n * \n * @example\n * cleanRut('12.345.678-9') // '123456789'\n * cleanRut('12345678-K') // '12345678K'\n * cleanRut(' 12-345-678.9 ') // '123456789'\n */\nexport function cleanRut(input: string): string {\n // Security: handle non-string inputs gracefully\n if (typeof input !== 'string') {\n return '';\n }\n\n // Security: prevent DoS with extremely long inputs\n if (input.length > MAX_INPUT_LENGTH) {\n input = input.slice(0, MAX_INPUT_LENGTH);\n }\n\n // Remove all non-valid characters and convert to uppercase\n return input.replace(CLEAN_REGEX, '').toUpperCase();\n}\n","import type { ParsedRut } from './types';\n\n/**\n * Calculates the verification digit for a RUT body using Module 11 algorithm.\n * \n * @param rutBody - RUT body (numbers only, without verification digit)\n * @returns Calculated verification digit ('0'-'9' or 'K')\n */\nexport function calculateVerificationDigit(rutBody: string): string {\n // Multiplier sequence for Module 11 algorithm\n const multipliers = [2, 3, 4, 5, 6, 7];\n\n let sum = 0;\n let multiplierIndex = 0;\n\n // Process digits from right to left\n for (let i = rutBody.length - 1; i >= 0; i--) {\n const digit = parseInt(rutBody[i], 10);\n sum += digit * multipliers[multiplierIndex];\n multiplierIndex = (multiplierIndex + 1) % 6; // Cycle through multipliers\n }\n\n // Calculate verification digit\n const remainder = sum % 11;\n const result = 11 - remainder;\n\n // Convert result to verification digit\n if (result === 11) return '0';\n if (result === 10) return 'K';\n return result.toString();\n}\n\n/**\n * Parses a cleaned RUT string into body and verification digit.\n * \n * @param cleanedRut - Cleaned RUT string (only numbers and K)\n * @returns Parsed RUT object or null if invalid format\n */\nexport function parseRut(cleanedRut: string): ParsedRut | null {\n if (cleanedRut.length < 2) {\n return null;\n }\n\n const verificationDigit = cleanedRut.slice(-1);\n const body = cleanedRut.slice(0, -1);\n\n // Body must contain only digits\n if (!/^\\d+$/.test(body)) {\n return null;\n }\n\n // Verification digit must be a digit or K\n if (!/^[0-9K]$/.test(verificationDigit)) {\n return null;\n }\n\n return { body, verificationDigit };\n}\n","import type { ValidationResult } from './types';\nimport { cleanRut } from './clean';\nimport { parseRut, calculateVerificationDigit } from './utils';\n\n// Minimum valid RUT (1-9)\nconst MIN_RUT_LENGTH = 2;\n// Maximum valid RUT length (including verification digit)\nconst MAX_RUT_LENGTH = 9;\n\n/**\n * Validates a Chilean RUT (Rol Único Tributario).\n * \n * Uses the official Module 11 algorithm to verify the check digit.\n * \n * @param rut - RUT string to validate (can include dots, dashes, spaces)\n * @returns Validation result with isValid flag and cleaned RUT if valid\n * \n * @example\n * validateRut('12.345.678-5') // { isValid: true, rut: '123456785' }\n * validateRut('12345678-5') // { isValid: true, rut: '123456785' }\n * validateRut('12345678-0') // { isValid: false, error: 'Invalid verification digit' }\n * validateRut('') // { isValid: false, error: 'RUT is required' }\n */\nexport function validateRut(rut: string): ValidationResult {\n // Handle empty input\n if (!rut || typeof rut !== 'string') {\n return { isValid: false, error: 'RUT is required' };\n }\n\n // Clean the RUT\n const cleaned = cleanRut(rut);\n\n // Check minimum length\n if (cleaned.length < MIN_RUT_LENGTH) {\n return { isValid: false, error: 'RUT is too short' };\n }\n\n // Check maximum length\n if (cleaned.length > MAX_RUT_LENGTH) {\n return { isValid: false, error: 'RUT is too long' };\n }\n\n // Parse the RUT\n const parsed = parseRut(cleaned);\n if (!parsed) {\n return { isValid: false, error: 'Invalid RUT format' };\n }\n\n // Calculate expected verification digit\n const expectedDigit = calculateVerificationDigit(parsed.body);\n\n // Compare with provided verification digit\n if (parsed.verificationDigit !== expectedDigit) {\n return { isValid: false, error: 'Invalid verification digit' };\n }\n\n return { isValid: true, rut: cleaned };\n}\n\n/**\n * Simple boolean check for RUT validity.\n * \n * @param rut - RUT string to validate\n * @returns true if RUT is valid, false otherwise\n * \n * @example\n * isValidRut('12.345.678-5') // true\n * isValidRut('12345678-0') // false\n */\nexport function isValidRut(rut: string): boolean {\n return validateRut(rut).isValid;\n}\n","import type { FormatOptions } from './types';\nimport { cleanRut } from './clean';\nimport { parseRut, calculateVerificationDigit } from './utils';\n\n// Pre-compiled regex for adding dots\nconst DOTS_REGEX = /\\B(?=(\\d{3})+(?!\\d))/g;\n\n/**\n * Default formatting options\n */\nconst DEFAULT_OPTIONS: Required<FormatOptions> = {\n dots: true,\n dash: true,\n uppercase: true,\n};\n\n/**\n * Formats a Chilean RUT with the specified options.\n * \n * By default, formats as: 12.345.678-9\n * \n * @param rut - RUT string to format (can include dots, dashes, spaces)\n * @param options - Formatting options\n * @returns Formatted RUT string, or empty string if invalid\n * \n * @example\n * formatRut('123456785') // '12.345.678-5'\n * formatRut('123456785', { dots: false }) // '12345678-5'\n * formatRut('123456785', { dash: false }) // '12.345.6785'\n * formatRut('12345678K', { uppercase: false }) // '12.345.678-k'\n */\nexport function formatRut(rut: string, options: FormatOptions = {}): string {\n // Merge with defaults\n const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };\n\n // Clean the RUT\n const cleaned = cleanRut(rut);\n\n // Parse and validate\n const parsed = parseRut(cleaned);\n if (!parsed) {\n return '';\n }\n\n // Validate the verification digit\n const expectedDigit = calculateVerificationDigit(parsed.body);\n if (parsed.verificationDigit !== expectedDigit) {\n return '';\n }\n\n // Format the body\n let formattedBody = parsed.body;\n if (opts.dots) {\n formattedBody = parsed.body.replace(DOTS_REGEX, '.');\n }\n\n // Format the verification digit\n let dv = parsed.verificationDigit;\n if (!opts.uppercase) {\n dv = dv.toLowerCase();\n }\n\n // Combine with separator\n const separator = opts.dash ? '-' : '';\n return `${formattedBody}${separator}${dv}`;\n}\n\n/**\n * Formats a RUT without validation (use with caution).\n * Useful when you need to format user input as they type.\n * \n * @param rut - RUT string to format\n * @param options - Formatting options\n * @returns Formatted RUT string\n * \n * @example\n * formatRutPartial('12345') // '12.345'\n * formatRutPartial('123456789') // '12.345.678-9'\n */\nexport function formatRutPartial(rut: string, options: FormatOptions = {}): string {\n const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };\n const cleaned = cleanRut(rut);\n\n if (cleaned.length === 0) {\n return '';\n }\n\n // Separate body and potential verification digit\n let body: string;\n let dv: string;\n\n if (cleaned.length > 1) {\n // Check if last char could be a verification digit (K or any digit)\n const lastChar = cleaned.slice(-1);\n if (/[0-9K]/.test(lastChar)) {\n body = cleaned.slice(0, -1);\n dv = opts.uppercase ? lastChar : lastChar.toLowerCase();\n } else {\n body = cleaned;\n dv = '';\n }\n } else {\n body = cleaned;\n dv = '';\n }\n\n // Format body with dots if needed\n let formattedBody = body;\n if (opts.dots && body.length > 0) {\n formattedBody = body.replace(DOTS_REGEX, '.');\n }\n\n // Add verification digit if present\n if (dv) {\n const separator = opts.dash ? '-' : '';\n return `${formattedBody}${separator}${dv}`;\n }\n\n return formattedBody;\n}\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var m=/[^0-9kK]/g;function l(t){return typeof t!="string"?"":(t.length>50&&(t=t.slice(0,50)),t.replace(m,"").toUpperCase())}function c(t){let o=[2,3,4,5,6,7],r=0,e=0;for(let a=t.length-1;a>=0;a--){let s=parseInt(t[a],10);r+=s*o[e],e=(e+1)%6;}let n=11-r%11;return n===11?"0":n===10?"K":n.toString()}function u(t){if(t.length<2)return null;let o=t.slice(-1),r=t.slice(0,-1);return !/^\d+$/.test(r)||!/^[0-9K]$/.test(o)?null:{body:r,verificationDigit:o}}var R=2,y=9;function f(t){if(!t||typeof t!="string")return {isValid:false,error:"RUT is required"};let o=l(t);if(o.length<R)return {isValid:false,error:"RUT is too short"};if(o.length>y)return {isValid:false,error:"RUT is too long"};let r=u(o);if(!r)return {isValid:false,error:"Invalid RUT format"};let e=c(r.body);return r.verificationDigit!==e?{isValid:false,error:"Invalid verification digit"}:{isValid:true,rut:o}}function T(t){return f(t).isValid}var p=/\B(?=(\d{3})+(?!\d))/g,d={dots:true,dash:true,uppercase:true};function V(t,o={}){let r={...d,...o},e=l(t),i=u(e);if(!i)return "";let n=c(i.body);if(i.verificationDigit!==n)return "";let a=i.body;r.dots&&(a=i.body.replace(p,"."));let s=i.verificationDigit;r.uppercase||(s=s.toLowerCase());let g=r.dash?"-":"";return `${a}${g}${s}`}function x(t,o={}){let r={...d,...o},e=l(t);if(e.length===0)return "";let i,n;if(e.length>1){let s=e.slice(-1);/[0-9K]/.test(s)?(i=e.slice(0,-1),n=r.uppercase?s:s.toLowerCase()):(i=e,n="");}else i=e,n="";let a=i;if(r.dots&&i.length>0&&(a=i.replace(p,".")),n){let s=r.dash?"-":"";return `${a}${s}${n}`}return a}export{c as calculateVerificationDigit,l as cleanRut,V as formatRut,x as formatRutPartial,T as isValidRut,u as parseRut,f as validateRut};//# sourceMappingURL=index.mjs.map
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/clean.ts","../src/utils.ts","../src/validate.ts","../src/format.ts"],"names":["CLEAN_REGEX","cleanRut","input","calculateVerificationDigit","rutBody","multipliers","sum","multiplierIndex","i","digit","result","parseRut","cleanedRut","verificationDigit","body","MIN_RUT_LENGTH","MAX_RUT_LENGTH","validateRut","rut","cleaned","parsed","expectedDigit","isValidRut","DOTS_REGEX","DEFAULT_OPTIONS","formatRut","options","opts","formattedBody","dv","separator","formatRutPartial","lastChar"],"mappings":"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","file":"index.mjs","sourcesContent":["// Pre-compiled regex for maximum performance\nconst CLEAN_REGEX = /[^0-9kK]/g;\n\n// Maximum allowed input length for security (prevents DoS)\nconst MAX_INPUT_LENGTH = 50;\n\n/**\n * Cleans a RUT string by removing all non-valid characters.\n * Keeps only numbers and 'K'/'k'.\n * \n * @param input - Raw RUT input string\n * @returns Cleaned RUT string with only valid characters\n * \n * @example\n * cleanRut('12.345.678-9') // '123456789'\n * cleanRut('12345678-K') // '12345678K'\n * cleanRut(' 12-345-678.9 ') // '123456789'\n */\nexport function cleanRut(input: string): string {\n // Security: handle non-string inputs gracefully\n if (typeof input !== 'string') {\n return '';\n }\n\n // Security: prevent DoS with extremely long inputs\n if (input.length > MAX_INPUT_LENGTH) {\n input = input.slice(0, MAX_INPUT_LENGTH);\n }\n\n // Remove all non-valid characters and convert to uppercase\n return input.replace(CLEAN_REGEX, '').toUpperCase();\n}\n","import type { ParsedRut } from './types';\n\n/**\n * Calculates the verification digit for a RUT body using Module 11 algorithm.\n * \n * @param rutBody - RUT body (numbers only, without verification digit)\n * @returns Calculated verification digit ('0'-'9' or 'K')\n */\nexport function calculateVerificationDigit(rutBody: string): string {\n // Multiplier sequence for Module 11 algorithm\n const multipliers = [2, 3, 4, 5, 6, 7];\n\n let sum = 0;\n let multiplierIndex = 0;\n\n // Process digits from right to left\n for (let i = rutBody.length - 1; i >= 0; i--) {\n const digit = parseInt(rutBody[i], 10);\n sum += digit * multipliers[multiplierIndex];\n multiplierIndex = (multiplierIndex + 1) % 6; // Cycle through multipliers\n }\n\n // Calculate verification digit\n const remainder = sum % 11;\n const result = 11 - remainder;\n\n // Convert result to verification digit\n if (result === 11) return '0';\n if (result === 10) return 'K';\n return result.toString();\n}\n\n/**\n * Parses a cleaned RUT string into body and verification digit.\n * \n * @param cleanedRut - Cleaned RUT string (only numbers and K)\n * @returns Parsed RUT object or null if invalid format\n */\nexport function parseRut(cleanedRut: string): ParsedRut | null {\n if (cleanedRut.length < 2) {\n return null;\n }\n\n const verificationDigit = cleanedRut.slice(-1);\n const body = cleanedRut.slice(0, -1);\n\n // Body must contain only digits\n if (!/^\\d+$/.test(body)) {\n return null;\n }\n\n // Verification digit must be a digit or K\n if (!/^[0-9K]$/.test(verificationDigit)) {\n return null;\n }\n\n return { body, verificationDigit };\n}\n","import type { ValidationResult } from './types';\nimport { cleanRut } from './clean';\nimport { parseRut, calculateVerificationDigit } from './utils';\n\n// Minimum valid RUT (1-9)\nconst MIN_RUT_LENGTH = 2;\n// Maximum valid RUT length (including verification digit)\nconst MAX_RUT_LENGTH = 9;\n\n/**\n * Validates a Chilean RUT (Rol Único Tributario).\n * \n * Uses the official Module 11 algorithm to verify the check digit.\n * \n * @param rut - RUT string to validate (can include dots, dashes, spaces)\n * @returns Validation result with isValid flag and cleaned RUT if valid\n * \n * @example\n * validateRut('12.345.678-5') // { isValid: true, rut: '123456785' }\n * validateRut('12345678-5') // { isValid: true, rut: '123456785' }\n * validateRut('12345678-0') // { isValid: false, error: 'Invalid verification digit' }\n * validateRut('') // { isValid: false, error: 'RUT is required' }\n */\nexport function validateRut(rut: string): ValidationResult {\n // Handle empty input\n if (!rut || typeof rut !== 'string') {\n return { isValid: false, error: 'RUT is required' };\n }\n\n // Clean the RUT\n const cleaned = cleanRut(rut);\n\n // Check minimum length\n if (cleaned.length < MIN_RUT_LENGTH) {\n return { isValid: false, error: 'RUT is too short' };\n }\n\n // Check maximum length\n if (cleaned.length > MAX_RUT_LENGTH) {\n return { isValid: false, error: 'RUT is too long' };\n }\n\n // Parse the RUT\n const parsed = parseRut(cleaned);\n if (!parsed) {\n return { isValid: false, error: 'Invalid RUT format' };\n }\n\n // Calculate expected verification digit\n const expectedDigit = calculateVerificationDigit(parsed.body);\n\n // Compare with provided verification digit\n if (parsed.verificationDigit !== expectedDigit) {\n return { isValid: false, error: 'Invalid verification digit' };\n }\n\n return { isValid: true, rut: cleaned };\n}\n\n/**\n * Simple boolean check for RUT validity.\n * \n * @param rut - RUT string to validate\n * @returns true if RUT is valid, false otherwise\n * \n * @example\n * isValidRut('12.345.678-5') // true\n * isValidRut('12345678-0') // false\n */\nexport function isValidRut(rut: string): boolean {\n return validateRut(rut).isValid;\n}\n","import type { FormatOptions } from './types';\nimport { cleanRut } from './clean';\nimport { parseRut, calculateVerificationDigit } from './utils';\n\n// Pre-compiled regex for adding dots\nconst DOTS_REGEX = /\\B(?=(\\d{3})+(?!\\d))/g;\n\n/**\n * Default formatting options\n */\nconst DEFAULT_OPTIONS: Required<FormatOptions> = {\n dots: true,\n dash: true,\n uppercase: true,\n};\n\n/**\n * Formats a Chilean RUT with the specified options.\n * \n * By default, formats as: 12.345.678-9\n * \n * @param rut - RUT string to format (can include dots, dashes, spaces)\n * @param options - Formatting options\n * @returns Formatted RUT string, or empty string if invalid\n * \n * @example\n * formatRut('123456785') // '12.345.678-5'\n * formatRut('123456785', { dots: false }) // '12345678-5'\n * formatRut('123456785', { dash: false }) // '12.345.6785'\n * formatRut('12345678K', { uppercase: false }) // '12.345.678-k'\n */\nexport function formatRut(rut: string, options: FormatOptions = {}): string {\n // Merge with defaults\n const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };\n\n // Clean the RUT\n const cleaned = cleanRut(rut);\n\n // Parse and validate\n const parsed = parseRut(cleaned);\n if (!parsed) {\n return '';\n }\n\n // Validate the verification digit\n const expectedDigit = calculateVerificationDigit(parsed.body);\n if (parsed.verificationDigit !== expectedDigit) {\n return '';\n }\n\n // Format the body\n let formattedBody = parsed.body;\n if (opts.dots) {\n formattedBody = parsed.body.replace(DOTS_REGEX, '.');\n }\n\n // Format the verification digit\n let dv = parsed.verificationDigit;\n if (!opts.uppercase) {\n dv = dv.toLowerCase();\n }\n\n // Combine with separator\n const separator = opts.dash ? '-' : '';\n return `${formattedBody}${separator}${dv}`;\n}\n\n/**\n * Formats a RUT without validation (use with caution).\n * Useful when you need to format user input as they type.\n * \n * @param rut - RUT string to format\n * @param options - Formatting options\n * @returns Formatted RUT string\n * \n * @example\n * formatRutPartial('12345') // '12.345'\n * formatRutPartial('123456789') // '12.345.678-9'\n */\nexport function formatRutPartial(rut: string, options: FormatOptions = {}): string {\n const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };\n const cleaned = cleanRut(rut);\n\n if (cleaned.length === 0) {\n return '';\n }\n\n // Separate body and potential verification digit\n let body: string;\n let dv: string;\n\n if (cleaned.length > 1) {\n // Check if last char could be a verification digit (K or any digit)\n const lastChar = cleaned.slice(-1);\n if (/[0-9K]/.test(lastChar)) {\n body = cleaned.slice(0, -1);\n dv = opts.uppercase ? lastChar : lastChar.toLowerCase();\n } else {\n body = cleaned;\n dv = '';\n }\n } else {\n body = cleaned;\n dv = '';\n }\n\n // Format body with dots if needed\n let formattedBody = body;\n if (opts.dots && body.length > 0) {\n formattedBody = body.replace(DOTS_REGEX, '.');\n }\n\n // Add verification digit if present\n if (dv) {\n const separator = opts.dash ? '-' : '';\n return `${formattedBody}${separator}${dv}`;\n }\n\n return formattedBody;\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "chilean-rut-formatter",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "High-performance library for formatting and validating Chilean RUTs (Rol Único Tributario)",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"lint": "tsc --noEmit",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"rut",
|
|
27
|
+
"chile",
|
|
28
|
+
"chilean",
|
|
29
|
+
"rut-validator",
|
|
30
|
+
"rut-formatter",
|
|
31
|
+
"tax-id",
|
|
32
|
+
"validation"
|
|
33
|
+
],
|
|
34
|
+
"author": "",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"tsup": "^8.0.0",
|
|
38
|
+
"typescript": "^5.3.0",
|
|
39
|
+
"vitest": "^1.2.0"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/your-username/chilean-rut-formatter"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=16"
|
|
47
|
+
}
|
|
48
|
+
}
|