@indodev/toolkit 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { NIKInfo, MaskOptions as NIKMaskOptions, formatBirthDate, formatNIK, getAge, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK } from './nik/index.cjs';
2
- export { PhoneFormat, PhoneInfo, MaskOptions as PhoneMaskOptions, cleanPhoneNumber, formatPhoneNumber, generateSmsLink, generateTelLink, generateWALink, getOperator, isLandlineNumber, isMobileNumber, isProvider, maskPhoneNumber, parsePhoneNumber, toE164, toInternational, toNational, validatePhoneNumber } from './phone/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-BDfy3aQw.cjs';
3
3
  export { NPWPInfo, MaskOptions as NPWPMaskOptions, formatNPWP, maskNPWP, parseNPWP, validateNPWP } from './npwp/index.cjs';
4
4
  export { f as formatPlate, g as getRegionFromPlate, v as validatePlate } from './utils-DDVlOusI.cjs';
5
5
  export { V as VINOptions, a as VINValidationResult, v as validateVIN } from './types-i5e6R0AS.cjs';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { NIKInfo, MaskOptions as NIKMaskOptions, formatBirthDate, formatNIK, getAge, isValidForBirthDate, isValidForGender, maskNIK, parseNIK, validateNIK } from './nik/index.js';
2
- export { PhoneFormat, PhoneInfo, MaskOptions as PhoneMaskOptions, cleanPhoneNumber, formatPhoneNumber, generateSmsLink, generateTelLink, generateWALink, getOperator, isLandlineNumber, isMobileNumber, isProvider, maskPhoneNumber, parsePhoneNumber, toE164, toInternational, toNational, validatePhoneNumber } from './phone/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-BDfy3aQw.js';
3
3
  export { NPWPInfo, MaskOptions as NPWPMaskOptions, formatNPWP, maskNPWP, parseNPWP, validateNPWP } from './npwp/index.js';
4
4
  export { f as formatPlate, g as getRegionFromPlate, v as validatePlate } from './utils-DDVlOusI.js';
5
5
  export { V as VINOptions, a as VINValidationResult, v as validateVIN } from './types-i5e6R0AS.js';
package/dist/index.js CHANGED
@@ -57,53 +57,66 @@ var REGENCIES = {
57
57
  }
58
58
  };
59
59
 
60
- // src/nik/validate.ts
61
- function validateNIK(nik) {
62
- if (!/^\d{16}$/.test(nik)) {
63
- return false;
64
- }
65
- const provinceCode = nik.substring(0, 2);
66
- if (!PROVINCES[provinceCode]) {
67
- return false;
60
+ // src/nik/utils/date.ts
61
+ function parseNIKDate(nik) {
62
+ if (nik.length !== 16) {
63
+ return null;
68
64
  }
69
65
  const yearStr = nik.substring(6, 8);
70
66
  const monthStr = nik.substring(8, 10);
71
- const dayStr = nik.substring(10, 12);
67
+ const dayEncodedStr = nik.substring(10, 12);
72
68
  const year = parseInt(yearStr, 10);
69
+ if (isNaN(year)) return null;
73
70
  const fullYear = year > 30 ? 1900 + year : 2e3 + year;
74
71
  const month = parseInt(monthStr, 10);
75
- let day = parseInt(dayStr, 10);
76
- if (day > 40) {
77
- day = day - 40;
72
+ if (isNaN(month)) return null;
73
+ const dayEncoded = parseInt(dayEncodedStr, 10);
74
+ if (isNaN(dayEncoded)) return null;
75
+ const gender = dayEncoded > 40 ? "female" : "male";
76
+ const day = dayEncoded > 40 ? dayEncoded - 40 : dayEncoded;
77
+ return { year, fullYear, month, day, gender, dayEncoded };
78
+ }
79
+ function validateNIKDateComponents(year, month, day) {
80
+ if (month < 1 || month > 12) return false;
81
+ if (day < 1 || day > 31) return false;
82
+ const testDate = new Date(year, month - 1, day);
83
+ return testDate.getFullYear() === year && testDate.getMonth() === month - 1 && testDate.getDate() === day;
84
+ }
85
+
86
+ // src/nik/validate.ts
87
+ var NIK_PATTERN = /^\d{16}$/;
88
+ function validateNIK(nik) {
89
+ if (!NIK_PATTERN.test(nik)) {
90
+ return false;
78
91
  }
79
- if (month < 1 || month > 12) {
92
+ const provinceCode = nik.substring(0, 2);
93
+ if (!PROVINCES[provinceCode]) {
80
94
  return false;
81
95
  }
82
- if (day < 1 || day > 31) {
96
+ const parsed = parseNIKDate(nik);
97
+ if (!parsed) {
83
98
  return false;
84
99
  }
85
- const testDate = new Date(fullYear, month - 1, day);
86
- if (testDate.getFullYear() !== fullYear || testDate.getMonth() !== month - 1 || testDate.getDate() !== day) {
100
+ const { fullYear, month, day } = parsed;
101
+ if (!validateNIKDateComponents(fullYear, month, day)) {
87
102
  return false;
88
103
  }
89
104
  const now = /* @__PURE__ */ new Date();
90
- if (testDate > now || testDate < new Date(1900, 0, 1)) {
105
+ if (new Date(fullYear, month - 1, day) > now || fullYear < 1900) {
91
106
  return false;
92
107
  }
93
108
  return true;
94
109
  }
95
110
 
96
111
  // src/nik/parse.ts
112
+ var NIK_PATTERN2 = /^\d{16}$/;
97
113
  function parseNIK(nik) {
98
- if (!/^\d{16}$/.test(nik)) {
114
+ if (!NIK_PATTERN2.test(nik)) {
99
115
  return null;
100
116
  }
101
117
  const provinceCode = nik.substring(0, 2);
102
118
  const regencyCode = nik.substring(2, 4);
103
119
  const districtCode = nik.substring(4, 6);
104
- const yearStr = nik.substring(6, 8);
105
- const monthStr = nik.substring(8, 10);
106
- const dayStr = nik.substring(10, 12);
107
120
  const serialNumber = nik.substring(12, 16);
108
121
  const province = PROVINCES[provinceCode];
109
122
  if (!province) {
@@ -111,21 +124,15 @@ function parseNIK(nik) {
111
124
  }
112
125
  const regencies = REGENCIES[provinceCode] || {};
113
126
  const regency = regencies[regencyCode] || "Unknown";
114
- let day = parseInt(dayStr, 10);
115
- const month = parseInt(monthStr, 10);
116
- const year = parseInt(yearStr, 10);
117
- let gender = null;
118
- if (day > 40) {
119
- gender = "female";
120
- day -= 40;
121
- } else {
122
- gender = "male";
127
+ const parsed = parseNIKDate(nik);
128
+ if (!parsed) {
129
+ return null;
123
130
  }
124
- const fullYear = year > 30 ? 1900 + year : 2e3 + year;
125
- const birthDate = new Date(fullYear, month - 1, day);
126
- if (birthDate.getFullYear() !== fullYear || birthDate.getMonth() !== month - 1 || birthDate.getDate() !== day) {
131
+ const { fullYear, month, day, gender } = parsed;
132
+ if (!validateNIKDateComponents(fullYear, month, day)) {
127
133
  return null;
128
134
  }
135
+ const birthDate = new Date(fullYear, month - 1, day);
129
136
  return {
130
137
  province: {
131
138
  code: provinceCode,
@@ -715,7 +722,7 @@ function isMobileNumber(phone) {
715
722
  let normalized;
716
723
  if (cleaned.startsWith("+62")) {
717
724
  normalized = "0" + cleaned.substring(3);
718
- } else if (cleaned.startsWith("62")) {
725
+ } else if (cleaned.startsWith("62") && !cleaned.startsWith("620")) {
719
726
  normalized = "0" + cleaned.substring(2);
720
727
  } else {
721
728
  normalized = cleaned;
@@ -729,19 +736,70 @@ function isLandlineNumber(phone) {
729
736
  return !isMobileNumber(phone);
730
737
  }
731
738
 
739
+ // src/phone/utils.ts
740
+ function normalizePhoneNumber(phone) {
741
+ if (!phone || typeof phone !== "string") {
742
+ return "";
743
+ }
744
+ if (phone.startsWith("+62")) {
745
+ return "0" + phone.substring(3);
746
+ }
747
+ if (phone.startsWith("62") && !phone.startsWith("620")) {
748
+ return "0" + phone.substring(2);
749
+ }
750
+ if (phone.startsWith("0")) {
751
+ return phone;
752
+ }
753
+ return "";
754
+ }
755
+ function normalizeToNational(phone) {
756
+ if (phone.startsWith("+62")) {
757
+ return "0" + phone.substring(3);
758
+ }
759
+ if (phone.startsWith("62") && !phone.startsWith("620")) {
760
+ return "0" + phone.substring(2);
761
+ }
762
+ if (phone.startsWith("0")) {
763
+ return phone;
764
+ }
765
+ return "";
766
+ }
767
+ function getLandlineRegion(phone) {
768
+ if (!phone || typeof phone !== "string") {
769
+ return null;
770
+ }
771
+ const cleaned = phone.replace(/[^\d+]/g, "");
772
+ const normalized = normalizeToNational(cleaned);
773
+ if (!normalized || !normalized.startsWith("0")) {
774
+ return null;
775
+ }
776
+ if (normalized.startsWith("08")) {
777
+ return null;
778
+ }
779
+ const areaCode4 = normalized.substring(0, 4);
780
+ if (AREA_CODES[areaCode4]) {
781
+ return AREA_CODES[areaCode4];
782
+ }
783
+ const areaCode3 = normalized.substring(0, 3);
784
+ if (AREA_CODES[areaCode3]) {
785
+ return AREA_CODES[areaCode3];
786
+ }
787
+ const areaCode2 = normalized.substring(0, 2);
788
+ if (AREA_CODES[areaCode2]) {
789
+ return AREA_CODES[areaCode2];
790
+ }
791
+ return null;
792
+ }
793
+
732
794
  // src/phone/format.ts
733
795
  function formatPhoneNumber(phone, format = "national") {
734
796
  if (!validatePhoneNumber(phone)) {
735
797
  return phone;
736
798
  }
737
799
  const cleaned = cleanPhoneNumber(phone);
738
- let normalized;
739
- if (cleaned.startsWith("+62")) {
740
- normalized = "0" + cleaned.substring(3);
741
- } else if (cleaned.startsWith("62") && !cleaned.startsWith("620")) {
742
- normalized = "0" + cleaned.substring(2);
743
- } else {
744
- normalized = cleaned;
800
+ const normalized = normalizePhoneNumber(cleaned);
801
+ if (!normalized) {
802
+ return phone;
745
803
  }
746
804
  switch (format) {
747
805
  case "international":
@@ -760,7 +818,7 @@ function toInternational(phone) {
760
818
  if (!cleaned) {
761
819
  return phone;
762
820
  }
763
- const normalized = normalizeToNational(cleaned);
821
+ const normalized = normalizePhoneNumber(cleaned);
764
822
  if (!normalized) {
765
823
  return phone;
766
824
  }
@@ -786,7 +844,7 @@ function toNational(phone) {
786
844
  if (!cleaned) {
787
845
  return phone;
788
846
  }
789
- const normalized = normalizeToNational(cleaned);
847
+ const normalized = normalizePhoneNumber(cleaned);
790
848
  if (!normalized) {
791
849
  return phone;
792
850
  }
@@ -811,7 +869,7 @@ function toE164(phone) {
811
869
  if (!cleaned) {
812
870
  return phone;
813
871
  }
814
- const normalized = normalizeToNational(cleaned);
872
+ const normalized = normalizePhoneNumber(cleaned);
815
873
  if (!normalized) {
816
874
  return phone;
817
875
  }
@@ -823,16 +881,6 @@ function cleanPhoneNumber(phone) {
823
881
  }
824
882
  return phone.replace(/[^\d+]/g, "");
825
883
  }
826
- function normalizeToNational(phone) {
827
- if (phone.startsWith("+62")) {
828
- return "0" + phone.substring(3);
829
- } else if (phone.startsWith("62") && !phone.startsWith("620")) {
830
- return "0" + phone.substring(2);
831
- } else if (phone.startsWith("0")) {
832
- return phone;
833
- }
834
- return "";
835
- }
836
884
  function getAreaCodeLength(normalized) {
837
885
  const fourDigitCode = normalized.substring(0, 5);
838
886
  if (AREA_CODES[fourDigitCode]) {
@@ -858,7 +906,7 @@ function maskPhoneNumber(phone, options = {}) {
858
906
  if (isInternational) {
859
907
  toMask = cleaned;
860
908
  } else {
861
- const normalized = normalizeToNational(cleaned);
909
+ const normalized = normalizePhoneNumber(cleaned);
862
910
  toMask = normalized || cleaned;
863
911
  }
864
912
  if (toMask.length < 4) {
@@ -927,7 +975,7 @@ function parsePhoneNumber(phone) {
927
975
  return null;
928
976
  }
929
977
  const cleaned = cleanPhoneNumber(phone);
930
- const normalized = normalizeToNational2(cleaned);
978
+ const normalized = normalizePhoneNumber(cleaned);
931
979
  if (!normalized) {
932
980
  return null;
933
981
  }
@@ -940,7 +988,7 @@ function parsePhoneNumber(phone) {
940
988
  if (isMobile) {
941
989
  operator = getOperator(normalized);
942
990
  } else {
943
- region = getRegion(normalized);
991
+ region = getLandlineRegion(normalized);
944
992
  }
945
993
  return {
946
994
  countryCode,
@@ -962,7 +1010,7 @@ function getOperator(phone) {
962
1010
  return null;
963
1011
  }
964
1012
  const cleaned = cleanPhoneNumber(phone);
965
- const normalized = normalizeToNational2(cleaned);
1013
+ const normalized = normalizePhoneNumber(cleaned);
966
1014
  if (!normalized || normalized.length < 4) {
967
1015
  return null;
968
1016
  }
@@ -976,30 +1024,6 @@ function isProvider(phone, providerName) {
976
1024
  }
977
1025
  return operator.toLowerCase() === providerName.toLowerCase();
978
1026
  }
979
- function getRegion(phone) {
980
- if (!phone.startsWith("0")) {
981
- return null;
982
- }
983
- const areaCode4 = phone.substring(0, 4);
984
- if (AREA_CODES[areaCode4]) {
985
- return AREA_CODES[areaCode4];
986
- }
987
- const areaCode3 = phone.substring(0, 3);
988
- if (AREA_CODES[areaCode3]) {
989
- return AREA_CODES[areaCode3];
990
- }
991
- return null;
992
- }
993
- function normalizeToNational2(phone) {
994
- if (phone.startsWith("+62")) {
995
- return "0" + phone.substring(3);
996
- } else if (phone.startsWith("62")) {
997
- return "0" + phone.substring(2);
998
- } else if (phone.startsWith("0")) {
999
- return phone;
1000
- }
1001
- return "";
1002
- }
1003
1027
 
1004
1028
  // src/npwp/validate.ts
1005
1029
  function validateNPWP(npwp) {