xypriss 9.6.97 → 9.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -22
- package/dist/cjs/src/index.js +0 -19
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js +4 -4
- package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/security/HoneypotTarpit.js +510 -0
- package/dist/cjs/src/middleware/built-in/security/HoneypotTarpit.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/security/SQLInjectionDetector.js +113 -34
- package/dist/cjs/src/middleware/built-in/security/SQLInjectionDetector.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/security/UriNormalizer.js +413 -0
- package/dist/cjs/src/middleware/built-in/security/UriNormalizer.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/security/XyPrissCors.js +98 -0
- package/dist/cjs/src/middleware/built-in/security/XyPrissCors.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/security/XyPrissHPP.js +52 -0
- package/dist/cjs/src/middleware/built-in/security/XyPrissHPP.js.map +1 -0
- package/dist/cjs/src/middleware/safe-json-middleware.js +0 -82
- package/dist/cjs/src/middleware/safe-json-middleware.js.map +1 -1
- package/dist/cjs/src/middleware/security-middleware.js +7 -4
- package/dist/cjs/src/middleware/security-middleware.js.map +1 -1
- package/dist/cjs/src/plugins/builtin/xems/XemsBuiltinPlugin.js +33 -10
- package/dist/cjs/src/plugins/builtin/xems/XemsBuiltinPlugin.js.map +1 -1
- package/dist/cjs/src/plugins/builtin/xems/XemsPlugin.js +34 -3
- package/dist/cjs/src/plugins/builtin/xems/XemsPlugin.js.map +1 -1
- package/dist/cjs/src/plugins/const/OFFICIAL_PLUGINS.js +1 -1
- package/dist/cjs/src/plugins/const/OFFICIAL_PLUGINS.js.map +1 -1
- package/dist/cjs/src/plugins/const/XyprissTempDir.js +72 -9
- package/dist/cjs/src/plugins/const/XyprissTempDir.js.map +1 -1
- package/dist/cjs/src/plugins/core/manager/PluginLoader.js +8 -0
- package/dist/cjs/src/plugins/core/manager/PluginLoader.js.map +1 -1
- package/dist/cjs/src/plugins/core/manager/PluginSecurity.js +87 -0
- package/dist/cjs/src/plugins/core/manager/PluginSecurity.js.map +1 -1
- package/dist/cjs/src/server/FastServer/index.js +5 -0
- package/dist/cjs/src/server/FastServer/index.js.map +1 -1
- package/dist/cjs/src/server/ServerFactory.js +8 -13
- package/dist/cjs/src/server/ServerFactory.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/RedirectManager.js +8 -58
- package/dist/cjs/src/server/components/fastapi/RedirectManager.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/upload/FileUploadManager.js +1 -1
- package/dist/cjs/src/server/components/fastapi/upload/FileUploadManager.js.map +1 -1
- package/dist/cjs/src/server/components/multi-server/MultiServerManager.js +9 -1
- package/dist/cjs/src/server/components/multi-server/MultiServerManager.js.map +1 -1
- package/dist/cjs/src/server/core/HttpServer.js +22 -0
- package/dist/cjs/src/server/core/HttpServer.js.map +1 -1
- package/dist/cjs/src/server/core/XHSCBridge/EngineManager.js +33 -2
- package/dist/cjs/src/server/core/XHSCBridge/EngineManager.js.map +1 -1
- package/dist/cjs/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js +1 -1
- package/dist/cjs/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js.map +1 -1
- package/dist/cjs/src/server/core/XyServerCreator.js +1 -0
- package/dist/cjs/src/server/core/XyServerCreator.js.map +1 -1
- package/dist/cjs/src/shared/logger/quickLogger.js +162 -0
- package/dist/cjs/src/shared/logger/quickLogger.js.map +1 -0
- package/dist/cjs/src/xhsc/PathApi.js +44 -3
- package/dist/cjs/src/xhsc/PathApi.js.map +1 -1
- package/dist/cjs/src/xhsc/System.js +2 -0
- package/dist/cjs/src/xhsc/System.js.map +1 -1
- package/dist/cjs/src/xhsc/UtilsApi.js +52 -0
- package/dist/cjs/src/xhsc/UtilsApi.js.map +1 -0
- package/dist/cjs/src/xhsc/XyPrissRunner.js +30 -2
- package/dist/cjs/src/xhsc/XyPrissRunner.js.map +1 -1
- package/dist/cjs/src/xhsc/fs/FSCore.js +148 -0
- package/dist/cjs/src/xhsc/fs/FSCore.js.map +1 -1
- package/dist/cjs/src/xhsc/fs/FileHandle.js +112 -0
- package/dist/cjs/src/xhsc/fs/FileHandle.js.map +1 -0
- package/dist/cjs/src/xhsc/ipc/XHSCDirectIPC.js +134 -0
- package/dist/cjs/src/xhsc/ipc/XHSCDirectIPC.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/ArrayUtils.js +67 -0
- package/dist/cjs/src/xhsc/utils/ArrayUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/AsyncUtils.js +582 -0
- package/dist/cjs/src/xhsc/utils/AsyncUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/DateUtils.js +959 -0
- package/dist/cjs/src/xhsc/utils/DateUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/FunctionUtils.js +29 -0
- package/dist/cjs/src/xhsc/utils/FunctionUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/IdUtils.js +22 -0
- package/dist/cjs/src/xhsc/utils/IdUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/NumberUtils.js +79 -0
- package/dist/cjs/src/xhsc/utils/NumberUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/ObjectUtils.js +141 -0
- package/dist/cjs/src/xhsc/utils/ObjectUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/StringUtils.js +145 -0
- package/dist/cjs/src/xhsc/utils/StringUtils.js.map +1 -0
- package/dist/cjs/src/xhsc/utils/ValidationUtils.js +49 -0
- package/dist/cjs/src/xhsc/utils/ValidationUtils.js.map +1 -0
- package/dist/cjs/src/xhsc.js +5 -3
- package/dist/cjs/src/xhsc.js.map +1 -1
- package/dist/esm/src/index.js +0 -2
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js +4 -4
- package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/esm/src/middleware/built-in/security/HoneypotTarpit.js +508 -0
- package/dist/esm/src/middleware/built-in/security/HoneypotTarpit.js.map +1 -0
- package/dist/esm/src/middleware/built-in/security/SQLInjectionDetector.js +113 -34
- package/dist/esm/src/middleware/built-in/security/SQLInjectionDetector.js.map +1 -1
- package/dist/esm/src/middleware/built-in/security/UriNormalizer.js +391 -0
- package/dist/esm/src/middleware/built-in/security/UriNormalizer.js.map +1 -0
- package/dist/esm/src/middleware/built-in/security/XyPrissCors.js +96 -0
- package/dist/esm/src/middleware/built-in/security/XyPrissCors.js.map +1 -0
- package/dist/esm/src/middleware/built-in/security/XyPrissHPP.js +50 -0
- package/dist/esm/src/middleware/built-in/security/XyPrissHPP.js.map +1 -0
- package/dist/esm/src/middleware/safe-json-middleware.js +1 -79
- package/dist/esm/src/middleware/safe-json-middleware.js.map +1 -1
- package/dist/esm/src/middleware/security-middleware.js +7 -4
- package/dist/esm/src/middleware/security-middleware.js.map +1 -1
- package/dist/esm/src/plugins/builtin/xems/XemsBuiltinPlugin.js +33 -10
- package/dist/esm/src/plugins/builtin/xems/XemsBuiltinPlugin.js.map +1 -1
- package/dist/esm/src/plugins/builtin/xems/XemsPlugin.js +34 -3
- package/dist/esm/src/plugins/builtin/xems/XemsPlugin.js.map +1 -1
- package/dist/esm/src/plugins/const/OFFICIAL_PLUGINS.js +1 -1
- package/dist/esm/src/plugins/const/OFFICIAL_PLUGINS.js.map +1 -1
- package/dist/esm/src/plugins/const/XyprissTempDir.js +70 -9
- package/dist/esm/src/plugins/const/XyprissTempDir.js.map +1 -1
- package/dist/esm/src/plugins/core/manager/PluginLoader.js +8 -0
- package/dist/esm/src/plugins/core/manager/PluginLoader.js.map +1 -1
- package/dist/esm/src/plugins/core/manager/PluginSecurity.js +87 -0
- package/dist/esm/src/plugins/core/manager/PluginSecurity.js.map +1 -1
- package/dist/esm/src/server/FastServer/index.js +5 -0
- package/dist/esm/src/server/FastServer/index.js.map +1 -1
- package/dist/esm/src/server/ServerFactory.js +8 -1
- package/dist/esm/src/server/ServerFactory.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/RedirectManager.js +8 -58
- package/dist/esm/src/server/components/fastapi/RedirectManager.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/upload/FileUploadManager.js +1 -1
- package/dist/esm/src/server/components/fastapi/upload/FileUploadManager.js.map +1 -1
- package/dist/esm/src/server/components/multi-server/MultiServerManager.js +9 -1
- package/dist/esm/src/server/components/multi-server/MultiServerManager.js.map +1 -1
- package/dist/esm/src/server/core/HttpServer.js +22 -0
- package/dist/esm/src/server/core/HttpServer.js.map +1 -1
- package/dist/esm/src/server/core/XHSCBridge/EngineManager.js +33 -2
- package/dist/esm/src/server/core/XHSCBridge/EngineManager.js.map +1 -1
- package/dist/esm/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js +1 -1
- package/dist/esm/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js.map +1 -1
- package/dist/esm/src/server/core/XyServerCreator.js +1 -0
- package/dist/esm/src/server/core/XyServerCreator.js.map +1 -1
- package/dist/esm/src/shared/logger/quickLogger.js +160 -0
- package/dist/esm/src/shared/logger/quickLogger.js.map +1 -0
- package/dist/esm/src/xhsc/PathApi.js +44 -3
- package/dist/esm/src/xhsc/PathApi.js.map +1 -1
- package/dist/esm/src/xhsc/System.js +2 -0
- package/dist/esm/src/xhsc/System.js.map +1 -1
- package/dist/esm/src/xhsc/UtilsApi.js +50 -0
- package/dist/esm/src/xhsc/UtilsApi.js.map +1 -0
- package/dist/esm/src/xhsc/XyPrissRunner.js +30 -2
- package/dist/esm/src/xhsc/XyPrissRunner.js.map +1 -1
- package/dist/esm/src/xhsc/fs/FSCore.js +148 -0
- package/dist/esm/src/xhsc/fs/FSCore.js.map +1 -1
- package/dist/esm/src/xhsc/fs/FileHandle.js +110 -0
- package/dist/esm/src/xhsc/fs/FileHandle.js.map +1 -0
- package/dist/esm/src/xhsc/ipc/XHSCDirectIPC.js +113 -0
- package/dist/esm/src/xhsc/ipc/XHSCDirectIPC.js.map +1 -0
- package/dist/esm/src/xhsc/utils/ArrayUtils.js +65 -0
- package/dist/esm/src/xhsc/utils/ArrayUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/AsyncUtils.js +580 -0
- package/dist/esm/src/xhsc/utils/AsyncUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/DateUtils.js +957 -0
- package/dist/esm/src/xhsc/utils/DateUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/FunctionUtils.js +27 -0
- package/dist/esm/src/xhsc/utils/FunctionUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/IdUtils.js +20 -0
- package/dist/esm/src/xhsc/utils/IdUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/NumberUtils.js +77 -0
- package/dist/esm/src/xhsc/utils/NumberUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/ObjectUtils.js +139 -0
- package/dist/esm/src/xhsc/utils/ObjectUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/StringUtils.js +143 -0
- package/dist/esm/src/xhsc/utils/StringUtils.js.map +1 -0
- package/dist/esm/src/xhsc/utils/ValidationUtils.js +47 -0
- package/dist/esm/src/xhsc/utils/ValidationUtils.js.map +1 -0
- package/dist/esm/src/xhsc.js +6 -5
- package/dist/esm/src/xhsc.js.map +1 -1
- package/dist/index.d.ts +1872 -234
- package/package.json +119 -137
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Server, IncomingMessage, ServerResponse } from 'http';
|
|
2
2
|
import { SecureCacheAdapter } from 'xypriss-security';
|
|
3
|
-
export { XyPriStringify, fastStringify, safeStringify } from 'xypriss-security';
|
|
4
3
|
import * as reliant_type from 'reliant-type';
|
|
5
4
|
import { Readable, Writable } from 'node:stream';
|
|
6
5
|
|
|
@@ -1268,6 +1267,8 @@ interface SQLInjectionConfig {
|
|
|
1268
1267
|
logAttempts?: boolean;
|
|
1269
1268
|
/** False positive threshold (0-1) */
|
|
1270
1269
|
falsePositiveThreshold?: number;
|
|
1270
|
+
/** Maximum allowed length for input strings before triggering 'Excessive length' detection */
|
|
1271
|
+
maxLength?: number;
|
|
1271
1272
|
}
|
|
1272
1273
|
/**
|
|
1273
1274
|
* Path Traversal Protection Configuration
|
|
@@ -1843,6 +1844,20 @@ interface SecurityConfig {
|
|
|
1843
1844
|
* ```
|
|
1844
1845
|
*/
|
|
1845
1846
|
bruteForce?: boolean | RateLimitConfig;
|
|
1847
|
+
/**
|
|
1848
|
+
* Honeypot Tarpit Configuration (Bot & Scanner Neutralization)
|
|
1849
|
+
*
|
|
1850
|
+
* Instantly blocks vulnerability scanners by performing an ultra-fast O(1)
|
|
1851
|
+
* lookup on common malicious payload signatures (e.g., `/.env`, `/.git`).
|
|
1852
|
+
* Prevents wasted CPU cycles from regex ReDoS and framework routing.
|
|
1853
|
+
* By default, this is implicitly **TRUE**.
|
|
1854
|
+
*
|
|
1855
|
+
* @example Disable honeypot tarpit (Not recommended)
|
|
1856
|
+
* ```typescript
|
|
1857
|
+
* honeypotTarpit: false
|
|
1858
|
+
* ```
|
|
1859
|
+
*/
|
|
1860
|
+
honeypotTarpit?: boolean;
|
|
1846
1861
|
/**
|
|
1847
1862
|
* Rate Limiting Configuration
|
|
1848
1863
|
*
|
|
@@ -2845,13 +2860,13 @@ declare class XyPrissRunner {
|
|
|
2845
2860
|
*
|
|
2846
2861
|
* Serves as the foundational layer for all XyPriss domain-specific APIs.
|
|
2847
2862
|
* It encapsulates the `XyPrissRunner` instance, ensuring that all subclasses
|
|
2848
|
-
* have unified access to the underlying
|
|
2863
|
+
* have unified access to the underlying XHSC bridge for high-performance system operations.
|
|
2849
2864
|
*/
|
|
2850
2865
|
declare class BaseApi {
|
|
2851
2866
|
protected runner: XyPrissRunner;
|
|
2852
2867
|
/**
|
|
2853
2868
|
* Initializes the Base API with a shared runner instance.
|
|
2854
|
-
* @param runner The XyPrissRunner
|
|
2869
|
+
* @param runner - The XyPrissRunner used to invoke native XHSC binaries.
|
|
2855
2870
|
*/
|
|
2856
2871
|
constructor(runner: XyPrissRunner);
|
|
2857
2872
|
}
|
|
@@ -2860,7 +2875,7 @@ declare class BaseApi {
|
|
|
2860
2875
|
*
|
|
2861
2876
|
* The `PathApi` class provides a comprehensive suite of robust, platform-independent
|
|
2862
2877
|
* utilities for working with file and directory paths. By bridging directly to
|
|
2863
|
-
* the native
|
|
2878
|
+
* the XHSC native binary, it ensures rigorous adherence to filesystem standards
|
|
2864
2879
|
* across Windows, macOS, and Linux environments.
|
|
2865
2880
|
*
|
|
2866
2881
|
* **Key Benefits:**
|
|
@@ -3082,10 +3097,41 @@ declare class PathApi extends BaseApi {
|
|
|
3082
3097
|
* @returns {boolean} True if the path is absolute, false otherwise.
|
|
3083
3098
|
*/
|
|
3084
3099
|
isAbsolute: (p: string) => boolean;
|
|
3100
|
+
/**
|
|
3101
|
+
* **Smart Path Correction**
|
|
3102
|
+
*
|
|
3103
|
+
* Attempts to fix path inconsistencies, such as doubled segments or redundant separators.
|
|
3104
|
+
* Prioritizes the high-performance XHSC implementation.
|
|
3105
|
+
*
|
|
3106
|
+
* @param p - Path to correct.
|
|
3107
|
+
* @param tentative - Maximum number of correction attempts.
|
|
3108
|
+
*/
|
|
3109
|
+
correct(path: string, options?: {
|
|
3110
|
+
tentative?: number;
|
|
3111
|
+
verify?: boolean;
|
|
3112
|
+
}): string;
|
|
3085
3113
|
/**
|
|
3086
3114
|
* **Get System Temp Directory**
|
|
3087
3115
|
*/
|
|
3088
3116
|
tempDir: () => string;
|
|
3117
|
+
/**
|
|
3118
|
+
* **User-Scoped Temp Directory**
|
|
3119
|
+
*
|
|
3120
|
+
* Resolves and ensures a unique, ephemeral temporary directory scoped
|
|
3121
|
+
* to the current user session under the XyPriss shared temp root
|
|
3122
|
+
* (`<os.tmpdir>/nehonix.xypriss.data/xuser/<hex4>`).
|
|
3123
|
+
*
|
|
3124
|
+
* Each access generates a fresh random sub-path — suited for
|
|
3125
|
+
* short-lived scratch space that must not collide across concurrent
|
|
3126
|
+
* processes or requests.
|
|
3127
|
+
*
|
|
3128
|
+
* @returns {string} Absolute path to the isolated user temp directory.
|
|
3129
|
+
*
|
|
3130
|
+
* @example
|
|
3131
|
+
* const scratch = __sys__.path.tmpUserDir;
|
|
3132
|
+
* __sys__.fs.writeFile(scratch + "/output.json", data);
|
|
3133
|
+
*/
|
|
3134
|
+
get tmpUserDir(): string;
|
|
3089
3135
|
/**
|
|
3090
3136
|
* **Check Existence**
|
|
3091
3137
|
*/
|
|
@@ -3112,7 +3158,7 @@ declare class PathApi extends BaseApi {
|
|
|
3112
3158
|
* **System Information Types**
|
|
3113
3159
|
*
|
|
3114
3160
|
* Standardized interfaces for the XyPriss System API.
|
|
3115
|
-
* Maps directly to the underlying
|
|
3161
|
+
* Maps directly to the underlying native core structures.
|
|
3116
3162
|
*/
|
|
3117
3163
|
interface SystemInfo {
|
|
3118
3164
|
hostname: string;
|
|
@@ -3292,12 +3338,12 @@ interface FileStats {
|
|
|
3292
3338
|
size: number;
|
|
3293
3339
|
is_file: boolean;
|
|
3294
3340
|
is_dir: boolean;
|
|
3295
|
-
is_symlink: boolean;
|
|
3296
3341
|
modified: number;
|
|
3297
|
-
created: number;
|
|
3298
|
-
accessed: number;
|
|
3299
|
-
readonly: boolean;
|
|
3300
3342
|
permissions: number;
|
|
3343
|
+
is_symlink?: boolean;
|
|
3344
|
+
created?: number;
|
|
3345
|
+
accessed?: number;
|
|
3346
|
+
readonly?: boolean;
|
|
3301
3347
|
}
|
|
3302
3348
|
interface DirUsage {
|
|
3303
3349
|
path: string;
|
|
@@ -3336,6 +3382,45 @@ interface BatchRenameChange {
|
|
|
3336
3382
|
old_path: string;
|
|
3337
3383
|
new_path: string;
|
|
3338
3384
|
}
|
|
3385
|
+
/**
|
|
3386
|
+
* **Filesystem Open Flags**
|
|
3387
|
+
*
|
|
3388
|
+
* Standardized flags for opening files, following Node.js conventions
|
|
3389
|
+
* and mapping to native XHSC `os` constants.
|
|
3390
|
+
*
|
|
3391
|
+
* ---
|
|
3392
|
+
*
|
|
3393
|
+
* ### Read flags
|
|
3394
|
+
* - `"r"` — Open for **reading only**. Fails if the file does not exist.
|
|
3395
|
+
* - `"r+"` — Open for **reading and writing**. Fails if the file does not exist.
|
|
3396
|
+
* - `"rs+"` — Open for **reading and writing in synchronous mode**. Instructs the OS
|
|
3397
|
+
* to bypass the local file system cache. Useful for NFS mounts or
|
|
3398
|
+
* scenarios where cache coherency is critical.
|
|
3399
|
+
*
|
|
3400
|
+
* ### Write flags
|
|
3401
|
+
* - `"w"` — Open for **writing only**. The file is **created** if it does not exist,
|
|
3402
|
+
* or **truncated to zero length** if it does.
|
|
3403
|
+
* - `"wx"` — Like `"w"`, but **fails if the file already exists** (exclusive create).
|
|
3404
|
+
* - `"w+"` — Open for **reading and writing**. The file is **created** if it does not
|
|
3405
|
+
* exist, or **truncated** if it does.
|
|
3406
|
+
* - `"wx+"` — Like `"w+"`, but **fails if the file already exists** (exclusive create).
|
|
3407
|
+
*
|
|
3408
|
+
* ### Append flags
|
|
3409
|
+
* - `"a"` — Open for **appending only**. The file is **created** if it does not exist.
|
|
3410
|
+
* The write position is always set to the end of the file.
|
|
3411
|
+
* - `"ax"` — Like `"a"`, but **fails if the file already exists** (exclusive create).
|
|
3412
|
+
* - `"a+"` — Open for **reading and appending**. The file is **created** if it does
|
|
3413
|
+
* not exist. Reading is allowed from any position; writes always go to EOF.
|
|
3414
|
+
* - `"ax+"` — Like `"a+"`, but **fails if the file already exists** (exclusive create).
|
|
3415
|
+
*
|
|
3416
|
+
* ---
|
|
3417
|
+
*
|
|
3418
|
+
* > **`x` suffix** — The exclusive flag (`x`) maps to `O_EXCL` at the OS level.
|
|
3419
|
+
* > It guarantees atomicity: the operation succeeds only if *this* call creates the file,
|
|
3420
|
+
* > preventing race conditions in concurrent environments.
|
|
3421
|
+
*/
|
|
3422
|
+
type OpenFlag = "r" | "r+" | "rs+" | "w" | "wx" | "w+" | "wx+" | "a" | "ax" | "a+" | "ax+";
|
|
3423
|
+
type FileOpenFlags = OpenFlag | number;
|
|
3339
3424
|
|
|
3340
3425
|
/**
|
|
3341
3426
|
* **Operating System & Hardware API**
|
|
@@ -3420,6 +3505,45 @@ declare class FSBase extends PathApi {
|
|
|
3420
3505
|
constructor(runner: XyPrissRunner);
|
|
3421
3506
|
}
|
|
3422
3507
|
|
|
3508
|
+
/**
|
|
3509
|
+
* **High-Performance File Toolbox**
|
|
3510
|
+
* Exposed via __sys__.fs.open(path, callback)
|
|
3511
|
+
*/
|
|
3512
|
+
declare class FileHandle {
|
|
3513
|
+
private id;
|
|
3514
|
+
private runner;
|
|
3515
|
+
private ipc;
|
|
3516
|
+
constructor(id: number, runner: any);
|
|
3517
|
+
/**
|
|
3518
|
+
* **Get Native Handle ID**
|
|
3519
|
+
*/
|
|
3520
|
+
get nativeId(): number;
|
|
3521
|
+
/**
|
|
3522
|
+
* **Read from File**
|
|
3523
|
+
* @param length - Max bytes to read
|
|
3524
|
+
*/
|
|
3525
|
+
read(length: number): Promise<Buffer>;
|
|
3526
|
+
/**
|
|
3527
|
+
* **Write to File**
|
|
3528
|
+
* @param data - Buffer or String
|
|
3529
|
+
*/
|
|
3530
|
+
write(data: Buffer | string): Promise<number>;
|
|
3531
|
+
/**
|
|
3532
|
+
* **Seek within File**
|
|
3533
|
+
* @param offset - Position
|
|
3534
|
+
* @param whence - 0: Start, 1: Current, 2: End
|
|
3535
|
+
*/
|
|
3536
|
+
seek(offset: number, whence?: number): Promise<number>;
|
|
3537
|
+
/**
|
|
3538
|
+
* **Get File Statistics**
|
|
3539
|
+
*/
|
|
3540
|
+
stat(): Promise<FileStats>;
|
|
3541
|
+
/**
|
|
3542
|
+
* **Close Handle**
|
|
3543
|
+
*/
|
|
3544
|
+
close(): Promise<void>;
|
|
3545
|
+
}
|
|
3546
|
+
|
|
3423
3547
|
/**
|
|
3424
3548
|
* **Core Filesystem Operations**
|
|
3425
3549
|
*/
|
|
@@ -3619,6 +3743,88 @@ declare class FSCore extends FSBase {
|
|
|
3619
3743
|
* **Find Duplicates**
|
|
3620
3744
|
*/
|
|
3621
3745
|
dedupe: (p: string) => DedupeGroup[];
|
|
3746
|
+
/**
|
|
3747
|
+
* **Open File**
|
|
3748
|
+
*
|
|
3749
|
+
* Opens a file and returns a numeric file descriptor (or runs a scoped callback).
|
|
3750
|
+
*
|
|
3751
|
+
* ---
|
|
3752
|
+
*
|
|
3753
|
+
* ### Modes via `flags`
|
|
3754
|
+
*
|
|
3755
|
+
* | Flag | Behavior |
|
|
3756
|
+
* |---------|-----------------------------------------------------------------|
|
|
3757
|
+
* | `"r"` | Read-only. Fails if the file does not exist. |
|
|
3758
|
+
* | `"r+"` | Read-write. Fails if the file does not exist. |
|
|
3759
|
+
* | `"rs+"` | Read-write, bypasses OS cache (useful for NFS / shared drives). |
|
|
3760
|
+
* | `"w"` | Write-only. Creates the file or truncates it if it exists. |
|
|
3761
|
+
* | `"wx"` | Write-only. Fails if the file already exists (atomic create). |
|
|
3762
|
+
* | `"w+"` | Read-write. Creates the file or truncates it if it exists. |
|
|
3763
|
+
* | `"wx+"` | Read-write. Fails if the file already exists (atomic create). |
|
|
3764
|
+
* | `"a"` | Append-only. Creates the file if missing. Writes go to EOF. |
|
|
3765
|
+
* | `"ax"` | Append-only. Fails if the file already exists (atomic create). |
|
|
3766
|
+
* | `"a+"` | Read-append. Creates the file if missing. Writes always at EOF. |
|
|
3767
|
+
* | `"ax+"` | Read-append. Fails if the file already exists (atomic create). |
|
|
3768
|
+
*
|
|
3769
|
+
* > **`x` suffix** — Maps to `O_EXCL` at the OS level: the call succeeds only if
|
|
3770
|
+
* > *this* invocation creates the file, preventing race conditions.
|
|
3771
|
+
*
|
|
3772
|
+
* ---
|
|
3773
|
+
*
|
|
3774
|
+
* ### Transport strategy
|
|
3775
|
+
*
|
|
3776
|
+
* The method resolves the file descriptor through two transports, in order:
|
|
3777
|
+
*
|
|
3778
|
+
* 1. **IPC** (`XYPRISS_IPC_PATH` set) — communicates with the XHSC daemon via a
|
|
3779
|
+
* Unix socket. File descriptors are **stateful and persistent** across calls.
|
|
3780
|
+
* 2. **Runner fallback** — used when IPC is unavailable or the environment variable
|
|
3781
|
+
* is not set. Descriptors are **not persistent** across multiple independent calls;
|
|
3782
|
+
* a warning is emitted to the console.
|
|
3783
|
+
*
|
|
3784
|
+
* ---
|
|
3785
|
+
*
|
|
3786
|
+
* ### Callback (scoped) mode
|
|
3787
|
+
*
|
|
3788
|
+
* When a `callback` is provided, the file is opened, passed as a {@link FileHandle}
|
|
3789
|
+
* toolbox to the callback, then **automatically closed** in a `finally` block —
|
|
3790
|
+
* even if the callback throws. In this mode the method returns `void`.
|
|
3791
|
+
*
|
|
3792
|
+
* When no callback is provided, the raw numeric file descriptor is returned and
|
|
3793
|
+
* **the caller is responsible for closing it**.
|
|
3794
|
+
*
|
|
3795
|
+
* ---
|
|
3796
|
+
*
|
|
3797
|
+
* @param p - Absolute or relative path to the target file.
|
|
3798
|
+
* @param flags - Open mode, as a string flag (default: `"r"`) or a numeric
|
|
3799
|
+
* `os` constant. See the flag table above.
|
|
3800
|
+
* @param callback - Optional scoped handler receiving a {@link FileHandle}.
|
|
3801
|
+
* When supplied, the handle is closed automatically on completion.
|
|
3802
|
+
*
|
|
3803
|
+
* @returns The numeric file descriptor when no callback is given; `void` otherwise.
|
|
3804
|
+
*
|
|
3805
|
+
* @example <caption>Scoped read (handle closed automatically)</caption>
|
|
3806
|
+
* ```typescript
|
|
3807
|
+
* await __sys__.fs.open("data.bin", "r", async (file) => {
|
|
3808
|
+
* const chunk = await file.read(1024);
|
|
3809
|
+
* console.log(chunk.toString());
|
|
3810
|
+
* });
|
|
3811
|
+
* ```
|
|
3812
|
+
*
|
|
3813
|
+
* @example <caption>Manual descriptor (caller must close)</caption>
|
|
3814
|
+
* ```typescript
|
|
3815
|
+
* const fd = await __sys__.fs.open("output.log", "a");
|
|
3816
|
+
* // ... write operations ...
|
|
3817
|
+
* await __sys__.fs.close(fd);
|
|
3818
|
+
* ```
|
|
3819
|
+
*/
|
|
3820
|
+
open(p: string, flags?: FileOpenFlags, callback?: (handle: FileHandle) => Promise<void> | void): Promise<number | void>;
|
|
3821
|
+
/**
|
|
3822
|
+
* **Close File Handle**
|
|
3823
|
+
*
|
|
3824
|
+
* @param handle - The file handle to close.
|
|
3825
|
+
*/
|
|
3826
|
+
close: (handle: number) => Promise<void>;
|
|
3827
|
+
private mapFlags;
|
|
3622
3828
|
}
|
|
3623
3829
|
|
|
3624
3830
|
/**
|
|
@@ -4416,233 +4622,1715 @@ declare class EnvApi implements IEnvApi {
|
|
|
4416
4622
|
* const timeout = __sys__.__env__.get("REQUEST_TIMEOUT_MS", "5000");
|
|
4417
4623
|
* const ms = parseInt(timeout, 10);
|
|
4418
4624
|
*
|
|
4419
|
-
* // Concise fallback with nullish coalescing
|
|
4420
|
-
* const logLevel = __sys__.__env__.get("LOG_LEVEL") ?? "info";
|
|
4625
|
+
* // Concise fallback with nullish coalescing
|
|
4626
|
+
* const logLevel = __sys__.__env__.get("LOG_LEVEL") ?? "info";
|
|
4627
|
+
*/
|
|
4628
|
+
get(key: string): string | undefined;
|
|
4629
|
+
get(key: string, defaultValue: string): string;
|
|
4630
|
+
/**
|
|
4631
|
+
* Reads a required variable from the secure internal store and throws if
|
|
4632
|
+
* it cannot be resolved.
|
|
4633
|
+
*
|
|
4634
|
+
* Use this method for every variable that is mandatory for application
|
|
4635
|
+
* correctness. It surfaces configuration errors at startup rather than
|
|
4636
|
+
* silently producing `undefined` at the point of use.
|
|
4637
|
+
*
|
|
4638
|
+
* @param key - Variable name to look up.
|
|
4639
|
+
* @param options - Optional validation settings.
|
|
4640
|
+
* @returns The stored value, guaranteed non-undefined.
|
|
4641
|
+
* @throws {EnvAccessError} When the variable is missing or empty.
|
|
4642
|
+
* @throws {EnvStoreError} When the store has not been initialised.
|
|
4643
|
+
*
|
|
4644
|
+
* @example
|
|
4645
|
+
* // Fail fast at boot if a critical variable is absent
|
|
4646
|
+
* const databaseUrl = __sys__.__env__.getStrict("DATABASE_URL");
|
|
4647
|
+
* const jwtSecret = __sys__.__env__.getStrict("JWT_SECRET", { rejectEmpty: true });
|
|
4648
|
+
* const smtpHost = __sys__.__env__.getStrict("SMTP_HOST");
|
|
4649
|
+
*
|
|
4650
|
+
* // Collect all required variables once at module initialisation
|
|
4651
|
+
* const config = {
|
|
4652
|
+
* db: __sys__.__env__.getStrict("DATABASE_URL"),
|
|
4653
|
+
* jwt: __sys__.__env__.getStrict("JWT_SECRET", { rejectEmpty: true }),
|
|
4654
|
+
* smtp: __sys__.__env__.getStrict("SMTP_HOST"),
|
|
4655
|
+
* };
|
|
4656
|
+
*/
|
|
4657
|
+
getStrict(key: string, options?: EnvGetStrictOptions): string;
|
|
4658
|
+
/**
|
|
4659
|
+
* Returns `true` when the given key is present in the secure internal
|
|
4660
|
+
* store, regardless of its value (including empty strings).
|
|
4661
|
+
*
|
|
4662
|
+
* @param key - Variable name to test.
|
|
4663
|
+
* @throws {EnvStoreError} When the store has not been initialised.
|
|
4664
|
+
*
|
|
4665
|
+
* @example
|
|
4666
|
+
* if (__sys__.__env__.has("SENTRY_DSN")) {
|
|
4667
|
+
* Sentry.init({ dsn: __sys__.__env__.get("SENTRY_DSN") });
|
|
4668
|
+
* }
|
|
4669
|
+
*
|
|
4670
|
+
* const betaEnabled = __sys__.__env__.has("ENABLE_BETA_UI");
|
|
4671
|
+
*/
|
|
4672
|
+
has(key: string): boolean;
|
|
4673
|
+
/**
|
|
4674
|
+
* Returns a frozen, point-in-time snapshot of stored variables.
|
|
4675
|
+
*
|
|
4676
|
+
* The object is frozen at the moment of the call; subsequent `set` or
|
|
4677
|
+
* `delete` calls do not affect it.
|
|
4678
|
+
*
|
|
4679
|
+
* Providing `options.keys` is strongly recommended in production code.
|
|
4680
|
+
* Returning the full store risks inadvertently capturing secrets in log
|
|
4681
|
+
* statements or JSON serialisations.
|
|
4682
|
+
*
|
|
4683
|
+
* @param options - Optional filter configuration.
|
|
4684
|
+
* @returns A frozen {@link EnvSnapshot}.
|
|
4685
|
+
* @throws {EnvStoreError} When the store has not been initialised.
|
|
4686
|
+
*
|
|
4687
|
+
* @example
|
|
4688
|
+
* // Filtered snapshot — preferred in all production code paths
|
|
4689
|
+
* const dbConfig = __sys__.__env__.all({
|
|
4690
|
+
* keys: ["DATABASE_URL", "DATABASE_POOL_SIZE", "DATABASE_TIMEOUT_MS"],
|
|
4691
|
+
* });
|
|
4692
|
+
*
|
|
4693
|
+
* // Full snapshot — use only for diagnostics / startup validation
|
|
4694
|
+
* const full = __sys__.__env__.all();
|
|
4695
|
+
* logger.debug("Env snapshot", { count: Object.keys(full).length });
|
|
4696
|
+
*/
|
|
4697
|
+
all(options?: EnvAllOptions): EnvSnapshot;
|
|
4698
|
+
/**
|
|
4699
|
+
* Returns `true` when the execution mode is `"production"`.
|
|
4700
|
+
*
|
|
4701
|
+
* @example
|
|
4702
|
+
* const logger = createLogger({
|
|
4703
|
+
* level: __sys__.__env__.isProduction() ? "error" : "debug",
|
|
4704
|
+
* });
|
|
4705
|
+
*/
|
|
4706
|
+
isProduction(): boolean;
|
|
4707
|
+
/**
|
|
4708
|
+
* Returns `true` when the execution mode is `"development"`.
|
|
4709
|
+
*
|
|
4710
|
+
* @example
|
|
4711
|
+
* if (__sys__.__env__.isDevelopment()) {
|
|
4712
|
+
* app.use(requestLogger({ colorize: true }));
|
|
4713
|
+
* }
|
|
4714
|
+
*/
|
|
4715
|
+
isDevelopment(): boolean;
|
|
4716
|
+
/**
|
|
4717
|
+
* Returns `true` when the execution mode is `"staging"`.
|
|
4718
|
+
*
|
|
4719
|
+
* @example
|
|
4720
|
+
* if (__sys__.__env__.isStaging()) {
|
|
4721
|
+
* payment.useSandbox();
|
|
4722
|
+
* }
|
|
4723
|
+
*/
|
|
4724
|
+
isStaging(): boolean;
|
|
4725
|
+
/**
|
|
4726
|
+
* Returns `true` when the execution mode is `"test"`.
|
|
4727
|
+
*
|
|
4728
|
+
* @example
|
|
4729
|
+
* const dbUrl = __sys__.__env__.isTest()
|
|
4730
|
+
* ? __sys__.__env__.getStrict("TEST_DATABASE_URL")
|
|
4731
|
+
* : __sys__.__env__.getStrict("DATABASE_URL");
|
|
4732
|
+
*/
|
|
4733
|
+
isTest(): boolean;
|
|
4734
|
+
/**
|
|
4735
|
+
* Returns `true` when the execution mode exactly matches `envName`
|
|
4736
|
+
* (case-sensitive).
|
|
4737
|
+
*
|
|
4738
|
+
* @param envName - Mode name to compare against.
|
|
4739
|
+
*
|
|
4740
|
+
* @example
|
|
4741
|
+
* if (__sys__.__env__.is("canary")) {
|
|
4742
|
+
* featureFlags.enableAll();
|
|
4743
|
+
* }
|
|
4744
|
+
*/
|
|
4745
|
+
is(envName: string): boolean;
|
|
4746
|
+
/**
|
|
4747
|
+
* Retrieves the OS-level username of the current process owner by invoking
|
|
4748
|
+
* the XHSC native Go binary.
|
|
4749
|
+
*
|
|
4750
|
+
* This method is synchronous and blocks until the native call completes.
|
|
4751
|
+
* Do not call it in request hot paths. Returns `""` on failure so callers
|
|
4752
|
+
* can safely use the result without null checks.
|
|
4753
|
+
*
|
|
4754
|
+
* @returns The current OS username, or `""` on failure.
|
|
4755
|
+
*
|
|
4756
|
+
* @example
|
|
4757
|
+
* const actor = __sys__.__env__.user() || "<unknown>";
|
|
4758
|
+
* auditLog.write({ actor, action: "deploy" });
|
|
4759
|
+
*/
|
|
4760
|
+
user(): string;
|
|
4761
|
+
/**
|
|
4762
|
+
* Returns the internal store, throwing {@link EnvStoreError} if it has not
|
|
4763
|
+
* yet been initialised.
|
|
4764
|
+
*
|
|
4765
|
+
* SECURITY: This is the single point of store access. Every read and write
|
|
4766
|
+
* method must go through here — never access `globalThis[XY_ENV_STORE_KEY]`
|
|
4767
|
+
* directly outside this method.
|
|
4768
|
+
*
|
|
4769
|
+
* Eliminating the `?? process.env` fallback is intentional. A silent
|
|
4770
|
+
* fallback to `process.env` during the bootstrap race window would bypass
|
|
4771
|
+
* the Shield and leak values without any warning. A thrown error is
|
|
4772
|
+
* immediately visible during development and integration testing.
|
|
4773
|
+
*
|
|
4774
|
+
* @internal
|
|
4775
|
+
* @throws {EnvStoreError}
|
|
4776
|
+
*/
|
|
4777
|
+
private requireStoreMap;
|
|
4778
|
+
private getStoreForCaller;
|
|
4779
|
+
/**
|
|
4780
|
+
* Asserts that `key` is a valid environment variable name.
|
|
4781
|
+
*
|
|
4782
|
+
* @internal
|
|
4783
|
+
* @throws {EnvKeyError}
|
|
4784
|
+
*/
|
|
4785
|
+
private validateKey;
|
|
4786
|
+
/**
|
|
4787
|
+
* Asserts that `value` does not contain characters that can corrupt
|
|
4788
|
+
* downstream parsers, log sinks, or HTTP serialisers.
|
|
4789
|
+
*
|
|
4790
|
+
* Rejected characters:
|
|
4791
|
+
* - CR (`\r`) and LF (`\n`) — break line-oriented `.env` parsers and
|
|
4792
|
+
* enable log injection attacks.
|
|
4793
|
+
* - NUL (`\0`) — truncates strings in C-based runtimes and can bypass
|
|
4794
|
+
* suffix-based extension checks in some file path handling code.
|
|
4795
|
+
*
|
|
4796
|
+
* @internal
|
|
4797
|
+
* @throws {EnvKeyError}
|
|
4798
|
+
*/
|
|
4799
|
+
private validateValue;
|
|
4800
|
+
/**
|
|
4801
|
+
* **Environment Security Shield**
|
|
4802
|
+
*
|
|
4803
|
+
* Replaces the `process.env` object with a hardened Proxy that enforces
|
|
4804
|
+
* the following policies on every property access:
|
|
4805
|
+
*
|
|
4806
|
+
* **Read trap**
|
|
4807
|
+
* - Whitelisted keys (see {@link EnvApi.whitelistedFields}) and keys
|
|
4808
|
+
* matching the prefixes `XY_`, `XYPRISS_`, `ENC_`, `DOTENV_`, or `__`
|
|
4809
|
+
* pass through to the real value.
|
|
4810
|
+
* - All other reads return `undefined`. A one-time per-key warning is
|
|
4811
|
+
* written to `process.stderr` (suppressed when
|
|
4812
|
+
* `XYPRISS_ENV_SHIELD=silent`).
|
|
4813
|
+
*
|
|
4814
|
+
* **`ownKeys` and `has` traps**
|
|
4815
|
+
* - Restrict the apparent key set to the whitelist. This prevents
|
|
4816
|
+
* third-party code from enumerating the real store through
|
|
4817
|
+
* `Object.keys(process.env)`, `JSON.stringify(process.env)`, or spread
|
|
4818
|
+
* operators — all of which bypass the `get` trap.
|
|
4819
|
+
*
|
|
4820
|
+
* The descriptor is applied with `writable: false` to prevent replacement
|
|
4821
|
+
* by application code, and `configurable: true` to allow test teardown.
|
|
4822
|
+
*
|
|
4823
|
+
* @internal
|
|
4824
|
+
*/
|
|
4825
|
+
/**
|
|
4826
|
+
* **Environment Security Shield**
|
|
4827
|
+
*
|
|
4828
|
+
* Replaces the `process.env` object with a hardened Proxy that enforces
|
|
4829
|
+
* the following policies on every property access:
|
|
4830
|
+
*
|
|
4831
|
+
* **Read trap**
|
|
4832
|
+
* - Whitelisted keys (see {@link EnvApi.whitelistedFields}) and keys
|
|
4833
|
+
* matching the prefixes `XY_`, `XYPRISS_`, `ENC_`, `DOTENV_`, or `__`
|
|
4834
|
+
* pass through to the real value.
|
|
4835
|
+
* - All other reads return `undefined`. A one-time per-key warning is
|
|
4836
|
+
* written to `process.stderr` (suppressed when
|
|
4837
|
+
* `XYPRISS_ENV_SHIELD=silent`).
|
|
4838
|
+
*
|
|
4839
|
+
* **`ownKeys` and `has` traps**
|
|
4840
|
+
* - Restrict the apparent key set to the whitelist. This prevents
|
|
4841
|
+
* third-party code from enumerating the real store through
|
|
4842
|
+
* `Object.keys(process.env)`, `JSON.stringify(process.env)`, or spread
|
|
4843
|
+
* operators — all of which bypass the `get` trap.
|
|
4844
|
+
*
|
|
4845
|
+
* The descriptor is applied with `writable: false` to prevent replacement
|
|
4846
|
+
* by application code, and `configurable: true` to allow test teardown.
|
|
4847
|
+
*
|
|
4848
|
+
* @internal
|
|
4849
|
+
*/
|
|
4850
|
+
private applyShield;
|
|
4851
|
+
private isCallerProjectCode;
|
|
4852
|
+
}
|
|
4853
|
+
|
|
4854
|
+
/**
|
|
4855
|
+
* **StringUtils — XyPriss String Utilities**
|
|
4856
|
+
*/
|
|
4857
|
+
declare class StringUtils {
|
|
4858
|
+
/**
|
|
4859
|
+
* **Generate a Random String**
|
|
4860
|
+
*
|
|
4861
|
+
* Generates a pseudo-random character sequence of a specified length.
|
|
4862
|
+
* Uses alphanumeric characters (A-Z, a-z, 0-9).
|
|
4863
|
+
*
|
|
4864
|
+
* @param length - The desired length of the string (default: `10`).
|
|
4865
|
+
* @returns A random alphanumeric string.
|
|
4866
|
+
*
|
|
4867
|
+
* @example
|
|
4868
|
+
* ```ts
|
|
4869
|
+
* utils.randomString(8); // "a7B2k9Xz"
|
|
4870
|
+
* ```
|
|
4871
|
+
*/
|
|
4872
|
+
randomString(length?: number): string;
|
|
4873
|
+
/**
|
|
4874
|
+
* **Slugify a String**
|
|
4875
|
+
*
|
|
4876
|
+
* Converts a string into a URL-friendly "slug" by lowering case,
|
|
4877
|
+
* removing non-alphanumeric characters, and replacing spaces with hyphens.
|
|
4878
|
+
*
|
|
4879
|
+
* @param text - The string to slugify.
|
|
4880
|
+
* @returns The URL-friendly slug.
|
|
4881
|
+
*
|
|
4882
|
+
* @example
|
|
4883
|
+
* ```ts
|
|
4884
|
+
* utils.slugify("Hello World!"); // "hello-world"
|
|
4885
|
+
* ```
|
|
4886
|
+
*/
|
|
4887
|
+
slugify(text: string): string;
|
|
4888
|
+
/**
|
|
4889
|
+
* **Truncate a String**
|
|
4890
|
+
*
|
|
4891
|
+
* Shortens a string to a specified length and appends a suffix (default: `...`)
|
|
4892
|
+
* if the original string was longer than the limit.
|
|
4893
|
+
*
|
|
4894
|
+
* @param text - The string to truncate.
|
|
4895
|
+
* @param maxLength - Maximum length including the suffix.
|
|
4896
|
+
* @param suffix - The string to append (default: `"..."`).
|
|
4897
|
+
* @returns The truncated string.
|
|
4898
|
+
*
|
|
4899
|
+
* @example
|
|
4900
|
+
* ```ts
|
|
4901
|
+
* utils.truncate("Very long sentence", 10); // "Very lo..."
|
|
4902
|
+
* ```
|
|
4903
|
+
*/
|
|
4904
|
+
truncate(text: string, maxLength: number, suffix?: string): string;
|
|
4905
|
+
/**
|
|
4906
|
+
* **Capitalize a String**
|
|
4907
|
+
*
|
|
4908
|
+
* Uppercases the first character of the string.
|
|
4909
|
+
*
|
|
4910
|
+
* @param text - The string to capitalize.
|
|
4911
|
+
* @returns The capitalized string.
|
|
4912
|
+
*/
|
|
4913
|
+
capitalize(text: string): string;
|
|
4914
|
+
/**
|
|
4915
|
+
* **Convert to camelCase**
|
|
4916
|
+
*
|
|
4917
|
+
* Converts hyphen-separated, underscore-separated, or space-separated
|
|
4918
|
+
* strings into camelCase.
|
|
4919
|
+
*
|
|
4920
|
+
* @param text - The string to convert.
|
|
4921
|
+
* @returns The camelCase string.
|
|
4922
|
+
*/
|
|
4923
|
+
toCamelCase(text: string): string;
|
|
4924
|
+
/**
|
|
4925
|
+
* **Pad a String**
|
|
4926
|
+
*
|
|
4927
|
+
* Adds padding characters to the start or end of a string until it
|
|
4928
|
+
* reaches the target length.
|
|
4929
|
+
*
|
|
4930
|
+
* @param text - The source string.
|
|
4931
|
+
* @param length - Target length.
|
|
4932
|
+
* @param char - Padding character (default: `" "`).
|
|
4933
|
+
* @param position - Whether to pad at `"start"` or `"end"`.
|
|
4934
|
+
* @returns The padded string.
|
|
4935
|
+
*/
|
|
4936
|
+
pad(text: string, length: number, char?: string, position?: "start" | "end"): string;
|
|
4937
|
+
/**
|
|
4938
|
+
* **Count Word/Substring Occurrences**
|
|
4939
|
+
*
|
|
4940
|
+
* Returns the number of times a specific word or substring appears.
|
|
4941
|
+
*
|
|
4942
|
+
* @param text - The body of text to search.
|
|
4943
|
+
* @param word - The substring to look for.
|
|
4944
|
+
* @param caseSensitive - Whether to respect case (default: `false`).
|
|
4945
|
+
* @returns The number of occurrences.
|
|
4946
|
+
*/
|
|
4947
|
+
countOccurrences(text: string, word: string, caseSensitive?: boolean): number;
|
|
4948
|
+
/**
|
|
4949
|
+
* **toQueryString**
|
|
4950
|
+
*
|
|
4951
|
+
* Serializes a flat record into a URL-encoded query string format.
|
|
4952
|
+
*
|
|
4953
|
+
* @param params The object to serialize.
|
|
4954
|
+
* @returns The query string.
|
|
4955
|
+
*/
|
|
4956
|
+
toQueryString(params: Record<string, unknown>): string;
|
|
4957
|
+
}
|
|
4958
|
+
|
|
4959
|
+
/**
|
|
4960
|
+
* **NumberUtils — XyPriss Number & Math Utilities**
|
|
4961
|
+
*/
|
|
4962
|
+
declare class NumberUtils {
|
|
4963
|
+
/**
|
|
4964
|
+
* **Clamp a Value**
|
|
4965
|
+
*
|
|
4966
|
+
* Restricts a numeric value to a defined range [min, max].
|
|
4967
|
+
*
|
|
4968
|
+
* @param value - The value to clamp.
|
|
4969
|
+
* @param min - The lower bound.
|
|
4970
|
+
* @param max - The upper bound.
|
|
4971
|
+
* @returns The clamped value.
|
|
4972
|
+
*/
|
|
4973
|
+
clamp(value: number, min: number, max: number): number;
|
|
4974
|
+
/**
|
|
4975
|
+
* **Linear Interpolation (LERP)**
|
|
4976
|
+
*
|
|
4977
|
+
* Returns the linear interpolation between `start` and `end` for a factor `t`.
|
|
4978
|
+
*
|
|
4979
|
+
* @param start - The start value.
|
|
4980
|
+
* @param end - The end value.
|
|
4981
|
+
* @param t - The interpolation factor (0.0 to 1.0).
|
|
4982
|
+
* @returns The interpolated value.
|
|
4983
|
+
*/
|
|
4984
|
+
lerp(start: number, end: number, t: number): number;
|
|
4985
|
+
/**
|
|
4986
|
+
* **Get a Random Integer**
|
|
4987
|
+
*
|
|
4988
|
+
* Returns a random integer between min (inclusive) and max (inclusive).
|
|
4989
|
+
*
|
|
4990
|
+
* @param min - Minimum value.
|
|
4991
|
+
* @param max - Maximum value.
|
|
4992
|
+
* @returns A random integer.
|
|
4993
|
+
*/
|
|
4994
|
+
randomInt(min: number, max: number): number;
|
|
4995
|
+
/**
|
|
4996
|
+
* **Format Number**
|
|
4997
|
+
*
|
|
4998
|
+
* Locale-aware number formatting.
|
|
4999
|
+
*
|
|
5000
|
+
* @param value - The number to format.
|
|
5001
|
+
* @param locale - Optional locale (default: `en-US`).
|
|
5002
|
+
* @param options - Intl.NumberFormatOptions.
|
|
5003
|
+
* @returns A localized string.
|
|
5004
|
+
*/
|
|
5005
|
+
formatNumber(value: number, locale?: string, options?: Intl.NumberFormatOptions): string;
|
|
5006
|
+
/**
|
|
5007
|
+
* **Format Bytes**
|
|
5008
|
+
*
|
|
5009
|
+
* Converts raw bytes into a human-readable size string (KB, MB, GB, etc.).
|
|
5010
|
+
*
|
|
5011
|
+
* @param bytes - The number of bytes.
|
|
5012
|
+
* @param decimals - Decimal precision.
|
|
5013
|
+
* @returns A human-readable size string.
|
|
5014
|
+
*/
|
|
5015
|
+
formatBytes(bytes: number, decimals?: number): string;
|
|
5016
|
+
}
|
|
5017
|
+
|
|
5018
|
+
/**
|
|
5019
|
+
* @file DateUtils.ts
|
|
5020
|
+
* @description XyPriss Date & Time Utilities — A comprehensive, zero-dependency
|
|
5021
|
+
* date/time utility class built on the native `Date` object and the `Intl` API.
|
|
5022
|
+
*
|
|
5023
|
+
* @remarks
|
|
5024
|
+
* All methods are pure and side-effect-free unless otherwise noted.
|
|
5025
|
+
* Timestamps can be provided in either **seconds** (Unix) or **milliseconds**
|
|
5026
|
+
* (JavaScript). The class auto-detects the unit using the heuristic:
|
|
5027
|
+
* values below `1e11` are treated as seconds; values at or above `1e11` are
|
|
5028
|
+
* treated as milliseconds. This heuristic is valid until **November 2286**.
|
|
5029
|
+
*
|
|
5030
|
+
* @example
|
|
5031
|
+
* ```ts
|
|
5032
|
+
* const du = new DateUtils();
|
|
5033
|
+
*
|
|
5034
|
+
* du.format(Date.now()); // "Apr 15, 2026"
|
|
5035
|
+
* du.timeAgo(Date.now() - 90_000); // "2 minutes ago"
|
|
5036
|
+
* du.formatDuration(3_661_000); // "1h 1m 1s"
|
|
5037
|
+
* du.startOf("month"); // 2026-04-01T00:00:00.000Z
|
|
5038
|
+
* ```
|
|
5039
|
+
*/
|
|
5040
|
+
declare class DateUtils {
|
|
5041
|
+
/**
|
|
5042
|
+
* Converts any supported input value to a `Date` object.
|
|
5043
|
+
*
|
|
5044
|
+
* Supported inputs:
|
|
5045
|
+
* - `Date` — returned as-is (not cloned).
|
|
5046
|
+
* - `number` — auto-detected as Unix seconds (`< 1e11`) or milliseconds.
|
|
5047
|
+
* - `string` — parsed via `new Date(string)` (ISO 8601 recommended).
|
|
5048
|
+
*
|
|
5049
|
+
* @param date - The value to convert.
|
|
5050
|
+
* @returns The corresponding `Date` object.
|
|
5051
|
+
* @throws {RangeError} If the resulting `Date` is invalid.
|
|
5052
|
+
*
|
|
5053
|
+
* @internal
|
|
5054
|
+
*/
|
|
5055
|
+
private toDate;
|
|
5056
|
+
/**
|
|
5057
|
+
* Converts any supported input value to a millisecond timestamp.
|
|
5058
|
+
*
|
|
5059
|
+
* @param date - The value to convert.
|
|
5060
|
+
* @returns Milliseconds since the Unix epoch.
|
|
5061
|
+
*
|
|
5062
|
+
* @internal
|
|
5063
|
+
*/
|
|
5064
|
+
private toMs;
|
|
5065
|
+
/**
|
|
5066
|
+
* Returns the current Unix timestamp in **seconds**.
|
|
5067
|
+
*
|
|
5068
|
+
* @returns The current time as a Unix timestamp (integer seconds).
|
|
5069
|
+
*
|
|
5070
|
+
* @example
|
|
5071
|
+
* ```ts
|
|
5072
|
+
* du.now(); // e.g. 1776287197
|
|
5073
|
+
* ```
|
|
5074
|
+
*/
|
|
5075
|
+
now(): number;
|
|
5076
|
+
/**
|
|
5077
|
+
* Returns the current time as a JavaScript timestamp in **milliseconds**.
|
|
5078
|
+
*
|
|
5079
|
+
* Equivalent to `Date.now()`.
|
|
5080
|
+
*
|
|
5081
|
+
* @returns The current time in milliseconds since the Unix epoch.
|
|
5082
|
+
*
|
|
5083
|
+
* @example
|
|
5084
|
+
* ```ts
|
|
5085
|
+
* du.nowMs(); // e.g. 1776287197000
|
|
5086
|
+
* ```
|
|
5087
|
+
*/
|
|
5088
|
+
nowMs(): number;
|
|
5089
|
+
/**
|
|
5090
|
+
* Returns the current time as a `Date` object.
|
|
5091
|
+
*
|
|
5092
|
+
* @returns A new `Date` representing the current instant.
|
|
5093
|
+
*
|
|
5094
|
+
* @example
|
|
5095
|
+
* ```ts
|
|
5096
|
+
* du.today(); // Date { ... }
|
|
5097
|
+
* ```
|
|
5098
|
+
*/
|
|
5099
|
+
today(): Date;
|
|
5100
|
+
/**
|
|
5101
|
+
* Serializes a date value into a localized string using `Intl.DateTimeFormat`.
|
|
5102
|
+
*
|
|
5103
|
+
* Automatically handles Unix timestamps (seconds) and JavaScript timestamps
|
|
5104
|
+
* (milliseconds) via the `< 1e11` heuristic.
|
|
5105
|
+
*
|
|
5106
|
+
* @param date - The input to format: `Date`, number (timestamp), or ISO string.
|
|
5107
|
+
* @param locale - BCP 47 locale tag (default: `"en-US"`).
|
|
5108
|
+
* @param options - `Intl.DateTimeFormatOptions` to customize the output.
|
|
5109
|
+
* @returns A localized date string.
|
|
5110
|
+
*
|
|
5111
|
+
* @example
|
|
5112
|
+
* ```ts
|
|
5113
|
+
* du.format(1776287197);
|
|
5114
|
+
* // → "Apr 15, 2026"
|
|
5115
|
+
*
|
|
5116
|
+
* du.format(new Date(), "fr-FR", { dateStyle: "full" });
|
|
5117
|
+
* // → "mercredi 15 avril 2026"
|
|
5118
|
+
*
|
|
5119
|
+
* du.format("2026-04-15T12:00:00Z", "en-GB", { timeStyle: "short" });
|
|
5120
|
+
* // → "12:00"
|
|
5121
|
+
* ```
|
|
5122
|
+
*/
|
|
5123
|
+
format(date: Date | number | string, locale?: string, options?: Intl.DateTimeFormatOptions): string;
|
|
5124
|
+
/**
|
|
5125
|
+
* Formats a date as an ISO 8601 string (`YYYY-MM-DDTHH:mm:ss.sssZ`).
|
|
5126
|
+
*
|
|
5127
|
+
* This is the format recommended for data interchange and storage.
|
|
5128
|
+
*
|
|
5129
|
+
* @param date - The date to format (default: current time).
|
|
5130
|
+
* @returns An ISO 8601 UTC string.
|
|
5131
|
+
*
|
|
5132
|
+
* @example
|
|
5133
|
+
* ```ts
|
|
5134
|
+
* du.toISO();
|
|
5135
|
+
* // → "2026-04-15T10:30:00.000Z"
|
|
5136
|
+
*
|
|
5137
|
+
* du.toISO(1776287197);
|
|
5138
|
+
* // → "2026-04-15T..."
|
|
5139
|
+
* ```
|
|
5140
|
+
*/
|
|
5141
|
+
toISO(date?: Date | number | string): string;
|
|
5142
|
+
/**
|
|
5143
|
+
* Formats a date as a plain date string: `YYYY-MM-DD`.
|
|
5144
|
+
*
|
|
5145
|
+
* The date is rendered in **local time** unless a UTC flag is set.
|
|
5146
|
+
*
|
|
5147
|
+
* @param date - The date to format (default: current time).
|
|
5148
|
+
* @param utc - If `true`, use UTC date components instead of local time (default: `false`).
|
|
5149
|
+
* @returns A date-only string in `YYYY-MM-DD` format.
|
|
5150
|
+
*
|
|
5151
|
+
* @example
|
|
5152
|
+
* ```ts
|
|
5153
|
+
* du.toDateString();
|
|
5154
|
+
* // → "2026-04-15"
|
|
5155
|
+
*
|
|
5156
|
+
* du.toDateString(new Date("2026-12-31T23:59:00Z"), true);
|
|
5157
|
+
* // → "2026-12-31"
|
|
5158
|
+
* ```
|
|
5159
|
+
*/
|
|
5160
|
+
toDateString(date?: Date | number | string, utc?: boolean): string;
|
|
5161
|
+
/**
|
|
5162
|
+
* Formats a date as a time string: `HH:mm:ss`.
|
|
5163
|
+
*
|
|
5164
|
+
* The time is rendered in **local time** unless the UTC flag is set.
|
|
5165
|
+
*
|
|
5166
|
+
* @param date - The date to format (default: current time).
|
|
5167
|
+
* @param utc - If `true`, use UTC time components (default: `false`).
|
|
5168
|
+
* @returns A time-only string in `HH:mm:ss` format.
|
|
5169
|
+
*
|
|
5170
|
+
* @example
|
|
5171
|
+
* ```ts
|
|
5172
|
+
* du.toTimeString(new Date("2026-04-15T08:05:03Z"), true);
|
|
5173
|
+
* // → "08:05:03"
|
|
5174
|
+
* ```
|
|
5175
|
+
*/
|
|
5176
|
+
toTimeString(date?: Date | number | string, utc?: boolean): string;
|
|
5177
|
+
/**
|
|
5178
|
+
* Converts a duration into a human-readable string (e.g., `"1d 2h 30m 5s"`).
|
|
5179
|
+
*
|
|
5180
|
+
* Components are omitted when their value is zero, except for seconds which
|
|
5181
|
+
* always appear when the total duration is less than one minute.
|
|
5182
|
+
*
|
|
5183
|
+
* @param value - The duration to format.
|
|
5184
|
+
* @param unit - The unit of `value`: `"ms"` (milliseconds, default) or `"s"` (seconds).
|
|
5185
|
+
* @returns A compact, space-separated duration string.
|
|
5186
|
+
*
|
|
5187
|
+
* @example
|
|
5188
|
+
* ```ts
|
|
5189
|
+
* du.formatDuration(3_661_000); // → "1h 1m 1s"
|
|
5190
|
+
* du.formatDuration(90, "s"); // → "1m 30s"
|
|
5191
|
+
* du.formatDuration(0); // → "0s"
|
|
5192
|
+
* du.formatDuration(86_400_000); // → "1d"
|
|
5193
|
+
* ```
|
|
5194
|
+
*/
|
|
5195
|
+
formatDuration(value: number, unit?: "ms" | "s"): string;
|
|
5196
|
+
/**
|
|
5197
|
+
* Returns a relative time string (e.g., `"5 minutes ago"`, `"in 2 hours"`).
|
|
5198
|
+
*
|
|
5199
|
+
* Uses `Intl.RelativeTimeFormat` for locale-aware output. Automatically
|
|
5200
|
+
* selects the most appropriate unit (second → minute → hour → day → month → year).
|
|
5201
|
+
*
|
|
5202
|
+
* @param date - The reference date, in the past or future.
|
|
5203
|
+
* @param locale - BCP 47 locale tag (default: `"en-US"`).
|
|
5204
|
+
* @returns A localized relative time string.
|
|
5205
|
+
*
|
|
5206
|
+
* @example
|
|
5207
|
+
* ```ts
|
|
5208
|
+
* du.timeAgo(Date.now() - 90_000); // → "2 minutes ago"
|
|
5209
|
+
* du.timeAgo(Date.now() + 3_600_000); // → "in 1 hour"
|
|
5210
|
+
* du.timeAgo(Date.now() - 90_000, "fr"); // → "il y a 2 minutes"
|
|
5211
|
+
* ```
|
|
5212
|
+
*/
|
|
5213
|
+
timeAgo(date: Date | number | string, locale?: string): string;
|
|
5214
|
+
/**
|
|
5215
|
+
* Adds a given amount of time to a date and returns a new `Date`.
|
|
5216
|
+
*
|
|
5217
|
+
* Supported units: `"ms"`, `"s"` (seconds), `"m"` (minutes), `"h"` (hours),
|
|
5218
|
+
* `"d"` (days), `"w"` (weeks), `"mo"` (months), `"y"` (years).
|
|
5219
|
+
*
|
|
5220
|
+
* Month and year arithmetic is handled using `setMonth` / `setFullYear`,
|
|
5221
|
+
* which correctly accounts for varying month lengths (e.g., adding 1 month
|
|
5222
|
+
* to January 31 yields February 28/29).
|
|
5223
|
+
*
|
|
5224
|
+
* @param date - The starting date.
|
|
5225
|
+
* @param value - The amount to add (can be negative to subtract).
|
|
5226
|
+
* @param unit - The time unit.
|
|
5227
|
+
* @returns A new `Date` offset by the specified amount.
|
|
5228
|
+
*
|
|
5229
|
+
* @example
|
|
5230
|
+
* ```ts
|
|
5231
|
+
* du.add(new Date("2026-01-31"), 1, "mo");
|
|
5232
|
+
* // → Date("2026-02-28") — accounts for shorter February
|
|
5233
|
+
*
|
|
5234
|
+
* du.add(new Date("2026-04-15"), -7, "d");
|
|
5235
|
+
* // → Date("2026-04-08")
|
|
5236
|
+
*
|
|
5237
|
+
* du.add(Date.now(), 2, "h");
|
|
5238
|
+
* // → Date 2 hours from now
|
|
5239
|
+
* ```
|
|
5240
|
+
*/
|
|
5241
|
+
add(date: Date | number | string, value: number, unit: "ms" | "s" | "m" | "h" | "d" | "w" | "mo" | "y"): Date;
|
|
5242
|
+
/**
|
|
5243
|
+
* Subtracts a given amount of time from a date and returns a new `Date`.
|
|
5244
|
+
*
|
|
5245
|
+
* This is a convenience wrapper around {@link add} with a negated `value`.
|
|
5246
|
+
*
|
|
5247
|
+
* @param date - The starting date.
|
|
5248
|
+
* @param value - The amount to subtract (must be positive).
|
|
5249
|
+
* @param unit - The time unit (same options as {@link add}).
|
|
5250
|
+
* @returns A new `Date` shifted back by the specified amount.
|
|
5251
|
+
*
|
|
5252
|
+
* @example
|
|
5253
|
+
* ```ts
|
|
5254
|
+
* du.subtract(new Date("2026-03-01"), 1, "mo");
|
|
5255
|
+
* // → Date("2026-02-01")
|
|
5256
|
+
* ```
|
|
5257
|
+
*/
|
|
5258
|
+
subtract(date: Date | number | string, value: number, unit: "ms" | "s" | "m" | "h" | "d" | "w" | "mo" | "y"): Date;
|
|
5259
|
+
/**
|
|
5260
|
+
* Returns the difference between two dates in the specified unit.
|
|
5261
|
+
*
|
|
5262
|
+
* The result is the **signed** difference `(dateA - dateB)` truncated
|
|
5263
|
+
* toward zero. A positive value means `dateA` is later than `dateB`.
|
|
5264
|
+
*
|
|
5265
|
+
* Supported units: `"ms"`, `"s"`, `"m"`, `"h"`, `"d"`, `"w"`.
|
|
5266
|
+
* Month and year differences are intentionally excluded because their
|
|
5267
|
+
* variable length makes a lossless inverse impossible; use {@link add}
|
|
5268
|
+
* and calendar-aware logic for those cases.
|
|
5269
|
+
*
|
|
5270
|
+
* @param dateA - The first date.
|
|
5271
|
+
* @param dateB - The second date.
|
|
5272
|
+
* @param unit - The unit for the result (default: `"ms"`).
|
|
5273
|
+
* @returns The signed integer difference in the requested unit.
|
|
5274
|
+
*
|
|
5275
|
+
* @example
|
|
5276
|
+
* ```ts
|
|
5277
|
+
* du.diff("2026-04-20", "2026-04-15", "d"); // → 5
|
|
5278
|
+
* du.diff("2026-04-10", "2026-04-15", "d"); // → -5
|
|
5279
|
+
* du.diff(Date.now(), Date.now() - 3600_000, "h"); // → 1
|
|
5280
|
+
* ```
|
|
5281
|
+
*/
|
|
5282
|
+
diff(dateA: Date | number | string, dateB: Date | number | string, unit?: "ms" | "s" | "m" | "h" | "d" | "w"): number;
|
|
5283
|
+
/**
|
|
5284
|
+
* Returns `true` if `dateA` is strictly before `dateB`.
|
|
5285
|
+
*
|
|
5286
|
+
* @param dateA - The first date.
|
|
5287
|
+
* @param dateB - The second date.
|
|
5288
|
+
* @returns `true` if `dateA < dateB`.
|
|
5289
|
+
*
|
|
5290
|
+
* @example
|
|
5291
|
+
* ```ts
|
|
5292
|
+
* du.isBefore("2026-01-01", "2026-06-01"); // → true
|
|
5293
|
+
* ```
|
|
5294
|
+
*/
|
|
5295
|
+
isBefore(dateA: Date | number | string, dateB: Date | number | string): boolean;
|
|
5296
|
+
/**
|
|
5297
|
+
* Returns `true` if `dateA` is strictly after `dateB`.
|
|
5298
|
+
*
|
|
5299
|
+
* @param dateA - The first date.
|
|
5300
|
+
* @param dateB - The second date.
|
|
5301
|
+
* @returns `true` if `dateA > dateB`.
|
|
5302
|
+
*
|
|
5303
|
+
* @example
|
|
5304
|
+
* ```ts
|
|
5305
|
+
* du.isAfter("2026-12-31", "2026-06-01"); // → true
|
|
5306
|
+
* ```
|
|
5307
|
+
*/
|
|
5308
|
+
isAfter(dateA: Date | number | string, dateB: Date | number | string): boolean;
|
|
5309
|
+
/**
|
|
5310
|
+
* Returns `true` if two dates represent the same instant in time.
|
|
5311
|
+
*
|
|
5312
|
+
* Comparison is performed at millisecond precision.
|
|
5313
|
+
*
|
|
5314
|
+
* @param dateA - The first date.
|
|
5315
|
+
* @param dateB - The second date.
|
|
5316
|
+
* @returns `true` if both dates resolve to the same millisecond.
|
|
5317
|
+
*
|
|
5318
|
+
* @example
|
|
5319
|
+
* ```ts
|
|
5320
|
+
* du.isSame(new Date("2026-04-15"), 1776268800000); // → true (if same instant)
|
|
5321
|
+
* ```
|
|
5322
|
+
*/
|
|
5323
|
+
isSame(dateA: Date | number | string, dateB: Date | number | string): boolean;
|
|
5324
|
+
/**
|
|
5325
|
+
* Returns `true` if `date` falls within the range `[start, end]` (inclusive).
|
|
5326
|
+
*
|
|
5327
|
+
* @param date - The date to test.
|
|
5328
|
+
* @param start - The start of the range.
|
|
5329
|
+
* @param end - The end of the range.
|
|
5330
|
+
* @returns `true` if `start ≤ date ≤ end`.
|
|
5331
|
+
*
|
|
5332
|
+
* @example
|
|
5333
|
+
* ```ts
|
|
5334
|
+
* du.isBetween("2026-04-15", "2026-01-01", "2026-12-31"); // → true
|
|
5335
|
+
* du.isBetween("2025-12-31", "2026-01-01", "2026-12-31"); // → false
|
|
5336
|
+
* ```
|
|
5337
|
+
*/
|
|
5338
|
+
isBetween(date: Date | number | string, start: Date | number | string, end: Date | number | string): boolean;
|
|
5339
|
+
/**
|
|
5340
|
+
* Returns a new `Date` set to the **start** of the specified unit
|
|
5341
|
+
* (i.e., all smaller components zeroed out).
|
|
5342
|
+
*
|
|
5343
|
+
* Supported units: `"day"`, `"week"` (Monday = start), `"month"`, `"year"`.
|
|
5344
|
+
*
|
|
5345
|
+
* @param unit - The boundary unit.
|
|
5346
|
+
* @param date - The reference date (default: current time).
|
|
5347
|
+
* @returns A new `Date` at the beginning of the unit.
|
|
5348
|
+
*
|
|
5349
|
+
* @example
|
|
5350
|
+
* ```ts
|
|
5351
|
+
* du.startOf("day");
|
|
5352
|
+
* // → 2026-04-15T00:00:00.000 (local)
|
|
5353
|
+
*
|
|
5354
|
+
* du.startOf("month", new Date("2026-04-15"));
|
|
5355
|
+
* // → 2026-04-01T00:00:00.000
|
|
5356
|
+
*
|
|
5357
|
+
* du.startOf("year", "2026-06-15");
|
|
5358
|
+
* // → 2026-01-01T00:00:00.000
|
|
5359
|
+
* ```
|
|
5360
|
+
*/
|
|
5361
|
+
startOf(unit: "day" | "week" | "month" | "year", date?: Date | number | string): Date;
|
|
5362
|
+
/**
|
|
5363
|
+
* Returns a new `Date` set to the **end** of the specified unit
|
|
5364
|
+
* (i.e., the last millisecond of that unit).
|
|
5365
|
+
*
|
|
5366
|
+
* Supported units: `"day"`, `"week"` (Sunday = end), `"month"`, `"year"`.
|
|
5367
|
+
*
|
|
5368
|
+
* @param unit - The boundary unit.
|
|
5369
|
+
* @param date - The reference date (default: current time).
|
|
5370
|
+
* @returns A new `Date` at the very last millisecond of the unit.
|
|
5371
|
+
*
|
|
5372
|
+
* @example
|
|
5373
|
+
* ```ts
|
|
5374
|
+
* du.endOf("month", new Date("2026-02-01"));
|
|
5375
|
+
* // → 2026-02-28T23:59:59.999
|
|
5376
|
+
*
|
|
5377
|
+
* du.endOf("year", "2026-01-01");
|
|
5378
|
+
* // → 2026-12-31T23:59:59.999
|
|
5379
|
+
* ```
|
|
5380
|
+
*/
|
|
5381
|
+
endOf(unit: "day" | "week" | "month" | "year", date?: Date | number | string): Date;
|
|
5382
|
+
/**
|
|
5383
|
+
* Returns `true` if the given year is a leap year.
|
|
5384
|
+
*
|
|
5385
|
+
* A year is a leap year if it is divisible by 4, except for century years,
|
|
5386
|
+
* which must also be divisible by 400.
|
|
5387
|
+
*
|
|
5388
|
+
* @param year - The four-digit year to test (default: current year).
|
|
5389
|
+
* @returns `true` if the year is a leap year.
|
|
5390
|
+
*
|
|
5391
|
+
* @example
|
|
5392
|
+
* ```ts
|
|
5393
|
+
* du.isLeapYear(2024); // → true
|
|
5394
|
+
* du.isLeapYear(2100); // → false
|
|
5395
|
+
* du.isLeapYear(2000); // → true
|
|
5396
|
+
* ```
|
|
5397
|
+
*/
|
|
5398
|
+
isLeapYear(year?: number): boolean;
|
|
5399
|
+
/**
|
|
5400
|
+
* Returns the number of days in a given month of a given year.
|
|
5401
|
+
*
|
|
5402
|
+
* Correctly accounts for leap years when querying February.
|
|
5403
|
+
*
|
|
5404
|
+
* @param month - The 1-based month index (1 = January, 12 = December).
|
|
5405
|
+
* @param year - The four-digit year (default: current year).
|
|
5406
|
+
* @returns The number of days in the specified month (28–31).
|
|
5407
|
+
*
|
|
5408
|
+
* @example
|
|
5409
|
+
* ```ts
|
|
5410
|
+
* du.daysInMonth(2, 2024); // → 29 (leap year)
|
|
5411
|
+
* du.daysInMonth(2, 2023); // → 28
|
|
5412
|
+
* du.daysInMonth(1, 2026); // → 31
|
|
5413
|
+
* ```
|
|
5414
|
+
*/
|
|
5415
|
+
daysInMonth(month: number, year?: number): number;
|
|
5416
|
+
/**
|
|
5417
|
+
* Returns the ISO 8601 week number (1–53) for a given date.
|
|
5418
|
+
*
|
|
5419
|
+
* ISO 8601 defines Week 1 as the week containing the year's first Thursday.
|
|
5420
|
+
* Weeks run Monday–Sunday. A date in early January may belong to the
|
|
5421
|
+
* final week of the previous year (e.g., January 1, 2016 → Week 53 of 2015).
|
|
5422
|
+
*
|
|
5423
|
+
* @param date - The reference date (default: current time).
|
|
5424
|
+
* @returns The ISO week number.
|
|
5425
|
+
*
|
|
5426
|
+
* @example
|
|
5427
|
+
* ```ts
|
|
5428
|
+
* du.weekNumber(new Date("2026-01-01")); // → 1
|
|
5429
|
+
* du.weekNumber(new Date("2016-01-03")); // → 53 (belongs to 2015)
|
|
5430
|
+
* ```
|
|
5431
|
+
*/
|
|
5432
|
+
weekNumber(date?: Date | number | string): number;
|
|
5433
|
+
/**
|
|
5434
|
+
* Returns the day of the year (1–366) for a given date.
|
|
5435
|
+
*
|
|
5436
|
+
* @param date - The reference date (default: current time).
|
|
5437
|
+
* @returns An integer from 1 to 366.
|
|
5438
|
+
*
|
|
5439
|
+
* @example
|
|
5440
|
+
* ```ts
|
|
5441
|
+
* du.dayOfYear(new Date("2026-02-01")); // → 32
|
|
5442
|
+
* du.dayOfYear(new Date("2026-12-31")); // → 365
|
|
5443
|
+
* ```
|
|
5444
|
+
*/
|
|
5445
|
+
dayOfYear(date?: Date | number | string): number;
|
|
5446
|
+
/**
|
|
5447
|
+
* Returns the ISO 8601 quarter (1–4) in which the given date falls.
|
|
5448
|
+
*
|
|
5449
|
+
* @param date - The reference date (default: current time).
|
|
5450
|
+
* @returns A quarter number: `1`, `2`, `3`, or `4`.
|
|
5451
|
+
*
|
|
5452
|
+
* @example
|
|
5453
|
+
* ```ts
|
|
5454
|
+
* du.quarter(new Date("2026-04-15")); // → 2 (Apr–Jun)
|
|
5455
|
+
* du.quarter(new Date("2026-11-01")); // → 4 (Oct–Dec)
|
|
5456
|
+
* ```
|
|
5457
|
+
*/
|
|
5458
|
+
quarter(date?: Date | number | string): 1 | 2 | 3 | 4;
|
|
5459
|
+
/**
|
|
5460
|
+
* Returns `true` if the given date falls on a weekend (Saturday or Sunday).
|
|
5461
|
+
*
|
|
5462
|
+
* The check uses **local time**.
|
|
5463
|
+
*
|
|
5464
|
+
* @param date - The date to check (default: current time).
|
|
5465
|
+
* @returns `true` if the date is a Saturday or Sunday.
|
|
5466
|
+
*
|
|
5467
|
+
* @example
|
|
5468
|
+
* ```ts
|
|
5469
|
+
* du.isWeekend(new Date("2026-04-18")); // → true (Saturday)
|
|
5470
|
+
* du.isWeekend(new Date("2026-04-15")); // → false (Wednesday)
|
|
5471
|
+
* ```
|
|
5472
|
+
*/
|
|
5473
|
+
isWeekend(date?: Date | number | string): boolean;
|
|
5474
|
+
/**
|
|
5475
|
+
* Returns `true` if the given date falls on a weekday (Monday–Friday).
|
|
5476
|
+
*
|
|
5477
|
+
* @param date - The date to check (default: current time).
|
|
5478
|
+
* @returns `true` if the date is Monday through Friday.
|
|
5479
|
+
*
|
|
5480
|
+
* @example
|
|
5481
|
+
* ```ts
|
|
5482
|
+
* du.isWeekday(new Date("2026-04-15")); // → true
|
|
5483
|
+
* du.isWeekday(new Date("2026-04-19")); // → false (Sunday)
|
|
5484
|
+
* ```
|
|
5485
|
+
*/
|
|
5486
|
+
isWeekday(date?: Date | number | string): boolean;
|
|
5487
|
+
/**
|
|
5488
|
+
* Returns `true` if two dates fall on the same calendar day (in local time).
|
|
5489
|
+
*
|
|
5490
|
+
* Only the year, month, and date components are compared; time is ignored.
|
|
5491
|
+
*
|
|
5492
|
+
* @param dateA - The first date.
|
|
5493
|
+
* @param dateB - The second date.
|
|
5494
|
+
* @returns `true` if both dates share the same year, month, and day.
|
|
5495
|
+
*
|
|
5496
|
+
* @example
|
|
5497
|
+
* ```ts
|
|
5498
|
+
* du.isSameDay("2026-04-15T08:00:00", "2026-04-15T22:00:00"); // → true
|
|
5499
|
+
* du.isSameDay("2026-04-15", "2026-04-16"); // → false
|
|
5500
|
+
* ```
|
|
5501
|
+
*/
|
|
5502
|
+
isSameDay(dateA: Date | number | string, dateB: Date | number | string): boolean;
|
|
5503
|
+
/**
|
|
5504
|
+
* Returns `true` if the given date is today (in local time).
|
|
5505
|
+
*
|
|
5506
|
+
* @param date - The date to test.
|
|
5507
|
+
* @returns `true` if `date` falls on the current calendar day.
|
|
5508
|
+
*
|
|
5509
|
+
* @example
|
|
5510
|
+
* ```ts
|
|
5511
|
+
* du.isToday(new Date()); // → true
|
|
5512
|
+
* du.isToday("2020-01-01"); // → false
|
|
5513
|
+
* ```
|
|
5514
|
+
*/
|
|
5515
|
+
isToday(date: Date | number | string): boolean;
|
|
5516
|
+
/**
|
|
5517
|
+
* Returns `true` if the given date is in the past (before the current instant).
|
|
5518
|
+
*
|
|
5519
|
+
* @param date - The date to check.
|
|
5520
|
+
* @returns `true` if `date` is strictly before `Date.now()`.
|
|
5521
|
+
*
|
|
5522
|
+
* @example
|
|
5523
|
+
* ```ts
|
|
5524
|
+
* du.isPast("2020-01-01"); // → true
|
|
5525
|
+
* du.isPast(Date.now() + 1000); // → false
|
|
5526
|
+
* ```
|
|
5527
|
+
*/
|
|
5528
|
+
isPast(date: Date | number | string): boolean;
|
|
5529
|
+
/**
|
|
5530
|
+
* Returns `true` if the given date is in the future (after the current instant).
|
|
5531
|
+
*
|
|
5532
|
+
* @param date - The date to check.
|
|
5533
|
+
* @returns `true` if `date` is strictly after `Date.now()`.
|
|
5534
|
+
*
|
|
5535
|
+
* @example
|
|
5536
|
+
* ```ts
|
|
5537
|
+
* du.isFuture(Date.now() + 5000); // → true
|
|
5538
|
+
* du.isFuture("2020-01-01"); // → false
|
|
5539
|
+
* ```
|
|
5540
|
+
*/
|
|
5541
|
+
isFuture(date: Date | number | string): boolean;
|
|
5542
|
+
/**
|
|
5543
|
+
* Clamps a date to a `[min, max]` range.
|
|
5544
|
+
*
|
|
5545
|
+
* If `date` is before `min`, `min` is returned.
|
|
5546
|
+
* If `date` is after `max`, `max` is returned.
|
|
5547
|
+
* Otherwise, `date` is returned unchanged (as a new `Date`).
|
|
5548
|
+
*
|
|
5549
|
+
* @param date - The date to clamp.
|
|
5550
|
+
* @param min - The lower bound.
|
|
5551
|
+
* @param max - The upper bound.
|
|
5552
|
+
* @returns A new `Date` clamped within `[min, max]`.
|
|
5553
|
+
*
|
|
5554
|
+
* @example
|
|
5555
|
+
* ```ts
|
|
5556
|
+
* du.clamp("2025-01-01", "2026-01-01", "2026-12-31");
|
|
5557
|
+
* // → Date("2026-01-01") — clamped to min
|
|
5558
|
+
*
|
|
5559
|
+
* du.clamp("2026-06-15", "2026-01-01", "2026-12-31");
|
|
5560
|
+
* // → Date("2026-06-15") — within range, unchanged
|
|
5561
|
+
* ```
|
|
5562
|
+
*/
|
|
5563
|
+
clamp(date: Date | number | string, min: Date | number | string, max: Date | number | string): Date;
|
|
5564
|
+
/**
|
|
5565
|
+
* Generates an array of `Date` objects representing each day in the range
|
|
5566
|
+
* `[start, end]`, inclusive.
|
|
5567
|
+
*
|
|
5568
|
+
* The range is capped at **3 650 days** (~10 years) to prevent accidental
|
|
5569
|
+
* allocation of enormous arrays.
|
|
5570
|
+
*
|
|
5571
|
+
* @param start - The first day of the range.
|
|
5572
|
+
* @param end - The last day of the range.
|
|
5573
|
+
* @returns An ordered array of `Date` objects, one per day.
|
|
5574
|
+
* @throws {RangeError} If the range exceeds 3 650 days.
|
|
5575
|
+
*
|
|
5576
|
+
* @example
|
|
5577
|
+
* ```ts
|
|
5578
|
+
* du.dateRange("2026-04-13", "2026-04-15");
|
|
5579
|
+
* // → [Date("2026-04-13"), Date("2026-04-14"), Date("2026-04-15")]
|
|
5580
|
+
* ```
|
|
5581
|
+
*/
|
|
5582
|
+
dateRange(start: Date | number | string, end: Date | number | string): Date[];
|
|
5583
|
+
/**
|
|
5584
|
+
* Returns `true` if the given value can be successfully interpreted
|
|
5585
|
+
* as a valid, finite date.
|
|
5586
|
+
*
|
|
5587
|
+
* Accepts `Date`, `number`, and `string` inputs. A `Date` whose
|
|
5588
|
+
* `getTime()` returns `NaN` is considered invalid.
|
|
5589
|
+
*
|
|
5590
|
+
* @param value - The value to validate.
|
|
5591
|
+
* @returns `true` if the value represents a valid date.
|
|
5592
|
+
*
|
|
5593
|
+
* @example
|
|
5594
|
+
* ```ts
|
|
5595
|
+
* du.isValid(new Date()); // → true
|
|
5596
|
+
* du.isValid("2026-04-15"); // → true
|
|
5597
|
+
* du.isValid("not-a-date"); // → false
|
|
5598
|
+
* du.isValid(new Date("invalid")); // → false
|
|
5599
|
+
* du.isValid(NaN); // → false
|
|
5600
|
+
* ```
|
|
5601
|
+
*/
|
|
5602
|
+
isValid(value: unknown): boolean;
|
|
5603
|
+
/**
|
|
5604
|
+
* Parses a date string using an ordered list of format patterns and returns
|
|
5605
|
+
* the first successfully parsed `Date`, or `null` if none match.
|
|
5606
|
+
*
|
|
5607
|
+
* Supported format tokens:
|
|
5608
|
+
* - `YYYY` — 4-digit year
|
|
5609
|
+
* - `MM` — 2-digit month (01–12)
|
|
5610
|
+
* - `DD` — 2-digit day (01–31)
|
|
5611
|
+
* - `HH` — 2-digit hours (00–23)
|
|
5612
|
+
* - `mm` — 2-digit minutes (00–59)
|
|
5613
|
+
* - `ss` — 2-digit seconds (00–59)
|
|
5614
|
+
*
|
|
5615
|
+
* @param value - The date string to parse.
|
|
5616
|
+
* @param formats - An ordered list of format strings to attempt.
|
|
5617
|
+
* @returns The first successfully parsed `Date`, or `null`.
|
|
5618
|
+
*
|
|
5619
|
+
* @example
|
|
5620
|
+
* ```ts
|
|
5621
|
+
* du.parse("15/04/2026", ["DD/MM/YYYY"]);
|
|
5622
|
+
* // → Date("2026-04-15")
|
|
5623
|
+
*
|
|
5624
|
+
* du.parse("2026-04-15 08:30:00", ["YYYY-MM-DD HH:mm:ss"]);
|
|
5625
|
+
* // → Date("2026-04-15T08:30:00")
|
|
5626
|
+
*
|
|
5627
|
+
* du.parse("bad-input", ["YYYY-MM-DD"]);
|
|
5628
|
+
* // → null
|
|
5629
|
+
* ```
|
|
5630
|
+
*/
|
|
5631
|
+
parse(value: string, formats: string[]): Date | null;
|
|
5632
|
+
/**
|
|
5633
|
+
* Returns the UTC offset of the local environment in minutes.
|
|
5634
|
+
*
|
|
5635
|
+
* Positive values indicate zones **behind** UTC (e.g., UTC-5 → `300`),
|
|
5636
|
+
* mirroring the behaviour of `Date.prototype.getTimezoneOffset()`.
|
|
5637
|
+
*
|
|
5638
|
+
* @returns The UTC offset in minutes.
|
|
5639
|
+
*
|
|
5640
|
+
* @example
|
|
5641
|
+
* ```ts
|
|
5642
|
+
* du.timezoneOffset(); // → -120 for UTC+2, 300 for UTC-5
|
|
5643
|
+
* ```
|
|
5644
|
+
*/
|
|
5645
|
+
timezoneOffset(): number;
|
|
5646
|
+
/**
|
|
5647
|
+
* Formats a date in a specific IANA timezone using `Intl.DateTimeFormat`.
|
|
5648
|
+
*
|
|
5649
|
+
* Requires the runtime to support the `timeZone` option (all modern
|
|
5650
|
+
* environments do).
|
|
5651
|
+
*
|
|
5652
|
+
* @param date - The date to format.
|
|
5653
|
+
* @param timeZone - A valid IANA timezone identifier (e.g., `"America/New_York"`).
|
|
5654
|
+
* @param locale - BCP 47 locale tag (default: `"en-US"`).
|
|
5655
|
+
* @param options - Additional `Intl.DateTimeFormatOptions`.
|
|
5656
|
+
* @returns A localized date string in the given timezone.
|
|
5657
|
+
*
|
|
5658
|
+
* @example
|
|
5659
|
+
* ```ts
|
|
5660
|
+
* du.formatInTimezone(Date.now(), "Asia/Tokyo", "ja-JP", { dateStyle: "full", timeStyle: "short" });
|
|
5661
|
+
* // → "2026年4月15日水曜日 19:00"
|
|
5662
|
+
* ```
|
|
5663
|
+
*/
|
|
5664
|
+
formatInTimezone(date: Date | number | string, timeZone: string, locale?: string, options?: Omit<Intl.DateTimeFormatOptions, "timeZone">): string;
|
|
5665
|
+
}
|
|
5666
|
+
|
|
5667
|
+
/**
|
|
5668
|
+
* **ObjectUtils — XyPriss Object Utilities**
|
|
5669
|
+
*/
|
|
5670
|
+
declare class ObjectUtils {
|
|
5671
|
+
/**
|
|
5672
|
+
* **Deep Clone an Object**
|
|
5673
|
+
*
|
|
5674
|
+
* Creates a deep copy of `obj` using `XStringify` for serialization,
|
|
5675
|
+
* which handles cyclic references and offers better performance
|
|
5676
|
+
* than the native `JSON.stringify` in complex object graphs.
|
|
5677
|
+
*
|
|
5678
|
+
* @param obj - The object to clone. Must be serializable.
|
|
5679
|
+
* @returns A completely independent deep copy of the input object.
|
|
5680
|
+
*
|
|
5681
|
+
* @example
|
|
5682
|
+
* ```ts
|
|
5683
|
+
* const original = { a: 1, nested: { b: 2 } };
|
|
5684
|
+
* const clone = utils.deepClone(original);
|
|
5685
|
+
* clone.nested.b = 99;
|
|
5686
|
+
* // original.nested.b is still 2
|
|
5687
|
+
* ```
|
|
5688
|
+
*/
|
|
5689
|
+
deepClone<T>(obj: T): T;
|
|
5690
|
+
/**
|
|
5691
|
+
* **Pick Specific Keys from an Object**
|
|
5692
|
+
*
|
|
5693
|
+
* Returns a new object containing only the key-value pairs whose
|
|
5694
|
+
* keys appear in the `keys` array. Non-existent keys are silently ignored.
|
|
5695
|
+
*
|
|
5696
|
+
* @param obj - The source object.
|
|
5697
|
+
* @param keys - Array of keys to extract.
|
|
5698
|
+
* @returns A new object with only the specified keys.
|
|
5699
|
+
*
|
|
5700
|
+
* @example
|
|
5701
|
+
* ```ts
|
|
5702
|
+
* utils.pick({ a: 1, b: 2, c: 3 }, ["a", "c"]); // { a: 1, c: 3 }
|
|
5703
|
+
* ```
|
|
5704
|
+
*/
|
|
5705
|
+
pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
|
|
5706
|
+
/**
|
|
5707
|
+
* **Omit Specific Keys from an Object**
|
|
5708
|
+
*
|
|
5709
|
+
* Returns a new object that is a shallow copy of `obj` with the
|
|
5710
|
+
* specified keys removed.
|
|
5711
|
+
*
|
|
5712
|
+
* @param obj - The source object.
|
|
5713
|
+
* @param keys - Array of keys to exclude.
|
|
5714
|
+
* @returns A new object without the specified keys.
|
|
5715
|
+
*
|
|
5716
|
+
* @example
|
|
5717
|
+
* ```ts
|
|
5718
|
+
* utils.omit({ a: 1, b: 2, c: 3 }, ["b"]); // { a: 1, c: 3 }
|
|
5719
|
+
* ```
|
|
5720
|
+
*/
|
|
5721
|
+
omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K>;
|
|
5722
|
+
/**
|
|
5723
|
+
* **Check if an Object is Empty**
|
|
5724
|
+
*
|
|
5725
|
+
* Returns `true` if the object has no own enumerable keys.
|
|
5726
|
+
* Works correctly with objects created via `Object.create(null)`.
|
|
5727
|
+
*
|
|
5728
|
+
* @param obj - The object to inspect.
|
|
5729
|
+
* @returns `true` if the object has no own keys, `false` otherwise.
|
|
5730
|
+
*
|
|
5731
|
+
* @example
|
|
5732
|
+
* ```ts
|
|
5733
|
+
* utils.isEmpty({}); // true
|
|
5734
|
+
* utils.isEmpty({ a: 1 }); // false
|
|
5735
|
+
* utils.isEmpty(Object.create(null)); // true
|
|
5736
|
+
* ```
|
|
5737
|
+
*/
|
|
5738
|
+
isEmpty(obj: object): boolean;
|
|
5739
|
+
/**
|
|
5740
|
+
* **flattenObject**
|
|
5741
|
+
*
|
|
5742
|
+
* Collapses nested objects into flat dot-notation (or custom) keys.
|
|
5743
|
+
* Useful for configuration mapping or CSV generation.
|
|
5744
|
+
*
|
|
5745
|
+
* @param obj - The object to flatten.
|
|
5746
|
+
* @param separator - Optional path separator (default: `"."`).
|
|
5747
|
+
* @returns A shallow object with path-based keys.
|
|
5748
|
+
*/
|
|
5749
|
+
flattenObject(obj: Record<string, unknown>, separator?: string): Record<string, unknown>;
|
|
5750
|
+
/**
|
|
5751
|
+
* **parse**
|
|
5752
|
+
*
|
|
5753
|
+
* Safely parses a JSON string. If the parsing fails, the provided fallback
|
|
5754
|
+
* value is returned instead of throwing an exception.
|
|
5755
|
+
*
|
|
5756
|
+
* @param json The JSON string to parse.
|
|
5757
|
+
* @param fallback The fallback value to return on failure.
|
|
5758
|
+
* @returns The parsed object or the fallback value.
|
|
5759
|
+
*/
|
|
5760
|
+
parse<T>(json: string, fallback?: T | null): T | null;
|
|
5761
|
+
}
|
|
5762
|
+
|
|
5763
|
+
/**
|
|
5764
|
+
* **ArrayUtils — XyPriss Array Utilities**
|
|
5765
|
+
*/
|
|
5766
|
+
declare class ArrayUtils {
|
|
5767
|
+
/**
|
|
5768
|
+
* **Chunk an Array**
|
|
5769
|
+
*
|
|
5770
|
+
* Splits an array into sub-arrays of a fixed maximum size.
|
|
5771
|
+
*/
|
|
5772
|
+
chunk<T>(arr: T[], size: number): T[][];
|
|
5773
|
+
/**
|
|
5774
|
+
* **Unique Elements**
|
|
5775
|
+
*
|
|
5776
|
+
* Returns a new array with all duplicates removed.
|
|
5777
|
+
*/
|
|
5778
|
+
unique<T>(arr: T[]): T[];
|
|
5779
|
+
/**
|
|
5780
|
+
* **Shuffle Elements**
|
|
5781
|
+
*
|
|
5782
|
+
* Randomly reorders an array using the Fisher-Yates algorithm.
|
|
5783
|
+
*/
|
|
5784
|
+
shuffle<T>(arr: T[]): T[];
|
|
5785
|
+
/**
|
|
5786
|
+
* **Group Elements**
|
|
5787
|
+
*
|
|
5788
|
+
* Groups array elements into an object based on a key-mapping function.
|
|
5789
|
+
*/
|
|
5790
|
+
groupBy<T>(arr: T[], keyFn: (item: T) => string): Record<string, T[]>;
|
|
5791
|
+
/**
|
|
5792
|
+
* **Pick Random Sample**
|
|
5793
|
+
*/
|
|
5794
|
+
sample<T>(arr: T[]): T | undefined;
|
|
5795
|
+
/**
|
|
5796
|
+
* **Flatten One Level**
|
|
5797
|
+
*/
|
|
5798
|
+
flatten<T>(arr: T[][]): T[];
|
|
5799
|
+
}
|
|
5800
|
+
|
|
5801
|
+
/**
|
|
5802
|
+
* # AsyncUtils — XyPriss Async Control Flow
|
|
5803
|
+
*
|
|
5804
|
+
* A comprehensive library of asynchronous control flow primitives for TypeScript.
|
|
5805
|
+
* Each method is designed to be safe, performant, and composable.
|
|
5806
|
+
*
|
|
5807
|
+
* @example
|
|
5808
|
+
* ```ts
|
|
5809
|
+
* const async = new AsyncUtils();
|
|
5810
|
+
*
|
|
5811
|
+
* // Auto-retry + debounce + performance measurement in a few lines
|
|
5812
|
+
* const save = async.debounce(async (data: string) => {
|
|
5813
|
+
* const { result, durationMs } = await async.measure(() =>
|
|
5814
|
+
* async.retry(() => api.save(data), { maxAttempts: 3, delay: 1000 })
|
|
5815
|
+
* );
|
|
5816
|
+
* console.log(`Saved in ${durationMs.toFixed(1)}ms`, result);
|
|
5817
|
+
* }, 500);
|
|
5818
|
+
* ```
|
|
5819
|
+
*
|
|
5820
|
+
* @module AsyncUtils
|
|
5821
|
+
*/
|
|
5822
|
+
/** Advanced options for {@link AsyncUtils.retry}. */
|
|
5823
|
+
interface RetryOptions {
|
|
5824
|
+
/** Maximum number of attempts. @default 3 */
|
|
5825
|
+
maxAttempts?: number;
|
|
5826
|
+
/** Initial delay between attempts (ms). @default 500 */
|
|
5827
|
+
delay?: number;
|
|
5828
|
+
/** Multiplicative factor for the delay at each attempt (exponential backoff). @default 1 */
|
|
5829
|
+
backoffFactor?: number;
|
|
5830
|
+
/** Maximum delay regardless of backoff (ms). @default Infinity */
|
|
5831
|
+
maxDelay?: number;
|
|
5832
|
+
/** Abort signal allowing to interrupt attempts at any time. */
|
|
5833
|
+
signal?: AbortSignal;
|
|
5834
|
+
/**
|
|
5835
|
+
* Optional predicate — returns `true` if the error is "retryable".
|
|
5836
|
+
* Useful for not retrying a 400 or 401 error that won't change.
|
|
5837
|
+
*
|
|
5838
|
+
* @example
|
|
5839
|
+
* ```ts
|
|
5840
|
+
* retryIf: (err) => err instanceof NetworkError
|
|
5841
|
+
* ```
|
|
5842
|
+
*/
|
|
5843
|
+
retryIf?: (error: unknown, attempt: number) => boolean;
|
|
5844
|
+
/**
|
|
5845
|
+
* Callback called at each failed attempt (ideal for telemetry).
|
|
5846
|
+
*
|
|
5847
|
+
* @example
|
|
5848
|
+
* ```ts
|
|
5849
|
+
* onRetry: (err, attempt) => logger.warn(`Attempt ${attempt} failed`, err)
|
|
5850
|
+
* ```
|
|
5851
|
+
*/
|
|
5852
|
+
onRetry?: (error: unknown, attempt: number) => void;
|
|
5853
|
+
}
|
|
5854
|
+
/** Options for {@link AsyncUtils.timeout}. */
|
|
5855
|
+
interface TimeoutOptions {
|
|
5856
|
+
/** Message of the error thrown in case of timeout. @default "Operation timed out" */
|
|
5857
|
+
message?: string;
|
|
5858
|
+
/** External signal allowing to cancel the promise before timeout. */
|
|
5859
|
+
signal?: AbortSignal;
|
|
5860
|
+
}
|
|
5861
|
+
/** Result of an execution via {@link AsyncUtils.measure}. */
|
|
5862
|
+
interface MeasureResult<T> {
|
|
5863
|
+
result: T;
|
|
5864
|
+
/** Operation duration in milliseconds (µs precision via `performance.now()`). */
|
|
5865
|
+
durationMs: number;
|
|
5866
|
+
}
|
|
5867
|
+
/** Result of an execution via {@link AsyncUtils.attempt}. */
|
|
5868
|
+
type AttemptResult<T> = {
|
|
5869
|
+
ok: true;
|
|
5870
|
+
value: T;
|
|
5871
|
+
error?: never;
|
|
5872
|
+
} | {
|
|
5873
|
+
ok: false;
|
|
5874
|
+
error: unknown;
|
|
5875
|
+
value?: never;
|
|
5876
|
+
};
|
|
5877
|
+
declare class AsyncUtils {
|
|
5878
|
+
/**
|
|
5879
|
+
* ## Asynchronous Pause
|
|
5880
|
+
*
|
|
5881
|
+
* Suspends execution for a given duration.
|
|
5882
|
+
* Compatible with `AbortSignal`: sleep will be interrupted cleanly
|
|
5883
|
+
* if the signal is triggered (the promise **resolves** without error in this case).
|
|
5884
|
+
*
|
|
5885
|
+
* @param ms - Pause duration in milliseconds.
|
|
5886
|
+
* @param signal - Optional cancellation signal (AbortController).
|
|
5887
|
+
* @returns A promise that resolves after `ms` ms (or earlier if signal triggered).
|
|
5888
|
+
*
|
|
5889
|
+
* @example Simple pause
|
|
5890
|
+
* ```ts
|
|
5891
|
+
* await utils.sleep(2000); // waits 2 seconds
|
|
5892
|
+
* ```
|
|
5893
|
+
*
|
|
5894
|
+
* @example Cancellation via AbortController
|
|
5895
|
+
* ```ts
|
|
5896
|
+
* const controller = new AbortController();
|
|
5897
|
+
* setTimeout(() => controller.abort(), 500);
|
|
5898
|
+
*
|
|
5899
|
+
* await utils.sleep(5000, controller.signal); // resolves after ~500ms
|
|
5900
|
+
* ```
|
|
5901
|
+
*/
|
|
5902
|
+
sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
5903
|
+
/**
|
|
5904
|
+
* ## Asynchronous Pause (alias of `sleep`)
|
|
5905
|
+
*
|
|
5906
|
+
* @alias sleep
|
|
5907
|
+
* @see {@link sleep}
|
|
5908
|
+
*/
|
|
5909
|
+
wait(ms: number, signal?: AbortSignal): Promise<void>;
|
|
5910
|
+
/**
|
|
5911
|
+
* ## Retry with Exponential Backoff
|
|
5912
|
+
*
|
|
5913
|
+
* Retries an asynchronous operation up to `maxAttempts` times.
|
|
5914
|
+
* Supports exponential backoff, maximum delay, filter predicate,
|
|
5915
|
+
* and `AbortSignal` to interrupt the retry cycle.
|
|
5916
|
+
*
|
|
5917
|
+
* Delay formula: `min(delay × backoffFactor^attempt, maxDelay)`.
|
|
5918
|
+
*
|
|
5919
|
+
* @param fn - The asynchronous function to execute.
|
|
5920
|
+
* @param options - Retry options (see {@link RetryOptions}).
|
|
5921
|
+
* @returns Resolved value of `fn` on the first successful attempt.
|
|
5922
|
+
* @throws Last error if all attempts fail.
|
|
5923
|
+
*
|
|
5924
|
+
* @example Basic retry (3 attempts, 500ms between each)
|
|
5925
|
+
* ```ts
|
|
5926
|
+
* const data = await utils.retry(() => fetch("/api/data").then(r => r.json()));
|
|
5927
|
+
* ```
|
|
5928
|
+
*
|
|
5929
|
+
* @example Exponential backoff: 200ms → 400ms → 800ms → max 1000ms
|
|
5930
|
+
* ```ts
|
|
5931
|
+
* const result = await utils.retry(() => unstableApi(), {
|
|
5932
|
+
* maxAttempts: 4,
|
|
5933
|
+
* delay: 200,
|
|
5934
|
+
* backoffFactor: 2,
|
|
5935
|
+
* maxDelay: 1000,
|
|
5936
|
+
* onRetry: (err, n) => console.warn(`Retry #${n}`, err),
|
|
5937
|
+
* });
|
|
5938
|
+
* ```
|
|
5939
|
+
*
|
|
5940
|
+
* @example Do not retry auth errors
|
|
5941
|
+
* ```ts
|
|
5942
|
+
* await utils.retry(() => api.call(), {
|
|
5943
|
+
* retryIf: (err) => !(err instanceof AuthError),
|
|
5944
|
+
* });
|
|
5945
|
+
* ```
|
|
5946
|
+
*/
|
|
5947
|
+
retry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
5948
|
+
/**
|
|
5949
|
+
* ## Promise Timeout
|
|
5950
|
+
*
|
|
5951
|
+
* Wraps a promise with a maximum duration. If the promise does not
|
|
5952
|
+
* resolve within the given time, an `Error` is thrown.
|
|
5953
|
+
*
|
|
5954
|
+
* Automatically handles internal timer cleanup to prevent memory leaks.
|
|
5955
|
+
*
|
|
5956
|
+
* @param fn - Function returning the promise to monitor.
|
|
5957
|
+
* @param ms - Maximum delay in milliseconds before rejecting.
|
|
5958
|
+
* @param options - Additional options (error message, cancellation signal).
|
|
5959
|
+
* @returns Resolved value if the promise succeeds within delay.
|
|
5960
|
+
* @throws `Error` with `options.message` if timeout is reached.
|
|
5961
|
+
*
|
|
5962
|
+
* @example
|
|
5963
|
+
* ```ts
|
|
5964
|
+
* const result = await utils.timeout(
|
|
5965
|
+
* () => fetch("/slow-api").then(r => r.json()),
|
|
5966
|
+
* 3000,
|
|
5967
|
+
* { message: "API took too long to respond" }
|
|
5968
|
+
* );
|
|
5969
|
+
* ```
|
|
5970
|
+
*/
|
|
5971
|
+
timeout<T>(fn: () => Promise<T>, ms: number, options?: TimeoutOptions): Promise<T>;
|
|
5972
|
+
/**
|
|
5973
|
+
* ## Safe Execution (Never Throws)
|
|
5974
|
+
*
|
|
5975
|
+
* Executes an asynchronous function and always captures the result as a
|
|
5976
|
+
* discriminated object `{ ok, value }` or `{ ok, error }`.
|
|
5977
|
+
* **Never throws exceptions**, simplifying control flow.
|
|
5978
|
+
*
|
|
5979
|
+
* Ideal for API calls, parsing, or any operation where failure is a normal outcome
|
|
5980
|
+
* and must be handled explicitly.
|
|
5981
|
+
*
|
|
5982
|
+
* @param fn - Asynchronous function to execute safely.
|
|
5983
|
+
* @returns Discriminated object indicating success or failure.
|
|
5984
|
+
*
|
|
5985
|
+
* @example Without `attempt` (verbose)
|
|
5986
|
+
* ```ts
|
|
5987
|
+
* let user;
|
|
5988
|
+
* try { user = await fetchUser(id); }
|
|
5989
|
+
* catch (e) { console.error(e); return; }
|
|
5990
|
+
* ```
|
|
5991
|
+
*
|
|
5992
|
+
* @example With `attempt` (concise)
|
|
5993
|
+
* ```ts
|
|
5994
|
+
* const { ok, value: user, error } = await utils.attempt(() => fetchUser(id));
|
|
5995
|
+
* if (!ok) { console.error(error); return; }
|
|
5996
|
+
* // `user` is guaranteed defined here
|
|
5997
|
+
* ```
|
|
5998
|
+
*
|
|
5999
|
+
* @example Combined with `retry`
|
|
6000
|
+
* ```ts
|
|
6001
|
+
* const { ok, value } = await utils.attempt(() =>
|
|
6002
|
+
* utils.retry(() => api.getData(), { maxAttempts: 5 })
|
|
6003
|
+
* );
|
|
6004
|
+
* ```
|
|
6005
|
+
*/
|
|
6006
|
+
attempt<T>(fn: () => Promise<T>): Promise<AttemptResult<T>>;
|
|
6007
|
+
/**
|
|
6008
|
+
* ## Debounce
|
|
6009
|
+
*
|
|
6010
|
+
* Delays execution of `fn` until `wait` ms have elapsed since the last call.
|
|
6011
|
+
* If a new call arrives before the delay ends, the previous one is cancelled
|
|
6012
|
+
* and the timer restarts from zero.
|
|
6013
|
+
*
|
|
6014
|
+
* Typical use cases: search fields (prevents one request per keystroke),
|
|
6015
|
+
* resize listeners, auto-save.
|
|
6016
|
+
*
|
|
6017
|
+
* The returned version exposes a `.cancel()` method to manually cancel the
|
|
6018
|
+
* pending timer, and `.flush()` to trigger execution immediately.
|
|
6019
|
+
*
|
|
6020
|
+
* @param fn - Function to debounce.
|
|
6021
|
+
* @param wait - Quiet period required before execution (ms). @default 300
|
|
6022
|
+
* @returns Debounced version of `fn` with `.cancel()` and `.flush()` methods.
|
|
6023
|
+
*
|
|
6024
|
+
* @example Real-time search
|
|
6025
|
+
* ```ts
|
|
6026
|
+
* const search = utils.debounce((query: string) => {
|
|
6027
|
+
* fetch(`/api/search?q=${query}`);
|
|
6028
|
+
* }, 400);
|
|
6029
|
+
*
|
|
6030
|
+
* input.addEventListener("input", (e) => search(e.target.value));
|
|
6031
|
+
* ```
|
|
6032
|
+
*
|
|
6033
|
+
* @example Explicit cancellation (e.g., on component unmount)
|
|
6034
|
+
* ```ts
|
|
6035
|
+
* const save = utils.debounce(saveToServer, 1000);
|
|
6036
|
+
* onUnmount(() => save.cancel());
|
|
6037
|
+
* ```
|
|
6038
|
+
*
|
|
6039
|
+
* @example Immediate flush (e.g., before navigation)
|
|
6040
|
+
* ```ts
|
|
6041
|
+
* window.addEventListener("beforeunload", () => save.flush());
|
|
6042
|
+
* ```
|
|
4421
6043
|
*/
|
|
4422
|
-
|
|
4423
|
-
|
|
6044
|
+
debounce<T extends (...args: any[]) => any>(fn: T, wait?: number): ((...args: Parameters<T>) => void) & {
|
|
6045
|
+
cancel: () => void;
|
|
6046
|
+
flush: (...args: Parameters<T>) => void;
|
|
6047
|
+
};
|
|
4424
6048
|
/**
|
|
4425
|
-
*
|
|
4426
|
-
* it cannot be resolved.
|
|
6049
|
+
* ## Throttle
|
|
4427
6050
|
*
|
|
4428
|
-
*
|
|
4429
|
-
*
|
|
4430
|
-
* silently producing `undefined` at the point of use.
|
|
6051
|
+
* Guarantees that `fn` executes no more than once per `limit` ms window,
|
|
6052
|
+
* regardless of how many calls are received.
|
|
4431
6053
|
*
|
|
4432
|
-
*
|
|
4433
|
-
*
|
|
4434
|
-
* @returns The stored value, guaranteed non-undefined.
|
|
4435
|
-
* @throws {EnvAccessError} When the variable is missing or empty.
|
|
4436
|
-
* @throws {EnvStoreError} When the store has not been initialised.
|
|
6054
|
+
* Unlike debounce, throttle executes `fn` **immediately** on the first call,
|
|
6055
|
+
* then ignores subsequent calls until the window ends.
|
|
4437
6056
|
*
|
|
4438
|
-
*
|
|
4439
|
-
* // Fail fast at boot if a critical variable is absent
|
|
4440
|
-
* const databaseUrl = __sys__.__env__.getStrict("DATABASE_URL");
|
|
4441
|
-
* const jwtSecret = __sys__.__env__.getStrict("JWT_SECRET", { rejectEmpty: true });
|
|
4442
|
-
* const smtpHost = __sys__.__env__.getStrict("SMTP_HOST");
|
|
6057
|
+
* Typical use cases: scroll handlers, mousemove, drag-and-drop, gamepads.
|
|
4443
6058
|
*
|
|
4444
|
-
*
|
|
4445
|
-
*
|
|
4446
|
-
*
|
|
4447
|
-
*
|
|
4448
|
-
*
|
|
4449
|
-
*
|
|
6059
|
+
* The returned version exposes a `.cancel()` method to manually reset the
|
|
6060
|
+
* throttle window.
|
|
6061
|
+
*
|
|
6062
|
+
* @param fn - Function to throttle.
|
|
6063
|
+
* @param limit - Minimum duration between two executions (ms). @default 300
|
|
6064
|
+
* @returns Throttled version of `fn` with `.cancel()` method.
|
|
6065
|
+
*
|
|
6066
|
+
* @example Scroll handler limited to 60fps (~16ms)
|
|
6067
|
+
* ```ts
|
|
6068
|
+
* const onScroll = utils.throttle(() => {
|
|
6069
|
+
* updateScrollIndicator();
|
|
6070
|
+
* }, 16);
|
|
6071
|
+
*
|
|
6072
|
+
* window.addEventListener("scroll", onScroll);
|
|
6073
|
+
* ```
|
|
4450
6074
|
*/
|
|
4451
|
-
|
|
6075
|
+
throttle<T extends (...args: any[]) => any>(fn: T, limit?: number): ((...args: Parameters<T>) => void) & {
|
|
6076
|
+
cancel: () => void;
|
|
6077
|
+
};
|
|
4452
6078
|
/**
|
|
4453
|
-
*
|
|
4454
|
-
* store, regardless of its value (including empty strings).
|
|
6079
|
+
* ## High-Precision Execution Time Measurement
|
|
4455
6080
|
*
|
|
4456
|
-
*
|
|
4457
|
-
*
|
|
6081
|
+
* Wraps a synchronous or asynchronous function and returns its result
|
|
6082
|
+
* along with its execution time in milliseconds (microsecond precision via `performance.now()`).
|
|
4458
6083
|
*
|
|
4459
|
-
* @
|
|
4460
|
-
*
|
|
4461
|
-
* Sentry.init({ dsn: __sys__.__env__.get("SENTRY_DSN") });
|
|
4462
|
-
* }
|
|
6084
|
+
* @param fn - Function to measure (sync or async).
|
|
6085
|
+
* @returns An object `{ result, durationMs }`.
|
|
4463
6086
|
*
|
|
4464
|
-
*
|
|
6087
|
+
* @example Measuring an API call
|
|
6088
|
+
* ```ts
|
|
6089
|
+
* const { result, durationMs } = await utils.measure(() =>
|
|
6090
|
+
* fetch("/api/heavy").then(r => r.json())
|
|
6091
|
+
* );
|
|
6092
|
+
* console.log(`Response received in ${durationMs.toFixed(2)}ms:`, result);
|
|
6093
|
+
* ```
|
|
4465
6094
|
*/
|
|
4466
|
-
|
|
6095
|
+
measure<T>(fn: () => T | Promise<T>): Promise<MeasureResult<T>>;
|
|
4467
6096
|
/**
|
|
4468
|
-
*
|
|
6097
|
+
* ## High-Precision Drift-Corrected Interval
|
|
4469
6098
|
*
|
|
4470
|
-
*
|
|
4471
|
-
* `
|
|
6099
|
+
* Repeatedly executes `fn` with automatic compensation for accumulated
|
|
6100
|
+
* clock drift. Unlike `setInterval`, this implementation adjusts each delay
|
|
6101
|
+
* based on actual elapsed time.
|
|
4472
6102
|
*
|
|
4473
|
-
*
|
|
4474
|
-
*
|
|
4475
|
-
* statements or JSON serialisations.
|
|
6103
|
+
* The current tick count is passed as a parameter to `fn`, enabling
|
|
6104
|
+
* animations or progression counting.
|
|
4476
6105
|
*
|
|
4477
|
-
*
|
|
4478
|
-
* @returns A frozen {@link EnvSnapshot}.
|
|
4479
|
-
* @throws {EnvStoreError} When the store has not been initialised.
|
|
6106
|
+
* Execution stops cleanly when `signal` is aborted.
|
|
4480
6107
|
*
|
|
4481
|
-
* @
|
|
4482
|
-
*
|
|
4483
|
-
*
|
|
4484
|
-
*
|
|
4485
|
-
* });
|
|
6108
|
+
* @param fn - Callback called at each tick, receiving the tick index (0-indexed).
|
|
6109
|
+
* @param ms - Target interval in milliseconds.
|
|
6110
|
+
* @param signal - `AbortSignal` to stop the loop.
|
|
6111
|
+
* @returns A promise that resolves when the signal is aborted.
|
|
4486
6112
|
*
|
|
4487
|
-
*
|
|
4488
|
-
*
|
|
4489
|
-
*
|
|
4490
|
-
*/
|
|
4491
|
-
all(options?: EnvAllOptions): EnvSnapshot;
|
|
4492
|
-
/**
|
|
4493
|
-
* Returns `true` when the execution mode is `"production"`.
|
|
6113
|
+
* @example Counter update every second
|
|
6114
|
+
* ```ts
|
|
6115
|
+
* const controller = new AbortController();
|
|
4494
6116
|
*
|
|
4495
|
-
*
|
|
4496
|
-
*
|
|
4497
|
-
*
|
|
4498
|
-
* });
|
|
4499
|
-
*/
|
|
4500
|
-
isProduction(): boolean;
|
|
4501
|
-
/**
|
|
4502
|
-
* Returns `true` when the execution mode is `"development"`.
|
|
6117
|
+
* utils.repeat((tick) => {
|
|
6118
|
+
* console.log(`Tick ${tick} — ${new Date().toLocaleTimeString()}`);
|
|
6119
|
+
* }, 1000, controller.signal);
|
|
4503
6120
|
*
|
|
4504
|
-
*
|
|
4505
|
-
*
|
|
4506
|
-
*
|
|
4507
|
-
* }
|
|
6121
|
+
* // Stop after 5 seconds
|
|
6122
|
+
* setTimeout(() => controller.abort(), 5000);
|
|
6123
|
+
* ```
|
|
4508
6124
|
*/
|
|
4509
|
-
|
|
6125
|
+
repeat(fn: (tick: number) => void | Promise<void>, ms: number, signal?: AbortSignal): Promise<void>;
|
|
4510
6126
|
/**
|
|
4511
|
-
*
|
|
6127
|
+
* ## Parallel Execution with Limited Concurrency
|
|
4512
6128
|
*
|
|
4513
|
-
*
|
|
4514
|
-
*
|
|
4515
|
-
*
|
|
4516
|
-
*
|
|
6129
|
+
* Processes an array of values in parallel via `fn`, limiting the number
|
|
6130
|
+
* of active promises simultaneously to `concurrency`. Results are returned
|
|
6131
|
+
* in the same order as inputs.
|
|
6132
|
+
*
|
|
6133
|
+
* Ideal for scenarios where you want to avoid saturating a server or database
|
|
6134
|
+
* with thousands of simultaneous requests.
|
|
6135
|
+
*
|
|
6136
|
+
* @param items - Array of items to process.
|
|
6137
|
+
* @param fn - Asynchronous function applied to each element.
|
|
6138
|
+
* @param concurrency - Maximum number of active parallel promises. @default 5
|
|
6139
|
+
* @returns Array of results in the same order as `items`.
|
|
6140
|
+
*
|
|
6141
|
+
* @example Batch file import (max 3 at a time)
|
|
6142
|
+
* ```ts
|
|
6143
|
+
* const files = ["f1.csv", "f2.csv", "f3.csv", "f4.csv"];
|
|
6144
|
+
* const results = await utils.pool(files, f => importFile(f), 3);
|
|
6145
|
+
* ```
|
|
4517
6146
|
*/
|
|
4518
|
-
|
|
6147
|
+
pool<T, R>(items: T[], fn: (item: T, index: number) => Promise<R>, concurrency?: number): Promise<R[]>;
|
|
4519
6148
|
/**
|
|
4520
|
-
*
|
|
6149
|
+
* ## Race with Built-in Timeout
|
|
4521
6150
|
*
|
|
4522
|
-
*
|
|
4523
|
-
*
|
|
4524
|
-
*
|
|
4525
|
-
*
|
|
6151
|
+
* Launches multiple promises in parallel and returns the first one to resolve.
|
|
6152
|
+
* If none resolve within `timeoutMs`, an error is thrown.
|
|
6153
|
+
*
|
|
6154
|
+
* Similar to `Promise.race`, but with an integrated temporal safety net.
|
|
6155
|
+
*
|
|
6156
|
+
* @param fns - Array of functions returning promises.
|
|
6157
|
+
* @param timeoutMs - Maximum delay in milliseconds. @default Infinity
|
|
6158
|
+
* @returns Value of the first resolved promise.
|
|
6159
|
+
* @throws `Error("Race timed out")` if timeout is reached.
|
|
4526
6160
|
*/
|
|
4527
|
-
|
|
6161
|
+
race<T>(fns: Array<() => Promise<T>>, timeoutMs?: number): Promise<T>;
|
|
4528
6162
|
/**
|
|
4529
|
-
*
|
|
4530
|
-
* (case-sensitive).
|
|
6163
|
+
* ## Async Memoization with TTL
|
|
4531
6164
|
*
|
|
4532
|
-
*
|
|
6165
|
+
* Returns a memoized version of `fn`: results are cached for `ttlMs` milliseconds.
|
|
6166
|
+
* After this delay, the next call triggers a fresh execution.
|
|
4533
6167
|
*
|
|
4534
|
-
*
|
|
4535
|
-
*
|
|
4536
|
-
*
|
|
4537
|
-
*
|
|
6168
|
+
* If multiple identical calls arrive simultaneously (while the promise is pending),
|
|
6169
|
+
* they share the same promise — avoiding "thundering herd" on cold caches.
|
|
6170
|
+
*
|
|
6171
|
+
* @param fn - Asynchronous function to memoize.
|
|
6172
|
+
* @param ttlMs - Cache entry TTL (ms). `0` = no expiration.
|
|
6173
|
+
* @param keyFn - Serialization function for arguments into cache keys.
|
|
6174
|
+
* @default `JSON.stringify`
|
|
6175
|
+
* @returns Memoized version of `fn` with `.clear()` method.
|
|
4538
6176
|
*/
|
|
4539
|
-
|
|
6177
|
+
memoize<TArgs extends any[], TResult>(fn: (...args: TArgs) => Promise<TResult>, ttlMs?: number, keyFn?: (...args: TArgs) => string): ((...args: TArgs) => Promise<TResult>) & {
|
|
6178
|
+
clear: () => void;
|
|
6179
|
+
};
|
|
4540
6180
|
/**
|
|
4541
|
-
*
|
|
4542
|
-
* the XHSC native Go binary.
|
|
6181
|
+
* ## Sequential Queue
|
|
4543
6182
|
*
|
|
4544
|
-
*
|
|
4545
|
-
*
|
|
4546
|
-
* can safely use the result without null checks.
|
|
6183
|
+
* Guarantees that tasks are executed **one by one, in the order they were added**.
|
|
6184
|
+
* Tasks submitted while another is pending are queued and executed sequentially.
|
|
4547
6185
|
*
|
|
4548
|
-
*
|
|
6186
|
+
* Unlike `pool(items, fn, 1)`, `queue` allows adding tasks dynamically over time.
|
|
4549
6187
|
*
|
|
4550
|
-
* @
|
|
4551
|
-
*
|
|
4552
|
-
*
|
|
6188
|
+
* @returns An object `{ add, size }`:
|
|
6189
|
+
* - `add(fn)` — Enqueues a task and returns a promise for its result.
|
|
6190
|
+
* - `size` — Getter for the current number of pending tasks.
|
|
6191
|
+
*
|
|
6192
|
+
* @example Critical Database Mutation
|
|
6193
|
+
* ```ts
|
|
6194
|
+
* const db = utils.queue();
|
|
6195
|
+
*
|
|
6196
|
+
* async function transfer(from: string, to: string, amount: number) {
|
|
6197
|
+
* return db.add(async () => {
|
|
6198
|
+
* const balance = await getBalance(from);
|
|
6199
|
+
* if (balance < amount) throw new Error("Insufficient funds");
|
|
6200
|
+
* await debit(from, amount);
|
|
6201
|
+
* await credit(to, amount);
|
|
6202
|
+
* });
|
|
6203
|
+
* }
|
|
6204
|
+
* ```
|
|
4553
6205
|
*/
|
|
4554
|
-
|
|
6206
|
+
queue(): {
|
|
6207
|
+
add: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
6208
|
+
readonly size: number;
|
|
6209
|
+
};
|
|
4555
6210
|
/**
|
|
4556
|
-
*
|
|
4557
|
-
* yet been initialised.
|
|
6211
|
+
* ## Once — Guaranteed Single Execution
|
|
4558
6212
|
*
|
|
4559
|
-
*
|
|
4560
|
-
*
|
|
4561
|
-
*
|
|
6213
|
+
* Returns a version of `fn` that executes only **once**, regardless of how
|
|
6214
|
+
* many calls are made. Subsequent calls receive the cached promise or value
|
|
6215
|
+
* without re-executing `fn`.
|
|
4562
6216
|
*
|
|
4563
|
-
*
|
|
4564
|
-
* fallback to `process.env` during the bootstrap race window would bypass
|
|
4565
|
-
* the Shield and leak values without any warning. A thrown error is
|
|
4566
|
-
* immediately visible during development and integration testing.
|
|
6217
|
+
* Particularly useful for expensive initializations (DB connections, config loading).
|
|
4567
6218
|
*
|
|
4568
|
-
* @
|
|
4569
|
-
* @
|
|
6219
|
+
* @param fn - The function to execute exactly once.
|
|
6220
|
+
* @returns A function that always returns the same resolved promise.
|
|
4570
6221
|
*/
|
|
4571
|
-
|
|
4572
|
-
private getStoreForCaller;
|
|
6222
|
+
once<TArgs extends any[], TResult>(fn: (...args: TArgs) => Promise<TResult>): (...args: TArgs) => Promise<TResult>;
|
|
4573
6223
|
/**
|
|
4574
|
-
*
|
|
6224
|
+
* ## Conditional Polling
|
|
4575
6225
|
*
|
|
4576
|
-
*
|
|
4577
|
-
*
|
|
6226
|
+
* Repeatedly polls `fn` until `predicate` returns `true` or a signal is aborted.
|
|
6227
|
+
*
|
|
6228
|
+
* @param fn - Asynchronous function returning value to test.
|
|
6229
|
+
* @param predicate - Success condition for the returned value.
|
|
6230
|
+
* @param interval - Delay between attempts (ms). @default 1000
|
|
6231
|
+
* @param signal - `AbortSignal` to stop polling.
|
|
6232
|
+
* @returns The value for which `predicate` returned `true`.
|
|
6233
|
+
* @throws `DOMException("AbortError")` if signal is aborted before success.
|
|
4578
6234
|
*/
|
|
4579
|
-
|
|
6235
|
+
poll<T>(fn: () => Promise<T>, predicate: (value: T) => boolean, interval?: number, signal?: AbortSignal): Promise<T>;
|
|
6236
|
+
}
|
|
6237
|
+
|
|
6238
|
+
/**
|
|
6239
|
+
* **ValidationUtils — XyPriss Validation Utilities**
|
|
6240
|
+
*/
|
|
6241
|
+
declare class ValidationUtils {
|
|
4580
6242
|
/**
|
|
4581
|
-
*
|
|
4582
|
-
* downstream parsers, log sinks, or HTTP serialisers.
|
|
6243
|
+
* **email**
|
|
4583
6244
|
*
|
|
4584
|
-
*
|
|
4585
|
-
* - CR (`\r`) and LF (`\n`) — break line-oriented `.env` parsers and
|
|
4586
|
-
* enable log injection attacks.
|
|
4587
|
-
* - NUL (`\0`) — truncates strings in C-based runtimes and can bypass
|
|
4588
|
-
* suffix-based extension checks in some file path handling code.
|
|
6245
|
+
* Performs semantic validation on an email address string.
|
|
4589
6246
|
*
|
|
4590
|
-
* @
|
|
4591
|
-
* @
|
|
6247
|
+
* @param email The email string to validate.
|
|
6248
|
+
* @returns `true` if valid, `false` otherwise.
|
|
4592
6249
|
*/
|
|
4593
|
-
|
|
6250
|
+
email(email: string): boolean;
|
|
4594
6251
|
/**
|
|
4595
|
-
* **
|
|
6252
|
+
* **url**
|
|
4596
6253
|
*
|
|
4597
|
-
*
|
|
4598
|
-
* the following policies on every property access:
|
|
4599
|
-
*
|
|
4600
|
-
* **Read trap**
|
|
4601
|
-
* - Whitelisted keys (see {@link EnvApi.whitelistedFields}) and keys
|
|
4602
|
-
* matching the prefixes `XY_`, `XYPRISS_`, `ENC_`, `DOTENV_`, or `__`
|
|
4603
|
-
* pass through to the real value.
|
|
4604
|
-
* - All other reads return `undefined`. A one-time per-key warning is
|
|
4605
|
-
* written to `process.stderr` (suppressed when
|
|
4606
|
-
* `XYPRISS_ENV_SHIELD=silent`).
|
|
6254
|
+
* Validates a URL string using the `strulink` RFC-compliant URI parser.
|
|
4607
6255
|
*
|
|
4608
|
-
*
|
|
4609
|
-
*
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
6256
|
+
* @param url The URL string to validate.
|
|
6257
|
+
* @returns `true` if valid, `false` otherwise.
|
|
6258
|
+
*/
|
|
6259
|
+
url(url: string | URL): boolean;
|
|
6260
|
+
/**
|
|
6261
|
+
* **nullish**
|
|
4613
6262
|
*
|
|
4614
|
-
*
|
|
4615
|
-
* by application code, and `configurable: true` to allow test teardown.
|
|
6263
|
+
* A type guard that determines if a value is either `null` or `undefined`.
|
|
4616
6264
|
*
|
|
4617
|
-
* @
|
|
6265
|
+
* @param value The value to check.
|
|
6266
|
+
* @returns `true` if null or undefined.
|
|
4618
6267
|
*/
|
|
6268
|
+
nullish(value: unknown): value is null | undefined;
|
|
6269
|
+
}
|
|
6270
|
+
|
|
6271
|
+
/**
|
|
6272
|
+
* **IdUtils — Identity Primitives**
|
|
6273
|
+
*/
|
|
6274
|
+
declare class IdUtils {
|
|
4619
6275
|
/**
|
|
4620
|
-
* **
|
|
4621
|
-
*
|
|
4622
|
-
* Replaces the `process.env` object with a hardened Proxy that enforces
|
|
4623
|
-
* the following policies on every property access:
|
|
6276
|
+
* **uuid**
|
|
4624
6277
|
*
|
|
4625
|
-
*
|
|
4626
|
-
* - Whitelisted keys (see {@link EnvApi.whitelistedFields}) and keys
|
|
4627
|
-
* matching the prefixes `XY_`, `XYPRISS_`, `ENC_`, `DOTENV_`, or `__`
|
|
4628
|
-
* pass through to the real value.
|
|
4629
|
-
* - All other reads return `undefined`. A one-time per-key warning is
|
|
4630
|
-
* written to `process.stderr` (suppressed when
|
|
4631
|
-
* `XYPRISS_ENV_SHIELD=silent`).
|
|
6278
|
+
* Generates a RFC-compliant UUID v4 using the `nehoid` engine.
|
|
4632
6279
|
*
|
|
4633
|
-
*
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
6280
|
+
* @returns A random UUID string.
|
|
6281
|
+
*/
|
|
6282
|
+
uuid(): string;
|
|
6283
|
+
}
|
|
6284
|
+
|
|
6285
|
+
/**
|
|
6286
|
+
* **FunctionUtils — Functional Programming Helpers**
|
|
6287
|
+
*/
|
|
6288
|
+
declare class FunctionUtils {
|
|
6289
|
+
/**
|
|
6290
|
+
* **memo**
|
|
4638
6291
|
*
|
|
4639
|
-
*
|
|
4640
|
-
* by application code, and `configurable: true` to allow test teardown.
|
|
6292
|
+
* Returns a memoized version of a function that caches its results based on input parameters.
|
|
4641
6293
|
*
|
|
4642
|
-
* @
|
|
6294
|
+
* @param fn The function to memoize.
|
|
6295
|
+
* @returns The memoized function.
|
|
4643
6296
|
*/
|
|
4644
|
-
|
|
4645
|
-
|
|
6297
|
+
memo<T extends (...args: any[]) => any>(fn: T): T;
|
|
6298
|
+
}
|
|
6299
|
+
|
|
6300
|
+
/**
|
|
6301
|
+
* **UtilsApi — XyPriss System Utility Module**
|
|
6302
|
+
*
|
|
6303
|
+
* A comprehensive, high-performance utility class for application development.
|
|
6304
|
+
* Utilities are grouped into specialized categories for better modularity.
|
|
6305
|
+
*
|
|
6306
|
+
* Exposed via `__sys__.utils`.
|
|
6307
|
+
*
|
|
6308
|
+
* @example
|
|
6309
|
+
* ```ts
|
|
6310
|
+
* __sys__.utils.num.formatBytes(1048576); // "1 MB"
|
|
6311
|
+
* __sys__.utils.is.email("test@example.com"); // true
|
|
6312
|
+
* __sys__.utils.id.uuid(); // "550e8400-e29b-41d4-a716-446655440000"
|
|
6313
|
+
* ```
|
|
6314
|
+
*/
|
|
6315
|
+
declare class UtilsApi {
|
|
6316
|
+
/** **String Utilities** (`slugify`, `truncate`, `randomString`, etc.) */
|
|
6317
|
+
readonly str: StringUtils;
|
|
6318
|
+
/** **Number & Math Utilities** (`clamp`, `lerp`, `formatBytes`, etc.) */
|
|
6319
|
+
readonly num: NumberUtils;
|
|
6320
|
+
/** **Date & Time Utilities** (`formatDuration`, `timeAgo`, etc.) */
|
|
6321
|
+
readonly date: DateUtils;
|
|
6322
|
+
/** **Object Utilities** (`deepClone`, `parse`, `pick`, etc.) */
|
|
6323
|
+
readonly obj: ObjectUtils;
|
|
6324
|
+
/** **Array Utilities** (`chunk`, `unique`, `groupBy`, etc.) */
|
|
6325
|
+
readonly arr: ArrayUtils;
|
|
6326
|
+
/** **Async & Control Flow Utilities** (`sleep`, `retry`, `debounce`, etc.) */
|
|
6327
|
+
readonly async: AsyncUtils;
|
|
6328
|
+
/** **Validation Utilities** (`email`, `url`, `nullish`) */
|
|
6329
|
+
readonly is: ValidationUtils;
|
|
6330
|
+
/** **Identity Utilities** (`uuid`) */
|
|
6331
|
+
readonly id: IdUtils;
|
|
6332
|
+
/** **Functional Utilities** (`memo`) */
|
|
6333
|
+
readonly fn: FunctionUtils;
|
|
4646
6334
|
}
|
|
4647
6335
|
|
|
4648
6336
|
/**
|
|
@@ -4669,6 +6357,7 @@ declare class XyPrissFS {
|
|
|
4669
6357
|
fs: FSApi;
|
|
4670
6358
|
path: PathApi;
|
|
4671
6359
|
os: OSApi;
|
|
6360
|
+
utils: UtilsApi;
|
|
4672
6361
|
protected _internalRoot: string;
|
|
4673
6362
|
/**
|
|
4674
6363
|
* **Project Root Path**
|
|
@@ -7321,6 +9010,12 @@ declare class XemsRunner {
|
|
|
7321
9010
|
/**
|
|
7322
9011
|
* Enables hardware-bound persistent storage for XEMS.
|
|
7323
9012
|
*/
|
|
9013
|
+
private static runnersByPath;
|
|
9014
|
+
/**
|
|
9015
|
+
* Internal factory for getting or creating a runner for a specific path.
|
|
9016
|
+
* This ensures only one process exists for a given file in the entire process.
|
|
9017
|
+
*/
|
|
9018
|
+
static getInstance(pathStr: string, options?: XemsOptions): XemsRunner;
|
|
7324
9019
|
enablePersistence(pathStr: string, secret: string, resources?: {
|
|
7325
9020
|
cacheSize?: number;
|
|
7326
9021
|
}): void;
|
|
@@ -8217,63 +9912,6 @@ declare class MultiServerApp implements XyPrissApp {
|
|
|
8217
9912
|
getOptimizerStats(): any;
|
|
8218
9913
|
}
|
|
8219
9914
|
|
|
8220
|
-
/**
|
|
8221
|
-
* Safe JSON Middleware for Express
|
|
8222
|
-
* Automatically handles circular references in JSON responses
|
|
8223
|
-
*/
|
|
8224
|
-
|
|
8225
|
-
interface SafeJsonOptions {
|
|
8226
|
-
/**
|
|
8227
|
-
* Enable safe JSON serialization for all responses
|
|
8228
|
-
* @default true
|
|
8229
|
-
*/
|
|
8230
|
-
enabled?: boolean;
|
|
8231
|
-
/**
|
|
8232
|
-
* Maximum depth for object serialization
|
|
8233
|
-
* @default 10
|
|
8234
|
-
*/
|
|
8235
|
-
maxDepth?: number;
|
|
8236
|
-
/**
|
|
8237
|
-
* Maximum string length before truncation
|
|
8238
|
-
* @default 1000
|
|
8239
|
-
*/
|
|
8240
|
-
truncateStrings?: number;
|
|
8241
|
-
/**
|
|
8242
|
-
* Include non-enumerable properties
|
|
8243
|
-
* @default false
|
|
8244
|
-
*/
|
|
8245
|
-
includeNonEnumerable?: boolean;
|
|
8246
|
-
/**
|
|
8247
|
-
* Log when circular references are detected
|
|
8248
|
-
* @default false
|
|
8249
|
-
*/
|
|
8250
|
-
logCircularRefs?: boolean;
|
|
8251
|
-
/**
|
|
8252
|
-
* Custom replacer function for additional handling
|
|
8253
|
-
*/
|
|
8254
|
-
customReplacer?: (key: string, value: any) => any;
|
|
8255
|
-
}
|
|
8256
|
-
/**
|
|
8257
|
-
* Creates middleware that safely handles JSON serialization
|
|
8258
|
-
*/
|
|
8259
|
-
declare function createSafeJsonMiddleware(options?: SafeJsonOptions): (req: XyPrisRequest, res: XyPrisResponse, next: NextFunction) => void;
|
|
8260
|
-
/**
|
|
8261
|
-
* Quick setup function for common use cases
|
|
8262
|
-
*/
|
|
8263
|
-
declare function setupSafeJson(app: any, options?: SafeJsonOptions): void;
|
|
8264
|
-
/**
|
|
8265
|
-
* Utility function to safely stringify any object
|
|
8266
|
-
*/
|
|
8267
|
-
declare function safeJsonStringify(obj: any, options?: SafeJsonOptions): string;
|
|
8268
|
-
/**
|
|
8269
|
-
* Enhanced res.json replacement that can be used manually
|
|
8270
|
-
*/
|
|
8271
|
-
declare function sendSafeJson(res: XyPrisResponse, obj: any, options?: SafeJsonOptions): void;
|
|
8272
|
-
/**
|
|
8273
|
-
* Middleware specifically for debugging circular references
|
|
8274
|
-
*/
|
|
8275
|
-
declare function createCircularRefDebugger(): (req: XyPrisRequest, res: XyPrisResponse, next: NextFunction) => void;
|
|
8276
|
-
|
|
8277
9915
|
/***************************************************************************
|
|
8278
9916
|
* XyPrissJS - Fast And Secure
|
|
8279
9917
|
*
|
|
@@ -8978,5 +10616,5 @@ declare const getMimes: (extensions?: string | string[]) => string[];
|
|
|
8978
10616
|
*/
|
|
8979
10617
|
declare function Router(): XyPrissRouter;
|
|
8980
10618
|
|
|
8981
|
-
export { ConfigurationManager as CM, ConfigurationManager as Configs, FileUploadAPI as FLA, FileUploadAPI, Plugin, PluginHookIds, Router, SecurityMiddleware, Upload, XJsonResponseHandler, XyGuard, MultiServerApp as XyPMS, XyPrissRouter, XyPrissXHSC, __cfg__, __const__, __sys__,
|
|
10619
|
+
export { ConfigurationManager as CM, ConfigurationManager as Configs, FileUploadAPI as FLA, FileUploadAPI, Plugin, PluginHookIds, Router, SecurityMiddleware, Upload, XJsonResponseHandler, XyGuard, MultiServerApp as XyPMS, XyPrissRouter, XyPrissXHSC, __cfg__, __const__, __sys__, createOptimalCache, createServer, getCallerProjectRoot, getIp, getMime, getMimes, identifyProjectRoot, initializeFileUpload, mergeWithDefaults, mergeWithDefaults as mwdef, quickServer, uploadAny, uploadArray, uploadFields, uploadSingle, xems };
|
|
8982
10620
|
export type { ArchiveOptions, BatchRenameChange, CacheConfig, FileUploadConfig as FiUpConfig, FileUploadConfig, GetIpResult, IpSource, MonitorSnapshot, MultiServerConfig, NetworkStats, NextFunction, PerformanceConfig, PluginCreator, ProcessInfo, ProcessMonitorSnapshot, XyPrisRequest as Request, RequestHandler, XyPrisResponse as Response, RoutRateLimit, RouteConfig, RouteGuard, RouteMeta, RouteOptions, ParamType as RouteParamType, SecurityConfig, ServerOptions$1 as ServerOptions, XyPrisRequest$1 as XRequest, XyPrisResponse$1 as XResponse, XemsTypes, XyPrisRequest$1 as XyPrisRequest, XyPrisResponse$1 as XyPrisResponse, XyPrissApp, XyPrissPlugin };
|