pakdatakit-faker 0.0.0-stage → 0.1.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 PakDataKit Contributors
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,199 @@
1
- # Temporary Holding Version
1
+ # pakdatakit-faker
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
+ Seeded mock data for Pakistan: **CNICs**, **mobile numbers**, **landlines and UANs**, **IBANs**, **NTN/STRN**, **names**, **addresses**, **companies**, **Raast QR codes**, and coherent **personas** and **businesses**. Every value is checked against [pakdatakit](https://github.com/chmuzamil/pakdatakit), the validator library it is built on.
4
+
5
+ - Valid by construction: CNICs pass `validateCNIC`, mobile numbers pass `validatePhone`, IBANs pass the mod-97 checksum, addresses are read back by `parseAddress` with the same city and province
6
+ - Coherent personas: the CNIC's first digit matches the province, its last digit matches the gender, the landline uses the city's area code, the postal code belongs to the city
7
+ - Reproducible: the same seed gives the same data on every platform and JavaScript engine
8
+ - Works with [`@faker-js/faker`](https://fakerjs.dev): plug in its random source so one seed drives both
9
+ - Uses pakdatakit's own datasets (cities, postal codes, banks, mobile prefixes, area codes), bundled at build time
10
+ - ESM and CommonJS, TypeScript types, no dependencies besides `pakdatakit`
11
+
12
+ > [!WARNING]
13
+ > **Read the [Safety](#safety) section before you use this anywhere near real systems.** Generated CNICs, mobile numbers and IBANs are structurally valid and may belong to real people.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install --save-dev pakdatakit-faker
19
+ ```
20
+
21
+ ## Quick start
22
+
23
+ ```ts
24
+ import { createFaker } from 'pakdatakit-faker';
25
+
26
+ const f = createFaker({ seed: 42 });
27
+
28
+ f.cnic(); // '68707-6932604-0'
29
+ f.phone(); // '03095592120'
30
+ f.iban(); // 'PK44MEZN5165216300839683'
31
+ f.name(); // 'Rehana Tanoli'
32
+ f.address(); // '113-B, Mohallah Bilal Ganj, Swat 19200'
33
+
34
+ f.person();
35
+ // {
36
+ // name: 'Marvi Raisani', firstName: 'Marvi', lastName: 'Raisani',
37
+ // gender: 'female', cnic: '16221-1058327-4', dateOfBirth: '1994-12-10',
38
+ // phone: '03432507443', email: 'marviraisani784@example.org',
39
+ // city: 'Lakki Marwat', province: 'Khyber Pakhtunkhwa', district: 'Lakki Marwat',
40
+ // address: 'House # 383, Street # 3, Civil Lines, Lakki Marwat 28420',
41
+ // postalCode: '28420', landline: '0969-357350',
42
+ // iban: 'PK83ASCM3772893706128459', bank: 'Askari Bank Limited',
43
+ // ntn: '16221-1058327-4'
44
+ // }
45
+ ```
46
+
47
+ (The example values above come from `seed: 42` with `now: new Date('2026-06-15T12:00:00Z')`.)
48
+
49
+ For quick scripts there is also a shared default instance with a random seed, and every generator is exported on its own, bound to it:
50
+
51
+ ```ts
52
+ import { cnic, person, seed, many } from 'pakdatakit-faker';
53
+
54
+ seed('fixtures-v1'); // optional: make the default instance reproducible
55
+ const users = many(50, () => person());
56
+ ```
57
+
58
+ ## Generators
59
+
60
+ All options are optional.
61
+
62
+ ### Identity
63
+
64
+ | Generator | Returns | Options |
65
+ | ----------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
66
+ | `cnic(opts)` | `'35202-1234567-1'` | `province` (name or `KP`/`ICT`/`GB`/`AJK`), `gender`, `formatted` (default `true`; `false` gives 13 digits), `provinceCode` (force the first digit 1-8) |
67
+ | `name(opts)` | `'Ayesha Khattak'` | `gender` |
68
+ | `firstName(opts)` | `'Bilal'` | `gender` |
69
+ | `lastName()` | `'Soomro'` | |
70
+ | `gender()` | `'male' \| 'female'` | |
71
+ | `dob(opts)` | `Date` (UTC midnight) | `minAge` (18), `maxAge` (65) |
72
+
73
+ The first CNIC digit is the province of registration: 1 Khyber Pakhtunkhwa, 3 Punjab, 4 Sindh, 5 Balochistan, 6 Islamabad, 7 Gilgit-Baltistan. By default codes are weighted roughly by population. Code 2 (former FATA) and code 8 (Azad Jammu and Kashmir, widely reported but not in FBR's list) are only produced when you ask: `cnic({ province: 'AJK' })` or `cnic({ provinceCode: 2 })`. The last digit is odd for men and even for women, so `getCNICInfo` always reads back the gender you asked for.
74
+
75
+ Names come from lists written for this package: about 120 male and 120 female given names and over 100 family names common among Punjabi, Sindhi, Pashtun, Baloch, Urdu-speaking, Kashmiri and Saraiki families, in Latin script.
76
+
77
+ ### Phone numbers
78
+
79
+ | Generator | Returns | Options |
80
+ | ---------------- | ------------------- | --------------------------------------------------------------------------- |
81
+ | `phone(opts)` | `'03001234567'` | `network` (`Jazz`, `Zong`, `Ufone`, `Telenor`, `SCO`), `format`, `dialable` |
82
+ | `landline(opts)` | `'042-35761234'` | `city` |
83
+ | `uan(opts)` | `'021-111-482-907'` | `city` |
84
+
85
+ `format` is `'local'` (`03001234567`, default), `'international'` (`+92 300 1234567`) or `'e164'` (`+923001234567`). Prefixes come from pakdatakit's `networks.json`, so `getNetwork` returns the network you asked for.
86
+
87
+ `landline` and `uan` use the area codes in `area-codes.json`; `analyzeNumber` reports the right type and lists the city. They throw a `RangeError` for a city with no known area code.
88
+
89
+ `phone({ dialable: false })` returns a number on an **unallocated** `036X` prefix, such as `03641234567`. It has the right shape for UI demos and screenshots, but cannot reach anyone, and it **fails `validatePhone` by design**.
90
+
91
+ ### Banking and tax
92
+
93
+ | Generator | Returns | Options |
94
+ | ------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
95
+ | `iban(opts)` | `'PK36SCBL0000001123456702'` | `bank` (4-letter code), `type` (`commercial`, `islamic`, `microfinance`, `digital`, `emi`, `foreign`, `specialized`), `formatted` (groups of 4) |
96
+ | `ibanDetails(opts)` | `{ iban, bankCode, bank, bankType }` | as `iban` |
97
+ | `ntn(opts)` | `'1234567-8'` | `type` (`business` default, or `individual` = a CNIC), `checkDigit` (default `true`), `cnic` (CNIC options for individuals) |
98
+ | `strn()` | `'3277876153826'` | |
99
+ | `amount(opts)` | `25000` | `min` (100), `max` (100,000), `decimals` (0) |
100
+ | `raastQr(opts)` | Raast P2P QR payload | `iban` (random if omitted), `amount`, `expiresIn` (default `'1h'` with an amount) |
101
+
102
+ Random IBANs only use banks that still exist: codes of merged banks (`mergedInto`), older alias codes (`aliasOf`) and the State Bank itself are skipped. Name any code explicitly, e.g. `iban({ bank: 'NIBP' })`, to get one anyway. `getBankFromIBAN` returns the bank of the generated code. SadaPay IBANs follow SadaPay's layout: `SADA` + `000000` + a 10-digit mobile number. `raastQr` uses pakdatakit's `createRaastP2PQr`, so `validateRaastQr` accepts the result.
103
+
104
+ ### Places and contact details
105
+
106
+ | Generator | Returns | Options |
107
+ | -------------------- | ---------------------------------------------------- | -------------------------------------- |
108
+ | `city(opts)` | `'Sialkot'` | `province` |
109
+ | `address(opts)` | `'House # 12, Street # 4, Johar Town, Lahore 54000'` | `city`, `province`, `includeProvince` |
110
+ | `addressParts(opts)` | `{ street, area, city, province, postalCode, full }` | as `address` |
111
+ | `company(opts)` | `'Indus Textiles (Pvt) Ltd'`, `'Memon Traders'` | `city` |
112
+ | `email(opts)` | `'ayesha.khattak@example.org'` | `name`, `domain` |
113
+ | `date(opts)` | `Date` | `from` (a year before now), `to` (now) |
114
+
115
+ Addresses use realistic patterns (house and street numbers, blocks, Islamabad sectors such as `Sector F-7/2`, mohallahs, and neighbourhoods from pakdatakit's postal data). `parseAddress` reads every generated address back with the same city and province. The postal code is the city's code from `postal-codes.json` (or the area's own code, e.g. Clifton, Karachi 75600); cities with no postal data get none.
116
+
117
+ Emails only use the RFC 2606 reserved domains `example.com`, `example.org` and `example.net` (exported as `RESERVED_EMAIL_DOMAINS`). Any other domain throws.
118
+
119
+ ### Personas
120
+
121
+ `person(opts)` returns a coherent, fictional person:
122
+
123
+ | Field | |
124
+ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------ |
125
+ | `name`, `firstName`, `lastName`, `gender` | |
126
+ | `cnic` | first digit matches `province`, last digit matches `gender` |
127
+ | `dateOfBirth` | `YYYY-MM-DD`, age between `minAge` and `maxAge` |
128
+ | `phone`, `email` | email built from the name |
129
+ | `city`, `province`, `district?` | `district` when a district of the same name exists |
130
+ | `address`, `postalCode` | |
131
+ | `landline` | city's area code when known, otherwise another area code in the same province, `null` if there is none |
132
+ | `iban`, `bank` | |
133
+ | `ntn` | the CNIC, as for every individual taxpayer |
134
+
135
+ Options: `gender`, `province`, `city`, `minAge`, `maxAge`, `bank`, `phone` (phone options such as `network` or `dialable: false`). Without `province` or `city`, people live anywhere except Azad Jammu and Kashmir, because its CNIC code (8) is unverified; pass `province: 'AJK'` to include it.
136
+
137
+ `business(opts)` returns `{ name, ntn, strn, city, province, address, postalCode, phone, landline, uan, iban, bank }`, with a business NTN and a UAN on the city's area code when UANs exist there (`null` otherwise). Options: `city`, `province`, `bank`.
138
+
139
+ ### Helpers
140
+
141
+ `int(min, max)` (inclusive), `float(min, max)`, `bool(probability)`, `pick(array)`, `digits(length)`, `random()` and `many(count, fn)` use the same random source as the generators.
142
+
143
+ ## Seeding
144
+
145
+ ```ts
146
+ const a = createFaker({ seed: 'checkout-tests' });
147
+ const b = createFaker({ seed: 'checkout-tests' });
148
+ a.person(); // deep-equals b.person()
149
+ ```
150
+
151
+ - Seeds can be numbers or strings (`42` and `'42'` are the same seed).
152
+ - The generator is [sfc32](https://pracrand.sourceforge.net/RNG_engines.txt) seeded through the cyrb128 string hash. It uses only 32-bit integer arithmetic, so sequences are identical in Node, browsers, Deno and Bun.
153
+ - `f.seed(value)` restarts an instance; `seed(value)` restarts the default instance.
154
+ - Ages and default dates are relative to "now". Pass `now` for fully reproducible dates: `createFaker({ seed: 1, now: new Date('2026-01-01') })`.
155
+ - `seededRandom(seed)` is exported if you need the raw generator.
156
+ - Output for a given seed can change between minor versions when datasets or generators improve. Pin the version if you snapshot generated data.
157
+
158
+ ## Using it with @faker-js/faker
159
+
160
+ Pass any function that returns numbers in `[0, 1)` as `random`. To drive both libraries from one seed, hand pakdatakit-faker the random source of `@faker-js/faker`:
161
+
162
+ ```ts
163
+ import { faker } from '@faker-js/faker';
164
+ import { createFaker } from 'pakdatakit-faker';
165
+
166
+ faker.seed(123);
167
+ const pk = createFaker({ random: () => faker.number.float() });
168
+
169
+ const user = {
170
+ id: faker.string.uuid(),
171
+ avatar: faker.image.avatar(),
172
+ ...pk.person(),
173
+ };
174
+ ```
175
+
176
+ `faker.number.float()` returns a number in `[0, 1)` by default. `seed` and `random` cannot be combined; seed `@faker-js/faker` instead. pakdatakit-faker does not depend on `@faker-js/faker`.
177
+
178
+ ## Safety
179
+
180
+ **Pakistan has no reserved test ranges for CNICs, mobile numbers or bank accounts.** Values from this package are structurally valid, so any of them may coincide with a real person's CNIC, a real subscriber's phone number or a real bank account.
181
+
182
+ - **Never** call, SMS or WhatsApp a generated number, and never let a system that sends messages (OTP, notifications, marketing) run on generated data. Use `phone({ dialable: false })` for demos and screenshots: it gives an unallocated `036X` number that cannot reach anyone (and fails `validatePhone`).
183
+ - **Never** use generated IBANs with real banks, Raast, or payment providers, including their sandbox environments when they are wired to real rails. Generated Raast QR codes are for testing scanners and parsers only.
184
+ - **Never** submit generated CNICs or NTNs to NADRA, FBR or any other government or third-party service.
185
+ - Keep generated data in test, staging and demo systems. Do not mix it with production data, where it could be mistaken for real records.
186
+ - Emails only use RFC 2606 domains (`example.com`, `example.org`, `example.net`), which never deliver mail.
187
+
188
+ Generated names, addresses and personas are random combinations and do not describe real people; any resemblance is coincidental.
189
+
190
+ ## Related
191
+
192
+ - [pakdatakit](https://github.com/chmuzamil/pakdatakit): validators, formatters and datasets for Pakistani data (CNIC, phone, IBAN, postal codes, address parsing, Raast QR and more)
193
+ - [pakdatakit-react](https://github.com/chmuzamil/pakdatakit/tree/main/react): React inputs that format as you type
194
+ - [Data sources](https://github.com/chmuzamil/pakdatakit/blob/main/DATA.md) for the datasets
195
+ - [Issues](https://github.com/chmuzamil/pakdatakit/issues)
196
+
197
+ ## License
198
+
199
+ MIT