@dxtmisha/functional-basic 1.7.1 → 1.8.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.8.1] - 2026-07-31
6
+
7
+ ### Added
8
+ - **ErrorCenter / ErrorCenterHandler**: Introduced `isConsole` property and `setIsConsole` method across `ErrorCenterHandler`, `ErrorCenterInstance`, and `ErrorCenter` to allow toggling or filtering console error logging via boolean or callback function `(cause: ErrorCenterCauseItem) => boolean`.
9
+ - **errorCenterTypes**: Exported `ErrorCenterHandlerIsConsole` and `ErrorCenterHandlerIsConsoleCallback` type definitions.
10
+
11
+ ### Changed
12
+ - **errorCenterTypes**: Renamed `src/types/errorCenter.ts` to `src/types/errorCenterTypes.ts` to adhere to the project `*Types.ts` file naming standard.
13
+ - **ErrorCenterHandler**: Refactored `toConsole` method to utilize `executeFunction` utility for evaluating `isConsole` and streamlined return control flow.
14
+ - **Documentation**: Updated `ai-doc.md` and `ai-doc.ru.md` with guidelines enforcing the use of primitive helper functions (`isFunction`, `executeFunction`, `isFilled`, etc.).
15
+
16
+ ### Fixed
17
+ - **sortList**: Fixed `ReferenceError: 'Intl' is not defined` in environments without `Intl` support (like the Figma plugin sandbox) by lazily instantiating `Intl.Collator` inside the function scope instead of the module's global scope, and implementing a safe fallback to `String.prototype.localeCompare`.
18
+
19
+ ## [1.8.0] - 2026-07-25
20
+
21
+ ### Added
22
+ - **domContentLoaded**: Introduced `domContentLoaded` DOM helper function to safely execute callbacks once the DOM is loaded, with comprehensive unit tests (`domContentLoaded.test.ts`).
23
+ - **toNumberPositive**: Introduced `toNumberPositive` utility function to convert inputs to positive finite numbers (`> 0`) or return a default fallback (`0`), with unit tests (`toNumberPositive.test.ts`).
24
+ - **sortList**: Introduced `sortList` standalone utility function for multi-column array sorting by property paths, directions (`'asc'`, `'desc'`), or custom comparison functions using locale-aware `Intl.Collator`.
25
+ - **sortTypes**: Added `SortDir`, `SortColumnItem`, and `SortFunction` type definitions, extending `SortColumnItem` to allow optional `dir` and `column` properties for 3-state sorting cycles (`asc` -> `desc` -> `undefined`).
26
+ - **getRandomItem**: Introduced a new `getRandomItem` utility function to safely retrieve a random element from arrays, objects, or primitive values, returning `undefined` when empty or missing, with full bilingual JSDocs.
27
+ - **Tests**: Added unit test suites for `sortList` (`sortList.test.ts`), `getRandomItem` (`getRandomItem.test.ts`), `domContentLoaded` (`domContentLoaded.test.ts`), and `toNumberPositive` (`toNumberPositive.test.ts`).
28
+
5
29
  ## [1.7.1] - 2026-07-14
6
30
 
7
31
  ### Changed
package/README.md CHANGED
@@ -81,3 +81,5 @@ Full API reference, examples, and guides:
81
81
  ## License
82
82
 
83
83
  [MIT](LICENSE)
84
+
85
+
package/ai-description.md CHANGED
@@ -1,19 +1,7 @@
1
- ### Core Purpose
2
- The library provides an isomorphic utility framework for managing high-level application concerns in JavaScript/TypeScript environments (SSR and DOM). It includes robust abstractions for API communication (REST/Fetch), structured state management, DOM-safe event handling, internationalization, and reactive data storage.
1
+ An isomorphic TypeScript utility framework designed to provide core runtime services for web applications across browser and Server-Side Rendering (SSR) environments. Its primary functions include wrapping the Fetch API with request/response caching and hydration, state management isolated by request context, comprehensive internationalization (i18n, unit conversions, phone masking, date/number formatting), SEO meta tag synchronization, reactive URL hash and query parameter tracking, managed DOM event lifecycle handling, in-memory list search with string highlighting, and centralized error handling.
3
2
 
4
- ### Key Expositions
5
- * **API & Networking**: `Api` (singleton interface), `ApiInstance` (core requester), `ApiCache` (request memoization), `ApiError` (centralized error handling), `ApiHydration` (SSR data serialization), and `ApiHeaders`.
6
- * **State & Storage**: `DataStorage` (persistent storage with prefixes/expiration), `ServerStorage` (SSR-safe context isolation), `CookieStorage` (isomorphic cookie management), `Query`/`Hash` (URL-state management), and `Global` (app-wide data).
7
- * **UI & Events**: `EventItem` (DOM-safe, optimized event management with `ResizeObserver` and `scroll-sync`), `LoadingInstance` (global loading state), and `ScrollbarWidth` (layout utility).
8
- * **Localization & Formatting**: `Geo` (locale/timezone management), `GeoIntl` (Intl API wrapper), `GeoUnit` (metric/imperial conversion), `Translate` (i18n), and `Formatters` (currency, number, date, and pluralization utility).
9
- * **Utilities & Data**: `Formatters`, `SearchList` (search matching/caching), `ResumableTimer`, and a suite of functional utilities for object cloning, string/date manipulation, and DOM operations.
3
+ Api and ApiInstance manage Fetch-based HTTP communication featuring retries, custom headers, preparation hooks, and mock response emulation. ApiCache handles client and server data caching. ServerStorage and DataStorage provide isomorphic request-isolated state retention and browser storage abstraction with SSR hydration support. CookieStorage and Cookie manage client/server cookies consistently. Geo, GeoIntl, GeoPhone, GeoUnit, and Datetime form a localization engine handling Intl formatting, country phone masking, unit conversions, and date calculations. Translate and TranslateInstance manage synchronous and asynchronous translation batching. Query, QueryInstance, Hash, and HashInstance offer reactive, watchable interfaces for URL query strings and hash parameters. EventItem wraps DOM event listeners with ResizeObserver and requestAnimationFrame scroll optimizations. SearchList provides in-memory text search, regex generation, and matching string highlights. Meta, MetaOg, and MetaTwitter manage standard HTML, Open Graph, and Twitter Card metadata tags in the DOM or as HTML strings. ErrorCenter provides centralized error tracking and routing.
10
4
 
11
- ### Triggers for Studying ai-types.md
12
- Review `ai-types.md` whenever the following requirements arise:
13
- 1. **API Integration**: You need to implement new request methods, custom error handling for specific HTTP status codes, or configure global API middleware (`wrapper`/`preparation`).
14
- 2. **I18n/Formatting**: You are dealing with complex localization rules, unit conversions (Geo/Units), or pluralization requirements.
15
- 3. **SSR Consistency**: You are implementing features that must function identically on both the server and client (Hydration, `ServerStorage`, or `Datetime` formatting).
16
- 4. **Complex State**: You need to map or query data structures in memory using `SearchList` or utilize `BroadcastChannel` for cross-context messaging.
5
+ Studying ai-types.md is mandatory when implementing or typing API configurations (ApiFetch, ApiConfig, ApiHydrationItem), setting up application error handling (ErrorCenterCauseItem, ErrorCenterHandlerList), configuring complex list transformations (FormattersOptionsList, FormattersType), managing geographic and phone mask parameters (GeoItem, GeoDate, GeoPhoneValue), defining search parameters (SearchOptions, SearchColumns), configuring SEO meta types (MetaOpenGraphTag, MetaTwitterCard), or working with core generic utility types (ArrayToItem, NormalOrPromise, ObjectOrArray, NumberOrString).
17
6
 
18
- ### Integration Context
19
- The library acts as a foundational service layer between the application logic and the runtime environment. It is designed to be framework-agnostic but is particularly optimized for SSR-heavy environments (like Vue/React) where hydration of state (via `ServerStorage`) and safe access to global browser objects (via `isDomRuntime`) are critical. It wraps native `fetch`, `localStorage`, `sessionStorage`, `BroadcastChannel`, and `Intl` APIs into structured, type-safe, and singleton-accessible services.
7
+ The library operates as a foundational layer directly above native browser and Node.js runtime APIs (Fetch API, Intl API, DOM Window/Element interfaces, ResizeObserver, BroadcastChannel, Web Storage). It integrates with frontend SSR frameworks (such as Vue, React, Nuxt, or Next.js) by decoupling server-side request state via ServerStorage and generating safe client hydration scripts (getElementSafeScript) to prevent client-server hydration mismatches.
package/ai-doc.md CHANGED
@@ -2,140 +2,64 @@
2
2
 
3
3
  Framework-agnostic utility library. **Vue developers MUST search `@dxtmisha/functional` first**; use this ONLY if no reactive/Vue-specific analog exists.
4
4
 
5
- ---
5
+ ## 1. Coding Standards & Conventions
6
+ - **Class Structure**: Properties/Variables (`public`->`protected`->`private`) -> Constructor -> Public Methods (Getters -> Setters -> Core actions) -> Protected Methods -> Private Methods.
7
+ - **Style/Types**: `PascalCase` classes, `camelCase` methods/props, `UPPER_SNAKE_CASE` constants. No `any` (use `unknown`/generics). Explicit return types for ALL methods. Export all interfaces. Type files: `*Types.ts`. Use `@effect/schema` for schemas.
8
+ - **SSR Safety**: Isomorphic code. Do NOT store request state in globals. Use `isDomRuntime()` before `window`/`document`. Use `ServerStorage.get('key', () => new Class())` for request-isolated singletons.
9
+ - **Utility & Primitive Functions**: ALWAYS use primitive helper functions from this package (e.g. `isFunction`, `executeFunction`, `isFilled`, `isObject`, `isString`, `isArray`, etc.) instead of writing custom inline checks or conditions.
6
10
 
7
- ## Coding Standards & Class Structure
11
+ ## 2. API Reference & Examples
8
12
 
9
- ### 1. Class Member Order
10
- 1. **Properties/Variables**: Top of class, ordered by visibility (`public` -> `protected` -> `private`). Initialize inline if possible.
11
- 2. **Constructor**: Follows properties. Parameter properties (e.g. `protected url: string`) allowed.
12
- 3. **Public Methods**:
13
- 1. Getters, checkers, status methods (`is*`, `get*`).
14
- 2. Setters & configuration (`set*`).
15
- 3. Core executors & actions (`request()`, `fetch()`, `show()`).
16
- 4. **Protected Methods**: Internal helpers for subclasses.
17
- 5. **Private Methods**: Internal helper logic at the very bottom.
18
-
19
- ### 2. Style & Type Conventions
20
- - **Naming**: Classes = `PascalCase`, Methods/Properties = `camelCase`, Constants = `UPPER_SNAKE_CASE`.
21
- - **TypeScript**: No `any` (use `unknown`/generics). Explicit return types on ALL methods (including `void`). Export all types/interfaces. Suffix type files with `Types` (e.g., `*Types.ts`). Use `@effect/schema` for API schemas if present.
22
- - **SSR Safety**: Isomorphic code. Do not store request-specific state in static/global variables. Use `isDomRuntime()` before accessing `window`/`document`/`location`. Use `ServerStorage.get(key, () => new Instance())` for request-isolated singletons.
23
-
24
- ---
25
-
26
- ## API Reference & Examples
27
-
28
- ### 1. HTTP Client (`Api`, `ApiInstance`, `ApiCache`)
13
+ ### HTTP Client & Caching
29
14
  ```typescript
30
15
  import { Api, ApiCache } from '@dxtmisha/functional-basic';
31
-
32
- // Config
33
- Api.setOrigin('https://api.example.com');
34
- Api.setUrl('/api/v1');
35
- Api.setRequestDefault({ client: 'web' });
16
+ Api.setOrigin('https://api.example.com'); Api.setUrl('/api/v1'); Api.setRequestDefault({ client: 'web' });
36
17
  Api.setHeaders(() => ({ Authorization: `Bearer ${localStorage.getItem('token') || ''}` }));
37
-
38
- // Interceptors
39
- Api.setPreparation(async (fetchOpts) => { if (fetchOpts.auth) fetchOpts.headers['X-Auth'] = '1'; });
40
- Api.setEnd(async (res, fetchOpts) => res.status === 401 ? { reset: true } : {});
41
-
42
- // Requests
43
- const users = await Api.request<User[]>('users'); // default GET
44
- const profile = await Api.get<User>({ path: 'profile' });
18
+ Api.setPreparation(async (opts) => { if (opts.auth) opts.headers['X-Auth'] = '1'; });
19
+ Api.setEnd(async (res) => res.status === 401 ? { reset: true } : {});
20
+ const users = await Api.request<User[]>('users'); // GET
45
21
  const updated = await Api.post<User>({ path: 'profile', request: { name: 'New' } });
46
-
47
- // Cache
48
- await ApiCache.set('key', { data: 1 }, 60000); // ms age
49
- const cached = await ApiCache.get<{ data: number }>('key');
22
+ await ApiCache.set('k', { a: 1 }, 60000); const cache = await ApiCache.get<{a: number}>('k');
50
23
  ```
51
24
 
52
- ### 2. State & Storage Management
25
+ ### Storage & State
53
26
  ```typescript
54
27
  import { DataStorage, CookieStorage, Cookie, ServerStorage } from '@dxtmisha/functional-basic';
55
-
56
- // DataStorage (localStorage/sessionStorage)
57
- DataStorage.setPrefix('my_app_');
58
- const userStorage = new DataStorage<{ id: string }>('user_session', false); // true for sessionStorage
59
- userStorage.set({ id: '123' });
60
- const user = userStorage.get({ id: 'guest' }); // fallback default
61
- userStorage.remove();
62
-
63
- // Cookies
64
- CookieStorage.set('theme', 'dark', { age: 31536000, secure: true, sameSite: 'lax' });
65
- const theme = CookieStorage.get<string>('theme', 'light');
66
- CookieStorage.remove('theme');
67
-
68
- const tokenCookie = new Cookie<string>('auth_token');
69
- tokenCookie.set('xyz123', { secure: true });
70
- const token = tokenCookie.get();
71
-
72
- // SSR Request-Isolated Storage
73
- const myService = ServerStorage.get('myService', () => new MyService());
28
+ DataStorage.setPrefix('app_');
29
+ const ls = new DataStorage<{ id: string }>('user', false); ls.set({ id: '1' }); ls.get({ id: '0' }); ls.remove();
30
+ CookieStorage.set('t', 'dark', { age: 31536000, secure: true }); CookieStorage.get<string>('t', 'light');
31
+ const c = new Cookie<string>('auth'); c.set('xyz', { secure: true }); c.get();
32
+ const srv = ServerStorage.get('svc', () => new Svc()); // SSR isolated
74
33
  ```
75
34
 
76
- ### 3. Geolocation & Localization
35
+ ### Geolocation, Formatting & Localization
77
36
  ```typescript
78
37
  import { Geo, GeoIntl, GeoFlag, GeoPhone } from '@dxtmisha/functional-basic';
79
-
80
- // Geo state
81
- const country = Geo.getCountry(); // e.g., 'VN'
82
- const lang = Geo.getLanguage(); // e.g., 'vi'
83
- Geo.set('en-US');
84
-
85
- // Formatters (Intl)
38
+ const country = Geo.getCountry(); const lang = Geo.getLanguage(); Geo.set('en-US');
86
39
  const intl = new GeoIntl('en-US');
87
- intl.number(123456.78); // '123,456.78'
88
- intl.currency(99.99, 'USD'); // '$99.99'
89
- intl.sizeFile(1024 * 1024 * 5); // '5.00 MB'
90
- intl.date(new Date(), 'date'); // 'Jun 18, 2026'
91
- intl.date(new Date(), 'time'); // '10:48 PM'
92
- intl.relative(new Date(Date.now() - 3600000)); // '1 hour ago'
93
- intl.plural(3, 'apple|apples'); // '3 apples' ('one|other' or 'one|few|many|other')
94
-
95
- // Flags & Phones
40
+ intl.number(1234.5); intl.currency(99, 'USD'); intl.sizeFile(1024*1024); intl.date(new Date(), 'date');
41
+ intl.relative(new Date(Date.now() - 3600000)); intl.plural(3, 'apple|apples');
96
42
  const flag = new GeoFlag().getFlag('VN');
97
- const phoneInfo = GeoPhone.getByPhone('+84900000000'); // .phone = cleaned string
98
- const mask = GeoPhone.toMask('84900000000');
43
+ const phone = GeoPhone.getByPhone('+84900000000'); const mask = GeoPhone.toMask('84900000000');
99
44
  ```
100
45
 
101
- ### 4. DOM, Safe Events & Helpers
46
+ ### DOM, Events & Helpers
102
47
  ```typescript
103
- import { EventItem, goScrollSmooth, writeClipboardData, getClipboardData } from '@dxtmisha/functional-basic';
48
+ import { EventItem, goScrollSmooth, writeClipboardData, getClipboardData, SearchList, Formatters, FormattersType, isFilled, isFunction, executeFunction, isDomRuntime, copyObject, anyToString, sleep } from '@dxtmisha/functional-basic';
104
49
 
105
- // Leak-proof Event management
106
- const clickListener = new EventItem(window, 'click', (e) => console.log(e), { passive: true });
107
- clickListener.start();
108
- clickListener.stop(); // Call on destroy/cleanup!
50
+ // Safe Events (leak-proof)
51
+ const listener = new EventItem(window, 'click', console.log, { passive: true }); listener.start(); listener.stop();
109
52
 
110
53
  // DOM / Clipboard
111
- goScrollSmooth(document.getElementById('target'));
112
- await writeClipboardData('text');
113
- const text = await getClipboardData();
114
- ```
54
+ goScrollSmooth(document.getElementById('t')); await writeClipboardData('txt'); await getClipboardData();
115
55
 
116
- ### 5. Search & Formatting Utilities
117
- ```typescript
118
- import { SearchList, Formatters, FormattersType } from '@dxtmisha/functional-basic';
119
-
120
- // Search List with highlights
121
- const searcher = new SearchList([{ name: 'John Doe' }], ['name'], 'john');
122
- const results = searcher.to(); // returns matching items with highlighted markup in matching keys
123
-
124
- // Object Formatter
125
- const formatter = new Formatters({
126
- price: { type: FormattersType.currency, options: 'USD' },
127
- date: { type: FormattersType.date, options: { month: 'long', year: 'numeric' } }
128
- }, { price: 12000, date: '2026-06-18' });
129
- const formatted = formatter.to(); // { price: '$12,000.00', date: 'June 2026' }
130
- ```
131
-
132
- ### 6. General Helpers
133
- ```typescript
134
- import { isFilled, isDomRuntime, copyObject, anyToString, sleep } from '@dxtmisha/functional-basic';
56
+ // Search & Formatters
57
+ const res = new SearchList([{ n: 'John' }], ['n'], 'jo').to(); // Highlights matches
58
+ const fmt = new Formatters({ p: { type: FormattersType.currency, options: 'USD' } }, { p: 12 }).to();
135
59
 
136
- isFilled([]); // false (works for strings, arrays, objects, numbers, booleans)
137
- isDomRuntime(); // true if in browser
138
- const cloned = copyObject({ a: 1 });
139
- const str = anyToString(123);
140
- await sleep(500);
60
+ // General
61
+ isFilled([]); // false (strings, arrays, objects, numbers, booleans)
62
+ executeFunction(callbackOrValue, arg1); // Executes callback if function, or returns value as is
63
+ isFunction(val); // Type-guard for functions
64
+ isDomRuntime(); const cloned = copyObject({ a: 1 }); const str = anyToString(123); await sleep(500);
141
65
  ```