dff-util 1.3.7 → 1.3.9

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 CHANGED
@@ -1,26 +1,72 @@
1
- ## Http
1
+ # dff-util
2
2
 
3
- ```
4
- Http calls
3
+ Utilities for HTTP requests, JWT tokens, application constants, shared types, text formatting, and data conversion.
5
4
 
6
- **note: if url start with http then it ignoring API_BASE_URL, logic is given below.
7
- >>>> url = url.startsWith('http') ? url : Http.API_BASE_URL + url;
5
+ Select a topic below to view its reference and examples.
8
6
 
9
- ```
7
+ **[Utilities](#utilities)**
10
8
 
11
- ## util
9
+ | | | | | | | |
10
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
11
+ | [AppRandomString](#general-utilities) | [AppUniqueCode](#general-utilities) | [AppCodeByType](#general-utilities) | [AppCode](#general-utilities) | [AppDaysBack](#general-utilities) | [AppAddDays](#general-utilities) | [AppUUID4](#general-utilities) |
12
+ | [TruncateText](#text-and-date-formatting) | [DateTime24HrFormat](#text-and-date-formatting) | [DateTime12HrFormat](#text-and-date-formatting) | [DateAndTime](#text-and-date-formatting) | [TimeAgo](#text-and-date-formatting) | [toCamelCase](#case-conversion-and-object-mapping) | [toSnakeCase](#case-conversion-and-object-mapping) |
13
+ | [toLowerCase](#case-conversion-and-object-mapping) | [toUpperCase](#case-conversion-and-object-mapping) | [toPascalCase](#case-conversion-and-object-mapping) | [toViewMapper](#case-conversion-and-object-mapping) | [toEntityMapper](#case-conversion-and-object-mapping) | [toSchemaMapper](#case-conversion-and-object-mapping) | [QueryCond](#query-conditions-querycond) |
12
14
 
13
- ```
14
- => Random number generate.
15
+ **[Http](#http)**
16
+
17
+ | | | | | | |
18
+ | :--- | :--- | :--- | :--- | :--- | :--- |
19
+ | [Get](#json-requests) | [Post](#json-requests) | [Put](#json-requests) | [Delete](#json-requests) | [Token](#retrieve-a-token) | [FormUpload](#multipart-form-upload) |
20
+ | [CloudUpload](#upload-a-file-directly) | [FileDownload](#download-a-file) | [HttpHeaders](#headers-and-request-ids) | [BaseHeaders](#headers-and-request-ids) | [RespType](#response-formats) | [ErrorWrapper](#handle-errors) |
21
+
22
+ **[Call Api](#call-api)**
23
+
24
+ | | | |
25
+ | :--- | :--- | :--- |
26
+ | [CallHbs](#handlebars-rendering-callhbs) | [CallLangText](#language-translation-calllangtext) | [CallCurrencyConvert](#currency-conversion-callcurrencyconvert) |
27
+
28
+ **[Tokens and encryption](#tokens-and-encryption)**
29
+
30
+ | | | | | | |
31
+ | :--- | :--- | :--- | :--- | :--- | :--- |
32
+ | [JwtEncode](#encode-a-token) | [JwtDecode](#decode-a-token) | [JwtVerify](#verify-a-token-with-a-secret) | [JwtValid](#check-token-expiration) | [Encrypt](#encryption-and-encoding) | [Decrypt](#encryption-and-encoding) |
33
+ | [EncodeBase64](#base64-url-and-safe-encoding) | [DecodeBase64](#base64-url-and-safe-encoding) | [EncodeURL](#base64-url-and-safe-encoding) | [DecodeURL](#base64-url-and-safe-encoding) | [SafeEncode](#base64-url-and-safe-encoding) | [SafeDecode](#base64-url-and-safe-encoding) |
34
+
35
+ **[Language and country reference](#language-and-country-reference)**
36
+
37
+ | | | | | | |
38
+ | :--- | :--- | :--- | :--- | :--- | :--- |
39
+ | [LangCountryCode](#language-and-country-lookup-langcountrycode) | [CountryType](#country-data-countrytype) | [Countries](#country-list) | [LanguageType](#language-metadata-languagetype) | [LangCountryType](#language-and-country-metadata-langcountrytype) | [AllLanguageCodesType](#supported-language-codes-alllanguagecodestype) |
40
+
41
+ **[Shared types](#shared-types)**
42
+
43
+ | | | | | |
44
+ | :--- | :--- | :--- | :--- | :--- |
45
+ | [LangDirType](#common-types) | [OrderType](#common-types) | [ThemeType](#common-types) | [UnixTimestampType](#common-types) | [OptionType](#common-types) |
46
+ | [FileType](#common-types) | [ResponseType](#request-and-response-types) | [SearchType](#request-and-response-types) | [KeyValueType](#request-and-response-types) | [JsonValueType](#request-and-response-types) |
47
+ | [RequestBodyType](#request-and-response-types) | [RequestQueryType](#request-and-response-types) | [RequestByIdType](#request-and-response-types) | [SessionUser](#session-user-sessionuser) | [SessionInfo](#session-information-sessioninfo) |
48
+
49
+ **[Constants and validation](#constants-and-validation)**
50
+
51
+ | | | |
52
+ | :--- | :--- | :--- |
53
+ | [ConstValue](#constants-constvalue) | [ConstMessages](#application-messages-constmessages) | [RegExp](#regular-expressions-regexp) |
54
+
55
+ ## Utilities
56
+
57
+ ### General utilities
58
+
59
+ ```typescript
60
+ // Generate a random string with the given length and character set.
15
61
  AppRandomString(length, charset);
16
62
 
17
- => Generate code with Upper case without special char
63
+ // Generate an uppercase code.
18
64
  AppUniqueCode();
19
65
 
20
- => Key give Upper case without special char by type
66
+ // Generate an uppercase key using a type or generated suffix.
21
67
  AppCodeByType(name, type);
22
68
 
23
- => Key give Upper case without special char
69
+ // Convert a name to an uppercase key with underscore separators.
24
70
  AppCode(name);
25
71
 
26
72
  AppDaysBack(date, addDays, isDays);
@@ -30,505 +76,643 @@ AppAddDays(date, addDays, isDays);
30
76
  AppUUID4();
31
77
  ```
32
78
 
33
- ## JWT
79
+ ### Text and date formatting
34
80
 
35
- #### Encode JWT Token with secret key, expiresIn in seconds (86400 = 1 day) default
81
+ Available helpers:
36
82
 
37
- ```
38
- JwtEncode(data, secret, expiresIn);
39
- ```
83
+ - `TruncateText`
84
+ - `DateTime24HrFormat`
85
+ - `DateTime12HrFormat`
86
+ - `DateAndTime`
87
+ - `TimeAgo`
40
88
 
41
- #### Deocde JWT Token
89
+ ### Case conversion and object mapping
42
90
 
91
+ #### String case conversion
92
+
93
+ | Function | Purpose | Input → output examples |
94
+ | :--- | :--- | :--- |
95
+ | `toCamelCase` | Join words in camel case | `user_name` → `userName`; `user-name` → `userName`; `User Name` → `userName`; `USER_NAME` → `uSERNAME` |
96
+ | `toSnakeCase` | Separate words with underscores and lowercase | `userName` → `user_name`; `UserName` → `user_name`; `user name` → `user_name`; `user-name` → `user_name` |
97
+ | `toLowerCase` | Convert word separators to underscores and lowercase | `user-name` → `user_name`; `userName` → `user__name`; `UserName` → `user__name` |
98
+ | `toUpperCase` | Convert word separators to underscores and uppercase | `user-name` → `USER_NAME`; `user name` → `USER_NAME`; `userName` → `USER__NAME`; `UserName` → `USER__NAME` |
99
+ | `toPascalCase` | Capitalize each separated word and join | `user_name` → `UserName`; `user name` → `UserName`; `user-name` → `UserName`; `USER_NAME` → `UserName` |
100
+
101
+ These examples reflect the current implementation. `toCamelCase` preserves internal uppercase letters; `toLowerCase` and `toUpperCase` can produce double underscores before uppercase letters.
102
+
103
+ #### Object mapping
104
+
105
+ | Function | Key conversion | Example input | Example output |
106
+ | :--- | :--- | :--- | :--- |
107
+ | `toViewMapper` | Convert keys to camel case and `_id` to `id` recursively | `{ _id: 'abc123', user_name: 'prasad', address_info: { city_name: 'hyderabad' } }` | `{ id: 'abc123', userName: 'prasad', addressInfo: { cityName: 'hyderabad' } }` |
108
+ | `toEntityMapper` | Convert keys to snake case recursively; preserve `id` | `{ id: 'abc123', userName: 'prasad', addressInfo: { cityName: 'hyderabad' } }` | `{ id: 'abc123', user_name: 'prasad', address_info: { city_name: 'hyderabad' } }` |
109
+ | `toSchemaMapper` | Convert top-level `id` to `_id` and keys to snake case; nested values use `toEntityMapper` | `{ id: 'abc123', userName: 'prasad', addressInfo: { cityName: 'hyderabad' } }` | `{ _id: 'abc123', user_name: 'prasad', address_info: { city_name: 'hyderabad' } }` |
110
+
111
+ All three preserve language maps whose keys are recognized language codes. Primitive and non-plain-object values are returned unchanged. `toViewMapper` and `toEntityMapper` process array items recursively; `toSchemaMapper` uses `toEntityMapper` for array items, so their `id` keys remain `id`.
112
+
113
+ ### Query conditions (QueryCond)
114
+
115
+ Parse a filter expression into an array of conditions. The example below includes comparison, membership, null, range, text, and existence filters.
116
+
117
+ ```typescript
118
+ const got = QueryCond(input);
119
+
120
+ example:
121
+ QueryCond input: isApproved=true,status!=false,age>18,score<100,height>=170,weight<=80,type=["accept","inprogress"],type!=["accept","inprogress"],role in ["admin","editor"],role not in ["admin","editor"],role notin ["admin","editor"],deletedAt is null,deletedAt is not null,deletedAt isnull,updatedAt isnotnull,deletedAt=null,deletedAt!=null,age between [18,30],createdAt between 2020-01-01..2020-01-31,name like "Jo%",email ilike "%@gmail.com",title contains "hello",code startswith "AB",code endswith "99",path regex "^/api/.*$",archivedAt,!archivedAt,name="a,b",meta={"a":1,"b":true},tags=["x,y","z"]
122
+ QueryCond output: [
123
+ {
124
+ "key": "isApproved",
125
+ "opt": "=",
126
+ "value": true
127
+ },
128
+ {
129
+ "key": "status",
130
+ "opt": "!=",
131
+ "value": false
132
+ },
133
+ {
134
+ "key": "age",
135
+ "opt": ">",
136
+ "value": 18
137
+ },
138
+ {
139
+ "key": "score",
140
+ "opt": "<",
141
+ "value": 100
142
+ },
143
+ {
144
+ "key": "height",
145
+ "opt": ">=",
146
+ "value": 170
147
+ },
148
+ {
149
+ "key": "weight",
150
+ "opt": "<=",
151
+ "value": 80
152
+ },
153
+ {
154
+ "key": "type",
155
+ "opt": "in",
156
+ "value": [
157
+ "accept",
158
+ "inprogress"
159
+ ]
160
+ },
161
+ {
162
+ "key": "type",
163
+ "opt": "not in",
164
+ "value": [
165
+ "accept",
166
+ "inprogress"
167
+ ]
168
+ },
169
+ {
170
+ "key": "role",
171
+ "opt": "in",
172
+ "value": [
173
+ "admin",
174
+ "editor"
175
+ ]
176
+ },
177
+ {
178
+ "key": "role",
179
+ "opt": "not in",
180
+ "value": [
181
+ "admin",
182
+ "editor"
183
+ ]
184
+ },
185
+ {
186
+ "key": "role",
187
+ "opt": "not in",
188
+ "value": [
189
+ "admin",
190
+ "editor"
191
+ ]
192
+ },
193
+ {
194
+ "key": "deletedAt",
195
+ "opt": "is null",
196
+ "value": null
197
+ },
198
+ {
199
+ "key": "deletedAt",
200
+ "opt": "is not null",
201
+ "value": null
202
+ },
203
+ {
204
+ "key": "deletedAt",
205
+ "opt": "is null",
206
+ "value": null
207
+ },
208
+ {
209
+ "key": "updatedAt",
210
+ "opt": "is not null",
211
+ "value": null
212
+ },
213
+ {
214
+ "key": "deletedAt",
215
+ "opt": "is null",
216
+ "value": null
217
+ },
218
+ {
219
+ "key": "deletedAt",
220
+ "opt": "is not null",
221
+ "value": null
222
+ },
223
+ {
224
+ "key": "age",
225
+ "opt": "between",
226
+ "value": [
227
+ 18,
228
+ 30
229
+ ]
230
+ },
231
+ {
232
+ "key": "createdAt",
233
+ "opt": "between",
234
+ "value": [
235
+ "2020-01-01",
236
+ "2020-01-31"
237
+ ]
238
+ },
239
+ {
240
+ "key": "name",
241
+ "opt": "like",
242
+ "value": "Jo%"
243
+ },
244
+ {
245
+ "key": "email",
246
+ "opt": "ilike",
247
+ "value": "%@gmail.com"
248
+ },
249
+ {
250
+ "key": "title",
251
+ "opt": "contains",
252
+ "value": "hello"
253
+ },
254
+ {
255
+ "key": "code",
256
+ "opt": "startswith",
257
+ "value": "AB"
258
+ },
259
+ {
260
+ "key": "code",
261
+ "opt": "endswith",
262
+ "value": "99"
263
+ },
264
+ {
265
+ "key": "path",
266
+ "opt": "regex",
267
+ "value": "^/api/.*$"
268
+ },
269
+ {
270
+ "key": "archivedAt",
271
+ "opt": "exists",
272
+ "value": true
273
+ },
274
+ {
275
+ "key": "archivedAt",
276
+ "opt": "exists",
277
+ "value": false
278
+ },
279
+ {
280
+ "key": "name",
281
+ "opt": "=",
282
+ "value": "a,b"
283
+ },
284
+ {
285
+ "key": "meta",
286
+ "opt": "=",
287
+ "value": {
288
+ "a": 1,
289
+ "b": true
290
+ }
291
+ },
292
+ {
293
+ "key": "tags",
294
+ "opt": "in",
295
+ "value": [
296
+ "x,y",
297
+ "z"
298
+ ]
299
+ }
300
+ ]
43
301
  ```
44
- JwtDecode(token);
45
- ```
46
302
 
47
- #### Verify JWT token with secret
303
+ ## Http
304
+
305
+ ### HTTP requests
48
306
 
307
+ `Http` provides static helpers built on `fetch` for JSON requests, token retrieval, uploads, and downloads. Use a runtime that provides `fetch`, `FormData`, and `File` for the corresponding operations. Examples using `await` belong in an async function or a module that supports top-level await.
308
+
309
+ #### Configuration
310
+
311
+ ```typescript
312
+ import { Http, HttpHeaders, RespType } from 'dff-util';
313
+
314
+ Http.API_BASE_URL = 'https://api.example.com'; // Default: empty string
315
+ Http.TOKEN_URL = '/apisix/plugin/jwt/sign'; // Default token endpoint
316
+
317
+ // Create a fresh headers object for each request.
318
+ const createHeaders = () => ({
319
+ ...HttpHeaders,
320
+ authorization: 'Bearer YOUR_ACCESS_TOKEN',
321
+ });
49
322
  ```
50
- JwtVerify(data, secret);
323
+
324
+ `Get`, `Post`, `Put`, `Delete`, and `FormUpload` prepend `API_BASE_URL` unless the URL starts with `http`. Paths are concatenated directly, so use a base URL without a trailing slash and a path beginning with `/`.
325
+
326
+ `Token` always joins `API_BASE_URL` and `TOKEN_URL`. `CloudUpload` and `FileDownload` use the supplied URL directly.
327
+
328
+ #### Methods
329
+
330
+ | Method | Arguments, in order | Result |
331
+ | :--- | :--- | :--- |
332
+ | `Get` | `url, params, headers, type = RespType.JSON` | Parsed response |
333
+ | `Post` | `url, data, headers, type = RespType.JSON` | Parsed response |
334
+ | `Put` | `url, data, headers, type = RespType.JSON` | Parsed response |
335
+ | `Delete` | `url, params, headers, type = RespType.JSON` | Parsed response |
336
+ | `Token` | `sessionInfo, appKey, apiKey?, type = RespType.TEXT` | Token text by default |
337
+ | `FormUpload` | `url, file, isHeadersAddMultiForm = false, data = {}, headers = BaseHeaders, method = 'PUT', type = RespType.JSON` | Parsed response |
338
+ | `CloudUpload` | `fullUrl, file, headers = null, method = 'PUT'` | Raw `Response` |
339
+ | `FileDownload` | `fullUrl, params, headers = HttpHeaders, method = 'GET'` | `Blob` |
340
+
341
+ For `Get` and `Delete`, pass `null` when no query parameters are needed. For the four JSON request methods, pass `null` for headers to use `HttpHeaders`; these positional arguments are required in the TypeScript signatures. Upload methods accept `'POST'` or `'PUT'`.
342
+
343
+ #### Headers and request IDs
344
+
345
+ - `HttpHeaders` contains `Content-Type: application/json`, plus `authorization` and `request-id` initialized to `null`.
346
+ - `BaseHeaders` contains the same authorization and request ID fields without a content type, for multipart uploads.
347
+ - Custom headers replace the defaults; spread `HttpHeaders` when you want to retain the JSON content type.
348
+ - Each helper assigns `request-id` when the supplied header value is missing or falsy. An existing ID is preserved.
349
+ - Headers are mutated when an ID is assigned. Reusing a headers object, including the shared defaults, can reuse that ID. Pass a fresh object for each request when you want distinct IDs.
350
+
351
+ #### JSON requests
352
+
353
+ ```typescript
354
+ const users = await Http.Get(
355
+ '/users',
356
+ { limit: 10, skip: 0, searchTerm: 'Jane Doe' },
357
+ createHeaders(),
358
+ );
359
+
360
+ const user = await Http.Get('/users/123', null, createHeaders());
361
+
362
+ const created = await Http.Post(
363
+ '/users',
364
+ { name: 'Jane Doe', email: 'jane@example.com' },
365
+ createHeaders(),
366
+ );
367
+
368
+ const updated = await Http.Put(
369
+ '/users/123',
370
+ { name: 'Jane Smith' },
371
+ createHeaders(),
372
+ );
373
+
374
+ // TEXT also works for an endpoint returning an empty success body.
375
+ const deleted = await Http.Delete(
376
+ '/users/123',
377
+ null,
378
+ createHeaders(),
379
+ RespType.TEXT,
380
+ );
51
381
  ```
52
382
 
53
- #### Check token expires or not
383
+ `Get` and `Delete` serialize parameters with `URLSearchParams` and append `?` followed by the query string. Supply a URL without an existing query string when passing `params`. `Post` and `Put` serialize `data` with `JSON.stringify`.
384
+
385
+ #### Response formats
54
386
 
387
+ | Value | Response parser | Returned value |
388
+ | :--- | :--- | :--- |
389
+ | `RespType.JSON` | `response.json()` | Parsed JSON |
390
+ | `RespType.TEXT` | `response.text()` | String |
391
+ | `RespType.BLOB` | `response.blob()` | `Blob` |
392
+ | `RespType.FORM_DATA` | `response.formData()` | `FormData` |
393
+ | `RespType.ARRAY_BUFFER` | `response.arrayBuffer()` | `ArrayBuffer` |
394
+
395
+ ```typescript
396
+ const text = await Http.Get('/health', null, createHeaders(), RespType.TEXT);
397
+ const image = await Http.Get('/image', null, createHeaders(), RespType.BLOB);
55
398
  ```
56
- JwtValid(token);
399
+
400
+ JSON is the default for ordinary requests and form uploads. Select a matching format for other response bodies; an empty response cannot be parsed as JSON. These helpers return the parsed body directly, without adding a `ResponseType` wrapper.
401
+
402
+ #### Retrieve a token
403
+
404
+ ```typescript
405
+ const token = await Http.Token(
406
+ { id: 'user-123', roles: ['user'] },
407
+ 'YOUR_APP_KEY',
408
+ 'YOUR_API_KEY',
409
+ );
57
410
  ```
58
411
 
59
- #### JWT examples
412
+ `Token` sends a GET request to the configured token endpoint with `key` and a JSON-serialized `payload` in the query string. It sets `X-API-KEY` to the supplied API key, or an empty string when omitted, and returns text by default.
413
+
414
+ #### Handle errors
60
415
 
416
+ For ordinary requests, token retrieval, and form uploads, non-success HTTP responses and response-parsing failures are caught and wrapped. The rejected value is a plain object:
417
+
418
+ ```typescript
419
+ try {
420
+ await Http.Post('/users', { name: 'Jane' }, createHeaders());
421
+ } catch (failure: any) {
422
+ console.error('Request URL:', failure.url);
423
+ console.error('Request ID:', failure.requestId);
424
+ console.error('Message:', failure.error.message);
425
+ console.error('Original message:', failure.error.main_message);
426
+ console.error('Submitted body:', failure.body); // Post and Put only
427
+ }
61
428
  ```
62
- import { JwtEncode, JwtVerify, JwtDecode, JwtValid } from '../src/index';
63
429
 
64
- const runJwtExamples = async () => {
65
- const secret = 'your-secret-key';
66
- const payload = { userId: '123', role: 'admin' };
430
+ `Http.ErrorWrapper(errorData)` copies the error fields and sets `message` from `internal_message`, then `message`, then `ConstKeys.INVALID_DATA`. It sets `main_message` from the original `message`, or the same fallback. Plain-text error responses may therefore appear as the fallback message rather than their original text.
67
431
 
68
- // 1. Encode a JWT
69
- const token = await JwtEncode(payload, secret, 3600);
70
- console.log('Encoded JWT Token:', token);
432
+ `CloudUpload` returns the raw response without checking `response.ok`; check it yourself. `FileDownload` reads the body as a blob without checking the status, so an HTTP error body can also be returned as a blob. Both wrap caught fetch/read failures with `url`, `requestId`, and `error`.
71
433
 
72
- // 2. Verify the JWT
73
- try {
74
- const verifiedPayload = await JwtVerify(token, secret);
75
- console.log('Verified Payload:', verifiedPayload);
76
- } catch (error: any) {
77
- console.error('Verification Error:', error.message);
78
- }
434
+ ### File uploads and downloads
79
435
 
80
- // 3. Decode the JWT without verification
81
- const decodedPayload = JwtDecode(token);
82
- console.log('Decoded Payload (without verification):', decodedPayload);
436
+ #### Multipart form upload
83
437
 
84
- // 4. Check if the JWT is valid
85
- const isValid = JwtValid(token);
86
- console.log('Is JWT valid:', isValid);
87
- };
438
+ `FormUpload` sends the file in a multipart field named `file`. Additional fields with non-null, non-undefined values are appended from `data`.
88
439
 
89
- runJwtExamples();
440
+ ```typescript
441
+ import { BaseHeaders, Http } from 'dff-util';
90
442
 
443
+ // Browser example: obtain a File from a file input.
444
+ const input = document.querySelector<HTMLInputElement>('#file-input');
445
+ const file = input?.files?.[0];
446
+
447
+ if (file) {
448
+ const result = await Http.FormUpload(
449
+ '/files',
450
+ file,
451
+ false,
452
+ { folder: 'documents' },
453
+ { ...BaseHeaders, authorization: 'Bearer YOUR_ACCESS_TOKEN' },
454
+ 'POST',
455
+ );
456
+ console.log(result);
457
+ }
91
458
  ```
92
459
 
93
- ## Constant Values
460
+ Keep `isHeadersAddMultiForm` set to `false` and omit `Content-Type` so `fetch` supplies the multipart boundary. Setting this flag to `true` adds `multipart/form-data` when no content type is supplied, but does not add the boundary. The default upload method is `PUT`; the example explicitly uses `POST`.
94
461
 
95
- ```
96
- ConstValue = {
97
- // Logical operators
98
- AND: '&&',
99
- OR: '||',
100
- NOT: '!',
101
-
102
- // Common special characters
103
- AT: '@',
104
- HASH: '#',
105
- DOLLAR: '$',
106
- PERCENT: '%',
107
- CARET: '^',
108
- AMPERSAND: '&',
109
- ASTERISK: '*',
110
- TILDE: '~',
111
- COLON: ':',
112
- SEMICOLON: ';',
113
- DOUBLE_QUOTE: '"',
114
- SINGLE_QUOTE: "'",
115
- COMMA: ',',
116
- PERIOD: '.',
117
- SLASH: '/',
118
- QUESTION_MARK: '?',
119
- PLUS: '+',
120
- UNDERSCORE: '_',
121
- HYPHEN: '-',
122
- EQUALS: '=',
123
- BACKSLASH: '\\',
124
- PIPE: '|',
125
-
126
- // Space
127
- SPACE: ' ',
128
- EMPTY: '',
129
-
130
- // Other
131
- TRUE: 'true',
132
- FALSE: 'false',
133
- NULL: 'null',
134
- UNDEFINED: 'undefined',
135
-
136
- STR_AND: 'AND',
137
- STR_OR: 'OR',
138
- STR_NOT: 'NOT',
462
+ #### Upload a file directly
139
463
 
140
- ASC: 'ASC',
141
- DESC: 'DESC',
464
+ `CloudUpload` sends the file itself as the request body, using its MIME type as the default `Content-Type`. Supply the complete destination URL.
142
465
 
143
- LTR: 'ltr',
144
- RTL: 'rtl',
466
+ ```typescript
467
+ async function uploadFile(uploadUrl: string, file: File) {
468
+ const response = await Http.CloudUpload(uploadUrl, file);
469
+ if (!response.ok) {
470
+ throw new Error(`Upload failed: ${response.status}`);
471
+ }
472
+ return response;
473
+ }
474
+ ```
145
475
 
146
- AM: 'AM',
147
- PM: 'PM',
476
+ Custom headers replace the default file content type. The destination must accept the headers sent by the helper, including `request-id`.
148
477
 
149
- LIGHT: 'light',
150
- DARK: 'dark',
478
+ #### Download a file
151
479
 
152
- MonthNames: [
153
- "Jan",
154
- "Feb",
155
- "Mar",
156
- "Apr",
157
- "May",
158
- "Jun",
159
- "Jul",
160
- "Aug",
161
- "Sep",
162
- "Oct",
163
- "Nov",
164
- "Dec",
165
- ],
480
+ `FileDownload` returns a `Blob`; it does not save the file to disk or trigger a browser download.
166
481
 
167
- };
482
+ ```typescript
483
+ const fileBlob = await Http.FileDownload(
484
+ 'https://api.example.com/files/report.pdf',
485
+ null,
486
+ { authorization: 'Bearer YOUR_ACCESS_TOKEN' },
487
+ );
168
488
  ```
169
489
 
170
- ## Regx
490
+ To reject non-success HTTP statuses before returning a blob, use `Get` with `RespType.BLOB`:
171
491
 
492
+ ```typescript
493
+ const fileBlob = await Http.Get(
494
+ '/files/report.pdf',
495
+ null,
496
+ { authorization: 'Bearer YOUR_ACCESS_TOKEN' },
497
+ RespType.BLOB,
498
+ );
172
499
  ```
173
- RegExp = {
174
- // Matches any non-alphanumeric characters
175
- NON_ALPHA_NUMERIC: /[^\w\s]/g,
176
500
 
177
- // Matches only numeric digits (0-9)
178
- DIGITS_ONLY: /^\d+$/,
501
+ ## Call Api
179
502
 
180
- // Matches only alphabets (case-insensitive)
181
- ALPHABETS_ONLY: /^[a-zA-Z]+$/,
503
+ These helpers are defined in `src/main/api-call.ts` and exported from `dff-util`. All three use synchronous `XMLHttpRequest`: they return values directly and throw errors synchronously. No `await` is needed. Browser XHR support and server CORS permission are required; requests block while waiting.
182
504
 
183
- // Matches alphanumeric characters (letters and digits)
184
- ALPHA_NUMERIC: /^[a-zA-Z0-9]+$/,
505
+ The former names `Hbs`, `LangText`, and `CurrencyConvert` are now `CallHbs`, `CallLangText`, and `CallCurrencyConvert`. Import them from `dff-util` or `main/api-call` instead of `main/util`.
185
506
 
186
- // Matches an email address
187
- EMAIL: /^[\w.%+-]+@[a-zA-Z\d.-]+\.[a-zA-Z]{2,}$/,
507
+ ### Handlebars rendering (CallHbs)
188
508
 
189
- // Matches a URL
190
- URL: /^(https?:\/\/)?([\w.-]+)\.([a-z]{2,6}\.?)(\/[\w.-]*)*\/?$/i,
509
+ `CallHbs` renders inline templates through `https://hbs.rndpro.in`, using the same request format as the HBS service. It uses synchronous `XMLHttpRequest` and sends the template and data to that service. It returns directly, without a Promise. Standard Node.js does not provide `XMLHttpRequest`.
191
510
 
192
- // Matches a US phone number (formats like (123) 456-7890, 123-456-7890, etc.)
193
- PHONE_US: /^(\(\d{3}\)\s?|\d{3}[-.\s]?)?\d{3}[-.\s]?\d{4}$/,
511
+ Synchronous requests block the browser while waiting and are deprecated on the main thread. The service must permit your browser origin and JSON POST requests through CORS. See [synchronous XHR limitations](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Synchronous_and_Asynchronous_Requests).
194
512
 
195
- // Matches a password with at least one lowercase, one uppercase, one digit, and one special character
196
- STRONG_PASSWORD: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/,
513
+ | Call | Endpoint | Return type |
514
+ | :--- | :--- | :--- |
515
+ | `CallHbs(template, data)` | `POST /render` | `string` |
516
+ | `CallHbs(template, items, true)` | `POST /multi` | `string[]` |
197
517
 
198
- // Matches whitespace characters
199
- WHITESPACE: /\s+/g,
518
+ The TypeScript return type is `string | string[]`; the table shows the result for each mode.
200
519
 
201
- // Matches any HTML tags
202
- HTML_TAG: /<\/?[\w\s="/.':;#-\/\?]+>/gi,
520
+ #### Supported inputs and rendering modes
203
521
 
204
- // Matches IPv4 addresses
205
- IPV4: /^(25[0-5]|2[0-4]\d|1?\d?\d)(\.(25[0-5]|2[0-4]\d|1?\d?\d)){3}$/,
522
+ Based on the `dff-hbs` service in the local `hbs` repository (`src/models.rs`, `src/controller.rs`, and `src/service.rs`). The client accepts objects or arrays of objects; the server model itself accepts any JSON value.
206
523
 
207
- // Matches dates in YYYY-MM-DD format
208
- DATE_YYYY_MM_DD: /^\d{4}-\d{2}-\d{2}$/,
524
+ | Input or mode | Type | Behavior / example |
525
+ | :--- | :--- | :--- |
526
+ | `template` | `string` | Inline Handlebars text, such as `Hello, {{name}}!`; not a registered template name |
527
+ | `data` with `multi = false` (default) | `RequestBodyType` | One object used as the template context: `{ name: 'Prasad' }` |
528
+ | `data` with `multi = false` | `RequestBodyType[]` | One array context; iterate using `{{#each this}}{{name}}{{/each}}` |
529
+ | `data` with `multi = true` | `RequestBodyType[]` | Render the same template for each object in one `/multi` request |
530
+ | Object property values | JSON string, number, boolean, null, object, or array | Nested data is supported, for example `{ user: { name: 'Prasad' }, active: true }` |
531
+ | Single result | `string` | Rendered text from `/render` |
532
+ | Batch result | `string[]` | Rendered strings in input order from `/multi`; an empty array returns `[]` |
533
+ | `data` is `null`/`undefined` | no request | Returns `template` unchanged; `[template]` when `multi = true` |
209
534
 
210
- // Matches time in HH:MM 24-hour format
211
- TIME_HH_MM: /^([01]\d|2[0-3]):([0-5]\d)$/,
535
+ #### Template helper reference
212
536
 
213
- // Matches ISO 8601 datetime format (e.g., 2023-08-15T13:45:30Z, 2023-08-15T13:45:30+05:30)
214
- ISO_DATETIME: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/,
537
+ The service registers `handlebars_misc_helpers::string_helpers` and `handlebars_switch::SwitchHelper`. The following string helpers are listed in the HBS repository's README. Use these expressions inside the `template` argument; they apply to both rendering modes.
215
538
 
216
- // Matches a hexadecimal color code
217
- HEX_COLOR: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
539
+ | Helper | Purpose | Template expression | Example (input → output) |
540
+ | :--- | :--- | :--- | :--- |
541
+ | `replace` | Replace text | `{{replace name "old" "new"}}` | `Hello old` → `Hello new` |
542
+ | `to_lower_case` | Lowercase text | `{{to_lower_case name}}` | `Admin` → `admin` |
543
+ | `to_upper_case` | Uppercase text | `{{to_upper_case name}}` | `Admin` → `ADMIN` |
544
+ | `to_camel_case` | camelCase | `{{to_camel_case name}}` | `admin_user` → `adminUser` |
545
+ | `to_pascal_case` | PascalCase | `{{to_pascal_case name}}` | `admin_user` → `AdminUser` |
546
+ | `to_snake_case` | snake_case | `{{to_snake_case name}}` | `AdminUser` → `admin_user` |
547
+ | `to_screaming_snake_case` | SCREAMING_SNAKE_CASE | `{{to_screaming_snake_case name}}` | `AdminUser` → `ADMIN_USER` |
548
+ | `to_kebab_case` | kebab-case | `{{to_kebab_case name}}` | `AdminUser` → `admin-user` |
549
+ | `to_train_case` | Train-Case | `{{to_train_case name}}` | `admin_user` → `Admin-User` |
550
+ | `to_sentence_case` | Sentence case | `{{to_sentence_case name}}` | `admin_user` → `Admin user` |
551
+ | `to_title_case` | Title Case | `{{to_title_case name}}` | `admin_user` → `Admin User` |
552
+ | `to_class_case` | Class-name conversion | `{{to_class_case name}}` | `admin_users` → `AdminUser` |
553
+ | `to_table_case` | Table-name conversion | `{{to_table_case name}}` | `AdminUser` → `admin_users` |
554
+ | `to_plural` | Pluralize a word | `{{to_plural name}}` | `user` → `users` |
555
+ | `to_singular` | Singularize a word | `{{to_singular name}}` | `users` → `user` |
556
+ | `to_foreign_key` | Foreign-key name conversion | `{{to_foreign_key name}}` | `AdminUser` → `admin_user_id` |
557
+ | `demodulize` | Remove module qualification | `{{demodulize "Test::Foo::Bar"}}` | `Test::Foo::Bar` → `Bar` |
558
+ | `ordinalize` | Convert a number to ordinal text | `{{ordinalize "9"}}` | `9` → `9th` |
559
+ | `deordinalize` | Remove ordinal suffix | `{{deordinalize "9th"}}` | `9th` → `9` |
560
+ | `trim` | Remove surrounding whitespace | `{{trim name}}` | `" Admin "` → `"Admin"` |
561
+ | `trim_start` | Remove leading whitespace | `{{trim_start name}}` | `" Admin "` → `"Admin "` |
562
+ | `trim_end` | Remove trailing whitespace | `{{trim_end name}}` | `" Admin "` → `" Admin"` |
563
+ | `unquote` | Remove surrounding quotes | `{{unquote name}}` | `"Admin"` → `Admin` |
564
+ | `quote` | Add quotes using the default delimiter | `{{quote "" name}}` | `Admin` → `"Admin"` |
565
+ | `first_non_empty` | Select the first nonempty value | `{{first_non_empty nickname name "Guest"}}` | `nickname: "", name: "Admin"` → `Admin` |
566
+ | `switch`, `case`, `default` | Choose output based on a value | `{{#switch access}}{{#case "admin"}}Admin{{/case}}{{#default}}User{{/default}}{{/switch}}` | `access: "admin"` → `Admin`; `access: "user"` → `User` |
218
567
 
219
- // Matches a UUID (version 4)
220
- UUID_V4: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
568
+ Helpers can be nested, for example `{{to_upper_case (first_non_empty nickname name "Guest")}}`.
221
569
 
222
- // Matches non-ASCII characters
223
- NON_ASCII: /[^\x00-\x7F]/g,
224
570
 
225
- // Matches line breaks (newlines)
226
- LINE_BREAK: /\r?\n/g,
571
+ Quote examples show the helper value before any HTML escaping. The registered helper is `quote`; the HBS repository README calls it `enquote`, but its dependency registers `quote`.
227
572
 
228
- // Matches amounts in decimal format (e.g., 123.45, 0.99, 1000)
229
- AMOUNT_DECIMAL: /^\d+(\.\d{1,2})?$/,
573
+ #### Render a single template
230
574
 
231
- // Matches percentages from 0-100 or in decimal format (e.g., 25%, 99.99%, 100, 0.5)
232
- PERCENTAGE: /^(100(\.0{1,2})?|0|0?\.\d{1,2}|[1-9]?\d(\.\d{1,2})?)%?$/,
233
- };
575
+ ```typescript
576
+ import { CallHbs } from 'dff-util';
577
+
578
+ const rendered = CallHbs('Hello, {{to_pascal_case name}}!', {
579
+ name: 'prasad',
580
+ });
581
+ console.log(rendered); // Hello, Prasad!
234
582
  ```
235
583
 
236
- ## Session Info
584
+ #### Render multiple data items in one request
237
585
 
238
- ```
239
- export type SessionInfo = {
240
- id: string;
241
- email?: string;
242
- mobile?: string;
243
- name?: string;
244
- roles: string[];
245
- type?: string;
246
- requestId?: string;
247
- token?: string;
248
- iat?: number;
249
- exp?: number;
250
- key: string;
251
- };
586
+ ```typescript
587
+ const rendered = CallHbs(
588
+ 'Hello, {{to_pascal_case name}}!',
589
+ [{ name: 'prasad' }, { name: 'monika' }],
590
+ true,
591
+ );
592
+ console.log(rendered); // ['Hello, Prasad!', 'Hello, Monika!']
252
593
  ```
253
594
 
254
- ## SessionUser
595
+ The third argument defaults to `false`. Set it to `true` to render the same template once per array item, preserving order. An empty batch returns `[]`. With `false`, an array is treated as a single template context, for example with `{{#each this}}`.
255
596
 
256
- ```
257
- export type SessionUser = {
258
- id: string;
259
- email?: string;
260
- mobile?: string;
261
- name?: string;
262
- roles: string[];
263
- type?: string;
264
- };
265
- ```
597
+ Both endpoints receive JSON in the form `{ template, data }`. Templates can use the string helpers and `switch` helper registered by HBS. Data must be a JSON object or an array of JSON objects; batch rendering requires an array of objects. If `data` is `null` or `undefined`, no request is made and the template is returned unchanged, or as `[template]` when `multi = true`. Empty templates are allowed. Omitting `multi` is equivalent to passing `false`.
266
598
 
599
+ #### Handle failures
267
600
 
268
- ## CountryType
269
- ```
270
- export type CountryType = {
271
- code: string; // ISO 3166-1 alpha-2
272
- name: string; // English country name
273
- locale: string; // Native/local language name
274
- googleNames: string[]; // Common names
275
- currencyCode: string; // ISO 4217 currency code
276
- currency: string; // Currency symbol
277
- telCode: number; // Numeric only (no +)
278
- flag: string; // Emoji flag
279
- };
601
+ ```typescript
602
+ try {
603
+ const result = CallHbs('Hello, {{name}}!', { name: 'Prasad' });
604
+ console.log(result);
605
+ } catch (error) {
606
+ console.error(error instanceof Error ? error.message : error);
607
+ }
280
608
  ```
281
609
 
282
- ### List of country and Locaion
283
- ```
284
- const countriesList = countries;
610
+ Non-success HTTP responses throw an error containing the status and response text. The service returns `400` for invalid requests and `500` for rendering failures; a failing batch reports the item index and rejects the entire batch. Network, CORS, and JSON-parsing errors propagate to the caller. Successful batch responses are checked to ensure they contain an array of strings.
285
611
 
286
- countries: CountryType[] = [ ..., ..., ... ];
287
- ```
288
- ## LangDirType, OrderType, ThemeType, UnixTimestampType, OptionType, FileType
289
- ```
290
- export type LangDirType = "ltr" | "rtl";
291
- export type OrderType = "ASC" | "DESC";
292
- export type ThemeType = "light" | "dark";
293
- export type UnixTimestampType = number & { __brand: "UnixTimestamp" };
612
+ ### Language translation (CallLangText)
294
613
 
295
- export type OptionType = {
296
- label: string;
297
- key: string | number;
298
- disabled?: boolean;
299
- icon?: string;
300
- lang?: Record<string, string>;
301
- };
614
+ `CallLangText(text, sourceLocale, targetLocale)` returns the translated text as a `string`.
302
615
 
303
- export type FileType = {
304
- filename: string;
305
- mimetype: string;
306
- url: string;
307
- };
308
- ```
309
- ## LanguageType
310
- ```
311
- export type LanguageType = {
312
- lang: string; // Locale code (e.g., en-US, hi-IN)
313
- code: string; // ISO 639-1 language code (e.g., en, hi)
314
- country: string; // ISO 3166-1 alpha-2 country code (e.g., US, IN)
315
- name: string; // English name of the language
316
- dir: "ltr" | "rtl"; // Text direction
317
- locale: string; // Native name of the language
318
- };
319
- ```
320
- ## LangCountryType
321
- ```
322
- export type LangCountryType = {
323
- lang: string; // Locale code (e.g., en-US, hi-IN)
324
- country: string; // ISO 3166-1 alpha-2 country code (e.g., US, IN)
325
- name: string; // English name of the language
326
- locale: string; // Native name of the language
327
- currencyCode: string; // ISO 4217 currency code
328
- currency: string; // Currency symbol
329
- telCode: number; // Numeric only (no +)
330
- flag: string; // Emoji flag
331
- dir: "ltr" | "rtl"; // Text direction
332
- };
333
- ```
616
+ ```typescript
617
+ import { CallLangText } from 'dff-util';
334
618
 
335
- ## Types
336
- ```
337
- export type ResponseType = {
338
- status?: string | number;
339
- data?: any;
340
- error?: any;
341
- total?: number;
342
- skip?: number;
343
- limit?: number;
344
- meta?: {
345
- traceId?: string | number;
346
- timestamp?: string | number;
347
- duration?: number;
348
- };
619
+ try {
620
+ const translated = CallLangText('Hello, how are you?', 'en-US', 'te-IN');
621
+ console.log(translated);
622
+ } catch (error) {
623
+ console.error(error instanceof Error ? error.message : error);
349
624
  }
625
+ ```
350
626
 
351
- export type SearchType = {
352
- limit?: number;
353
- skip?: number;
354
- orderBy?: string;
355
- order?: 'ASC' | 'DESC';
356
- searchTerm?: string;
357
- active?: boolean;
358
- filters?: string;
359
- };
627
+ Uses `https://lingva.ml/api/v1`, taking the two-letter language prefix from each locale. Text is URL-encoded. Empty inputs, invalid language codes, unsuccessful HTTP responses, and service-reported errors throw.
360
628
 
361
- export type KeyValueType = {
362
- [key: string]: any;
629
+ ### Currency conversion (CallCurrencyConvert)
630
+
631
+ `CallCurrencyConvert(fromCurrency, toCurrency)` returns the exchange rate as a `number`: the target-currency value of one source-currency unit.
632
+
633
+ ```typescript
634
+ import { CallCurrencyConvert } from 'dff-util';
635
+
636
+ try {
637
+ const rate = CallCurrencyConvert('INR', 'USD');
638
+ console.log(rate);
639
+ console.log(CallCurrencyConvert('USD', 'USD')); // 1; no HTTP request
640
+ } catch (error) {
641
+ console.error(error instanceof Error ? error.message : error);
363
642
  }
643
+ ```
364
644
 
365
- export type JsonValueType = string | number | boolean | null | JsonValueType[] | { [key: string]: JsonValueType };
366
- export type RequestBodyType = Record<string, JsonValueType>;
367
- export type RequestQueryType = Record<string, string | number | boolean | null>;
368
- export type RequestByIdType = {
369
- id: string | number;
370
- };
645
+ Uses `https://api.frankfurter.dev/v1/latest`. Missing inputs, unsuccessful HTTP responses, and missing or nonnumeric rates throw. Network and JSON-parsing errors propagate to the caller.
646
+
647
+ ## Tokens and encryption
648
+
649
+ ### JWT tokens
650
+
651
+ #### Encode a token
371
652
 
653
+ Sign a payload with a secret key. `expiresIn` is measured in seconds and defaults to `86400` (one day).
654
+
655
+ ```typescript
656
+ JwtEncode(data, secret, expiresIn);
372
657
  ```
373
658
 
659
+ #### Decode a token
374
660
 
661
+ ```typescript
662
+ JwtDecode(token);
663
+ ```
375
664
 
376
- ## ConstMessages
665
+ #### Verify a token with a secret
377
666
 
667
+ ```typescript
668
+ JwtVerify(token, secret);
378
669
  ```
379
- export const ConstMessages = {
380
- // Validation messages
381
- REQUIRED: 'Required',
382
- MIN_LENGTH_REQUIRED: 'Minimum length required',
383
- MAX_LENGTH_EXCEED: 'Maximum length exceeded',
384
- INVALID_DATA: 'Invalid data',
385
- FIELD_MUST_BE_NUMERIC: 'This field must be numeric',
386
- FIELD_MUST_BE_ALPHABETIC: 'This field must contain only letters',
387
- FIELD_MUST_BE_ALPHANUMERIC: 'This field must contain only letters and numbers',
388
- INVALID_EMAIL: 'Invalid email format',
389
- INVALID_PHONE: 'Invalid phone number',
390
- PASSWORD_TOO_WEAK: 'Password is too weak',
391
- PASSWORDS_DO_NOT_MATCH: 'Passwords do not match',
392
- INVALID_DATE_FORMAT: 'Invalid date format',
393
- DATE_OUT_OF_RANGE: 'Date is out of acceptable range',
394
- VALUE_TOO_LOW: 'Value is too low',
395
- VALUE_TOO_HIGH: 'Value is too high',
396
- EXCEEDS_MAX_CHARACTERS: 'Exceeds maximum character limit',
397
- INVALID_URL: 'Invalid URL format',
398
- INVALID_ZIP_CODE: 'Invalid zip/postal code',
399
- ONLY_POSITIVE_NUMBERS: 'Only positive numbers are allowed',
400
- INVALID_CREDIT_CARD: 'Invalid credit card number',
401
- INVALID_FILE_TYPE: 'Unsupported file type',
402
- FILE_TOO_LARGE: 'File size exceeds the maximum limit',
403
670
 
404
- // Success messages
405
- SUCCESS: 'Operation completed successfully',
406
- SAVED_SUCCESSFULLY: 'Data saved successfully',
407
- UPDATED_SUCCESSFULLY: 'Data updated successfully',
408
- DELETED_SUCCESSFULLY: 'Data deleted successfully',
409
- SUBMITTED_SUCCESSFULLY: 'Form submitted successfully',
410
- EMAIL_SENT: 'Email sent successfully',
411
- PASSWORD_CHANGED: 'Password changed successfully',
412
- LOGGED_IN: 'Logged in successfully',
413
- LOGGED_OUT: 'Logged out successfully',
414
- UPLOAD_SUCCESSFUL: 'File uploaded successfully',
415
- PAYMENT_SUCCESSFUL: 'Payment processed successfully',
416
- DATA_FETCHED: 'Data fetched successfully',
417
- DATA_LOADED: 'Data loaded successfully',
418
- ACTION_COMPLETED: 'Action completed successfully',
419
-
420
- // Error messages
421
- WENT_WRONG: 'Something went wrong, please try again',
422
- NOT_FOUND: 'Requested resource not found',
423
- UNAUTHORIZED: 'You are not authorized to perform this action',
424
- FORBIDDEN: 'Access to this resource is forbidden',
425
- SERVER_ERROR: 'Internal server error, please contact support',
426
- CONNECTION_ERROR: 'Unable to connect, please check your internet connection',
427
- TIMEOUT_ERROR: 'The request timed out, please try again later',
428
- VALIDATION_FAILED: 'Validation failed, please check the input',
429
- DUPLICATE_ENTRY: 'Duplicate entry, please provide unique data',
430
- SESSION_EXPIRED: 'Your session has expired, please log in again',
431
- INVALID_SESSION: 'Invalid session, please authenticate',
432
- RATE_LIMIT_EXCEEDED: 'Too many requests, please try again later',
433
- RESOURCE_LOCKED: 'This resource is currently locked',
434
- DATA_CORRUPTED: 'Data is corrupted',
435
- SERVICE_UNAVAILABLE: 'Service is currently unavailable',
436
- PAYMENT_FAILED: 'Payment failed, please check your details',
437
- OPERATION_FAILED: 'Operation failed, please try again',
438
- ACCESS_DENIED: 'Access denied',
439
- INVALID_CREDENTIALS: 'Invalid credentials, please try again',
440
- INVALID_TOKEN: 'Invalid token, please try again',
441
- USER_NOT_FOUND: 'User not found, please try again',
442
- PASSWORD_RESET_FAILED: 'Password reset failed, please try again',
671
+ #### Check token expiration
443
672
 
444
- // Informational Messages
445
- NO_DATA_FOUND: 'No data found',
446
- NO_RECORD_FOUND: 'No record found',
447
- NO_RECORDS_FOUND: 'No records found',
448
- NO_RECORDS_MATCHED: 'No records matched your search criteria',
449
- NO_RECORDS_MATCHED_FILTER: 'No records matched your filter criteria',
450
- LOADING: 'Loading, please wait...',
451
- FETCHING_DATA: 'Fetching data, please wait...',
452
- PROCESSING: 'Processing your request...',
453
- PLEASE_WAIT: 'Please wait...',
454
- NO_RESULTS_FOUND: 'No results found',
455
- NO_DATA_AVAILABLE: 'No data available',
456
- SEARCHING: 'Searching...',
457
- REDIRECTING: 'Redirecting, please wait...',
458
- CONNECTING: 'Connecting, please wait...',
459
- LOGGING_OUT: 'Logging out, please wait...',
460
- LOGGING_IN: 'Logging in, please wait...',
461
- PREPARING_DOWNLOAD: 'Preparing your download...',
462
- CHECKING_UPDATES: 'Checking for updates...',
673
+ `JwtValid` checks whether the token can be decoded and has expired; use `JwtVerify` to verify its signature.
463
674
 
464
- // Confirmation Messages
465
- CONFIRM_DELETE: 'Are you sure you want to delete this?',
466
- CONFIRM_SAVE: 'Do you want to save changes?',
467
- CONFIRM_SUBMIT: 'Do you want to submit this form?',
468
- CONFIRM_LOGOUT: 'Are you sure you want to log out?',
469
- CONFIRM_ACTION: 'Are you sure you want to proceed?',
470
- CONFIRM_CLOSE: 'Are you sure you want to close this window?',
471
- CONFIRM_CANCEL: 'Do you want to cancel this action?',
472
- CONFIRM_RESTART: 'Do you want to restart the process?',
675
+ ```typescript
676
+ JwtValid(token);
677
+ ```
473
678
 
474
- // Warning Messages
475
- UNSAVED_CHANGES: 'You have unsaved changes. Do you want to discard them?',
476
- LOW_BATTERY: 'Battery level is low, please connect your charger',
477
- HIGH_USAGE: 'High system usage detected',
478
- INCOMPLETE_FORM: 'The form is incomplete',
479
- LIMIT_REACHED: 'You have reached the maximum limit',
480
- OUTDATED_VERSION: 'You are using an outdated version of the application',
679
+ #### Example
481
680
 
482
- // General Messages
483
- WELCOME: 'Welcome to the application',
484
- GOODBYE: 'Goodbye, have a great day!',
485
- HELLO: 'Hello, how can we help you today?',
486
- THANK_YOU: 'Thank you for using our service',
487
- TRY_AGAIN: 'Please try again',
488
- UNDER_MAINTENANCE: 'The system is under maintenance, please check back later',
489
- FEATURE_COMING_SOON: 'This feature is coming soon',
490
- CONTACT_SUPPORT: 'If the issue persists, please contact support',
491
- UPDATING: 'Updating, please wait...',
492
- INSTALLING: 'Installing, please wait...',
493
- RESTART_REQUIRED: 'A restart is required to apply changes',
494
- RESTARTING: 'Restarting, please wait...',
495
- LOADING_DATA: 'Loading data, please wait...',
496
- SAVING: 'Saving, please wait...',
497
- };
681
+ ```typescript
682
+ import { JwtEncode, JwtVerify, JwtDecode, JwtValid } from '../src/index';
498
683
 
499
- ```
684
+ const runJwtExamples = async () => {
685
+ const secret = 'your-secret-key';
686
+ const payload = { userId: '123', role: 'admin' };
500
687
 
501
- ## file upload test
688
+ // 1. Encode a JWT
689
+ const token = await JwtEncode(payload, secret, 3600);
690
+ console.log('Encoded JWT Token:', token);
502
691
 
503
- ```
504
- // ts-node test/fileupload.ts
692
+ // 2. Verify the JWT
693
+ try {
694
+ const verifiedPayload = await JwtVerify(token, secret);
695
+ console.log('Verified Payload:', verifiedPayload);
696
+ } catch (error: any) {
697
+ console.error('Verification Error:', error.message);
698
+ }
505
699
 
506
- import fs from 'fs/promises';
507
- import { Http } from '../src';
508
- import path from 'path';
700
+ // 3. Decode the JWT without verification
701
+ const decodedPayload = JwtDecode(token);
702
+ console.log('Decoded Payload (without verification):', decodedPayload);
509
703
 
510
- const url = '/file';
511
- const filename = 'testing2.xlsx';
512
- const filePath = path.join(__dirname, filename);
513
- console.log(filePath);
514
- const main = async () => {
515
- const data = await fs.readFile(filePath);
516
- const resp = await Http.Upload(
517
- url,
518
- new File([data], filePath, {
519
- type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
520
- lastModified: Date.now(),
521
- }),
522
- );
523
- console.log('Http.Upload :: ', resp);
704
+ // 4. Check if the JWT is valid
705
+ const isValid = JwtValid(token);
706
+ console.log('Is JWT valid:', isValid);
524
707
  };
525
708
 
526
- main();
709
+ runJwtExamples();
710
+
527
711
  ```
528
712
 
529
- ## crypto
713
+ ### Encryption and encoding
530
714
 
531
- ```
715
+ ```typescript
532
716
  const hexStringToArrayBuffer = (hex: string) => {
533
717
  const hexMatches = hex.match(/.{1,2}/g) || [];
534
718
  const typedArray = new Uint8Array(hexMatches.map((byte) => parseInt(byte, 16)));
@@ -547,7 +731,7 @@ export const Decrypt = async (text: string, key: string) => {
547
731
  };
548
732
  ```
549
733
 
550
- ```
734
+ ```typescript
551
735
  import * as crypto from 'crypto';
552
736
  export const Encrypt = (text: string, key: string) => {
553
737
  const iv = crypto.randomBytes(16);
@@ -558,7 +742,7 @@ export const Encrypt = (text: string, key: string) => {
558
742
  };
559
743
  ```
560
744
 
561
- ```
745
+ ```typescript
562
746
  // ts-node test/test.ts
563
747
  import crypto from 'crypto';
564
748
 
@@ -580,12 +764,16 @@ const main = async () => {
580
764
 
581
765
  main();
582
766
 
583
- ---------------------------------------------------
767
+ ```
768
+
769
+ #### Base64, URL, and safe encoding
770
+
771
+ ```typescript
584
772
 
585
773
  // Base64
586
774
  const text = "Hello World!";
587
- const encodedBase64 = encodeBase64(text); // "SGVsbG8gV29ybGQh"
588
- const decodedBase64 = decodeBase64(encodedBase64); // "Hello World!"
775
+ const encodedBase64 = EncodeBase64(text); // "SGVsbG8gV29ybGQh"
776
+ const decodedBase64 = DecodeBase64(encodedBase64); // "Hello World!"
589
777
 
590
778
  console.log(encodedBase64, decodedBase64);
591
779
 
@@ -593,77 +781,108 @@ console.log(encodedBase64, decodedBase64);
593
781
  const url = "https://example.com/query?name=John Doe&city=New York";
594
782
 
595
783
  // First encode
596
- const encodedURL1 = encodeURL(url);
784
+ const encodedURL1 = EncodeURL(url);
597
785
  console.log(encodedURL1);
598
786
  // Output: "https%3A%2F%2Fexample.com%2Fquery%3Fname%3DJohn%20Doe%26city%3DNew%20York"
599
787
 
600
788
  // Encode again (idempotent)
601
- const encodedURL2 = encodeURL(encodedURL1);
789
+ const encodedURL2 = EncodeURL(encodedURL1);
602
790
  console.log(encodedURL2 === encodedURL1); // true ✅
603
791
 
604
792
  // Decode
605
- const decodedURL1 = decodeURL(encodedURL1);
793
+ const decodedURL1 = DecodeURL(encodedURL1);
606
794
  console.log(decodedURL1); // "https://example.com/query?name=John Doe&city=New York"
607
795
 
608
796
  // Decode again (idempotent)
609
- const decodedURL2 = decodeURL(decodedURL1);
797
+ const decodedURL2 = DecodeURL(decodedURL1);
610
798
  console.log(decodedURL2 === decodedURL1); // true ✅
611
799
 
612
800
  const original = "Hello World! @#$% 😊";
613
801
 
614
802
  // Encode
615
- const safe = safeEncode(original);
803
+ const safe = SafeEncode(original);
616
804
  console.log(safe);
617
805
  // Output: "U0dWc2JHOGdWMjl5YkdRPQ%3D%3D"
618
806
 
619
807
  // Decode
620
- const decoded = safeDecode(safe);
808
+ const decoded = SafeDecode(safe);
621
809
  console.log(decoded);
622
810
  // Output: "Hello World! @#$% 😊"
623
811
 
624
812
  // Multiple encode/decode calls (idempotent)
625
- console.log(safeEncode(safeDecode(safe)) === safe); // true
813
+ console.log(SafeEncode(SafeDecode(safe)) === safe); // true
814
+
815
+ ```
626
816
 
817
+ ## Language and country reference
627
818
 
819
+ ### Language and country lookup (LangCountryCode)
628
820
 
629
- ```
821
+ Look up country and language metadata locally without an API request.
630
822
 
631
- ### Call LangText, CallLangCountry, CurrencyConvert,
823
+ ```typescript
824
+ import { LangCountryCode } from 'dff-util';
825
+
826
+ const country = LangCountryCode('en-US');
827
+ console.log(country);
632
828
  ```
633
- // bun run src/tests/util.ts
634
829
 
635
- import { CurrencyConvert, LangCountryCode } from "../main/util";
830
+ ### Country data (CountryType)
636
831
 
637
- const CallLangCountry = () => {
638
- const lang = "en-US";
639
- const country = LangCountryCode(lang);
640
- console.log("LangCountryCode:: ", country);
832
+ ```typescript
833
+ export type CountryType = {
834
+ code: string; // ISO 3166-1 alpha-2
835
+ name: string; // English country name
836
+ locale: string; // Native/local language name
837
+ googleNames: string[]; // Common names
838
+ currencyCode: string; // ISO 4217 currency code
839
+ currency: string; // Currency symbol
840
+ telCode: number; // Numeric only (no +)
841
+ flag: string; // Emoji flag
641
842
  };
843
+ ```
642
844
 
643
- const CallLangText = async () => {
644
- const resp = await LangText("Hello, how are you?", "en-US", "te-IN");
645
- console.log("Resp Kannada:: ", resp);
646
- }
845
+ #### Country list
846
+ ```typescript
847
+ import { Countries } from 'dff-util';
647
848
 
648
- const CallCurrencyConvert = async () => {
649
- const resp = await CurrencyConvert("INR", "USD");
650
- console.log("Resp Currency:: ", resp);
651
- }
849
+ const countriesList = Countries;
850
+
851
+ // Countries is a CountryType[] containing country metadata.
852
+ ```
652
853
 
653
- import { LangText } from "../main/util";
854
+ ### Language metadata (LanguageType)
654
855
 
655
- const run = async () => {
656
- await CallLangCountry();
657
- await CallLangText();
658
- await CallCurrencyConvert();
856
+ ```typescript
857
+ export type LanguageType = {
858
+ lang: string; // Locale code (e.g., en-US, hi-IN)
859
+ code: string; // ISO 639-1 language code (e.g., en, hi)
860
+ country: string; // ISO 3166-1 alpha-2 country code (e.g., US, IN)
861
+ name: string; // English name of the language
862
+ dir: "ltr" | "rtl"; // Text direction
863
+ locale: string; // Native name of the language
659
864
  };
865
+ ```
660
866
 
661
- run();
867
+ ### Language and country metadata (LangCountryType)
662
868
 
869
+ ```typescript
870
+ export type LangCountryType = {
871
+ lang: string; // Locale code (e.g., en-US, hi-IN)
872
+ country: string; // ISO 3166-1 alpha-2 country code (e.g., US, IN)
873
+ name: string; // English name of the language
874
+ locale: string; // Native name of the language
875
+ currencyCode: string; // ISO 4217 currency code
876
+ currency: string; // Currency symbol
877
+ telCode: number; // Numeric only (no +)
878
+ flag: string; // Emoji flag
879
+ dir: "ltr" | "rtl"; // Text direction
880
+ };
663
881
  ```
664
882
 
665
- ### Type AllLanguageCodesType
666
- ```
883
+ ### Supported language codes (AllLanguageCodesType)
884
+
885
+ ```typescript
667
886
  export type AllLanguageCodesType =
668
887
  | "ps-AF"
669
888
  | "sq-AL"
@@ -875,263 +1094,368 @@ export type AllLanguageCodesType =
875
1094
  | "en-ZW";
876
1095
  ```
877
1096
 
878
- ### Available methods TruncateText, DateTime24HrFormat,DateTime12HrFormat, DateAndTime, TimeAgo
1097
+ ## Shared types
1098
+
1099
+ ### Common types
1100
+
1101
+ ```typescript
1102
+ export type LangDirType = "ltr" | "rtl";
1103
+ export type OrderType = "ASC" | "DESC";
1104
+ export type ThemeType = "light" | "dark";
1105
+ export type UnixTimestampType = number & { __brand: "UnixTimestamp" };
1106
+
1107
+ export type OptionType = {
1108
+ label: string;
1109
+ key: string | number;
1110
+ disabled?: boolean;
1111
+ icon?: string;
1112
+ lang?: Record<string, string>;
1113
+ };
879
1114
 
880
- ### Case
1115
+ export type FileType = {
1116
+ filename: string;
1117
+ mimetype: string;
1118
+ url: string;
1119
+ };
881
1120
  ```
882
- toCamelCase("user_name") // "userName"
883
- toCamelCase("user-name") // "userName"
884
- toCamelCase("User Name") // "userName"
885
- toCamelCase("USER_NAME") // "userName"
886
-
887
- toSnakeCase("userName") // "user_name"
888
- toSnakeCase("UserName") // "user_name"
889
- toSnakeCase("user name") // "user_name"
890
- toSnakeCase("user-name") // "user_name"
891
-
892
- toLowerCase("userName") // "user_name"
893
- toLowerCase("UserName") // "user_name"
894
- toLowerCase("user-name") // "user_name"
895
-
896
- toUpperCase("userName") // "USER_NAME"
897
- toUpperCase("user name") // "USER_NAME"
898
- toUpperCase("user-name") // "USER_NAME"
899
- toUpperCase("UserName") // "USER_NAME"
900
-
901
- toPascalCase("user_name") // "UserName"
902
- toPascalCase("user name") // "UserName"
903
- toPascalCase("user-name") // "UserName"
904
- toPascalCase("USER_NAME") // "UserName"
905
-
906
- input:
907
- const mongoDoc = {
908
- _id: 'abc123',
909
- user_name: 'prasad',
910
- address_info: {
911
- city_name: 'hyderabad'
912
- }
913
- };
914
-
915
- toViewMapper(mongoDoc) -->
916
- {
917
- id: 'abc123',
918
- userName: 'prasad',
919
- addressInfo: {
920
- cityName: 'hyderabad'
921
- }
922
- }
923
1121
 
1122
+ ### Request and response types
924
1123
 
925
- const viewObj = {
926
- id: 'abc123',
927
- userName: 'prasad',
928
- addressInfo: {
929
- cityName: 'hyderabad'
930
- }
1124
+ ```typescript
1125
+ export type ResponseType = {
1126
+ status?: string | number;
1127
+ data?: any;
1128
+ error?: any;
1129
+ total?: number;
1130
+ skip?: number;
1131
+ limit?: number;
1132
+ meta?: {
1133
+ requestId?: string | number;
1134
+ timestamp?: string | number;
1135
+ duration?: number;
1136
+ };
931
1137
  }
932
1138
 
933
- toEntityMapper(viewObj) -->
934
- {
935
- id: 'abc123',
936
- user_name: 'prasad',
937
- address_info: {
938
- city_name: 'hyderabad'
939
- }
940
- }
1139
+ export type SearchType = {
1140
+ limit?: number;
1141
+ skip?: number;
1142
+ orderBy?: string;
1143
+ order?: 'ASC' | 'DESC';
1144
+ searchTerm?: string;
1145
+ active?: boolean;
1146
+ filters?: string;
1147
+ };
941
1148
 
942
- toSchemaMapper(viewObj) -->
943
- {
944
- _id: 'abc123',
945
- user_name: 'prasad',
946
- address_info: {
947
- city_name: 'hyderabad'
948
- }
1149
+ export type KeyValueType = {
1150
+ [key: string]: any;
949
1151
  }
950
1152
 
1153
+ export type JsonValueType = string | number | boolean | null | JsonValueType[] | { [key: string]: JsonValueType };
1154
+ export type RequestBodyType = Record<string, JsonValueType>;
1155
+ export type RequestQueryType = Record<string, string | number | boolean | null>;
1156
+ export type RequestByIdType = {
1157
+ id: string | number;
1158
+ };
1159
+
951
1160
  ```
952
1161
 
1162
+ ### Session user (SessionUser)
1163
+
1164
+ ```typescript
1165
+ export type SessionUser = {
1166
+ id: string;
1167
+ email?: string;
1168
+ mobile?: string;
1169
+ name?: string;
1170
+ roles: string[];
1171
+ type?: string;
1172
+ };
953
1173
  ```
954
- const got = QueryCond(input);
955
1174
 
956
- example:
957
- QueryCond input: isApproved=true,status!=false,age>18,score<100,height>=170,weight<=80,type=["accept","inprogress"],type!=["accept","inprogress"],role in ["admin","editor"],role not in ["admin","editor"],role notin ["admin","editor"],deletedAt is null,deletedAt is not null,deletedAt isnull,updatedAt isnotnull,deletedAt=null,deletedAt!=null,age between [18,30],createdAt between 2020-01-01..2020-01-31,name like "Jo%",email ilike "%@gmail.com",title contains "hello",code startswith "AB",code endswith "99",path regex "^/api/.*$",archivedAt,!archivedAt,name="a,b",meta={"a":1,"b":true},tags=["x,y","z"]
958
- QueryCond output: [
959
- {
960
- "key": "isApproved",
961
- "opt": "=",
962
- "value": true
963
- },
964
- {
965
- "key": "status",
966
- "opt": "!=",
967
- "value": false
968
- },
969
- {
970
- "key": "age",
971
- "opt": ">",
972
- "value": 18
973
- },
974
- {
975
- "key": "score",
976
- "opt": "<",
977
- "value": 100
978
- },
979
- {
980
- "key": "height",
981
- "opt": ">=",
982
- "value": 170
983
- },
984
- {
985
- "key": "weight",
986
- "opt": "<=",
987
- "value": 80
988
- },
989
- {
990
- "key": "type",
991
- "opt": "in",
992
- "value": [
993
- "accept",
994
- "inprogress"
995
- ]
996
- },
997
- {
998
- "key": "type",
999
- "opt": "not in",
1000
- "value": [
1001
- "accept",
1002
- "inprogress"
1003
- ]
1004
- },
1005
- {
1006
- "key": "role",
1007
- "opt": "in",
1008
- "value": [
1009
- "admin",
1010
- "editor"
1011
- ]
1012
- },
1013
- {
1014
- "key": "role",
1015
- "opt": "not in",
1016
- "value": [
1017
- "admin",
1018
- "editor"
1019
- ]
1020
- },
1021
- {
1022
- "key": "role",
1023
- "opt": "not in",
1024
- "value": [
1025
- "admin",
1026
- "editor"
1027
- ]
1028
- },
1029
- {
1030
- "key": "deletedAt",
1031
- "opt": "is null",
1032
- "value": null
1033
- },
1034
- {
1035
- "key": "deletedAt",
1036
- "opt": "is not null",
1037
- "value": null
1038
- },
1039
- {
1040
- "key": "deletedAt",
1041
- "opt": "is null",
1042
- "value": null
1043
- },
1044
- {
1045
- "key": "updatedAt",
1046
- "opt": "is not null",
1047
- "value": null
1048
- },
1049
- {
1050
- "key": "deletedAt",
1051
- "opt": "is null",
1052
- "value": null
1053
- },
1054
- {
1055
- "key": "deletedAt",
1056
- "opt": "is not null",
1057
- "value": null
1058
- },
1059
- {
1060
- "key": "age",
1061
- "opt": "between",
1062
- "value": [
1063
- 18,
1064
- 30
1065
- ]
1066
- },
1067
- {
1068
- "key": "createdAt",
1069
- "opt": "between",
1070
- "value": [
1071
- "2020-01-01",
1072
- "2020-01-31"
1073
- ]
1074
- },
1075
- {
1076
- "key": "name",
1077
- "opt": "like",
1078
- "value": "Jo%"
1079
- },
1080
- {
1081
- "key": "email",
1082
- "opt": "ilike",
1083
- "value": "%@gmail.com"
1084
- },
1085
- {
1086
- "key": "title",
1087
- "opt": "contains",
1088
- "value": "hello"
1089
- },
1090
- {
1091
- "key": "code",
1092
- "opt": "startswith",
1093
- "value": "AB"
1094
- },
1095
- {
1096
- "key": "code",
1097
- "opt": "endswith",
1098
- "value": "99"
1099
- },
1100
- {
1101
- "key": "path",
1102
- "opt": "regex",
1103
- "value": "^/api/.*$"
1104
- },
1105
- {
1106
- "key": "archivedAt",
1107
- "opt": "exists",
1108
- "value": true
1109
- },
1110
- {
1111
- "key": "archivedAt",
1112
- "opt": "exists",
1113
- "value": false
1114
- },
1115
- {
1116
- "key": "name",
1117
- "opt": "=",
1118
- "value": "a,b"
1119
- },
1120
- {
1121
- "key": "meta",
1122
- "opt": "=",
1123
- "value": {
1124
- "a": 1,
1125
- "b": true
1126
- }
1127
- },
1128
- {
1129
- "key": "tags",
1130
- "opt": "in",
1131
- "value": [
1132
- "x,y",
1133
- "z"
1134
- ]
1135
- }
1136
- ]
1137
- ```
1175
+ ### Session information (SessionInfo)
1176
+
1177
+ ```typescript
1178
+ export type SessionInfo = {
1179
+ id: string;
1180
+ email?: string;
1181
+ mobile?: string;
1182
+ name?: string;
1183
+ roles: string[];
1184
+ type?: string;
1185
+ requestId?: string;
1186
+ token?: string;
1187
+ iat?: number;
1188
+ exp?: number;
1189
+ key: string;
1190
+ };
1191
+ ```
1192
+
1193
+ ## Constants and validation
1194
+
1195
+ ### Constants (ConstValue)
1196
+
1197
+ ```typescript
1198
+ ConstValue = {
1199
+ // Logical operators
1200
+ AND: '&&',
1201
+ OR: '||',
1202
+ NOT: '!',
1203
+
1204
+ // Common special characters
1205
+ AT: '@',
1206
+ HASH: '#',
1207
+ DOLLAR: '$',
1208
+ PERCENT: '%',
1209
+ CARET: '^',
1210
+ AMPERSAND: '&',
1211
+ ASTERISK: '*',
1212
+ TILDE: '~',
1213
+ COLON: ':',
1214
+ SEMICOLON: ';',
1215
+ DOUBLE_QUOTE: '"',
1216
+ SINGLE_QUOTE: "'",
1217
+ COMMA: ',',
1218
+ PERIOD: '.',
1219
+ SLASH: '/',
1220
+ QUESTION_MARK: '?',
1221
+ PLUS: '+',
1222
+ UNDERSCORE: '_',
1223
+ HYPHEN: '-',
1224
+ EQUALS: '=',
1225
+ BACKSLASH: '\\',
1226
+ PIPE: '|',
1227
+
1228
+ // Space
1229
+ SPACE: ' ',
1230
+ EMPTY: '',
1231
+
1232
+ // Other
1233
+ TRUE: 'true',
1234
+ FALSE: 'false',
1235
+ NULL: 'null',
1236
+ UNDEFINED: 'undefined',
1237
+
1238
+ STR_AND: 'AND',
1239
+ STR_OR: 'OR',
1240
+ STR_NOT: 'NOT',
1241
+
1242
+ ASC: 'ASC',
1243
+ DESC: 'DESC',
1244
+
1245
+ LTR: 'ltr',
1246
+ RTL: 'rtl',
1247
+
1248
+ AM: 'AM',
1249
+ PM: 'PM',
1250
+
1251
+ LIGHT: 'light',
1252
+ DARK: 'dark',
1253
+
1254
+ MonthNames: [
1255
+ "Jan",
1256
+ "Feb",
1257
+ "Mar",
1258
+ "Apr",
1259
+ "May",
1260
+ "Jun",
1261
+ "Jul",
1262
+ "Aug",
1263
+ "Sep",
1264
+ "Oct",
1265
+ "Nov",
1266
+ "Dec",
1267
+ ],
1268
+
1269
+ };
1270
+ ```
1271
+
1272
+ ### Application messages (ConstMessages)
1273
+
1274
+ ```typescript
1275
+ export const ConstMessages = {
1276
+ // Validation messages
1277
+ REQUIRED: 'Required',
1278
+ MIN_LENGTH_REQUIRED: 'Minimum length required',
1279
+ MAX_LENGTH_EXCEED: 'Maximum length exceeded',
1280
+ INVALID_DATA: 'Invalid data',
1281
+ FIELD_MUST_BE_NUMERIC: 'This field must be numeric',
1282
+ FIELD_MUST_BE_ALPHABETIC: 'This field must contain only letters',
1283
+ FIELD_MUST_BE_ALPHANUMERIC: 'This field must contain only letters and numbers',
1284
+ INVALID_EMAIL: 'Invalid email format',
1285
+ INVALID_PHONE: 'Invalid phone number',
1286
+ PASSWORD_TOO_WEAK: 'Password is too weak',
1287
+ PASSWORDS_DO_NOT_MATCH: 'Passwords do not match',
1288
+ INVALID_DATE_FORMAT: 'Invalid date format',
1289
+ DATE_OUT_OF_RANGE: 'Date is out of acceptable range',
1290
+ VALUE_TOO_LOW: 'Value is too low',
1291
+ VALUE_TOO_HIGH: 'Value is too high',
1292
+ EXCEEDS_MAX_CHARACTERS: 'Exceeds maximum character limit',
1293
+ INVALID_URL: 'Invalid URL format',
1294
+ INVALID_ZIP_CODE: 'Invalid zip/postal code',
1295
+ ONLY_POSITIVE_NUMBERS: 'Only positive numbers are allowed',
1296
+ INVALID_CREDIT_CARD: 'Invalid credit card number',
1297
+ INVALID_FILE_TYPE: 'Unsupported file type',
1298
+ FILE_TOO_LARGE: 'File size exceeds the maximum limit',
1299
+
1300
+ // Success messages
1301
+ SUCCESS: 'Operation completed successfully',
1302
+ SAVED_SUCCESSFULLY: 'Data saved successfully',
1303
+ UPDATED_SUCCESSFULLY: 'Data updated successfully',
1304
+ DELETED_SUCCESSFULLY: 'Data deleted successfully',
1305
+ SUBMITTED_SUCCESSFULLY: 'Form submitted successfully',
1306
+ EMAIL_SENT: 'Email sent successfully',
1307
+ PASSWORD_CHANGED: 'Password changed successfully',
1308
+ LOGGED_IN: 'Logged in successfully',
1309
+ LOGGED_OUT: 'Logged out successfully',
1310
+ UPLOAD_SUCCESSFUL: 'File uploaded successfully',
1311
+ PAYMENT_SUCCESSFUL: 'Payment processed successfully',
1312
+ DATA_FETCHED: 'Data fetched successfully',
1313
+ DATA_LOADED: 'Data loaded successfully',
1314
+ ACTION_COMPLETED: 'Action completed successfully',
1315
+
1316
+ // Error messages
1317
+ WENT_WRONG: 'Something went wrong, please try again',
1318
+ NOT_FOUND: 'Requested resource not found',
1319
+ UNAUTHORIZED: 'You are not authorized to perform this action',
1320
+ FORBIDDEN: 'Access to this resource is forbidden',
1321
+ SERVER_ERROR: 'Internal server error, please contact support',
1322
+ CONNECTION_ERROR: 'Unable to connect, please check your internet connection',
1323
+ TIMEOUT_ERROR: 'The request timed out, please try again later',
1324
+ VALIDATION_FAILED: 'Validation failed, please check the input',
1325
+ DUPLICATE_ENTRY: 'Duplicate entry, please provide unique data',
1326
+ SESSION_EXPIRED: 'Your session has expired, please log in again',
1327
+ INVALID_SESSION: 'Invalid session, please authenticate',
1328
+ RATE_LIMIT_EXCEEDED: 'Too many requests, please try again later',
1329
+ RESOURCE_LOCKED: 'This resource is currently locked',
1330
+ DATA_CORRUPTED: 'Data is corrupted',
1331
+ SERVICE_UNAVAILABLE: 'Service is currently unavailable',
1332
+ PAYMENT_FAILED: 'Payment failed, please check your details',
1333
+ OPERATION_FAILED: 'Operation failed, please try again',
1334
+ ACCESS_DENIED: 'Access denied',
1335
+ INVALID_CREDENTIALS: 'Invalid credentials, please try again',
1336
+ INVALID_TOKEN: 'Invalid token, please try again',
1337
+ USER_NOT_FOUND: 'User not found, please try again',
1338
+ PASSWORD_RESET_FAILED: 'Password reset failed, please try again',
1339
+
1340
+ // Informational Messages
1341
+ NO_DATA_FOUND: 'No data found',
1342
+ NO_RECORD_FOUND: 'No record found',
1343
+ NO_RECORDS_FOUND: 'No records found',
1344
+ NO_RECORDS_MATCHED: 'No records matched your search criteria',
1345
+ NO_RECORDS_MATCHED_FILTER: 'No records matched your filter criteria',
1346
+ LOADING: 'Loading, please wait...',
1347
+ FETCHING_DATA: 'Fetching data, please wait...',
1348
+ PROCESSING: 'Processing your request...',
1349
+ PLEASE_WAIT: 'Please wait...',
1350
+ NO_RESULTS_FOUND: 'No results found',
1351
+ NO_DATA_AVAILABLE: 'No data available',
1352
+ SEARCHING: 'Searching...',
1353
+ REDIRECTING: 'Redirecting, please wait...',
1354
+ CONNECTING: 'Connecting, please wait...',
1355
+ LOGGING_OUT: 'Logging out, please wait...',
1356
+ LOGGING_IN: 'Logging in, please wait...',
1357
+ PREPARING_DOWNLOAD: 'Preparing your download...',
1358
+ CHECKING_UPDATES: 'Checking for updates...',
1359
+
1360
+ // Confirmation Messages
1361
+ CONFIRM_DELETE: 'Are you sure you want to delete this?',
1362
+ CONFIRM_SAVE: 'Do you want to save changes?',
1363
+ CONFIRM_SUBMIT: 'Do you want to submit this form?',
1364
+ CONFIRM_LOGOUT: 'Are you sure you want to log out?',
1365
+ CONFIRM_ACTION: 'Are you sure you want to proceed?',
1366
+ CONFIRM_CLOSE: 'Are you sure you want to close this window?',
1367
+ CONFIRM_CANCEL: 'Do you want to cancel this action?',
1368
+ CONFIRM_RESTART: 'Do you want to restart the process?',
1369
+
1370
+ // Warning Messages
1371
+ UNSAVED_CHANGES: 'You have unsaved changes. Do you want to discard them?',
1372
+ LOW_BATTERY: 'Battery level is low, please connect your charger',
1373
+ HIGH_USAGE: 'High system usage detected',
1374
+ INCOMPLETE_FORM: 'The form is incomplete',
1375
+ LIMIT_REACHED: 'You have reached the maximum limit',
1376
+ OUTDATED_VERSION: 'You are using an outdated version of the application',
1377
+
1378
+ // General Messages
1379
+ WELCOME: 'Welcome to the application',
1380
+ GOODBYE: 'Goodbye, have a great day!',
1381
+ HELLO: 'Hello, how can we help you today?',
1382
+ THANK_YOU: 'Thank you for using our service',
1383
+ TRY_AGAIN: 'Please try again',
1384
+ UNDER_MAINTENANCE: 'The system is under maintenance, please check back later',
1385
+ FEATURE_COMING_SOON: 'This feature is coming soon',
1386
+ CONTACT_SUPPORT: 'If the issue persists, please contact support',
1387
+ UPDATING: 'Updating, please wait...',
1388
+ INSTALLING: 'Installing, please wait...',
1389
+ RESTART_REQUIRED: 'A restart is required to apply changes',
1390
+ RESTARTING: 'Restarting, please wait...',
1391
+ LOADING_DATA: 'Loading data, please wait...',
1392
+ SAVING: 'Saving, please wait...',
1393
+ };
1394
+
1395
+ ```
1396
+
1397
+ ### Regular expressions (RegExp)
1398
+
1399
+ ```typescript
1400
+ RegExp = {
1401
+ // Matches any non-alphanumeric characters
1402
+ NON_ALPHA_NUMERIC: /[^\w\s]/g,
1403
+
1404
+ // Matches only numeric digits (0-9)
1405
+ DIGITS_ONLY: /^\d+$/,
1406
+
1407
+ // Matches only alphabets (case-insensitive)
1408
+ ALPHABETS_ONLY: /^[a-zA-Z]+$/,
1409
+
1410
+ // Matches alphanumeric characters (letters and digits)
1411
+ ALPHA_NUMERIC: /^[a-zA-Z0-9]+$/,
1412
+
1413
+ // Matches an email address
1414
+ EMAIL: /^[\w.%+-]+@[a-zA-Z\d.-]+\.[a-zA-Z]{2,}$/,
1415
+
1416
+ // Matches a URL
1417
+ URL: /^(https?:\/\/)?([\w.-]+)\.([a-z]{2,6}\.?)(\/[\w.-]*)*\/?$/i,
1418
+
1419
+ // Matches a US phone number (formats like (123) 456-7890, 123-456-7890, etc.)
1420
+ PHONE_US: /^(\(\d{3}\)\s?|\d{3}[-.\s]?)?\d{3}[-.\s]?\d{4}$/,
1421
+
1422
+ // Matches a password with at least one lowercase, one uppercase, one digit, and one special character
1423
+ STRONG_PASSWORD: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}$/,
1424
+
1425
+ // Matches whitespace characters
1426
+ WHITESPACE: /\s+/g,
1427
+
1428
+ // Matches any HTML tags
1429
+ HTML_TAG: /<\/?[\w\s="/.':;#-\/\?]+>/gi,
1430
+
1431
+ // Matches IPv4 addresses
1432
+ IPV4: /^(25[0-5]|2[0-4]\d|1?\d?\d)(\.(25[0-5]|2[0-4]\d|1?\d?\d)){3}$/,
1433
+
1434
+ // Matches dates in YYYY-MM-DD format
1435
+ DATE_YYYY_MM_DD: /^\d{4}-\d{2}-\d{2}$/,
1436
+
1437
+ // Matches time in HH:MM 24-hour format
1438
+ TIME_HH_MM: /^([01]\d|2[0-3]):([0-5]\d)$/,
1439
+
1440
+ // Matches ISO 8601 datetime format (e.g., 2023-08-15T13:45:30Z, 2023-08-15T13:45:30+05:30)
1441
+ ISO_DATETIME: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/,
1442
+
1443
+ // Matches a hexadecimal color code
1444
+ HEX_COLOR: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
1445
+
1446
+ // Matches a UUID (version 4)
1447
+ UUID_V4: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
1448
+
1449
+ // Matches non-ASCII characters
1450
+ NON_ASCII: /[^\x00-\x7F]/g,
1451
+
1452
+ // Matches line breaks (newlines)
1453
+ LINE_BREAK: /\r?\n/g,
1454
+
1455
+ // Matches amounts in decimal format (e.g., 123.45, 0.99, 1000)
1456
+ AMOUNT_DECIMAL: /^\d+(\.\d{1,2})?$/,
1457
+
1458
+ // Matches percentages from 0-100 or in decimal format (e.g., 25%, 99.99%, 100, 0.5)
1459
+ PERCENTAGE: /^(100(\.0{1,2})?|0|0?\.\d{1,2}|[1-9]?\d(\.\d{1,2})?)%?$/,
1460
+ };
1461
+ ```