indycheck 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -255,6 +255,14 @@ export declare function generateGstin(stateCode?: unknown): string;
255
255
  /** Generates a syntactically valid Indian mobile number (10 digits,
256
256
  * first digit 6-9). TEST DATA ONLY — not a real person's number. */
257
257
  export declare function generateMobile(): string;
258
+ /** Generates a syntactically valid state-format vehicle registration
259
+ * number (`DL01AB1234`: state code + district + series + number).
260
+ * TEST DATA ONLY — not a real issued registration number. */
261
+ export declare function generateVehicle(): string;
262
+ /** Generates a syntactically valid Bharat (BH) series vehicle number
263
+ * (`22BH1234AA`: year 21-26, `BH`, number 0001-9999, suffix without
264
+ * `I`/`O`). TEST DATA ONLY — not a real issued registration number. */
265
+ export declare function generateVehicleBharat(): string;
258
266
  /** The Rust `detect` string for a trimmed input (lib.rs order). */
259
267
  export declare function detectType(input: string): string;
260
268
  export declare function detect(input: unknown): ValidationResult<DetectParsed>;
@@ -289,6 +297,8 @@ declare const _default: {
289
297
  generateAadhaar: typeof generateAadhaar;
290
298
  generateGstin: typeof generateGstin;
291
299
  generateMobile: typeof generateMobile;
300
+ generateVehicle: typeof generateVehicle;
301
+ generateVehicleBharat: typeof generateVehicleBharat;
292
302
  defaultOptions: typeof defaultOptions;
293
303
  lenientOptions: typeof lenientOptions;
294
304
  noSpacesHyphensOptions: typeof noSpacesHyphensOptions;
package/dist/index.js CHANGED
@@ -109,6 +109,8 @@ exports.generatePan = generatePan;
109
109
  exports.generateAadhaar = generateAadhaar;
110
110
  exports.generateGstin = generateGstin;
111
111
  exports.generateMobile = generateMobile;
112
+ exports.generateVehicle = generateVehicle;
113
+ exports.generateVehicleBharat = generateVehicleBharat;
112
114
  exports.detectType = detectType;
113
115
  exports.detect = detect;
114
116
  exports.validateMany = validateMany;
@@ -986,6 +988,14 @@ function randomDigit() {
986
988
  function randomDigitRange(low, high) {
987
989
  return String(low + Math.floor(Math.random() * (high - low + 1)));
988
990
  }
991
+ /** A letter excluding `I` and `O` (they look like digits on a plate). */
992
+ function randomLetterNoIO() {
993
+ const letters = "ABCDEFGHJKLMNPQRSTUVWXYZ";
994
+ return letters[Math.floor(Math.random() * letters.length)];
995
+ }
996
+ const VEHICLE_STATE_CODES = [
997
+ "DL", "MH", "UP", "KA", "TN", "GJ", "RJ", "WB", "KL", "PB", "HR", "AP", "TS", "MP", "BR",
998
+ ];
989
999
  /** Generates a syntactically valid PAN for the given entity character
990
1000
  * (`P`, `C`, `H`, `F`, `A`, `T`, `B`, `L`, `J` or `G`).
991
1001
  * An unknown entity character falls back to `P` (Individual).
@@ -1039,6 +1049,28 @@ function generateMobile() {
1039
1049
  mobile += randomDigit();
1040
1050
  return mobile;
1041
1051
  }
1052
+ /** Generates a syntactically valid state-format vehicle registration
1053
+ * number (`DL01AB1234`: state code + district + series + number).
1054
+ * TEST DATA ONLY — not a real issued registration number. */
1055
+ function generateVehicle() {
1056
+ const state = VEHICLE_STATE_CODES[Math.floor(Math.random() * VEHICLE_STATE_CODES.length)];
1057
+ const district = String(1 + Math.floor(Math.random() * 99)).padStart(2, "0");
1058
+ const seriesLength = Math.random() < 0.5 ? 1 : 2;
1059
+ let series = "";
1060
+ for (let i = 0; i < seriesLength; i++)
1061
+ series += randomLetterNoIO();
1062
+ const number = String(1 + Math.floor(Math.random() * 9999)).padStart(4, "0");
1063
+ return `${state}${district}${series}${number}`;
1064
+ }
1065
+ /** Generates a syntactically valid Bharat (BH) series vehicle number
1066
+ * (`22BH1234AA`: year 21-26, `BH`, number 0001-9999, suffix without
1067
+ * `I`/`O`). TEST DATA ONLY — not a real issued registration number. */
1068
+ function generateVehicleBharat() {
1069
+ const year = String(21 + Math.floor(Math.random() * 6)).padStart(2, "0");
1070
+ const number = String(1 + Math.floor(Math.random() * 9999)).padStart(4, "0");
1071
+ const suffix = randomLetterNoIO() + randomLetterNoIO();
1072
+ return `${year}BH${number}${suffix}`;
1073
+ }
1042
1074
  const VALIDATORS = {
1043
1075
  mobile: validateMobile,
1044
1076
  pan: validatePan,
@@ -1299,6 +1331,8 @@ exports.default = {
1299
1331
  generateAadhaar,
1300
1332
  generateGstin,
1301
1333
  generateMobile,
1334
+ generateVehicle,
1335
+ generateVehicleBharat,
1302
1336
  defaultOptions,
1303
1337
  lenientOptions,
1304
1338
  noSpacesHyphensOptions,
@@ -0,0 +1,122 @@
1
+ /**
2
+ * indycheck — optional native (napi-rs) backend.
3
+ *
4
+ * Same public API as the pure-TypeScript mirror in `./index`, but the
5
+ * validation itself runs in the compiled Rust core through the
6
+ * napi-rs addon in `crates/indycheck-napi` instead of the TypeScript
7
+ * re-implementation. The addon is optional: when it is not built (or
8
+ * cannot be loaded) every function below falls back to `./index`
9
+ * silently, so the package works with no native code at all.
10
+ *
11
+ * How it loads: `isNativeAvailable()` tries, in order,
12
+ * 1. `INDYCHECK_NATIVE_PATH` — a path to the addon's `index.js` (or
13
+ * directly to a `.node` file), when the env var is set;
14
+ * 2. `crates/indycheck-napi/index.js` relative to this file (works
15
+ * from both `src/` under vitest and `dist/`);
16
+ * 3. the same path found by walking up from the current working
17
+ * directory to a repo checkout.
18
+ * The `.node` binary itself is never committed to the repo — build it
19
+ * with `npm run build` in `crates/indycheck-napi` (see its README).
20
+ *
21
+ * Shape note: the Rust wrappers return JSON strings (see
22
+ * `crates/indycheck-napi/src/lib.rs`); they are parsed here into the
23
+ * same `{ valid, code, reason_en, reason_hi, parsed }` objects the
24
+ * TypeScript implementation returns. `detect` in Rust returns only
25
+ * the type string ("pan" | "aadhaar" | ... | "unknown"), so the
26
+ * `ValidationResult<DetectParsed>` shape is rebuilt here from the
27
+ * native type + the matching native validator, exactly like
28
+ * `detect` in `./index`. `validateMany` in Rust returns a bare
29
+ * `ValidationResult[]` (one per input, in order); the
30
+ * `input` / `type` / totals wrapper is rebuilt here with the same
31
+ * `VALID` / `SOME_INVALID` codes and reason strings as `./index`.
32
+ * The `*WithOptions` variants have no native equivalent (the Rust
33
+ * core's options live behind different entry points), so they always
34
+ * use the TypeScript implementation.
35
+ *
36
+ * Every function here never throws on bad input, like `./index`.
37
+ */
38
+ import type { AadhaarParsed, CinParsed, DetectParsed, GstinParsed, IfscParsed, LlpinParsed, MobileParsed, PincodeParsed, TanParsed, UpiParsed, ValidateManyParsed, ValidationResult, VehicleParsed, VoterParsed } from "./index";
39
+ import * as tsImpl from "./index";
40
+ import type { PanParsed } from "./index";
41
+ /** `true` when the native addon loaded and can be used. */
42
+ export declare function isNativeAvailable(): boolean;
43
+ /** Which backend the functions below are currently using. */
44
+ export declare function backend(): "native" | "typescript";
45
+ export declare function validatePan(input: unknown): ValidationResult<PanParsed>;
46
+ export declare function validateAadhaar(input: unknown): ValidationResult<AadhaarParsed>;
47
+ export declare function validateGstin(input: unknown): ValidationResult<GstinParsed>;
48
+ export declare function validateIfsc(input: unknown): ValidationResult<IfscParsed>;
49
+ export declare function validateUpi(input: unknown): ValidationResult<UpiParsed>;
50
+ export declare function validateMobile(input: unknown): ValidationResult<MobileParsed>;
51
+ export declare function validatePincode(input: unknown): ValidationResult<PincodeParsed>;
52
+ export declare function validateTan(input: unknown): ValidationResult<TanParsed>;
53
+ export declare function validateCin(input: unknown): ValidationResult<CinParsed>;
54
+ export declare function validateLlpin(input: unknown): ValidationResult<LlpinParsed>;
55
+ export declare function validateVoterId(input: unknown): ValidationResult<VoterParsed>;
56
+ /** Alias for `validateVoterId`: EPIC is the name printed on the card. */
57
+ export declare function validateEpic(input: unknown): ValidationResult<VoterParsed>;
58
+ export declare function validateVehicle(input: unknown): ValidationResult<VehicleParsed>;
59
+ /** Alias for `validateVehicle`. */
60
+ export declare function validateVehicleRegistration(input: unknown): ValidationResult<VehicleParsed>;
61
+ /** The Rust `detect` string for a trimmed input. */
62
+ export declare function detectType(input: string): string;
63
+ export declare function detect(input: unknown): ValidationResult<DetectParsed>;
64
+ export declare function validateMany(inputs: unknown): ValidationResult<ValidateManyParsed>;
65
+ export declare function formatMobile(input: unknown): ValidationResult<MobileParsed>;
66
+ export declare function formatPan(input: unknown): string | null;
67
+ export declare function formatGstin(input: unknown): string | null;
68
+ export declare function maskAadhaar(input: unknown): ValidationResult<AadhaarParsed>;
69
+ export declare function maskPan(input: unknown): string;
70
+ export declare function maskMobile(input: unknown): string;
71
+ export declare function generatePan(entity?: unknown): string;
72
+ export declare function generateAadhaar(): string;
73
+ export declare function generateGstin(stateCode?: unknown): string;
74
+ export declare function generateMobile(): string;
75
+ export declare const validateMobileWithOptions: typeof tsImpl.validateMobileWithOptions;
76
+ export declare const validatePanWithOptions: typeof tsImpl.validatePanWithOptions;
77
+ export declare const validateAadhaarWithOptions: typeof tsImpl.validateAadhaarWithOptions;
78
+ export declare const validateGstinWithOptions: typeof tsImpl.validateGstinWithOptions;
79
+ export declare const formatMobileWithOptions: typeof tsImpl.formatMobileWithOptions;
80
+ export declare const defaultOptions: typeof tsImpl.defaultOptions;
81
+ export declare const lenientOptions: typeof tsImpl.lenientOptions;
82
+ export declare const noSpacesHyphensOptions: typeof tsImpl.noSpacesHyphensOptions;
83
+ declare const _default: {
84
+ backend: typeof backend;
85
+ isNativeAvailable: typeof isNativeAvailable;
86
+ validateMobile: typeof validateMobile;
87
+ validatePan: typeof validatePan;
88
+ validateAadhaar: typeof validateAadhaar;
89
+ validateGstin: typeof validateGstin;
90
+ validateIfsc: typeof validateIfsc;
91
+ validateUpi: typeof validateUpi;
92
+ validatePincode: typeof validatePincode;
93
+ validateTan: typeof validateTan;
94
+ validateCin: typeof validateCin;
95
+ validateLlpin: typeof validateLlpin;
96
+ validateVoterId: typeof validateVoterId;
97
+ validateEpic: typeof validateEpic;
98
+ validateVehicle: typeof validateVehicle;
99
+ validateVehicleRegistration: typeof validateVehicleRegistration;
100
+ validateMobileWithOptions: typeof tsImpl.validateMobileWithOptions;
101
+ validatePanWithOptions: typeof tsImpl.validatePanWithOptions;
102
+ validateAadhaarWithOptions: typeof tsImpl.validateAadhaarWithOptions;
103
+ validateGstinWithOptions: typeof tsImpl.validateGstinWithOptions;
104
+ formatMobile: typeof formatMobile;
105
+ formatMobileWithOptions: typeof tsImpl.formatMobileWithOptions;
106
+ formatPan: typeof formatPan;
107
+ formatGstin: typeof formatGstin;
108
+ maskAadhaar: typeof maskAadhaar;
109
+ maskPan: typeof maskPan;
110
+ maskMobile: typeof maskMobile;
111
+ generatePan: typeof generatePan;
112
+ generateAadhaar: typeof generateAadhaar;
113
+ generateGstin: typeof generateGstin;
114
+ generateMobile: typeof generateMobile;
115
+ defaultOptions: typeof tsImpl.defaultOptions;
116
+ lenientOptions: typeof tsImpl.lenientOptions;
117
+ noSpacesHyphensOptions: typeof tsImpl.noSpacesHyphensOptions;
118
+ detect: typeof detect;
119
+ detectType: typeof detectType;
120
+ validateMany: typeof validateMany;
121
+ };
122
+ export default _default;
package/dist/native.js ADDED
@@ -0,0 +1,518 @@
1
+ "use strict";
2
+ /**
3
+ * indycheck — optional native (napi-rs) backend.
4
+ *
5
+ * Same public API as the pure-TypeScript mirror in `./index`, but the
6
+ * validation itself runs in the compiled Rust core through the
7
+ * napi-rs addon in `crates/indycheck-napi` instead of the TypeScript
8
+ * re-implementation. The addon is optional: when it is not built (or
9
+ * cannot be loaded) every function below falls back to `./index`
10
+ * silently, so the package works with no native code at all.
11
+ *
12
+ * How it loads: `isNativeAvailable()` tries, in order,
13
+ * 1. `INDYCHECK_NATIVE_PATH` — a path to the addon's `index.js` (or
14
+ * directly to a `.node` file), when the env var is set;
15
+ * 2. `crates/indycheck-napi/index.js` relative to this file (works
16
+ * from both `src/` under vitest and `dist/`);
17
+ * 3. the same path found by walking up from the current working
18
+ * directory to a repo checkout.
19
+ * The `.node` binary itself is never committed to the repo — build it
20
+ * with `npm run build` in `crates/indycheck-napi` (see its README).
21
+ *
22
+ * Shape note: the Rust wrappers return JSON strings (see
23
+ * `crates/indycheck-napi/src/lib.rs`); they are parsed here into the
24
+ * same `{ valid, code, reason_en, reason_hi, parsed }` objects the
25
+ * TypeScript implementation returns. `detect` in Rust returns only
26
+ * the type string ("pan" | "aadhaar" | ... | "unknown"), so the
27
+ * `ValidationResult<DetectParsed>` shape is rebuilt here from the
28
+ * native type + the matching native validator, exactly like
29
+ * `detect` in `./index`. `validateMany` in Rust returns a bare
30
+ * `ValidationResult[]` (one per input, in order); the
31
+ * `input` / `type` / totals wrapper is rebuilt here with the same
32
+ * `VALID` / `SOME_INVALID` codes and reason strings as `./index`.
33
+ * The `*WithOptions` variants have no native equivalent (the Rust
34
+ * core's options live behind different entry points), so they always
35
+ * use the TypeScript implementation.
36
+ *
37
+ * Every function here never throws on bad input, like `./index`.
38
+ */
39
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
40
+ if (k2 === undefined) k2 = k;
41
+ var desc = Object.getOwnPropertyDescriptor(m, k);
42
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
43
+ desc = { enumerable: true, get: function() { return m[k]; } };
44
+ }
45
+ Object.defineProperty(o, k2, desc);
46
+ }) : (function(o, m, k, k2) {
47
+ if (k2 === undefined) k2 = k;
48
+ o[k2] = m[k];
49
+ }));
50
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
51
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
52
+ }) : function(o, v) {
53
+ o["default"] = v;
54
+ });
55
+ var __importStar = (this && this.__importStar) || (function () {
56
+ var ownKeys = function(o) {
57
+ ownKeys = Object.getOwnPropertyNames || function (o) {
58
+ var ar = [];
59
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
60
+ return ar;
61
+ };
62
+ return ownKeys(o);
63
+ };
64
+ return function (mod) {
65
+ if (mod && mod.__esModule) return mod;
66
+ var result = {};
67
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
68
+ __setModuleDefault(result, mod);
69
+ return result;
70
+ };
71
+ })();
72
+ Object.defineProperty(exports, "__esModule", { value: true });
73
+ exports.noSpacesHyphensOptions = exports.lenientOptions = exports.defaultOptions = exports.formatMobileWithOptions = exports.validateGstinWithOptions = exports.validateAadhaarWithOptions = exports.validatePanWithOptions = exports.validateMobileWithOptions = void 0;
74
+ exports.isNativeAvailable = isNativeAvailable;
75
+ exports.backend = backend;
76
+ exports.validatePan = validatePan;
77
+ exports.validateAadhaar = validateAadhaar;
78
+ exports.validateGstin = validateGstin;
79
+ exports.validateIfsc = validateIfsc;
80
+ exports.validateUpi = validateUpi;
81
+ exports.validateMobile = validateMobile;
82
+ exports.validatePincode = validatePincode;
83
+ exports.validateTan = validateTan;
84
+ exports.validateCin = validateCin;
85
+ exports.validateLlpin = validateLlpin;
86
+ exports.validateVoterId = validateVoterId;
87
+ exports.validateEpic = validateEpic;
88
+ exports.validateVehicle = validateVehicle;
89
+ exports.validateVehicleRegistration = validateVehicleRegistration;
90
+ exports.detectType = detectType;
91
+ exports.detect = detect;
92
+ exports.validateMany = validateMany;
93
+ exports.formatMobile = formatMobile;
94
+ exports.formatPan = formatPan;
95
+ exports.formatGstin = formatGstin;
96
+ exports.maskAadhaar = maskAadhaar;
97
+ exports.maskPan = maskPan;
98
+ exports.maskMobile = maskMobile;
99
+ exports.generatePan = generatePan;
100
+ exports.generateAadhaar = generateAadhaar;
101
+ exports.generateGstin = generateGstin;
102
+ exports.generateMobile = generateMobile;
103
+ const node_module_1 = require("node:module");
104
+ const node_fs_1 = require("node:fs");
105
+ const node_path_1 = require("node:path");
106
+ const tsImpl = __importStar(require("./index"));
107
+ const nativeRequire = (0, node_module_1.createRequire)((0, node_path_1.join)(process.cwd(), "package.json"));
108
+ function bindingCandidates() {
109
+ const envPath = process.env.INDYCHECK_NATIVE_PATH;
110
+ // An explicit path is authoritative: if it cannot be loaded, the
111
+ // addon is treated as absent (TypeScript fallback) instead of
112
+ // silently loading a different binary.
113
+ if (envPath)
114
+ return [envPath];
115
+ const candidates = [];
116
+ // CommonJS: relative to this file (dist/ or src/ under packages/js).
117
+ if (typeof __dirname !== "undefined") {
118
+ candidates.push((0, node_path_1.join)(__dirname, "..", "..", "..", "crates", "indycheck-napi", "index.js"));
119
+ }
120
+ // Walk up from the working directory to a repo checkout (covers
121
+ // vitest, where __dirname is not defined, and `npm test` from anywhere).
122
+ let dir = process.cwd();
123
+ for (let i = 0; i < 6; i++) {
124
+ candidates.push((0, node_path_1.join)(dir, "crates", "indycheck-napi", "index.js"));
125
+ const parent = (0, node_path_1.dirname)(dir);
126
+ if (parent === dir)
127
+ break;
128
+ dir = parent;
129
+ }
130
+ return [...new Set(candidates)].filter((c) => (0, node_fs_1.existsSync)(c));
131
+ }
132
+ let binding = null;
133
+ let attempted = false;
134
+ function loadBinding() {
135
+ if (attempted)
136
+ return binding;
137
+ attempted = true;
138
+ for (const candidate of bindingCandidates()) {
139
+ try {
140
+ const mod = nativeRequire(candidate);
141
+ if (mod &&
142
+ typeof mod.validatePan === "function" &&
143
+ typeof mod.validateVehicle === "function" &&
144
+ typeof mod.detect === "function" &&
145
+ typeof mod.validateMany === "function") {
146
+ binding = mod;
147
+ break;
148
+ }
149
+ }
150
+ catch {
151
+ // Not built / not loadable here — try the next candidate.
152
+ }
153
+ }
154
+ return binding;
155
+ }
156
+ /** `true` when the native addon loaded and can be used. */
157
+ function isNativeAvailable() {
158
+ return loadBinding() !== null;
159
+ }
160
+ /** Which backend the functions below are currently using. */
161
+ function backend() {
162
+ return loadBinding() !== null ? "native" : "typescript";
163
+ }
164
+ // ---------------------------------------------------------------------------
165
+ // Call helpers
166
+ // ---------------------------------------------------------------------------
167
+ /** Rust `ValidationResult::err` omits `parsed` from the JSON entirely
168
+ * (serde `skip_serializing_if`), while the TS mirror sets it to
169
+ * `null` — normalise so both backends return identical shapes. */
170
+ function normalizeResult(r) {
171
+ if (r.parsed === undefined)
172
+ r.parsed = null;
173
+ return r;
174
+ }
175
+ /** Run a native call that returns a JSON `ValidationResult`; on any
176
+ * failure (missing addon, bad JSON) use the TypeScript fallback. */
177
+ function callJson(fn, fallback) {
178
+ const b = loadBinding();
179
+ if (b === null)
180
+ return fallback();
181
+ try {
182
+ return normalizeResult(JSON.parse(fn(b)));
183
+ }
184
+ catch {
185
+ return fallback();
186
+ }
187
+ }
188
+ /** Run a native call returning a plain value; fall back on any failure. */
189
+ function callPlain(fn, fallback) {
190
+ const b = loadBinding();
191
+ if (b === null)
192
+ return fallback();
193
+ try {
194
+ return fn(b);
195
+ }
196
+ catch {
197
+ return fallback();
198
+ }
199
+ }
200
+ /** Native validator for a `detect` type string, or null for "unknown". */
201
+ function validateByNativeType(b, type, input) {
202
+ let json;
203
+ switch (type) {
204
+ case "pan":
205
+ json = b.validatePan(input);
206
+ break;
207
+ case "aadhaar":
208
+ json = b.validateAadhaar(input);
209
+ break;
210
+ case "gstin":
211
+ json = b.validateGstin(input);
212
+ break;
213
+ case "ifsc":
214
+ json = b.validateIfsc(input);
215
+ break;
216
+ case "upi":
217
+ json = b.validateUpi(input);
218
+ break;
219
+ case "mobile":
220
+ json = b.validateMobile(input);
221
+ break;
222
+ case "pincode":
223
+ json = b.validatePincode(input);
224
+ break;
225
+ case "tan":
226
+ json = b.validateTan(input);
227
+ break;
228
+ case "cin":
229
+ json = b.validateCin(input);
230
+ break;
231
+ case "llpin":
232
+ json = b.validateLlpin(input);
233
+ break;
234
+ case "voter":
235
+ json = b.validateVoterId(input);
236
+ break;
237
+ case "vehicle":
238
+ json = b.validateVehicle(input);
239
+ break;
240
+ default:
241
+ return null;
242
+ }
243
+ return normalizeResult(JSON.parse(json));
244
+ }
245
+ // ---------------------------------------------------------------------------
246
+ // Validators — native when available, TypeScript otherwise
247
+ // ---------------------------------------------------------------------------
248
+ function validatePan(input) {
249
+ if (typeof input !== "string")
250
+ return tsImpl.validatePan(input);
251
+ return callJson((b) => b.validatePan(input), () => tsImpl.validatePan(input));
252
+ }
253
+ function validateAadhaar(input) {
254
+ if (typeof input !== "string")
255
+ return tsImpl.validateAadhaar(input);
256
+ return callJson((b) => b.validateAadhaar(input), () => tsImpl.validateAadhaar(input));
257
+ }
258
+ function validateGstin(input) {
259
+ if (typeof input !== "string")
260
+ return tsImpl.validateGstin(input);
261
+ return callJson((b) => b.validateGstin(input), () => tsImpl.validateGstin(input));
262
+ }
263
+ function validateIfsc(input) {
264
+ if (typeof input !== "string")
265
+ return tsImpl.validateIfsc(input);
266
+ return callJson((b) => b.validateIfsc(input), () => tsImpl.validateIfsc(input));
267
+ }
268
+ function validateUpi(input) {
269
+ if (typeof input !== "string")
270
+ return tsImpl.validateUpi(input);
271
+ return callJson((b) => b.validateUpi(input), () => tsImpl.validateUpi(input));
272
+ }
273
+ function validateMobile(input) {
274
+ if (typeof input !== "string")
275
+ return tsImpl.validateMobile(input);
276
+ return callJson((b) => b.validateMobile(input), () => tsImpl.validateMobile(input));
277
+ }
278
+ function validatePincode(input) {
279
+ if (typeof input !== "string")
280
+ return tsImpl.validatePincode(input);
281
+ return callJson((b) => b.validatePincode(input), () => tsImpl.validatePincode(input));
282
+ }
283
+ function validateTan(input) {
284
+ if (typeof input !== "string")
285
+ return tsImpl.validateTan(input);
286
+ return callJson((b) => b.validateTan(input), () => tsImpl.validateTan(input));
287
+ }
288
+ function validateCin(input) {
289
+ if (typeof input !== "string")
290
+ return tsImpl.validateCin(input);
291
+ return callJson((b) => b.validateCin(input), () => tsImpl.validateCin(input));
292
+ }
293
+ function validateLlpin(input) {
294
+ if (typeof input !== "string")
295
+ return tsImpl.validateLlpin(input);
296
+ return callJson((b) => b.validateLlpin(input), () => tsImpl.validateLlpin(input));
297
+ }
298
+ function validateVoterId(input) {
299
+ if (typeof input !== "string")
300
+ return tsImpl.validateVoterId(input);
301
+ return callJson((b) => b.validateVoterId(input), () => tsImpl.validateVoterId(input));
302
+ }
303
+ /** Alias for `validateVoterId`: EPIC is the name printed on the card. */
304
+ function validateEpic(input) {
305
+ return validateVoterId(input);
306
+ }
307
+ function validateVehicle(input) {
308
+ if (typeof input !== "string")
309
+ return tsImpl.validateVehicle(input);
310
+ return callJson((b) => b.validateVehicle(input), () => tsImpl.validateVehicle(input));
311
+ }
312
+ /** Alias for `validateVehicle`. */
313
+ function validateVehicleRegistration(input) {
314
+ return validateVehicle(input);
315
+ }
316
+ // ---------------------------------------------------------------------------
317
+ // detect / validateMany — shapes rebuilt from the native primitives
318
+ // ---------------------------------------------------------------------------
319
+ /** The Rust `detect` string for a trimmed input. */
320
+ function detectType(input) {
321
+ const b = loadBinding();
322
+ if (b === null)
323
+ return tsImpl.detectType(input);
324
+ try {
325
+ return b.detect(input);
326
+ }
327
+ catch {
328
+ return tsImpl.detectType(input);
329
+ }
330
+ }
331
+ function detect(input) {
332
+ if (typeof input !== "string")
333
+ return tsImpl.detect(input);
334
+ const b = loadBinding();
335
+ if (b === null)
336
+ return tsImpl.detect(input);
337
+ try {
338
+ const type = b.detect(input);
339
+ const trimmed = input.trim();
340
+ if (type === "unknown") {
341
+ return {
342
+ valid: false,
343
+ code: "UNKNOWN_TYPE",
344
+ reason_en: "Could not detect the type of this input",
345
+ reason_hi: "Is input ka type pehchana nahi ja saka",
346
+ parsed: { type: "unknown", value: trimmed, result: null },
347
+ };
348
+ }
349
+ const result = validateByNativeType(b, type, input);
350
+ if (result === null)
351
+ return tsImpl.detect(input);
352
+ return {
353
+ valid: result.valid,
354
+ code: result.code,
355
+ reason_en: result.reason_en,
356
+ reason_hi: result.reason_hi,
357
+ parsed: { type, value: trimmed, result },
358
+ };
359
+ }
360
+ catch {
361
+ return tsImpl.detect(input);
362
+ }
363
+ }
364
+ function validateMany(inputs) {
365
+ if (!Array.isArray(inputs) || inputs.length === 0) {
366
+ return tsImpl.validateMany(inputs);
367
+ }
368
+ if (!inputs.every((item) => typeof item === "string")) {
369
+ // Typed `{ value, type }` entries and non-strings are a
370
+ // TypeScript-wrapper feature — the native batch takes strings only.
371
+ return tsImpl.validateMany(inputs);
372
+ }
373
+ const b = loadBinding();
374
+ if (b === null)
375
+ return tsImpl.validateMany(inputs);
376
+ try {
377
+ const results = JSON.parse(b.validateMany(inputs));
378
+ const items = inputs.map((item, i) => {
379
+ const result = normalizeResult(results[i]);
380
+ const type = b.detect(item);
381
+ return {
382
+ input: item,
383
+ type: type === "unknown" ? null : type,
384
+ valid: result.valid,
385
+ code: result.code,
386
+ reason_en: result.reason_en,
387
+ reason_hi: result.reason_hi,
388
+ parsed: result.parsed,
389
+ };
390
+ });
391
+ const validCount = items.filter((r) => r.valid).length;
392
+ const invalidCount = items.length - validCount;
393
+ const parsed = {
394
+ results: items,
395
+ total: items.length,
396
+ validCount,
397
+ invalidCount,
398
+ };
399
+ if (invalidCount === 0) {
400
+ return {
401
+ valid: true,
402
+ code: "VALID",
403
+ reason_en: "All inputs are valid.",
404
+ reason_hi: "Saare input sahi hain.",
405
+ parsed,
406
+ };
407
+ }
408
+ return {
409
+ valid: false,
410
+ code: "SOME_INVALID",
411
+ reason_en: "Some inputs are invalid.",
412
+ reason_hi: "Kuch input galat hain.",
413
+ parsed,
414
+ };
415
+ }
416
+ catch {
417
+ return tsImpl.validateMany(inputs);
418
+ }
419
+ }
420
+ // ---------------------------------------------------------------------------
421
+ // Format / mask — same contracts as ./index
422
+ // ---------------------------------------------------------------------------
423
+ function formatMobile(input) {
424
+ // Same contract as validateMobile (see ./index).
425
+ return validateMobile(input);
426
+ }
427
+ function formatPan(input) {
428
+ if (typeof input !== "string")
429
+ return tsImpl.formatPan(input);
430
+ return callPlain((b) => b.formatPan(input), () => tsImpl.formatPan(input));
431
+ }
432
+ function formatGstin(input) {
433
+ if (typeof input !== "string")
434
+ return tsImpl.formatGstin(input);
435
+ return callPlain((b) => b.formatGstin(input), () => tsImpl.formatGstin(input));
436
+ }
437
+ function maskAadhaar(input) {
438
+ // Same contract as validateAadhaar (see ./index) — NOT the Rust
439
+ // `mask_aadhaar` string function, which masks any 12-digit string.
440
+ return validateAadhaar(input);
441
+ }
442
+ function maskPan(input) {
443
+ if (typeof input !== "string")
444
+ return tsImpl.maskPan(input);
445
+ return callPlain((b) => b.maskPan(input), () => tsImpl.maskPan(input));
446
+ }
447
+ function maskMobile(input) {
448
+ if (typeof input !== "string")
449
+ return tsImpl.maskMobile(input);
450
+ return callPlain((b) => b.maskMobile(input), () => tsImpl.maskMobile(input));
451
+ }
452
+ // ---------------------------------------------------------------------------
453
+ // Mock test-data generators — TEST DATA ONLY, never real issued IDs
454
+ // ---------------------------------------------------------------------------
455
+ function generatePan(entity) {
456
+ const code = typeof entity === "string" && entity.length > 0 ? entity : "P";
457
+ return callPlain((b) => b.generatePan(code), () => tsImpl.generatePan(entity));
458
+ }
459
+ function generateAadhaar() {
460
+ return callPlain((b) => b.generateAadhaar(), () => tsImpl.generateAadhaar());
461
+ }
462
+ function generateGstin(stateCode) {
463
+ const code = typeof stateCode === "string" ? stateCode : "18";
464
+ return callPlain((b) => b.generateGstin(code), () => tsImpl.generateGstin(stateCode));
465
+ }
466
+ function generateMobile() {
467
+ return callPlain((b) => b.generateMobile(), () => tsImpl.generateMobile());
468
+ }
469
+ // ---------------------------------------------------------------------------
470
+ // Options variants — no native equivalent; always TypeScript
471
+ // ---------------------------------------------------------------------------
472
+ exports.validateMobileWithOptions = tsImpl.validateMobileWithOptions;
473
+ exports.validatePanWithOptions = tsImpl.validatePanWithOptions;
474
+ exports.validateAadhaarWithOptions = tsImpl.validateAadhaarWithOptions;
475
+ exports.validateGstinWithOptions = tsImpl.validateGstinWithOptions;
476
+ exports.formatMobileWithOptions = tsImpl.formatMobileWithOptions;
477
+ exports.defaultOptions = tsImpl.defaultOptions;
478
+ exports.lenientOptions = tsImpl.lenientOptions;
479
+ exports.noSpacesHyphensOptions = tsImpl.noSpacesHyphensOptions;
480
+ exports.default = {
481
+ backend,
482
+ isNativeAvailable,
483
+ validateMobile,
484
+ validatePan,
485
+ validateAadhaar,
486
+ validateGstin,
487
+ validateIfsc,
488
+ validateUpi,
489
+ validatePincode,
490
+ validateTan,
491
+ validateCin,
492
+ validateLlpin,
493
+ validateVoterId,
494
+ validateEpic,
495
+ validateVehicle,
496
+ validateVehicleRegistration,
497
+ validateMobileWithOptions: exports.validateMobileWithOptions,
498
+ validatePanWithOptions: exports.validatePanWithOptions,
499
+ validateAadhaarWithOptions: exports.validateAadhaarWithOptions,
500
+ validateGstinWithOptions: exports.validateGstinWithOptions,
501
+ formatMobile,
502
+ formatMobileWithOptions: exports.formatMobileWithOptions,
503
+ formatPan,
504
+ formatGstin,
505
+ maskAadhaar,
506
+ maskPan,
507
+ maskMobile,
508
+ generatePan,
509
+ generateAadhaar,
510
+ generateGstin,
511
+ generateMobile,
512
+ defaultOptions: exports.defaultOptions,
513
+ lenientOptions: exports.lenientOptions,
514
+ noSpacesHyphensOptions: exports.noSpacesHyphensOptions,
515
+ detect,
516
+ detectType,
517
+ validateMany,
518
+ };
package/package.json CHANGED
@@ -31,11 +31,16 @@
31
31
  "optional": true
32
32
  }
33
33
  },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/dusmamud/indycheck.git"
37
+ },
34
38
  "scripts": {
35
39
  "build": "tsc -p tsconfig.build.json",
40
+ "native:build": "npm --prefix ../../crates/indycheck-napi run build",
36
41
  "test": "vitest run",
37
42
  "typecheck": "tsc --noEmit"
38
43
  },
39
44
  "types": "dist/index.d.ts",
40
- "version": "0.2.0"
45
+ "version": "0.2.2"
41
46
  }