utilzify 1.14.1 → 1.14.4

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.
Files changed (38) hide show
  1. package/README.md +689 -1
  2. package/lib/browser/bundle.iife.js +1 -1
  3. package/lib/browser/bundle.umd.js +1 -1
  4. package/lib/cjs/_virtual/customParseFormat.js +1 -0
  5. package/lib/cjs/_virtual/dayjs.min.js +1 -0
  6. package/lib/cjs/node_modules/dayjs/dayjs.min.js +1 -0
  7. package/lib/cjs/node_modules/dayjs/plugin/customParseFormat.js +1 -0
  8. package/lib/cjs/utils/_dayjs.d.ts +3 -0
  9. package/lib/cjs/utils/_dayjs.d.ts.map +1 -0
  10. package/lib/cjs/utils/_dayjs.js +1 -0
  11. package/lib/cjs/utils/axios-handlers.js +1 -1
  12. package/lib/cjs/utils/column-parser.js +1 -1
  13. package/lib/cjs/utils/convert-base64-to-file.js +1 -1
  14. package/lib/cjs/utils/dom.js +1 -1
  15. package/lib/cjs/utils/excel.js +1 -1
  16. package/lib/cjs/utils/extract-error-message.js +1 -1
  17. package/lib/cjs/utils/mappers.d.ts.map +1 -1
  18. package/lib/cjs/utils/mappers.js +1 -1
  19. package/lib/cjs/utils/save-file.js +1 -1
  20. package/lib/cjs/utils/tools.js +1 -1
  21. package/lib/esm/_virtual/customParseFormat.js +1 -0
  22. package/lib/esm/_virtual/dayjs.min.js +1 -0
  23. package/lib/esm/node_modules/dayjs/dayjs.min.js +1 -0
  24. package/lib/esm/node_modules/dayjs/plugin/customParseFormat.js +1 -0
  25. package/lib/esm/utils/_dayjs.d.ts +3 -0
  26. package/lib/esm/utils/_dayjs.d.ts.map +1 -0
  27. package/lib/esm/utils/_dayjs.js +1 -0
  28. package/lib/esm/utils/axios-handlers.js +1 -1
  29. package/lib/esm/utils/column-parser.js +1 -1
  30. package/lib/esm/utils/convert-base64-to-file.js +1 -1
  31. package/lib/esm/utils/dom.js +1 -1
  32. package/lib/esm/utils/excel.js +1 -1
  33. package/lib/esm/utils/extract-error-message.js +1 -1
  34. package/lib/esm/utils/mappers.d.ts.map +1 -1
  35. package/lib/esm/utils/mappers.js +1 -1
  36. package/lib/esm/utils/save-file.js +1 -1
  37. package/lib/esm/utils/tools.js +1 -1
  38. package/package.json +4 -4
package/README.md CHANGED
@@ -1 +1,689 @@
1
- # ApiZum with sheets
1
+ # utilzify
2
+
3
+ > JavaScript va TypeScript loyihalari uchun yengil, modulli yordamchi funksiyalar kutubxonasi.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/utilzify.svg)](https://www.npmjs.com/package/utilzify)
6
+ [![npm downloads](https://img.shields.io/npm/dm/utilzify.svg)](https://www.npmjs.com/package/utilzify)
7
+ [![license](https://img.shields.io/npm/l/utilzify.svg)](https://github.com/svkhrobbeck/utilzify/blob/main/LICENSE)
8
+
9
+ `utilzify` — frontend va backend ishlanmalarda eng ko'p uchraydigan vazifalarni soddalashtirish uchun mo'ljallangan utilitlar to'plami. Sana formatlash, raqam parselash, Excel/CSV bilan ishlash, Google Sheets'dan ma'lumot o'qish, HTTP header generatsiyasi, xato xabarlarini chiqarib olish va boshqa ko'plab vazifalar uchun tayyor yechimlar.
10
+
11
+ ---
12
+
13
+ ## Mundarija
14
+
15
+ - [O'rnatish](#ornatish)
16
+ - [Xususiyatlar](#xususiyatlar)
17
+ - [Tezkor boshlash](#tezkor-boshlash)
18
+ - [API hujjati](#api-hujjati)
19
+ - [Sana bilan ishlash](#sana-bilan-ishlash)
20
+ - [Raqam va matnni formatlash](#raqam-va-matnni-formatlash)
21
+ - [Asinxron yordamchilar](#asinxron-yordamchilar)
22
+ - [Vaqt birliklari](#vaqt-birliklari)
23
+ - [Object va jadval bilan ishlash](#object-va-jadval-bilan-ishlash)
24
+ - [Excel bilan ishlash](#excel-bilan-ishlash)
25
+ - [Column / Row parser](#column--row-parser)
26
+ - [Google Sheets mapper](#google-sheets-mapper)
27
+ - [Axios handler'lari](#axios-handlerlari)
28
+ - [HTTP header generator](#http-header-generator)
29
+ - [Xato xabarlarini ajratish](#xato-xabarlarini-ajratish)
30
+ - [DOM va fayl saqlash](#dom-va-fayl-saqlash)
31
+ - [Atrof-muhit (environment)](#atrof-muhit-environment)
32
+ - [Boshqa utilitlar](#boshqa-utilitlar)
33
+ - [TypeScript qo'llab-quvvatlash](#typescript-qollab-quvvatlash)
34
+ - [Litsenziya](#litsenziya)
35
+
36
+ ---
37
+
38
+ ## O'rnatish
39
+
40
+ ```bash
41
+ # yarn
42
+ yarn add utilzify
43
+
44
+ # npm
45
+ npm install utilzify
46
+
47
+ # pnpm
48
+ pnpm add utilzify
49
+ ```
50
+
51
+ **Talablar:** Node.js >= 20. Kutubxona ESM, CJS va UMD formatlarida tarqatiladi.
52
+
53
+ ---
54
+
55
+ ## Xususiyatlar
56
+
57
+ - **Yengil bundle** — sanalar uchun `dayjs` (~2kb gzip)
58
+ - **Tree-shakeable** — `sideEffects: false`, faqat ishlatilgan funksiyalar build'ga tushadi
59
+ - **TypeScript** — barcha funksiyalar uchun to'liq typelar va nested key inferensiyasi
60
+ - **Universal** — Node.js va brauzer muhitlarida ishlaydi (muhitga bog'liq funksiyalar avtomatik tekshiriladi)
61
+ - **Excel/CSV** — `exceljs` asosida o'qish/yozish
62
+ - **Robust xato ajratish** — har qanday API javobidan xato matnini topib oladi
63
+
64
+ ---
65
+
66
+ ## Tezkor boshlash
67
+
68
+ ```ts
69
+ import { getFormattedDate, formatCurrencyPrice, debounce, Excel } from "utilzify";
70
+
71
+ // Sana formatlash
72
+ getFormattedDate(new Date(), "DD/MM/YYYY"); // "15/05/2026"
73
+
74
+ // Pulni formatlash
75
+ formatCurrencyPrice(1250000, "UZS"); // "UZS 1,250,000.00"
76
+
77
+ // Debounce
78
+ const onSearch = debounce((q: string) => fetch(`/api?q=${q}`), 300);
79
+
80
+ // Excel o'qish (frontend)
81
+ const excel = new Excel();
82
+ const rows = await excel.readFromArrayBuffer(blob, 1);
83
+ ```
84
+
85
+ ---
86
+
87
+ ## API hujjati
88
+
89
+ ### Sana bilan ishlash
90
+
91
+ Ichkarida `dayjs` ishlatiladi, `customParseFormat` plugini avtomatik kengaytirilgan — `moment` formatidagi tokenlar (`DD/MM/YYYY`, `HH:mm:ss` va h.k.) ishlayveradi.
92
+
93
+ #### `getFormattedDate(date?, format?)`
94
+
95
+ `Date`, `number` yoki `string` qiymatni formatlangan satrga aylantiradi.
96
+
97
+ ```ts
98
+ getFormattedDate(); // "15/05/2026 14:30:00" (default: DD/MM/YYYY HH:mm:ss)
99
+ getFormattedDate(Date.now(), "YYYY-MM-DD"); // "2026-05-15"
100
+ getFormattedDate("2026-05-15T10:00:00Z", "HH:mm"); // "15:00"
101
+ getFormattedDate("noto'g'ri sana"); // "" (yaroqsiz bo'lsa bo'sh satr)
102
+ ```
103
+
104
+ #### `getValidDate(dateStr, parseFormat)`
105
+
106
+ Formatga ko'ra satrdan `Date` obyektini parselaydi.
107
+
108
+ ```ts
109
+ getValidDate("15/05/2026", "DD/MM/YYYY"); // Date obyekti
110
+ ```
111
+
112
+ #### `formatDateLocaleString(date, locales?, timeZone?)`
113
+
114
+ `Intl` orqali mahalliy formatlash. Default: `en-GB` locale, `Asia/Tashkent` vaqt zonasi.
115
+
116
+ ```ts
117
+ formatDateLocaleString(Date.now()); // "15/05/2026, 14:30:00"
118
+ formatDateLocaleString(Date.now(), "uz-UZ", "Asia/Tashkent"); // "15.05.2026, 14:30:00"
119
+ ```
120
+
121
+ ---
122
+
123
+ ### Raqam va matnni formatlash
124
+
125
+ #### `formatCurrencyPrice(price, currency, locales?)`
126
+
127
+ Pul qiymatini valyuta bilan birga formatlaydi.
128
+
129
+ ```ts
130
+ formatCurrencyPrice(1250000, "UZS"); // "UZS 1,250,000.00"
131
+ formatCurrencyPrice(99.99, "USD", "en-US"); // "$99.99"
132
+ formatCurrencyPrice(1500, "EUR", "de-DE"); // "1.500,00 €"
133
+ ```
134
+
135
+ #### `formatStringToFloat(str, defaultValue?)`
136
+
137
+ Har xil formatdagi raqamli matnlarni `number` ga aylantiradi. Hind (`1,23,456.78`), Yevropa (`1.234,56`) va oddiy (`1234.56`) formatlarni tushunadi.
138
+
139
+ ```ts
140
+ formatStringToFloat("1,234.56"); // 1234.56
141
+ formatStringToFloat("1.234,56"); // 1234.56
142
+ formatStringToFloat("1,23,456.78"); // 123456.78
143
+ formatStringToFloat("noto'g'ri", 0); // 0
144
+ ```
145
+
146
+ #### `parseSeparatedNumber(str)`
147
+
148
+ Verguldan tozalab `Number` ga aylantiradi.
149
+
150
+ ```ts
151
+ parseSeparatedNumber("1,234,567"); // 1234567
152
+ ```
153
+
154
+ #### `isIndianFormat(str)` / `parseIndianFormat(str)` / `parseEuropeanFormat(str)`
155
+
156
+ Spetsifik format aniqlovchilari va parserlar (`formatStringToFloat` ichida ishlatiladi).
157
+
158
+ #### `stripHtmlTags(html)`
159
+
160
+ HTML teglarni olib tashlaydi.
161
+
162
+ ```ts
163
+ stripHtmlTags("<p>Salom <b>dunyo</b></p>"); // "Salom dunyo"
164
+ ```
165
+
166
+ ---
167
+
168
+ ### Asinxron yordamchilar
169
+
170
+ #### `delay(ms)`
171
+
172
+ Berilgan vaqtga kutadi.
173
+
174
+ ```ts
175
+ await delay(1000); // 1 soniya
176
+ ```
177
+
178
+ #### `delayRun(ms, callback?)`
179
+
180
+ Berilgan vaqtdan keyin callback'ni ishga tushiradi va natijasini qaytaradi.
181
+
182
+ ```ts
183
+ const result = await delayRun(500, async () => fetchData());
184
+ ```
185
+
186
+ #### `debounce(func, delay?, immediate?)`
187
+
188
+ Funksiyani debounce qiladi (default: 300ms).
189
+
190
+ ```ts
191
+ const onChange = debounce((value: string) => {
192
+ console.log("Foydalanuvchi yozishni to'xtatdi:", value);
193
+ }, 500);
194
+ ```
195
+
196
+ #### `measureExecutionTime(fn, label?, format)`
197
+
198
+ Funksiya bajarilish vaqtini o'lchaydi va konsolga chiqaradi.
199
+
200
+ ```ts
201
+ const data = await measureExecutionTime(
202
+ () => fetchLargeDataset(),
203
+ "fetchLargeDataset",
204
+ "s",
205
+ );
206
+ // [fetchLargeDataset] Boshladi: 15/05/2026 14:30:00
207
+ // [fetchLargeDataset] Tugadi: 15/05/2026 14:30:03
208
+ // [fetchLargeDataset] Davomiyligi: 3.20 soniya
209
+ ```
210
+
211
+ ---
212
+
213
+ ### Vaqt birliklari
214
+
215
+ #### `toMilliseconds(time)`
216
+
217
+ Turli vaqt birliklarini millisekundga aylantiradi.
218
+
219
+ ```ts
220
+ toMilliseconds({ minutes: 5, seconds: 30 }); // 330000
221
+ toMilliseconds({ hours: 1, days: 2 }); // 176400000
222
+ toMilliseconds({ years: 1 }); // 31557600000
223
+ ```
224
+
225
+ Qabul qiluvchi kalitlar: `milliseconds`, `seconds`, `minutes`, `hours`, `days`, `weeks`, `months` (30.44 kun), `years` (365.25 kun).
226
+
227
+ #### `formatDuration(ms, format)`
228
+
229
+ Davomiylikni odamga tushunarli ko'rinishga keltiradi.
230
+
231
+ ```ts
232
+ formatDuration(125000, "human"); // "2 daqiqa 5 soniya"
233
+ formatDuration(125000, "s"); // "125.00 soniya"
234
+ formatDuration(125000, "min"); // "2.08 daqiqa"
235
+ formatDuration(125000, "ms"); // "125000 millisoniya"
236
+ ```
237
+
238
+ ---
239
+
240
+ ### Object va jadval bilan ishlash
241
+
242
+ #### `getNestedValue(obj, key)`
243
+
244
+ Nested kalit bo'yicha qiymatni xavfsiz olish.
245
+
246
+ ```ts
247
+ getNestedValue({ a: { b: { c: 42 } } }, "a.b.c"); // 42
248
+ getNestedValue({ a: null }, "a.b.c"); // null
249
+ ```
250
+
251
+ TypeScript bilan ishlatilganda `NestedKeyOf<T>` orqali kalit avtomatik to'liq tip xavfsiz bo'ladi.
252
+
253
+ #### `buildTableRows(data, columns, withHeader?, extraMapper?)`
254
+
255
+ Obyekt massivini jadval (`any[][]`) ko'rinishiga aylantiradi. Excel/CSV eksporti va react-table kabi kutubxonalar uchun ideal.
256
+
257
+ ```ts
258
+ type User = { id: number; name: string; email: string; createdAt: string };
259
+
260
+ const users: User[] = [...];
261
+
262
+ const rows = buildTableRows(users, {
263
+ id: "ID", // sodda header
264
+ name: { header: "Ismi" }, // obyekt formati
265
+ email: [
266
+ "Email manzili",
267
+ (val, row) => `<${val}>`, // tuple: [header, mapper]
268
+ ],
269
+ createdAt: (val) => getFormattedDate(val), // faqat mapper
270
+ }, true);
271
+
272
+ // Natija:
273
+ // [
274
+ // ["ID", "Ismi", "Email manzili", "createdAt"],
275
+ // [1, "Ali", "<ali@example.com>", "15/05/2026 14:30:00"],
276
+ // ...
277
+ // ]
278
+ ```
279
+
280
+ **Column tip variantlari:**
281
+
282
+ | Format | Misol | Tushuntirish |
283
+ |---|---|---|
284
+ | `string` | `"Header nomi"` | Faqat header matni |
285
+ | `MapperFn` | `(val, row, key) => ...` | Faqat mapper, header avtomatik |
286
+ | `[string, MapperFn]` | `["Header", mapper]` | Header va mapper |
287
+ | `Object` | `{ header, mapper, emptyVal, staticVal }` | To'liq nazorat |
288
+ | `false` | — | Bu ustun skip qilinadi |
289
+
290
+ **Performance:** Funksiya 25k+ qatorlik massivlar bilan ham tez ishlaydi — column metadata bir marta compile qilinib hot loopda qayta ishlatiladi.
291
+
292
+ #### `objectToArray(data, keys, headers?, emptyVal?)`
293
+
294
+ Tezkor variant: faqat ko'rsatilgan kalitlardan jadval tuzadi (mapper yo'q).
295
+
296
+ ```ts
297
+ objectToArray(users, ["id", "name", "email"], ["ID", "Ism", "Email"]);
298
+ ```
299
+
300
+ #### `objectItemToArray(row, keys, emptyVal?)`
301
+
302
+ Bitta obyektni massivga aylantiradi.
303
+
304
+ #### `getPrimitiveKeys(input)`
305
+
306
+ Obyekt yoki massiv ichidagi barcha primitiv kalitlarni `dot.notation` ko'rinishida qaytaradi (dinamik tablica generatsiyasi uchun foydali).
307
+
308
+ ```ts
309
+ getPrimitiveKeys([{ id: 1, user: { name: "Ali" } }]);
310
+ // ["id", "user.name"]
311
+ ```
312
+
313
+ ---
314
+
315
+ ### Excel bilan ishlash
316
+
317
+ `Excel` sinfi `exceljs` asosida ishlaydi va faqat **frontend muhitda** chaqiriladi (konstruktor o'zi muhitni tekshiradi).
318
+
319
+ ```ts
320
+ import { Excel } from "utilzify";
321
+
322
+ const excel = new Excel();
323
+
324
+ // 1) Blob/ArrayBuffer dan o'qish
325
+ const rows = await excel.readFromArrayBuffer(blob, 1);
326
+
327
+ // 2) Disk yo'lidan o'qish (Node muhitida)
328
+ const rows2 = await excel.read("./data.xlsx", "Sheet1");
329
+
330
+ // 3) Obyekt massividan yozish va yuklatish
331
+ await excel.write(
332
+ users,
333
+ ["ID", "Ismi", "Email"],
334
+ ["id", "name", "email"],
335
+ "users",
336
+ "Sheet1",
337
+ );
338
+ // → users_2026-05-15.xlsx yuklab olinadi
339
+
340
+ // 4) Massivlardan yozish
341
+ await excel.writeFromArray(
342
+ [["1", "Ali", "ali@example.com"]],
343
+ ["ID", "Ismi", "Email"],
344
+ "users",
345
+ );
346
+ ```
347
+
348
+ ---
349
+
350
+ ### Column / Row parser
351
+
352
+ Excel/Google Sheets dan kelgan qator massivlarini tip-xavfsiz ravishda parselash uchun.
353
+
354
+ #### Yordamchi funksiyalar
355
+
356
+ ```ts
357
+ getColumnIndex("A"); // 0
358
+ getColumnIndex("Z"); // 25
359
+ getColumnIndex("AA"); // 26
360
+
361
+ getColumnName(0); // "A"
362
+ getColumnName(26); // "AA"
363
+
364
+ getValueByName(row, "C", null); // C ustun qiymati
365
+ ```
366
+
367
+ #### `ColumnParser`
368
+
369
+ Default qiymat va tip-xavfsiz ishlash bilan.
370
+
371
+ ```ts
372
+ const row = ["Ali", "25", "TRUE", "1,250,000", "15/05/2026"];
373
+
374
+ ColumnParser.string(row, "A"); // "Ali"
375
+ ColumnParser.number(row, "B", 0); // 25
376
+ ColumnParser.boolean(row, "C", false); // true
377
+ ColumnParser.price(row, "D"); // 1250000
378
+ ColumnParser.date(row, "E", "DD/MM/YYYY"); // Date obyekti
379
+ ColumnParser.formattedDate(row, "E", "DD/MM/YYYY", "YYYY-MM-DD"); // "2026-05-15"
380
+ ```
381
+
382
+ #### `ColumnMapper` va `IndexMapper`
383
+
384
+ Eski API — `ColumnMapper` kalit nomi bo'yicha (`"A"`, `"B"`), `IndexMapper` indeks bo'yicha (`0`, `1`) ishlaydi.
385
+
386
+ ```ts
387
+ ColumnMapper.getStr(row, "A", "default");
388
+ ColumnMapper.getNum(row, "B", 0);
389
+ ColumnMapper.getBool(row, "C", false);
390
+ ColumnMapper.getPrice(row, "D");
391
+ ColumnMapper.getDate(row, "E", "DD/MM/YYYY");
392
+ ColumnMapper.getDateFormatted(row, "E", "YYYY-MM-DD", "DD/MM/YYYY");
393
+
394
+ IndexMapper.getStr(row, 0);
395
+ IndexMapper.getNum(row, 1);
396
+ // ...
397
+ ```
398
+
399
+ #### `resolveHeaderColumn` va `resolveHeaderColumnMap`
400
+
401
+ Sheet'ning birinchi qatoridagi headerlar bo'yicha ustun harflarini topish.
402
+
403
+ ```ts
404
+ const headers = ["ID", "Ismi", "Email", "Sana"];
405
+
406
+ resolveHeaderColumn(headers, "Email"); // "C"
407
+ resolveHeaderColumn(headers, "Telefon", "X"); // "X" (topilmasa)
408
+
409
+ resolveHeaderColumnMap(headers, {
410
+ id: "ID",
411
+ name: "Ismi",
412
+ email: ["Email", "C"], // [header, default]
413
+ });
414
+ // → { id: "A", name: "B", email: "C" }
415
+ ```
416
+
417
+ ---
418
+
419
+ ### Google Sheets mapper
420
+
421
+ Tipik Google Sheets ma'lumotlarini tip-xavfsiz ravishda obyektlarga aylantirish uchun yuqori darajali API.
422
+
423
+ #### `createColMapper` — ustun harfi bo'yicha
424
+
425
+ ```ts
426
+ import { createColMapper, col } from "utilzify";
427
+
428
+ const mapRow = createColMapper({
429
+ id: col.num("A"),
430
+ name: col.str("B", ""),
431
+ isActive: col.bool("C", false),
432
+ price: col.price("D"),
433
+ createdAt: col.date("E", "DD/MM/YYYY"),
434
+ formattedDate: col.datefmt("E", "DD/MM/YYYY", "YYYY-MM-DD"),
435
+ fullName: col.fn((row) => `${row[1]} ${row[2]}`), // custom logika
436
+ });
437
+
438
+ const result = mapRow(["1", "Ali", "TRUE", "1,250,000", "15/05/2026"]);
439
+ // { id: 1, name: "Ali", isActive: true, price: 1250000, ... }
440
+ ```
441
+
442
+ #### `createHdrMapper` — header nomi bo'yicha
443
+
444
+ Sheet ustunlari joyi o'zgarib turishi mumkin bo'lgan holatlar uchun.
445
+
446
+ ```ts
447
+ import { createHdrMapper, hdr } from "utilzify";
448
+
449
+ const buildMapper = createHdrMapper({
450
+ id: hdr.num("ID"),
451
+ name: hdr.str("Ismi"),
452
+ email: hdr.str(["Email", "C"]), // default ustun "C"
453
+ });
454
+
455
+ const rows = await excel.read("./data.xlsx");
456
+ const [headers, ...dataRows] = rows;
457
+
458
+ const mapRow = buildMapper(headers);
459
+ const users = dataRows.map(mapRow);
460
+ ```
461
+
462
+ Builderlar: `col.str()`, `col.num()`, `col.bool()`, `col.price()`, `col.date()`, `col.datefmt()`, `col.fn()`. Shu kabi `hdr.*`.
463
+
464
+ ---
465
+
466
+ ### Axios handler'lari
467
+
468
+ `axios` interceptor'lari uchun tayyor handler'lar.
469
+
470
+ ```ts
471
+ import axios from "axios";
472
+ import { axiosSuccessHandler, axiosErrorHandler } from "utilzify";
473
+
474
+ axios.interceptors.response.use(
475
+ axiosSuccessHandler((data) => console.log("OK:", data)),
476
+ axiosErrorHandler((err, message) => console.error("XATO:", message)),
477
+ );
478
+
479
+ // Endi har qanday so'rov natijasi:
480
+ // { ...response, type: "SUCCESS" }
481
+ // yoki rejected: { error, data, status, statusText, type: "ERROR" }
482
+ ```
483
+
484
+ `axiosErrorHandler` ning ikkinchi parametri (`reject`) `false` qilinsa, xato o'rniga resolved promise qaytariladi.
485
+
486
+ ---
487
+
488
+ ### HTTP header generator
489
+
490
+ Brauzer fingerprintingidan qochish yoki test qilish uchun real ko'rinishdagi headerlar.
491
+
492
+ ```ts
493
+ import {
494
+ generateUserAgents,
495
+ generateRandomHeaders,
496
+ generateAndAssignRandomHeaders,
497
+ clearHeaders,
498
+ headerRandomizer,
499
+ randIp,
500
+ } from "utilzify";
501
+
502
+ generateUserAgents(5);
503
+ // ["Mozilla/5.0 (Windows NT 10.0; en) Chrome/12.3 Blink/4.7", ...]
504
+
505
+ generateRandomHeaders();
506
+ // { Accept: "...", "User-Agent": "...", Referer: "...", "X-Forwarded-For": "...", ... }
507
+
508
+ randIp(); // "15.234.12.87"
509
+
510
+ // Axios config'iga to'g'ridan-to'g'ri qo'shish
511
+ const config = generateAndAssignRandomHeaders({ url: "/api/data" });
512
+
513
+ clearHeaders(headers, ["x-custom-header"]); // Sezgir headerlarni olib tashlaydi
514
+ ```
515
+
516
+ Eslatma: Brauzer muhitida `User-Agent`, `Referer` va shu kabilar avtomatik o'tkazib yuboriladi (brauzer ularni o'zi belgilaydi).
517
+
518
+ ---
519
+
520
+ ### Xato xabarlarini ajratish
521
+
522
+ Har qanday API javobidan eng mos xato matnini topib chiqaradi (50+ umumiy kalit yo'llari sinab ko'riladi).
523
+
524
+ #### `extractErrorMessage(error, defaultMsg?, additionalKeys?)`
525
+
526
+ ```ts
527
+ import { extractErrorMessage } from "utilzify";
528
+
529
+ try {
530
+ await api.request();
531
+ } catch (err) {
532
+ const msg = extractErrorMessage(err, "Noma'lum xato");
533
+ showToast(msg);
534
+ }
535
+ ```
536
+
537
+ Quyidagi yo'llardan biri bo'yicha xato topiladi: `response.data.error`, `response.data.message`, `error.message`, `cause.message`, `errors[*].message`, va h.k. HTML teglar avtomatik tozalanadi.
538
+
539
+ #### `extractErrorMessages(error, additionalKeys?)`
540
+
541
+ Bir nechta xato xabarlarini massiv ko'rinishida qaytaradi (validatsiya xatolari uchun).
542
+
543
+ ```ts
544
+ const messages = extractErrorMessages(validationError);
545
+ // ["Ism majburiy", "Email noto'g'ri formatda", ...]
546
+ ```
547
+
548
+ ---
549
+
550
+ ### DOM va fayl saqlash
551
+
552
+ > Bu funksiyalar **faqat brauzer muhitida** ishlaydi. Node.js da chaqirilsa `Error` tashlanadi.
553
+
554
+ #### `scrollToElement(selector)`
555
+
556
+ ```ts
557
+ scrollToElement("#section-2"); // smooth scroll
558
+ ```
559
+
560
+ #### `saveFile(blob, fileName)`
561
+
562
+ Blob'ni foydalanuvchiga fayl ko'rinishida yuklatadi.
563
+
564
+ ```ts
565
+ const blob = new Blob([data], { type: "application/pdf" });
566
+ saveFile(blob, "hisobot.pdf");
567
+ ```
568
+
569
+ #### `convertBase64ToFile(base64, fileName, fileType)`
570
+
571
+ Base64 satrni faylga aylantirib yuklatadi.
572
+
573
+ ```ts
574
+ convertBase64ToFile(base64String, "rasm", "PNG");
575
+ convertBase64ToFile(pdfBase64, "shartnoma", "PDF");
576
+ ```
577
+
578
+ Qo'llab-quvvatlanadigan turlar: `PDF`, `PNG`, `JPEG`, `EXCEL`, `WORD`, `TEXT`.
579
+
580
+ ---
581
+
582
+ ### Atrof-muhit (environment)
583
+
584
+ ```ts
585
+ import { isBrowser, isNode, checkEnvironment } from "utilzify";
586
+
587
+ if (isBrowser()) {
588
+ // brauzer kodi
589
+ }
590
+
591
+ if (isNode()) {
592
+ // Node.js kodi
593
+ }
594
+
595
+ // Noto'g'ri muhitda chaqirilsa xato tashlaydi:
596
+ checkEnvironment("frontend");
597
+ checkEnvironment("backend");
598
+ ```
599
+
600
+ ---
601
+
602
+ ### Boshqa utilitlar
603
+
604
+ #### `getRandomInt(min, max)`
605
+
606
+ ```ts
607
+ getRandomInt(1, 100); // 1 va 100 oraligida tasodifiy butun son
608
+ ```
609
+
610
+ #### `generateIdempotencyKey()`
611
+
612
+ UUID v4 generatsiyasi (API'larda takroriy so'rovlarni oldini olish uchun).
613
+
614
+ ```ts
615
+ generateIdempotencyKey(); // "f47ac10b-58cc-4372-a567-0e02b2c3d479"
616
+ ```
617
+
618
+ #### `convertDigitalSize(input, output, value)`
619
+
620
+ Raqamli o'lchov birliklarini aylantirish: `bit`, `byte`, `kb`, `mb`, `gb`, `tb`.
621
+
622
+ ```ts
623
+ convertDigitalSize("mb", "gb", 1500); // 1.46
624
+ convertDigitalSize("byte", "kb", 2048); // 2
625
+ ```
626
+
627
+ #### `calculateDiscountedPrice(originalPrice, discountPercentage)`
628
+
629
+ Chegirma narxini hisoblash.
630
+
631
+ ```ts
632
+ calculateDiscountedPrice(100000, 15); // 85000
633
+ ```
634
+
635
+ #### `formatJsonForTelegram(data)`
636
+
637
+ Telegram bot uchun JSON xabarini `<pre>` blokda formatlash (HTML parse mode).
638
+
639
+ ```ts
640
+ formatJsonForTelegram({ status: "ok", id: 42 });
641
+ // "<pre>{\n \"status\": \"ok\",\n \"id\": 42\n}</pre>"
642
+ ```
643
+
644
+ #### `FileType` va `fileConfigs`
645
+
646
+ Fayl turlari va ularning MIME-type/extension xaritalari.
647
+
648
+ ```ts
649
+ import { FileType, fileConfigs } from "utilzify";
650
+
651
+ fileConfigs[FileType.PDF]; // { mimeType: "application/pdf", extension: "pdf" }
652
+ fileConfigs[FileType.EXCEL]; // { mimeType: "...spreadsheetml.sheet", extension: "xlsx" }
653
+ ```
654
+
655
+ ---
656
+
657
+ ## TypeScript qo'llab-quvvatlash
658
+
659
+ Kutubxona TypeScript bilan yozilgan va barcha publik API uchun tiplar mavjud. Eng qiziq tiplar:
660
+
661
+ ```ts
662
+ import type {
663
+ NestedKeyOf, // T obyektining "a.b.c" ko'rinishidagi barcha kalitlari
664
+ MapperFn, // buildTableRows uchun mapper signature
665
+ SortedArrayColumn, // buildTableRows kolumn definitsiyasi
666
+ ColSchema, HdrSchema, // createColMapper / createHdrMapper sxemalari
667
+ InferColSchema, // sxemadan natija tipini inferensiya qilish
668
+ TimeInput, // toMilliseconds parametri
669
+ FormatDurationTime, // "ms" | "s" | "min" | "human"
670
+ UnitType, // "bit" | "byte" | "kb" | "mb" | "gb" | "tb"
671
+ FileConfig,
672
+ EcosystemApp, // pm2 ecosystem.config tipi
673
+ EcosystemConfig,
674
+ } from "utilzify";
675
+ ```
676
+
677
+ `NestedKeyOf` orqali nested kalitlar avtomatik to'liq tip-xavfsiz bo'ladi:
678
+
679
+ ```ts
680
+ type User = { id: number; profile: { name: string; age: number } };
681
+
682
+ getNestedValue<User, "profile.name">(user, "profile.name"); // string | null
683
+ ```
684
+
685
+ ---
686
+
687
+ ## Litsenziya
688
+
689
+ ISC © [svkhrobbeck](https://github.com/svkhrobbeck)