gstin-utils 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 +21 -0
- package/README.md +340 -0
- package/dist/checksum.d.ts +50 -0
- package/dist/checksum.d.ts.map +1 -0
- package/dist/checksum.js +75 -0
- package/dist/checksum.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/state-codes.d.ts +29 -0
- package/dist/state-codes.d.ts.map +1 -0
- package/dist/state-codes.js +83 -0
- package/dist/state-codes.js.map +1 -0
- package/dist/types.d.ts +55 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/validator.d.ts +157 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +345 -0
- package/dist/validator.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ujjwal Pratap
|
|
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,340 @@
|
|
|
1
|
+
# gstin-utils
|
|
2
|
+
|
|
3
|
+
> A lightweight, zero-dependency utility package for Indian GSTIN validation, parsing, normalization, masking, and metadata extraction.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/gstin-utils)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Why gstin-utils?
|
|
12
|
+
|
|
13
|
+
Working with Indian GST (Goods and Services Tax) data is a common requirement in fintech, invoicing, ERP, e-commerce, and tax-compliance applications. GSTIN numbers have a strict 15-character format with embedded state codes, PAN, entity identifiers, and a checksum β yet most codebases validate them with ad-hoc regexes that miss important checks.
|
|
14
|
+
|
|
15
|
+
**gstin-utils** gives you production-grade utilities to:
|
|
16
|
+
|
|
17
|
+
- β
**Validate** GSTINs with full checksum verification (Luhn mod-36)
|
|
18
|
+
- π **Parse** a GSTIN into state code, PAN, entity code, and more
|
|
19
|
+
- π·οΈ **Extract** state names, PAN numbers, and metadata
|
|
20
|
+
- π **Mask** GSTINs for safe display in logs or UI
|
|
21
|
+
- π **Normalize** raw user input (trim + uppercase)
|
|
22
|
+
- πΊοΈ **Map** all 37+ Indian state/UT codes to their names
|
|
23
|
+
- π‘οΈ **Zero dependencies** β lightweight and secure
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install gstin-utils
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
yarn add gstin-utils
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm add gstin-utils
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { isValidGSTIN, parseGSTIN, maskGSTIN } from 'gstin-utils';
|
|
47
|
+
|
|
48
|
+
// Validate
|
|
49
|
+
isValidGSTIN('27AAPFU0939F1ZV'); // true
|
|
50
|
+
isValidGSTIN('INVALIDGSTIN123'); // false
|
|
51
|
+
|
|
52
|
+
// Parse
|
|
53
|
+
parseGSTIN('27AAPFU0939F1ZV');
|
|
54
|
+
// {
|
|
55
|
+
// gstin: '27AAPFU0939F1ZV',
|
|
56
|
+
// stateCode: '27',
|
|
57
|
+
// stateName: 'Maharashtra',
|
|
58
|
+
// pan: 'AAPFU0939F',
|
|
59
|
+
// entityCode: '1',
|
|
60
|
+
// checksum: 'V',
|
|
61
|
+
// isValid: true,
|
|
62
|
+
// ...
|
|
63
|
+
// }
|
|
64
|
+
|
|
65
|
+
// Mask for display
|
|
66
|
+
maskGSTIN('27AAPFU0939F1ZV'); // "27AAP****39F1ZV"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## GSTIN Format Reference
|
|
72
|
+
|
|
73
|
+
A GSTIN is a **15-character alphanumeric** string with the following structure:
|
|
74
|
+
|
|
75
|
+
| Position | Characters | Meaning | Example |
|
|
76
|
+
| -------- | ---------- | ------------------------------------ | ------- |
|
|
77
|
+
| 1β2 | `27` | State/UT code | `27` |
|
|
78
|
+
| 3β7 | `AAPFU` | First 5 characters of PAN (letters) | `AAPFU` |
|
|
79
|
+
| 8β11 | `0939` | Next 4 characters of PAN (digits) | `0939` |
|
|
80
|
+
| 12 | `F` | Last character of PAN (letter) | `F` |
|
|
81
|
+
| 13 | `1` | Entity code (1β9 or AβZ) | `1` |
|
|
82
|
+
| 14 | `Z` | Default/reserved character | `Z` |
|
|
83
|
+
| 15 | `V` | Checksum (computed via Luhn mod-36) | `V` |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## API Reference
|
|
88
|
+
|
|
89
|
+
### `normalizeGSTIN(gstin: unknown): string`
|
|
90
|
+
|
|
91
|
+
Trims whitespace and converts to uppercase.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
normalizeGSTIN(' 27aapfu0939f1zv '); // "27AAPFU0939F1ZV"
|
|
95
|
+
normalizeGSTIN(null); // ""
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### `isValidGSTIN(gstin: unknown): boolean`
|
|
101
|
+
|
|
102
|
+
Quick boolean check β validates format, state code, and checksum.
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
isValidGSTIN('27AAPFU0939F1ZV'); // true
|
|
106
|
+
isValidGSTIN('00AAPFU0939F1ZV'); // false (invalid state code)
|
|
107
|
+
isValidGSTIN(undefined); // false
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### `validateGSTIN(gstin: unknown): GSTINValidationResult`
|
|
113
|
+
|
|
114
|
+
Returns a detailed validation object with individual check results and error messages.
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
validateGSTIN('27AAPFU0939F1ZV');
|
|
118
|
+
// {
|
|
119
|
+
// isValid: true,
|
|
120
|
+
// formatValid: true,
|
|
121
|
+
// lengthValid: true,
|
|
122
|
+
// stateCodeValid: true,
|
|
123
|
+
// panSegmentValid: true,
|
|
124
|
+
// entityCodeValid: true,
|
|
125
|
+
// defaultZValid: true,
|
|
126
|
+
// checksumValid: true,
|
|
127
|
+
// errors: []
|
|
128
|
+
// }
|
|
129
|
+
|
|
130
|
+
validateGSTIN('00AAPFU0939F1ZV');
|
|
131
|
+
// {
|
|
132
|
+
// isValid: false,
|
|
133
|
+
// stateCodeValid: false,
|
|
134
|
+
// errors: ['"00" is not a recognized GST state/UT code.', ...]
|
|
135
|
+
// }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
### `parseGSTIN(gstin: unknown): GSTINParsedResult | null`
|
|
141
|
+
|
|
142
|
+
Breaks down a GSTIN into its constituent parts. Returns `null` for unusable input.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
parseGSTIN('27AAPFU0939F1ZV');
|
|
146
|
+
// {
|
|
147
|
+
// gstin: '27AAPFU0939F1ZV',
|
|
148
|
+
// normalized: '27AAPFU0939F1ZV',
|
|
149
|
+
// stateCode: '27',
|
|
150
|
+
// stateName: 'Maharashtra',
|
|
151
|
+
// pan: 'AAPFU0939F',
|
|
152
|
+
// entityCode: '1',
|
|
153
|
+
// defaultChar: 'Z',
|
|
154
|
+
// checksum: 'V',
|
|
155
|
+
// isValid: true
|
|
156
|
+
// }
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
### `getStateCodeFromGSTIN(gstin: unknown): string | null`
|
|
162
|
+
|
|
163
|
+
Extracts the 2-digit state code.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
getStateCodeFromGSTIN('27AAPFU0939F1ZV'); // "27"
|
|
167
|
+
getStateCodeFromGSTIN(''); // null
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### `getStateNameFromGSTIN(gstin: unknown): string | null`
|
|
173
|
+
|
|
174
|
+
Returns the human-readable state/UT name.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
getStateNameFromGSTIN('27AAPFU0939F1ZV'); // "Maharashtra"
|
|
178
|
+
getStateNameFromGSTIN('07AAPFU0939F1ZV'); // "Delhi"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### `getPANFromGSTIN(gstin: unknown): string | null`
|
|
184
|
+
|
|
185
|
+
Extracts the 10-character PAN segment.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
getPANFromGSTIN('27AAPFU0939F1ZV'); // "AAPFU0939F"
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### `maskGSTIN(gstin: unknown): string | null`
|
|
194
|
+
|
|
195
|
+
Masks the middle portion for safe display.
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
maskGSTIN('27AAPFU0939F1ZV'); // "27AAP****39F1ZV"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### `isValidStateCode(code: unknown): boolean`
|
|
204
|
+
|
|
205
|
+
Validates a 2-digit GST state/UT code against the known list.
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
isValidStateCode('27'); // true (Maharashtra)
|
|
209
|
+
isValidStateCode('00'); // false
|
|
210
|
+
isValidStateCode('99'); // true (Centre Jurisdiction)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### `computeChecksum(gstin: string): string`
|
|
216
|
+
|
|
217
|
+
Computes the expected checksum character using the Luhn mod-36 algorithm.
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
computeChecksum('27AAPFU0939F1ZV'); // "V"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### `isChecksumValid(gstin: string): boolean`
|
|
226
|
+
|
|
227
|
+
Checks if the 15th character matches the computed checksum.
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
isChecksumValid('27AAPFU0939F1ZV'); // true
|
|
231
|
+
isChecksumValid('27AAPFU0939F1ZA'); // false
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Data Exports
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
import { STATE_CODE_MAP, getAllStateCodes, getStateNameByCode } from 'gstin-utils';
|
|
240
|
+
|
|
241
|
+
STATE_CODE_MAP['27']; // "Maharashtra"
|
|
242
|
+
getAllStateCodes(); // ['01', '02', '03', ...]
|
|
243
|
+
getStateNameByCode('07'); // "Delhi"
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Edge Case Handling
|
|
249
|
+
|
|
250
|
+
All functions handle these edge cases gracefully:
|
|
251
|
+
|
|
252
|
+
| Input | Behavior |
|
|
253
|
+
| ------------------ | ----------------------------------------------- |
|
|
254
|
+
| `null` | Returns safe default (`""`, `false`, or `null`) |
|
|
255
|
+
| `undefined` | Returns safe default |
|
|
256
|
+
| `""` | Returns safe default |
|
|
257
|
+
| `12345` (number) | Returns safe default (non-string) |
|
|
258
|
+
| `" 27aapfu... "` | Auto-trimmed and uppercased |
|
|
259
|
+
| Short strings | Returns `null` or validation failure |
|
|
260
|
+
| Long strings | Returns validation failure |
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## State/UT Codes Supported
|
|
265
|
+
|
|
266
|
+
The package includes a complete mapping of **37+ GST state and UT codes**, including:
|
|
267
|
+
|
|
268
|
+
- All 28 Indian states
|
|
269
|
+
- All 8 Union Territories
|
|
270
|
+
- Special codes: `96` (Foreign Country), `97` (Other Territory), `99` (Centre Jurisdiction)
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Project Structure
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
gstin-utils/
|
|
278
|
+
βββ src/
|
|
279
|
+
β βββ index.ts # Barrel exports
|
|
280
|
+
β βββ validator.ts # Core validation & utility functions
|
|
281
|
+
β βββ checksum.ts # Luhn mod-36 checksum algorithm
|
|
282
|
+
β βββ state-codes.ts # State/UT code mapping
|
|
283
|
+
β βββ types.ts # TypeScript interfaces
|
|
284
|
+
βββ tests/
|
|
285
|
+
β βββ gstin-utils.test.ts
|
|
286
|
+
βββ examples/
|
|
287
|
+
β βββ usage.ts
|
|
288
|
+
βββ package.json
|
|
289
|
+
βββ tsconfig.json
|
|
290
|
+
βββ jest.config.js
|
|
291
|
+
βββ LICENSE
|
|
292
|
+
βββ README.md
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Development
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# Install dependencies
|
|
301
|
+
npm install
|
|
302
|
+
|
|
303
|
+
# Build
|
|
304
|
+
npm run build
|
|
305
|
+
|
|
306
|
+
# Run tests
|
|
307
|
+
npm test
|
|
308
|
+
|
|
309
|
+
# Run tests with coverage
|
|
310
|
+
npm run test:coverage
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Use Cases
|
|
316
|
+
|
|
317
|
+
- π¦ **Fintech** β Validate merchant GSTINs during onboarding
|
|
318
|
+
- π§Ύ **Invoicing** β Parse and display GSTIN details on invoices
|
|
319
|
+
- π **ERP systems** β Normalize and store GSTINs consistently
|
|
320
|
+
- π **Form validation** β Client-side or server-side GSTIN validation
|
|
321
|
+
- π **Analytics** β Extract state-level data from GSTIN records
|
|
322
|
+
- π **Logging** β Mask GSTINs in logs to protect PII
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Contributing
|
|
327
|
+
|
|
328
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
329
|
+
|
|
330
|
+
1. Fork the repository
|
|
331
|
+
2. Create your feature branch: `git checkout -b feature/my-feature`
|
|
332
|
+
3. Commit your changes: `git commit -m 'Add my feature'`
|
|
333
|
+
4. Push to the branch: `git push origin feature/my-feature`
|
|
334
|
+
5. Open a pull request
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## License
|
|
339
|
+
|
|
340
|
+
[MIT](./LICENSE) Β© Ujjwal Pratap
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module gstin-utils/checksum
|
|
3
|
+
*
|
|
4
|
+
* Implements the GSTIN checksum verification algorithm.
|
|
5
|
+
*
|
|
6
|
+
* GSTIN uses a **modified Luhn mod-36** algorithm for its 15th (check) character.
|
|
7
|
+
* The algorithm maps each character of the first 14 characters to a numeric value,
|
|
8
|
+
* applies a weighted computation, and derives the expected check character.
|
|
9
|
+
*
|
|
10
|
+
* Character set (base-36):
|
|
11
|
+
* 0-9 β 0β9
|
|
12
|
+
* A-Z β 10β35
|
|
13
|
+
*
|
|
14
|
+
* Algorithm steps:
|
|
15
|
+
* 1. For each of the first 14 characters, get its numeric value.
|
|
16
|
+
* 2. Compute: factor = value Γ (position is odd ? 1 : 2)
|
|
17
|
+
* 3. Split factor into: quotient = floor(factor / 36), remainder = factor % 36
|
|
18
|
+
* 4. Sum all (quotient + remainder) values.
|
|
19
|
+
* 5. Check character value = (36 - (sum % 36)) % 36
|
|
20
|
+
* 6. Map check character value back to the character set.
|
|
21
|
+
*
|
|
22
|
+
* Reference: Government of India GST Portal documentation.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Computes the expected checksum character for a GSTIN.
|
|
26
|
+
*
|
|
27
|
+
* @param gstin - A 15-character GSTIN string (uppercase, no spaces)
|
|
28
|
+
* @returns The expected checksum character (the 15th character)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* computeChecksum('27AAPFU0939F1ZV'); // 'V'
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeChecksum(gstin: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Validates whether the 15th character of a GSTIN matches
|
|
38
|
+
* the computed checksum.
|
|
39
|
+
*
|
|
40
|
+
* @param gstin - A 15-character GSTIN string (uppercase, no spaces)
|
|
41
|
+
* @returns `true` if checksum is valid, `false` otherwise
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* isChecksumValid('27AAPFU0939F1ZV'); // true
|
|
46
|
+
* isChecksumValid('27AAPFU0939F1ZA'); // false
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function isChecksumValid(gstin: string): boolean;
|
|
50
|
+
//# sourceMappingURL=checksum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAkBrD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAItD"}
|
package/dist/checksum.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module gstin-utils/checksum
|
|
4
|
+
*
|
|
5
|
+
* Implements the GSTIN checksum verification algorithm.
|
|
6
|
+
*
|
|
7
|
+
* GSTIN uses a **modified Luhn mod-36** algorithm for its 15th (check) character.
|
|
8
|
+
* The algorithm maps each character of the first 14 characters to a numeric value,
|
|
9
|
+
* applies a weighted computation, and derives the expected check character.
|
|
10
|
+
*
|
|
11
|
+
* Character set (base-36):
|
|
12
|
+
* 0-9 β 0β9
|
|
13
|
+
* A-Z β 10β35
|
|
14
|
+
*
|
|
15
|
+
* Algorithm steps:
|
|
16
|
+
* 1. For each of the first 14 characters, get its numeric value.
|
|
17
|
+
* 2. Compute: factor = value Γ (position is odd ? 1 : 2)
|
|
18
|
+
* 3. Split factor into: quotient = floor(factor / 36), remainder = factor % 36
|
|
19
|
+
* 4. Sum all (quotient + remainder) values.
|
|
20
|
+
* 5. Check character value = (36 - (sum % 36)) % 36
|
|
21
|
+
* 6. Map check character value back to the character set.
|
|
22
|
+
*
|
|
23
|
+
* Reference: Government of India GST Portal documentation.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.computeChecksum = computeChecksum;
|
|
27
|
+
exports.isChecksumValid = isChecksumValid;
|
|
28
|
+
/** The characters used for base-36 encoding */
|
|
29
|
+
const CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
30
|
+
/**
|
|
31
|
+
* Computes the expected checksum character for a GSTIN.
|
|
32
|
+
*
|
|
33
|
+
* @param gstin - A 15-character GSTIN string (uppercase, no spaces)
|
|
34
|
+
* @returns The expected checksum character (the 15th character)
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* computeChecksum('27AAPFU0939F1ZV'); // 'V'
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
function computeChecksum(gstin) {
|
|
42
|
+
const input = gstin.substring(0, 14);
|
|
43
|
+
let sum = 0;
|
|
44
|
+
for (let i = 0; i < 14; i++) {
|
|
45
|
+
const char = input[i];
|
|
46
|
+
const value = CHARS.indexOf(char);
|
|
47
|
+
// Positions are 1-indexed: odd positions use factor 1, even use factor 2
|
|
48
|
+
const factor = value * (i % 2 === 0 ? 1 : 2);
|
|
49
|
+
const quotient = Math.floor(factor / 36);
|
|
50
|
+
const remainder = factor % 36;
|
|
51
|
+
sum += quotient + remainder;
|
|
52
|
+
}
|
|
53
|
+
const checkValue = (36 - (sum % 36)) % 36;
|
|
54
|
+
return CHARS[checkValue];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validates whether the 15th character of a GSTIN matches
|
|
58
|
+
* the computed checksum.
|
|
59
|
+
*
|
|
60
|
+
* @param gstin - A 15-character GSTIN string (uppercase, no spaces)
|
|
61
|
+
* @returns `true` if checksum is valid, `false` otherwise
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* isChecksumValid('27AAPFU0939F1ZV'); // true
|
|
66
|
+
* isChecksumValid('27AAPFU0939F1ZA'); // false
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
function isChecksumValid(gstin) {
|
|
70
|
+
if (typeof gstin !== 'string' || gstin.length !== 15)
|
|
71
|
+
return false;
|
|
72
|
+
const expected = computeChecksum(gstin);
|
|
73
|
+
return gstin[14] === expected;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=checksum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.js","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;AAgBH,0CAkBC;AAeD,0CAIC;AAnDD,+CAA+C;AAC/C,MAAM,KAAK,GAAG,sCAAsC,CAAC;AAErD;;;;;;;;;;GAUG;AACH,SAAgB,eAAe,CAAC,KAAa;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrC,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAElC,yEAAyE;QACzE,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,GAAG,EAAE,CAAC;QAE9B,GAAG,IAAI,QAAQ,GAAG,SAAS,CAAC;IAC9B,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IAC1C,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,eAAe,CAAC,KAAa;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACnE,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,QAAQ,CAAC;AAChC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module gstin-utils
|
|
3
|
+
*
|
|
4
|
+
* A lightweight, zero-dependency utility package for Indian GSTIN
|
|
5
|
+
* validation, parsing, normalization, masking, and metadata extraction.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import {
|
|
10
|
+
* isValidGSTIN,
|
|
11
|
+
* parseGSTIN,
|
|
12
|
+
* maskGSTIN,
|
|
13
|
+
* } from 'gstin-utils';
|
|
14
|
+
*
|
|
15
|
+
* isValidGSTIN('27AAPFU0939F1ZV'); // true
|
|
16
|
+
* parseGSTIN('27AAPFU0939F1ZV'); // { stateCode: '27', stateName: 'Maharashtra', ... }
|
|
17
|
+
* maskGSTIN('27AAPFU0939F1ZV'); // "27AAP****39F1ZV"
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export { normalizeGSTIN, isValidGSTIN, validateGSTIN, parseGSTIN, getStateCodeFromGSTIN, getStateNameFromGSTIN, getPANFromGSTIN, maskGSTIN, isValidStateCode, } from './validator';
|
|
21
|
+
export { computeChecksum, isChecksumValid } from './checksum';
|
|
22
|
+
export { STATE_CODE_MAP, getAllStateCodes, getStateNameByCode, } from './state-codes';
|
|
23
|
+
export type { GSTINValidationResult, GSTINParsedResult } from './types';
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,UAAU,EACV,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,SAAS,EACT,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG9D,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module gstin-utils
|
|
4
|
+
*
|
|
5
|
+
* A lightweight, zero-dependency utility package for Indian GSTIN
|
|
6
|
+
* validation, parsing, normalization, masking, and metadata extraction.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import {
|
|
11
|
+
* isValidGSTIN,
|
|
12
|
+
* parseGSTIN,
|
|
13
|
+
* maskGSTIN,
|
|
14
|
+
* } from 'gstin-utils';
|
|
15
|
+
*
|
|
16
|
+
* isValidGSTIN('27AAPFU0939F1ZV'); // true
|
|
17
|
+
* parseGSTIN('27AAPFU0939F1ZV'); // { stateCode: '27', stateName: 'Maharashtra', ... }
|
|
18
|
+
* maskGSTIN('27AAPFU0939F1ZV'); // "27AAP****39F1ZV"
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.getStateNameByCode = exports.getAllStateCodes = exports.STATE_CODE_MAP = exports.isChecksumValid = exports.computeChecksum = exports.isValidStateCode = exports.maskGSTIN = exports.getPANFromGSTIN = exports.getStateNameFromGSTIN = exports.getStateCodeFromGSTIN = exports.parseGSTIN = exports.validateGSTIN = exports.isValidGSTIN = exports.normalizeGSTIN = void 0;
|
|
23
|
+
// --- Core functions --------------------------------------------------------
|
|
24
|
+
var validator_1 = require("./validator");
|
|
25
|
+
Object.defineProperty(exports, "normalizeGSTIN", { enumerable: true, get: function () { return validator_1.normalizeGSTIN; } });
|
|
26
|
+
Object.defineProperty(exports, "isValidGSTIN", { enumerable: true, get: function () { return validator_1.isValidGSTIN; } });
|
|
27
|
+
Object.defineProperty(exports, "validateGSTIN", { enumerable: true, get: function () { return validator_1.validateGSTIN; } });
|
|
28
|
+
Object.defineProperty(exports, "parseGSTIN", { enumerable: true, get: function () { return validator_1.parseGSTIN; } });
|
|
29
|
+
Object.defineProperty(exports, "getStateCodeFromGSTIN", { enumerable: true, get: function () { return validator_1.getStateCodeFromGSTIN; } });
|
|
30
|
+
Object.defineProperty(exports, "getStateNameFromGSTIN", { enumerable: true, get: function () { return validator_1.getStateNameFromGSTIN; } });
|
|
31
|
+
Object.defineProperty(exports, "getPANFromGSTIN", { enumerable: true, get: function () { return validator_1.getPANFromGSTIN; } });
|
|
32
|
+
Object.defineProperty(exports, "maskGSTIN", { enumerable: true, get: function () { return validator_1.maskGSTIN; } });
|
|
33
|
+
Object.defineProperty(exports, "isValidStateCode", { enumerable: true, get: function () { return validator_1.isValidStateCode; } });
|
|
34
|
+
// --- Checksum utilities ----------------------------------------------------
|
|
35
|
+
var checksum_1 = require("./checksum");
|
|
36
|
+
Object.defineProperty(exports, "computeChecksum", { enumerable: true, get: function () { return checksum_1.computeChecksum; } });
|
|
37
|
+
Object.defineProperty(exports, "isChecksumValid", { enumerable: true, get: function () { return checksum_1.isChecksumValid; } });
|
|
38
|
+
// --- State code data & helpers ---------------------------------------------
|
|
39
|
+
var state_codes_1 = require("./state-codes");
|
|
40
|
+
Object.defineProperty(exports, "STATE_CODE_MAP", { enumerable: true, get: function () { return state_codes_1.STATE_CODE_MAP; } });
|
|
41
|
+
Object.defineProperty(exports, "getAllStateCodes", { enumerable: true, get: function () { return state_codes_1.getAllStateCodes; } });
|
|
42
|
+
Object.defineProperty(exports, "getStateNameByCode", { enumerable: true, get: function () { return state_codes_1.getStateNameByCode; } });
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;AAEH,8EAA8E;AAC9E,yCAUqB;AATnB,2GAAA,cAAc,OAAA;AACd,yGAAA,YAAY,OAAA;AACZ,0GAAA,aAAa,OAAA;AACb,uGAAA,UAAU,OAAA;AACV,kHAAA,qBAAqB,OAAA;AACrB,kHAAA,qBAAqB,OAAA;AACrB,4GAAA,eAAe,OAAA;AACf,sGAAA,SAAS,OAAA;AACT,6GAAA,gBAAgB,OAAA;AAGlB,8EAA8E;AAC9E,uCAA8D;AAArD,2GAAA,eAAe,OAAA;AAAE,2GAAA,eAAe,OAAA;AAEzC,8EAA8E;AAC9E,6CAIuB;AAHrB,6GAAA,cAAc,OAAA;AACd,+GAAA,gBAAgB,OAAA;AAChB,iHAAA,kBAAkB,OAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module gstin-utils/state-codes
|
|
3
|
+
*
|
|
4
|
+
* Complete mapping of Indian GST state/UT codes to their names.
|
|
5
|
+
* This includes all 28 states, 8 union territories, and special codes
|
|
6
|
+
* used by the GST system.
|
|
7
|
+
*
|
|
8
|
+
* Reference: https://www.gst.gov.in
|
|
9
|
+
*/
|
|
10
|
+
export declare const STATE_CODE_MAP: Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Returns an array of all valid GST state codes.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getAllStateCodes(): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Returns the full state/UT name for a given state code.
|
|
17
|
+
*
|
|
18
|
+
* @param code - Two-digit state code (e.g., "27")
|
|
19
|
+
* @returns The state/UT name, or `undefined` if the code is invalid
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* getStateNameByCode('27'); // "Maharashtra"
|
|
24
|
+
* getStateNameByCode('99'); // "Centre Jurisdiction"
|
|
25
|
+
* getStateNameByCode('00'); // undefined
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function getStateNameByCode(code: string): string | undefined;
|
|
29
|
+
//# sourceMappingURL=state-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-codes.d.ts","sourceRoot":"","sources":["../src/state-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA2CjD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGnE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module gstin-utils/state-codes
|
|
4
|
+
*
|
|
5
|
+
* Complete mapping of Indian GST state/UT codes to their names.
|
|
6
|
+
* This includes all 28 states, 8 union territories, and special codes
|
|
7
|
+
* used by the GST system.
|
|
8
|
+
*
|
|
9
|
+
* Reference: https://www.gst.gov.in
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.STATE_CODE_MAP = void 0;
|
|
13
|
+
exports.getAllStateCodes = getAllStateCodes;
|
|
14
|
+
exports.getStateNameByCode = getStateNameByCode;
|
|
15
|
+
exports.STATE_CODE_MAP = {
|
|
16
|
+
'01': 'Jammu & Kashmir',
|
|
17
|
+
'02': 'Himachal Pradesh',
|
|
18
|
+
'03': 'Punjab',
|
|
19
|
+
'04': 'Chandigarh',
|
|
20
|
+
'05': 'Uttarakhand',
|
|
21
|
+
'06': 'Haryana',
|
|
22
|
+
'07': 'Delhi',
|
|
23
|
+
'08': 'Rajasthan',
|
|
24
|
+
'09': 'Uttar Pradesh',
|
|
25
|
+
'10': 'Bihar',
|
|
26
|
+
'11': 'Sikkim',
|
|
27
|
+
'12': 'Arunachal Pradesh',
|
|
28
|
+
'13': 'Nagaland',
|
|
29
|
+
'14': 'Manipur',
|
|
30
|
+
'15': 'Mizoram',
|
|
31
|
+
'16': 'Tripura',
|
|
32
|
+
'17': 'Meghalaya',
|
|
33
|
+
'18': 'Assam',
|
|
34
|
+
'19': 'West Bengal',
|
|
35
|
+
'20': 'Jharkhand',
|
|
36
|
+
'21': 'Odisha',
|
|
37
|
+
'22': 'Chhattisgarh',
|
|
38
|
+
'23': 'Madhya Pradesh',
|
|
39
|
+
'24': 'Gujarat',
|
|
40
|
+
'25': 'Daman & Diu',
|
|
41
|
+
'26': 'Dadra & Nagar Haveli and Daman & Diu',
|
|
42
|
+
'27': 'Maharashtra',
|
|
43
|
+
'28': 'Andhra Pradesh (Old)',
|
|
44
|
+
'29': 'Karnataka',
|
|
45
|
+
'30': 'Goa',
|
|
46
|
+
'31': 'Lakshadweep',
|
|
47
|
+
'32': 'Kerala',
|
|
48
|
+
'33': 'Tamil Nadu',
|
|
49
|
+
'34': 'Puducherry',
|
|
50
|
+
'35': 'Andaman & Nicobar Islands',
|
|
51
|
+
'36': 'Telangana',
|
|
52
|
+
'37': 'Andhra Pradesh',
|
|
53
|
+
'38': 'Ladakh',
|
|
54
|
+
// Special codes used by GST
|
|
55
|
+
'96': 'Foreign Country',
|
|
56
|
+
'97': 'Other Territory',
|
|
57
|
+
'99': 'Centre Jurisdiction',
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Returns an array of all valid GST state codes.
|
|
61
|
+
*/
|
|
62
|
+
function getAllStateCodes() {
|
|
63
|
+
return Object.keys(exports.STATE_CODE_MAP);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Returns the full state/UT name for a given state code.
|
|
67
|
+
*
|
|
68
|
+
* @param code - Two-digit state code (e.g., "27")
|
|
69
|
+
* @returns The state/UT name, or `undefined` if the code is invalid
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* getStateNameByCode('27'); // "Maharashtra"
|
|
74
|
+
* getStateNameByCode('99'); // "Centre Jurisdiction"
|
|
75
|
+
* getStateNameByCode('00'); // undefined
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
function getStateNameByCode(code) {
|
|
79
|
+
if (typeof code !== 'string')
|
|
80
|
+
return undefined;
|
|
81
|
+
return exports.STATE_CODE_MAP[code.trim()];
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=state-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-codes.js","sourceRoot":"","sources":["../src/state-codes.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAkDH,4CAEC;AAeD,gDAGC;AApEY,QAAA,cAAc,GAA2B;IACpD,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,cAAc;IACpB,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,sCAAsC;IAC5C,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE,2BAA2B;IACjC,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,QAAQ;IACd,4BAA4B;IAC5B,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,qBAAqB;CAC5B,CAAC;AAEF;;GAEG;AACH,SAAgB,gBAAgB;IAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,sBAAc,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC/C,OAAO,sBAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module gstin-utils/types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the gstin-utils package.
|
|
5
|
+
* All return types for validation, parsing, and utility functions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Detailed validation result returned by `validateGSTIN()`.
|
|
9
|
+
* Each field represents one aspect of GSTIN validity.
|
|
10
|
+
*/
|
|
11
|
+
export interface GSTINValidationResult {
|
|
12
|
+
/** Whether the GSTIN passes all validation checks */
|
|
13
|
+
isValid: boolean;
|
|
14
|
+
/** Whether the GSTIN matches the expected regex format */
|
|
15
|
+
formatValid: boolean;
|
|
16
|
+
/** Whether the GSTIN is exactly 15 characters */
|
|
17
|
+
lengthValid: boolean;
|
|
18
|
+
/** Whether the first two digits are a recognized GST state/UT code */
|
|
19
|
+
stateCodeValid: boolean;
|
|
20
|
+
/** Whether characters 3β12 form a valid PAN pattern */
|
|
21
|
+
panSegmentValid: boolean;
|
|
22
|
+
/** Whether the 13th character (entity code) is a valid alphanumeric digit */
|
|
23
|
+
entityCodeValid: boolean;
|
|
24
|
+
/** Whether the 14th character is 'Z' (default/reserved) */
|
|
25
|
+
defaultZValid: boolean;
|
|
26
|
+
/** Whether the 15th character (checksum) is valid per the Luhn-mod-36 algorithm */
|
|
27
|
+
checksumValid: boolean;
|
|
28
|
+
/** List of human-readable error messages for each failed check */
|
|
29
|
+
errors: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parsed GSTIN structure returned by `parseGSTIN()`.
|
|
33
|
+
* Breaks down a GSTIN into its constituent parts.
|
|
34
|
+
*/
|
|
35
|
+
export interface GSTINParsedResult {
|
|
36
|
+
/** The original GSTIN (as provided) */
|
|
37
|
+
gstin: string;
|
|
38
|
+
/** Normalized (trimmed + uppercased) GSTIN */
|
|
39
|
+
normalized: string;
|
|
40
|
+
/** First 2 digits β the GST state/UT code */
|
|
41
|
+
stateCode: string;
|
|
42
|
+
/** Human-readable state/UT name, or "Unknown" if code is not recognized */
|
|
43
|
+
stateName: string;
|
|
44
|
+
/** Characters 3β12 β the PAN of the entity */
|
|
45
|
+
pan: string;
|
|
46
|
+
/** 13th character β entity/registration number within the same PAN */
|
|
47
|
+
entityCode: string;
|
|
48
|
+
/** 14th character β reserved character (should be 'Z') */
|
|
49
|
+
defaultChar: string;
|
|
50
|
+
/** 15th character β checksum digit */
|
|
51
|
+
checksum: string;
|
|
52
|
+
/** Whether the GSTIN is valid (passes all checks) */
|
|
53
|
+
isValid: boolean;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,WAAW,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,WAAW,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,cAAc,EAAE,OAAO,CAAC;IACxB,uDAAuD;IACvD,eAAe,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,eAAe,EAAE,OAAO,CAAC;IACzB,2DAA2D;IAC3D,aAAa,EAAE,OAAO,CAAC;IACvB,mFAAmF;IACnF,aAAa,EAAE,OAAO,CAAC;IACvB,kEAAkE;IAClE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;CAClB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module gstin-utils/types
|
|
4
|
+
*
|
|
5
|
+
* Type definitions for the gstin-utils package.
|
|
6
|
+
* All return types for validation, parsing, and utility functions.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module gstin-utils/validator
|
|
3
|
+
*
|
|
4
|
+
* Core GSTIN validation and utility functions.
|
|
5
|
+
* All functions accept raw user input and handle edge cases gracefully.
|
|
6
|
+
*/
|
|
7
|
+
import { GSTINValidationResult, GSTINParsedResult } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Normalizes a GSTIN string by trimming whitespace and converting
|
|
10
|
+
* to uppercase. Useful before storing or comparing GSTINs.
|
|
11
|
+
*
|
|
12
|
+
* @param gstin - Raw GSTIN input
|
|
13
|
+
* @returns Cleaned GSTIN string (trimmed + uppercased)
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* normalizeGSTIN(' 27aapfu0939f1zv '); // "27AAPFU0939F1ZV"
|
|
18
|
+
* normalizeGSTIN(null); // ""
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizeGSTIN(gstin: unknown): string;
|
|
22
|
+
/**
|
|
23
|
+
* Quick boolean check: is the given GSTIN structurally valid?
|
|
24
|
+
*
|
|
25
|
+
* This checks length, format regex, state code validity, and checksum.
|
|
26
|
+
* For detailed diagnostics, use `validateGSTIN()` instead.
|
|
27
|
+
*
|
|
28
|
+
* @param gstin - Raw GSTIN input
|
|
29
|
+
* @returns `true` if valid, `false` otherwise
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* isValidGSTIN('27AAPFU0939F1ZV'); // true
|
|
34
|
+
* isValidGSTIN('INVALIDGSTIN'); // false
|
|
35
|
+
* isValidGSTIN(undefined); // false
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function isValidGSTIN(gstin: unknown): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Performs a detailed, multi-step validation of a GSTIN.
|
|
41
|
+
* Returns an object describing which checks passed and which failed,
|
|
42
|
+
* along with human-readable error messages.
|
|
43
|
+
*
|
|
44
|
+
* @param gstin - Raw GSTIN input
|
|
45
|
+
* @returns A `GSTINValidationResult` object
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const result = validateGSTIN('27AAPFU0939F1ZV');
|
|
50
|
+
* // {
|
|
51
|
+
* // isValid: true,
|
|
52
|
+
* // formatValid: true,
|
|
53
|
+
* // lengthValid: true,
|
|
54
|
+
* // stateCodeValid: true,
|
|
55
|
+
* // panSegmentValid: true,
|
|
56
|
+
* // entityCodeValid: true,
|
|
57
|
+
* // defaultZValid: true,
|
|
58
|
+
* // checksumValid: true,
|
|
59
|
+
* // errors: []
|
|
60
|
+
* // }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function validateGSTIN(gstin: unknown): GSTINValidationResult;
|
|
64
|
+
/**
|
|
65
|
+
* Parses a GSTIN into its constituent parts.
|
|
66
|
+
*
|
|
67
|
+
* Even if the GSTIN is invalid, this function will still attempt to extract
|
|
68
|
+
* whatever information it can (state code, PAN, etc.). The `isValid` field
|
|
69
|
+
* tells you whether the GSTIN passed all validation checks.
|
|
70
|
+
*
|
|
71
|
+
* @param gstin - Raw GSTIN input
|
|
72
|
+
* @returns A `GSTINParsedResult` object, or `null` if input is empty/unusable
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* parseGSTIN('27AAPFU0939F1ZV');
|
|
77
|
+
* // {
|
|
78
|
+
* // gstin: '27AAPFU0939F1ZV',
|
|
79
|
+
* // normalized: '27AAPFU0939F1ZV',
|
|
80
|
+
* // stateCode: '27',
|
|
81
|
+
* // stateName: 'Maharashtra',
|
|
82
|
+
* // pan: 'AAPFU0939F',
|
|
83
|
+
* // entityCode: '1',
|
|
84
|
+
* // defaultChar: 'Z',
|
|
85
|
+
* // checksum: 'V',
|
|
86
|
+
* // isValid: true
|
|
87
|
+
* // }
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function parseGSTIN(gstin: unknown): GSTINParsedResult | null;
|
|
91
|
+
/**
|
|
92
|
+
* Extracts the 2-digit state code from a GSTIN.
|
|
93
|
+
*
|
|
94
|
+
* @param gstin - Raw GSTIN input
|
|
95
|
+
* @returns The state code string, or `null` if input is too short
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* getStateCodeFromGSTIN('27AAPFU0939F1ZV'); // "27"
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function getStateCodeFromGSTIN(gstin: unknown): string | null;
|
|
103
|
+
/**
|
|
104
|
+
* Extracts the state/UT name from a GSTIN.
|
|
105
|
+
*
|
|
106
|
+
* @param gstin - Raw GSTIN input
|
|
107
|
+
* @returns The state name, or `null` if the code is unrecognized or input is too short
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* getStateNameFromGSTIN('27AAPFU0939F1ZV'); // "Maharashtra"
|
|
112
|
+
* getStateNameFromGSTIN('99XXXXX0000X1ZA'); // "Centre Jurisdiction"
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export declare function getStateNameFromGSTIN(gstin: unknown): string | null;
|
|
116
|
+
/**
|
|
117
|
+
* Extracts the PAN (characters 3β12) from a GSTIN.
|
|
118
|
+
*
|
|
119
|
+
* @param gstin - Raw GSTIN input
|
|
120
|
+
* @returns The 10-character PAN string, or `null` if input is too short
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* getPANFromGSTIN('27AAPFU0939F1ZV'); // "AAPFU0939F"
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export declare function getPANFromGSTIN(gstin: unknown): string | null;
|
|
128
|
+
/**
|
|
129
|
+
* Masks the middle portion of a GSTIN for display or logging purposes.
|
|
130
|
+
* Replaces characters 6β9 (0-indexed: 5β8) with asterisks.
|
|
131
|
+
*
|
|
132
|
+
* Format: `XXAAP****39F1ZV` (first 5 + **** + last 6)
|
|
133
|
+
*
|
|
134
|
+
* @param gstin - Raw GSTIN input
|
|
135
|
+
* @returns The masked GSTIN string, or `null` if input is too short
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* maskGSTIN('27AAPFU0939F1ZV'); // "27AAP****39F1ZV"
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export declare function maskGSTIN(gstin: unknown): string | null;
|
|
143
|
+
/**
|
|
144
|
+
* Checks whether a given 2-digit code is a valid GST state/UT code.
|
|
145
|
+
*
|
|
146
|
+
* @param code - A 2-digit state code string
|
|
147
|
+
* @returns `true` if the code is recognized, `false` otherwise
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* isValidStateCode('27'); // true (Maharashtra)
|
|
152
|
+
* isValidStateCode('00'); // false
|
|
153
|
+
* isValidStateCode('99'); // true (Centre Jurisdiction)
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export declare function isValidStateCode(code: unknown): boolean;
|
|
157
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAoDnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASpD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,CAyFnE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,CAyBnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAInE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAInE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI7D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAOvD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAIvD"}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module gstin-utils/validator
|
|
4
|
+
*
|
|
5
|
+
* Core GSTIN validation and utility functions.
|
|
6
|
+
* All functions accept raw user input and handle edge cases gracefully.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.normalizeGSTIN = normalizeGSTIN;
|
|
10
|
+
exports.isValidGSTIN = isValidGSTIN;
|
|
11
|
+
exports.validateGSTIN = validateGSTIN;
|
|
12
|
+
exports.parseGSTIN = parseGSTIN;
|
|
13
|
+
exports.getStateCodeFromGSTIN = getStateCodeFromGSTIN;
|
|
14
|
+
exports.getStateNameFromGSTIN = getStateNameFromGSTIN;
|
|
15
|
+
exports.getPANFromGSTIN = getPANFromGSTIN;
|
|
16
|
+
exports.maskGSTIN = maskGSTIN;
|
|
17
|
+
exports.isValidStateCode = isValidStateCode;
|
|
18
|
+
const state_codes_1 = require("./state-codes");
|
|
19
|
+
const checksum_1 = require("./checksum");
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Constants
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/**
|
|
24
|
+
* Regex pattern for a structurally valid GSTIN.
|
|
25
|
+
*
|
|
26
|
+
* Breakdown:
|
|
27
|
+
* ^ β start of string
|
|
28
|
+
* [0-9]{2} β 2-digit state code
|
|
29
|
+
* [A-Z]{5} β 5 letters of PAN (first 5 chars: entity type + name)
|
|
30
|
+
* [0-9]{4} β 4 digits of PAN
|
|
31
|
+
* [A-Z] β 1 letter of PAN (check letter)
|
|
32
|
+
* [1-9A-Z] β entity code (1β9 or AβZ, never 0)
|
|
33
|
+
* Z β default reserved character
|
|
34
|
+
* [0-9A-Z] β checksum character
|
|
35
|
+
* $ β end of string
|
|
36
|
+
*/
|
|
37
|
+
const GSTIN_REGEX = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$/;
|
|
38
|
+
/**
|
|
39
|
+
* Regex pattern for a valid PAN segment (characters 3β12 of GSTIN).
|
|
40
|
+
*
|
|
41
|
+
* PAN format: AAAAA9999A
|
|
42
|
+
* 5 uppercase letters + 4 digits + 1 uppercase letter
|
|
43
|
+
*/
|
|
44
|
+
const PAN_REGEX = /^[A-Z]{5}[0-9]{4}[A-Z]$/;
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Helpers (internal)
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
/**
|
|
49
|
+
* Safely coerces input to a trimmed, uppercased string.
|
|
50
|
+
* Returns an empty string for null, undefined, or non-string values.
|
|
51
|
+
*
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
function sanitize(input) {
|
|
55
|
+
if (input === null || input === undefined)
|
|
56
|
+
return '';
|
|
57
|
+
if (typeof input !== 'string')
|
|
58
|
+
return '';
|
|
59
|
+
return input.trim().toUpperCase();
|
|
60
|
+
}
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Public API
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
/**
|
|
65
|
+
* Normalizes a GSTIN string by trimming whitespace and converting
|
|
66
|
+
* to uppercase. Useful before storing or comparing GSTINs.
|
|
67
|
+
*
|
|
68
|
+
* @param gstin - Raw GSTIN input
|
|
69
|
+
* @returns Cleaned GSTIN string (trimmed + uppercased)
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* normalizeGSTIN(' 27aapfu0939f1zv '); // "27AAPFU0939F1ZV"
|
|
74
|
+
* normalizeGSTIN(null); // ""
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
function normalizeGSTIN(gstin) {
|
|
78
|
+
return sanitize(gstin);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Quick boolean check: is the given GSTIN structurally valid?
|
|
82
|
+
*
|
|
83
|
+
* This checks length, format regex, state code validity, and checksum.
|
|
84
|
+
* For detailed diagnostics, use `validateGSTIN()` instead.
|
|
85
|
+
*
|
|
86
|
+
* @param gstin - Raw GSTIN input
|
|
87
|
+
* @returns `true` if valid, `false` otherwise
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* isValidGSTIN('27AAPFU0939F1ZV'); // true
|
|
92
|
+
* isValidGSTIN('INVALIDGSTIN'); // false
|
|
93
|
+
* isValidGSTIN(undefined); // false
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
function isValidGSTIN(gstin) {
|
|
97
|
+
const normalized = sanitize(gstin);
|
|
98
|
+
if (normalized.length !== 15)
|
|
99
|
+
return false;
|
|
100
|
+
if (!GSTIN_REGEX.test(normalized))
|
|
101
|
+
return false;
|
|
102
|
+
const stateCode = normalized.substring(0, 2);
|
|
103
|
+
if (!(stateCode in state_codes_1.STATE_CODE_MAP))
|
|
104
|
+
return false;
|
|
105
|
+
return (0, checksum_1.isChecksumValid)(normalized);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Performs a detailed, multi-step validation of a GSTIN.
|
|
109
|
+
* Returns an object describing which checks passed and which failed,
|
|
110
|
+
* along with human-readable error messages.
|
|
111
|
+
*
|
|
112
|
+
* @param gstin - Raw GSTIN input
|
|
113
|
+
* @returns A `GSTINValidationResult` object
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const result = validateGSTIN('27AAPFU0939F1ZV');
|
|
118
|
+
* // {
|
|
119
|
+
* // isValid: true,
|
|
120
|
+
* // formatValid: true,
|
|
121
|
+
* // lengthValid: true,
|
|
122
|
+
* // stateCodeValid: true,
|
|
123
|
+
* // panSegmentValid: true,
|
|
124
|
+
* // entityCodeValid: true,
|
|
125
|
+
* // defaultZValid: true,
|
|
126
|
+
* // checksumValid: true,
|
|
127
|
+
* // errors: []
|
|
128
|
+
* // }
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
function validateGSTIN(gstin) {
|
|
132
|
+
const normalized = sanitize(gstin);
|
|
133
|
+
const errors = [];
|
|
134
|
+
// 1. Length check
|
|
135
|
+
const lengthValid = normalized.length === 15;
|
|
136
|
+
if (!lengthValid) {
|
|
137
|
+
errors.push(`GSTIN must be exactly 15 characters, received ${normalized.length}.`);
|
|
138
|
+
}
|
|
139
|
+
// 2. Overall format check
|
|
140
|
+
const formatValid = GSTIN_REGEX.test(normalized);
|
|
141
|
+
if (!formatValid && lengthValid) {
|
|
142
|
+
errors.push('GSTIN does not match the expected format.');
|
|
143
|
+
}
|
|
144
|
+
// For the remaining checks we need at least 15 characters
|
|
145
|
+
let stateCodeValid = false;
|
|
146
|
+
let panSegmentValid = false;
|
|
147
|
+
let entityCodeValid = false;
|
|
148
|
+
let defaultZValid = false;
|
|
149
|
+
let checksumValid = false;
|
|
150
|
+
if (lengthValid) {
|
|
151
|
+
// 3. State code check
|
|
152
|
+
const stateCode = normalized.substring(0, 2);
|
|
153
|
+
stateCodeValid = stateCode in state_codes_1.STATE_CODE_MAP;
|
|
154
|
+
if (!stateCodeValid) {
|
|
155
|
+
errors.push(`"${stateCode}" is not a recognized GST state/UT code.`);
|
|
156
|
+
}
|
|
157
|
+
// 4. PAN segment check (characters 3β12, i.e. index 2β11)
|
|
158
|
+
const panSegment = normalized.substring(2, 12);
|
|
159
|
+
panSegmentValid = PAN_REGEX.test(panSegment);
|
|
160
|
+
if (!panSegmentValid) {
|
|
161
|
+
errors.push(`PAN segment "${panSegment}" does not match the expected PAN format (AAAAA9999A).`);
|
|
162
|
+
}
|
|
163
|
+
// 5. Entity code check (13th character, index 12)
|
|
164
|
+
const entityCode = normalized[12];
|
|
165
|
+
entityCodeValid = /^[1-9A-Z]$/.test(entityCode);
|
|
166
|
+
if (!entityCodeValid) {
|
|
167
|
+
errors.push(`Entity code "${entityCode}" is invalid. Must be 1β9 or AβZ.`);
|
|
168
|
+
}
|
|
169
|
+
// 6. Default 'Z' check (14th character, index 13)
|
|
170
|
+
defaultZValid = normalized[13] === 'Z';
|
|
171
|
+
if (!defaultZValid) {
|
|
172
|
+
errors.push(`14th character must be "Z" (reserved), found "${normalized[13]}".`);
|
|
173
|
+
}
|
|
174
|
+
// 7. Checksum check (15th character, index 14)
|
|
175
|
+
checksumValid = (0, checksum_1.isChecksumValid)(normalized);
|
|
176
|
+
if (!checksumValid) {
|
|
177
|
+
const expected = (0, checksum_1.computeChecksum)(normalized);
|
|
178
|
+
errors.push(`Checksum character "${normalized[14]}" is invalid. Expected "${expected}".`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const isValid = lengthValid &&
|
|
182
|
+
formatValid &&
|
|
183
|
+
stateCodeValid &&
|
|
184
|
+
panSegmentValid &&
|
|
185
|
+
entityCodeValid &&
|
|
186
|
+
defaultZValid &&
|
|
187
|
+
checksumValid;
|
|
188
|
+
return {
|
|
189
|
+
isValid,
|
|
190
|
+
formatValid,
|
|
191
|
+
lengthValid,
|
|
192
|
+
stateCodeValid,
|
|
193
|
+
panSegmentValid,
|
|
194
|
+
entityCodeValid,
|
|
195
|
+
defaultZValid,
|
|
196
|
+
checksumValid,
|
|
197
|
+
errors,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Parses a GSTIN into its constituent parts.
|
|
202
|
+
*
|
|
203
|
+
* Even if the GSTIN is invalid, this function will still attempt to extract
|
|
204
|
+
* whatever information it can (state code, PAN, etc.). The `isValid` field
|
|
205
|
+
* tells you whether the GSTIN passed all validation checks.
|
|
206
|
+
*
|
|
207
|
+
* @param gstin - Raw GSTIN input
|
|
208
|
+
* @returns A `GSTINParsedResult` object, or `null` if input is empty/unusable
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```ts
|
|
212
|
+
* parseGSTIN('27AAPFU0939F1ZV');
|
|
213
|
+
* // {
|
|
214
|
+
* // gstin: '27AAPFU0939F1ZV',
|
|
215
|
+
* // normalized: '27AAPFU0939F1ZV',
|
|
216
|
+
* // stateCode: '27',
|
|
217
|
+
* // stateName: 'Maharashtra',
|
|
218
|
+
* // pan: 'AAPFU0939F',
|
|
219
|
+
* // entityCode: '1',
|
|
220
|
+
* // defaultChar: 'Z',
|
|
221
|
+
* // checksum: 'V',
|
|
222
|
+
* // isValid: true
|
|
223
|
+
* // }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
function parseGSTIN(gstin) {
|
|
227
|
+
var _a;
|
|
228
|
+
const raw = typeof gstin === 'string' ? gstin : '';
|
|
229
|
+
const normalized = sanitize(gstin);
|
|
230
|
+
if (normalized.length < 15)
|
|
231
|
+
return null;
|
|
232
|
+
const stateCode = normalized.substring(0, 2);
|
|
233
|
+
const stateName = (_a = (0, state_codes_1.getStateNameByCode)(stateCode)) !== null && _a !== void 0 ? _a : 'Unknown';
|
|
234
|
+
const pan = normalized.substring(2, 12);
|
|
235
|
+
const entityCode = normalized[12];
|
|
236
|
+
const defaultChar = normalized[13];
|
|
237
|
+
const checksum = normalized[14];
|
|
238
|
+
const valid = isValidGSTIN(normalized);
|
|
239
|
+
return {
|
|
240
|
+
gstin: raw.trim(),
|
|
241
|
+
normalized,
|
|
242
|
+
stateCode,
|
|
243
|
+
stateName,
|
|
244
|
+
pan,
|
|
245
|
+
entityCode,
|
|
246
|
+
defaultChar,
|
|
247
|
+
checksum,
|
|
248
|
+
isValid: valid,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Extracts the 2-digit state code from a GSTIN.
|
|
253
|
+
*
|
|
254
|
+
* @param gstin - Raw GSTIN input
|
|
255
|
+
* @returns The state code string, or `null` if input is too short
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* ```ts
|
|
259
|
+
* getStateCodeFromGSTIN('27AAPFU0939F1ZV'); // "27"
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
function getStateCodeFromGSTIN(gstin) {
|
|
263
|
+
const normalized = sanitize(gstin);
|
|
264
|
+
if (normalized.length < 2)
|
|
265
|
+
return null;
|
|
266
|
+
return normalized.substring(0, 2);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Extracts the state/UT name from a GSTIN.
|
|
270
|
+
*
|
|
271
|
+
* @param gstin - Raw GSTIN input
|
|
272
|
+
* @returns The state name, or `null` if the code is unrecognized or input is too short
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```ts
|
|
276
|
+
* getStateNameFromGSTIN('27AAPFU0939F1ZV'); // "Maharashtra"
|
|
277
|
+
* getStateNameFromGSTIN('99XXXXX0000X1ZA'); // "Centre Jurisdiction"
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
function getStateNameFromGSTIN(gstin) {
|
|
281
|
+
var _a;
|
|
282
|
+
const code = getStateCodeFromGSTIN(gstin);
|
|
283
|
+
if (!code)
|
|
284
|
+
return null;
|
|
285
|
+
return (_a = (0, state_codes_1.getStateNameByCode)(code)) !== null && _a !== void 0 ? _a : null;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Extracts the PAN (characters 3β12) from a GSTIN.
|
|
289
|
+
*
|
|
290
|
+
* @param gstin - Raw GSTIN input
|
|
291
|
+
* @returns The 10-character PAN string, or `null` if input is too short
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```ts
|
|
295
|
+
* getPANFromGSTIN('27AAPFU0939F1ZV'); // "AAPFU0939F"
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
function getPANFromGSTIN(gstin) {
|
|
299
|
+
const normalized = sanitize(gstin);
|
|
300
|
+
if (normalized.length < 12)
|
|
301
|
+
return null;
|
|
302
|
+
return normalized.substring(2, 12);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Masks the middle portion of a GSTIN for display or logging purposes.
|
|
306
|
+
* Replaces characters 6β9 (0-indexed: 5β8) with asterisks.
|
|
307
|
+
*
|
|
308
|
+
* Format: `XXAAP****39F1ZV` (first 5 + **** + last 6)
|
|
309
|
+
*
|
|
310
|
+
* @param gstin - Raw GSTIN input
|
|
311
|
+
* @returns The masked GSTIN string, or `null` if input is too short
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* maskGSTIN('27AAPFU0939F1ZV'); // "27AAP****39F1ZV"
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
function maskGSTIN(gstin) {
|
|
319
|
+
const normalized = sanitize(gstin);
|
|
320
|
+
if (normalized.length < 15)
|
|
321
|
+
return null;
|
|
322
|
+
const prefix = normalized.substring(0, 5); // "27AAP"
|
|
323
|
+
const suffix = normalized.substring(9, 15); // "39F1ZV"
|
|
324
|
+
return `${prefix}****${suffix}`;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Checks whether a given 2-digit code is a valid GST state/UT code.
|
|
328
|
+
*
|
|
329
|
+
* @param code - A 2-digit state code string
|
|
330
|
+
* @returns `true` if the code is recognized, `false` otherwise
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* ```ts
|
|
334
|
+
* isValidStateCode('27'); // true (Maharashtra)
|
|
335
|
+
* isValidStateCode('00'); // false
|
|
336
|
+
* isValidStateCode('99'); // true (Centre Jurisdiction)
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
function isValidStateCode(code) {
|
|
340
|
+
if (typeof code !== 'string')
|
|
341
|
+
return false;
|
|
342
|
+
const trimmed = code.trim();
|
|
343
|
+
return trimmed in state_codes_1.STATE_CODE_MAP;
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAmEH,wCAEC;AAkBD,oCASC;AA0BD,sCAyFC;AA4BD,gCAyBC;AAaD,sDAIC;AAcD,sDAIC;AAaD,0CAIC;AAgBD,8BAOC;AAeD,4CAIC;AAnWD,+CAAmE;AACnE,yCAA8D;AAE9D,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,GAAG,kDAAkD,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,SAAS,GAAG,yBAAyB,CAAC;AAE5C,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;GAKG;AACH,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACpC,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,SAAgB,cAAc,CAAC,KAAc;IAC3C,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,YAAY,CAAC,KAAc;IACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAEhD,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC,SAAS,IAAI,4BAAc,CAAC;QAAE,OAAO,KAAK,CAAC;IAEjD,OAAO,IAAA,0BAAe,EAAC,UAAU,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,aAAa,CAAC,KAAc;IAC1C,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,kBAAkB;IAClB,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC;IAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CACT,iDAAiD,UAAU,CAAC,MAAM,GAAG,CACtE,CAAC;IACJ,CAAC;IAED,0BAA0B;IAC1B,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,WAAW,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IAC3D,CAAC;IAED,0DAA0D;IAC1D,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,aAAa,GAAG,KAAK,CAAC;IAE1B,IAAI,WAAW,EAAE,CAAC;QAChB,sBAAsB;QACtB,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7C,cAAc,GAAG,SAAS,IAAI,4BAAc,CAAC;QAC7C,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,0CAA0C,CAAC,CAAC;QACvE,CAAC;QAED,0DAA0D;QAC1D,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/C,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CACT,gBAAgB,UAAU,wDAAwD,CACnF,CAAC;QACJ,CAAC;QAED,kDAAkD;QAClD,MAAM,UAAU,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAClC,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CACT,gBAAgB,UAAU,mCAAmC,CAC9D,CAAC;QACJ,CAAC;QAED,kDAAkD;QAClD,aAAa,GAAG,UAAU,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC;QACvC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CACT,iDAAiD,UAAU,CAAC,EAAE,CAAC,IAAI,CACpE,CAAC;QACJ,CAAC;QAED,+CAA+C;QAC/C,aAAa,GAAG,IAAA,0BAAe,EAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,IAAA,0BAAe,EAAC,UAAU,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CACT,uBAAuB,UAAU,CAAC,EAAE,CAAC,2BAA2B,QAAQ,IAAI,CAC7E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GACX,WAAW;QACX,WAAW;QACX,cAAc;QACd,eAAe;QACf,eAAe;QACf,aAAa;QACb,aAAa,CAAC;IAEhB,OAAO;QACL,OAAO;QACP,WAAW;QACX,WAAW;QACX,cAAc;QACd,eAAe;QACf,eAAe;QACf,aAAa;QACb,aAAa;QACb,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,UAAU,CAAC,KAAc;;IACvC,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,UAAU,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,MAAA,IAAA,gCAAkB,EAAC,SAAS,CAAC,mCAAI,SAAS,CAAC;IAC7D,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,WAAW,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAEvC,OAAO;QACL,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE;QACjB,UAAU;QACV,SAAS;QACT,SAAS;QACT,GAAG;QACH,UAAU;QACV,WAAW;QACX,QAAQ;QACR,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,qBAAqB,CAAC,KAAc;IAClD,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,qBAAqB,CAAC,KAAc;;IAClD,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,MAAA,IAAA,gCAAkB,EAAC,IAAI,CAAC,mCAAI,IAAI,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,eAAe,CAAC,KAAc;IAC5C,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,UAAU,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,SAAS,CAAC,KAAc;IACtC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,UAAU,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAG,UAAU;IACvD,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAE,WAAW;IACxD,OAAO,GAAG,MAAM,OAAO,MAAM,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,gBAAgB,CAAC,IAAa;IAC5C,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,OAAO,IAAI,4BAAc,CAAC;AACnC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gstin-utils",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight, zero-dependency utility package for Indian GSTIN validation, parsing, normalization, masking, and metadata extraction.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"test:coverage": "jest --coverage",
|
|
16
|
+
"prepublishOnly": "npm run build && npm test",
|
|
17
|
+
"lint": "tsc --noEmit"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"gstin",
|
|
21
|
+
"gst",
|
|
22
|
+
"india",
|
|
23
|
+
"tax",
|
|
24
|
+
"validation",
|
|
25
|
+
"parser",
|
|
26
|
+
"fintech",
|
|
27
|
+
"invoice",
|
|
28
|
+
"erp",
|
|
29
|
+
"pan",
|
|
30
|
+
"state-code",
|
|
31
|
+
"checksum",
|
|
32
|
+
"masking",
|
|
33
|
+
"utility"
|
|
34
|
+
],
|
|
35
|
+
"author": "Dheeraj Singh",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/dheeraj0808/gstin-validator"
|
|
40
|
+
},
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/dheeraj0808/gstin-validator/issues"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/ujjwalpratap/gstin-utils#readme",
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=14.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/jest": "^29.5.12",
|
|
50
|
+
"jest": "^29.7.0",
|
|
51
|
+
"ts-jest": "^29.1.2",
|
|
52
|
+
"typescript": "^5.4.5"
|
|
53
|
+
}
|
|
54
|
+
}
|