@indodev/toolkit 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/email-validator/index.cjs +10 -0
  2. package/dist/email-validator/index.cjs.map +1 -1
  3. package/dist/email-validator/index.d.cts +1 -1
  4. package/dist/email-validator/index.d.ts +1 -1
  5. package/dist/email-validator/index.js +10 -1
  6. package/dist/email-validator/index.js.map +1 -1
  7. package/dist/{parse-BmmsNlJt.d.cts → errors--47zprcf.d.cts} +41 -7
  8. package/dist/{parse-BmmsNlJt.d.ts → errors--47zprcf.d.ts} +41 -7
  9. package/dist/{email-validator-R9L5unIw.d.cts → errors-DdutHLae.d.cts} +23 -1
  10. package/dist/{email-validator-R9L5unIw.d.ts → errors-DdutHLae.d.ts} +23 -1
  11. package/dist/index.cjs +317 -38
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +7 -7
  14. package/dist/index.d.ts +7 -7
  15. package/dist/index.js +310 -39
  16. package/dist/index.js.map +1 -1
  17. package/dist/{compare-Ku_8OhuU.d.cts → mask-CToJqmrd.d.cts} +79 -1
  18. package/dist/{compare-Ku_8OhuU.d.ts → mask-CToJqmrd.d.ts} +79 -1
  19. package/dist/nik/index.cjs +177 -24
  20. package/dist/nik/index.cjs.map +1 -1
  21. package/dist/nik/index.d.cts +24 -330
  22. package/dist/nik/index.d.ts +24 -330
  23. package/dist/nik/index.js +174 -25
  24. package/dist/nik/index.js.map +1 -1
  25. package/dist/npwp/index.cjs +10 -0
  26. package/dist/npwp/index.cjs.map +1 -1
  27. package/dist/npwp/index.d.cts +23 -1
  28. package/dist/npwp/index.d.ts +23 -1
  29. package/dist/npwp/index.js +10 -1
  30. package/dist/npwp/index.js.map +1 -1
  31. package/dist/parse-B3UzEHq3.d.cts +155 -0
  32. package/dist/parse-B3UzEHq3.d.ts +155 -0
  33. package/dist/parse-DlrgrRfY.d.cts +155 -0
  34. package/dist/parse-DlrgrRfY.d.ts +155 -0
  35. package/dist/phone/index.cjs +36 -12
  36. package/dist/phone/index.cjs.map +1 -1
  37. package/dist/phone/index.d.cts +1 -1
  38. package/dist/phone/index.d.ts +1 -1
  39. package/dist/phone/index.js +36 -13
  40. package/dist/phone/index.js.map +1 -1
  41. package/dist/plate/index.cjs +57 -0
  42. package/dist/plate/index.cjs.map +1 -1
  43. package/dist/plate/index.d.cts +1 -1
  44. package/dist/plate/index.d.ts +1 -1
  45. package/dist/plate/index.js +56 -1
  46. package/dist/plate/index.js.map +1 -1
  47. package/dist/text/index.cjs +31 -8
  48. package/dist/text/index.cjs.map +1 -1
  49. package/dist/text/index.d.cts +2 -63
  50. package/dist/text/index.d.ts +2 -63
  51. package/dist/text/index.js +31 -8
  52. package/dist/text/index.js.map +1 -1
  53. package/dist/utils-D4A4ro8M.d.cts +507 -0
  54. package/dist/utils-D4A4ro8M.d.ts +507 -0
  55. package/dist/vin/index.cjs +64 -0
  56. package/dist/vin/index.cjs.map +1 -1
  57. package/dist/vin/index.d.cts +1 -1
  58. package/dist/vin/index.d.ts +1 -1
  59. package/dist/vin/index.js +63 -1
  60. package/dist/vin/index.js.map +1 -1
  61. package/package.json +1 -1
  62. package/dist/types-i5e6R0AS.d.cts +0 -39
  63. package/dist/types-i5e6R0AS.d.ts +0 -39
  64. package/dist/utils-DDVlOusI.d.cts +0 -30
  65. package/dist/utils-DDVlOusI.d.ts +0 -30
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- export { NIKInfo, MaskOptions as NIKMaskOptions, formatBirthDate, formatNIK, getAge, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK } from './nik/index.cjs';
2
- export { P as PhoneFormat, l as PhoneInfo, M as PhoneMaskOptions, d as cleanPhoneNumber, f as formatPhoneNumber, h as generateSmsLink, j as generateTelLink, e as generateWALink, g as getOperator, a as isLandlineNumber, i as isMobileNumber, k as isProvider, m as maskPhoneNumber, p as parsePhoneNumber, c as toE164, t as toInternational, b as toNational, v as validatePhoneNumber } from './parse-BmmsNlJt.cjs';
3
- export { NPWPInfo, MaskOptions as NPWPMaskOptions, formatNPWP, maskNPWP, parseNPWP, validateNPWP } from './npwp/index.cjs';
4
- export { f as formatPlate, g as getRegionFromPlate, v as validatePlate } from './utils-DDVlOusI.cjs';
5
- export { V as VINOptions, a as VINValidationResult, v as validateVIN } from './types-i5e6R0AS.cjs';
6
- export { c as EmailInfo, b as EmailMaskOptions, E as EmailValidationOptions, a as EmailValidationResult, g as getEmailInfo, m as maskEmail, n as normalizeEmail, v as validateEmail } from './email-validator-R9L5unIw.cjs';
1
+ export { N as NIKInfo, M as NIKMaskOptions, a as formatBirthDate, f as formatNIK, g as getAge, b as isValidForBirthDate, i as isValidForGender, m as maskNIK, p as parseNIK, v as validateNIK } from './utils-D4A4ro8M.cjs';
2
+ export { I as InvalidPhoneError, P as PhoneFormat, l as PhoneInfo, M as PhoneMaskOptions, d as cleanPhoneNumber, f as formatPhoneNumber, h as generateSmsLink, j as generateTelLink, e as generateWALink, g as getOperator, a as isLandlineNumber, i as isMobileNumber, k as isProvider, m as maskPhoneNumber, p as parsePhoneNumber, c as toE164, t as toInternational, b as toNational, v as validatePhoneNumber } from './errors--47zprcf.cjs';
3
+ export { InvalidNPWPError, NPWPInfo, MaskOptions as NPWPMaskOptions, formatNPWP, maskNPWP, parseNPWP, validateNPWP } from './npwp/index.cjs';
4
+ export { I as InvalidPlateError, P as PlateInfo, f as formatPlate, g as getRegionFromPlate, p as parsePlate, v as validatePlate } from './parse-B3UzEHq3.cjs';
5
+ export { I as InvalidVINError, b as VINInfo, V as VINOptions, a as VINValidationResult, p as parseVIN, v as validateVIN } from './parse-DlrgrRfY.cjs';
6
+ export { c as EmailInfo, b as EmailMaskOptions, E as EmailValidationOptions, a as EmailValidationResult, I as InvalidEmailError, g as getEmailInfo, m as maskEmail, n as normalizeEmail, v as validateEmail } from './errors-DdutHLae.cjs';
7
7
  export { R as RupiahOptions, W as WordOptions, d as addRupiahSymbol, c as calculateTax, b as formatAccounting, a as formatCompact, f as formatRupiah, p as parseRupiah, r as roundToClean, t as toWords } from './utils-OG1yMaAa.cjs';
8
- export { C as CompareOptions, E as ExtractOptions, m as SanitizeOptions, S as SlugifyOptions, T as TitleCaseOptions, o as TruncateOptions, c as capitalize, k as compareStrings, d as contractAbbreviation, e as expandAbbreviation, g as extractWords, j as isAlay, n as normalizeWhitespace, p as profanityFilter, r as removeAccents, h as removeStopwords, b as sanitize, l as similarity, s as slugify, i as toFormal, a as toSentenceCase, t as toTitleCase, f as truncate } from './compare-Ku_8OhuU.cjs';
8
+ export { C as CompareOptions, E as ExtractOptions, o as SanitizeOptions, S as SlugifyOptions, M as TextMaskOptions, T as TitleCaseOptions, q as TruncateOptions, c as capitalize, k as compareStrings, d as contractAbbreviation, e as expandAbbreviation, g as extractWords, j as isAlay, m as maskText, n as normalizeWhitespace, p as profanityFilter, r as removeAccents, h as removeStopwords, b as sanitize, l as similarity, s as slugify, i as toFormal, a as toSentenceCase, t as toTitleCase, f as truncate } from './mask-CToJqmrd.cjs';
9
9
  export { AgeOptions, AgeResult, DAY_NAMES, DAY_NAMES_SHORT, DateStyle, InvalidDateError, InvalidDateRangeError, MONTH_NAMES, MONTH_NAMES_SHORT, TIMEZONE_MAP, VALID_UTC_OFFSETS, daysInMonth, formatDate, formatDateRange, getAge as getAgeFromDate, getIndonesianTimezone, isLeapYear, isValidDate, isWeekend, isWorkingDay, parseDate, toRelativeTime } from './datetime/index.cjs';
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export { NIKInfo, MaskOptions as NIKMaskOptions, formatBirthDate, formatNIK, getAge, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK } from './nik/index.js';
2
- export { P as PhoneFormat, l as PhoneInfo, M as PhoneMaskOptions, d as cleanPhoneNumber, f as formatPhoneNumber, h as generateSmsLink, j as generateTelLink, e as generateWALink, g as getOperator, a as isLandlineNumber, i as isMobileNumber, k as isProvider, m as maskPhoneNumber, p as parsePhoneNumber, c as toE164, t as toInternational, b as toNational, v as validatePhoneNumber } from './parse-BmmsNlJt.js';
3
- export { NPWPInfo, MaskOptions as NPWPMaskOptions, formatNPWP, maskNPWP, parseNPWP, validateNPWP } from './npwp/index.js';
4
- export { f as formatPlate, g as getRegionFromPlate, v as validatePlate } from './utils-DDVlOusI.js';
5
- export { V as VINOptions, a as VINValidationResult, v as validateVIN } from './types-i5e6R0AS.js';
6
- export { c as EmailInfo, b as EmailMaskOptions, E as EmailValidationOptions, a as EmailValidationResult, g as getEmailInfo, m as maskEmail, n as normalizeEmail, v as validateEmail } from './email-validator-R9L5unIw.js';
1
+ export { N as NIKInfo, M as NIKMaskOptions, a as formatBirthDate, f as formatNIK, g as getAge, b as isValidForBirthDate, i as isValidForGender, m as maskNIK, p as parseNIK, v as validateNIK } from './utils-D4A4ro8M.js';
2
+ export { I as InvalidPhoneError, P as PhoneFormat, l as PhoneInfo, M as PhoneMaskOptions, d as cleanPhoneNumber, f as formatPhoneNumber, h as generateSmsLink, j as generateTelLink, e as generateWALink, g as getOperator, a as isLandlineNumber, i as isMobileNumber, k as isProvider, m as maskPhoneNumber, p as parsePhoneNumber, c as toE164, t as toInternational, b as toNational, v as validatePhoneNumber } from './errors--47zprcf.js';
3
+ export { InvalidNPWPError, NPWPInfo, MaskOptions as NPWPMaskOptions, formatNPWP, maskNPWP, parseNPWP, validateNPWP } from './npwp/index.js';
4
+ export { I as InvalidPlateError, P as PlateInfo, f as formatPlate, g as getRegionFromPlate, p as parsePlate, v as validatePlate } from './parse-B3UzEHq3.js';
5
+ export { I as InvalidVINError, b as VINInfo, V as VINOptions, a as VINValidationResult, p as parseVIN, v as validateVIN } from './parse-DlrgrRfY.js';
6
+ export { c as EmailInfo, b as EmailMaskOptions, E as EmailValidationOptions, a as EmailValidationResult, I as InvalidEmailError, g as getEmailInfo, m as maskEmail, n as normalizeEmail, v as validateEmail } from './errors-DdutHLae.js';
7
7
  export { R as RupiahOptions, W as WordOptions, d as addRupiahSymbol, c as calculateTax, b as formatAccounting, a as formatCompact, f as formatRupiah, p as parseRupiah, r as roundToClean, t as toWords } from './utils-OG1yMaAa.js';
8
- export { C as CompareOptions, E as ExtractOptions, m as SanitizeOptions, S as SlugifyOptions, T as TitleCaseOptions, o as TruncateOptions, c as capitalize, k as compareStrings, d as contractAbbreviation, e as expandAbbreviation, g as extractWords, j as isAlay, n as normalizeWhitespace, p as profanityFilter, r as removeAccents, h as removeStopwords, b as sanitize, l as similarity, s as slugify, i as toFormal, a as toSentenceCase, t as toTitleCase, f as truncate } from './compare-Ku_8OhuU.js';
8
+ export { C as CompareOptions, E as ExtractOptions, o as SanitizeOptions, S as SlugifyOptions, M as TextMaskOptions, T as TitleCaseOptions, q as TruncateOptions, c as capitalize, k as compareStrings, d as contractAbbreviation, e as expandAbbreviation, g as extractWords, j as isAlay, m as maskText, n as normalizeWhitespace, p as profanityFilter, r as removeAccents, h as removeStopwords, b as sanitize, l as similarity, s as slugify, i as toFormal, a as toSentenceCase, t as toTitleCase, f as truncate } from './mask-CToJqmrd.js';
9
9
  export { AgeOptions, AgeResult, DAY_NAMES, DAY_NAMES_SHORT, DateStyle, InvalidDateError, InvalidDateRangeError, MONTH_NAMES, MONTH_NAMES_SHORT, TIMEZONE_MAP, VALID_UTC_OFFSETS, daysInMonth, formatDate, formatDateRange, getAge as getAgeFromDate, getIndonesianTimezone, isLeapYear, isValidDate, isWeekend, isWorkingDay, parseDate, toRelativeTime } from './datetime/index.js';
package/dist/index.js CHANGED
@@ -179,8 +179,17 @@ function maskNIK(nik, options = {}) {
179
179
  if (!/^\d{16}$/.test(nik)) {
180
180
  return nik;
181
181
  }
182
- const { start = 4, end = 4, char = "*", separator } = options;
183
- if (start + end >= 16) {
182
+ const { visibleStart, visibleEnd, maskChar, separator, start, end, char } = options;
183
+ const hasLegacyOptions = start !== void 0 || end !== void 0 || char !== void 0;
184
+ if (hasLegacyOptions) {
185
+ console.warn(
186
+ "[DEPRECATED] Mask options start/end/char are deprecated. Use visibleStart/visibleEnd/maskChar instead. These old names will be removed in v1.0.0."
187
+ );
188
+ }
189
+ const effectiveStart = visibleStart !== void 0 ? visibleStart : start !== void 0 ? start : 4;
190
+ const effectiveEnd = visibleEnd !== void 0 ? visibleEnd : end !== void 0 ? end : 4;
191
+ const effectiveChar = maskChar !== void 0 ? maskChar : char !== void 0 ? char : "*";
192
+ if (effectiveStart + effectiveEnd >= 16) {
184
193
  return nik;
185
194
  }
186
195
  if (separator) {
@@ -191,54 +200,86 @@ function maskNIK(nik, options = {}) {
191
200
  const partStart = charCount;
192
201
  const partEnd = charCount + part.length;
193
202
  charCount += part.length;
194
- if (partEnd <= start) {
203
+ if (partEnd <= effectiveStart) {
195
204
  return part;
196
- } else if (partStart >= 16 - end) {
205
+ } else if (partStart >= 16 - effectiveEnd) {
197
206
  return part;
198
- } else if (partStart >= start && partEnd <= 16 - end) {
199
- return char.repeat(part.length);
207
+ } else if (partStart >= effectiveStart && partEnd <= 16 - effectiveEnd) {
208
+ return effectiveChar.repeat(part.length);
200
209
  } else {
201
210
  return part.split("").map((ch, idx) => {
202
211
  const pos = partStart + idx;
203
- if (pos < start || pos >= 16 - end) {
212
+ if (pos < effectiveStart || pos >= 16 - effectiveEnd) {
204
213
  return ch;
205
214
  }
206
- return char;
215
+ return effectiveChar;
207
216
  }).join("");
208
217
  }
209
218
  });
210
219
  return maskedParts.join(separator);
211
220
  }
212
- const startPart = nik.substring(0, start);
213
- const endPart = nik.substring(16 - end);
214
- const maskLength = 16 - start - end;
215
- return startPart + char.repeat(maskLength) + endPart;
221
+ const startPart = nik.substring(0, effectiveStart);
222
+ const endPart = nik.substring(16 - effectiveEnd);
223
+ const maskLength = 16 - effectiveStart - effectiveEnd;
224
+ return startPart + effectiveChar.repeat(maskLength) + endPart;
216
225
  }
217
226
 
218
227
  // src/nik/utils.ts
219
- function getAge(nik, referenceDate = /* @__PURE__ */ new Date()) {
228
+ function getAge(nik, options = {}) {
229
+ const { referenceDate = /* @__PURE__ */ new Date(), asString = false } = options;
220
230
  const info = parseNIK(nik);
221
231
  if (!info || !info.birthDate) {
222
232
  return null;
223
233
  }
224
234
  const birthDate = info.birthDate;
225
- let age = referenceDate.getFullYear() - birthDate.getFullYear();
226
- const m = referenceDate.getMonth() - birthDate.getMonth();
227
- if (m < 0 || m === 0 && referenceDate.getDate() < birthDate.getDate()) {
228
- age--;
229
- }
230
- return age;
231
- }
232
- function formatBirthDate(nik, options = {
233
- day: "numeric",
234
- month: "long",
235
- year: "numeric"
236
- }, locale = "id-ID") {
235
+ let years = referenceDate.getFullYear() - birthDate.getFullYear();
236
+ let months = referenceDate.getMonth() - birthDate.getMonth();
237
+ let days = referenceDate.getDate() - birthDate.getDate();
238
+ if (days < 0) {
239
+ months--;
240
+ const prevMonth = new Date(
241
+ referenceDate.getFullYear(),
242
+ referenceDate.getMonth(),
243
+ 0
244
+ );
245
+ days += prevMonth.getDate();
246
+ }
247
+ if (months < 0) {
248
+ years--;
249
+ months += 12;
250
+ }
251
+ if (asString) {
252
+ const parts = [];
253
+ if (years > 0) parts.push(`${years} Tahun`);
254
+ if (months > 0) parts.push(`${months} Bulan`);
255
+ if (days > 0 || parts.length === 0) parts.push(`${days} Hari`);
256
+ return parts.join(" ");
257
+ }
258
+ return { years, months, days };
259
+ }
260
+ function formatBirthDate(nik) {
237
261
  const info = parseNIK(nik);
238
262
  if (!info || !info.birthDate) {
239
263
  return null;
240
264
  }
241
- return new Intl.DateTimeFormat(locale, options).format(info.birthDate);
265
+ const day = info.birthDate.getDate();
266
+ const month = info.birthDate.getMonth();
267
+ const year = info.birthDate.getFullYear();
268
+ const monthNames = [
269
+ "Januari",
270
+ "Februari",
271
+ "Maret",
272
+ "April",
273
+ "Mei",
274
+ "Juni",
275
+ "Juli",
276
+ "Agustus",
277
+ "September",
278
+ "Oktober",
279
+ "November",
280
+ "Desember"
281
+ ];
282
+ return `${day} ${monthNames[month]} ${year}`;
242
283
  }
243
284
  function isValidForGender(nik, gender) {
244
285
  const info = parseNIK(nik);
@@ -900,28 +941,42 @@ function maskPhoneNumber(phone, options = {}) {
900
941
  if (toMask.length < 4) {
901
942
  return phone;
902
943
  }
903
- const { char = "*", separator } = options;
904
- let { start = 4, end = 4 } = options;
905
- if (start + end >= toMask.length) {
944
+ const { maskChar, separator, visibleStart, visibleEnd, start, end, char } = options;
945
+ const hasLegacyOptions = start !== void 0 || end !== void 0 || char !== void 0;
946
+ if (hasLegacyOptions) {
947
+ console.warn(
948
+ "[DEPRECATED] Mask options start/end/char are deprecated. Use visibleStart/visibleEnd/maskChar instead. These old names will be removed in v1.0.0."
949
+ );
950
+ }
951
+ const effectiveStart = visibleStart !== void 0 ? visibleStart : start !== void 0 ? start : 4;
952
+ const effectiveEnd = visibleEnd !== void 0 ? visibleEnd : end !== void 0 ? end : 4;
953
+ const effectiveChar = maskChar !== void 0 ? maskChar : char !== void 0 ? char : "*";
954
+ if (effectiveStart + effectiveEnd >= toMask.length) {
906
955
  if (toMask.length < 10) {
907
956
  const minMaskLength = 1;
908
957
  const availableForVisible = toMask.length - minMaskLength;
909
958
  if (availableForVisible >= 2) {
910
- start = Math.floor(availableForVisible / 2);
911
- end = availableForVisible - start;
959
+ const newStart = Math.floor(availableForVisible / 2);
960
+ const newEnd = availableForVisible - newStart;
961
+ const startPart2 = toMask.substring(0, newStart);
962
+ const endPart2 = toMask.substring(toMask.length - newEnd);
963
+ const masked2 = startPart2 + effectiveChar + endPart2;
964
+ if (separator) {
965
+ return `${startPart2}${separator}${effectiveChar}${separator}${endPart2}`;
966
+ }
967
+ return masked2;
912
968
  } else {
913
969
  return toMask;
914
970
  }
915
- } else {
916
- return toMask;
917
971
  }
972
+ return toMask;
918
973
  }
919
- const startPart = toMask.substring(0, start);
920
- const endPart = toMask.substring(toMask.length - end);
921
- const maskLength = toMask.length - start - end;
922
- const masked = startPart + char.repeat(maskLength) + endPart;
974
+ const startPart = toMask.substring(0, effectiveStart);
975
+ const endPart = toMask.substring(toMask.length - effectiveEnd);
976
+ const maskLength = toMask.length - effectiveStart - effectiveEnd;
977
+ const masked = startPart + effectiveChar.repeat(maskLength) + endPart;
923
978
  if (separator) {
924
- return `${masked.substring(0, start)}${separator}${masked.substring(start, masked.length - end)}${separator}${masked.substring(masked.length - end)}`;
979
+ return `${masked.substring(0, effectiveStart)}${separator}${masked.substring(effectiveStart, masked.length - effectiveEnd)}${separator}${masked.substring(masked.length - effectiveEnd)}`;
925
980
  }
926
981
  return masked;
927
982
  }
@@ -1013,6 +1068,15 @@ function isProvider(phone, providerName) {
1013
1068
  return operator.toLowerCase() === providerName.toLowerCase();
1014
1069
  }
1015
1070
 
1071
+ // src/phone/errors.ts
1072
+ var InvalidPhoneError = class extends Error {
1073
+ constructor(message = "Invalid phone number provided") {
1074
+ super(message);
1075
+ this.code = "INVALID_PHONE";
1076
+ this.name = "InvalidPhoneError";
1077
+ }
1078
+ };
1079
+
1016
1080
  // src/npwp/validate.ts
1017
1081
  function validateNPWP(npwp) {
1018
1082
  if (!npwp || typeof npwp !== "string") {
@@ -1100,6 +1164,15 @@ function maskNPWP(npwp, options) {
1100
1164
  return `${start}${middle}${end}`;
1101
1165
  }
1102
1166
 
1167
+ // src/npwp/errors.ts
1168
+ var InvalidNPWPError = class extends Error {
1169
+ constructor(message = "Invalid NPWP provided") {
1170
+ super(message);
1171
+ this.code = "INVALID_NPWP";
1172
+ this.name = "InvalidNPWPError";
1173
+ }
1174
+ };
1175
+
1103
1176
  // src/plate/regions.ts
1104
1177
  var PLATE_REGIONS = {
1105
1178
  A: "Banten",
@@ -1191,6 +1264,61 @@ function formatPlate(plate) {
1191
1264
  return `${match[1]} ${match[2]} ${match[3]}`;
1192
1265
  }
1193
1266
 
1267
+ // src/plate/errors.ts
1268
+ var InvalidPlateError = class extends Error {
1269
+ constructor(message = "Invalid plate provided") {
1270
+ super(message);
1271
+ this.code = "INVALID_PLATE";
1272
+ this.name = "InvalidPlateError";
1273
+ }
1274
+ };
1275
+
1276
+ // src/plate/parse.ts
1277
+ function parsePlate(plate) {
1278
+ if (!plate || typeof plate !== "string") {
1279
+ return null;
1280
+ }
1281
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1282
+ const privatePlateRegex = /^[A-Z]{1,2}\d{1,4}[A-Z]{1,3}$/;
1283
+ const publicPlateRegex = /^[A-Z]{1,2}\d{1,4}[A-Z]{0,3}$/;
1284
+ if (!privatePlateRegex.test(cleaned) && !publicPlateRegex.test(cleaned)) {
1285
+ return null;
1286
+ }
1287
+ const isValid = validatePlate(plate);
1288
+ const match = cleaned.match(/^([A-Z]{1,2})(\d{1,4})([A-Z]{0,3})$/);
1289
+ if (!match) {
1290
+ return null;
1291
+ }
1292
+ const prefix = match[1];
1293
+ const number = match[2];
1294
+ const suffix = match[3] || "";
1295
+ const type = determinePlateType(cleaned);
1296
+ return {
1297
+ prefix,
1298
+ number,
1299
+ suffix,
1300
+ type,
1301
+ formatted: formatPlate(plate),
1302
+ isValid
1303
+ };
1304
+ }
1305
+ function determinePlateType(plate) {
1306
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
1307
+ if (cleaned.startsWith("CD") || cleaned.startsWith("CC") || cleaned.startsWith("KL")) {
1308
+ return "diplomat";
1309
+ }
1310
+ if (/^[A-Z]{1,2}\d{1,4}[A-Z]{0,3}$/.test(cleaned)) {
1311
+ const numDigits = cleaned.match(/\d+/)?.[0].length || 0;
1312
+ if (numDigits <= 4) {
1313
+ return "private";
1314
+ }
1315
+ }
1316
+ if (/^[A-Z]{1,2}\d{1,4}[A-Z]{0,3}$/.test(cleaned)) {
1317
+ return "public";
1318
+ }
1319
+ return null;
1320
+ }
1321
+
1194
1322
  // src/vin/constants.ts
1195
1323
  var VIN_LENGTH = 17;
1196
1324
  var VIN_CHECK_DIGIT_INDEX = 8;
@@ -1261,6 +1389,68 @@ function validateVIN(vin) {
1261
1389
  return actualCheckDigit === expectedCheckDigit;
1262
1390
  }
1263
1391
 
1392
+ // src/vin/errors.ts
1393
+ var InvalidVINError = class extends Error {
1394
+ constructor(message = "Invalid VIN provided") {
1395
+ super(message);
1396
+ this.code = "INVALID_VIN";
1397
+ this.name = "InvalidVINError";
1398
+ }
1399
+ };
1400
+
1401
+ // src/vin/parse.ts
1402
+ function parseVIN(vin) {
1403
+ if (!vin || typeof vin !== "string") {
1404
+ return null;
1405
+ }
1406
+ const normalizedVIN = vin.toUpperCase();
1407
+ if (normalizedVIN.length !== VIN_LENGTH) {
1408
+ return null;
1409
+ }
1410
+ for (const char of EXCLUDED_VIN_CHARS) {
1411
+ if (normalizedVIN.includes(char)) {
1412
+ return null;
1413
+ }
1414
+ }
1415
+ for (const char of normalizedVIN) {
1416
+ if (VIN_CHAR_VALUES[char] === void 0) {
1417
+ return null;
1418
+ }
1419
+ }
1420
+ const isValid = validateCheckDigit(normalizedVIN);
1421
+ const wmi = normalizedVIN.substring(0, 3);
1422
+ const vds = normalizedVIN.substring(3, 9);
1423
+ const checkDigit = normalizedVIN[VIN_CHECK_DIGIT_INDEX];
1424
+ const modelYearCode = normalizedVIN[9];
1425
+ const plantCode = normalizedVIN[10];
1426
+ const serialNumber = normalizedVIN.substring(11, 17);
1427
+ return {
1428
+ wmi,
1429
+ vds,
1430
+ checkDigit,
1431
+ modelYearCode,
1432
+ plantCode,
1433
+ serialNumber,
1434
+ isValid
1435
+ };
1436
+ }
1437
+ function validateCheckDigit(vin) {
1438
+ let sum = 0;
1439
+ for (let i = 0; i < VIN_LENGTH; i++) {
1440
+ const char = vin[i];
1441
+ const weight = VIN_WEIGHTS[i];
1442
+ const val = VIN_CHAR_VALUES[char];
1443
+ if (val === void 0) {
1444
+ return false;
1445
+ }
1446
+ sum += val * weight;
1447
+ }
1448
+ const checkDigitValue = sum % VIN_MODULUS;
1449
+ const expectedCheckDigit = checkDigitValue === 10 ? VIN_CHECK_DIGIT_X : checkDigitValue.toString();
1450
+ const actualCheckDigit = vin[VIN_CHECK_DIGIT_INDEX];
1451
+ return actualCheckDigit === expectedCheckDigit;
1452
+ }
1453
+
1264
1454
  // src/email-validator/constants.ts
1265
1455
  var EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$/;
1266
1456
  var DISPOSABLE_DOMAINS = [
@@ -1334,6 +1524,15 @@ function normalizeEmail(email) {
1334
1524
  return email.trim().toLowerCase();
1335
1525
  }
1336
1526
 
1527
+ // src/email-validator/errors.ts
1528
+ var InvalidEmailError = class extends Error {
1529
+ constructor(message = "Invalid email provided") {
1530
+ super(message);
1531
+ this.code = "INVALID_EMAIL";
1532
+ this.name = "InvalidEmailError";
1533
+ }
1534
+ };
1535
+
1337
1536
  // src/currency/format.ts
1338
1537
  function formatRupiah(amount, options) {
1339
1538
  const {
@@ -3332,6 +3531,78 @@ function similarity(str1, str2) {
3332
3531
  return 1 - distance / maxLength;
3333
3532
  }
3334
3533
 
3534
+ // src/text/mask.ts
3535
+ function maskText(text, options) {
3536
+ if (!text) return text;
3537
+ const {
3538
+ pattern = "middle",
3539
+ maskChar,
3540
+ visibleStart,
3541
+ visibleEnd,
3542
+ separator,
3543
+ start,
3544
+ end,
3545
+ char
3546
+ } = options || {};
3547
+ const hasLegacyOptions = start !== void 0 || end !== void 0 || char !== void 0;
3548
+ if (hasLegacyOptions) {
3549
+ console.warn(
3550
+ "[DEPRECATED] Mask options start/end/char are deprecated. Use visibleStart/visibleEnd/maskChar instead. These old names will be removed in v1.0.0."
3551
+ );
3552
+ }
3553
+ const effectivePattern = pattern || "middle";
3554
+ const effectiveStart = visibleStart !== void 0 ? visibleStart : start !== void 0 ? start : 2;
3555
+ const effectiveEnd = visibleEnd !== void 0 ? visibleEnd : end !== void 0 ? end : 2;
3556
+ const effectiveChar = maskChar !== void 0 ? maskChar : char !== void 0 ? char : "*";
3557
+ switch (effectivePattern) {
3558
+ case "all":
3559
+ return maskAll(text, effectiveChar);
3560
+ case "email":
3561
+ return maskEmail2(text, effectiveChar);
3562
+ case "middle":
3563
+ default:
3564
+ return maskMiddle(
3565
+ text,
3566
+ effectiveChar,
3567
+ effectiveStart,
3568
+ effectiveEnd,
3569
+ separator
3570
+ );
3571
+ }
3572
+ }
3573
+ function maskAll(text, maskChar) {
3574
+ return text.split("").map((char) => char === " " ? " " : maskChar).join("");
3575
+ }
3576
+ function maskMiddle(text, maskChar, visibleStart, visibleEnd, separator) {
3577
+ const length = text.length;
3578
+ const totalVisible = visibleStart + visibleEnd;
3579
+ if (length < totalVisible) {
3580
+ return maskChar.repeat(length);
3581
+ }
3582
+ const start = text.slice(0, visibleStart);
3583
+ const middle = maskChar.repeat(length - totalVisible);
3584
+ const end = text.slice(length - visibleEnd);
3585
+ if (separator) {
3586
+ return `${start}${separator}${middle}${separator}${end}`;
3587
+ }
3588
+ return start + middle + end;
3589
+ }
3590
+ function maskEmail2(text, maskChar) {
3591
+ const atIndex = text.indexOf("@");
3592
+ if (atIndex === -1) {
3593
+ return maskMiddle(text, maskChar, 2, 0);
3594
+ }
3595
+ const localPart = text.slice(0, atIndex);
3596
+ const domain = text.slice(atIndex);
3597
+ if (localPart.length <= 2) {
3598
+ const maskedLocal2 = localPart + maskChar.repeat(Math.max(0, 2 - localPart.length));
3599
+ return maskedLocal2 + domain;
3600
+ }
3601
+ const visibleLocal = localPart.slice(0, 2);
3602
+ const maskedLocal = visibleLocal + maskChar.repeat(localPart.length - 2);
3603
+ return maskedLocal + domain;
3604
+ }
3605
+
3335
3606
  // src/datetime/types.ts
3336
3607
  var InvalidDateError = class extends Error {
3337
3608
  constructor(message = "Invalid date provided") {
@@ -3751,6 +4022,6 @@ function getIndonesianTimezone(input) {
3751
4022
  return null;
3752
4023
  }
3753
4024
 
3754
- export { DAY_NAMES, DAY_NAMES_SHORT, InvalidDateError, InvalidDateRangeError, MONTH_NAMES, MONTH_NAMES_SHORT, TIMEZONE_MAP, VALID_UTC_OFFSETS, addRupiahSymbol, calculateTax, capitalize2 as capitalize, cleanPhoneNumber, compareStrings, contractAbbreviation, daysInMonth, expandAbbreviation, extractWords, formatAccounting, formatBirthDate, formatCompact, formatDate, formatDateRange, formatNIK, formatNPWP, formatPhoneNumber, formatPlate, formatRupiah, generateSmsLink, generateTelLink, generateWALink, getAge, getAge2 as getAgeFromDate, getEmailInfo, getIndonesianTimezone, getOperator, getRegionFromPlate, isAlay, isLandlineNumber, isLeapYear, isMobileNumber, isProvider, isValidDate, isValidForBirthDate, isValidForGender, isWeekend, isWorkingDay, maskEmail, maskNIK, maskNPWP, maskPhoneNumber, normalizeEmail, normalizeWhitespace, parseDate, parseNIK, parseNPWP, parsePhoneNumber, parseRupiah, profanityFilter, removeAccents, removeStopwords, roundToClean, sanitize, similarity, slugify, toE164, toFormal, toInternational, toNational, toRelativeTime, toSentenceCase, toTitleCase, toWords, truncate, validateEmail, validateNIK, validateNPWP, validatePhoneNumber, validatePlate, validateVIN };
4025
+ export { DAY_NAMES, DAY_NAMES_SHORT, InvalidDateError, InvalidDateRangeError, InvalidEmailError, InvalidNPWPError, InvalidPhoneError, InvalidPlateError, InvalidVINError, MONTH_NAMES, MONTH_NAMES_SHORT, TIMEZONE_MAP, VALID_UTC_OFFSETS, addRupiahSymbol, calculateTax, capitalize2 as capitalize, cleanPhoneNumber, compareStrings, contractAbbreviation, daysInMonth, expandAbbreviation, extractWords, formatAccounting, formatBirthDate, formatCompact, formatDate, formatDateRange, formatNIK, formatNPWP, formatPhoneNumber, formatPlate, formatRupiah, generateSmsLink, generateTelLink, generateWALink, getAge, getAge2 as getAgeFromDate, getEmailInfo, getIndonesianTimezone, getOperator, getRegionFromPlate, isAlay, isLandlineNumber, isLeapYear, isMobileNumber, isProvider, isValidDate, isValidForBirthDate, isValidForGender, isWeekend, isWorkingDay, maskEmail, maskNIK, maskNPWP, maskPhoneNumber, maskText, normalizeEmail, normalizeWhitespace, parseDate, parseNIK, parseNPWP, parsePhoneNumber, parsePlate, parseRupiah, parseVIN, profanityFilter, removeAccents, removeStopwords, roundToClean, sanitize, similarity, slugify, toE164, toFormal, toInternational, toNational, toRelativeTime, toSentenceCase, toTitleCase, toWords, truncate, validateEmail, validateNIK, validateNPWP, validatePhoneNumber, validatePlate, validateVIN };
3755
4026
  //# sourceMappingURL=index.js.map
3756
4027
  //# sourceMappingURL=index.js.map