@libs-ui/utils
v0.2.357-18
Published
> Thư viện tập trung toàn bộ **utility functions** dùng chung cho các libs-ui trong project.
Readme
@libs-ui/utils
Thư viện tập trung toàn bộ utility functions dùng chung cho các libs-ui trong project.
Version: 0.2.355-10
Giới thiệu
Thư viện @libs-ui/utils cung cấp các hàm tiện ích dùng chung (format, transform, validate...) để:
- Giảm trùng lặp code utility trong nhiều libs khác nhau
- Dễ bảo trì và mở rộng khi cần thêm utility mới
- Chuẩn hóa cách xử lý dữ liệu trong toàn bộ project
Cài đặt
npm install @libs-ui/utils
# hoặc
yarn add @libs-ui/utilsSử dụng
Import
import {
isNil,
isEmpty,
get,
set,
cloneDeep,
keyBy,
groupBy,
range,
isEqual,
uniqBy,
base64Encode,
base64Decode,
convertBase64ToBlob,
convertFileToBase64,
UtilsCache,
addArrayToSet,
convertSetToArray,
colorContrastFromOrigin,
getColorById,
detectAndCleanNearWhiteColors,
UtilsCommunicateMicro,
encrypt3rd,
decrypt3rd,
setKeyCrypto3rd,
encrypt,
decrypt,
setKeyCrypto,
md5,
isDangerousObject,
isPrimitiveType,
isDOMObject,
isFrameworkObject,
getObjectSize,
getDayjs,
formatDate,
isDifferenceDay,
setDefaultTimeZone,
getDeviceInfo,
isTouchDevice,
getViewport,
setStylesElement,
downloadFileByUrl,
downloadFileByUrlUseXmlRequest,
UtilsLanguageConstants,
protectString,
revealString,
createUniqueRandomIntGenerator,
patternEmail,
patternMobilePhone,
patternUrl,
patternRuleFieldReplace,
patternGetFieldByRuleFieldReplace,
traceStack,
convertObjectToSignal,
convertSignalToObject,
unwrapSignal,
watchSignalEffect,
encodeURI,
decodeURI,
endCodeUrl,
normalizeUrl,
uuid,
xssFilter,
updateFunctionXssFilter,
UtilsUrlSearchParams,
formatNumber,
viewDataNumberByLanguage,
isTypeImage,
isTypeVideo,
isTypeAudio,
getFileExtension,
getLabelBySizeFile,
convertBlobToFile,
convertUrlToFile,
highlightByKeyword,
fullNameFormat,
capitalize,
firstLetterToUpperCase,
escapeHtml,
decodeEscapeHtml,
deleteUnicode,
removeEmoji,
formatTextCompare,
getSmartAxisScale,
isEmbedFrame,
updateFunctionCheckEmbedFrame,
getKeyCacheByArrayObject,
UtilsKeyCodeConstant,
LINK_IMAGE_ERROR_TOKEN_INJECT,
PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT,
PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT,
} from '@libs-ui/utils';Ví dụ cơ bản
Base64 & File
import { base64Encode, base64Decode, convertFileToBase64 } from '@libs-ui/utils';
// Mã hóa Unicode an toàn
const encoded = base64Encode('Xin chào 👋');
const decoded = base64Decode(encoded); // 'Xin chào 👋'
// Chuyển File sang Base64 để preview
const base64 = await convertFileToBase64(file);
// data:image/png;base64,iVBORw...Language
import { UtilsLanguageConstants } from '@libs-ui/utils';
// Dùng hằng số thay vì hardcode chuỗi
const viCode = UtilsLanguageConstants.VI; // 'vi'
const enCode = UtilsLanguageConstants.EN; // 'en'
const jaCode = UtilsLanguageConstants.JA; // 'ja'
// Tự động phát hiện ngôn ngữ trình duyệt (đọc navigator.language, fallback về 'en')
const lang = UtilsLanguageConstants.defaultLang();
// Kiểm tra ngôn ngữ có nằm trong danh sách hỗ trợ không
UtilsLanguageConstants.isSupported('vi'); // true
UtilsLanguageConstants.isSupported('xx'); // false
// Ghi đè toàn bộ danh sách ngôn ngữ hỗ trợ (gọi 1 lần lúc khởi động app)
UtilsLanguageConstants.setSupportedLanguages(['vi', 'en']);
UtilsLanguageConstants.isSupported('ja'); // false (đã bị loại khỏi danh sách)Random & String Protection
import { protectString, revealString, createUniqueRandomIntGenerator } from '@libs-ui/utils';
// Obfuscate nhẹ (XOR + reverse + base64) — KHÔNG dùng cho dữ liệu nhạy cảm thật sự
const hidden = protectString('user-token-abc123');
const plain = revealString(hidden); // 'user-token-abc123'
// Round-trip luôn trả về đúng chuỗi gốc
console.log(revealString(protectString('Xin chào')) === 'Xin chào'); // true
// Factory tạo số nguyên ngẫu nhiên không trùng trong 10 lần gần nhất
const nextId = createUniqueRandomIntGenerator(1, 100);
console.log(nextId()); // ví dụ: 42
console.log(nextId()); // ví dụ: 17 (khác 42)Cache
import { UtilsCache } from '@libs-ui/utils';
// LocalStorage (Đồng bộ)
UtilsCache.Set('key', { a: 1 }, 3600); // 1 giờ
const data = UtilsCache.Get('key');
// IndexedDB (Bất đồng bộ)
await UtilsCache.SetAsync('large_key', data);
const asyncData = await UtilsCache.GetAsync('large_key');Collection
import { addArrayToSet, convertSetToArray } from '@libs-ui/utils';
const s = new Set([1]);
addArrayToSet(s, [1, 2, 3]); // Set {1, 2, 3}
const arr = convertSetToArray(s, (v) => `Item ${v}`); // ["Item 1", "Item 2", "Item 3"]Color
import { colorContrastFromOrigin, getColorById } from '@libs-ui/utils';
// Tạo bảng màu
const palette = colorContrastFromOrigin('#226FF5');
// Lấy màu định danh theo ID
const userColor = getColorById('user_id_123');Communicate Micro
import { UtilsCommunicateMicro } from '@libs-ui/utils';
// Khởi tạo tại AppComponent
UtilsCommunicateMicro.initEvent(window, destroyRef);
// Lắng nghe
UtilsCommunicateMicro.GetMessage('DATA_SYNC').subscribe((e) => {
console.log(e.data.response);
});
// Gửi cho cha (ví dụ từ Iframe)
UtilsCommunicateMicro.PostMessageToParent({ type: 'DATA_SYNC', response: { id: 1 } });Crypto 3rd
import { encrypt3rd, decrypt3rd, setKeyCrypto3rd } from '@libs-ui/utils';
// Setup key (một lần)
setKeyCrypto3rd('12345678901234567890123456789012');
// Mã hóa
const secret = encrypt3rd('My Secret Data');
// Giải mã
const original = decrypt3rd(secret);Crypto
import { encrypt, decrypt, md5 } from '@libs-ui/utils';
// AES Internal
const secureData = encrypt('Secret');
const plain = decrypt(secureData);
// MD5 Hash
const hash = md5('hello');Dangerous Object
import { isDangerousObject, isPrimitiveType } from '@libs-ui/utils';
isDangerousObject(window); // true
isDangerousObject(document.body); // true
isPrimitiveType(123); // true
isPrimitiveType({}); // falseData
import { getObjectSize } from '@libs-ui/utils';
const size = getObjectSize({ a: 1 }); // "10 bytes"Date
import { formatDate, getDayjs } from '@libs-ui/utils';
// Format tiếng Việt
formatDate('2024-05-20', 'dmy', 'vi'); // "20 Thg 5, 2024"
// Lấy đối tượng Day.js (local timezone)
const now = getDayjs();DOM
import { getViewport, isTouchDevice } from '@libs-ui/utils';
const { width, height } = getViewport();
const isTouch = isTouchDevice();Format Number
import { formatNumber, viewDataNumberByLanguage } from '@libs-ui/utils';
// Chuẩn hóa chuỗi số theo locale hiện tại về dạng parseable (bỏ dấu phân cách locale)
formatNumber('1,234,567'); // EN: "1234567"
formatNumber('1.234.567,89'); // VI: "1234567.89"
// Định dạng số hiển thị theo ngôn ngữ (VI dùng dấu chấm nghìn + phẩy thập phân, EN ngược lại)
viewDataNumberByLanguage(1234567.891, true, 2); // VI (mặc định theo cache): "1.234.567,89"
viewDataNumberByLanguage(1234567.891, true, 2, false, false, 'en'); // EN: "1,234,567.89"
viewDataNumberByLanguage(-100, false); // acceptNegativeValue = false → 0File
import { isTypeImage, getFileExtension, getLabelBySizeFile, convertBlobToFile, convertUrlToFile } from '@libs-ui/utils';
// Kiểm tra loại file qua MIME type
isTypeImage(file); // true nếu file.type khớp "image/*"
// Lấy extension (hỗ trợ cả File chuẩn và IFile nội bộ)
getFileExtension(file); // "png", "pdf"...
// Format dung lượng file dễ đọc
getLabelBySizeFile(500000); // " 488.28 KB"
getLabelBySizeFile(5 * 1024 * 1024); // " 5.00 MB"
// Blob → File (tự sinh tên bằng uuid nếu không truyền fileName)
const newFile = convertBlobToFile(blob, 'avatar.png');
// Tải file từ URL rồi convert thành đối tượng File
const downloaded = await convertUrlToFile('https://example.com/image.png', 'image.png');Download
import { downloadFileByUrl } from '@libs-ui/utils';
// Tải file PDF từ server
await downloadFileByUrl('https://example.com/report.pdf', 'report.pdf');
// Chỉ mở tab mới (không download)
await downloadFileByUrl('https://example.com/doc.pdf', 'preview.pdf', true);Regex Patterns
import { patternEmail, patternMobilePhone, patternRuleFieldReplace, patternGetFieldByRuleFieldReplace } from '@libs-ui/utils';
// Kiểm tra email
patternEmail().test('[email protected]'); // true
// Kiểm tra số điện thoại di động Việt Nam (0xx, 84xx, +84xx)
patternMobilePhone().test('0987654321'); // true
patternMobilePhone().test('+84987654321'); // true
// Trích xuất biến dạng {{field}} trong template string
const template = 'Xin chào {{user_name}}, chào mừng đến với {{app_name}}!';
const markers = template.match(patternRuleFieldReplace()); // ['{{user_name}}', '{{app_name}}']
const fields = markers?.map((m) => m.match(patternGetFieldByRuleFieldReplace())?.[0]); // ['user_name', 'app_name']Format Text (highlight, capitalize, escape, unicode, emoji)
import { highlightByKeyword, fullNameFormat, capitalize, firstLetterToUpperCase, escapeHtml, decodeEscapeHtml, deleteUnicode, removeEmoji, formatTextCompare } from '@libs-ui/utils';
// Highlight từ khóa — Unicode-insensitive (tìm "nguyen" vẫn khớp "nguyên"), trả về chuỗi HTML
highlightByKeyword(' nguyễn văn an 😀🎉 ', 'nguyễn');
// ' <span class="bg-[#19344a] text-white">nguyễn</span> văn an 😀🎉 '
// Chuẩn hóa họ tên: capitalize + trim + xóa emoji + xóa khoảng trắng thừa
fullNameFormat(' nguyễn văn an '); // 'Nguyễn Văn An'
// Viết hoa chữ cái đầu mỗi từ / chỉ chữ đầu tiên
capitalize('hello world'); // 'Hello World'
firstLetterToUpperCase('hello'); // 'Hello'
// Escape / Decode HTML entities (chống XSS khi hiển thị nội dung do user nhập)
escapeHtml('<script>alert(1)</script>'); // '<script>alert(1)</script>'
escapeHtml('a & b'); // 'a & b'
decodeEscapeHtml('<b>Hello</b>'); // '<b>Hello</b>'
// Xóa dấu tiếng Việt (Latin hóa, hỗ trợ cả hoa/thường)
deleteUnicode('Nguyễn Văn An'); // 'Nguyen Van An'
// Xóa toàn bộ emoji khỏi chuỗi
removeEmoji('Hello 😀 World'); // 'Hello World'
// Chuẩn hóa Unicode NFC để so sánh chuỗi nhất quán
typeof formatTextCompare('café'); // 'string'Trace Stack
import { traceStack } from '@libs-ui/utils';
function first() {
second();
}
function second() {
const stack = traceStack();
console.log('Call path:', stack.join(' -> '));
// Output: "Call path: first -> second"
}
first();Two-Way Signal Object
import { convertObjectToSignal, convertSignalToObject, unwrapSignal } from '@libs-ui/utils';
// Plain object từ API
const source = { name: 'Alice', age: 25 };
// 1. Chuyển thành signal (deep signals) — truyền true, true để .set() được cả giá trị nguyên thủy
const reactive = convertObjectToSignal<any>(source, true, true);
reactive().name.set('Bob');
// 2. Chuyển ngược lại object thuần để gửi API
const plain = convertSignalToObject(reactive);
console.log(plain.name); // 'Bob'
// 3. Unwrap signal lồng nhiều lớp (kể cả signal(signal(signal(...))))
const heavySignal = signal(signal(signal('Deep Value')));
console.log(unwrapSignal(heavySignal)); // 'Deep Value'
// 4. Touch nhiều signal cùng lúc để đăng ký dependency bên trong effect()
// (dùng khi muốn effect chạy lại mỗi khi BẤT KỲ signal nào thay đổi mà không cần giá trị)
effect(() => {
watchSignalEffect(signalA, signalB, signalC);
console.log('Một trong các signal đã thay đổi');
});URI
import { encodeURI, decodeURI, endCodeUrl } from '@libs-ui/utils';
// Mã hóa/Giải mã
const original = 'Xin chào & Hẹn gặp lại!';
const encoded = encodeURI(original);
const decoded = decodeURI(encoded);
console.log(decoded === original); // true
// Query String builder — tự loại bỏ giá trị null/undefined/rỗng
const qs = endCodeUrl({ id: 1, q: 'tag', empty: '' }, false); // "?id=1&q=tag"
const body = endCodeUrl({ id: 1 }, true); // "id=1" (không có dấu ? khi isBody = true)URL
import { normalizeUrl } from '@libs-ui/utils';
// Chuẩn hóa đường dẫn URL (chỉ gộp dấu // dư thừa trong pathname, giữ nguyên protocol)
const clean = normalizeUrl('http://example.com//api///users');
// Output: "http://example.com/api/users"URL Search Params
import { UtilsUrlSearchParams } from '@libs-ui/utils';
const usp = new UtilsUrlSearchParams('page?id=123&name=test&status=active');
console.log(usp.get('id')); // "123"
usp.set('status', 'inactive');
usp.set('new', 'true');
console.log(usp.toString()); // "id=123&name=test&new=true&status=inactive" (auto-sort theo key)
// So sánh 2 bộ tham số — không quan tâm thứ tự
UtilsUrlSearchParams.getInstance().compareParams('a=1&b=2', 'b=2&a=1'); // trueUUID
import { uuid } from '@libs-ui/utils';
// Tạo unique ID (băm MD5, 32 ký tự) — không phải chuẩn UUID v4
const newId = uuid();
// Output: "a1b2c3d4..." (32 ký tự alphanumeric)XSS Filter
import { updateFunctionXssFilter, xssFilter } from '@libs-ui/utils';
import DOMPurify from 'dompurify';
// 1. Cấu hình ban đầu — gọi 1 lần lúc khởi động app (vd: APP_INITIALIZER)
// Mặc định xssFilter() KHÔNG lọc gì cả, chỉ trả về đúng chuỗi gốc cho tới khi được cấu hình
updateFunctionXssFilter(async (data: string) => DOMPurify.sanitize(data));
// 2. Sử dụng ở mọi nơi để làm sạch HTML
const cleanHTML = await xssFilter('<script>evil()</script><b>Good</b>');
// Output: "<b>Good</b>"Kiểm tra giá trị
import { isNil, isEmpty, isTruthy, isFalsy } from '@libs-ui/utils';
// Kiểm tra null/undefined
isNil(null); // true
isNil(undefined); // true
isNil(0); // false
// Kiểm tra rỗng
isEmpty(null); // true
isEmpty(''); // true
isEmpty({}); // true
isEmpty([]); // true
isEmpty({ a: 1 }); // falseThao tác Object
import { get, set, cloneDeep } from '@libs-ui/utils';
const user = {
profile: {
name: 'John',
address: { city: 'Hanoi' },
},
};
// Lấy giá trị theo path
get(user, 'profile.name'); // 'John'
get(user, 'profile.address.city'); // 'Hanoi'
get(user, 'profile.email', 'N/A'); // 'N/A' (default value)
// Thiết lập giá trị theo path
set(user, 'profile.name', 'Jane');
set(user, 'profile.age', 25);
// Clone sâu
const cloned = cloneDeep(user);
cloned.profile.name = 'Bob'; // Không ảnh hưởng user gốcThao tác Array
import { keyBy, groupBy, range, uniqBy, isEqual } from '@libs-ui/utils';
const users = [
{ id: 1, name: 'John', type: 'admin' },
{ id: 2, name: 'Jane', type: 'user' },
{ id: 3, name: 'Bob', type: 'admin' },
];
// Chuyển array thành object
keyBy(users, 'id');
// { "1": {id:1,name:"John",type:"admin"}, "2": {...}, "3": {...} }
// Nhóm theo type
groupBy(users, 'type');
// { "admin": [{...}, {...}], "user": [{...}] }
// Tạo mảng số
range(5); // [0, 1, 2, 3, 4]
range(1, 5); // [1, 2, 3, 4]
range(0, 10, 2); // [0, 2, 4, 6, 8]
// Loại bỏ trùng lặp
uniqBy([{ id: 1 }, { id: 2 }, { id: 1 }], 'id'); // [{id:1}, {id:2}]
// So sánh deep equality
isEqual({ a: 1, b: 2 }, { a: 1, b: 2 }); // true
isEqual([1, 2, 3], [1, 2, 3]); // trueHTTP Query Params (Type-Safe)
import { UtilsHttpParamsRequest, UtilsHttpParamsRequestInstance } from '@libs-ui/utils';
// Định nghĩa interface cho params
interface SearchParams {
keyword: string;
page: number;
size: number;
}
// 1. Dùng fromObject với type safety
const params = new UtilsHttpParamsRequest<SearchParams>({
fromObject: { keyword: 'Angular', page: 1, size: 20 },
});
params.toString(); // keyword=Angular&page=1&size=20
// 2. Factory function (không cần new)
const params2 = UtilsHttpParamsRequestInstance<SearchParams>({
fromObject: { keyword: 'Angular', page: 1, size: 20 },
});
// 3. Method chaining
const params3 = new UtilsHttpParamsRequest().set('page', 1).set('size', 10).set('sort', 'name');
params3.delete('sort');
params3.toString(); // page=1&size=10
// 4. Wrap HttpParams có sẵn
import { HttpParams } from '@angular/common/http';
const base = new HttpParams().set('version', 'v2');
const wrapped = new UtilsHttpParamsRequest(undefined, base);
wrapped.get('version'); // 'v2'GET_PATH_VARIABLE — Type-Safe Path Params
import { GET_PATH_VARIABLE } from '@libs-ui/utils';
interface UserResource {
userId: number;
orgId: string;
}
// Tạo type với pattern "pathVariable-{key}"
type UserPathParams = GET_PATH_VARIABLE<UserResource>;
// Tương đương: { "pathVariable-userid": number; "pathVariable-orgid": string }
const pathParams: UserPathParams = {
'pathVariable-userid': 123,
'pathVariable-orgid': 'org-abc',
};Smart Axis Scale
import { getSmartAxisScale } from '@libs-ui/utils';
// Tính toán scale trục Y đẹp cho biểu đồ (ApexCharts, Chart.js...)
getSmartAxisScale(850);
// { stepSize: 100, max: 900, min: 0, tickAmount: 9 }
// Hỗ trợ dữ liệu âm — bắt buộc truyền minNegative khi acceptNegative = true
getSmartAxisScale(500, { acceptNegative: true, minNegative: -200 });
// { stepSize: ..., max: ..., min: (giá trị <= -200 tùy step), tickAmount: ... }
// Giới hạn số lượng tick tùy chỉnh
getSmartAxisScale(100, { minTickCount: 3, maxTickCount: 6 });
// Ném lỗi khi maxData < 0 mà không bật acceptNegative
try {
getSmartAxisScale(-100);
} catch (e) {
console.error(e); // Error: maxData is less than 0 and acceptNegative is false
}Embed Frame Detection
import { isEmbedFrame, updateFunctionCheckEmbedFrame } from '@libs-ui/utils';
// Mặc định: so sánh window.parent !== window.top
if (isEmbedFrame()) {
// Ẩn header/sidebar vì container ngoài đã quản lý
}
// Ghi đè logic — dùng cho Micro-frontend (Module Federation) hoặc Unit Test
// Gọi 1 lần lúc bootstrap ứng dụng
updateFunctionCheckEmbedFrame(() => !!(window as any).__IS_HOST_APP__);
// Trong unit test — mock luôn true/false
updateFunctionCheckEmbedFrame(() => true);
isEmbedFrame(); // trueKey Cache (tạo cache key từ tham số)
import { getKeyCacheByArrayObject } from '@libs-ui/utils';
import { HttpParams } from '@angular/common/http';
// Tạo hash MD5 duy nhất từ prefix + mảng tham số
const key = getKeyCacheByArrayObject('user_profile', [101, 'standard']);
// "c2...-8e..." (chuỗi MD5)
// Tự động sort keys và loại bỏ field 'pem' — cùng dữ liệu, khác thứ tự key vẫn ra cùng 1 hash
const hash1 = getKeyCacheByArrayObject('api_call', [{ b: 2, a: 1, pem: 'secret' }]);
const hash2 = getKeyCacheByArrayObject('api_call', [{ a: 1, b: 2 }]);
console.log(hash1 === hash2); // true
// Hỗ trợ trực tiếp Angular HttpParams
const params = new HttpParams().set('page', '1').set('query', 'angular');
const hashFromHttpParams = getKeyCacheByArrayObject('search', [params]);Key Code Constants
import { UtilsKeyCodeConstant } from '@libs-ui/utils';
// Dùng thay cho "magic number" khi xử lý sự kiện bàn phím
onKeyDown(event: KeyboardEvent) {
if (event.keyCode === UtilsKeyCodeConstant.ENTER) {
console.log('Bạn đã nhấn Enter!');
}
if (event.keyCode === UtilsKeyCodeConstant.ESCAPE) {
this.closeModal();
}
}
// Điều hướng bằng phím mũi tên
handleArrowKeys(event: KeyboardEvent) {
switch (event.keyCode) {
case UtilsKeyCodeConstant.UP_ARROW:
this.moveUp();
break;
case UtilsKeyCodeConstant.DOWN_ARROW:
this.moveDown();
break;
}
}Injection Tokens
import { LINK_IMAGE_ERROR_TOKEN_INJECT, PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT, PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT } from '@libs-ui/utils';
import { inject } from '@angular/core';
// 1. Cung cấp giá trị (app.config.ts)
export const appConfig: ApplicationConfig = {
providers: [{ provide: LINK_IMAGE_ERROR_TOKEN_INJECT, useValue: 'assets/images/image-error-fallback.png' }],
};
// 2. Inject và sử dụng trong Component/Service — nên dùng { optional: true } nếu không chắc đã được provide
class MyComponent {
private readonly fallbackImg = inject(LINK_IMAGE_ERROR_TOKEN_INJECT, { optional: true });
get imageUrl() {
return this.fallbackImg ?? 'https://default-cdn.com/default.png';
}
}Important Notes
⚠️ Lưu ý quan trọng khi sử dụng:
- Các functions hỗ trợ unwrap Signal tự động (trừ khi dùng option
ignoreUnWrapSignal). get()vàset()hỗ trợ path dạng string (vd:"user.profile.name") hoặc array (vd:["user", "profile", "name"]).cloneDeep()có thể clone Signal, Date, RegExp, Map, Set và các object phức tạp khác.isEqual()có thể so sánh deep equality cho objects và arrays.UtilsHttpParamsRequestkế thừaHttpParams— compatible 100% với Angular HttpClient.HttpParamscủa Angular là immutable;UtilsHttpParamsRequestxử lý điều này nội bộ (tự assign lạithis.paramssau mỗi mutation).highlightByKeyword()trả về chuỗi HTML — cần dùng[innerHTML](quaxssFilter/pipe an toàn) thay vì{{ }}khi hiển thị trong template.getSmartAxisScale()bắt buộc truyềnminNegativekhiacceptNegative = true, nếu không sẽ ném lỗi (MISSING_MIN_NEGATIVE).updateFunctionCheckEmbedFrame()ghi đè hàm kiểm tra ở phạm vi module (global) — chỉ nên gọi một lần lúc bootstrap ứng dụng hoặc trongbeforeEach/afterEachcủa unit test.getKeyCacheByArrayObject()tự động sort key của object và loại bỏ fieldpemtrước khi băm MD5, đảm bảo cùng dữ liệu (khác thứ tự key) luôn ra cùng cache key.
API Reference
Xem chi tiết API tại Documentation.
Các Functions chính
| Function | Mô tả |
| ------------------------------------------------------- | -------------------------------------------- |
| isNil(value, options?) | Kiểm tra giá trị có phải null hoặc undefined |
| isEmpty(value, options?) | Kiểm tra giá trị có rỗng không |
| isTruthy(value, options?) | Kiểm tra giá trị truthy |
| isFalsy(value, options?) | Kiểm tra giá trị falsy |
| get(obj, path, defaultValue?, keepLastValueIfSignal?) | Lấy giá trị theo path |
| set(obj, path, value, options?) | Thiết lập giá trị theo path |
| cloneDeep(data, options?, seen?) | Clone sâu object/array |
| keyBy(data, key) | Chuyển array thành object |
| groupBy(data, key) | Nhóm array theo key |
| range(start, end?, step?) | Tạo mảng số |
| isEqual(value1, value2, options?) | So sánh deep equality |
| uniqBy(data, key?) | Loại bỏ trùng lặp |
| omitBy(objData, predicate) | Loại bỏ thuộc tính theo điều kiện |
| generateInterface(obj, interfaceName) | Tạo interface từ object |
| base64Encode(value) | Mã hóa Base64 (hỗ trợ Unicode) |
| base64Decode(value) | Giải mã Base64 (hỗ trợ Unicode) |
| convertBase64ToBlob(data) | Chuyển Base64 sang Blob |
| convertFileToBase64(file) | Chuyển File sang Base64 string |
| UtilsCache | Quản lý Cache (Sync & Async) |
| addArrayToSet(set, data) | Thêm mảng vào Set |
| convertSetToArray(set, map?) | Chuyển Set sang Array |
| colorContrastFromOrigin(color) | Tạo bảng sắc độ (shades/tints) |
| getColorById(str) | Hash chuỗi thành màu cố định |
| detectAndCleanNearWhiteColors(style) | Làm sạch CSS style khỏi màu gần trắng |
| UtilsCommunicateMicro | Giao tiếp Cross-window (mã hóa) |
| encrypt3rd(data) | Mã hóa AES-CBC |
| decrypt3rd(data) | Giải mã AES-CBC |
| encrypt(data) | Mã hóa AES nội bộ |
| md5(data) | Hash MD5 |
| isDangerousObject(obj) | Kiểm tra Window/DOM/Global |
| isPrimitiveType(val) | Kiểm tra kiểu dữ liệu nguyên thủy |
| getObjectSize(obj) | Đo dung lượng object |
| formatDate(date, format?) | Định dạng ngày tháng |
| getDayjs(config?) | Khởi tạo Day.js instance |
| getDeviceInfo() | Lấy thông tin thiết bị |
| isTouchDevice() | Kiểm tra thiết bị cảm ứng |
| getViewport() | Lấy kích thước Viewport |
| downloadFileByUrl(url, name, onlyOpen?) | Tải file từ URL |
| downloadFileByUrlUseXmlRequest(url, name) | Tải file bằng XMLHttpRequest |
| downloadImageFromELement(img, type?, name?) | Lưu ảnh từ thẻ img |
| isTypeImage(file) | Kiểm tra Blob/File là ảnh |
| isTypeVideo(file) | Kiểm tra Blob/File là video |
| isTypeAudio(file) | Kiểm tra Blob/File là audio |
| isTypeFile(file) | Kiểm tra giá trị có phải đối tượng File |
| getFileExtension(file) | Lấy extension của file |
| getLabelBySizeFile(size, toFixed?) | Format kích thước byte |
| convertBlobToFile(blob, name?) | Chuyển Blob thành File |
| convertUrlToFile(url, name?) | Tải file từ URL và chuyển thành đối tượng File |
| formatNumber(value) | Chuẩn hóa chuỗi số theo locale |
| viewDataNumberByLanguage(val, neg, fixed?, ...) | Định dạng số theo VI/EN locale |
| UtilsLanguageConstants.{KEY} | Hằng số mã ngôn ngữ ISO 639-1 (27 ngôn ngữ) |
| UtilsLanguageConstants.defaultLang() | Tự dò ngôn ngữ trình duyệt, fallback 'en' |
| UtilsLanguageConstants.isSupported(lang) | Kiểm tra ngôn ngữ có được hỗ trợ |
| UtilsLanguageConstants.setSupportedLanguages(langs) | Ghi đè danh sách ngôn ngữ hỗ trợ |
| protectString(input) | XOR + reverse + base64 encode (obfuscation) |
| revealString(encoded) | Giải mã ngược lại protectString |
| createUniqueRandomIntGenerator(min, max) | Factory tạo số ngẫu nhiên không trùng (10 lần) |
| patternEmail() | Regex kiểm tra email chuẩn |
| patternUrl() | Regex kiểm tra URL đầy đủ |
| patternMobilePhone() | Regex kiểm tra SĐT di động Việt Nam |
| patternNameUtf8() | Regex hỗ trợ tên tiếng Việt có dấu |
| patternEmoji() | Regex phát hiện ký tự emoji (global) |
| traceStack() | Trích xuất call stack sạch (lọc rác) |
| convertObjectToSignal() | Biến object thành cấu trúc Signals lồng nhau |
| convertSignalToObject() | Chuyển cấu trúc signals về plain object |
| unwrapSignal() | Lấy giá trị cuối cùng từ (lồng) signal |
| watchSignalEffect(...signals) | Touch nhiều signal để đăng ký dependency trong effect() |
| normalizeUrl(rawUrl) | Chuẩn hóa URL, gộp dấu // trong pathname |
| uuid() | Tạo chuỗi định danh duy nhất (MD5 hash) |
| xssFilter(data) | Lọc chuỗi HTML khỏi XSS thông qua hàm custom |
| updateFunctionXssFilter(fn) | Cập nhật custom implementation cho xssFilter |
| new UtilsUrlSearchParams(str) | Khởi tạo bộ xử lý query string từ URL/chuỗi params |
| getKeyCacheByArrayObject(keyCache, argumentsValue?) | Tạo mã hash (MD5) làm cache key từ prefix + mảng tham số |
| UtilsKeyCodeConstant.{KEY} | Hằng số mã phím bàn phím (ENTER, ESCAPE, UP_ARROW, ...) |
| highlightByKeyword(value, search, ignore?, class?) | Highlight từ khóa (Unicode-insensitive), trả về HTML |
| formatTextCompare(text, options?) | Chuẩn hóa Unicode NFC trước khi so sánh chuỗi |
| fullNameFormat(value) | Chuẩn hóa họ tên: capitalize + trim + xóa emoji |
| capitalize(text, options?) | Viết hoa chữ cái đầu mỗi từ |
| firstLetterToUpperCase(text, options?) | Viết hoa chữ cái đầu tiên của chuỗi |
| uppercaseByPosition(text, position, options?) | Viết hoa ký tự tại vị trí bất kỳ |
| escapeHtml(str) | Escape HTML entities (chống XSS) |
| decodeEscapeHtml(str) | Giải mã HTML entities về ký tự gốc |
| deleteUnicode(str) | Xóa dấu tiếng Việt (Latin hóa) |
| removeEmoji(text) | Xóa toàn bộ emoji khỏi chuỗi |
| getSmartAxisScale(maxData, options?) | Tính toán scale trục Y cho biểu đồ (step/min/max/tickAmount) |
| isEmbedFrame() | Kiểm tra app có đang chạy trong iframe/embed frame |
| updateFunctionCheckEmbedFrame(fn) | Ghi đè logic kiểm tra embed frame |
| LINK_IMAGE_ERROR_TOKEN_INJECT | InjectionToken cho URL ảnh fallback khi lỗi |
| PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT | InjectionToken cấu hình mặc định process bar standard |
| PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT | InjectionToken cấu hình mặc định process bar steps |
Công nghệ sử dụng
- Angular: >=18.0.0
- TypeScript: Latest
- RxJS: ~7.8.0
- dayjs: 1.11.5
- crypto-es: ^2.1.0
Tài liệu
Xem thêm tài liệu chi tiết tại docs/utils/utils.md.
