@libs-ui/utils 0.2.355-9 → 0.2.356-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/README.md +633 -2
- package/base64.d.ts +25 -0
- package/cache.d.ts +73 -0
- package/collection.d.ts +12 -0
- package/color.d.ts +37 -0
- package/communicate-micro.d.ts +34 -1
- package/crypto-3rd.d.ts +12 -0
- package/crypto.d.ts +17 -0
- package/dangerous-object.d.ts +8 -1
- package/data.d.ts +5 -3
- package/date.d.ts +12 -0
- package/dom.d.ts +56 -0
- package/download.d.ts +21 -0
- package/esm2022/base64.mjs +27 -2
- package/esm2022/cache.mjs +74 -1
- package/esm2022/collection.mjs +13 -1
- package/esm2022/color.mjs +38 -1
- package/esm2022/communicate-micro.mjs +37 -5
- package/esm2022/crypto-3rd.mjs +13 -1
- package/esm2022/crypto.mjs +18 -1
- package/esm2022/dangerous-object.mjs +11 -2
- package/esm2022/data.mjs +6 -4
- package/esm2022/date.mjs +13 -1
- package/esm2022/dom.mjs +57 -1
- package/esm2022/download.mjs +22 -1
- package/esm2022/file.mjs +54 -1
- package/esm2022/format-number.mjs +31 -3
- package/esm2022/format-text.mjs +73 -2
- package/esm2022/function-check-embed-frame.mjs +28 -1
- package/esm2022/pattern.mjs +83 -3
- package/esm2022/trace.mjs +8 -1
- package/esm2022/two-way-signal-object.mjs +14 -1
- package/esm2022/uri.mjs +22 -3
- package/esm2022/url-search-params.mjs +68 -1
- package/esm2022/url.mjs +10 -1
- package/esm2022/uuid.mjs +7 -1
- package/esm2022/xss-filter.mjs +14 -1
- package/fesm2022/libs-ui-utils.mjs +723 -21
- package/fesm2022/libs-ui-utils.mjs.map +1 -1
- package/file.d.ts +53 -0
- package/format-number.d.ts +29 -1
- package/format-text.d.ts +71 -0
- package/function-check-embed-frame.d.ts +22 -0
- package/package.json +2 -2
- package/pattern.d.ts +81 -1
- package/trace.d.ts +7 -0
- package/two-way-signal-object.d.ts +13 -0
- package/uri.d.ts +20 -0
- package/url-search-params.d.ts +67 -0
- package/url.d.ts +9 -0
- package/uuid.d.ts +6 -0
- package/xss-filter.d.ts +13 -0
package/README.md
CHANGED
|
@@ -1,3 +1,634 @@
|
|
|
1
|
-
|
|
1
|
+
# @libs-ui/utils
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Thư viện tập trung toàn bộ **utility functions** dùng chung cho các libs-ui trong project.
|
|
4
|
+
|
|
5
|
+
**Version**: `0.2.355-10`
|
|
6
|
+
|
|
7
|
+
## Giới thiệu
|
|
8
|
+
|
|
9
|
+
Thư viện `@libs-ui/utils` cung cấp các hàm tiện ích dùng chung (format, transform, validate...) để:
|
|
10
|
+
|
|
11
|
+
- Giảm trùng lặp code utility trong nhiều libs khác nhau
|
|
12
|
+
- Dễ bảo trì và mở rộng khi cần thêm utility mới
|
|
13
|
+
- Chuẩn hóa cách xử lý dữ liệu trong toàn bộ project
|
|
14
|
+
|
|
15
|
+
## Cài đặt
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @libs-ui/utils
|
|
19
|
+
# hoặc
|
|
20
|
+
yarn add @libs-ui/utils
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Sử dụng
|
|
24
|
+
|
|
25
|
+
### Import
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import {
|
|
29
|
+
isNil,
|
|
30
|
+
isEmpty,
|
|
31
|
+
get,
|
|
32
|
+
set,
|
|
33
|
+
cloneDeep,
|
|
34
|
+
keyBy,
|
|
35
|
+
groupBy,
|
|
36
|
+
range,
|
|
37
|
+
isEqual,
|
|
38
|
+
uniqBy,
|
|
39
|
+
base64Encode,
|
|
40
|
+
base64Decode,
|
|
41
|
+
convertBase64ToBlob,
|
|
42
|
+
convertFileToBase64,
|
|
43
|
+
UtilsCache,
|
|
44
|
+
addArrayToSet,
|
|
45
|
+
convertSetToArray,
|
|
46
|
+
colorContrastFromOrigin,
|
|
47
|
+
getColorById,
|
|
48
|
+
detectAndCleanNearWhiteColors,
|
|
49
|
+
UtilsCommunicateMicro,
|
|
50
|
+
encrypt3rd,
|
|
51
|
+
decrypt3rd,
|
|
52
|
+
setKeyCrypto3rd,
|
|
53
|
+
encrypt,
|
|
54
|
+
decrypt,
|
|
55
|
+
setKeyCrypto,
|
|
56
|
+
md5,
|
|
57
|
+
isDangerousObject,
|
|
58
|
+
isPrimitiveType,
|
|
59
|
+
isDOMObject,
|
|
60
|
+
isFrameworkObject,
|
|
61
|
+
getObjectSize,
|
|
62
|
+
getDayjs,
|
|
63
|
+
formatDate,
|
|
64
|
+
isDifferenceDay,
|
|
65
|
+
setDefaultTimeZone,
|
|
66
|
+
getDeviceInfo,
|
|
67
|
+
isTouchDevice,
|
|
68
|
+
getViewport,
|
|
69
|
+
setStylesElement,
|
|
70
|
+
downloadFileByUrl,
|
|
71
|
+
downloadFileByUrlUseXmlRequest,
|
|
72
|
+
} from '@libs-ui/utils';
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Ví dụ cơ bản
|
|
76
|
+
|
|
77
|
+
#### Base64 & File
|
|
78
|
+
|
|
79
|
+
````typescript
|
|
80
|
+
import { base64Encode, base64Decode, convertFileToBase64 } from '@libs-ui/utils';
|
|
81
|
+
|
|
82
|
+
// Mã hóa Unicode an toàn
|
|
83
|
+
const encoded = base64Encode('Xin chào 👋');
|
|
84
|
+
const decoded = base64Decode(encoded); // 'Xin chào 👋'
|
|
85
|
+
|
|
86
|
+
// Chuyển File sang Base64 để preview
|
|
87
|
+
const base64 = await convertFileToBase64(file);
|
|
88
|
+
// data:image/png;base64,iVBORw...
|
|
89
|
+
|
|
90
|
+
#### Language
|
|
91
|
+
```typescript
|
|
92
|
+
import { UtilsLanguageConstants } from '@libs-ui/utils';
|
|
93
|
+
|
|
94
|
+
// Dùng hằng số thay vì hardcode chuỗi
|
|
95
|
+
const viCode = UtilsLanguageConstants.VI; // 'vi'
|
|
96
|
+
const enCode = UtilsLanguageConstants.EN; // 'en'
|
|
97
|
+
const jaCode = UtilsLanguageConstants.JA; // 'ja'
|
|
98
|
+
|
|
99
|
+
// Tự động phát hiện ngôn ngữ trình duyệt (fallback về 'en')
|
|
100
|
+
const lang = UtilsLanguageConstants.defaultLang();
|
|
101
|
+
|
|
102
|
+
// Kiểm tra hỗ trợ
|
|
103
|
+
UtilsLanguageConstants.isSupported('vi'); // true
|
|
104
|
+
UtilsLanguageConstants.isSupported('xx'); // false
|
|
105
|
+
|
|
106
|
+
// Tùy chỉnh danh sách ngôn ngữ hỗ trợ (gọi một lần lúc khởi động)
|
|
107
|
+
UtilsLanguageConstants.setSupportedLanguages(['vi', 'en']);
|
|
108
|
+
|
|
109
|
+
#### Random & String Protection
|
|
110
|
+
```typescript
|
|
111
|
+
import { protectString, revealString, createUniqueRandomIntGenerator } from '@libs-ui/utils';
|
|
112
|
+
|
|
113
|
+
// Obfuscate nhẹ cổng giao tiếp
|
|
114
|
+
const hidden = protectString('user-token-abc123');
|
|
115
|
+
const plain = revealString(hidden); // 'user-token-abc123'
|
|
116
|
+
|
|
117
|
+
// Round-trip luôn trả về cỗi gốc
|
|
118
|
+
console.log(revealString(protectString('Xin chào')) === 'Xin chào'); // true
|
|
119
|
+
|
|
120
|
+
// Tạo số ngẫu nhiên không trùng trong 10 lần gần nhất
|
|
121
|
+
const nextId = createUniqueRandomIntGenerator(1, 100);
|
|
122
|
+
console.log(nextId()); // 42
|
|
123
|
+
console.log(nextId()); // 17 (khác 42)
|
|
124
|
+
|
|
125
|
+
#### Cache
|
|
126
|
+
```typescript
|
|
127
|
+
import { UtilsCache } from '@libs-ui/utils';
|
|
128
|
+
|
|
129
|
+
// LocalStorage (Đồng bộ)
|
|
130
|
+
UtilsCache.Set('key', { a: 1 }, 3600); // 1 giờ
|
|
131
|
+
const data = UtilsCache.Get('key');
|
|
132
|
+
|
|
133
|
+
// IndexedDB (Bất đồng bộ)
|
|
134
|
+
await UtilsCache.SetAsync('large_key', data);
|
|
135
|
+
const asyncData = await UtilsCache.GetAsync('large_key');
|
|
136
|
+
|
|
137
|
+
#### Collection
|
|
138
|
+
```typescript
|
|
139
|
+
import { addArrayToSet, convertSetToArray } from '@libs-ui/utils';
|
|
140
|
+
|
|
141
|
+
const s = new Set([1]);
|
|
142
|
+
addArrayToSet(s, [1, 2, 3]); // Set {1, 2, 3}
|
|
143
|
+
|
|
144
|
+
const arr = convertSetToArray(s, v => `Item ${v}`); // ["Item 1", "Item 2", "Item 3"]
|
|
145
|
+
|
|
146
|
+
#### Color
|
|
147
|
+
```typescript
|
|
148
|
+
import { colorContrastFromOrigin, getColorById } from '@libs-ui/utils';
|
|
149
|
+
|
|
150
|
+
// Tạo bảng màu
|
|
151
|
+
const palette = colorContrastFromOrigin('#226FF5');
|
|
152
|
+
|
|
153
|
+
// Lấy màu định danh theo ID
|
|
154
|
+
const userColor = getColorById('user_id_123');
|
|
155
|
+
|
|
156
|
+
/* ... */
|
|
157
|
+
|
|
158
|
+
#### Communicate Micro
|
|
159
|
+
```typescript
|
|
160
|
+
import { UtilsCommunicateMicro } from '@libs-ui/utils';
|
|
161
|
+
|
|
162
|
+
// Khởi tạo tại AppComponent
|
|
163
|
+
UtilsCommunicateMicro.initEvent(window, destroyRef);
|
|
164
|
+
|
|
165
|
+
// Lắng nghe
|
|
166
|
+
UtilsCommunicateMicro.GetMessage('DATA_SYNC').subscribe(e => {
|
|
167
|
+
console.log(e.data.response);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Gửi cho cha (ví dụ từ Iframe)
|
|
171
|
+
UtilsCommunicateMicro.PostMessageToParent({ type: 'DATA_SYNC', response: { id: 1 } });
|
|
172
|
+
|
|
173
|
+
#### Crypto 3rd
|
|
174
|
+
```typescript
|
|
175
|
+
import { encrypt3rd, decrypt3rd, setKeyCrypto3rd } from '@libs-ui/utils';
|
|
176
|
+
|
|
177
|
+
// Setup key (một lần)
|
|
178
|
+
setKeyCrypto3rd('12345678901234567890123456789012');
|
|
179
|
+
|
|
180
|
+
// Mã hóa
|
|
181
|
+
const secret = encrypt3rd('My Secret Data');
|
|
182
|
+
|
|
183
|
+
// Giải mã
|
|
184
|
+
const original = decrypt3rd(secret);
|
|
185
|
+
|
|
186
|
+
#### Crypto
|
|
187
|
+
```typescript
|
|
188
|
+
import { encrypt, decrypt, md5 } from '@libs-ui/utils';
|
|
189
|
+
|
|
190
|
+
// AES Internal
|
|
191
|
+
const secureData = encrypt('Secret');
|
|
192
|
+
const plain = decrypt(secureData);
|
|
193
|
+
|
|
194
|
+
// MD5 Hash
|
|
195
|
+
const hash = md5('hello');
|
|
196
|
+
|
|
197
|
+
#### Dangerous Object
|
|
198
|
+
```typescript
|
|
199
|
+
import { isDangerousObject, isPrimitiveType } from '@libs-ui/utils';
|
|
200
|
+
|
|
201
|
+
isDangerousObject(window); // true
|
|
202
|
+
isDangerousObject(document.body); // true
|
|
203
|
+
isPrimitiveType(123); // true
|
|
204
|
+
isPrimitiveType({}); // false
|
|
205
|
+
|
|
206
|
+
#### Data
|
|
207
|
+
```typescript
|
|
208
|
+
import { getObjectSize } from '@libs-ui/utils';
|
|
209
|
+
|
|
210
|
+
const size = getObjectSize({ a: 1 }); // "10 bytes"
|
|
211
|
+
|
|
212
|
+
#### Date
|
|
213
|
+
```typescript
|
|
214
|
+
import { formatDate, getDayjs } from '@libs-ui/utils';
|
|
215
|
+
|
|
216
|
+
// Format tiếng Việt
|
|
217
|
+
formatDate('2024-05-20', 'dmy', 'vi'); // "20 Thg 5, 2024"
|
|
218
|
+
|
|
219
|
+
// Lấy đối tượng Day.js (local timezone)
|
|
220
|
+
const now = getDayjs();
|
|
221
|
+
|
|
222
|
+
#### DOM
|
|
223
|
+
```typescript
|
|
224
|
+
import { getViewport, isTouchDevice } from '@libs-ui/utils';
|
|
225
|
+
|
|
226
|
+
const { width, height } = getViewport();
|
|
227
|
+
const isTouch = isTouchDevice();
|
|
228
|
+
|
|
229
|
+
#### Download
|
|
230
|
+
```typescript
|
|
231
|
+
import { downloadFileByUrl } from '@libs-ui/utils';
|
|
232
|
+
|
|
233
|
+
// Tải file PDF từ server
|
|
234
|
+
await downloadFileByUrl('https://example.com/report.pdf', 'report.pdf');
|
|
235
|
+
|
|
236
|
+
// Chỉ mở tầ mới (không download)
|
|
237
|
+
await downloadFileByUrl('https://example.com/doc.pdf', 'preview.pdf', true);
|
|
238
|
+
|
|
239
|
+
#### Regex Patterns
|
|
240
|
+
```typescript
|
|
241
|
+
import { patternEmail, patternMobilePhone, patternUrl } from '@libs-ui/utils';
|
|
242
|
+
|
|
243
|
+
// Kiểm tra email
|
|
244
|
+
const emailRe = patternEmail();
|
|
245
|
+
emailRe.test('user@gmail.com'); // true
|
|
246
|
+
|
|
247
|
+
// Kiểm tra số điện thoại VN
|
|
248
|
+
patternMobilePhone().test('0987654321'); // true
|
|
249
|
+
|
|
250
|
+
// Match pattern cụ thể
|
|
251
|
+
const templateRe = patternRuleFieldReplace(); // /[{]{2}[a-zA-Z_-]+[}]{2}/g
|
|
252
|
+
'hello {{name}}'.match(templateRe); // ['{{name}}']
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Trace Stack
|
|
256
|
+
```typescript
|
|
257
|
+
import { traceStack } from '@libs-ui/utils';
|
|
258
|
+
|
|
259
|
+
function a() {
|
|
260
|
+
b();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function b() {
|
|
264
|
+
console.log(traceStack());
|
|
265
|
+
// Output: ["a", "b"] (đã lọc các frame rác)
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Two-Way Signal Object
|
|
270
|
+
```typescript
|
|
271
|
+
import { convertObjectToSignal, convertSignalToObject } from '@libs-ui/utils';
|
|
272
|
+
|
|
273
|
+
const obj = { name: 'Alice' };
|
|
274
|
+
const reactive = convertObjectToSignal<any>(obj);
|
|
275
|
+
|
|
276
|
+
reactive().name.set('Bob');
|
|
277
|
+
|
|
278
|
+
const plain = convertSignalToObject(reactive);
|
|
279
|
+
console.log(plain.name); // 'Bob'
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### URI
|
|
283
|
+
```typescript
|
|
284
|
+
import { encodeURI, decodeURI, endCodeUrl } from '@libs-ui/utils';
|
|
285
|
+
|
|
286
|
+
// Mã hóa/Giải mã
|
|
287
|
+
const encoded = encodeURI('Xin chào & Hẹn gặp lại!');
|
|
288
|
+
const decoded = decodeURI(encoded);
|
|
289
|
+
|
|
290
|
+
// Query String builder
|
|
291
|
+
const qs = endCodeUrl({ id: 1, q: 'tag' }, false); // "?id=1&q=tag"
|
|
292
|
+
|
|
293
|
+
#### URL
|
|
294
|
+
```typescript
|
|
295
|
+
import { normalizeUrl } from '@libs-ui/utils';
|
|
296
|
+
|
|
297
|
+
// Chuẩn hóa đường dẫn URL (gộp dấu // dư thừa)
|
|
298
|
+
const clean = normalizeUrl('http://example.com//api///users');
|
|
299
|
+
// Output: "http://example.com/api/users"
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### UUID
|
|
303
|
+
```typescript
|
|
304
|
+
import { uuid } from '@libs-ui/utils';
|
|
305
|
+
|
|
306
|
+
// Tạo unique ID (MD5 hash - 32 character)
|
|
307
|
+
const newId = uuid();
|
|
308
|
+
// Output: "a1b2c3d4..."
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### XSS Filter
|
|
312
|
+
```typescript
|
|
313
|
+
import { updateFunctionXssFilter, xssFilter } from '@libs-ui/utils';
|
|
314
|
+
import DOMPurify from 'dompurify';
|
|
315
|
+
|
|
316
|
+
// 1. Cấu hình ban đầu (Ví dụ: trong app.component.ts)
|
|
317
|
+
updateFunctionXssFilter(async (data: string) => DOMPurify.sanitize(data));
|
|
318
|
+
|
|
319
|
+
// 2. Sử dụng ở mọi nơi để làm sạch HTML
|
|
320
|
+
const cleanHTML = await xssFilter('<script>evil()</script><b>Good</b>');
|
|
321
|
+
// Output: "<b>Good</b>"
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### URL Search Params
|
|
325
|
+
```typescript
|
|
326
|
+
import { UtilsUrlSearchParams } from '@libs-ui/utils';
|
|
327
|
+
|
|
328
|
+
const usp = new UtilsUrlSearchParams('?id=1&name=test');
|
|
329
|
+
console.log(usp.get('id')); // "1"
|
|
330
|
+
|
|
331
|
+
usp.set('page', '2');
|
|
332
|
+
console.log(usp.toString()); // "id=1&name=test&page=2"
|
|
333
|
+
```
|
|
334
|
+
```
|
|
335
|
+
```
|
|
336
|
+
```
|
|
337
|
+
```
|
|
338
|
+
```
|
|
339
|
+
```
|
|
340
|
+
```
|
|
341
|
+
```
|
|
342
|
+
```
|
|
343
|
+
````
|
|
344
|
+
|
|
345
|
+
````
|
|
346
|
+
|
|
347
|
+
#### Kiểm tra giá trị
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
import { isNil, isEmpty, isTruthy, isFalsy } from '@libs-ui/utils';
|
|
351
|
+
|
|
352
|
+
// Kiểm tra null/undefined
|
|
353
|
+
isNil(null); // true
|
|
354
|
+
isNil(undefined); // true
|
|
355
|
+
isNil(0); // false
|
|
356
|
+
|
|
357
|
+
// Kiểm tra rỗng
|
|
358
|
+
isEmpty(null); // true
|
|
359
|
+
isEmpty(''); // true
|
|
360
|
+
isEmpty({}); // true
|
|
361
|
+
isEmpty([]); // true
|
|
362
|
+
isEmpty({ a: 1 }); // false
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### Thao tác Object
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
import { get, set, cloneDeep } from '@libs-ui/utils';
|
|
369
|
+
|
|
370
|
+
const user = {
|
|
371
|
+
profile: {
|
|
372
|
+
name: 'John',
|
|
373
|
+
address: { city: 'Hanoi' },
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
// Lấy giá trị theo path
|
|
378
|
+
get(user, 'profile.name'); // 'John'
|
|
379
|
+
get(user, 'profile.address.city'); // 'Hanoi'
|
|
380
|
+
get(user, 'profile.email', 'N/A'); // 'N/A' (default value)
|
|
381
|
+
|
|
382
|
+
// Thiết lập giá trị theo path
|
|
383
|
+
set(user, 'profile.name', 'Jane');
|
|
384
|
+
set(user, 'profile.age', 25);
|
|
385
|
+
|
|
386
|
+
// Clone sâu
|
|
387
|
+
const cloned = cloneDeep(user);
|
|
388
|
+
cloned.profile.name = 'Bob'; // Không ảnh hưởng user gốc
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
#### Thao tác Array
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
import { keyBy, groupBy, range, uniqBy, isEqual } from '@libs-ui/utils';
|
|
395
|
+
|
|
396
|
+
const users = [
|
|
397
|
+
{ id: 1, name: 'John', type: 'admin' },
|
|
398
|
+
{ id: 2, name: 'Jane', type: 'user' },
|
|
399
|
+
{ id: 3, name: 'Bob', type: 'admin' },
|
|
400
|
+
];
|
|
401
|
+
|
|
402
|
+
// Chuyển array thành object
|
|
403
|
+
keyBy(users, 'id');
|
|
404
|
+
// { "1": {id:1,name:"John",type:"admin"}, "2": {...}, "3": {...} }
|
|
405
|
+
|
|
406
|
+
// Nhóm theo type
|
|
407
|
+
groupBy(users, 'type');
|
|
408
|
+
// { "admin": [{...}, {...}], "user": [{...}] }
|
|
409
|
+
|
|
410
|
+
// Tạo mảng số
|
|
411
|
+
range(5); // [0, 1, 2, 3, 4]
|
|
412
|
+
range(1, 5); // [1, 2, 3, 4]
|
|
413
|
+
range(0, 10, 2); // [0, 2, 4, 6, 8]
|
|
414
|
+
|
|
415
|
+
// Loại bỏ trùng lặp
|
|
416
|
+
uniqBy([{ id: 1 }, { id: 2 }, { id: 1 }], 'id'); // [{id:1}, {id:2}]
|
|
417
|
+
|
|
418
|
+
// So sánh deep equality
|
|
419
|
+
isEqual({ a: 1, b: 2 }, { a: 1, b: 2 }); // true
|
|
420
|
+
isEqual([1, 2, 3], [1, 2, 3]); // true
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
#### HTTP Query Params (Type-Safe)
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { UtilsHttpParamsRequest, UtilsHttpParamsRequestInstance } from '@libs-ui/utils';
|
|
427
|
+
|
|
428
|
+
// Định nghĩa interface cho params
|
|
429
|
+
interface SearchParams {
|
|
430
|
+
keyword: string;
|
|
431
|
+
page: number;
|
|
432
|
+
size: number;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// 1. Dùng fromObject với type safety
|
|
436
|
+
const params = new UtilsHttpParamsRequest<SearchParams>({
|
|
437
|
+
fromObject: { keyword: 'Angular', page: 1, size: 20 },
|
|
438
|
+
});
|
|
439
|
+
params.toString(); // keyword=Angular&page=1&size=20
|
|
440
|
+
|
|
441
|
+
// 2. Factory function (không cần new)
|
|
442
|
+
const params2 = UtilsHttpParamsRequestInstance<SearchParams>({
|
|
443
|
+
fromObject: { keyword: 'Angular', page: 1, size: 20 },
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// 3. Method chaining
|
|
447
|
+
const params3 = new UtilsHttpParamsRequest().set('page', 1).set('size', 10).set('sort', 'name');
|
|
448
|
+
|
|
449
|
+
params3.delete('sort');
|
|
450
|
+
params3.toString(); // page=1&size=10
|
|
451
|
+
|
|
452
|
+
// 4. Wrap HttpParams có sẵn
|
|
453
|
+
import { HttpParams } from '@angular/common/http';
|
|
454
|
+
const base = new HttpParams().set('version', 'v2');
|
|
455
|
+
const wrapped = new UtilsHttpParamsRequest(undefined, base);
|
|
456
|
+
wrapped.get('version'); // 'v2'
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### GET_PATH_VARIABLE — Type-Safe Path Params
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
import { GET_PATH_VARIABLE } from '@libs-ui/utils';
|
|
463
|
+
|
|
464
|
+
interface UserResource {
|
|
465
|
+
userId: number;
|
|
466
|
+
orgId: string;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Tạo type với pattern "pathVariable-{key}"
|
|
470
|
+
type UserPathParams = GET_PATH_VARIABLE<UserResource>;
|
|
471
|
+
// Tương đương: { "pathVariable-userid": number; "pathVariable-orgid": string }
|
|
472
|
+
|
|
473
|
+
const pathParams: UserPathParams = {
|
|
474
|
+
'pathVariable-userid': 123,
|
|
475
|
+
'pathVariable-orgid': 'org-abc',
|
|
476
|
+
};
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Important Notes
|
|
480
|
+
|
|
481
|
+
⚠️ **Lưu ý quan trọng khi sử dụng**:
|
|
482
|
+
|
|
483
|
+
- Các functions hỗ trợ unwrap Signal tự động (trừ khi dùng option `ignoreUnWrapSignal`).
|
|
484
|
+
- `get()` và `set()` hỗ trợ path dạng string (vd: `"user.profile.name"`) hoặc array (vd: `["user", "profile", "name"]`).
|
|
485
|
+
- `cloneDeep()` có thể clone Signal, Date, RegExp, Map, Set và các object phức tạp khác.
|
|
486
|
+
- `isEqual()` có thể so sánh deep equality cho objects và arrays.
|
|
487
|
+
- `UtilsHttpParamsRequest` kế thừa `HttpParams` — compatible 100% với Angular HttpClient.
|
|
488
|
+
- `HttpParams` của Angular là **immutable**; `UtilsHttpParamsRequest` xử lý điều này nội bộ (tự assign lại `this.params` sau mỗi mutation).
|
|
489
|
+
|
|
490
|
+
## API Reference
|
|
491
|
+
|
|
492
|
+
Xem chi tiết API tại [Documentation](./docs/utils/utils.md) hoặc [Demo Live](http://localhost:4500/utils/helpers).
|
|
493
|
+
|
|
494
|
+
### Các Functions chính
|
|
495
|
+
|
|
496
|
+
| Function | Mô tả |
|
|
497
|
+
| ------------------------------------------------------- | -------------------------------------------- |
|
|
498
|
+
| `isNil(value, options?)` | Kiểm tra giá trị có phải null hoặc undefined |
|
|
499
|
+
| `isEmpty(value, options?)` | Kiểm tra giá trị có rỗng không |
|
|
500
|
+
| `isTruthy(value, options?)` | Kiểm tra giá trị truthy |
|
|
501
|
+
| `isFalsy(value, options?)` | Kiểm tra giá trị falsy |
|
|
502
|
+
| `get(obj, path, defaultValue?, keepLastValueIfSignal?)` | Lấy giá trị theo path |
|
|
503
|
+
| `set(obj, path, value, options?)` | Thiết lập giá trị theo path |
|
|
504
|
+
| `cloneDeep(data, options?, seen?)` | Clone sâu object/array |
|
|
505
|
+
| `keyBy(data, key)` | Chuyển array thành object |
|
|
506
|
+
| `groupBy(data, key)` | Nhóm array theo key |
|
|
507
|
+
| `range(start, end?, step?)` | Tạo mảng số |
|
|
508
|
+
| `isEqual(value1, value2, options?)` | So sánh deep equality |
|
|
509
|
+
| `uniqBy(data, key?)` | Loại bỏ trùng lặp |
|
|
510
|
+
| `omitBy(objData, predicate)` | Loại bỏ thuộc tính theo điều kiện |
|
|
511
|
+
| `generateInterface(obj, interfaceName)` | Tạo interface từ object |
|
|
512
|
+
| `base64Encode(value)` | Mã hóa Base64 (hỗ trợ Unicode) |
|
|
513
|
+
| `base64Decode(value)` | Giải mã Base64 (hỗ trợ Unicode) |
|
|
514
|
+
| `convertBase64ToBlob(data)` | Chuyển Base64 sang Blob |
|
|
515
|
+
| `convertFileToBase64(file)` | Chuyển File sang Base64 string |
|
|
516
|
+
| `UtilsCache` | Quản lý Cache (Sync & Async) |
|
|
517
|
+
| `addArrayToSet(set, data)` | Thêm mảng vào Set |
|
|
518
|
+
| `convertSetToArray(set, map?)` | Chuyển Set sang Array |
|
|
519
|
+
| `colorContrastFromOrigin(color)` | Tạo bảng sắc độ (shades/tints) |
|
|
520
|
+
| `getColorById(str)` | Hash chuỗi thành màu cố định |
|
|
521
|
+
| `detectAndCleanNearWhiteColors(style)` | Làm sạch CSS style khỏi màu gần trắng |
|
|
522
|
+
| `UtilsCommunicateMicro` | Giao tiếp Cross-window (mã hóa) |
|
|
523
|
+
| `encrypt3rd(data)` | Mã hóa AES-CBC |
|
|
524
|
+
| `decrypt3rd(data)` | Giải mã AES-CBC |
|
|
525
|
+
| `encrypt(data)` | Mã hóa AES nội bộ |
|
|
526
|
+
| `md5(data)` | Hash MD5 |
|
|
527
|
+
| `isDangerousObject(obj)` | Kiểm tra Window/DOM/Global |
|
|
528
|
+
| `isPrimitiveType(val)` | Kiểm tra kiểu dữ liệu nguyên thủy |
|
|
529
|
+
| `getObjectSize(obj)` | Đo dung lượng object |
|
|
530
|
+
| `formatDate(date, format?)` | Định dạng ngày tháng |
|
|
531
|
+
| `getDayjs(config?)` | Khởi tạo Day.js instance |
|
|
532
|
+
| `getDeviceInfo()` | Lấy thông tin thiết bị |
|
|
533
|
+
| `isTouchDevice()` | Kiểm tra thiết bị cảm ứng |
|
|
534
|
+
| `getViewport()` | Lấy kích thước Viewport |
|
|
535
|
+
| `downloadFileByUrl(url, name, onlyOpen?)` | Tải file từ URL |
|
|
536
|
+
| `downloadFileByUrlUseXmlRequest(url, name)` | Tải file bằng XMLHttpRequest |
|
|
537
|
+
| `downloadImageFromELement(img, type?, name?)` | Lưu ảnh từ thẻ img |
|
|
538
|
+
| `isTypeImage(file)` | Kiểm tra Blob/File là ảnh |
|
|
539
|
+
| `isTypeVideo(file)` | Kiểm tra Blob/File là video |
|
|
540
|
+
| `getFileExtension(file)` | Lấy extension của file |
|
|
541
|
+
| `getLabelBySizeFile(size, toFixed?)` | Format kích thước byte |
|
|
542
|
+
| `convertBlobToFile(blob, name?)` | Chuyển Blob thành File |
|
|
543
|
+
| `formatNumber(value)` | Chuẩn hóa chuỗi số theo locale |
|
|
544
|
+
| `viewDataNumberByLanguage(val, neg, fixed?, ...)` | Định dạng số theo VI/EN locale |
|
|
545
|
+
| `UtilsLanguageConstants.{KEY}` | Hằng số mã ngôn ngữ ISO 639-1 (27 ngôn ngữ) |
|
|
546
|
+
| `UtilsLanguageConstants.defaultLang()` | Tự dò ngôn ngữ trình duyệt, fallback 'en' |
|
|
547
|
+
| `UtilsLanguageConstants.isSupported(lang)` | Kiểm tra ngôn ngữ có được hỗ trợ |
|
|
548
|
+
| `UtilsLanguageConstants.setSupportedLanguages(langs)` | Ghi đè danh sách ngôn ngữ hỗ trợ |
|
|
549
|
+
| `protectString(input)` | XOR + reverse + base64 encode (obfuscation) |
|
|
550
|
+
| `revealString(encoded)` | Giải mã ngược lại protectString |
|
|
551
|
+
| `createUniqueRandomIntGenerator(min, max)` | Factory tạo số ngẫu nhiên không trùng (10 lần) |
|
|
552
|
+
| `patternEmail()` | Regex kiểm tra email chuẩn |
|
|
553
|
+
| `patternUrl()` | Regex kiểm tra URL đầy đủ |
|
|
554
|
+
| `patternMobilePhone()` | Regex kiểm tra SĐT di động Việt Nam |
|
|
555
|
+
| `patternNameUtf8()` | Regex hỗ trợ tên tiếng Việt có dấu |
|
|
556
|
+
| `patternEmoji()` | Regex phát hiện ký tự emoji (global) |
|
|
557
|
+
| `traceStack()` | Trích xuất call stack sạch (lọc rác) |
|
|
558
|
+
| `convertObjectToSignal()` | Biến object thành cấu trúc Signals lồng nhau |
|
|
559
|
+
| `convertSignalToObject()` | Chuyển cấu trúc signals về plain object |
|
|
560
|
+
| `unwrapSignal()` | Lấy giá trị cuối cùng từ (lồng) signal |
|
|
561
|
+
| `normalizeUrl(rawUrl)` | Chuẩn hóa URL, gộp dấu // trong pathname |
|
|
562
|
+
| `uuid()` | Tạo chuỗi định danh duy nhất (MD5 hash) |
|
|
563
|
+
| `xssFilter(data)` | Lọc chuỗi HTML khỏi XSS thông qua hàm custom |
|
|
564
|
+
| `updateFunctionXssFilter(fn)` | Cập nhật custom implementation cho xssFilter |
|
|
565
|
+
|
|
566
|
+
## Demo
|
|
567
|
+
|
|
568
|
+
- **Local Utilities**: [http://localhost:4500/utils/helpers](http://localhost:4500/utils/helpers)
|
|
569
|
+
- **Local Base64**: [http://localhost:4500/utils/base64](http://localhost:4500/utils/base64)
|
|
570
|
+
- **Local Cache**: [http://localhost:4500/utils/cache](http://localhost:4500/utils/cache)
|
|
571
|
+
- **Local Collection**: [http://localhost:4500/utils/collection](http://localhost:4500/utils/collection)
|
|
572
|
+
- **Local Color**: [http://localhost:4500/utils/color](http://localhost:4500/utils/color)
|
|
573
|
+
- **Local Micro Comms**: [http://localhost:4500/utils/communicate-micro](http://localhost:4500/utils/communicate-micro)
|
|
574
|
+
- **Local Crypto 3rd**: [http://localhost:4500/utils/crypto-3rd](http://localhost:4500/utils/crypto-3rd)
|
|
575
|
+
- **Local Crypto**: [http://localhost:4500/utils/crypto](http://localhost:4500/utils/crypto)
|
|
576
|
+
- **Local Dangerous Object**: [http://localhost:4500/utils/dangerous-object](http://localhost:4500/utils/dangerous-object)
|
|
577
|
+
- **Local Data**: [http://localhost:4500/utils/data](http://localhost:4500/utils/data)
|
|
578
|
+
- **Local Date**: [http://localhost:4500/utils/date](http://localhost:4500/utils/date)
|
|
579
|
+
- **Local DOM**: [http://localhost:4500/utils/dom](http://localhost:4500/utils/dom)
|
|
580
|
+
- **Local Download**: [http://localhost:4500/utils/download](http://localhost:4500/utils/download)
|
|
581
|
+
- **Local File**: [http://localhost:4500/utils/file](http://localhost:4500/utils/file)
|
|
582
|
+
- **Local Format Number**: [http://localhost:4500/utils/format-number](http://localhost:4500/utils/format-number)
|
|
583
|
+
- **Local Format Text**: [http://localhost:4500/utils/format-text](http://localhost:4500/utils/format-text)
|
|
584
|
+
- **Local Embed Frame**: [http://localhost:4500/utils/embed-frame](http://localhost:4500/utils/embed-frame)
|
|
585
|
+
- **Local Smart Axis Scale**: [http://localhost:4500/utils/smart-axis-scale](http://localhost:4500/utils/smart-axis-scale)
|
|
586
|
+
- **Local Language**: [http://localhost:4500/utils/language](http://localhost:4500/utils/language)
|
|
587
|
+
- **Local Random & String Protection**: [http://localhost:4500/utils/random](http://localhost:4500/utils/random)
|
|
588
|
+
- **Local Patterns (Regex)**: [http://localhost:4500/utils/pattern](http://localhost:4500/utils/pattern)
|
|
589
|
+
- **Local Trace Stack**: [http://localhost:4500/utils/trace](http://localhost:4500/utils/trace)
|
|
590
|
+
- **Local Two-Way Signal Object**: [http://localhost:4500/utils/two-way-signal-object](http://localhost:4500/utils/two-way-signal-object)
|
|
591
|
+
- **Local URI Utilities**: [http://localhost:4500/utils/uri](http://localhost:4500/utils/uri)
|
|
592
|
+
- **Local URL Utilities**: [http://localhost:4500/utils/url](http://localhost:4500/utils/url)
|
|
593
|
+
- **Local URL Search Params**: [http://localhost:4500/utils/url-search-params](http://localhost:4500/utils/url-search-params)
|
|
594
|
+
- **Local UUID Utilities**: [http://localhost:4500/utils/uuid](http://localhost:4500/utils/uuid)
|
|
595
|
+
- **Local Xss Filter Utilities**: [http://localhost:4500/utils/xss-filter](http://localhost:4500/utils/xss-filter)
|
|
596
|
+
|
|
597
|
+
### HTTP Params
|
|
598
|
+
|
|
599
|
+
| Class / Type | Mô tả |
|
|
600
|
+
| ----------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
601
|
+
| `UtilsHttpParamsRequest<Type>` | Wrapper type-safe cho Angular HttpParams — hỗ trợ method chaining, fromObject với generic type |
|
|
602
|
+
| `UtilsHttpParamsRequestInstance<Type>()` | Factory function tạo `UtilsHttpParamsRequest` không cần `new` |
|
|
603
|
+
| `GET_PATH_VARIABLE<TypePath, TypeOther?>` | Utility type tạo map path-variable từ interface (pattern: `pathVariable-{key}`) |
|
|
604
|
+
| `HttpParamsOptions<Type>` | Interface options cho constructor (`fromString`, `fromObject`, `encoder`) |
|
|
605
|
+
|
|
606
|
+
### InjectionTokens
|
|
607
|
+
|
|
608
|
+
| Token | Mô tả |
|
|
609
|
+
| -------------------------------------------------- | ----------------------------------------------------- |
|
|
610
|
+
| `LINK_IMAGE_ERROR_TOKEN_INJECT` | InjectionToken cho link ảnh fallback |
|
|
611
|
+
| `PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT` | InjectionToken cấu hình mặc định process bar standard |
|
|
612
|
+
| `PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT` | InjectionToken cấu hình mặc định process bar steps |
|
|
613
|
+
|
|
614
|
+
## Demo
|
|
615
|
+
|
|
616
|
+
- **Helpers utilities**: [http://localhost:4500/utils/helpers](http://localhost:4500/utils/helpers)
|
|
617
|
+
- **HTTP Params**: [http://localhost:4500/utils/http-params](http://localhost:4500/utils/http-params)
|
|
618
|
+
- **Injection Tokens**: [http://localhost:4500/utils/inject-token](http://localhost:4500/utils/inject-token)
|
|
619
|
+
- **Key Cache**: [http://localhost:4500/utils/key-cache](http://localhost:4500/utils/key-cache)
|
|
620
|
+
- **Key Code**: [http://localhost:4500/utils/key-code](http://localhost:4500/utils/key-code)
|
|
621
|
+
- **Production**: (Chưa có)
|
|
622
|
+
|
|
623
|
+
## Công nghệ sử dụng
|
|
624
|
+
|
|
625
|
+
- **Angular**: >=18.0.0
|
|
626
|
+
- **TypeScript**: Latest
|
|
627
|
+
- **RxJS**: ~7.8.0
|
|
628
|
+
- **dayjs**: 1.11.5
|
|
629
|
+
- **crypto-es**: ^2.1.0
|
|
630
|
+
|
|
631
|
+
## Tài liệu
|
|
632
|
+
|
|
633
|
+
Xem thêm tài liệu chi tiết tại [docs/utils/utils.md](../../docs/utils/utils.md).
|
|
634
|
+
````
|
package/base64.d.ts
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mã hóa chuỗi thành Base64 (có hỗ trợ ký tự đặc biệt qua encodeURI)
|
|
3
|
+
* @param value Chuỗi cần mã hóa
|
|
4
|
+
* @returns Chuỗi đã mã hóa Base64
|
|
5
|
+
*/
|
|
1
6
|
export declare const base64Encode: (value: string) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Giải mã chuỗi Base64 (có hỗ trợ ký tự đặc biệt qua decodeURI)
|
|
9
|
+
* @param value Chuỗi Base64 cần giải mã
|
|
10
|
+
* @returns Chuỗi đã giải mã
|
|
11
|
+
*/
|
|
2
12
|
export declare const base64Decode: (value: string) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Chuyển đổi dữ liệu Base64 thành Blob
|
|
15
|
+
* @param dataBase64 Dữ liệu Base64 (có thể bao gồm marker ;base64,)
|
|
16
|
+
* @returns Blob tương ứng
|
|
17
|
+
*/
|
|
3
18
|
export declare const convertBase64ToBlob: (dataBase64: string) => Blob;
|
|
19
|
+
/**
|
|
20
|
+
* Chuyển đổi File thành Base64 string hoặc Object URL tùy loại file
|
|
21
|
+
* @param file Đối tượng File cần chuyển đổi
|
|
22
|
+
* @returns Nếu là ảnh, trả về Base64 string. Ngược lại trả về Object URL.
|
|
23
|
+
*/
|
|
4
24
|
export declare const convertFileToBase64_ObjectUrl: (file: File) => Promise<string | ArrayBuffer>;
|
|
25
|
+
/**
|
|
26
|
+
* Chuyển đổi File thành Base64 string
|
|
27
|
+
* @param file Đối tượng File cần chuyển đổi
|
|
28
|
+
* @returns Promise chứa chuỗi Base64
|
|
29
|
+
*/
|
|
5
30
|
export declare const convertFileToBase64: (file: File) => Promise<string | ArrayBuffer>;
|