indian-gst-validator 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ayush Kumar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+
2
+ # 🇮🇳 Indian GST Validator
3
+
4
+ A lightweight JavaScript library to validate Indian GSTIN (Goods and Services Tax Identification Number) and extract useful information from it.
5
+
6
+ `indian-gst-validator` helps developers validate GSTIN format, verify checksum, extract PAN, and identify the state and GST holder type — all without making an API call.
7
+
8
+ ## Features
9
+
10
+ - Validate GSTIN format
11
+ - Verify GSTIN checksum
12
+ - Extract PAN from GSTIN
13
+ - Get state name from GST state code
14
+ - Identify GST holder type
15
+ - Validate PAN format
16
+ - Lightweight and easy to use
17
+ - No external API or dependencies required
18
+
19
+ ## Installation
20
+
21
+ Install the package using npm:
22
+
23
+ ```bash
24
+ npm install indian-gst-validator
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```js
30
+ const {
31
+ isValidGST,
32
+ getStateFromGST,
33
+ extractPAN,
34
+ getGSTHolderType
35
+ } = require("indian-gst-validator");
36
+
37
+ const gstin = "27AAPFU0939F1ZV";
38
+
39
+ // Validate GSTIN
40
+ console.log(isValidGST(gstin));
41
+
42
+ // Get state name
43
+ console.log(getStateFromGST(gstin));
44
+
45
+ // Extract PAN
46
+ console.log(extractPAN(gstin));
47
+
48
+ // Get GST holder type
49
+ console.log(getGSTHolderType(gstin));
50
+ ```
51
+
52
+ ## API Reference
53
+
54
+ ### `isValidGST(gstin)`
55
+
56
+ Checks whether the provided GSTIN has a valid format and checksum.
57
+
58
+ ```js
59
+ isValidGST("27AAPFU0939F1ZV");
60
+ // true or false
61
+ ```
62
+
63
+ ### `getStateFromGST(gstin)`
64
+
65
+ Returns the state or UT name associated with the GSTIN state code.
66
+
67
+ ```js
68
+ getStateFromGST("27AAPFU0939F1ZV");
69
+ // "Maharashtra"
70
+ ```
71
+
72
+ ### `extractPAN(gstin)`
73
+
74
+ Extracts the PAN embedded in a GSTIN.
75
+
76
+ ```js
77
+ extractPAN("27AAPFU0939F1ZV");
78
+ // "AAPFU0939F"
79
+ ```
80
+
81
+ ### `getGSTHolderType(gstin)`
82
+
83
+ Returns the holder type based on the PAN's fourth character.
84
+
85
+ ```js
86
+ getGSTHolderType("27AAPFU0939F1ZV");
87
+ // "Firm"
88
+ ```
89
+
90
+ > **Note:** Return values depend on the input and the package's implementation. Invalid inputs may return `false`, `null`, or another documented fallback.
91
+
92
+ ## Running Tests
93
+
94
+ Clone the repository and install dependencies:
95
+
96
+ ```bash
97
+ git clone https://github.com/Ayushkr7380/indian-gst-validator.git
98
+
99
+ cd indian-gst-validator
100
+
101
+ npm install
102
+ ```
103
+
104
+ Run the test suite:
105
+
106
+ ```bash
107
+ npm test
108
+ ```
109
+
110
+ ## Important Note
111
+
112
+ This package performs local GSTIN format and checksum validation. It does **not** verify GST registration status, taxpayer details, or active status from the official GST portal.
113
+
114
+ For official GST registration verification, use the appropriate GST portal or authorized API.
115
+
116
+ ## Contributing
117
+
118
+ Contributions, bug reports, and feature suggestions are welcome!
119
+
120
+ 1. Fork the repository
121
+ 2. Create a new branch
122
+ 3. Make your changes
123
+ 4. Run the tests
124
+ 5. Submit a pull request
125
+
126
+ ## License
127
+
128
+ This project is licensed under the [MIT License](LICENSE).
129
+
130
+ ## Author
131
+
132
+ **Ayush Kumar**
133
+
134
+ - GitHub: [@Ayushkr7380](https://github.com/Ayushkr7380)
135
+ - npm: [indian-gst-validator](https://www.npmjs.com/package/indian-gst-validator)
package/index.js ADDED
@@ -0,0 +1,14 @@
1
+ const { isValidGST, getStateFromGST, extractPAN, getGSTHolderType } = require("./src/gstValidator");
2
+ const { getStateName, STATE_CODES } = require("./src/stateCodes");
3
+ const { isValidPANFormat, getHolderType } = require("./src/pan");
4
+
5
+ module.exports = {
6
+ isValidGST,
7
+ getStateFromGST,
8
+ extractPAN,
9
+ getGSTHolderType,
10
+ getStateName,
11
+ STATE_CODES,
12
+ isValidPANFormat,
13
+ getHolderType,
14
+ };
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "indian-gst-validator",
3
+ "version": "1.0.0",
4
+ "description": "Validate and extract details from Indian GST numbers",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "node test/test.js"
8
+ },
9
+ "keywords": [
10
+ "gst",
11
+ "gstin",
12
+ "india",
13
+ "validator",
14
+ "tax"
15
+ ],
16
+ "author": "Ayush Kumar",
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/Ayushkr7380/indian-gst-validator.git"
21
+ },
22
+ "homepage": "https://github.com/Ayushkr7380/indian-gst-validator#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/Ayushkr7380/indian-gst-validator/issues"
25
+ },
26
+ "engines": {
27
+ "node": ">=14"
28
+ }
29
+ }
@@ -0,0 +1,43 @@
1
+ // Characters used for GST checksum calculation
2
+ const CHAR_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
3
+
4
+ // Calculate the check digit using the first 14 characters of the GST number
5
+ function calculateCheckDigit(gstFirst14) {
6
+ let sum = 0;
7
+
8
+ for (let i = 0; i < gstFirst14.length; i++) {
9
+ const char = gstFirst14[i];
10
+ const codePoint = CHAR_SET.indexOf(char);
11
+
12
+ // Alternate between multiplying by 1 and 2
13
+ const factor = i % 2 === 0 ? 1 : 2;
14
+
15
+ const product = codePoint * factor;
16
+
17
+ // Convert the product into a base-36 digit sum
18
+ const digit = Math.floor(product / 36) + (product % 36);
19
+
20
+ sum += digit;
21
+ }
22
+
23
+ // Calculate the final checksum value
24
+ const checksumValue = (36 - (sum % 36)) % 36;
25
+
26
+ return CHAR_SET[checksumValue];
27
+ }
28
+
29
+ // Check whether the GST number has a valid checksum
30
+ function isValidChecksum(gstNumber) {
31
+ if (typeof gstNumber !== "string" || gstNumber.length !== 15) return false;
32
+
33
+ const first14 = gstNumber.slice(0, 14).toUpperCase();
34
+ const providedCheckDigit = gstNumber[14].toUpperCase();
35
+
36
+ // Compare the calculated check digit with the provided one
37
+ const calculated = calculateCheckDigit(first14);
38
+
39
+ return calculated === providedCheckDigit;
40
+ }
41
+
42
+ // Export the checksum functions
43
+ module.exports = { calculateCheckDigit, isValidChecksum };
@@ -0,0 +1,68 @@
1
+ const { getStateName } = require("./stateCodes");
2
+ const { isValidPANFormat, getHolderType } = require("./pan");
3
+ const { isValidChecksum } = require("./checksum");
4
+
5
+ // Regex to check the basic GST number format
6
+ const GST_REGEX = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/;
7
+
8
+ // Check whether the GST number follows the correct format
9
+ function isValidGSTFormat(gst) {
10
+ if (typeof gst !== "string") return false;
11
+
12
+ return GST_REGEX.test(gst.toUpperCase());
13
+ }
14
+
15
+ // Validate the GST number using its format, state code, PAN and checksum
16
+ function isValidGST(gstNumber) {
17
+ if (typeof gstNumber !== "string") return false;
18
+
19
+ const gst = gstNumber.toUpperCase().trim();
20
+
21
+ if (!isValidGSTFormat(gst)) return false;
22
+
23
+ // The first two characters represent the state code
24
+ const stateCode = gst.slice(0, 2);
25
+ if (!getStateName(stateCode)) return false;
26
+
27
+ // Extract and validate the PAN embedded in the GST number
28
+ const pan = gst.slice(2, 12);
29
+ if (!isValidPANFormat(pan)) return false;
30
+
31
+ // Check whether the last character matches the calculated checksum
32
+ if (!isValidChecksum(gst)) return false;
33
+
34
+ return true;
35
+ }
36
+
37
+ // Get the state name from the first two characters of the GST number
38
+ function getStateFromGST(gstNumber) {
39
+ if (typeof gstNumber !== "string" || gstNumber.length < 2) return null;
40
+
41
+ const stateCode = gstNumber.slice(0, 2);
42
+
43
+ return getStateName(stateCode);
44
+ }
45
+
46
+ // Extract the PAN from a GST number
47
+ function extractPAN(gstNumber) {
48
+ if (typeof gstNumber !== "string" || gstNumber.length < 12) return null;
49
+
50
+ return gstNumber.slice(2, 12).toUpperCase();
51
+ }
52
+
53
+ // Get the PAN holder type associated with the GST number
54
+ function getGSTHolderType(gstNumber) {
55
+ const pan = extractPAN(gstNumber);
56
+
57
+ if (!pan) return null;
58
+
59
+ return getHolderType(pan);
60
+ }
61
+
62
+ // Export the GST validation and extraction functions
63
+ module.exports = {
64
+ isValidGST,
65
+ getStateFromGST,
66
+ extractPAN,
67
+ getGSTHolderType,
68
+ };
package/src/pan.js ADDED
@@ -0,0 +1,35 @@
1
+ // PAN format validation pattern
2
+ const PAN_REGEX = /^[A-Z]{3}[ABCFGHLJPT][A-Z][0-9]{4}[A-Z]$/;
3
+
4
+ // PAN holder types based on the fourth character
5
+ const HOLDER_TYPES = {
6
+ A: "Association of Persons (AOP)",
7
+ B: "Body of Individuals (BOI)",
8
+ C: "Company",
9
+ F: "Firm / Partnership",
10
+ G: "Government",
11
+ H: "Hindu Undivided Family (HUF)",
12
+ L: "Local Authority",
13
+ J: "Artificial Juridical Person",
14
+ P: "Individual",
15
+ T: "Trust",
16
+ };
17
+
18
+ // Check whether the given PAN follows the correct format
19
+ function isValidPANFormat(pan) {
20
+ if (typeof pan !== "string") return false;
21
+
22
+ return PAN_REGEX.test(pan.toUpperCase());
23
+ }
24
+
25
+ // Get the PAN holder type from its fourth character
26
+ function getHolderType(pan) {
27
+ if (!isValidPANFormat(pan)) return null;
28
+
29
+ const fourthChar = pan.toUpperCase()[3];
30
+
31
+ return HOLDER_TYPES[fourthChar] || null;
32
+ }
33
+
34
+ // Export the functions and holder type mapping
35
+ module.exports = { isValidPANFormat, getHolderType, HOLDER_TYPES };
@@ -0,0 +1,49 @@
1
+ // Indian state and union territory codes with their names
2
+ const STATE_CODES = {
3
+ "01": "Jammu and Kashmir",
4
+ "02": "Himachal Pradesh",
5
+ "03": "Punjab",
6
+ "04": "Chandigarh",
7
+ "05": "Uttarakhand",
8
+ "06": "Haryana",
9
+ "07": "Delhi",
10
+ "08": "Rajasthan",
11
+ "09": "Uttar Pradesh",
12
+ "10": "Bihar",
13
+ "11": "Sikkim",
14
+ "12": "Arunachal Pradesh",
15
+ "13": "Nagaland",
16
+ "14": "Manipur",
17
+ "15": "Mizoram",
18
+ "16": "Tripura",
19
+ "17": "Meghalaya",
20
+ "18": "Assam",
21
+ "19": "West Bengal",
22
+ "20": "Jharkhand",
23
+ "21": "Odisha",
24
+ "22": "Chhattisgarh",
25
+ "23": "Madhya Pradesh",
26
+ "24": "Gujarat",
27
+ "25": "Daman and Diu",
28
+ "26": "Dadra and Nagar Haveli",
29
+ "27": "Maharashtra",
30
+ "28": "Andhra Pradesh (Old)",
31
+ "29": "Karnataka",
32
+ "30": "Goa",
33
+ "31": "Lakshadweep",
34
+ "32": "Kerala",
35
+ "33": "Tamil Nadu",
36
+ "34": "Puducherry",
37
+ "35": "Andaman and Nicobar Islands",
38
+ "36": "Telangana",
39
+ "37": "Andhra Pradesh",
40
+ "38": "Ladakh",
41
+ };
42
+
43
+ // Get the state name using its code
44
+ function getStateName(code) {
45
+ return STATE_CODES[code] || null;
46
+ }
47
+
48
+ // Export the codes and function
49
+ module.exports = { STATE_CODES, getStateName };
package/test/test.js ADDED
@@ -0,0 +1,32 @@
1
+ const gst = require("../index");
2
+
3
+ // Test cases for GST number validation
4
+ const tests = [
5
+ ["27AAPFU0939F1ZV", true, "Valid GST number"],
6
+ ["27AAPFU0939F1ZX", false, "Wrong checksum"],
7
+ ["99AAPFU0939F1ZV", false, "Invalid state code"],
8
+ ["27AAPFU0939F1Z", false, "Too short (14 chars)"],
9
+ ["", false, "Empty string"],
10
+ [null, false, "Null input"],
11
+ [12345, false, "Number instead of string"],
12
+ ];
13
+
14
+ let passed = 0;
15
+ let failed = 0;
16
+
17
+ // Run each test case and compare the result with the expected value
18
+ tests.forEach(([input, expected, description]) => {
19
+ const result = gst.isValidGST(input);
20
+ const status = result === expected ? "PASS" : "FAIL";
21
+
22
+ // Keep track of passed and failed test cases
23
+ if (status === "PASS") passed++;
24
+ else failed++;
25
+
26
+ console.log(
27
+ `[${status}] ${description} — input: ${input}, expected: ${expected}, got: ${result}`
28
+ );
29
+ });
30
+
31
+ // Print the final test summary
32
+ console.log(`\n${passed} passed, ${failed} failed`);