@indodev/toolkit 0.3.0 → 0.3.1

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.
@@ -0,0 +1,95 @@
1
+ 'use strict';
2
+
3
+ // src/npwp/validate.ts
4
+ function validateNPWP(npwp) {
5
+ if (!npwp || typeof npwp !== "string") {
6
+ return false;
7
+ }
8
+ const cleaned = npwp.replace(/[^\d]/g, "");
9
+ if (cleaned.length !== 15 && cleaned.length !== 16) {
10
+ return false;
11
+ }
12
+ if (!/^\d+$/.test(cleaned)) {
13
+ return false;
14
+ }
15
+ return true;
16
+ }
17
+
18
+ // src/npwp/format.ts
19
+ function formatNPWP(npwp) {
20
+ if (!validateNPWP(npwp)) {
21
+ return npwp;
22
+ }
23
+ const cleaned = npwp.replace(/[^\d]/g, "");
24
+ if (cleaned.length === 15) {
25
+ return `${cleaned.substring(0, 2)}.${cleaned.substring(
26
+ 2,
27
+ 5
28
+ )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(
29
+ 9,
30
+ 12
31
+ )}.${cleaned.substring(12, 15)}`;
32
+ }
33
+ return cleaned;
34
+ }
35
+ function parseNPWP(npwp) {
36
+ if (!validateNPWP(npwp)) {
37
+ return null;
38
+ }
39
+ const cleaned = npwp.replace(/[^\d]/g, "");
40
+ const isNikBased = cleaned.length === 16;
41
+ if (isNikBased) {
42
+ return {
43
+ npwp: cleaned,
44
+ type: cleaned.substring(0, 2),
45
+ serial: cleaned.substring(2, 8),
46
+ checksum: cleaned.substring(8, 9),
47
+ taxOfficeCode: cleaned.substring(9, 12),
48
+ branchCode: cleaned.substring(12, 16),
49
+ isNikBased: true
50
+ };
51
+ }
52
+ return {
53
+ npwp: cleaned,
54
+ type: cleaned.substring(0, 2),
55
+ serial: cleaned.substring(2, 8),
56
+ checksum: cleaned.substring(8, 9),
57
+ taxOfficeCode: cleaned.substring(9, 12),
58
+ branchCode: cleaned.substring(12, 15),
59
+ isNikBased: false
60
+ };
61
+ }
62
+ function maskNPWP(npwp, options) {
63
+ if (!npwp) return "";
64
+ const { visibleStart = 2, visibleEnd = 3, maskChar = "*" } = options || {};
65
+ if (npwp.includes(".") || npwp.includes("-")) {
66
+ let digitCount = 0;
67
+ const digitsOnly = npwp.replace(/[^\d]/g, "");
68
+ const totalDigits = digitsOnly.length;
69
+ return npwp.split("").map((char) => {
70
+ if (/\d/.test(char)) {
71
+ digitCount++;
72
+ if (digitCount <= visibleStart || digitCount > totalDigits - visibleEnd) {
73
+ return char;
74
+ }
75
+ return maskChar;
76
+ }
77
+ return char;
78
+ }).join("");
79
+ }
80
+ const cleaned = npwp.replace(/[^\d]/g, "");
81
+ if (cleaned.length < visibleStart + visibleEnd) {
82
+ return cleaned.replace(/./g, maskChar);
83
+ }
84
+ const start = cleaned.substring(0, visibleStart);
85
+ const end = cleaned.substring(cleaned.length - visibleEnd);
86
+ const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);
87
+ return `${start}${middle}${end}`;
88
+ }
89
+
90
+ exports.formatNPWP = formatNPWP;
91
+ exports.maskNPWP = maskNPWP;
92
+ exports.parseNPWP = parseNPWP;
93
+ exports.validateNPWP = validateNPWP;
94
+ //# sourceMappingURL=index.cjs.map
95
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/npwp/validate.ts","../../src/npwp/format.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).\n *\n * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.\n *\n * @param npwp - The NPWP string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNPWP('01.234.567.8-012.000'); // true\n * validateNPWP('012345678012000'); // true\n * ```\n */\nexport function validateNPWP(npwp: string): boolean {\n if (!npwp || typeof npwp !== 'string') {\n return false;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n // Must be 15 or 16 digits\n if (cleaned.length !== 15 && cleaned.length !== 16) {\n return false;\n }\n\n // Basic check: all numeric\n if (!/^\\d+$/.test(cleaned)) {\n return false;\n }\n\n return true;\n}\n","import { validateNPWP } from './validate';\nimport { NPWPInfo, MaskOptions } from './types';\n\n/**\n * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).\n *\n * @param npwp - The NPWP string to format\n * @returns Formatted NPWP string, or original if invalid\n *\n * @example\n * ```typescript\n * formatNPWP('012345678012000'); // '01.234.567.8-012.000'\n * ```\n */\nexport function formatNPWP(npwp: string): string {\n if (!validateNPWP(npwp)) {\n return npwp;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length === 15) {\n return `${cleaned.substring(0, 2)}.${cleaned.substring(\n 2,\n 5\n )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(\n 9,\n 12\n )}.${cleaned.substring(12, 15)}`;\n }\n\n // 16-digit NPWP (NIK) usually doesn't have a standard \"dots\" format like 15-digit\n // but if it's NIK, it might be formatted as NIK elsewhere.\n // For now, return as is or implement a simple format.\n return cleaned;\n}\n\n/**\n * Parses an NPWP string into its components.\n *\n * @param npwp - The NPWP string to parse\n * @returns NPWPInfo object, or null if invalid\n */\nexport function parseNPWP(npwp: string): NPWPInfo | null {\n if (!validateNPWP(npwp)) {\n return null;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n const isNikBased = cleaned.length === 16;\n\n if (isNikBased) {\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 16),\n isNikBased: true,\n };\n }\n\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 15),\n isNikBased: false,\n };\n}\n\n/**\n * Masks an NPWP string for privacy.\n *\n * @param npwp - The NPWP string to mask\n * @param options - Masking options\n * @returns Masked NPWP string\n */\nexport function maskNPWP(npwp: string, options?: MaskOptions): string {\n if (!npwp) return '';\n\n const { visibleStart = 2, visibleEnd = 3, maskChar = '*' } = options || {};\n\n // If input is formatted, we mask the digits but keep the symbols in place\n if (npwp.includes('.') || npwp.includes('-')) {\n let digitCount = 0;\n const digitsOnly = npwp.replace(/[^\\d]/g, '');\n const totalDigits = digitsOnly.length;\n\n return npwp\n .split('')\n .map((char) => {\n if (/\\d/.test(char)) {\n digitCount++;\n if (\n digitCount <= visibleStart ||\n digitCount > totalDigits - visibleEnd\n ) {\n return char;\n }\n return maskChar;\n }\n return char;\n })\n .join('');\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length < visibleStart + visibleEnd) {\n return cleaned.replace(/./g, maskChar);\n }\n\n const start = cleaned.substring(0, visibleStart);\n const end = cleaned.substring(cleaned.length - visibleEnd);\n const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);\n\n return `${start}${middle}${end}`;\n}\n"]}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).
3
+ *
4
+ * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.
5
+ *
6
+ * @param npwp - The NPWP string to validate
7
+ * @returns `true` if valid, `false` otherwise
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * validateNPWP('01.234.567.8-012.000'); // true
12
+ * validateNPWP('012345678012000'); // true
13
+ * ```
14
+ */
15
+ declare function validateNPWP(npwp: string): boolean;
16
+
17
+ /**
18
+ * Information extracted from an NPWP string.
19
+ */
20
+ interface NPWPInfo {
21
+ /** The full 15 or 16 digit numeric string */
22
+ npwp: string;
23
+ /** Taxpayer type (e.g., 01-03 for individual, etc.) */
24
+ type: string;
25
+ /** Serial number */
26
+ serial: string;
27
+ /** Checksum digit */
28
+ checksum: string;
29
+ /** Tax office code */
30
+ taxOfficeCode: string;
31
+ /** Branch code (usually 000 for head office) */
32
+ branchCode: string;
33
+ /** Whether the NPWP is a 16-digit (NIK-based) NPWP */
34
+ isNikBased: boolean;
35
+ }
36
+ /**
37
+ * Options for NPWP masking.
38
+ */
39
+ interface MaskOptions {
40
+ /** Number of characters to keep visible at the start (default: 2) */
41
+ visibleStart?: number;
42
+ /** Number of characters to keep visible at the end (default: 3) */
43
+ visibleEnd?: number;
44
+ /** Character to use for masking (default: '*') */
45
+ maskChar?: string;
46
+ }
47
+
48
+ /**
49
+ * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).
50
+ *
51
+ * @param npwp - The NPWP string to format
52
+ * @returns Formatted NPWP string, or original if invalid
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * formatNPWP('012345678012000'); // '01.234.567.8-012.000'
57
+ * ```
58
+ */
59
+ declare function formatNPWP(npwp: string): string;
60
+ /**
61
+ * Parses an NPWP string into its components.
62
+ *
63
+ * @param npwp - The NPWP string to parse
64
+ * @returns NPWPInfo object, or null if invalid
65
+ */
66
+ declare function parseNPWP(npwp: string): NPWPInfo | null;
67
+ /**
68
+ * Masks an NPWP string for privacy.
69
+ *
70
+ * @param npwp - The NPWP string to mask
71
+ * @param options - Masking options
72
+ * @returns Masked NPWP string
73
+ */
74
+ declare function maskNPWP(npwp: string, options?: MaskOptions): string;
75
+
76
+ export { type MaskOptions, type NPWPInfo, formatNPWP, maskNPWP, parseNPWP, validateNPWP };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).
3
+ *
4
+ * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.
5
+ *
6
+ * @param npwp - The NPWP string to validate
7
+ * @returns `true` if valid, `false` otherwise
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * validateNPWP('01.234.567.8-012.000'); // true
12
+ * validateNPWP('012345678012000'); // true
13
+ * ```
14
+ */
15
+ declare function validateNPWP(npwp: string): boolean;
16
+
17
+ /**
18
+ * Information extracted from an NPWP string.
19
+ */
20
+ interface NPWPInfo {
21
+ /** The full 15 or 16 digit numeric string */
22
+ npwp: string;
23
+ /** Taxpayer type (e.g., 01-03 for individual, etc.) */
24
+ type: string;
25
+ /** Serial number */
26
+ serial: string;
27
+ /** Checksum digit */
28
+ checksum: string;
29
+ /** Tax office code */
30
+ taxOfficeCode: string;
31
+ /** Branch code (usually 000 for head office) */
32
+ branchCode: string;
33
+ /** Whether the NPWP is a 16-digit (NIK-based) NPWP */
34
+ isNikBased: boolean;
35
+ }
36
+ /**
37
+ * Options for NPWP masking.
38
+ */
39
+ interface MaskOptions {
40
+ /** Number of characters to keep visible at the start (default: 2) */
41
+ visibleStart?: number;
42
+ /** Number of characters to keep visible at the end (default: 3) */
43
+ visibleEnd?: number;
44
+ /** Character to use for masking (default: '*') */
45
+ maskChar?: string;
46
+ }
47
+
48
+ /**
49
+ * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).
50
+ *
51
+ * @param npwp - The NPWP string to format
52
+ * @returns Formatted NPWP string, or original if invalid
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * formatNPWP('012345678012000'); // '01.234.567.8-012.000'
57
+ * ```
58
+ */
59
+ declare function formatNPWP(npwp: string): string;
60
+ /**
61
+ * Parses an NPWP string into its components.
62
+ *
63
+ * @param npwp - The NPWP string to parse
64
+ * @returns NPWPInfo object, or null if invalid
65
+ */
66
+ declare function parseNPWP(npwp: string): NPWPInfo | null;
67
+ /**
68
+ * Masks an NPWP string for privacy.
69
+ *
70
+ * @param npwp - The NPWP string to mask
71
+ * @param options - Masking options
72
+ * @returns Masked NPWP string
73
+ */
74
+ declare function maskNPWP(npwp: string, options?: MaskOptions): string;
75
+
76
+ export { type MaskOptions, type NPWPInfo, formatNPWP, maskNPWP, parseNPWP, validateNPWP };
@@ -0,0 +1,90 @@
1
+ // src/npwp/validate.ts
2
+ function validateNPWP(npwp) {
3
+ if (!npwp || typeof npwp !== "string") {
4
+ return false;
5
+ }
6
+ const cleaned = npwp.replace(/[^\d]/g, "");
7
+ if (cleaned.length !== 15 && cleaned.length !== 16) {
8
+ return false;
9
+ }
10
+ if (!/^\d+$/.test(cleaned)) {
11
+ return false;
12
+ }
13
+ return true;
14
+ }
15
+
16
+ // src/npwp/format.ts
17
+ function formatNPWP(npwp) {
18
+ if (!validateNPWP(npwp)) {
19
+ return npwp;
20
+ }
21
+ const cleaned = npwp.replace(/[^\d]/g, "");
22
+ if (cleaned.length === 15) {
23
+ return `${cleaned.substring(0, 2)}.${cleaned.substring(
24
+ 2,
25
+ 5
26
+ )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(
27
+ 9,
28
+ 12
29
+ )}.${cleaned.substring(12, 15)}`;
30
+ }
31
+ return cleaned;
32
+ }
33
+ function parseNPWP(npwp) {
34
+ if (!validateNPWP(npwp)) {
35
+ return null;
36
+ }
37
+ const cleaned = npwp.replace(/[^\d]/g, "");
38
+ const isNikBased = cleaned.length === 16;
39
+ if (isNikBased) {
40
+ return {
41
+ npwp: cleaned,
42
+ type: cleaned.substring(0, 2),
43
+ serial: cleaned.substring(2, 8),
44
+ checksum: cleaned.substring(8, 9),
45
+ taxOfficeCode: cleaned.substring(9, 12),
46
+ branchCode: cleaned.substring(12, 16),
47
+ isNikBased: true
48
+ };
49
+ }
50
+ return {
51
+ npwp: cleaned,
52
+ type: cleaned.substring(0, 2),
53
+ serial: cleaned.substring(2, 8),
54
+ checksum: cleaned.substring(8, 9),
55
+ taxOfficeCode: cleaned.substring(9, 12),
56
+ branchCode: cleaned.substring(12, 15),
57
+ isNikBased: false
58
+ };
59
+ }
60
+ function maskNPWP(npwp, options) {
61
+ if (!npwp) return "";
62
+ const { visibleStart = 2, visibleEnd = 3, maskChar = "*" } = options || {};
63
+ if (npwp.includes(".") || npwp.includes("-")) {
64
+ let digitCount = 0;
65
+ const digitsOnly = npwp.replace(/[^\d]/g, "");
66
+ const totalDigits = digitsOnly.length;
67
+ return npwp.split("").map((char) => {
68
+ if (/\d/.test(char)) {
69
+ digitCount++;
70
+ if (digitCount <= visibleStart || digitCount > totalDigits - visibleEnd) {
71
+ return char;
72
+ }
73
+ return maskChar;
74
+ }
75
+ return char;
76
+ }).join("");
77
+ }
78
+ const cleaned = npwp.replace(/[^\d]/g, "");
79
+ if (cleaned.length < visibleStart + visibleEnd) {
80
+ return cleaned.replace(/./g, maskChar);
81
+ }
82
+ const start = cleaned.substring(0, visibleStart);
83
+ const end = cleaned.substring(cleaned.length - visibleEnd);
84
+ const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);
85
+ return `${start}${middle}${end}`;
86
+ }
87
+
88
+ export { formatNPWP, maskNPWP, parseNPWP, validateNPWP };
89
+ //# sourceMappingURL=index.js.map
90
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/npwp/validate.ts","../../src/npwp/format.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).\n *\n * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.\n *\n * @param npwp - The NPWP string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNPWP('01.234.567.8-012.000'); // true\n * validateNPWP('012345678012000'); // true\n * ```\n */\nexport function validateNPWP(npwp: string): boolean {\n if (!npwp || typeof npwp !== 'string') {\n return false;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n // Must be 15 or 16 digits\n if (cleaned.length !== 15 && cleaned.length !== 16) {\n return false;\n }\n\n // Basic check: all numeric\n if (!/^\\d+$/.test(cleaned)) {\n return false;\n }\n\n return true;\n}\n","import { validateNPWP } from './validate';\nimport { NPWPInfo, MaskOptions } from './types';\n\n/**\n * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).\n *\n * @param npwp - The NPWP string to format\n * @returns Formatted NPWP string, or original if invalid\n *\n * @example\n * ```typescript\n * formatNPWP('012345678012000'); // '01.234.567.8-012.000'\n * ```\n */\nexport function formatNPWP(npwp: string): string {\n if (!validateNPWP(npwp)) {\n return npwp;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length === 15) {\n return `${cleaned.substring(0, 2)}.${cleaned.substring(\n 2,\n 5\n )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(\n 9,\n 12\n )}.${cleaned.substring(12, 15)}`;\n }\n\n // 16-digit NPWP (NIK) usually doesn't have a standard \"dots\" format like 15-digit\n // but if it's NIK, it might be formatted as NIK elsewhere.\n // For now, return as is or implement a simple format.\n return cleaned;\n}\n\n/**\n * Parses an NPWP string into its components.\n *\n * @param npwp - The NPWP string to parse\n * @returns NPWPInfo object, or null if invalid\n */\nexport function parseNPWP(npwp: string): NPWPInfo | null {\n if (!validateNPWP(npwp)) {\n return null;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n const isNikBased = cleaned.length === 16;\n\n if (isNikBased) {\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 16),\n isNikBased: true,\n };\n }\n\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 15),\n isNikBased: false,\n };\n}\n\n/**\n * Masks an NPWP string for privacy.\n *\n * @param npwp - The NPWP string to mask\n * @param options - Masking options\n * @returns Masked NPWP string\n */\nexport function maskNPWP(npwp: string, options?: MaskOptions): string {\n if (!npwp) return '';\n\n const { visibleStart = 2, visibleEnd = 3, maskChar = '*' } = options || {};\n\n // If input is formatted, we mask the digits but keep the symbols in place\n if (npwp.includes('.') || npwp.includes('-')) {\n let digitCount = 0;\n const digitsOnly = npwp.replace(/[^\\d]/g, '');\n const totalDigits = digitsOnly.length;\n\n return npwp\n .split('')\n .map((char) => {\n if (/\\d/.test(char)) {\n digitCount++;\n if (\n digitCount <= visibleStart ||\n digitCount > totalDigits - visibleEnd\n ) {\n return char;\n }\n return maskChar;\n }\n return char;\n })\n .join('');\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length < visibleStart + visibleEnd) {\n return cleaned.replace(/./g, maskChar);\n }\n\n const start = cleaned.substring(0, visibleStart);\n const end = cleaned.substring(cleaned.length - visibleEnd);\n const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);\n\n return `${start}${middle}${end}`;\n}\n"]}
@@ -0,0 +1,99 @@
1
+ 'use strict';
2
+
3
+ // src/plate/regions.ts
4
+ var PLATE_REGIONS = {
5
+ A: "Banten",
6
+ B: "Jakarta, Depok, Tangerang, Bekasi",
7
+ D: "Bandung, Cimahi",
8
+ E: "Cirebon, Indramayu, Majalengka, Kuningan",
9
+ F: "Bogor, Cianjur, Sukabumi",
10
+ G: "Pekalongan, Pemalang, Batang, Tegal, Brebes",
11
+ H: "Semarang, Salatiga, Kendal, Demak",
12
+ K: "Pati, Kudus, Jepara, Rembang, Blora, Grobogan",
13
+ L: "Surabaya",
14
+ M: "Madura",
15
+ N: "Malang, Probolinggo, Pasuruan, Lumajang, Batu",
16
+ P: "Besuki, Bondowoso, Situbondo, Jember, Banyuwangi",
17
+ R: "Banyumas, Cilacap, Purbalinggo, Banjarnegara",
18
+ S: "Bojonegoro, Tuban, Lamongan, Jombang, Mojokerto",
19
+ T: "Purwakarta, Subang, Karawang",
20
+ AA: "Kedu, Magelang, Purworejo, Kebumen, Temanggung, Wonosobo",
21
+ AB: "Yogyakarta",
22
+ AD: "Surakarta, Boyolali, Sukoharjo, Karanganyar, Wonogiri, Sragen, Klaten",
23
+ AE: "Madiun, Ngawi, Magetan, Ponorogo, Pacitan",
24
+ AG: "Kediri, Blitar, Tulungagung, Nganjuk, Trenggalek",
25
+ BA: "Sumatera Barat",
26
+ BB: "Sumatera Utara (Pantai Barat)",
27
+ BD: "Bengkulu",
28
+ BE: "Lampung",
29
+ BG: "Sumatera Selatan",
30
+ BH: "Jambi",
31
+ BK: "Sumatera Utara (Pantai Timur)",
32
+ BL: "Aceh",
33
+ BM: "Riau",
34
+ BN: "Kepulauan Bangka Belitung",
35
+ BP: "Kepulauan Riau",
36
+ DA: "Kalimantan Selatan",
37
+ DB: "Sulawesi Utara (Daratan)",
38
+ DC: "Sulawesi Barat",
39
+ DD: "Sulawesi Selatan (Selatan)",
40
+ DE: "Maluku",
41
+ DF: "Timor Timur (Historical)",
42
+ DG: "Maluku Utara",
43
+ DH: "NTT (Timor)",
44
+ DK: "Bali",
45
+ DL: "Sulawesi Utara (Kepulauan)",
46
+ DM: "Gorontalo",
47
+ DN: "Sulawesi Tengah",
48
+ DP: "Sulawesi Selatan (Utara)",
49
+ DR: "NTB (Lombok)",
50
+ DS: "Papua",
51
+ DT: "Sulawesi Tenggara",
52
+ EA: "NTB (Sumbawa)",
53
+ EB: "NTT (Flores)",
54
+ ED: "NTT (Sumba)",
55
+ KB: "Kalimantan Barat",
56
+ KH: "Kalimantan Tengah",
57
+ KT: "Kalimantan Timur",
58
+ KU: "Kalimantan Utara",
59
+ PA: "Papua",
60
+ PB: "Papua Barat"
61
+ };
62
+
63
+ // src/plate/utils.ts
64
+ function validatePlate(plate) {
65
+ if (!plate || typeof plate !== "string") {
66
+ return false;
67
+ }
68
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
69
+ const regex = /^[A-Z]{1,2}\d{1,4}[A-Z]{1,3}$/;
70
+ return regex.test(cleaned);
71
+ }
72
+ function getRegionFromPlate(plate) {
73
+ if (!plate || typeof plate !== "string") {
74
+ return null;
75
+ }
76
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
77
+ const match = cleaned.match(/^([A-Z]{1,2})/);
78
+ if (!match) {
79
+ return null;
80
+ }
81
+ const prefix = match[1];
82
+ return PLATE_REGIONS[prefix] || null;
83
+ }
84
+ function formatPlate(plate) {
85
+ if (!plate) return "";
86
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
87
+ const match = cleaned.match(/^([A-Z]{1,2})(\d{1,4})([A-Z]{1,3})$/);
88
+ if (!match) {
89
+ return cleaned;
90
+ }
91
+ return `${match[1]} ${match[2]} ${match[3]}`;
92
+ }
93
+
94
+ exports.PLATE_REGIONS = PLATE_REGIONS;
95
+ exports.formatPlate = formatPlate;
96
+ exports.getRegionFromPlate = getRegionFromPlate;
97
+ exports.validatePlate = validatePlate;
98
+ //# sourceMappingURL=index.cjs.map
99
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plate/regions.ts","../../src/plate/utils.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Mapping of Indonesian license plate prefixes to their regions.\n */\nexport const PLATE_REGIONS: Record<string, string> = {\n A: 'Banten',\n B: 'Jakarta, Depok, Tangerang, Bekasi',\n D: 'Bandung, Cimahi',\n E: 'Cirebon, Indramayu, Majalengka, Kuningan',\n F: 'Bogor, Cianjur, Sukabumi',\n G: 'Pekalongan, Pemalang, Batang, Tegal, Brebes',\n H: 'Semarang, Salatiga, Kendal, Demak',\n K: 'Pati, Kudus, Jepara, Rembang, Blora, Grobogan',\n L: 'Surabaya',\n M: 'Madura',\n N: 'Malang, Probolinggo, Pasuruan, Lumajang, Batu',\n P: 'Besuki, Bondowoso, Situbondo, Jember, Banyuwangi',\n R: 'Banyumas, Cilacap, Purbalinggo, Banjarnegara',\n S: 'Bojonegoro, Tuban, Lamongan, Jombang, Mojokerto',\n T: 'Purwakarta, Subang, Karawang',\n AA: 'Kedu, Magelang, Purworejo, Kebumen, Temanggung, Wonosobo',\n AB: 'Yogyakarta',\n AD: 'Surakarta, Boyolali, Sukoharjo, Karanganyar, Wonogiri, Sragen, Klaten',\n AE: 'Madiun, Ngawi, Magetan, Ponorogo, Pacitan',\n AG: 'Kediri, Blitar, Tulungagung, Nganjuk, Trenggalek',\n BA: 'Sumatera Barat',\n BB: 'Sumatera Utara (Pantai Barat)',\n BD: 'Bengkulu',\n BE: 'Lampung',\n BG: 'Sumatera Selatan',\n BH: 'Jambi',\n BK: 'Sumatera Utara (Pantai Timur)',\n BL: 'Aceh',\n BM: 'Riau',\n BN: 'Kepulauan Bangka Belitung',\n BP: 'Kepulauan Riau',\n DA: 'Kalimantan Selatan',\n DB: 'Sulawesi Utara (Daratan)',\n DC: 'Sulawesi Barat',\n DD: 'Sulawesi Selatan (Selatan)',\n DE: 'Maluku',\n DF: 'Timor Timur (Historical)',\n DG: 'Maluku Utara',\n DH: 'NTT (Timor)',\n DK: 'Bali',\n DL: 'Sulawesi Utara (Kepulauan)',\n DM: 'Gorontalo',\n DN: 'Sulawesi Tengah',\n DP: 'Sulawesi Selatan (Utara)',\n DR: 'NTB (Lombok)',\n DS: 'Papua',\n DT: 'Sulawesi Tenggara',\n EA: 'NTB (Sumbawa)',\n EB: 'NTT (Flores)',\n ED: 'NTT (Sumba)',\n KB: 'Kalimantan Barat',\n KH: 'Kalimantan Tengah',\n KT: 'Kalimantan Timur',\n KU: 'Kalimantan Utara',\n PA: 'Papua',\n PB: 'Papua Barat',\n};\n","import { PLATE_REGIONS } from './regions';\n\n/**\n * Validates an Indonesian license plate number format.\n * Format: [1-2 letters] [1-4 digits] [1-3 letters]\n *\n * @param plate - The plate number string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validatePlate('B 1234 ABC'); // true\n * validatePlate('AB 1 CD'); // true\n * ```\n */\nexport function validatePlate(plate: string): boolean {\n if (!plate || typeof plate !== 'string') {\n return false;\n }\n\n const cleaned = plate.replace(/\\s+/g, '').toUpperCase();\n const regex = /^[A-Z]{1,2}\\d{1,4}[A-Z]{1,3}$/;\n\n return regex.test(cleaned);\n}\n\n/**\n * Gets the region name from a license plate number.\n *\n * @param plate - The plate number\n * @returns Region name or null if not found\n */\nexport function getRegionFromPlate(plate: string): string | null {\n if (!plate || typeof plate !== 'string') {\n return null;\n }\n\n const cleaned = plate.replace(/\\s+/g, '').toUpperCase();\n const match = cleaned.match(/^([A-Z]{1,2})/);\n\n if (!match) {\n return null;\n }\n\n const prefix = match[1];\n return PLATE_REGIONS[prefix] || null;\n}\n\n/**\n * Formats a license plate number with spaces (e.g., B 1234 ABC).\n *\n * @param plate - The plate number\n * @returns Formatted plate string\n */\nexport function formatPlate(plate: string): string {\n if (!plate) return '';\n\n const cleaned = plate.replace(/\\s+/g, '').toUpperCase();\n const match = cleaned.match(/^([A-Z]{1,2})(\\d{1,4})([A-Z]{1,3})$/);\n\n if (!match) {\n return cleaned;\n }\n\n return `${match[1]} ${match[2]} ${match[3]}`;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ export { f as formatPlate, g as getRegionFromPlate, v as validatePlate } from '../utils-DDVlOusI.cjs';
2
+
3
+ /**
4
+ * Mapping of Indonesian license plate prefixes to their regions.
5
+ */
6
+ declare const PLATE_REGIONS: Record<string, string>;
7
+
8
+ export { PLATE_REGIONS };
@@ -0,0 +1,8 @@
1
+ export { f as formatPlate, g as getRegionFromPlate, v as validatePlate } from '../utils-DDVlOusI.js';
2
+
3
+ /**
4
+ * Mapping of Indonesian license plate prefixes to their regions.
5
+ */
6
+ declare const PLATE_REGIONS: Record<string, string>;
7
+
8
+ export { PLATE_REGIONS };
@@ -0,0 +1,94 @@
1
+ // src/plate/regions.ts
2
+ var PLATE_REGIONS = {
3
+ A: "Banten",
4
+ B: "Jakarta, Depok, Tangerang, Bekasi",
5
+ D: "Bandung, Cimahi",
6
+ E: "Cirebon, Indramayu, Majalengka, Kuningan",
7
+ F: "Bogor, Cianjur, Sukabumi",
8
+ G: "Pekalongan, Pemalang, Batang, Tegal, Brebes",
9
+ H: "Semarang, Salatiga, Kendal, Demak",
10
+ K: "Pati, Kudus, Jepara, Rembang, Blora, Grobogan",
11
+ L: "Surabaya",
12
+ M: "Madura",
13
+ N: "Malang, Probolinggo, Pasuruan, Lumajang, Batu",
14
+ P: "Besuki, Bondowoso, Situbondo, Jember, Banyuwangi",
15
+ R: "Banyumas, Cilacap, Purbalinggo, Banjarnegara",
16
+ S: "Bojonegoro, Tuban, Lamongan, Jombang, Mojokerto",
17
+ T: "Purwakarta, Subang, Karawang",
18
+ AA: "Kedu, Magelang, Purworejo, Kebumen, Temanggung, Wonosobo",
19
+ AB: "Yogyakarta",
20
+ AD: "Surakarta, Boyolali, Sukoharjo, Karanganyar, Wonogiri, Sragen, Klaten",
21
+ AE: "Madiun, Ngawi, Magetan, Ponorogo, Pacitan",
22
+ AG: "Kediri, Blitar, Tulungagung, Nganjuk, Trenggalek",
23
+ BA: "Sumatera Barat",
24
+ BB: "Sumatera Utara (Pantai Barat)",
25
+ BD: "Bengkulu",
26
+ BE: "Lampung",
27
+ BG: "Sumatera Selatan",
28
+ BH: "Jambi",
29
+ BK: "Sumatera Utara (Pantai Timur)",
30
+ BL: "Aceh",
31
+ BM: "Riau",
32
+ BN: "Kepulauan Bangka Belitung",
33
+ BP: "Kepulauan Riau",
34
+ DA: "Kalimantan Selatan",
35
+ DB: "Sulawesi Utara (Daratan)",
36
+ DC: "Sulawesi Barat",
37
+ DD: "Sulawesi Selatan (Selatan)",
38
+ DE: "Maluku",
39
+ DF: "Timor Timur (Historical)",
40
+ DG: "Maluku Utara",
41
+ DH: "NTT (Timor)",
42
+ DK: "Bali",
43
+ DL: "Sulawesi Utara (Kepulauan)",
44
+ DM: "Gorontalo",
45
+ DN: "Sulawesi Tengah",
46
+ DP: "Sulawesi Selatan (Utara)",
47
+ DR: "NTB (Lombok)",
48
+ DS: "Papua",
49
+ DT: "Sulawesi Tenggara",
50
+ EA: "NTB (Sumbawa)",
51
+ EB: "NTT (Flores)",
52
+ ED: "NTT (Sumba)",
53
+ KB: "Kalimantan Barat",
54
+ KH: "Kalimantan Tengah",
55
+ KT: "Kalimantan Timur",
56
+ KU: "Kalimantan Utara",
57
+ PA: "Papua",
58
+ PB: "Papua Barat"
59
+ };
60
+
61
+ // src/plate/utils.ts
62
+ function validatePlate(plate) {
63
+ if (!plate || typeof plate !== "string") {
64
+ return false;
65
+ }
66
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
67
+ const regex = /^[A-Z]{1,2}\d{1,4}[A-Z]{1,3}$/;
68
+ return regex.test(cleaned);
69
+ }
70
+ function getRegionFromPlate(plate) {
71
+ if (!plate || typeof plate !== "string") {
72
+ return null;
73
+ }
74
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
75
+ const match = cleaned.match(/^([A-Z]{1,2})/);
76
+ if (!match) {
77
+ return null;
78
+ }
79
+ const prefix = match[1];
80
+ return PLATE_REGIONS[prefix] || null;
81
+ }
82
+ function formatPlate(plate) {
83
+ if (!plate) return "";
84
+ const cleaned = plate.replace(/\s+/g, "").toUpperCase();
85
+ const match = cleaned.match(/^([A-Z]{1,2})(\d{1,4})([A-Z]{1,3})$/);
86
+ if (!match) {
87
+ return cleaned;
88
+ }
89
+ return `${match[1]} ${match[2]} ${match[3]}`;
90
+ }
91
+
92
+ export { PLATE_REGIONS, formatPlate, getRegionFromPlate, validatePlate };
93
+ //# sourceMappingURL=index.js.map
94
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plate/regions.ts","../../src/plate/utils.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Mapping of Indonesian license plate prefixes to their regions.\n */\nexport const PLATE_REGIONS: Record<string, string> = {\n A: 'Banten',\n B: 'Jakarta, Depok, Tangerang, Bekasi',\n D: 'Bandung, Cimahi',\n E: 'Cirebon, Indramayu, Majalengka, Kuningan',\n F: 'Bogor, Cianjur, Sukabumi',\n G: 'Pekalongan, Pemalang, Batang, Tegal, Brebes',\n H: 'Semarang, Salatiga, Kendal, Demak',\n K: 'Pati, Kudus, Jepara, Rembang, Blora, Grobogan',\n L: 'Surabaya',\n M: 'Madura',\n N: 'Malang, Probolinggo, Pasuruan, Lumajang, Batu',\n P: 'Besuki, Bondowoso, Situbondo, Jember, Banyuwangi',\n R: 'Banyumas, Cilacap, Purbalinggo, Banjarnegara',\n S: 'Bojonegoro, Tuban, Lamongan, Jombang, Mojokerto',\n T: 'Purwakarta, Subang, Karawang',\n AA: 'Kedu, Magelang, Purworejo, Kebumen, Temanggung, Wonosobo',\n AB: 'Yogyakarta',\n AD: 'Surakarta, Boyolali, Sukoharjo, Karanganyar, Wonogiri, Sragen, Klaten',\n AE: 'Madiun, Ngawi, Magetan, Ponorogo, Pacitan',\n AG: 'Kediri, Blitar, Tulungagung, Nganjuk, Trenggalek',\n BA: 'Sumatera Barat',\n BB: 'Sumatera Utara (Pantai Barat)',\n BD: 'Bengkulu',\n BE: 'Lampung',\n BG: 'Sumatera Selatan',\n BH: 'Jambi',\n BK: 'Sumatera Utara (Pantai Timur)',\n BL: 'Aceh',\n BM: 'Riau',\n BN: 'Kepulauan Bangka Belitung',\n BP: 'Kepulauan Riau',\n DA: 'Kalimantan Selatan',\n DB: 'Sulawesi Utara (Daratan)',\n DC: 'Sulawesi Barat',\n DD: 'Sulawesi Selatan (Selatan)',\n DE: 'Maluku',\n DF: 'Timor Timur (Historical)',\n DG: 'Maluku Utara',\n DH: 'NTT (Timor)',\n DK: 'Bali',\n DL: 'Sulawesi Utara (Kepulauan)',\n DM: 'Gorontalo',\n DN: 'Sulawesi Tengah',\n DP: 'Sulawesi Selatan (Utara)',\n DR: 'NTB (Lombok)',\n DS: 'Papua',\n DT: 'Sulawesi Tenggara',\n EA: 'NTB (Sumbawa)',\n EB: 'NTT (Flores)',\n ED: 'NTT (Sumba)',\n KB: 'Kalimantan Barat',\n KH: 'Kalimantan Tengah',\n KT: 'Kalimantan Timur',\n KU: 'Kalimantan Utara',\n PA: 'Papua',\n PB: 'Papua Barat',\n};\n","import { PLATE_REGIONS } from './regions';\n\n/**\n * Validates an Indonesian license plate number format.\n * Format: [1-2 letters] [1-4 digits] [1-3 letters]\n *\n * @param plate - The plate number string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validatePlate('B 1234 ABC'); // true\n * validatePlate('AB 1 CD'); // true\n * ```\n */\nexport function validatePlate(plate: string): boolean {\n if (!plate || typeof plate !== 'string') {\n return false;\n }\n\n const cleaned = plate.replace(/\\s+/g, '').toUpperCase();\n const regex = /^[A-Z]{1,2}\\d{1,4}[A-Z]{1,3}$/;\n\n return regex.test(cleaned);\n}\n\n/**\n * Gets the region name from a license plate number.\n *\n * @param plate - The plate number\n * @returns Region name or null if not found\n */\nexport function getRegionFromPlate(plate: string): string | null {\n if (!plate || typeof plate !== 'string') {\n return null;\n }\n\n const cleaned = plate.replace(/\\s+/g, '').toUpperCase();\n const match = cleaned.match(/^([A-Z]{1,2})/);\n\n if (!match) {\n return null;\n }\n\n const prefix = match[1];\n return PLATE_REGIONS[prefix] || null;\n}\n\n/**\n * Formats a license plate number with spaces (e.g., B 1234 ABC).\n *\n * @param plate - The plate number\n * @returns Formatted plate string\n */\nexport function formatPlate(plate: string): string {\n if (!plate) return '';\n\n const cleaned = plate.replace(/\\s+/g, '').toUpperCase();\n const match = cleaned.match(/^([A-Z]{1,2})(\\d{1,4})([A-Z]{1,3})$/);\n\n if (!match) {\n return cleaned;\n }\n\n return `${match[1]} ${match[2]} ${match[3]}`;\n}\n"]}
@@ -1,4 +1,4 @@
1
- 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, j as extractWords, i as isAlay, n as normalizeWhitespace, p as profanityFilter, r as removeAccents, f as removeStopwords, b as sanitize, l as similarity, s as slugify, g as toFormal, a as toSentenceCase, t as toTitleCase, h as truncate } from '../compare-BIodyGn7.cjs';
1
+ 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-CZadJMGl.cjs';
2
2
 
3
3
  /**
4
4
  * ============================================================================
@@ -1,4 +1,4 @@
1
- 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, j as extractWords, i as isAlay, n as normalizeWhitespace, p as profanityFilter, r as removeAccents, f as removeStopwords, b as sanitize, l as similarity, s as slugify, g as toFormal, a as toSentenceCase, t as toTitleCase, h as truncate } from '../compare-BIodyGn7.js';
1
+ 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-CZadJMGl.js';
2
2
 
3
3
  /**
4
4
  * ============================================================================