@code-plate/iran-cities 1.0.0 → 1.0.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/README.fa.md ADDED
@@ -0,0 +1,259 @@
1
+ [English](./README.md) | فارسی
2
+
3
+ # @code-plate/iran-cities
4
+
5
+ لیست کامل و آماده‌ی **استان‌ها و شهرهای ایران** (فارسی + انگلیسی)، بسته‌بندی‌شده به شکل یک کتابخانه‌ی سبک، بدون هیچ وابستگی اجباری، که در **هر پروژه‌ی جاوااسکریپتی/تایپ‌اسکریپتی** قابل استفاده است:
6
+
7
+ - ✅ React / Next.js (App Router و Pages Router)
8
+ - ✅ Vue 2 / Vue 3
9
+ - ✅ Angular
10
+ - ✅ Svelte
11
+ - ✅ Node.js / Express (بک‌اند خالص)
12
+ - ✅ Vanilla JS (مرورگر یا هر باندلر دیگر)
13
+
14
+ هسته‌ی اصلی پکیج **هیچ وابستگی‌ای** ندارد (zero-dependency) و هم به‌صورت **CJS** و هم **ESM** ارائه می‌شود. یک ساب‌پس اختیاری (`@code-plate/iran-cities/react`) هم برای کسانی که در React کار می‌کنند وجود دارد که چند هوک آماده می‌دهد؛ اگر پروژه‌تان React نیست، هرگز این فایل import نمی‌شود و React اصلاً لازم نیست نصب شود.
15
+
16
+ ## نصب
17
+
18
+ ```bash
19
+ npm install @code-plate/iran-cities
20
+ # یا
21
+ yarn add @code-plate/iran-cities
22
+ # یا
23
+ pnpm add @code-plate/iran-cities
24
+ ```
25
+
26
+ ## داده‌ها
27
+
28
+ - `۳۱` استان
29
+ - `۱۲۵۳` شهر
30
+ - هر رکورد شامل `en` (شناسه لاتین kebab-case، مثل `tehran`) و `fa` (نام فارسی، مثل `تهران`) است.
31
+
32
+ ---
33
+
34
+ ## استفاده در جاوااسکریپت / تایپ‌اسکریپت خالص (و Node.js/Express)
35
+
36
+ ```ts
37
+ import {
38
+ getProvinces,
39
+ getProvincesList,
40
+ getProvince,
41
+ getCities,
42
+ getCity,
43
+ getAllCities,
44
+ getProvinceOfCity,
45
+ searchProvinces,
46
+ searchCities,
47
+ getStats,
48
+ } from '@code-plate/iran-cities';
49
+
50
+ // همه‌ی استان‌ها به همراه شهرهایشان
51
+ getProvinces();
52
+ // [{ en: 'alborz', fa: 'البرز', cities: [{ en: 'karaj', fa: 'کرج' }, ...] }, ...]
53
+
54
+ // فقط لیست استان‌ها (بدون شهر) - برای Select/Dropdown
55
+ getProvincesList();
56
+ // [{ en: 'alborz', fa: 'البرز' }, { en: 'ardabil', fa: 'اردبیل' }, ...]
57
+
58
+ // گرفتن یک استان با نام انگلیسی یا فارسی
59
+ getProvince('tehran');
60
+ getProvince('تهران'); // همین نتیجه را می‌دهد
61
+
62
+ // شهرهای یک استان خاص
63
+ getCities('fars'); // بر اساس شناسه انگلیسی
64
+ getCities('فارس'); // یا بر اساس نام فارسی، هر دو یکسان کار می‌کنند
65
+
66
+ // پیدا کردن یک شهر مشخص (در کل کشور یا محدود به یک استان)
67
+ getCity('shiraz');
68
+ getCity('شیراز', 'fars'); // محدود به استان فارس
69
+
70
+ // لیست مسطح (flat) همه‌ی شهرهای کشور همراه با استان مربوطه
71
+ getAllCities();
72
+ // [{ en: 'karaj', fa: 'کرج', provinceEn: 'alborz', provinceFa: 'البرز' }, ...]
73
+
74
+ // پیدا کردن استانِ یک شهر
75
+ getProvinceOfCity('اصفهان'); // => { en: 'isfahan', fa: 'اصفهان', cities: [...] }
76
+
77
+ // جستجوی زنده (autocomplete) در استان‌ها یا شهرها
78
+ searchProvinces('خراسان'); // هر سه استان خراسان را برمی‌گرداند
79
+ searchCities('شهر', { limit: 10 }); // ۱۰ نتیجه‌ی اول شامل «شهر»
80
+ searchCities('mashhad', { locale: 'en' }); // جستجو فقط در نام انگلیسی
81
+
82
+ // آمار کلی
83
+ getStats(); // { provinceCount: 31, cityCount: 1253 }
84
+ ```
85
+
86
+ ### نکته‌ی مهم درباره‌ی جستجو
87
+ تابع‌های `getProvince`, `getCities`, `getCity` و `getProvinceOfCity` به‌صورت **نرمال‌شده** مقایسه می‌کنند؛ یعنی تفاوت «ی» فارسی/«ي» عربی، «ک»/«ك»، نیم‌فاصله، فاصله و خط‌تیره را نادیده می‌گیرند. پس `getCity('كرج')` و `getCity('کرج')` هر دو کار می‌کنند.
88
+
89
+ ---
90
+
91
+ ## استفاده در Node.js / Express (بک‌اند)
92
+
93
+ ```js
94
+ const express = require('express');
95
+ const { getProvincesList, getCities, searchCities } = require('@code-plate/iran-cities');
96
+
97
+ const app = express();
98
+
99
+ app.get('/api/provinces', (req, res) => {
100
+ res.json(getProvincesList());
101
+ });
102
+
103
+ app.get('/api/cities/:province', (req, res) => {
104
+ res.json(getCities(req.params.province));
105
+ });
106
+
107
+ app.get('/api/cities/search', (req, res) => {
108
+ res.json(searchCities(req.query.q ?? '', { limit: 20 }));
109
+ });
110
+ ```
111
+
112
+ ---
113
+
114
+ ## استفاده در React / Next.js
115
+
116
+ برای React یک ساب‌پس اختیاری وجود دارد که چند هوک آماده ارائه می‌دهد:
117
+
118
+ ```tsx
119
+ import { useProvinces, useCities, useProvinceCitySelect, useCitySearch } from '@code-plate/iran-cities/react';
120
+
121
+ function AddressForm() {
122
+ const { provinces, cities, province, setProvince, city, setCity } = useProvinceCitySelect();
123
+
124
+ return (
125
+ <>
126
+ <select value={province} onChange={(e) => setProvince(e.target.value)}>
127
+ <option value="">انتخاب استان</option>
128
+ {provinces.map((p) => (
129
+ <option key={p.en} value={p.en}>{p.fa}</option>
130
+ ))}
131
+ </select>
132
+
133
+ <select value={city} onChange={(e) => setCity(e.target.value)} disabled={!province}>
134
+ <option value="">انتخاب شهر</option>
135
+ {cities.map((c) => (
136
+ <option key={c.en} value={c.en}>{c.fa}</option>
137
+ ))}
138
+ </select>
139
+ </>
140
+ );
141
+ }
142
+ ```
143
+
144
+ جستجوی زنده‌ی شهر (autocomplete):
145
+
146
+ ```tsx
147
+ import { useCitySearch } from '@code-plate/iran-cities/react';
148
+
149
+ function CityAutocomplete() {
150
+ const { query, setQuery, results } = useCitySearch('', { limit: 8 });
151
+
152
+ return (
153
+ <div>
154
+ <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="نام شهر..." />
155
+ <ul>
156
+ {results.map((c) => (
157
+ <li key={`${c.provinceEn}-${c.en}`}>{c.fa} ({c.provinceFa})</li>
158
+ ))}
159
+ </ul>
160
+ </div>
161
+ );
162
+ }
163
+ ```
164
+
165
+ هوک‌های در دسترس در ساب‌پس `react`:
166
+
167
+ | هوک | کاربرد |
168
+ |---|---|
169
+ | `useProvinces()` | لیست استان‌ها |
170
+ | `useCities(provinceQuery)` | شهرهای یک استان، وابسته به تغییر پارامتر |
171
+ | `useProvinceCitySelect()` | state کامل یک فرم استان→شهر (با ریست خودکار شهر هنگام تغییر استان) |
172
+ | `useCitySearch(initialQuery?, options?)` | state جستجوی زنده‌ی شهر |
173
+ | `useProvinceSearch(initialQuery?, options?)` | state جستجوی زنده‌ی استان |
174
+
175
+ > اگر پروژه‌تان Vue، Angular یا هر چیز دیگری است، فقط از مسیر اصلی (`@code-plate/iran-cities`) استفاده کنید و توابع خام (`getProvinces`, `getCities`, ...) را داخل computed/signal/observable خودتان قرار دهید — نیازی به هیچ ابزار اضافه‌ای نیست.
176
+
177
+ ---
178
+
179
+ ## استفاده در Vue 3 (نمونه)
180
+
181
+ ```vue
182
+ <script setup>
183
+ import { ref, computed } from 'vue';
184
+ import { getProvincesList, getCities } from '@code-plate/iran-cities';
185
+
186
+ const provinces = getProvincesList();
187
+ const selectedProvince = ref('');
188
+ const cities = computed(() => getCities(selectedProvince.value));
189
+ </script>
190
+
191
+ <template>
192
+ <select v-model="selectedProvince">
193
+ <option v-for="p in provinces" :key="p.en" :value="p.en">{{ p.fa }}</option>
194
+ </select>
195
+ <select :disabled="!selectedProvince">
196
+ <option v-for="c in cities" :key="c.en" :value="c.en">{{ c.fa }}</option>
197
+ </select>
198
+ </template>
199
+ ```
200
+
201
+ ## استفاده در Angular (نمونه سرویس)
202
+
203
+ ```ts
204
+ import { Injectable } from '@angular/core';
205
+ import { getProvincesList, getCities, type City } from '@code-plate/iran-cities';
206
+
207
+ @Injectable({ providedIn: 'root' })
208
+ export class IranLocationsService {
209
+ getProvinces() {
210
+ return getProvincesList();
211
+ }
212
+ getCitiesOf(provinceEn: string): City[] {
213
+ return getCities(provinceEn);
214
+ }
215
+ }
216
+ ```
217
+
218
+ ---
219
+
220
+ ## API کامل
221
+
222
+ ### توابع اصلی (import از `'@code-plate/iran-cities'`)
223
+
224
+ | تابع | ورودی | خروجی | توضیح |
225
+ |---|---|---|---|
226
+ | `getProvinces()` | - | `Province[]` | همه‌ی استان‌ها به همراه شهرها |
227
+ | `getProvincesList()` | - | `{en, fa}[]` | فقط لیست استان‌ها |
228
+ | `getProvince(query)` | `string` | `Province \| undefined` | یک استان با en یا fa |
229
+ | `getCities(provinceQuery)` | `string` | `City[]` | شهرهای یک استان |
230
+ | `getCity(cityQuery, provinceQuery?)` | `string, string?` | `FlatCity \| undefined` | یک شهر مشخص |
231
+ | `getAllCities()` | - | `FlatCity[]` | همه‌ی شهرها به‌صورت مسطح |
232
+ | `getProvinceOfCity(cityQuery)` | `string` | `Province \| undefined` | استانِ یک شهر |
233
+ | `searchProvinces(query, options?)` | `string, SearchOptions?` | `Province[]` | جستجوی fuzzy استان |
234
+ | `searchCities(query, options?)` | `string, SearchOptions?` | `FlatCity[]` | جستجوی fuzzy شهر |
235
+ | `getStats()` | - | `{provinceCount, cityCount}` | آمار کلی |
236
+
237
+ `SearchOptions`: `{ limit?: number; locale?: 'en' | 'fa' | 'both' }`
238
+
239
+ ### تایپ‌ها
240
+
241
+ ```ts
242
+ interface City { en: string; fa: string; }
243
+ interface Province { en: string; fa: string; cities: City[]; }
244
+ interface FlatCity extends City { provinceEn: string; provinceFa: string; }
245
+ ```
246
+
247
+ ---
248
+
249
+ ## توسعه
250
+
251
+ ```bash
252
+ npm install
253
+ npm run build # خروجی dist/ (cjs + esm + d.ts)
254
+ npm run typecheck
255
+ ```
256
+
257
+ ## لایسنس
258
+
259
+ MIT
package/README.md CHANGED
@@ -1,35 +1,37 @@
1
+ English | [فارسی](./README.fa.md)
2
+
1
3
  # @code-plate/iran-cities
2
4
 
3
- لیست کامل و آماده‌ی **استان‌ها و شهرهای ایران** (فارسی + انگلیسی)، بسته‌بندی‌شده به شکل یک کتابخانه‌ی سبک، بدون هیچ وابستگی اجباری، که در **هر پروژه‌ی جاوااسکریپتی/تایپ‌اسکریپتی** قابل استفاده است:
5
+ A complete, ready-to-use list of **Iran's provinces and cities** (Persian + English), packaged as a lightweight library with no forced dependencies, usable in **any JavaScript/TypeScript project**:
4
6
 
5
- - ✅ React / Next.js (App Router و Pages Router)
7
+ - ✅ React / Next.js (App Router and Pages Router)
6
8
  - ✅ Vue 2 / Vue 3
7
9
  - ✅ Angular
8
10
  - ✅ Svelte
9
- - ✅ Node.js / Express (بک‌اند خالص)
10
- - ✅ Vanilla JS (مرورگر یا هر باندلر دیگر)
11
+ - ✅ Node.js / Express (pure backend)
12
+ - ✅ Vanilla JS (browser or any other bundler)
11
13
 
12
- هسته‌ی اصلی پکیج **هیچ وابستگی‌ای** ندارد (zero-dependency) و هم به‌صورت **CJS** و هم **ESM** ارائه می‌شود. یک ساب‌پس اختیاری (`@code-plate/iran-cities/react`) هم برای کسانی که در React کار می‌کنند وجود دارد که چند هوک آماده می‌دهد؛ اگر پروژه‌تان React نیست، هرگز این فایل import نمی‌شود و React اصلاً لازم نیست نصب شود.
14
+ The core of the package has **zero dependencies** and ships as both **CJS** and **ESM**. There's also an optional subpath (`@code-plate/iran-cities/react`) for React users with a few ready-made hooks; if your project isn't React, that file is never imported and React doesn't need to be installed at all.
13
15
 
14
- ## نصب
16
+ ## Installation
15
17
 
16
18
  ```bash
17
19
  npm install @code-plate/iran-cities
18
- # یا
20
+ # or
19
21
  yarn add @code-plate/iran-cities
20
- # یا
22
+ # or
21
23
  pnpm add @code-plate/iran-cities
22
24
  ```
23
25
 
24
- ## داده‌ها
26
+ ## Data
25
27
 
26
- - `۳۱` استان
27
- - `۱۲۵۳` شهر
28
- - هر رکورد شامل `en` (شناسه لاتین kebab-case، مثل `tehran`) و `fa` (نام فارسی، مثل `تهران`) است.
28
+ - `31` provinces
29
+ - `1253` cities
30
+ - Every record has an `en` field (latin, kebab-case identifier, e.g. `tehran`) and an `fa` field (Persian name, e.g. `تهران`).
29
31
 
30
32
  ---
31
33
 
32
- ## استفاده در جاوااسکریپت / تایپ‌اسکریپت خالص (و Node.js/Express)
34
+ ## Usage in plain JavaScript / TypeScript (and Node.js/Express)
33
35
 
34
36
  ```ts
35
37
  import {
@@ -45,48 +47,48 @@ import {
45
47
  getStats,
46
48
  } from '@code-plate/iran-cities';
47
49
 
48
- // همه‌ی استان‌ها به همراه شهرهایشان
50
+ // All provinces along with their cities
49
51
  getProvinces();
50
52
  // [{ en: 'alborz', fa: 'البرز', cities: [{ en: 'karaj', fa: 'کرج' }, ...] }, ...]
51
53
 
52
- // فقط لیست استان‌ها (بدون شهر) - برای Select/Dropdown
54
+ // Just the list of provinces (no cities) - for a Select/Dropdown
53
55
  getProvincesList();
54
56
  // [{ en: 'alborz', fa: 'البرز' }, { en: 'ardabil', fa: 'اردبیل' }, ...]
55
57
 
56
- // گرفتن یک استان با نام انگلیسی یا فارسی
58
+ // Get a single province by English id or Persian name
57
59
  getProvince('tehran');
58
- getProvince('تهران'); // همین نتیجه را می‌دهد
60
+ getProvince('تهران'); // same result
59
61
 
60
- // شهرهای یک استان خاص
61
- getCities('fars'); // بر اساس شناسه انگلیسی
62
- getCities('فارس'); // یا بر اساس نام فارسی، هر دو یکسان کار می‌کنند
62
+ // Cities of a specific province
63
+ getCities('fars'); // by English id
64
+ getCities('فارس'); // or by Persian name, both work the same way
63
65
 
64
- // پیدا کردن یک شهر مشخص (در کل کشور یا محدود به یک استان)
66
+ // Find a specific city (across the whole country, or scoped to a province)
65
67
  getCity('shiraz');
66
- getCity('شیراز', 'fars'); // محدود به استان فارس
68
+ getCity('شیراز', 'fars'); // scoped to Fars province
67
69
 
68
- // لیست مسطح (flat) همه‌ی شهرهای کشور همراه با استان مربوطه
70
+ // Flat list of every city in the country, along with its province
69
71
  getAllCities();
70
72
  // [{ en: 'karaj', fa: 'کرج', provinceEn: 'alborz', provinceFa: 'البرز' }, ...]
71
73
 
72
- // پیدا کردن استانِ یک شهر
74
+ // Find which province a city belongs to
73
75
  getProvinceOfCity('اصفهان'); // => { en: 'isfahan', fa: 'اصفهان', cities: [...] }
74
76
 
75
- // جستجوی زنده (autocomplete) در استان‌ها یا شهرها
76
- searchProvinces('خراسان'); // هر سه استان خراسان را برمی‌گرداند
77
- searchCities('شهر', { limit: 10 }); // ۱۰ نتیجه‌ی اول شامل «شهر»
78
- searchCities('mashhad', { locale: 'en' }); // جستجو فقط در نام انگلیسی
77
+ // Live search (autocomplete) over provinces or cities
78
+ searchProvinces('خراسان'); // returns all three "Khorasan" provinces
79
+ searchCities('شهر', { limit: 10 }); // first 10 results containing "شهر"
80
+ searchCities('mashhad', { locale: 'en' }); // search English names only
79
81
 
80
- // آمار کلی
82
+ // Overall stats
81
83
  getStats(); // { provinceCount: 31, cityCount: 1253 }
82
84
  ```
83
85
 
84
- ### نکته‌ی مهم درباره‌ی جستجو
85
- تابع‌های `getProvince`, `getCities`, `getCity` و `getProvinceOfCity` به‌صورت **نرمال‌شده** مقایسه می‌کنند؛ یعنی تفاوت «ی» فارسی/«ي» عربی، «ک»/«ك»، نیم‌فاصله، فاصله و خط‌تیره را نادیده می‌گیرند. پس `getCity('كرج')` و `getCity('کرج')` هر دو کار می‌کنند.
86
+ ### A note on search
87
+ `getProvince`, `getCities`, `getCity` and `getProvinceOfCity` compare strings in a **normalized** way — differences between Persian «ی» and Arabic «ي», «ک» vs. «ك», zero-width non-joiners, spaces and hyphens are all ignored. So `getCity('كرج')` and `getCity('کرج')` both work.
86
88
 
87
89
  ---
88
90
 
89
- ## استفاده در Node.js / Express (بک‌اند)
91
+ ## Usage in Node.js / Express (backend)
90
92
 
91
93
  ```js
92
94
  const express = require('express');
@@ -109,9 +111,9 @@ app.get('/api/cities/search', (req, res) => {
109
111
 
110
112
  ---
111
113
 
112
- ## استفاده در React / Next.js
114
+ ## Usage in React / Next.js
113
115
 
114
- برای React یک ساب‌پس اختیاری وجود دارد که چند هوک آماده ارائه می‌دهد:
116
+ An optional subpath is available for React with a few ready-made hooks:
115
117
 
116
118
  ```tsx
117
119
  import { useProvinces, useCities, useProvinceCitySelect, useCitySearch } from '@code-plate/iran-cities/react';
@@ -122,14 +124,14 @@ function AddressForm() {
122
124
  return (
123
125
  <>
124
126
  <select value={province} onChange={(e) => setProvince(e.target.value)}>
125
- <option value="">انتخاب استان</option>
127
+ <option value="">Select a province</option>
126
128
  {provinces.map((p) => (
127
129
  <option key={p.en} value={p.en}>{p.fa}</option>
128
130
  ))}
129
131
  </select>
130
132
 
131
133
  <select value={city} onChange={(e) => setCity(e.target.value)} disabled={!province}>
132
- <option value="">انتخاب شهر</option>
134
+ <option value="">Select a city</option>
133
135
  {cities.map((c) => (
134
136
  <option key={c.en} value={c.en}>{c.fa}</option>
135
137
  ))}
@@ -139,7 +141,7 @@ function AddressForm() {
139
141
  }
140
142
  ```
141
143
 
142
- جستجوی زنده‌ی شهر (autocomplete):
144
+ Live city search (autocomplete):
143
145
 
144
146
  ```tsx
145
147
  import { useCitySearch } from '@code-plate/iran-cities/react';
@@ -149,7 +151,7 @@ function CityAutocomplete() {
149
151
 
150
152
  return (
151
153
  <div>
152
- <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="نام شهر..." />
154
+ <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="City name..." />
153
155
  <ul>
154
156
  {results.map((c) => (
155
157
  <li key={`${c.provinceEn}-${c.en}`}>{c.fa} ({c.provinceFa})</li>
@@ -160,21 +162,21 @@ function CityAutocomplete() {
160
162
  }
161
163
  ```
162
164
 
163
- هوک‌های در دسترس در ساب‌پس `react`:
165
+ Hooks available in the `react` subpath:
164
166
 
165
- | هوک | کاربرد |
167
+ | Hook | Purpose |
166
168
  |---|---|
167
- | `useProvinces()` | لیست استان‌ها |
168
- | `useCities(provinceQuery)` | شهرهای یک استان، وابسته به تغییر پارامتر |
169
- | `useProvinceCitySelect()` | state کامل یک فرم استان→شهر (با ریست خودکار شهر هنگام تغییر استان) |
170
- | `useCitySearch(initialQuery?, options?)` | state جستجوی زنده‌ی شهر |
171
- | `useProvinceSearch(initialQuery?, options?)` | state جستجوی زنده‌ی استان |
169
+ | `useProvinces()` | List of provinces |
170
+ | `useCities(provinceQuery)` | Cities of a province, reacts to changes in the parameter |
171
+ | `useProvinceCitySelect()` | Full state + logic for a province→city form field (auto-resets the city when the province changes) |
172
+ | `useCitySearch(initialQuery?, options?)` | Live city search state |
173
+ | `useProvinceSearch(initialQuery?, options?)` | Live province search state |
172
174
 
173
- > اگر پروژه‌تان Vue، Angular یا هر چیز دیگری است، فقط از مسیر اصلی (`@code-plate/iran-cities`) استفاده کنید و توابع خام (`getProvinces`, `getCities`, ...) را داخل computed/signal/observable خودتان قرار دهید — نیازی به هیچ ابزار اضافه‌ای نیست.
175
+ > If your project is Vue, Angular, or anything else, just use the main entry point (`@code-plate/iran-cities`) and plug the raw functions (`getProvinces`, `getCities`, ...) into your own computed/signal/observable — no extra tooling required.
174
176
 
175
177
  ---
176
178
 
177
- ## استفاده در Vue 3 (نمونه)
179
+ ## Usage in Vue 3 (example)
178
180
 
179
181
  ```vue
180
182
  <script setup>
@@ -196,7 +198,7 @@ const cities = computed(() => getCities(selectedProvince.value));
196
198
  </template>
197
199
  ```
198
200
 
199
- ## استفاده در Angular (نمونه سرویس)
201
+ ## Usage in Angular (example service)
200
202
 
201
203
  ```ts
202
204
  import { Injectable } from '@angular/core';
@@ -215,26 +217,26 @@ export class IranLocationsService {
215
217
 
216
218
  ---
217
219
 
218
- ## API کامل
220
+ ## Full API
219
221
 
220
- ### توابع اصلی (import از `'@code-plate/iran-cities'`)
222
+ ### Core functions (import from `'@code-plate/iran-cities'`)
221
223
 
222
- | تابع | ورودی | خروجی | توضیح |
224
+ | Function | Input | Output | Description |
223
225
  |---|---|---|---|
224
- | `getProvinces()` | - | `Province[]` | همه‌ی استان‌ها به همراه شهرها |
225
- | `getProvincesList()` | - | `{en, fa}[]` | فقط لیست استان‌ها |
226
- | `getProvince(query)` | `string` | `Province \| undefined` | یک استان با en یا fa |
227
- | `getCities(provinceQuery)` | `string` | `City[]` | شهرهای یک استان |
228
- | `getCity(cityQuery, provinceQuery?)` | `string, string?` | `FlatCity \| undefined` | یک شهر مشخص |
229
- | `getAllCities()` | - | `FlatCity[]` | همه‌ی شهرها به‌صورت مسطح |
230
- | `getProvinceOfCity(cityQuery)` | `string` | `Province \| undefined` | استانِ یک شهر |
231
- | `searchProvinces(query, options?)` | `string, SearchOptions?` | `Province[]` | جستجوی fuzzy استان |
232
- | `searchCities(query, options?)` | `string, SearchOptions?` | `FlatCity[]` | جستجوی fuzzy شهر |
233
- | `getStats()` | - | `{provinceCount, cityCount}` | آمار کلی |
226
+ | `getProvinces()` | - | `Province[]` | All provinces with their cities |
227
+ | `getProvincesList()` | - | `{en, fa}[]` | Provinces only |
228
+ | `getProvince(query)` | `string` | `Province \| undefined` | A province by en or fa |
229
+ | `getCities(provinceQuery)` | `string` | `City[]` | Cities of a province |
230
+ | `getCity(cityQuery, provinceQuery?)` | `string, string?` | `FlatCity \| undefined` | A specific city |
231
+ | `getAllCities()` | - | `FlatCity[]` | All cities, flattened |
232
+ | `getProvinceOfCity(cityQuery)` | `string` | `Province \| undefined` | The province a city belongs to |
233
+ | `searchProvinces(query, options?)` | `string, SearchOptions?` | `Province[]` | Fuzzy province search |
234
+ | `searchCities(query, options?)` | `string, SearchOptions?` | `FlatCity[]` | Fuzzy city search |
235
+ | `getStats()` | - | `{provinceCount, cityCount}` | Overall stats |
234
236
 
235
237
  `SearchOptions`: `{ limit?: number; locale?: 'en' | 'fa' | 'both' }`
236
238
 
237
- ### تایپ‌ها
239
+ ### Types
238
240
 
239
241
  ```ts
240
242
  interface City { en: string; fa: string; }
@@ -244,14 +246,14 @@ interface FlatCity extends City { provinceEn: string; provinceFa: string; }
244
246
 
245
247
  ---
246
248
 
247
- ## توسعه
249
+ ## Development
248
250
 
249
251
  ```bash
250
252
  npm install
251
- npm run build # خروجی dist/ (cjs + esm + d.ts)
253
+ npm run build # outputs dist/ (cjs + esm + d.ts)
252
254
  npm run typecheck
253
255
  ```
254
256
 
255
- ## لایسنس
257
+ ## License
256
258
 
257
259
  MIT