inr-num-words 0.0.0-stage → 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 Pirapaakaran Pirathapan
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 CHANGED
@@ -1,3 +1,142 @@
1
- # Temporary Holding Version
1
+ # 🇮🇳 inr-num-words
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > Zero-dependency TypeScript utility for converting numbers and Indian Rupee (INR) amounts into words (English & Tamil) with Lakhs, Crores, Paise, Cheque formatting, and GST calculation.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/inr-num-words.svg)](https://www.npmjs.com/package/inr-num-words)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue?logo=typescript)](https://www.typescriptlang.org/)
8
+
9
+ ---
10
+
11
+ ## ✨ Features
12
+
13
+ - 🏛️ **Indian Numbering System** — Formats accurately with **Lakhs** (1,00,000) and **Crores** (1,00,00,000), not Western millions/billions.
14
+ - 🧾 **Invoice & Cheque Ready** — Automatically appends `"Rupees"`, `"Paise"`, and `"Only"` (standard for bank cheques & billing apps).
15
+ - 🇮🇳 **Tamil Language Support (தமிழ்)** — Convert any number or currency directly to Tamil words (`இலட்சம்`, `கோடி`, `ரூபாய்`, `பைசா`).
16
+ - 💰 **GST Tax Calculator** — Calculate CGST + SGST (Intra-state) or IGST (Inter-state) and receive total with words in one call.
17
+ - 🪙 **Indian Currency Formatter** — Easy comma grouping (`₹ 15,00,000.00`).
18
+ - ⚡ **Zero Dependencies** — Ultra-lightweight (~3 KB), purely native JavaScript/TypeScript.
19
+ - 📦 **Dual ESM & CommonJS** — Works in Node.js, Next.js, React, React Native, Vite, Express, and browsers.
20
+
21
+ ---
22
+
23
+ ## 📥 Installation
24
+
25
+ ```bash
26
+ npm install inr-num-words
27
+ ```
28
+ or with Yarn / pnpm:
29
+ ```bash
30
+ pnpm add inr-num-words
31
+ # or
32
+ yarn add inr-num-words
33
+ ```
34
+
35
+ ---
36
+
37
+ ## 🚀 Quick Start
38
+
39
+ ### 1. Bank Cheque & Invoice Format (English)
40
+
41
+ ```typescript
42
+ import { numberToIndianWords } from 'inr-num-words';
43
+
44
+ console.log(numberToIndianWords(150000));
45
+ // "One Lakh Fifty Thousand Rupees Only"
46
+
47
+ console.log(numberToIndianWords(125450.75));
48
+ // "One Lakh Twenty-Five Thousand Four Hundred Fifty Rupees and Seventy-Five Paise Only"
49
+
50
+ console.log(numberToIndianWords(25000000));
51
+ // "Two Crore Fifty Lakh Rupees Only"
52
+ ```
53
+
54
+ ---
55
+
56
+ ### 2. Tamil Words Output (தமிழ்)
57
+
58
+ ```typescript
59
+ import { numberToTamilWords } from 'inr-num-words';
60
+
61
+ console.log(numberToTamilWords(1500));
62
+ // "ஆயிரத்து ஐந்நூறு ரூபாய் மட்டும்"
63
+
64
+ console.log(numberToTamilWords(100000));
65
+ // "ஒன்று இலட்சம் ரூபாய் மட்டும்"
66
+ ```
67
+
68
+ ---
69
+
70
+ ### 3. Currency Comma Formatter (`formatINR`)
71
+
72
+ ```typescript
73
+ import { formatINR } from 'inr-num-words';
74
+
75
+ console.log(formatINR(1234567.89));
76
+ // "₹ 12,34,567.89"
77
+
78
+ console.log(formatINR(50000, { symbol: false }));
79
+ // "50,000.00"
80
+ ```
81
+
82
+ ---
83
+
84
+ ### 4. GST Breakdown & Invoice Helper
85
+
86
+ ```typescript
87
+ import { calculateGST } from 'inr-num-words';
88
+
89
+ // Intra-state (Within Tamil Nadu): 18% GST splits into 9% CGST + 9% SGST
90
+ const invoice = calculateGST(10000, 18, false);
91
+
92
+ console.log(invoice);
93
+ /*
94
+ {
95
+ baseAmount: 10000,
96
+ gstRate: 18,
97
+ isInterState: false,
98
+ cgstAmount: 900,
99
+ sgstAmount: 900,
100
+ igstAmount: 0,
101
+ totalTax: 1800,
102
+ totalAmount: 11800,
103
+ totalInWords: "Eleven Thousand Eight Hundred Rupees Only"
104
+ }
105
+ */
106
+ ```
107
+
108
+ ---
109
+
110
+ ## ⚙️ Options Reference
111
+
112
+ ```typescript
113
+ numberToIndianWords(amount, options)
114
+ ```
115
+
116
+ | Option | Type | Default | Description |
117
+ |---|---|---|---|
118
+ | `currency` | `boolean` | `true` | Appends "Rupees" or "ரூபாய்". |
119
+ | `includePaise` | `boolean` | `true` | Formats decimal cents as "Paise" / "பைசா". |
120
+ | `suffixOnly` | `boolean` | `true` | Appends "Only" / "மட்டும்" at the end. |
121
+ | `language` | `'en' \| 'ta'` | `'en'` | Output language (`'en'` for English, `'ta'` for Tamil). |
122
+
123
+ ---
124
+
125
+ ## 🛠 Development & Testing
126
+
127
+ ```bash
128
+ # Install dependencies
129
+ npm install
130
+
131
+ # Run unit tests
132
+ npm test
133
+
134
+ # Build dual ESM/CJS bundles + .d.ts types
135
+ npm run build
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 📄 License
141
+
142
+ MIT © 2026 Pirapaakaran Pirathapan
package/dist/index.cjs ADDED
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ calculateGST: () => calculateGST,
24
+ formatINR: () => formatINR,
25
+ numberToIndianWords: () => numberToIndianWords,
26
+ numberToTamilWords: () => numberToTamilWords
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+ var EN_ONES = [
30
+ "",
31
+ "One",
32
+ "Two",
33
+ "Three",
34
+ "Four",
35
+ "Five",
36
+ "Six",
37
+ "Seven",
38
+ "Eight",
39
+ "Nine",
40
+ "Ten",
41
+ "Eleven",
42
+ "Twelve",
43
+ "Thirteen",
44
+ "Fourteen",
45
+ "Fifteen",
46
+ "Sixteen",
47
+ "Seventeen",
48
+ "Eighteen",
49
+ "Nineteen"
50
+ ];
51
+ var EN_TENS = [
52
+ "",
53
+ "",
54
+ "Twenty",
55
+ "Thirty",
56
+ "Forty",
57
+ "Fifty",
58
+ "Sixty",
59
+ "Seventy",
60
+ "Eighty",
61
+ "Ninety"
62
+ ];
63
+ function convertThreeDigitEnglish(n) {
64
+ let str = "";
65
+ if (n >= 100) {
66
+ str += EN_ONES[Math.floor(n / 100)] + " Hundred ";
67
+ n %= 100;
68
+ }
69
+ if (n >= 20) {
70
+ const tens = EN_TENS[Math.floor(n / 10)];
71
+ n %= 10;
72
+ if (n > 0) {
73
+ str += `${tens}-${EN_ONES[n]} `;
74
+ n = 0;
75
+ } else {
76
+ str += `${tens} `;
77
+ }
78
+ } else if (n > 0) {
79
+ str += EN_ONES[n] + " ";
80
+ }
81
+ return str.trim();
82
+ }
83
+ function convertIntegerToIndianWordsEn(num) {
84
+ if (num === 0) return "Zero";
85
+ const parts = [];
86
+ const crores = Math.floor(num / 1e7);
87
+ num %= 1e7;
88
+ const lakhs = Math.floor(num / 1e5);
89
+ num %= 1e5;
90
+ const thousands = Math.floor(num / 1e3);
91
+ num %= 1e3;
92
+ const remaining = Math.floor(num);
93
+ if (crores > 0) {
94
+ const croreWords = crores >= 100 ? convertIntegerToIndianWordsEn(crores) : convertThreeDigitEnglish(crores);
95
+ parts.push(`${croreWords} Crore`);
96
+ }
97
+ if (lakhs > 0) {
98
+ parts.push(`${convertThreeDigitEnglish(lakhs)} Lakh`);
99
+ }
100
+ if (thousands > 0) {
101
+ parts.push(`${convertThreeDigitEnglish(thousands)} Thousand`);
102
+ }
103
+ if (remaining > 0) {
104
+ parts.push(convertThreeDigitEnglish(remaining));
105
+ }
106
+ return parts.join(" ").trim();
107
+ }
108
+ var TA_ONES = [
109
+ "",
110
+ "\u0B92\u0BA9\u0BCD\u0BB1\u0BC1",
111
+ "\u0B87\u0BB0\u0BA3\u0BCD\u0B9F\u0BC1",
112
+ "\u0BAE\u0BC2\u0BA9\u0BCD\u0BB1\u0BC1",
113
+ "\u0BA8\u0BBE\u0BA9\u0BCD\u0B95\u0BC1",
114
+ "\u0B90\u0BA8\u0BCD\u0BA4\u0BC1",
115
+ "\u0B86\u0BB1\u0BC1",
116
+ "\u0B8F\u0BB4\u0BC1",
117
+ "\u0B8E\u0B9F\u0BCD\u0B9F\u0BC1",
118
+ "\u0B92\u0BA9\u0BCD\u0BAA\u0BA4\u0BC1",
119
+ "\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1",
120
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BCA\u0BA9\u0BCD\u0BB1\u0BC1",
121
+ "\u0BAA\u0BA9\u0BCD\u0BA9\u0BBF\u0BB0\u0BA3\u0BCD\u0B9F\u0BC1",
122
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BCD\u0BAE\u0BC2\u0BA9\u0BCD\u0BB1\u0BC1",
123
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BBE\u0BA9\u0BCD\u0B95\u0BC1",
124
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BC8\u0BA8\u0BCD\u0BA4\u0BC1",
125
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BBE\u0BB1\u0BC1",
126
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BC7\u0BB4\u0BC1",
127
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BC6\u0B9F\u0BCD\u0B9F\u0BC1",
128
+ "\u0BAA\u0BA4\u0BCD\u0BA4\u0BCA\u0BA9\u0BCD\u0BAA\u0BA4\u0BC1"
129
+ ];
130
+ var TA_TENS_PREFIX = [
131
+ "",
132
+ "",
133
+ "\u0B87\u0BB0\u0BC1\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
134
+ "\u0BAE\u0BC1\u0BAA\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
135
+ "\u0BA8\u0BBE\u0BB1\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
136
+ "\u0B90\u0BAE\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
137
+ "\u0B85\u0BB1\u0BC1\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
138
+ "\u0B8E\u0BB4\u0BC1\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
139
+ "\u0B8E\u0BA3\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
140
+ "\u0BA4\u0BCA\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 "
141
+ ];
142
+ var TA_TENS_EXACT = [
143
+ "",
144
+ "",
145
+ "\u0B87\u0BB0\u0BC1\u0BAA\u0BA4\u0BC1",
146
+ "\u0BAE\u0BC1\u0BAA\u0BCD\u0BAA\u0BA4\u0BC1",
147
+ "\u0BA8\u0BBE\u0BB1\u0BCD\u0BAA\u0BA4\u0BC1",
148
+ "\u0B90\u0BAE\u0BCD\u0BAA\u0BA4\u0BC1",
149
+ "\u0B85\u0BB1\u0BC1\u0BAA\u0BA4\u0BC1",
150
+ "\u0B8E\u0BB4\u0BC1\u0BAA\u0BA4\u0BC1",
151
+ "\u0B8E\u0BA3\u0BCD\u0BAA\u0BA4\u0BC1",
152
+ "\u0BA4\u0BCA\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BC1"
153
+ ];
154
+ var TA_HUNDREDS = [
155
+ "",
156
+ "\u0BA8\u0BC2\u0BB1\u0BC1",
157
+ "\u0B87\u0BB0\u0BC1\u0BA8\u0BC2\u0BB1\u0BC1",
158
+ "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BC1",
159
+ "\u0BA8\u0BBE\u0BA9\u0BC2\u0BB1\u0BC1",
160
+ "\u0B90\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BC1",
161
+ "\u0B85\u0BB1\u0BC1\u0BA8\u0BC2\u0BB1\u0BC1",
162
+ "\u0B8E\u0BB4\u0BC1\u0BA8\u0BC2\u0BB1\u0BC1",
163
+ "\u0B8E\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BC1",
164
+ "\u0BA4\u0BCA\u0BB3\u0BCD\u0BB3\u0BBE\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD"
165
+ ];
166
+ function convertThreeDigitTamil(n) {
167
+ let str = "";
168
+ if (n >= 100) {
169
+ const h = Math.floor(n / 100);
170
+ n %= 100;
171
+ if (n === 0) {
172
+ str += TA_HUNDREDS[h] + " ";
173
+ } else {
174
+ const prefix = ["\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B87\u0BB0\u0BC1\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0BA8\u0BBE\u0BA9\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B90\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B85\u0BB1\u0BC1\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B8E\u0BB4\u0BC1\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B8E\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0BA4\u0BCA\u0BB3\u0BCD\u0BB3\u0BBE\u0BAF\u0BBF\u0BB0\u0BA4\u0BCD\u0BA4\u0BC1 "];
175
+ str += prefix[h - 1];
176
+ }
177
+ }
178
+ if (n >= 20) {
179
+ const t = Math.floor(n / 10);
180
+ n %= 10;
181
+ if (n === 0) {
182
+ str += TA_TENS_EXACT[t] + " ";
183
+ } else {
184
+ str += TA_TENS_PREFIX[t];
185
+ }
186
+ }
187
+ if (n > 0) {
188
+ str += TA_ONES[n] + " ";
189
+ }
190
+ return str.trim();
191
+ }
192
+ function convertIntegerToTamilWords(num) {
193
+ if (num === 0) return "\u0BAA\u0BC2\u0B9C\u0BCD\u0B9C\u0BBF\u0BAF\u0BAE\u0BCD";
194
+ const parts = [];
195
+ const crores = Math.floor(num / 1e7);
196
+ num %= 1e7;
197
+ const lakhs = Math.floor(num / 1e5);
198
+ num %= 1e5;
199
+ const thousands = Math.floor(num / 1e3);
200
+ num %= 1e3;
201
+ const remaining = Math.floor(num);
202
+ if (crores > 0) {
203
+ const croreWords = crores >= 100 ? convertIntegerToTamilWords(crores) : convertThreeDigitTamil(crores);
204
+ parts.push(`${croreWords} \u0B95\u0BCB\u0B9F\u0BBF`);
205
+ }
206
+ if (lakhs > 0) {
207
+ parts.push(`${convertThreeDigitTamil(lakhs)} \u0B87\u0BB2\u0B9F\u0BCD\u0B9A\u0BAE\u0BCD`);
208
+ }
209
+ if (thousands > 0) {
210
+ parts.push(`${convertThreeDigitTamil(thousands)} \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD`);
211
+ }
212
+ if (remaining > 0) {
213
+ parts.push(convertThreeDigitTamil(remaining));
214
+ }
215
+ return parts.join(" ").trim();
216
+ }
217
+ function numberToIndianWords(amount, options = {}) {
218
+ const {
219
+ currency = true,
220
+ includePaise = true,
221
+ suffixOnly = true,
222
+ language = "en"
223
+ } = options;
224
+ if (isNaN(amount)) {
225
+ return language === "ta" ? "\u0B9A\u0BC6\u0BB2\u0BCD\u0BB2\u0BC1\u0BAA\u0B9F\u0BBF\u0BAF\u0BBE\u0B95\u0BBE\u0BA4 \u0B8E\u0BA3\u0BCD" : "Invalid Number";
226
+ }
227
+ const isNegative = amount < 0;
228
+ const absAmount = Math.abs(amount);
229
+ const integerPart = Math.floor(absAmount);
230
+ const decimalPart = Math.round((absAmount - integerPart) * 100);
231
+ if (language === "ta") {
232
+ let result2 = convertIntegerToTamilWords(integerPart);
233
+ if (currency) {
234
+ result2 += " \u0BB0\u0BC2\u0BAA\u0BBE\u0BAF\u0BCD";
235
+ }
236
+ if (includePaise && decimalPart > 0) {
237
+ const paiseWord = convertThreeDigitTamil(decimalPart);
238
+ result2 += ` ${paiseWord} \u0BAA\u0BC8\u0B9A\u0BBE`;
239
+ }
240
+ if (suffixOnly) {
241
+ result2 += " \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD";
242
+ }
243
+ return (isNegative ? "\u0BAE\u0BC8\u0BA9\u0BB8\u0BCD " : "") + result2.trim();
244
+ }
245
+ let result = convertIntegerToIndianWordsEn(integerPart);
246
+ if (currency) {
247
+ result += integerPart === 1 ? " Rupee" : " Rupees";
248
+ }
249
+ if (includePaise && decimalPart > 0) {
250
+ const paiseWord = convertThreeDigitEnglish(decimalPart);
251
+ result += ` and ${paiseWord} Paise`;
252
+ }
253
+ if (suffixOnly) {
254
+ result += " Only";
255
+ }
256
+ return (isNegative ? "Minus " : "") + result.trim();
257
+ }
258
+ function numberToTamilWords(amount, options = {}) {
259
+ return numberToIndianWords(amount, { ...options, language: "ta" });
260
+ }
261
+ function formatINR(amount, options = {}) {
262
+ const { symbol = true, decimals = 2 } = options;
263
+ const formatted = new Intl.NumberFormat("en-IN", {
264
+ minimumFractionDigits: decimals,
265
+ maximumFractionDigits: decimals
266
+ }).format(amount);
267
+ return symbol ? `\u20B9 ${formatted}` : formatted;
268
+ }
269
+ function calculateGST(baseAmount, gstRatePercent, isInterState = false) {
270
+ const totalTax = Number((baseAmount * gstRatePercent / 100).toFixed(2));
271
+ const totalAmount = Number((baseAmount + totalTax).toFixed(2));
272
+ let cgstAmount = 0;
273
+ let sgstAmount = 0;
274
+ let igstAmount = 0;
275
+ if (isInterState) {
276
+ igstAmount = totalTax;
277
+ } else {
278
+ cgstAmount = Number((totalTax / 2).toFixed(2));
279
+ sgstAmount = Number((totalTax / 2).toFixed(2));
280
+ }
281
+ return {
282
+ baseAmount,
283
+ gstRate: gstRatePercent,
284
+ isInterState,
285
+ cgstAmount,
286
+ sgstAmount,
287
+ igstAmount,
288
+ totalTax,
289
+ totalAmount,
290
+ totalInWords: numberToIndianWords(totalAmount)
291
+ };
292
+ }
293
+ // Annotate the CommonJS export names for ESM import in node:
294
+ 0 && (module.exports = {
295
+ calculateGST,
296
+ formatINR,
297
+ numberToIndianWords,
298
+ numberToTamilWords
299
+ });
@@ -0,0 +1,87 @@
1
+ /**
2
+ * inr-num-words
3
+ * Zero-dependency utility for converting numbers and Indian Rupee (INR) amounts
4
+ * into words (English & Tamil) with Lakhs, Crores, Paise, and Invoice/Cheque formatting.
5
+ */
6
+ interface IndianWordsOptions {
7
+ /**
8
+ * Whether to include currency wording ("Rupees" or "ரூபாய்").
9
+ * @default true
10
+ */
11
+ currency?: boolean;
12
+ /**
13
+ * Whether to include the decimal fractional part as Paise ("Fifty Paise" or "ஐம்பது பைசா").
14
+ * @default true
15
+ */
16
+ includePaise?: boolean;
17
+ /**
18
+ * Whether to append "Only" / "மட்டும்" at the end (standard for cheques and invoices).
19
+ * @default true
20
+ */
21
+ suffixOnly?: boolean;
22
+ /**
23
+ * Language for word conversion: 'en' for English, 'ta' for Tamil.
24
+ * @default 'en'
25
+ */
26
+ language?: 'en' | 'ta';
27
+ }
28
+ /**
29
+ * Converts a number to words in the Indian numbering system.
30
+ * Supports English and Tamil outputs, Lakhs, Crores, Paise, and Invoice format.
31
+ *
32
+ * @param amount Numeric value to convert (can include decimals)
33
+ * @param options Configuration for currency words, paise, language, suffix
34
+ * @returns Fully formatted words string
35
+ *
36
+ * @example
37
+ * numberToIndianWords(125450.50)
38
+ * // "One Lakh Twenty-Five Thousand Four Hundred Fifty Rupees and Fifty Paise Only"
39
+ *
40
+ * numberToIndianWords(1500, { language: 'ta' })
41
+ * // "ஆயிரத்து ஐந்நூறு ரூபாய் மட்டும்"
42
+ */
43
+ declare function numberToIndianWords(amount: number, options?: IndianWordsOptions): string;
44
+ /**
45
+ * Shorthand helper for Tamil words conversion.
46
+ */
47
+ declare function numberToTamilWords(amount: number, options?: Omit<IndianWordsOptions, 'language'>): string;
48
+ interface FormatINROptions {
49
+ /**
50
+ * Whether to include the Rupee symbol ₹.
51
+ * @default true
52
+ */
53
+ symbol?: boolean;
54
+ /**
55
+ * Number of decimal places.
56
+ * @default 2
57
+ */
58
+ decimals?: number;
59
+ }
60
+ /**
61
+ * Formats a number with Indian comma grouping (Lakhs and Crores).
62
+ *
63
+ * @example
64
+ * formatINR(1234567.89) // "₹ 12,34,567.89"
65
+ */
66
+ declare function formatINR(amount: number, options?: FormatINROptions): string;
67
+ interface GSTCalculationResult {
68
+ baseAmount: number;
69
+ gstRate: number;
70
+ isInterState: boolean;
71
+ cgstAmount: number;
72
+ sgstAmount: number;
73
+ igstAmount: number;
74
+ totalTax: number;
75
+ totalAmount: number;
76
+ totalInWords: string;
77
+ }
78
+ /**
79
+ * Calculates GST breakdown (CGST + SGST or IGST) and provides total in words.
80
+ *
81
+ * @param baseAmount The pre-tax taxable amount
82
+ * @param gstRatePercent GST rate (e.g., 5, 12, 18, 28)
83
+ * @param isInterState If true, IGST is applied instead of CGST + SGST
84
+ */
85
+ declare function calculateGST(baseAmount: number, gstRatePercent: number, isInterState?: boolean): GSTCalculationResult;
86
+
87
+ export { type FormatINROptions, type GSTCalculationResult, type IndianWordsOptions, calculateGST, formatINR, numberToIndianWords, numberToTamilWords };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * inr-num-words
3
+ * Zero-dependency utility for converting numbers and Indian Rupee (INR) amounts
4
+ * into words (English & Tamil) with Lakhs, Crores, Paise, and Invoice/Cheque formatting.
5
+ */
6
+ interface IndianWordsOptions {
7
+ /**
8
+ * Whether to include currency wording ("Rupees" or "ரூபாய்").
9
+ * @default true
10
+ */
11
+ currency?: boolean;
12
+ /**
13
+ * Whether to include the decimal fractional part as Paise ("Fifty Paise" or "ஐம்பது பைசா").
14
+ * @default true
15
+ */
16
+ includePaise?: boolean;
17
+ /**
18
+ * Whether to append "Only" / "மட்டும்" at the end (standard for cheques and invoices).
19
+ * @default true
20
+ */
21
+ suffixOnly?: boolean;
22
+ /**
23
+ * Language for word conversion: 'en' for English, 'ta' for Tamil.
24
+ * @default 'en'
25
+ */
26
+ language?: 'en' | 'ta';
27
+ }
28
+ /**
29
+ * Converts a number to words in the Indian numbering system.
30
+ * Supports English and Tamil outputs, Lakhs, Crores, Paise, and Invoice format.
31
+ *
32
+ * @param amount Numeric value to convert (can include decimals)
33
+ * @param options Configuration for currency words, paise, language, suffix
34
+ * @returns Fully formatted words string
35
+ *
36
+ * @example
37
+ * numberToIndianWords(125450.50)
38
+ * // "One Lakh Twenty-Five Thousand Four Hundred Fifty Rupees and Fifty Paise Only"
39
+ *
40
+ * numberToIndianWords(1500, { language: 'ta' })
41
+ * // "ஆயிரத்து ஐந்நூறு ரூபாய் மட்டும்"
42
+ */
43
+ declare function numberToIndianWords(amount: number, options?: IndianWordsOptions): string;
44
+ /**
45
+ * Shorthand helper for Tamil words conversion.
46
+ */
47
+ declare function numberToTamilWords(amount: number, options?: Omit<IndianWordsOptions, 'language'>): string;
48
+ interface FormatINROptions {
49
+ /**
50
+ * Whether to include the Rupee symbol ₹.
51
+ * @default true
52
+ */
53
+ symbol?: boolean;
54
+ /**
55
+ * Number of decimal places.
56
+ * @default 2
57
+ */
58
+ decimals?: number;
59
+ }
60
+ /**
61
+ * Formats a number with Indian comma grouping (Lakhs and Crores).
62
+ *
63
+ * @example
64
+ * formatINR(1234567.89) // "₹ 12,34,567.89"
65
+ */
66
+ declare function formatINR(amount: number, options?: FormatINROptions): string;
67
+ interface GSTCalculationResult {
68
+ baseAmount: number;
69
+ gstRate: number;
70
+ isInterState: boolean;
71
+ cgstAmount: number;
72
+ sgstAmount: number;
73
+ igstAmount: number;
74
+ totalTax: number;
75
+ totalAmount: number;
76
+ totalInWords: string;
77
+ }
78
+ /**
79
+ * Calculates GST breakdown (CGST + SGST or IGST) and provides total in words.
80
+ *
81
+ * @param baseAmount The pre-tax taxable amount
82
+ * @param gstRatePercent GST rate (e.g., 5, 12, 18, 28)
83
+ * @param isInterState If true, IGST is applied instead of CGST + SGST
84
+ */
85
+ declare function calculateGST(baseAmount: number, gstRatePercent: number, isInterState?: boolean): GSTCalculationResult;
86
+
87
+ export { type FormatINROptions, type GSTCalculationResult, type IndianWordsOptions, calculateGST, formatINR, numberToIndianWords, numberToTamilWords };
package/dist/index.js ADDED
@@ -0,0 +1,271 @@
1
+ // src/index.ts
2
+ var EN_ONES = [
3
+ "",
4
+ "One",
5
+ "Two",
6
+ "Three",
7
+ "Four",
8
+ "Five",
9
+ "Six",
10
+ "Seven",
11
+ "Eight",
12
+ "Nine",
13
+ "Ten",
14
+ "Eleven",
15
+ "Twelve",
16
+ "Thirteen",
17
+ "Fourteen",
18
+ "Fifteen",
19
+ "Sixteen",
20
+ "Seventeen",
21
+ "Eighteen",
22
+ "Nineteen"
23
+ ];
24
+ var EN_TENS = [
25
+ "",
26
+ "",
27
+ "Twenty",
28
+ "Thirty",
29
+ "Forty",
30
+ "Fifty",
31
+ "Sixty",
32
+ "Seventy",
33
+ "Eighty",
34
+ "Ninety"
35
+ ];
36
+ function convertThreeDigitEnglish(n) {
37
+ let str = "";
38
+ if (n >= 100) {
39
+ str += EN_ONES[Math.floor(n / 100)] + " Hundred ";
40
+ n %= 100;
41
+ }
42
+ if (n >= 20) {
43
+ const tens = EN_TENS[Math.floor(n / 10)];
44
+ n %= 10;
45
+ if (n > 0) {
46
+ str += `${tens}-${EN_ONES[n]} `;
47
+ n = 0;
48
+ } else {
49
+ str += `${tens} `;
50
+ }
51
+ } else if (n > 0) {
52
+ str += EN_ONES[n] + " ";
53
+ }
54
+ return str.trim();
55
+ }
56
+ function convertIntegerToIndianWordsEn(num) {
57
+ if (num === 0) return "Zero";
58
+ const parts = [];
59
+ const crores = Math.floor(num / 1e7);
60
+ num %= 1e7;
61
+ const lakhs = Math.floor(num / 1e5);
62
+ num %= 1e5;
63
+ const thousands = Math.floor(num / 1e3);
64
+ num %= 1e3;
65
+ const remaining = Math.floor(num);
66
+ if (crores > 0) {
67
+ const croreWords = crores >= 100 ? convertIntegerToIndianWordsEn(crores) : convertThreeDigitEnglish(crores);
68
+ parts.push(`${croreWords} Crore`);
69
+ }
70
+ if (lakhs > 0) {
71
+ parts.push(`${convertThreeDigitEnglish(lakhs)} Lakh`);
72
+ }
73
+ if (thousands > 0) {
74
+ parts.push(`${convertThreeDigitEnglish(thousands)} Thousand`);
75
+ }
76
+ if (remaining > 0) {
77
+ parts.push(convertThreeDigitEnglish(remaining));
78
+ }
79
+ return parts.join(" ").trim();
80
+ }
81
+ var TA_ONES = [
82
+ "",
83
+ "\u0B92\u0BA9\u0BCD\u0BB1\u0BC1",
84
+ "\u0B87\u0BB0\u0BA3\u0BCD\u0B9F\u0BC1",
85
+ "\u0BAE\u0BC2\u0BA9\u0BCD\u0BB1\u0BC1",
86
+ "\u0BA8\u0BBE\u0BA9\u0BCD\u0B95\u0BC1",
87
+ "\u0B90\u0BA8\u0BCD\u0BA4\u0BC1",
88
+ "\u0B86\u0BB1\u0BC1",
89
+ "\u0B8F\u0BB4\u0BC1",
90
+ "\u0B8E\u0B9F\u0BCD\u0B9F\u0BC1",
91
+ "\u0B92\u0BA9\u0BCD\u0BAA\u0BA4\u0BC1",
92
+ "\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1",
93
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BCA\u0BA9\u0BCD\u0BB1\u0BC1",
94
+ "\u0BAA\u0BA9\u0BCD\u0BA9\u0BBF\u0BB0\u0BA3\u0BCD\u0B9F\u0BC1",
95
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BCD\u0BAE\u0BC2\u0BA9\u0BCD\u0BB1\u0BC1",
96
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BBE\u0BA9\u0BCD\u0B95\u0BC1",
97
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BC8\u0BA8\u0BCD\u0BA4\u0BC1",
98
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BBE\u0BB1\u0BC1",
99
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BC7\u0BB4\u0BC1",
100
+ "\u0BAA\u0BA4\u0BBF\u0BA9\u0BC6\u0B9F\u0BCD\u0B9F\u0BC1",
101
+ "\u0BAA\u0BA4\u0BCD\u0BA4\u0BCA\u0BA9\u0BCD\u0BAA\u0BA4\u0BC1"
102
+ ];
103
+ var TA_TENS_PREFIX = [
104
+ "",
105
+ "",
106
+ "\u0B87\u0BB0\u0BC1\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
107
+ "\u0BAE\u0BC1\u0BAA\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
108
+ "\u0BA8\u0BBE\u0BB1\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
109
+ "\u0B90\u0BAE\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
110
+ "\u0B85\u0BB1\u0BC1\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
111
+ "\u0B8E\u0BB4\u0BC1\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
112
+ "\u0B8E\u0BA3\u0BCD\u0BAA\u0BA4\u0BCD\u0BA4\u0BC1 ",
113
+ "\u0BA4\u0BCA\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 "
114
+ ];
115
+ var TA_TENS_EXACT = [
116
+ "",
117
+ "",
118
+ "\u0B87\u0BB0\u0BC1\u0BAA\u0BA4\u0BC1",
119
+ "\u0BAE\u0BC1\u0BAA\u0BCD\u0BAA\u0BA4\u0BC1",
120
+ "\u0BA8\u0BBE\u0BB1\u0BCD\u0BAA\u0BA4\u0BC1",
121
+ "\u0B90\u0BAE\u0BCD\u0BAA\u0BA4\u0BC1",
122
+ "\u0B85\u0BB1\u0BC1\u0BAA\u0BA4\u0BC1",
123
+ "\u0B8E\u0BB4\u0BC1\u0BAA\u0BA4\u0BC1",
124
+ "\u0B8E\u0BA3\u0BCD\u0BAA\u0BA4\u0BC1",
125
+ "\u0BA4\u0BCA\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BC1"
126
+ ];
127
+ var TA_HUNDREDS = [
128
+ "",
129
+ "\u0BA8\u0BC2\u0BB1\u0BC1",
130
+ "\u0B87\u0BB0\u0BC1\u0BA8\u0BC2\u0BB1\u0BC1",
131
+ "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BC1",
132
+ "\u0BA8\u0BBE\u0BA9\u0BC2\u0BB1\u0BC1",
133
+ "\u0B90\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BC1",
134
+ "\u0B85\u0BB1\u0BC1\u0BA8\u0BC2\u0BB1\u0BC1",
135
+ "\u0B8E\u0BB4\u0BC1\u0BA8\u0BC2\u0BB1\u0BC1",
136
+ "\u0B8E\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BC1",
137
+ "\u0BA4\u0BCA\u0BB3\u0BCD\u0BB3\u0BBE\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD"
138
+ ];
139
+ function convertThreeDigitTamil(n) {
140
+ let str = "";
141
+ if (n >= 100) {
142
+ const h = Math.floor(n / 100);
143
+ n %= 100;
144
+ if (n === 0) {
145
+ str += TA_HUNDREDS[h] + " ";
146
+ } else {
147
+ const prefix = ["\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B87\u0BB0\u0BC1\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0BAE\u0BC1\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0BA8\u0BBE\u0BA9\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B90\u0BA8\u0BCD\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B85\u0BB1\u0BC1\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B8E\u0BB4\u0BC1\u0BA8\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0B8E\u0BA3\u0BCD\u0BA3\u0BC2\u0BB1\u0BCD\u0BB1\u0BC1 ", "\u0BA4\u0BCA\u0BB3\u0BCD\u0BB3\u0BBE\u0BAF\u0BBF\u0BB0\u0BA4\u0BCD\u0BA4\u0BC1 "];
148
+ str += prefix[h - 1];
149
+ }
150
+ }
151
+ if (n >= 20) {
152
+ const t = Math.floor(n / 10);
153
+ n %= 10;
154
+ if (n === 0) {
155
+ str += TA_TENS_EXACT[t] + " ";
156
+ } else {
157
+ str += TA_TENS_PREFIX[t];
158
+ }
159
+ }
160
+ if (n > 0) {
161
+ str += TA_ONES[n] + " ";
162
+ }
163
+ return str.trim();
164
+ }
165
+ function convertIntegerToTamilWords(num) {
166
+ if (num === 0) return "\u0BAA\u0BC2\u0B9C\u0BCD\u0B9C\u0BBF\u0BAF\u0BAE\u0BCD";
167
+ const parts = [];
168
+ const crores = Math.floor(num / 1e7);
169
+ num %= 1e7;
170
+ const lakhs = Math.floor(num / 1e5);
171
+ num %= 1e5;
172
+ const thousands = Math.floor(num / 1e3);
173
+ num %= 1e3;
174
+ const remaining = Math.floor(num);
175
+ if (crores > 0) {
176
+ const croreWords = crores >= 100 ? convertIntegerToTamilWords(crores) : convertThreeDigitTamil(crores);
177
+ parts.push(`${croreWords} \u0B95\u0BCB\u0B9F\u0BBF`);
178
+ }
179
+ if (lakhs > 0) {
180
+ parts.push(`${convertThreeDigitTamil(lakhs)} \u0B87\u0BB2\u0B9F\u0BCD\u0B9A\u0BAE\u0BCD`);
181
+ }
182
+ if (thousands > 0) {
183
+ parts.push(`${convertThreeDigitTamil(thousands)} \u0B86\u0BAF\u0BBF\u0BB0\u0BAE\u0BCD`);
184
+ }
185
+ if (remaining > 0) {
186
+ parts.push(convertThreeDigitTamil(remaining));
187
+ }
188
+ return parts.join(" ").trim();
189
+ }
190
+ function numberToIndianWords(amount, options = {}) {
191
+ const {
192
+ currency = true,
193
+ includePaise = true,
194
+ suffixOnly = true,
195
+ language = "en"
196
+ } = options;
197
+ if (isNaN(amount)) {
198
+ return language === "ta" ? "\u0B9A\u0BC6\u0BB2\u0BCD\u0BB2\u0BC1\u0BAA\u0B9F\u0BBF\u0BAF\u0BBE\u0B95\u0BBE\u0BA4 \u0B8E\u0BA3\u0BCD" : "Invalid Number";
199
+ }
200
+ const isNegative = amount < 0;
201
+ const absAmount = Math.abs(amount);
202
+ const integerPart = Math.floor(absAmount);
203
+ const decimalPart = Math.round((absAmount - integerPart) * 100);
204
+ if (language === "ta") {
205
+ let result2 = convertIntegerToTamilWords(integerPart);
206
+ if (currency) {
207
+ result2 += " \u0BB0\u0BC2\u0BAA\u0BBE\u0BAF\u0BCD";
208
+ }
209
+ if (includePaise && decimalPart > 0) {
210
+ const paiseWord = convertThreeDigitTamil(decimalPart);
211
+ result2 += ` ${paiseWord} \u0BAA\u0BC8\u0B9A\u0BBE`;
212
+ }
213
+ if (suffixOnly) {
214
+ result2 += " \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD";
215
+ }
216
+ return (isNegative ? "\u0BAE\u0BC8\u0BA9\u0BB8\u0BCD " : "") + result2.trim();
217
+ }
218
+ let result = convertIntegerToIndianWordsEn(integerPart);
219
+ if (currency) {
220
+ result += integerPart === 1 ? " Rupee" : " Rupees";
221
+ }
222
+ if (includePaise && decimalPart > 0) {
223
+ const paiseWord = convertThreeDigitEnglish(decimalPart);
224
+ result += ` and ${paiseWord} Paise`;
225
+ }
226
+ if (suffixOnly) {
227
+ result += " Only";
228
+ }
229
+ return (isNegative ? "Minus " : "") + result.trim();
230
+ }
231
+ function numberToTamilWords(amount, options = {}) {
232
+ return numberToIndianWords(amount, { ...options, language: "ta" });
233
+ }
234
+ function formatINR(amount, options = {}) {
235
+ const { symbol = true, decimals = 2 } = options;
236
+ const formatted = new Intl.NumberFormat("en-IN", {
237
+ minimumFractionDigits: decimals,
238
+ maximumFractionDigits: decimals
239
+ }).format(amount);
240
+ return symbol ? `\u20B9 ${formatted}` : formatted;
241
+ }
242
+ function calculateGST(baseAmount, gstRatePercent, isInterState = false) {
243
+ const totalTax = Number((baseAmount * gstRatePercent / 100).toFixed(2));
244
+ const totalAmount = Number((baseAmount + totalTax).toFixed(2));
245
+ let cgstAmount = 0;
246
+ let sgstAmount = 0;
247
+ let igstAmount = 0;
248
+ if (isInterState) {
249
+ igstAmount = totalTax;
250
+ } else {
251
+ cgstAmount = Number((totalTax / 2).toFixed(2));
252
+ sgstAmount = Number((totalTax / 2).toFixed(2));
253
+ }
254
+ return {
255
+ baseAmount,
256
+ gstRate: gstRatePercent,
257
+ isInterState,
258
+ cgstAmount,
259
+ sgstAmount,
260
+ igstAmount,
261
+ totalTax,
262
+ totalAmount,
263
+ totalInWords: numberToIndianWords(totalAmount)
264
+ };
265
+ }
266
+ export {
267
+ calculateGST,
268
+ formatINR,
269
+ numberToIndianWords,
270
+ numberToTamilWords
271
+ };
package/package.json CHANGED
@@ -1,6 +1,55 @@
1
1
  {
2
2
  "name": "inr-num-words",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Converts numbers and Indian Rupee (INR) amounts into words (English & Tamil) with Lakhs, Crores, Paise, and Invoice/Cheque formatting.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "prepublishOnly": "npm run build && npm test"
31
+ },
32
+ "keywords": [
33
+ "inr",
34
+ "indian-rupee",
35
+ "number-to-words",
36
+ "numbers-to-words",
37
+ "currency",
38
+ "cheque",
39
+ "invoice",
40
+ "billing",
41
+ "lakh",
42
+ "crore",
43
+ "tamil",
44
+ "finance",
45
+ "typescript"
46
+ ],
47
+ "author": "Pirapaakaran Pirathapan <pirapaakaranpirathapan@gmail.com>",
48
+ "license": "MIT",
49
+ "devDependencies": {
50
+ "@types/node": "^22.13.0",
51
+ "tsup": "^8.3.6",
52
+ "typescript": "^5.7.3",
53
+ "vitest": "^3.0.5"
54
+ }
55
+ }