@md-oss/common 0.1.5 → 0.1.7
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/dist/arrays-6DA6GfsQ.mjs +2 -0
- package/dist/arrays-6DA6GfsQ.mjs.map +1 -0
- package/dist/arrays-DvPJ1GeR.d.cts +163 -0
- package/dist/arrays-DvPJ1GeR.d.mts +163 -0
- package/dist/arrays-bgbansWs.cjs +2 -0
- package/dist/arrays-bgbansWs.cjs.map +1 -0
- package/dist/constants/bytes.cjs +1 -1
- package/dist/constants/bytes.cjs.map +1 -1
- package/dist/constants/bytes.d.cts +31 -1
- package/dist/constants/bytes.d.mts +31 -1
- package/dist/constants/bytes.mjs +1 -1
- package/dist/constants/bytes.mjs.map +1 -1
- package/dist/files-DzKYei0a.mjs +2 -0
- package/dist/files-DzKYei0a.mjs.map +1 -0
- package/dist/files-m1nnj5gT.cjs +2 -0
- package/dist/files-m1nnj5gT.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +10 -8
- package/dist/index.d.mts +10 -8
- package/dist/index.mjs +1 -1
- package/dist/mime-types-BmvBrrZ7.cjs.map +1 -1
- package/dist/mime-types-D_K53zgk.mjs.map +1 -1
- package/dist/{mime-types-Bjt4NvnE.d.cts → mime-types-Dajfhq2c.d.cts} +58 -1
- package/dist/{mime-types-Bjt4NvnE.d.mts → mime-types-Dajfhq2c.d.mts} +58 -1
- package/dist/numbers-B_mptknO.cjs +2 -0
- package/dist/numbers-B_mptknO.cjs.map +1 -0
- package/dist/numbers-C2680fmA.d.cts +184 -0
- package/dist/numbers-C2680fmA.d.mts +184 -0
- package/dist/numbers-lJ6gwIpk.mjs +2 -0
- package/dist/numbers-lJ6gwIpk.mjs.map +1 -0
- package/dist/objects-VXf3mqE5.mjs +2 -0
- package/dist/objects-VXf3mqE5.mjs.map +1 -0
- package/dist/objects-fiFExjsf.d.cts +116 -0
- package/dist/objects-fiFExjsf.d.mts +116 -0
- package/dist/objects-wcO6hNA8.cjs +2 -0
- package/dist/objects-wcO6hNA8.cjs.map +1 -0
- package/dist/random-668tofPV.cjs +2 -0
- package/dist/random-668tofPV.cjs.map +1 -0
- package/dist/random-BqJDZAPb.d.cts +131 -0
- package/dist/random-BqJDZAPb.d.mts +131 -0
- package/dist/random-ihslkInn.mjs +2 -0
- package/dist/random-ihslkInn.mjs.map +1 -0
- package/dist/runtime-7fkN5_oL.d.cts +206 -0
- package/dist/runtime-7fkN5_oL.d.mts +206 -0
- package/dist/runtime-Bfs-yn_-.cjs +2 -0
- package/dist/runtime-Bfs-yn_-.cjs.map +1 -0
- package/dist/runtime-CE36Va0l.mjs +2 -0
- package/dist/runtime-CE36Va0l.mjs.map +1 -0
- package/dist/strings-CrzGdnZH.mjs +3 -0
- package/dist/strings-CrzGdnZH.mjs.map +1 -0
- package/dist/strings-_1vAPvzS.cjs +3 -0
- package/dist/strings-_1vAPvzS.cjs.map +1 -0
- package/dist/strings-jE1j-qqa.d.cts +213 -0
- package/dist/strings-jE1j-qqa.d.mts +213 -0
- package/dist/time-BrLHgSth.d.mts +68 -0
- package/dist/time-DmJNWZeL.mjs.map +1 -1
- package/dist/time-ufhllID1.d.cts +68 -0
- package/dist/time-yNkQSJnQ.cjs.map +1 -1
- package/dist/utils/arrays.cjs +1 -1
- package/dist/utils/arrays.d.cts +1 -1
- package/dist/utils/arrays.d.mts +1 -1
- package/dist/utils/arrays.mjs +1 -1
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.cts +187 -8
- package/dist/utils/index.d.mts +187 -8
- package/dist/utils/index.mjs +1 -1
- package/dist/utils/mime-types.d.cts +1 -1
- package/dist/utils/mime-types.d.mts +1 -1
- package/dist/utils/numbers.cjs +1 -1
- package/dist/utils/numbers.d.cts +1 -1
- package/dist/utils/numbers.d.mts +1 -1
- package/dist/utils/numbers.mjs +1 -1
- package/dist/utils/objects.cjs +1 -1
- package/dist/utils/objects.d.cts +1 -1
- package/dist/utils/objects.d.mts +1 -1
- package/dist/utils/objects.mjs +1 -1
- package/dist/utils/random.cjs +1 -1
- package/dist/utils/random.d.cts +1 -1
- package/dist/utils/random.d.mts +1 -1
- package/dist/utils/random.mjs +1 -1
- package/dist/utils/runtime.cjs +1 -1
- package/dist/utils/runtime.d.cts +1 -1
- package/dist/utils/runtime.d.mts +1 -1
- package/dist/utils/runtime.mjs +1 -1
- package/dist/utils/strings.cjs +1 -1
- package/dist/utils/strings.d.cts +1 -1
- package/dist/utils/strings.d.mts +1 -1
- package/dist/utils/strings.mjs +1 -1
- package/dist/utils/time.d.cts +1 -1
- package/dist/utils/time.d.mts +1 -1
- package/package.json +2 -2
- package/dist/arrays-BkHBzTDO.mjs +0 -2
- package/dist/arrays-BkHBzTDO.mjs.map +0 -1
- package/dist/arrays-CElcW69H.d.cts +0 -43
- package/dist/arrays-CElcW69H.d.mts +0 -43
- package/dist/arrays-DaB1Xn47.cjs +0 -2
- package/dist/arrays-DaB1Xn47.cjs.map +0 -1
- package/dist/numbers-BmUSgeah.d.cts +0 -46
- package/dist/numbers-BmUSgeah.d.mts +0 -46
- package/dist/numbers-Bx9JTSQe.mjs +0 -2
- package/dist/numbers-Bx9JTSQe.mjs.map +0 -1
- package/dist/numbers-DuVx9Qiu.cjs +0 -2
- package/dist/numbers-DuVx9Qiu.cjs.map +0 -1
- package/dist/objects--cO_X3EV.mjs +0 -2
- package/dist/objects--cO_X3EV.mjs.map +0 -1
- package/dist/objects-CnGoVkh6.cjs +0 -2
- package/dist/objects-CnGoVkh6.cjs.map +0 -1
- package/dist/objects-cf8j7rS8.d.cts +0 -26
- package/dist/objects-cf8j7rS8.d.mts +0 -26
- package/dist/random-D1e1NTOt.cjs +0 -2
- package/dist/random-D1e1NTOt.cjs.map +0 -1
- package/dist/random-DbidGSrQ.mjs +0 -2
- package/dist/random-DbidGSrQ.mjs.map +0 -1
- package/dist/random-DpNyGGAZ.d.cts +0 -28
- package/dist/random-DpNyGGAZ.d.mts +0 -28
- package/dist/runtime-B-jA8ZxR.cjs +0 -2
- package/dist/runtime-B-jA8ZxR.cjs.map +0 -1
- package/dist/runtime-CbfL6Fgj.mjs +0 -2
- package/dist/runtime-CbfL6Fgj.mjs.map +0 -1
- package/dist/runtime-T8Kcf7Af.d.cts +0 -28
- package/dist/runtime-T8Kcf7Af.d.mts +0 -28
- package/dist/strings-B0BRwNX9.mjs +0 -3
- package/dist/strings-B0BRwNX9.mjs.map +0 -1
- package/dist/strings-DV446vv-.cjs +0 -3
- package/dist/strings-DV446vv-.cjs.map +0 -1
- package/dist/strings-DhPbrpq7.d.cts +0 -47
- package/dist/strings-DhPbrpq7.d.mts +0 -47
- package/dist/time-8KLG8kBO.d.cts +0 -29
- package/dist/time-D8Wfqzu6.d.mts +0 -29
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sleep for a specified number of milliseconds
|
|
3
|
+
* @param ms - Milliseconds to sleep
|
|
4
|
+
* @returns Promise that resolves after the specified time
|
|
5
|
+
* @example await sleep(1000) // Sleep for 1 second
|
|
6
|
+
*/
|
|
7
|
+
declare const sleep: (ms: number) => Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Sleep until a condition becomes true
|
|
10
|
+
* @param condition - Function that returns true when ready to continue
|
|
11
|
+
* @param interval - How often to check the condition in ms (default: 1000)
|
|
12
|
+
* @returns Promise that resolves when condition is true
|
|
13
|
+
* @example await sleepUntil(() => dataLoaded, 500)
|
|
14
|
+
*/
|
|
15
|
+
declare const sleepUntil: (condition: () => boolean | Promise<boolean>, interval?: number) => Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Sleep until a condition becomes true or timeout is reached
|
|
18
|
+
* @param condition - Function that returns true when ready to continue
|
|
19
|
+
* @param timeout - Maximum time to wait in ms
|
|
20
|
+
* @param interval - How often to check the condition in ms (default: 1000)
|
|
21
|
+
* @returns Promise that resolves when condition is true or timeout is reached
|
|
22
|
+
* @example await sleepUntilOrTimeout(() => dataLoaded, 5000, 500)
|
|
23
|
+
*/
|
|
24
|
+
declare const sleepUntilOrTimeout: (condition: () => boolean | Promise<boolean>, timeout: number, interval?: number) => Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Race a promise against a timeout
|
|
27
|
+
* @param promise - Promise to await
|
|
28
|
+
* @param timeout - Timeout in milliseconds
|
|
29
|
+
* @returns Promise that resolves with the value or rejects on timeout
|
|
30
|
+
* @example await awaitOrTimeout(fetchData(), 5000)
|
|
31
|
+
*/
|
|
32
|
+
declare const awaitOrTimeout: <T>(promise: Promise<T>, timeout: number) => Promise<T>;
|
|
33
|
+
/**
|
|
34
|
+
* Safely set a timeout that handles values larger than INT32_MAX
|
|
35
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
36
|
+
* @param scheduleOverflowInFuture - Whether to schedule overflow timeouts automatically
|
|
37
|
+
* @param fn - Function to execute
|
|
38
|
+
* @param onNewTimeout - Callback when a new timeout is scheduled
|
|
39
|
+
* @returns Timeout handle
|
|
40
|
+
* @example safeSetTimeout(2147483648, true, () => console.log('Done'))
|
|
41
|
+
*/
|
|
42
|
+
declare const safeSetTimeout: (timeoutMs: number, scheduleOverflowInFuture: boolean, fn: () => void, onNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void) => NodeJS.Timeout;
|
|
43
|
+
/**
|
|
44
|
+
* Safely set an interval that handles values larger than INT32_MAX
|
|
45
|
+
* @param intervalMs - Interval in milliseconds
|
|
46
|
+
* @param fn - Function to execute
|
|
47
|
+
* @param onNewTimeout - Callback when a new timeout is scheduled
|
|
48
|
+
* @returns Timeout handle
|
|
49
|
+
* @example safeSetInterval(2147483648, () => console.log('Tick'))
|
|
50
|
+
*/
|
|
51
|
+
declare const safeSetInterval: (intervalMs: number, fn: () => void, onNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void) => NodeJS.Timeout;
|
|
52
|
+
/**
|
|
53
|
+
* Safely set an async interval that handles values larger than INT32_MAX
|
|
54
|
+
* @param intervalMs - Interval in milliseconds
|
|
55
|
+
* @param fn - Async function to execute
|
|
56
|
+
* @param onNewTimeout - Callback when a new timeout is scheduled
|
|
57
|
+
* @returns Timeout handle
|
|
58
|
+
* @example safeSetAsyncInterval(2147483648, async () => await doWork())
|
|
59
|
+
*/
|
|
60
|
+
declare const safeSetAsyncInterval: (intervalMs: number, fn: () => Promise<void>, onNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void) => NodeJS.Timeout;
|
|
61
|
+
/**
|
|
62
|
+
* Result of a batch operation
|
|
63
|
+
*/
|
|
64
|
+
type BatchResult<T> = {
|
|
65
|
+
/** Successfully processed results */
|
|
66
|
+
results: T[];
|
|
67
|
+
/** Errors that occurred during processing */
|
|
68
|
+
errors: Array<{
|
|
69
|
+
index: number;
|
|
70
|
+
error: Error;
|
|
71
|
+
}>;
|
|
72
|
+
/** Total number of tasks */
|
|
73
|
+
total: number;
|
|
74
|
+
/** Number of successful tasks */
|
|
75
|
+
successful: number;
|
|
76
|
+
/** Number of failed tasks */
|
|
77
|
+
failed: number;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Options for batch processing
|
|
81
|
+
*/
|
|
82
|
+
interface BatchProcessOptions {
|
|
83
|
+
/** Maximum number of concurrent executions (default: 5) */
|
|
84
|
+
concurrency?: number;
|
|
85
|
+
/** Whether to stop on first error (default: false) */
|
|
86
|
+
stopOnError?: boolean;
|
|
87
|
+
/** Timeout per task in milliseconds (default: none) */
|
|
88
|
+
taskTimeout?: number;
|
|
89
|
+
/** Delay between batches in milliseconds (default: 0) */
|
|
90
|
+
batchDelay?: number;
|
|
91
|
+
/** Callback for progress updates */
|
|
92
|
+
onProgress?: (completed: number, total: number) => void;
|
|
93
|
+
/** Callback for each error */
|
|
94
|
+
onError?: (error: Error, index: number) => void;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Options for batch processing with retry
|
|
98
|
+
*/
|
|
99
|
+
interface BatchProcessWithRetryOptions extends BatchProcessOptions {
|
|
100
|
+
/** Maximum number of retry attempts (default: 3) */
|
|
101
|
+
maxRetries?: number;
|
|
102
|
+
/** Delay between retries in milliseconds (default: 1000) */
|
|
103
|
+
retryDelay?: number;
|
|
104
|
+
/** Backoff multiplier for retry delay (default: 2) */
|
|
105
|
+
retryBackoff?: number;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Execute async tasks with controlled concurrency
|
|
109
|
+
* @param tasks - Array of async functions to execute
|
|
110
|
+
* @param concurrency - Maximum number of concurrent executions (default: 5)
|
|
111
|
+
* @returns Array of results in the same order as input tasks
|
|
112
|
+
* @throws Error if any task fails (use batchProcess for error handling)
|
|
113
|
+
* @example
|
|
114
|
+
* const results = await executeWithConcurrency(
|
|
115
|
+
* urls.map(url => () => fetch(url)),
|
|
116
|
+
* 3
|
|
117
|
+
* );
|
|
118
|
+
*/
|
|
119
|
+
declare function executeWithConcurrency<T>(tasks: (() => Promise<T>)[], concurrency?: number): Promise<T[]>;
|
|
120
|
+
/**
|
|
121
|
+
* Process tasks in batches with advanced error handling and progress tracking
|
|
122
|
+
* @param tasks - Array of async functions to execute
|
|
123
|
+
* @param options - Batch processing options
|
|
124
|
+
* @returns BatchResult with results and error information
|
|
125
|
+
* @example
|
|
126
|
+
* const result = await batchProcess(
|
|
127
|
+
* urls.map(url => () => fetchData(url)),
|
|
128
|
+
* {
|
|
129
|
+
* concurrency: 3,
|
|
130
|
+
* stopOnError: false,
|
|
131
|
+
* onProgress: (done, total) => console.log(`${done}/${total}`)
|
|
132
|
+
* }
|
|
133
|
+
* );
|
|
134
|
+
*/
|
|
135
|
+
declare function batchProcess<T>(tasks: (() => Promise<T>)[], options?: BatchProcessOptions): Promise<BatchResult<T>>;
|
|
136
|
+
/**
|
|
137
|
+
* Map over an array with controlled concurrency
|
|
138
|
+
* @param items - Array of items to process
|
|
139
|
+
* @param mapper - Async function to transform each item
|
|
140
|
+
* @param concurrency - Maximum number of concurrent executions (default: 5)
|
|
141
|
+
* @returns Array of transformed results in the same order
|
|
142
|
+
* @throws Error if any transformation fails
|
|
143
|
+
* @example
|
|
144
|
+
* const users = await batchMap(
|
|
145
|
+
* userIds,
|
|
146
|
+
* async (id) => await fetchUser(id),
|
|
147
|
+
* 3
|
|
148
|
+
* );
|
|
149
|
+
*/
|
|
150
|
+
declare function batchMap<T, R>(items: T[], mapper: (item: T, index: number) => Promise<R>, concurrency?: number): Promise<R[]>;
|
|
151
|
+
/**
|
|
152
|
+
* Map over an array with controlled concurrency and retry logic
|
|
153
|
+
* @param items - Array of items to process
|
|
154
|
+
* @param mapper - Async function to transform each item
|
|
155
|
+
* @param options - Batch processing options with retry configuration
|
|
156
|
+
* @returns BatchResult with results and error information
|
|
157
|
+
* @example
|
|
158
|
+
* const result = await batchMapWithRetry(
|
|
159
|
+
* userIds,
|
|
160
|
+
* async (id) => await fetchUser(id),
|
|
161
|
+
* {
|
|
162
|
+
* concurrency: 3,
|
|
163
|
+
* maxRetries: 3,
|
|
164
|
+
* retryDelay: 1000,
|
|
165
|
+
* stopOnError: false
|
|
166
|
+
* }
|
|
167
|
+
* );
|
|
168
|
+
*/
|
|
169
|
+
declare function batchMapWithRetry<T, R>(items: T[], mapper: (item: T, index: number) => Promise<R>, options?: BatchProcessWithRetryOptions): Promise<BatchResult<R>>;
|
|
170
|
+
/**
|
|
171
|
+
* Process items in chunks/batches sequentially
|
|
172
|
+
* @param items - Array of items to process
|
|
173
|
+
* @param batchSize - Number of items per batch
|
|
174
|
+
* @param processor - Function to process each batch
|
|
175
|
+
* @returns Array of batch results
|
|
176
|
+
* @example
|
|
177
|
+
* const results = await processBatches(
|
|
178
|
+
* allUsers,
|
|
179
|
+
* 100,
|
|
180
|
+
* async (batch) => await bulkInsert(batch)
|
|
181
|
+
* );
|
|
182
|
+
*/
|
|
183
|
+
declare function processBatches<T, R>(items: T[], batchSize: number, processor: (batch: T[], batchIndex: number) => Promise<R>): Promise<R[]>;
|
|
184
|
+
|
|
185
|
+
type runtime_BatchProcessOptions = BatchProcessOptions;
|
|
186
|
+
type runtime_BatchProcessWithRetryOptions = BatchProcessWithRetryOptions;
|
|
187
|
+
type runtime_BatchResult<T> = BatchResult<T>;
|
|
188
|
+
declare const runtime_awaitOrTimeout: typeof awaitOrTimeout;
|
|
189
|
+
declare const runtime_batchMap: typeof batchMap;
|
|
190
|
+
declare const runtime_batchMapWithRetry: typeof batchMapWithRetry;
|
|
191
|
+
declare const runtime_batchProcess: typeof batchProcess;
|
|
192
|
+
declare const runtime_executeWithConcurrency: typeof executeWithConcurrency;
|
|
193
|
+
declare const runtime_processBatches: typeof processBatches;
|
|
194
|
+
declare const runtime_safeSetAsyncInterval: typeof safeSetAsyncInterval;
|
|
195
|
+
declare const runtime_safeSetInterval: typeof safeSetInterval;
|
|
196
|
+
declare const runtime_safeSetTimeout: typeof safeSetTimeout;
|
|
197
|
+
declare const runtime_sleep: typeof sleep;
|
|
198
|
+
declare const runtime_sleepUntil: typeof sleepUntil;
|
|
199
|
+
declare const runtime_sleepUntilOrTimeout: typeof sleepUntilOrTimeout;
|
|
200
|
+
declare namespace runtime {
|
|
201
|
+
export { runtime_awaitOrTimeout as awaitOrTimeout, runtime_batchMap as batchMap, runtime_batchMapWithRetry as batchMapWithRetry, runtime_batchProcess as batchProcess, runtime_executeWithConcurrency as executeWithConcurrency, runtime_processBatches as processBatches, runtime_safeSetAsyncInterval as safeSetAsyncInterval, runtime_safeSetInterval as safeSetInterval, runtime_safeSetTimeout as safeSetTimeout, runtime_sleep as sleep, runtime_sleepUntil as sleepUntil, runtime_sleepUntilOrTimeout as sleepUntilOrTimeout };
|
|
202
|
+
export type { runtime_BatchProcessOptions as BatchProcessOptions, runtime_BatchProcessWithRetryOptions as BatchProcessWithRetryOptions, runtime_BatchResult as BatchResult };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export { sleepUntil as a, sleepUntilOrTimeout as b, awaitOrTimeout as c, safeSetTimeout as d, safeSetInterval as e, safeSetAsyncInterval as f, executeWithConcurrency as g, batchProcess as h, batchMap as i, batchMapWithRetry as j, processBatches as p, runtime as r, sleep as s };
|
|
206
|
+
export type { BatchResult as B, BatchProcessOptions as k, BatchProcessWithRetryOptions as l };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var N=Object.defineProperty;var s=(e,t)=>N(e,"name",{value:t,configurable:!0});var I=require("./numbers-B_mptknO.cjs"),d=require("./constants/time.cjs");const T=s(e=>new Promise(t=>setTimeout(t,e)),"sleep"),v=s(async(e,t=d.TimeMagic.MILLISECONDS_PER_SECOND)=>{for(;!await e();)await T(t)},"sleepUntil"),x=s(async(e,t,r=d.TimeMagic.MILLISECONDS_PER_SECOND)=>{const a=Date.now();for(;!await e()&&Date.now()-a<t;)await T(r)},"sleepUntilOrTimeout"),b=s((e,t)=>new Promise((r,a)=>{const o=setTimeout(()=>{a(new Error(`Promise timed out after ${t}ms`))},t);e.then(n=>{clearTimeout(o),r(n)},n=>{clearTimeout(o),a(n)})}),"awaitOrTimeout"),S=s((e,t,r,a)=>{if(e<0)throw new Error("Timeout value is negative");const o=e<=I.INT32_MAX;if(!o&&!t)throw new Error("Timeout value is too large, as it doesn't fit in an int32");if(o)return setTimeout(r,e);const n=s(c=>{let i,f=!1;return c>I.INT32_MAX?i=setTimeout(()=>{n(c-I.INT32_MAX)},I.INT32_MAX):(f=!0,i=setTimeout(()=>{r()},c)),e!==c&&a?.(i,f),i},"scheduleTimeout");return n(e)},"safeSetTimeout"),O=s((e,t,r)=>S(e,!0,()=>{t(),O(e,t,r)},r),"safeSetInterval"),_=s((e,t,r)=>S(e,!0,async()=>{await t(),_(e,t,r)},r),"safeSetAsyncInterval");async function A(e,t=5){if(t<=0)throw new Error("Concurrency must be greater than 0");if(e.length===0)return[];const r=new Array(e.length);let a=0;const o=s(async()=>{for(;a<e.length;){const i=a++;r[i]=await e[i]()}},"worker"),n=Math.min(t,e.length),c=Array.from({length:n},()=>o());return await Promise.all(c),r}s(A,"executeWithConcurrency");async function P(e,t={}){const{concurrency:r=5,stopOnError:a=!1,taskTimeout:o,batchDelay:n=0,onProgress:c,onError:i}=t;if(r<=0)throw new Error("Concurrency must be greater than 0");if(e.length===0)return{results:[],errors:[],total:0,successful:0,failed:0};const f=new Array(e.length),l=[];let u=0,m=0,g=!1;const p=s(async w=>{try{const h=e[w],y=o?await b(h(),o):await h();f[w]=y,u++,c?.(u,e.length)}catch(h){const y=h instanceof Error?h:new Error(String(h));l.push({index:w,error:y}),u++,i?.(y,w),a&&(g=!0),c?.(u,e.length)}},"executeTask"),E=s(async()=>{for(;m<e.length&&!g;){const w=m++;await p(w),n>0&&m<e.length&&await T(n)}},"worker"),R=Math.min(r,e.length),M=Array.from({length:R},()=>E());return await Promise.all(M),{results:f.filter((w,h)=>!l.some(y=>y.index===h)),errors:l,total:e.length,successful:e.length-l.length,failed:l.length}}s(P,"batchProcess");async function C(e,t,r=5){const a=e.map((o,n)=>()=>t(o,n));return A(a,r)}s(C,"batchMap");async function D(e,t,r={}){const{maxRetries:a=3,retryDelay:o=1e3,retryBackoff:n=2,...c}=r,i=s((l,u)=>async()=>{let m=null,g=o;for(let p=0;p<=a;p++)try{return await t(l,u)}catch(E){m=E instanceof Error?E:new Error(String(E)),p<a&&(await T(g),g*=n)}throw m},"createTaskWithRetry"),f=e.map((l,u)=>i(l,u));return P(f,c)}s(D,"batchMapWithRetry");async function W(e,t,r){if(t<=0)throw new Error("Batch size must be greater than 0");const a=[];let o=0;for(let n=0;n<e.length;n+=t){const c=e.slice(n,n+t),i=await r(c,o++);a.push(i)}return a}s(W,"processBatches");var U=Object.freeze({__proto__:null,awaitOrTimeout:b,batchMap:C,batchMapWithRetry:D,batchProcess:P,executeWithConcurrency:A,processBatches:W,safeSetAsyncInterval:_,safeSetInterval:O,safeSetTimeout:S,sleep:T,sleepUntil:v,sleepUntilOrTimeout:x});exports.awaitOrTimeout=b,exports.batchMap=C,exports.batchMapWithRetry=D,exports.batchProcess=P,exports.executeWithConcurrency=A,exports.processBatches=W,exports.runtime=U,exports.safeSetAsyncInterval=_,exports.safeSetInterval=O,exports.safeSetTimeout=S,exports.sleep=T,exports.sleepUntil=v,exports.sleepUntilOrTimeout=x;
|
|
2
|
+
//# sourceMappingURL=runtime-Bfs-yn_-.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-Bfs-yn_-.cjs","sources":["../src/utils/runtime.ts"],"sourcesContent":["import { INT32_MAX } from './numbers';\nimport { TimeMagic } from './time';\n\n/**\n * Sleep for a specified number of milliseconds\n * @param ms - Milliseconds to sleep\n * @returns Promise that resolves after the specified time\n * @example await sleep(1000) // Sleep for 1 second\n */\nconst sleep = (ms: number): Promise<void> =>\n\tnew Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Sleep until a condition becomes true\n * @param condition - Function that returns true when ready to continue\n * @param interval - How often to check the condition in ms (default: 1000)\n * @returns Promise that resolves when condition is true\n * @example await sleepUntil(() => dataLoaded, 500)\n */\nconst sleepUntil = async (\n\tcondition: () => boolean | Promise<boolean>,\n\tinterval: number = TimeMagic.MILLISECONDS_PER_SECOND\n): Promise<void> => {\n\twhile (!(await condition())) await sleep(interval);\n};\n\n/**\n * Sleep until a condition becomes true or timeout is reached\n * @param condition - Function that returns true when ready to continue\n * @param timeout - Maximum time to wait in ms\n * @param interval - How often to check the condition in ms (default: 1000)\n * @returns Promise that resolves when condition is true or timeout is reached\n * @example await sleepUntilOrTimeout(() => dataLoaded, 5000, 500)\n */\nconst sleepUntilOrTimeout = async (\n\tcondition: () => boolean | Promise<boolean>,\n\ttimeout: number,\n\tinterval: number = TimeMagic.MILLISECONDS_PER_SECOND\n): Promise<void> => {\n\tconst start = Date.now();\n\twhile (!(await condition()) && Date.now() - start < timeout)\n\t\tawait sleep(interval);\n};\n\n/**\n * Race a promise against a timeout\n * @param promise - Promise to await\n * @param timeout - Timeout in milliseconds\n * @returns Promise that resolves with the value or rejects on timeout\n * @example await awaitOrTimeout(fetchData(), 5000)\n */\nconst awaitOrTimeout = <T>(\n\tpromise: Promise<T>,\n\ttimeout: number\n): Promise<T> => {\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\treject(new Error(`Promise timed out after ${timeout}ms`));\n\t\t}, timeout);\n\n\t\tpromise.then(\n\t\t\t(value) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(reason) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(reason);\n\t\t\t}\n\t\t);\n\t});\n};\n\n/**\n * Safely set a timeout that handles values larger than INT32_MAX\n * @param timeoutMs - Timeout in milliseconds\n * @param scheduleOverflowInFuture - Whether to schedule overflow timeouts automatically\n * @param fn - Function to execute\n * @param onNewTimeout - Callback when a new timeout is scheduled\n * @returns Timeout handle\n * @example safeSetTimeout(2147483648, true, () => console.log('Done'))\n */\nconst safeSetTimeout = (\n\ttimeoutMs: number,\n\tscheduleOverflowInFuture: boolean,\n\tfn: () => void,\n\tonNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void\n): NodeJS.Timeout => {\n\tif (timeoutMs < 0) {\n\t\tthrow new Error('Timeout value is negative');\n\t}\n\n\tconst isSafe = timeoutMs <= INT32_MAX;\n\n\tif (!isSafe && !scheduleOverflowInFuture) {\n\t\tthrow new Error(\n\t\t\t\"Timeout value is too large, as it doesn't fit in an int32\"\n\t\t);\n\t}\n\n\tif (isSafe) {\n\t\treturn setTimeout(fn, timeoutMs);\n\t}\n\n\tconst scheduleTimeout = (_timeoutMs: number): NodeJS.Timeout => {\n\t\tlet timeout: NodeJS.Timeout;\n\t\tlet isTimeoutForRunFn = false;\n\n\t\tif (_timeoutMs > INT32_MAX) {\n\t\t\ttimeout = setTimeout(() => {\n\t\t\t\tscheduleTimeout(_timeoutMs - INT32_MAX);\n\t\t\t}, INT32_MAX);\n\t\t} else {\n\t\t\tisTimeoutForRunFn = true;\n\t\t\ttimeout = setTimeout(() => {\n\t\t\t\tfn();\n\t\t\t}, _timeoutMs);\n\t\t}\n\n\t\tif (timeoutMs !== _timeoutMs) {\n\t\t\tonNewTimeout?.(timeout, isTimeoutForRunFn);\n\t\t}\n\n\t\treturn timeout;\n\t};\n\n\treturn scheduleTimeout(timeoutMs);\n};\n\n/**\n * Safely set an interval that handles values larger than INT32_MAX\n * @param intervalMs - Interval in milliseconds\n * @param fn - Function to execute\n * @param onNewTimeout - Callback when a new timeout is scheduled\n * @returns Timeout handle\n * @example safeSetInterval(2147483648, () => console.log('Tick'))\n */\nconst safeSetInterval = (\n\tintervalMs: number,\n\tfn: () => void,\n\tonNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void\n): NodeJS.Timeout => {\n\treturn safeSetTimeout(\n\t\tintervalMs,\n\t\ttrue,\n\t\t() => {\n\t\t\tfn();\n\t\t\tsafeSetInterval(intervalMs, fn, onNewTimeout);\n\t\t},\n\t\tonNewTimeout\n\t);\n};\n\n/**\n * Safely set an async interval that handles values larger than INT32_MAX\n * @param intervalMs - Interval in milliseconds\n * @param fn - Async function to execute\n * @param onNewTimeout - Callback when a new timeout is scheduled\n * @returns Timeout handle\n * @example safeSetAsyncInterval(2147483648, async () => await doWork())\n */\nconst safeSetAsyncInterval = (\n\tintervalMs: number,\n\tfn: () => Promise<void>,\n\tonNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void\n): NodeJS.Timeout => {\n\treturn safeSetTimeout(\n\t\tintervalMs,\n\t\ttrue,\n\t\tasync () => {\n\t\t\tawait fn();\n\t\t\tsafeSetAsyncInterval(intervalMs, fn, onNewTimeout);\n\t\t},\n\t\tonNewTimeout\n\t);\n};\n\n/**\n * Result of a batch operation\n */\ntype BatchResult<T> = {\n\t/** Successfully processed results */\n\tresults: T[];\n\t/** Errors that occurred during processing */\n\terrors: Array<{ index: number; error: Error }>;\n\t/** Total number of tasks */\n\ttotal: number;\n\t/** Number of successful tasks */\n\tsuccessful: number;\n\t/** Number of failed tasks */\n\tfailed: number;\n};\n\n/**\n * Options for batch processing\n */\ninterface BatchProcessOptions {\n\t/** Maximum number of concurrent executions (default: 5) */\n\tconcurrency?: number;\n\t/** Whether to stop on first error (default: false) */\n\tstopOnError?: boolean;\n\t/** Timeout per task in milliseconds (default: none) */\n\ttaskTimeout?: number;\n\t/** Delay between batches in milliseconds (default: 0) */\n\tbatchDelay?: number;\n\t/** Callback for progress updates */\n\tonProgress?: (completed: number, total: number) => void;\n\t/** Callback for each error */\n\tonError?: (error: Error, index: number) => void;\n}\n\n/**\n * Options for batch processing with retry\n */\ninterface BatchProcessWithRetryOptions extends BatchProcessOptions {\n\t/** Maximum number of retry attempts (default: 3) */\n\tmaxRetries?: number;\n\t/** Delay between retries in milliseconds (default: 1000) */\n\tretryDelay?: number;\n\t/** Backoff multiplier for retry delay (default: 2) */\n\tretryBackoff?: number;\n}\n\n/**\n * Execute async tasks with controlled concurrency\n * @param tasks - Array of async functions to execute\n * @param concurrency - Maximum number of concurrent executions (default: 5)\n * @returns Array of results in the same order as input tasks\n * @throws Error if any task fails (use batchProcess for error handling)\n * @example\n * const results = await executeWithConcurrency(\n * urls.map(url => () => fetch(url)),\n * 3\n * );\n */\nasync function executeWithConcurrency<T>(\n\ttasks: (() => Promise<T>)[],\n\tconcurrency = 5\n): Promise<T[]> {\n\tif (concurrency <= 0) {\n\t\tthrow new Error('Concurrency must be greater than 0');\n\t}\n\n\tif (tasks.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst results: T[] = new Array(tasks.length);\n\tlet nextTaskIndex = 0;\n\n\tconst worker = async (): Promise<void> => {\n\t\twhile (nextTaskIndex < tasks.length) {\n\t\t\tconst taskIndex = nextTaskIndex++;\n\t\t\tresults[taskIndex] = await tasks[taskIndex]();\n\t\t}\n\t};\n\n\tconst numWorkers = Math.min(concurrency, tasks.length);\n\tconst workers = Array.from({ length: numWorkers }, () => worker());\n\n\tawait Promise.all(workers);\n\treturn results;\n}\n\n/**\n * Process tasks in batches with advanced error handling and progress tracking\n * @param tasks - Array of async functions to execute\n * @param options - Batch processing options\n * @returns BatchResult with results and error information\n * @example\n * const result = await batchProcess(\n * urls.map(url => () => fetchData(url)),\n * {\n * concurrency: 3,\n * stopOnError: false,\n * onProgress: (done, total) => console.log(`${done}/${total}`)\n * }\n * );\n */\nasync function batchProcess<T>(\n\ttasks: (() => Promise<T>)[],\n\toptions: BatchProcessOptions = {}\n): Promise<BatchResult<T>> {\n\tconst {\n\t\tconcurrency = 5,\n\t\tstopOnError = false,\n\t\ttaskTimeout,\n\t\tbatchDelay = 0,\n\t\tonProgress,\n\t\tonError,\n\t} = options;\n\n\tif (concurrency <= 0) {\n\t\tthrow new Error('Concurrency must be greater than 0');\n\t}\n\n\tif (tasks.length === 0) {\n\t\treturn {\n\t\t\tresults: [],\n\t\t\terrors: [],\n\t\t\ttotal: 0,\n\t\t\tsuccessful: 0,\n\t\t\tfailed: 0,\n\t\t};\n\t}\n\n\tconst results: T[] = new Array(tasks.length);\n\tconst errors: Array<{ index: number; error: Error }> = [];\n\tlet completed = 0;\n\tlet nextTaskIndex = 0;\n\tlet shouldStop = false;\n\n\tconst executeTask = async (index: number): Promise<void> => {\n\t\ttry {\n\t\t\tconst task = tasks[index];\n\t\t\tconst result = taskTimeout\n\t\t\t\t? await awaitOrTimeout(task(), taskTimeout)\n\t\t\t\t: await task();\n\t\t\tresults[index] = result;\n\t\t\tcompleted++;\n\t\t\tonProgress?.(completed, tasks.length);\n\t\t} catch (error) {\n\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\terrors.push({ index, error: err });\n\t\t\tcompleted++;\n\t\t\tonError?.(err, index);\n\n\t\t\tif (stopOnError) {\n\t\t\t\tshouldStop = true;\n\t\t\t}\n\n\t\t\tonProgress?.(completed, tasks.length);\n\t\t}\n\t};\n\n\tconst worker = async (): Promise<void> => {\n\t\twhile (nextTaskIndex < tasks.length && !shouldStop) {\n\t\t\tconst taskIndex = nextTaskIndex++;\n\t\t\tawait executeTask(taskIndex);\n\n\t\t\t// Add delay between batches if configured\n\t\t\tif (batchDelay > 0 && nextTaskIndex < tasks.length) {\n\t\t\t\tawait sleep(batchDelay);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst numWorkers = Math.min(concurrency, tasks.length);\n\tconst workers = Array.from({ length: numWorkers }, () => worker());\n\n\tawait Promise.all(workers);\n\n\treturn {\n\t\tresults: results.filter((_, idx) => !errors.some((e) => e.index === idx)),\n\t\terrors,\n\t\ttotal: tasks.length,\n\t\tsuccessful: tasks.length - errors.length,\n\t\tfailed: errors.length,\n\t};\n}\n\n/**\n * Map over an array with controlled concurrency\n * @param items - Array of items to process\n * @param mapper - Async function to transform each item\n * @param concurrency - Maximum number of concurrent executions (default: 5)\n * @returns Array of transformed results in the same order\n * @throws Error if any transformation fails\n * @example\n * const users = await batchMap(\n * userIds,\n * async (id) => await fetchUser(id),\n * 3\n * );\n */\nasync function batchMap<T, R>(\n\titems: T[],\n\tmapper: (item: T, index: number) => Promise<R>,\n\tconcurrency = 5\n): Promise<R[]> {\n\tconst tasks = items.map((item, index) => () => mapper(item, index));\n\treturn executeWithConcurrency(tasks, concurrency);\n}\n\n/**\n * Map over an array with controlled concurrency and retry logic\n * @param items - Array of items to process\n * @param mapper - Async function to transform each item\n * @param options - Batch processing options with retry configuration\n * @returns BatchResult with results and error information\n * @example\n * const result = await batchMapWithRetry(\n * userIds,\n * async (id) => await fetchUser(id),\n * {\n * concurrency: 3,\n * maxRetries: 3,\n * retryDelay: 1000,\n * stopOnError: false\n * }\n * );\n */\nasync function batchMapWithRetry<T, R>(\n\titems: T[],\n\tmapper: (item: T, index: number) => Promise<R>,\n\toptions: BatchProcessWithRetryOptions = {}\n): Promise<BatchResult<R>> {\n\tconst {\n\t\tmaxRetries = 3,\n\t\tretryDelay = 1000,\n\t\tretryBackoff = 2,\n\t\t...batchOptions\n\t} = options;\n\n\tconst createTaskWithRetry = (item: T, index: number): (() => Promise<R>) => {\n\t\treturn async () => {\n\t\t\tlet lastError: Error | null = null;\n\t\t\tlet currentDelay = retryDelay;\n\n\t\t\tfor (let attempt = 0; attempt <= maxRetries; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await mapper(item, index);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error));\n\n\t\t\t\t\t// Don't delay after the last attempt\n\t\t\t\t\tif (attempt < maxRetries) {\n\t\t\t\t\t\tawait sleep(currentDelay);\n\t\t\t\t\t\tcurrentDelay *= retryBackoff;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow lastError;\n\t\t};\n\t};\n\n\tconst tasks = items.map((item, index) => createTaskWithRetry(item, index));\n\treturn batchProcess(tasks, batchOptions);\n}\n\n/**\n * Process items in chunks/batches sequentially\n * @param items - Array of items to process\n * @param batchSize - Number of items per batch\n * @param processor - Function to process each batch\n * @returns Array of batch results\n * @example\n * const results = await processBatches(\n * allUsers,\n * 100,\n * async (batch) => await bulkInsert(batch)\n * );\n */\nasync function processBatches<T, R>(\n\titems: T[],\n\tbatchSize: number,\n\tprocessor: (batch: T[], batchIndex: number) => Promise<R>\n): Promise<R[]> {\n\tif (batchSize <= 0) {\n\t\tthrow new Error('Batch size must be greater than 0');\n\t}\n\n\tconst results: R[] = [];\n\tlet batchIndex = 0;\n\n\tfor (let i = 0; i < items.length; i += batchSize) {\n\t\tconst batch = items.slice(i, i + batchSize);\n\t\tconst result = await processor(batch, batchIndex++);\n\t\tresults.push(result);\n\t}\n\n\treturn results;\n}\n\nexport {\n\tsleep,\n\tsleepUntil,\n\tsleepUntilOrTimeout,\n\tawaitOrTimeout,\n\tsafeSetTimeout,\n\tsafeSetInterval,\n\tsafeSetAsyncInterval,\n\texecuteWithConcurrency,\n\tbatchProcess,\n\tbatchMap,\n\tbatchMapWithRetry,\n\tprocessBatches,\n\ttype BatchResult,\n\ttype BatchProcessOptions,\n\ttype BatchProcessWithRetryOptions,\n};\n"],"names":["sleep","__name","ms","resolve","sleepUntil","condition","interval","TimeMagic","sleepUntilOrTimeout","timeout","start","awaitOrTimeout","promise","reject","timer","value","reason","safeSetTimeout","timeoutMs","scheduleOverflowInFuture","fn","onNewTimeout","isSafe","INT32_MAX","scheduleTimeout","_timeoutMs","isTimeoutForRunFn","safeSetInterval","intervalMs","safeSetAsyncInterval","executeWithConcurrency","tasks","concurrency","results","nextTaskIndex","worker","taskIndex","numWorkers","workers","batchProcess","options","stopOnError","taskTimeout","batchDelay","onProgress","onError","errors","completed","shouldStop","executeTask","index","task","result","error","err","_","idx","e","batchMap","items","mapper","item","batchMapWithRetry","maxRetries","retryDelay","retryBackoff","batchOptions","createTaskWithRetry","lastError","currentDelay","attempt","processBatches","batchSize","processor","batchIndex","i","batch"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var B=Object.defineProperty;var s=(e,t)=>B(e,"name",{value:t,configurable:!0});import{I}from"./numbers-lJ6gwIpk.mjs";import{TimeMagic as D}from"./constants/time.mjs";const g=s(e=>new Promise(t=>setTimeout(t,e)),"sleep"),C=s(async(e,t=D.MILLISECONDS_PER_SECOND)=>{for(;!await e();)await g(t)},"sleepUntil"),A=s(async(e,t,r=D.MILLISECONDS_PER_SECOND)=>{const a=Date.now();for(;!await e()&&Date.now()-a<t;)await g(r)},"sleepUntilOrTimeout"),b=s((e,t)=>new Promise((r,a)=>{const o=setTimeout(()=>{a(new Error(`Promise timed out after ${t}ms`))},t);e.then(n=>{clearTimeout(o),r(n)},n=>{clearTimeout(o),a(n)})}),"awaitOrTimeout"),S=s((e,t,r,a)=>{if(e<0)throw new Error("Timeout value is negative");const o=e<=I;if(!o&&!t)throw new Error("Timeout value is too large, as it doesn't fit in an int32");if(o)return setTimeout(r,e);const n=s(c=>{let i,f=!1;return c>I?i=setTimeout(()=>{n(c-I)},I):(f=!0,i=setTimeout(()=>{r()},c)),e!==c&&a?.(i,f),i},"scheduleTimeout");return n(e)},"safeSetTimeout"),d=s((e,t,r)=>S(e,!0,()=>{t(),d(e,t,r)},r),"safeSetInterval"),O=s((e,t,r)=>S(e,!0,async()=>{await t(),O(e,t,r)},r),"safeSetAsyncInterval");async function x(e,t=5){if(t<=0)throw new Error("Concurrency must be greater than 0");if(e.length===0)return[];const r=new Array(e.length);let a=0;const o=s(async()=>{for(;a<e.length;){const i=a++;r[i]=await e[i]()}},"worker"),n=Math.min(t,e.length),c=Array.from({length:n},()=>o());return await Promise.all(c),r}s(x,"executeWithConcurrency");async function P(e,t={}){const{concurrency:r=5,stopOnError:a=!1,taskTimeout:o,batchDelay:n=0,onProgress:c,onError:i}=t;if(r<=0)throw new Error("Concurrency must be greater than 0");if(e.length===0)return{results:[],errors:[],total:0,successful:0,failed:0};const f=new Array(e.length),l=[];let u=0,m=0,p=!1;const T=s(async w=>{try{const h=e[w],y=o?await b(h(),o):await h();f[w]=y,u++,c?.(u,e.length)}catch(h){const y=h instanceof Error?h:new Error(String(h));l.push({index:w,error:y}),u++,i?.(y,w),a&&(p=!0),c?.(u,e.length)}},"executeTask"),E=s(async()=>{for(;m<e.length&&!p;){const w=m++;await T(w),n>0&&m<e.length&&await g(n)}},"worker"),v=Math.min(r,e.length),k=Array.from({length:v},()=>E());return await Promise.all(k),{results:f.filter((w,h)=>!l.some(y=>y.index===h)),errors:l,total:e.length,successful:e.length-l.length,failed:l.length}}s(P,"batchProcess");async function R(e,t,r=5){const a=e.map((o,n)=>()=>t(o,n));return x(a,r)}s(R,"batchMap");async function W(e,t,r={}){const{maxRetries:a=3,retryDelay:o=1e3,retryBackoff:n=2,...c}=r,i=s((l,u)=>async()=>{let m=null,p=o;for(let T=0;T<=a;T++)try{return await t(l,u)}catch(E){m=E instanceof Error?E:new Error(String(E)),T<a&&(await g(p),p*=n)}throw m},"createTaskWithRetry"),f=e.map((l,u)=>i(l,u));return P(f,c)}s(W,"batchMapWithRetry");async function _(e,t,r){if(t<=0)throw new Error("Batch size must be greater than 0");const a=[];let o=0;for(let n=0;n<e.length;n+=t){const c=e.slice(n,n+t),i=await r(c,o++);a.push(i)}return a}s(_,"processBatches");var L=Object.freeze({__proto__:null,awaitOrTimeout:b,batchMap:R,batchMapWithRetry:W,batchProcess:P,executeWithConcurrency:x,processBatches:_,safeSetAsyncInterval:O,safeSetInterval:d,safeSetTimeout:S,sleep:g,sleepUntil:C,sleepUntilOrTimeout:A});export{C as a,A as b,b as c,S as d,d as e,O as f,x as g,P as h,R as i,W as j,_ as p,L as r,g as s};
|
|
2
|
+
//# sourceMappingURL=runtime-CE36Va0l.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-CE36Va0l.mjs","sources":["../src/utils/runtime.ts"],"sourcesContent":["import { INT32_MAX } from './numbers';\nimport { TimeMagic } from './time';\n\n/**\n * Sleep for a specified number of milliseconds\n * @param ms - Milliseconds to sleep\n * @returns Promise that resolves after the specified time\n * @example await sleep(1000) // Sleep for 1 second\n */\nconst sleep = (ms: number): Promise<void> =>\n\tnew Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Sleep until a condition becomes true\n * @param condition - Function that returns true when ready to continue\n * @param interval - How often to check the condition in ms (default: 1000)\n * @returns Promise that resolves when condition is true\n * @example await sleepUntil(() => dataLoaded, 500)\n */\nconst sleepUntil = async (\n\tcondition: () => boolean | Promise<boolean>,\n\tinterval: number = TimeMagic.MILLISECONDS_PER_SECOND\n): Promise<void> => {\n\twhile (!(await condition())) await sleep(interval);\n};\n\n/**\n * Sleep until a condition becomes true or timeout is reached\n * @param condition - Function that returns true when ready to continue\n * @param timeout - Maximum time to wait in ms\n * @param interval - How often to check the condition in ms (default: 1000)\n * @returns Promise that resolves when condition is true or timeout is reached\n * @example await sleepUntilOrTimeout(() => dataLoaded, 5000, 500)\n */\nconst sleepUntilOrTimeout = async (\n\tcondition: () => boolean | Promise<boolean>,\n\ttimeout: number,\n\tinterval: number = TimeMagic.MILLISECONDS_PER_SECOND\n): Promise<void> => {\n\tconst start = Date.now();\n\twhile (!(await condition()) && Date.now() - start < timeout)\n\t\tawait sleep(interval);\n};\n\n/**\n * Race a promise against a timeout\n * @param promise - Promise to await\n * @param timeout - Timeout in milliseconds\n * @returns Promise that resolves with the value or rejects on timeout\n * @example await awaitOrTimeout(fetchData(), 5000)\n */\nconst awaitOrTimeout = <T>(\n\tpromise: Promise<T>,\n\ttimeout: number\n): Promise<T> => {\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\treject(new Error(`Promise timed out after ${timeout}ms`));\n\t\t}, timeout);\n\n\t\tpromise.then(\n\t\t\t(value) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(reason) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(reason);\n\t\t\t}\n\t\t);\n\t});\n};\n\n/**\n * Safely set a timeout that handles values larger than INT32_MAX\n * @param timeoutMs - Timeout in milliseconds\n * @param scheduleOverflowInFuture - Whether to schedule overflow timeouts automatically\n * @param fn - Function to execute\n * @param onNewTimeout - Callback when a new timeout is scheduled\n * @returns Timeout handle\n * @example safeSetTimeout(2147483648, true, () => console.log('Done'))\n */\nconst safeSetTimeout = (\n\ttimeoutMs: number,\n\tscheduleOverflowInFuture: boolean,\n\tfn: () => void,\n\tonNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void\n): NodeJS.Timeout => {\n\tif (timeoutMs < 0) {\n\t\tthrow new Error('Timeout value is negative');\n\t}\n\n\tconst isSafe = timeoutMs <= INT32_MAX;\n\n\tif (!isSafe && !scheduleOverflowInFuture) {\n\t\tthrow new Error(\n\t\t\t\"Timeout value is too large, as it doesn't fit in an int32\"\n\t\t);\n\t}\n\n\tif (isSafe) {\n\t\treturn setTimeout(fn, timeoutMs);\n\t}\n\n\tconst scheduleTimeout = (_timeoutMs: number): NodeJS.Timeout => {\n\t\tlet timeout: NodeJS.Timeout;\n\t\tlet isTimeoutForRunFn = false;\n\n\t\tif (_timeoutMs > INT32_MAX) {\n\t\t\ttimeout = setTimeout(() => {\n\t\t\t\tscheduleTimeout(_timeoutMs - INT32_MAX);\n\t\t\t}, INT32_MAX);\n\t\t} else {\n\t\t\tisTimeoutForRunFn = true;\n\t\t\ttimeout = setTimeout(() => {\n\t\t\t\tfn();\n\t\t\t}, _timeoutMs);\n\t\t}\n\n\t\tif (timeoutMs !== _timeoutMs) {\n\t\t\tonNewTimeout?.(timeout, isTimeoutForRunFn);\n\t\t}\n\n\t\treturn timeout;\n\t};\n\n\treturn scheduleTimeout(timeoutMs);\n};\n\n/**\n * Safely set an interval that handles values larger than INT32_MAX\n * @param intervalMs - Interval in milliseconds\n * @param fn - Function to execute\n * @param onNewTimeout - Callback when a new timeout is scheduled\n * @returns Timeout handle\n * @example safeSetInterval(2147483648, () => console.log('Tick'))\n */\nconst safeSetInterval = (\n\tintervalMs: number,\n\tfn: () => void,\n\tonNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void\n): NodeJS.Timeout => {\n\treturn safeSetTimeout(\n\t\tintervalMs,\n\t\ttrue,\n\t\t() => {\n\t\t\tfn();\n\t\t\tsafeSetInterval(intervalMs, fn, onNewTimeout);\n\t\t},\n\t\tonNewTimeout\n\t);\n};\n\n/**\n * Safely set an async interval that handles values larger than INT32_MAX\n * @param intervalMs - Interval in milliseconds\n * @param fn - Async function to execute\n * @param onNewTimeout - Callback when a new timeout is scheduled\n * @returns Timeout handle\n * @example safeSetAsyncInterval(2147483648, async () => await doWork())\n */\nconst safeSetAsyncInterval = (\n\tintervalMs: number,\n\tfn: () => Promise<void>,\n\tonNewTimeout?: (timeout: NodeJS.Timeout, isTimeoutForRunFn: boolean) => void\n): NodeJS.Timeout => {\n\treturn safeSetTimeout(\n\t\tintervalMs,\n\t\ttrue,\n\t\tasync () => {\n\t\t\tawait fn();\n\t\t\tsafeSetAsyncInterval(intervalMs, fn, onNewTimeout);\n\t\t},\n\t\tonNewTimeout\n\t);\n};\n\n/**\n * Result of a batch operation\n */\ntype BatchResult<T> = {\n\t/** Successfully processed results */\n\tresults: T[];\n\t/** Errors that occurred during processing */\n\terrors: Array<{ index: number; error: Error }>;\n\t/** Total number of tasks */\n\ttotal: number;\n\t/** Number of successful tasks */\n\tsuccessful: number;\n\t/** Number of failed tasks */\n\tfailed: number;\n};\n\n/**\n * Options for batch processing\n */\ninterface BatchProcessOptions {\n\t/** Maximum number of concurrent executions (default: 5) */\n\tconcurrency?: number;\n\t/** Whether to stop on first error (default: false) */\n\tstopOnError?: boolean;\n\t/** Timeout per task in milliseconds (default: none) */\n\ttaskTimeout?: number;\n\t/** Delay between batches in milliseconds (default: 0) */\n\tbatchDelay?: number;\n\t/** Callback for progress updates */\n\tonProgress?: (completed: number, total: number) => void;\n\t/** Callback for each error */\n\tonError?: (error: Error, index: number) => void;\n}\n\n/**\n * Options for batch processing with retry\n */\ninterface BatchProcessWithRetryOptions extends BatchProcessOptions {\n\t/** Maximum number of retry attempts (default: 3) */\n\tmaxRetries?: number;\n\t/** Delay between retries in milliseconds (default: 1000) */\n\tretryDelay?: number;\n\t/** Backoff multiplier for retry delay (default: 2) */\n\tretryBackoff?: number;\n}\n\n/**\n * Execute async tasks with controlled concurrency\n * @param tasks - Array of async functions to execute\n * @param concurrency - Maximum number of concurrent executions (default: 5)\n * @returns Array of results in the same order as input tasks\n * @throws Error if any task fails (use batchProcess for error handling)\n * @example\n * const results = await executeWithConcurrency(\n * urls.map(url => () => fetch(url)),\n * 3\n * );\n */\nasync function executeWithConcurrency<T>(\n\ttasks: (() => Promise<T>)[],\n\tconcurrency = 5\n): Promise<T[]> {\n\tif (concurrency <= 0) {\n\t\tthrow new Error('Concurrency must be greater than 0');\n\t}\n\n\tif (tasks.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst results: T[] = new Array(tasks.length);\n\tlet nextTaskIndex = 0;\n\n\tconst worker = async (): Promise<void> => {\n\t\twhile (nextTaskIndex < tasks.length) {\n\t\t\tconst taskIndex = nextTaskIndex++;\n\t\t\tresults[taskIndex] = await tasks[taskIndex]();\n\t\t}\n\t};\n\n\tconst numWorkers = Math.min(concurrency, tasks.length);\n\tconst workers = Array.from({ length: numWorkers }, () => worker());\n\n\tawait Promise.all(workers);\n\treturn results;\n}\n\n/**\n * Process tasks in batches with advanced error handling and progress tracking\n * @param tasks - Array of async functions to execute\n * @param options - Batch processing options\n * @returns BatchResult with results and error information\n * @example\n * const result = await batchProcess(\n * urls.map(url => () => fetchData(url)),\n * {\n * concurrency: 3,\n * stopOnError: false,\n * onProgress: (done, total) => console.log(`${done}/${total}`)\n * }\n * );\n */\nasync function batchProcess<T>(\n\ttasks: (() => Promise<T>)[],\n\toptions: BatchProcessOptions = {}\n): Promise<BatchResult<T>> {\n\tconst {\n\t\tconcurrency = 5,\n\t\tstopOnError = false,\n\t\ttaskTimeout,\n\t\tbatchDelay = 0,\n\t\tonProgress,\n\t\tonError,\n\t} = options;\n\n\tif (concurrency <= 0) {\n\t\tthrow new Error('Concurrency must be greater than 0');\n\t}\n\n\tif (tasks.length === 0) {\n\t\treturn {\n\t\t\tresults: [],\n\t\t\terrors: [],\n\t\t\ttotal: 0,\n\t\t\tsuccessful: 0,\n\t\t\tfailed: 0,\n\t\t};\n\t}\n\n\tconst results: T[] = new Array(tasks.length);\n\tconst errors: Array<{ index: number; error: Error }> = [];\n\tlet completed = 0;\n\tlet nextTaskIndex = 0;\n\tlet shouldStop = false;\n\n\tconst executeTask = async (index: number): Promise<void> => {\n\t\ttry {\n\t\t\tconst task = tasks[index];\n\t\t\tconst result = taskTimeout\n\t\t\t\t? await awaitOrTimeout(task(), taskTimeout)\n\t\t\t\t: await task();\n\t\t\tresults[index] = result;\n\t\t\tcompleted++;\n\t\t\tonProgress?.(completed, tasks.length);\n\t\t} catch (error) {\n\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\terrors.push({ index, error: err });\n\t\t\tcompleted++;\n\t\t\tonError?.(err, index);\n\n\t\t\tif (stopOnError) {\n\t\t\t\tshouldStop = true;\n\t\t\t}\n\n\t\t\tonProgress?.(completed, tasks.length);\n\t\t}\n\t};\n\n\tconst worker = async (): Promise<void> => {\n\t\twhile (nextTaskIndex < tasks.length && !shouldStop) {\n\t\t\tconst taskIndex = nextTaskIndex++;\n\t\t\tawait executeTask(taskIndex);\n\n\t\t\t// Add delay between batches if configured\n\t\t\tif (batchDelay > 0 && nextTaskIndex < tasks.length) {\n\t\t\t\tawait sleep(batchDelay);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst numWorkers = Math.min(concurrency, tasks.length);\n\tconst workers = Array.from({ length: numWorkers }, () => worker());\n\n\tawait Promise.all(workers);\n\n\treturn {\n\t\tresults: results.filter((_, idx) => !errors.some((e) => e.index === idx)),\n\t\terrors,\n\t\ttotal: tasks.length,\n\t\tsuccessful: tasks.length - errors.length,\n\t\tfailed: errors.length,\n\t};\n}\n\n/**\n * Map over an array with controlled concurrency\n * @param items - Array of items to process\n * @param mapper - Async function to transform each item\n * @param concurrency - Maximum number of concurrent executions (default: 5)\n * @returns Array of transformed results in the same order\n * @throws Error if any transformation fails\n * @example\n * const users = await batchMap(\n * userIds,\n * async (id) => await fetchUser(id),\n * 3\n * );\n */\nasync function batchMap<T, R>(\n\titems: T[],\n\tmapper: (item: T, index: number) => Promise<R>,\n\tconcurrency = 5\n): Promise<R[]> {\n\tconst tasks = items.map((item, index) => () => mapper(item, index));\n\treturn executeWithConcurrency(tasks, concurrency);\n}\n\n/**\n * Map over an array with controlled concurrency and retry logic\n * @param items - Array of items to process\n * @param mapper - Async function to transform each item\n * @param options - Batch processing options with retry configuration\n * @returns BatchResult with results and error information\n * @example\n * const result = await batchMapWithRetry(\n * userIds,\n * async (id) => await fetchUser(id),\n * {\n * concurrency: 3,\n * maxRetries: 3,\n * retryDelay: 1000,\n * stopOnError: false\n * }\n * );\n */\nasync function batchMapWithRetry<T, R>(\n\titems: T[],\n\tmapper: (item: T, index: number) => Promise<R>,\n\toptions: BatchProcessWithRetryOptions = {}\n): Promise<BatchResult<R>> {\n\tconst {\n\t\tmaxRetries = 3,\n\t\tretryDelay = 1000,\n\t\tretryBackoff = 2,\n\t\t...batchOptions\n\t} = options;\n\n\tconst createTaskWithRetry = (item: T, index: number): (() => Promise<R>) => {\n\t\treturn async () => {\n\t\t\tlet lastError: Error | null = null;\n\t\t\tlet currentDelay = retryDelay;\n\n\t\t\tfor (let attempt = 0; attempt <= maxRetries; attempt++) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await mapper(item, index);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error));\n\n\t\t\t\t\t// Don't delay after the last attempt\n\t\t\t\t\tif (attempt < maxRetries) {\n\t\t\t\t\t\tawait sleep(currentDelay);\n\t\t\t\t\t\tcurrentDelay *= retryBackoff;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow lastError;\n\t\t};\n\t};\n\n\tconst tasks = items.map((item, index) => createTaskWithRetry(item, index));\n\treturn batchProcess(tasks, batchOptions);\n}\n\n/**\n * Process items in chunks/batches sequentially\n * @param items - Array of items to process\n * @param batchSize - Number of items per batch\n * @param processor - Function to process each batch\n * @returns Array of batch results\n * @example\n * const results = await processBatches(\n * allUsers,\n * 100,\n * async (batch) => await bulkInsert(batch)\n * );\n */\nasync function processBatches<T, R>(\n\titems: T[],\n\tbatchSize: number,\n\tprocessor: (batch: T[], batchIndex: number) => Promise<R>\n): Promise<R[]> {\n\tif (batchSize <= 0) {\n\t\tthrow new Error('Batch size must be greater than 0');\n\t}\n\n\tconst results: R[] = [];\n\tlet batchIndex = 0;\n\n\tfor (let i = 0; i < items.length; i += batchSize) {\n\t\tconst batch = items.slice(i, i + batchSize);\n\t\tconst result = await processor(batch, batchIndex++);\n\t\tresults.push(result);\n\t}\n\n\treturn results;\n}\n\nexport {\n\tsleep,\n\tsleepUntil,\n\tsleepUntilOrTimeout,\n\tawaitOrTimeout,\n\tsafeSetTimeout,\n\tsafeSetInterval,\n\tsafeSetAsyncInterval,\n\texecuteWithConcurrency,\n\tbatchProcess,\n\tbatchMap,\n\tbatchMapWithRetry,\n\tprocessBatches,\n\ttype BatchResult,\n\ttype BatchProcessOptions,\n\ttype BatchProcessWithRetryOptions,\n};\n"],"names":["sleep","__name","ms","resolve","sleepUntil","condition","interval","TimeMagic","sleepUntilOrTimeout","timeout","start","awaitOrTimeout","promise","reject","timer","value","reason","safeSetTimeout","timeoutMs","scheduleOverflowInFuture","fn","onNewTimeout","isSafe","INT32_MAX","scheduleTimeout","_timeoutMs","isTimeoutForRunFn","safeSetInterval","intervalMs","safeSetAsyncInterval","executeWithConcurrency","tasks","concurrency","results","nextTaskIndex","worker","taskIndex","numWorkers","workers","batchProcess","options","stopOnError","taskTimeout","batchDelay","onProgress","onError","errors","completed","shouldStop","executeTask","index","task","result","error","err","_","idx","e","batchMap","items","mapper","item","batchMapWithRetry","maxRetries","retryDelay","retryBackoff","batchOptions","createTaskWithRetry","lastError","currentDelay","attempt","processBatches","batchSize","processor","batchIndex","i","batch"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var W=Object.defineProperty;var s=(e,t)=>W(e,"name",{value:t,configurable:!0});const C=s((e,t,a="...")=>e.length>t?e.slice(0,t-a.length)+a:e,"truncate"),g=s(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),"capitalize"),$=s(e=>e.split(" ").map(t=>g(t)).join(" "),"capitalizeWords"),z=s(e=>e.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,""),"slugify"),j=s(e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),"escapeHtml"),b=s(e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'"),"unescapeHtml"),O=s(e=>e.split("").reverse().join(""),"reverse"),x=s((e,t,a=!0)=>{if(!t)return 0;const r=a?e:e.toLowerCase(),c=a?t:t.toLowerCase();return(r.match(new RegExp(c,"g"))||[]).length},"countOccurrences"),I=s(e=>/^[a-zA-Z]+$/.test(e),"isAlpha"),U=s(e=>/^[a-zA-Z0-9]+$/.test(e),"isAlphanumeric"),Z=s((e,t,a=" ",r="right")=>{if(e.length>=t)return e;const c=t-e.length;if(r==="left")return a.repeat(c)+e;if(r==="right")return e+a.repeat(c);{const n=Math.floor(c/2),l=c-n;return a.repeat(n)+e+a.repeat(l)}},"pad"),A=s((e,t)=>{const{prefix:a="",suffix:r="",maxItemLength:c,maxTotalLength:n,joinString:l=", ",maxItems:u,stringify:p}=t,m=a.length+r.length,h=s(i=>a+i.join(l)+r,"withOptions"),w=s(i=>{const y=s(d=>{const o=p(d);return typeof c>"u"||o.length<=c?o:C(o,c)},"processItem");if(typeof n>"u")return{result:i.map(y),truncatedItems:0};let L=0;const f=[];for(const d of i){const o=y(d);if(L+=o.length,L>n-m)break;f.push(o)}return{result:f,truncatedItems:i.length-f.length}},"processArray")(e.slice(0,u));return{result:h(w.result),truncatedItems:w.truncatedItems}},"stringifyArray"),_=s((e,t)=>{if(e.length===0)return t.emptyOutput;const{result:a,truncatedItems:r}=A(e,t);return`${a}${r>0?`
|
|
2
|
+
...and ${r} more...`:""}`},"displayArray"),k=s((e,t)=>t===1?e:`${e}s`,"pluralize"),v=s(e=>e.replace(/\s+/g,"_").replace(/([A-Z])/g,t=>`_${t.toLowerCase()}`).replace(/^_/,"").toLowerCase(),"snakeCase"),H=s(e=>e.split(" ").map(t=>g(t)).join(" "),"titleCase"),R=s(e=>e.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)?.join("-").toLowerCase()??e,"kebabCase"),q=s(e=>e.toLowerCase().split(/\s+|-/).reduce((t,a,r)=>t+(r===0?a:a.charAt(0).toUpperCase()+a.slice(1))),"camelCase"),S=s(e=>e.replace(/(\w)(\w*)/g,(t,a,r)=>`${a.toUpperCase()}${r.toLowerCase()}`),"pascalCase"),T=s((e,t=" ")=>e.split(/(?=[A-Z])/).join(t),"splitOnUppercase"),E=s((e,t,a=["{","}"])=>{const[r,c]=a,n=s(p=>p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"escapeRegex"),l=n(r),u=n(c);return Object.entries(t).reduce((p,[m,h])=>p.replace(new RegExp(`${l}${m}${u}`,"g"),h),e)},"replaceTags"),P=s(e=>{try{return new URL(e),!0}catch{return!1}},"isUrl");var M=Object.freeze({__proto__:null,camelCase:q,capitalize:g,capitalizeWords:$,countOccurrences:x,displayArray:_,escapeHtml:j,isAlpha:I,isAlphanumeric:U,isUrl:P,kebabCase:R,pad:Z,pascalCase:S,pluralize:k,replaceTags:E,reverse:O,slugify:z,snakeCase:v,splitOnUppercase:T,stringifyArray:A,titleCase:H,truncate:C,unescapeHtml:b});export{$ as a,z as b,g as c,x as d,j as e,U as f,A as g,_ as h,I as i,k as j,v as k,H as l,R as m,q as n,S as o,Z as p,T as q,O as r,M as s,C as t,b as u,E as v,P as w};
|
|
3
|
+
//# sourceMappingURL=strings-CrzGdnZH.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings-CrzGdnZH.mjs","sources":["../src/utils/strings.ts"],"sourcesContent":["type StringifyArrayOptions<T> = {\n\tmaxItems: number;\n\tmaxItemLength?: number;\n\tmaxTotalLength?: number;\n\tstringify: (item: T) => string;\n\tprefix?: string;\n\tsuffix?: string;\n\tjoinString?: string;\n};\n\n/**\n * Truncate a string to a maximum length, adding a suffix if truncated\n * @param input - String to truncate\n * @param length - Maximum length\n * @param suffix - Suffix to add (default: \"...\")\n * @returns Truncated string\n * @example truncate(\"Hello World\", 8) // \"Hello...\"\n */\nconst truncate = (input: string, length: number, suffix = '...'): string =>\n\tinput.length > length\n\t\t? input.slice(0, length - suffix.length) + suffix\n\t\t: input;\n\n/**\n * Capitalize the first letter of a string\n * @param input - String to capitalize\n * @returns Capitalized string\n * @example capitalize(\"hello world\") // \"Hello world\"\n */\nconst capitalize = (input: string): string =>\n\tinput.charAt(0).toUpperCase() + input.slice(1).toLowerCase();\n\n/**\n * Capitalize the first letter of each word\n * @param input - String to capitalize\n * @returns String with each word capitalized\n * @example capitalizeWords(\"hello world\") // \"Hello World\"\n */\nconst capitalizeWords = (input: string): string =>\n\tinput\n\t\t.split(' ')\n\t\t.map((word) => capitalize(word))\n\t\t.join(' ');\n\n/**\n * Create a URL-friendly slug from a string\n * @param input - String to slugify\n * @returns Slugified string\n * @example slugify(\"Hello World!\") // \"hello-world\"\n */\nconst slugify = (input: string): string =>\n\tinput\n\t\t.toLowerCase()\n\t\t.trim()\n\t\t.replace(/[^\\w\\s-]/g, '')\n\t\t.replace(/[\\s_-]+/g, '-')\n\t\t.replace(/^-+|-+$/g, '');\n\n/**\n * Escape HTML special characters\n * @param input - String to escape\n * @returns Escaped string\n * @example escapeHtml(\"<div>Hello</div>\") // \"<div>Hello</div>\"\n */\nconst escapeHtml = (input: string): string =>\n\tinput\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/'/g, ''');\n\n/**\n * Unescape HTML entities\n * @param input - String to unescape\n * @returns Unescaped string\n * @example unescapeHtml(\"<div>\") // \"<div>\"\n */\nconst unescapeHtml = (input: string): string =>\n\tinput\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/"/g, '\"')\n\t\t.replace(/'/g, \"'\");\n\n/**\n * Reverse a string\n * @param input - String to reverse\n * @returns Reversed string\n * @example reverse(\"hello\") // \"olleh\"\n */\nconst reverse = (input: string): string => input.split('').reverse().join('');\n\n/**\n * Count occurrences of a substring\n * @param input - String to search in\n * @param search - Substring to count\n * @param caseSensitive - Whether to be case sensitive (default: true)\n * @returns Number of occurrences\n * @example countOccurrences(\"hello hello world\", \"hello\") // 2\n */\nconst countOccurrences = (\n\tinput: string,\n\tsearch: string,\n\tcaseSensitive = true\n): number => {\n\tif (!search) return 0;\n\tconst str = caseSensitive ? input : input.toLowerCase();\n\tconst searchStr = caseSensitive ? search : search.toLowerCase();\n\treturn (str.match(new RegExp(searchStr, 'g')) || []).length;\n};\n\n/**\n * Check if a string contains only letters\n * @param input - String to check\n * @returns True if only letters\n * @example isAlpha(\"hello\") // true, isAlpha(\"hello123\") // false\n */\nconst isAlpha = (input: string): boolean => /^[a-zA-Z]+$/.test(input);\n\n/**\n * Check if a string contains only alphanumeric characters\n * @param input - String to check\n * @returns True if alphanumeric\n * @example isAlphanumeric(\"hello123\") // true, isAlphanumeric(\"hello-123\") // false\n */\nconst isAlphanumeric = (input: string): boolean => /^[a-zA-Z0-9]+$/.test(input);\n\n/**\n * Pad a string to a certain length with a character\n * @param input - String to pad\n * @param length - Target length\n * @param char - Character to pad with (default: \" \")\n * @param direction - Direction to pad (\"left\", \"right\", or \"both\")\n * @returns Padded string\n * @example pad(\"hello\", 10, \"*\", \"right\") // \"hello*****\"\n */\nconst pad = (\n\tinput: string,\n\tlength: number,\n\tchar = ' ',\n\tdirection: 'left' | 'right' | 'both' = 'right'\n): string => {\n\tif (input.length >= length) return input;\n\tconst padLength = length - input.length;\n\n\tif (direction === 'left') {\n\t\treturn char.repeat(padLength) + input;\n\t} else if (direction === 'right') {\n\t\treturn input + char.repeat(padLength);\n\t} else {\n\t\tconst leftPad = Math.floor(padLength / 2);\n\t\tconst rightPad = padLength - leftPad;\n\t\treturn char.repeat(leftPad) + input + char.repeat(rightPad);\n\t}\n};\n\n/**\n * Stringify an array with various formatting options\n * @param arr - Array to stringify\n * @param options - Formatting options (max items, max length, etc.)\n * @returns Object with result string and truncation info\n * @example stringifyArray([1, 2, 3], {maxItems: 2, stringify: String}) // {result: \"1, 2\", truncatedItems: 1}\n */\nconst stringifyArray = <T>(\n\tarr: T[],\n\toptions: StringifyArrayOptions<T>\n): {\n\tresult: string;\n\ttruncatedItems: number;\n} => {\n\tconst {\n\t\tprefix = '',\n\t\tsuffix = '',\n\t\tmaxItemLength,\n\t\tmaxTotalLength,\n\t\tjoinString = ', ',\n\t\tmaxItems,\n\t\tstringify,\n\t} = options;\n\tconst reservedLength = prefix.length + suffix.length;\n\n\tconst withOptions = (_arr: string[]) =>\n\t\tprefix + _arr.join(joinString) + suffix;\n\n\tconst processArray = (\n\t\t_arr: T[]\n\t): {\n\t\tresult: string[];\n\t\ttruncatedItems: number;\n\t} => {\n\t\tconst processItem = (item: T) => {\n\t\t\tconst itemStr = stringify(item);\n\n\t\t\tif (\n\t\t\t\ttypeof maxItemLength === 'undefined' ||\n\t\t\t\titemStr.length <= maxItemLength\n\t\t\t) {\n\t\t\t\treturn itemStr;\n\t\t\t}\n\n\t\t\treturn truncate(itemStr, maxItemLength);\n\t\t};\n\n\t\tif (typeof maxTotalLength === 'undefined')\n\t\t\treturn {\n\t\t\t\tresult: _arr.map(processItem),\n\t\t\t\ttruncatedItems: 0,\n\t\t\t};\n\n\t\tlet totalLength = 0;\n\t\tconst result: string[] = [];\n\n\t\tfor (const item of _arr) {\n\t\t\tconst itemStr = processItem(item);\n\n\t\t\ttotalLength += itemStr.length;\n\n\t\t\tif (totalLength > maxTotalLength - reservedLength) break;\n\n\t\t\tresult.push(itemStr);\n\t\t}\n\n\t\treturn {\n\t\t\tresult,\n\t\t\ttruncatedItems: _arr.length - result.length,\n\t\t};\n\t};\n\n\tconst processed = processArray(arr.slice(0, maxItems));\n\n\treturn {\n\t\tresult: withOptions(processed.result),\n\t\ttruncatedItems: processed.truncatedItems,\n\t};\n};\n\n/**\n * Display array as string with formatting and optional truncation message\n * @param arr - Array to display\n * @param options - Display options\n * @returns Formatted string\n */\nconst displayArray = <T>(\n\tarr: T[],\n\toptions: StringifyArrayOptions<T> & {\n\t\temptyOutput: string;\n\t}\n): string => {\n\tif (arr.length === 0) return options.emptyOutput;\n\n\tconst { result, truncatedItems } = stringifyArray(arr, options);\n\n\treturn `${result}${\n\t\ttruncatedItems > 0 ? `\\n...and ${truncatedItems} more...` : ''\n\t}`;\n};\n\n/**\n * Convert a word to plural form (simple English pluralization)\n * @param input - Word to pluralize\n * @param count - Count to determine if plural is needed\n * @returns Pluralized word\n * @example pluralize(\"cat\", 2) // \"cats\", pluralize(\"cat\", 1) // \"cat\"\n */\nconst pluralize = (input: string, count: number): string =>\n\tcount === 1 ? input : `${input}s`;\n\n/**\n * Convert string to snake_case\n * @param input - String to convert\n * @returns snake_case string\n * @example snakeCase(\"helloWorld\") // \"hello_world\"\n */\nconst snakeCase = (input: string): string =>\n\tinput\n\t\t.replace(/\\s+/g, '_')\n\t\t.replace(/([A-Z])/g, (match) => `_${match.toLowerCase()}`)\n\t\t.replace(/^_/, '')\n\t\t.toLowerCase();\n\n/**\n * Convert string to Title Case\n * @param input - String to convert\n * @returns Title Case string\n * @example titleCase(\"hello world\") // \"Hello World\"\n */\nconst titleCase = (input: string): string =>\n\tinput\n\t\t.split(' ')\n\t\t.map((word) => capitalize(word))\n\t\t.join(' ');\n\n/**\n * Convert string to kebab-case\n * @param input - String to convert\n * @returns kebab-case string\n * @example kebabCase(\"helloWorld\") // \"hello-world\"\n */\nconst kebabCase = (input: string): string =>\n\tinput\n\t\t.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)\n\t\t?.join('-')\n\t\t.toLowerCase() ?? input;\n\n/**\n * Convert string to camelCase\n * @param input - String to convert\n * @returns camelCase string\n * @example camelCase(\"hello world\") // \"helloWorld\"\n */\nconst camelCase = (input: string): string =>\n\tinput\n\t\t.toLowerCase()\n\t\t.split(/\\s+|-/)\n\t\t.reduce(\n\t\t\t(s, c, i) => s + (i === 0 ? c : c.charAt(0).toUpperCase() + c.slice(1))\n\t\t);\n\n/**\n * Convert string to PascalCase\n * @param input - String to convert\n * @returns PascalCase string\n * @example pascalCase(\"hello world\") // \"HelloWorld\"\n */\nconst pascalCase = (input: string): string =>\n\tinput.replace(\n\t\t/(\\w)(\\w*)/g,\n\t\t(_g0, g1, g2) => `${g1.toUpperCase()}${g2.toLowerCase()}`\n\t);\n\n/**\n * Split a string on uppercase letters\n * @param input - String to split\n * @param splitChar - Character to insert (default: \" \")\n * @returns Split string\n * @example splitOnUppercase(\"helloWorld\") // \"hello World\"\n */\nconst splitOnUppercase = (input: string, splitChar = ' '): string =>\n\tinput.split(/(?=[A-Z])/).join(splitChar);\n\n/**\n * Replace template tags in a string with custom delimiters\n * @param input - String with template tags\n * @param placeholders - Object with key-value pairs\n * @param delimiters - Opening and closing delimiters (default: [\"{\", \"}\"])\n * @returns String with replaced tags\n * @example replaceTags(\"Hello {name}!\", {name: \"World\"}) // \"Hello World!\"\n * @example replaceTags(\"Hello {{name}}!\", {name: \"World\"}, [\"{{\", \"}}\"])\n * @example replaceTags(\"Hello [name]!\", {name: \"World\"}, [\"[\", \"]\"])\n */\nconst replaceTags = (\n\tinput: string,\n\tplaceholders: Record<string, string>,\n\tdelimiters: [string, string] = ['{', '}']\n): string => {\n\tconst [open, close] = delimiters;\n\n\t// Escape special regex characters\n\tconst escapeRegex = (str: string) =>\n\t\tstr.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\tconst escapedOpen = escapeRegex(open);\n\tconst escapedClose = escapeRegex(close);\n\n\treturn Object.entries(placeholders).reduce(\n\t\t(str, [key, value]) =>\n\t\t\tstr.replace(\n\t\t\t\tnew RegExp(`${escapedOpen}${key}${escapedClose}`, 'g'),\n\t\t\t\tvalue\n\t\t\t),\n\t\tinput\n\t);\n};\n\n/**\n * Check if a string is a valid URL\n * @param input - String to check\n * @returns True if valid URL\n * @example isUrl(\"https://example.com\") // true\n */\nconst isUrl = (input: string): boolean => {\n\ttry {\n\t\tnew URL(input);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nexport {\n\ttruncate,\n\tcapitalize,\n\tcapitalizeWords,\n\tslugify,\n\tescapeHtml,\n\tunescapeHtml,\n\treverse,\n\tcountOccurrences,\n\tisAlpha,\n\tisAlphanumeric,\n\tpad,\n\tstringifyArray,\n\tdisplayArray,\n\tpluralize,\n\tsnakeCase,\n\ttitleCase,\n\tkebabCase,\n\tcamelCase,\n\tpascalCase,\n\tsplitOnUppercase,\n\treplaceTags,\n\tisUrl,\n\ttype StringifyArrayOptions,\n};\n"],"names":["truncate","__name","input","length","suffix","capitalize","capitalizeWords","word","slugify","escapeHtml","unescapeHtml","reverse","countOccurrences","search","caseSensitive","str","searchStr","isAlpha","isAlphanumeric","pad","char","direction","padLength","leftPad","rightPad","stringifyArray","arr","options","prefix","maxItemLength","maxTotalLength","joinString","maxItems","stringify","reservedLength","withOptions","_arr","processed","processItem","item","itemStr","totalLength","result","displayArray","truncatedItems","pluralize","count","snakeCase","match","titleCase","kebabCase","camelCase","s","c","i","pascalCase","_g0","g1","g2","splitOnUppercase","splitChar","replaceTags","placeholders","delimiters","open","close","escapeRegex","escapedOpen","escapedClose","key","value","isUrl"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";var P=Object.defineProperty;var s=(e,t)=>P(e,"name",{value:t,configurable:!0});const f=s((e,t,r="...")=>e.length>t?e.slice(0,t-r.length)+r:e,"truncate"),g=s(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),"capitalize"),$=s(e=>e.split(" ").map(t=>g(t)).join(" "),"capitalizeWords"),z=s(e=>e.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,""),"slugify"),O=s(e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),"escapeHtml"),b=s(e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'"),"unescapeHtml"),U=s(e=>e.split("").reverse().join(""),"reverse"),j=s((e,t,r=!0)=>{if(!t)return 0;const a=r?e:e.toLowerCase(),c=r?t:t.toLowerCase();return(a.match(new RegExp(c,"g"))||[]).length},"countOccurrences"),I=s(e=>/^[a-zA-Z]+$/.test(e),"isAlpha"),Z=s(e=>/^[a-zA-Z0-9]+$/.test(e),"isAlphanumeric"),k=s((e,t,r=" ",a="right")=>{if(e.length>=t)return e;const c=t-e.length;if(a==="left")return r.repeat(c)+e;if(a==="right")return e+r.repeat(c);{const n=Math.floor(c/2),o=c-n;return r.repeat(n)+e+r.repeat(o)}},"pad"),A=s((e,t)=>{const{prefix:r="",suffix:a="",maxItemLength:c,maxTotalLength:n,joinString:o=", ",maxItems:u,stringify:p}=t,m=r.length+a.length,h=s(i=>r+i.join(o)+a,"withOptions"),y=s(i=>{const w=s(d=>{const l=p(d);return typeof c>"u"||l.length<=c?l:f(l,c)},"processItem");if(typeof n>"u")return{result:i.map(w),truncatedItems:0};let L=0;const C=[];for(const d of i){const l=w(d);if(L+=l.length,L>n-m)break;C.push(l)}return{result:C,truncatedItems:i.length-C.length}},"processArray")(e.slice(0,u));return{result:h(y.result),truncatedItems:y.truncatedItems}},"stringifyArray"),x=s((e,t)=>{if(e.length===0)return t.emptyOutput;const{result:r,truncatedItems:a}=A(e,t);return`${r}${a>0?`
|
|
2
|
+
...and ${a} more...`:""}`},"displayArray"),_=s((e,t)=>t===1?e:`${e}s`,"pluralize"),H=s(e=>e.replace(/\s+/g,"_").replace(/([A-Z])/g,t=>`_${t.toLowerCase()}`).replace(/^_/,"").toLowerCase(),"snakeCase"),v=s(e=>e.split(" ").map(t=>g(t)).join(" "),"titleCase"),R=s(e=>e.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)?.join("-").toLowerCase()??e,"kebabCase"),T=s(e=>e.toLowerCase().split(/\s+|-/).reduce((t,r,a)=>t+(a===0?r:r.charAt(0).toUpperCase()+r.slice(1))),"camelCase"),S=s(e=>e.replace(/(\w)(\w*)/g,(t,r,a)=>`${r.toUpperCase()}${a.toLowerCase()}`),"pascalCase"),W=s((e,t=" ")=>e.split(/(?=[A-Z])/).join(t),"splitOnUppercase"),q=s((e,t,r=["{","}"])=>{const[a,c]=r,n=s(p=>p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"escapeRegex"),o=n(a),u=n(c);return Object.entries(t).reduce((p,[m,h])=>p.replace(new RegExp(`${o}${m}${u}`,"g"),h),e)},"replaceTags"),E=s(e=>{try{return new URL(e),!0}catch{return!1}},"isUrl");var M=Object.freeze({__proto__:null,camelCase:T,capitalize:g,capitalizeWords:$,countOccurrences:j,displayArray:x,escapeHtml:O,isAlpha:I,isAlphanumeric:Z,isUrl:E,kebabCase:R,pad:k,pascalCase:S,pluralize:_,replaceTags:q,reverse:U,slugify:z,snakeCase:H,splitOnUppercase:W,stringifyArray:A,titleCase:v,truncate:f,unescapeHtml:b});exports.camelCase=T,exports.capitalize=g,exports.capitalizeWords=$,exports.countOccurrences=j,exports.displayArray=x,exports.escapeHtml=O,exports.isAlpha=I,exports.isAlphanumeric=Z,exports.isUrl=E,exports.kebabCase=R,exports.pad=k,exports.pascalCase=S,exports.pluralize=_,exports.replaceTags=q,exports.reverse=U,exports.slugify=z,exports.snakeCase=H,exports.splitOnUppercase=W,exports.stringifyArray=A,exports.strings=M,exports.titleCase=v,exports.truncate=f,exports.unescapeHtml=b;
|
|
3
|
+
//# sourceMappingURL=strings-_1vAPvzS.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings-_1vAPvzS.cjs","sources":["../src/utils/strings.ts"],"sourcesContent":["type StringifyArrayOptions<T> = {\n\tmaxItems: number;\n\tmaxItemLength?: number;\n\tmaxTotalLength?: number;\n\tstringify: (item: T) => string;\n\tprefix?: string;\n\tsuffix?: string;\n\tjoinString?: string;\n};\n\n/**\n * Truncate a string to a maximum length, adding a suffix if truncated\n * @param input - String to truncate\n * @param length - Maximum length\n * @param suffix - Suffix to add (default: \"...\")\n * @returns Truncated string\n * @example truncate(\"Hello World\", 8) // \"Hello...\"\n */\nconst truncate = (input: string, length: number, suffix = '...'): string =>\n\tinput.length > length\n\t\t? input.slice(0, length - suffix.length) + suffix\n\t\t: input;\n\n/**\n * Capitalize the first letter of a string\n * @param input - String to capitalize\n * @returns Capitalized string\n * @example capitalize(\"hello world\") // \"Hello world\"\n */\nconst capitalize = (input: string): string =>\n\tinput.charAt(0).toUpperCase() + input.slice(1).toLowerCase();\n\n/**\n * Capitalize the first letter of each word\n * @param input - String to capitalize\n * @returns String with each word capitalized\n * @example capitalizeWords(\"hello world\") // \"Hello World\"\n */\nconst capitalizeWords = (input: string): string =>\n\tinput\n\t\t.split(' ')\n\t\t.map((word) => capitalize(word))\n\t\t.join(' ');\n\n/**\n * Create a URL-friendly slug from a string\n * @param input - String to slugify\n * @returns Slugified string\n * @example slugify(\"Hello World!\") // \"hello-world\"\n */\nconst slugify = (input: string): string =>\n\tinput\n\t\t.toLowerCase()\n\t\t.trim()\n\t\t.replace(/[^\\w\\s-]/g, '')\n\t\t.replace(/[\\s_-]+/g, '-')\n\t\t.replace(/^-+|-+$/g, '');\n\n/**\n * Escape HTML special characters\n * @param input - String to escape\n * @returns Escaped string\n * @example escapeHtml(\"<div>Hello</div>\") // \"<div>Hello</div>\"\n */\nconst escapeHtml = (input: string): string =>\n\tinput\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/'/g, ''');\n\n/**\n * Unescape HTML entities\n * @param input - String to unescape\n * @returns Unescaped string\n * @example unescapeHtml(\"<div>\") // \"<div>\"\n */\nconst unescapeHtml = (input: string): string =>\n\tinput\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/"/g, '\"')\n\t\t.replace(/'/g, \"'\");\n\n/**\n * Reverse a string\n * @param input - String to reverse\n * @returns Reversed string\n * @example reverse(\"hello\") // \"olleh\"\n */\nconst reverse = (input: string): string => input.split('').reverse().join('');\n\n/**\n * Count occurrences of a substring\n * @param input - String to search in\n * @param search - Substring to count\n * @param caseSensitive - Whether to be case sensitive (default: true)\n * @returns Number of occurrences\n * @example countOccurrences(\"hello hello world\", \"hello\") // 2\n */\nconst countOccurrences = (\n\tinput: string,\n\tsearch: string,\n\tcaseSensitive = true\n): number => {\n\tif (!search) return 0;\n\tconst str = caseSensitive ? input : input.toLowerCase();\n\tconst searchStr = caseSensitive ? search : search.toLowerCase();\n\treturn (str.match(new RegExp(searchStr, 'g')) || []).length;\n};\n\n/**\n * Check if a string contains only letters\n * @param input - String to check\n * @returns True if only letters\n * @example isAlpha(\"hello\") // true, isAlpha(\"hello123\") // false\n */\nconst isAlpha = (input: string): boolean => /^[a-zA-Z]+$/.test(input);\n\n/**\n * Check if a string contains only alphanumeric characters\n * @param input - String to check\n * @returns True if alphanumeric\n * @example isAlphanumeric(\"hello123\") // true, isAlphanumeric(\"hello-123\") // false\n */\nconst isAlphanumeric = (input: string): boolean => /^[a-zA-Z0-9]+$/.test(input);\n\n/**\n * Pad a string to a certain length with a character\n * @param input - String to pad\n * @param length - Target length\n * @param char - Character to pad with (default: \" \")\n * @param direction - Direction to pad (\"left\", \"right\", or \"both\")\n * @returns Padded string\n * @example pad(\"hello\", 10, \"*\", \"right\") // \"hello*****\"\n */\nconst pad = (\n\tinput: string,\n\tlength: number,\n\tchar = ' ',\n\tdirection: 'left' | 'right' | 'both' = 'right'\n): string => {\n\tif (input.length >= length) return input;\n\tconst padLength = length - input.length;\n\n\tif (direction === 'left') {\n\t\treturn char.repeat(padLength) + input;\n\t} else if (direction === 'right') {\n\t\treturn input + char.repeat(padLength);\n\t} else {\n\t\tconst leftPad = Math.floor(padLength / 2);\n\t\tconst rightPad = padLength - leftPad;\n\t\treturn char.repeat(leftPad) + input + char.repeat(rightPad);\n\t}\n};\n\n/**\n * Stringify an array with various formatting options\n * @param arr - Array to stringify\n * @param options - Formatting options (max items, max length, etc.)\n * @returns Object with result string and truncation info\n * @example stringifyArray([1, 2, 3], {maxItems: 2, stringify: String}) // {result: \"1, 2\", truncatedItems: 1}\n */\nconst stringifyArray = <T>(\n\tarr: T[],\n\toptions: StringifyArrayOptions<T>\n): {\n\tresult: string;\n\ttruncatedItems: number;\n} => {\n\tconst {\n\t\tprefix = '',\n\t\tsuffix = '',\n\t\tmaxItemLength,\n\t\tmaxTotalLength,\n\t\tjoinString = ', ',\n\t\tmaxItems,\n\t\tstringify,\n\t} = options;\n\tconst reservedLength = prefix.length + suffix.length;\n\n\tconst withOptions = (_arr: string[]) =>\n\t\tprefix + _arr.join(joinString) + suffix;\n\n\tconst processArray = (\n\t\t_arr: T[]\n\t): {\n\t\tresult: string[];\n\t\ttruncatedItems: number;\n\t} => {\n\t\tconst processItem = (item: T) => {\n\t\t\tconst itemStr = stringify(item);\n\n\t\t\tif (\n\t\t\t\ttypeof maxItemLength === 'undefined' ||\n\t\t\t\titemStr.length <= maxItemLength\n\t\t\t) {\n\t\t\t\treturn itemStr;\n\t\t\t}\n\n\t\t\treturn truncate(itemStr, maxItemLength);\n\t\t};\n\n\t\tif (typeof maxTotalLength === 'undefined')\n\t\t\treturn {\n\t\t\t\tresult: _arr.map(processItem),\n\t\t\t\ttruncatedItems: 0,\n\t\t\t};\n\n\t\tlet totalLength = 0;\n\t\tconst result: string[] = [];\n\n\t\tfor (const item of _arr) {\n\t\t\tconst itemStr = processItem(item);\n\n\t\t\ttotalLength += itemStr.length;\n\n\t\t\tif (totalLength > maxTotalLength - reservedLength) break;\n\n\t\t\tresult.push(itemStr);\n\t\t}\n\n\t\treturn {\n\t\t\tresult,\n\t\t\ttruncatedItems: _arr.length - result.length,\n\t\t};\n\t};\n\n\tconst processed = processArray(arr.slice(0, maxItems));\n\n\treturn {\n\t\tresult: withOptions(processed.result),\n\t\ttruncatedItems: processed.truncatedItems,\n\t};\n};\n\n/**\n * Display array as string with formatting and optional truncation message\n * @param arr - Array to display\n * @param options - Display options\n * @returns Formatted string\n */\nconst displayArray = <T>(\n\tarr: T[],\n\toptions: StringifyArrayOptions<T> & {\n\t\temptyOutput: string;\n\t}\n): string => {\n\tif (arr.length === 0) return options.emptyOutput;\n\n\tconst { result, truncatedItems } = stringifyArray(arr, options);\n\n\treturn `${result}${\n\t\ttruncatedItems > 0 ? `\\n...and ${truncatedItems} more...` : ''\n\t}`;\n};\n\n/**\n * Convert a word to plural form (simple English pluralization)\n * @param input - Word to pluralize\n * @param count - Count to determine if plural is needed\n * @returns Pluralized word\n * @example pluralize(\"cat\", 2) // \"cats\", pluralize(\"cat\", 1) // \"cat\"\n */\nconst pluralize = (input: string, count: number): string =>\n\tcount === 1 ? input : `${input}s`;\n\n/**\n * Convert string to snake_case\n * @param input - String to convert\n * @returns snake_case string\n * @example snakeCase(\"helloWorld\") // \"hello_world\"\n */\nconst snakeCase = (input: string): string =>\n\tinput\n\t\t.replace(/\\s+/g, '_')\n\t\t.replace(/([A-Z])/g, (match) => `_${match.toLowerCase()}`)\n\t\t.replace(/^_/, '')\n\t\t.toLowerCase();\n\n/**\n * Convert string to Title Case\n * @param input - String to convert\n * @returns Title Case string\n * @example titleCase(\"hello world\") // \"Hello World\"\n */\nconst titleCase = (input: string): string =>\n\tinput\n\t\t.split(' ')\n\t\t.map((word) => capitalize(word))\n\t\t.join(' ');\n\n/**\n * Convert string to kebab-case\n * @param input - String to convert\n * @returns kebab-case string\n * @example kebabCase(\"helloWorld\") // \"hello-world\"\n */\nconst kebabCase = (input: string): string =>\n\tinput\n\t\t.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)\n\t\t?.join('-')\n\t\t.toLowerCase() ?? input;\n\n/**\n * Convert string to camelCase\n * @param input - String to convert\n * @returns camelCase string\n * @example camelCase(\"hello world\") // \"helloWorld\"\n */\nconst camelCase = (input: string): string =>\n\tinput\n\t\t.toLowerCase()\n\t\t.split(/\\s+|-/)\n\t\t.reduce(\n\t\t\t(s, c, i) => s + (i === 0 ? c : c.charAt(0).toUpperCase() + c.slice(1))\n\t\t);\n\n/**\n * Convert string to PascalCase\n * @param input - String to convert\n * @returns PascalCase string\n * @example pascalCase(\"hello world\") // \"HelloWorld\"\n */\nconst pascalCase = (input: string): string =>\n\tinput.replace(\n\t\t/(\\w)(\\w*)/g,\n\t\t(_g0, g1, g2) => `${g1.toUpperCase()}${g2.toLowerCase()}`\n\t);\n\n/**\n * Split a string on uppercase letters\n * @param input - String to split\n * @param splitChar - Character to insert (default: \" \")\n * @returns Split string\n * @example splitOnUppercase(\"helloWorld\") // \"hello World\"\n */\nconst splitOnUppercase = (input: string, splitChar = ' '): string =>\n\tinput.split(/(?=[A-Z])/).join(splitChar);\n\n/**\n * Replace template tags in a string with custom delimiters\n * @param input - String with template tags\n * @param placeholders - Object with key-value pairs\n * @param delimiters - Opening and closing delimiters (default: [\"{\", \"}\"])\n * @returns String with replaced tags\n * @example replaceTags(\"Hello {name}!\", {name: \"World\"}) // \"Hello World!\"\n * @example replaceTags(\"Hello {{name}}!\", {name: \"World\"}, [\"{{\", \"}}\"])\n * @example replaceTags(\"Hello [name]!\", {name: \"World\"}, [\"[\", \"]\"])\n */\nconst replaceTags = (\n\tinput: string,\n\tplaceholders: Record<string, string>,\n\tdelimiters: [string, string] = ['{', '}']\n): string => {\n\tconst [open, close] = delimiters;\n\n\t// Escape special regex characters\n\tconst escapeRegex = (str: string) =>\n\t\tstr.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\tconst escapedOpen = escapeRegex(open);\n\tconst escapedClose = escapeRegex(close);\n\n\treturn Object.entries(placeholders).reduce(\n\t\t(str, [key, value]) =>\n\t\t\tstr.replace(\n\t\t\t\tnew RegExp(`${escapedOpen}${key}${escapedClose}`, 'g'),\n\t\t\t\tvalue\n\t\t\t),\n\t\tinput\n\t);\n};\n\n/**\n * Check if a string is a valid URL\n * @param input - String to check\n * @returns True if valid URL\n * @example isUrl(\"https://example.com\") // true\n */\nconst isUrl = (input: string): boolean => {\n\ttry {\n\t\tnew URL(input);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nexport {\n\ttruncate,\n\tcapitalize,\n\tcapitalizeWords,\n\tslugify,\n\tescapeHtml,\n\tunescapeHtml,\n\treverse,\n\tcountOccurrences,\n\tisAlpha,\n\tisAlphanumeric,\n\tpad,\n\tstringifyArray,\n\tdisplayArray,\n\tpluralize,\n\tsnakeCase,\n\ttitleCase,\n\tkebabCase,\n\tcamelCase,\n\tpascalCase,\n\tsplitOnUppercase,\n\treplaceTags,\n\tisUrl,\n\ttype StringifyArrayOptions,\n};\n"],"names":["truncate","__name","input","length","suffix","capitalize","capitalizeWords","word","slugify","escapeHtml","unescapeHtml","reverse","countOccurrences","search","caseSensitive","str","searchStr","isAlpha","isAlphanumeric","pad","char","direction","padLength","leftPad","rightPad","stringifyArray","arr","options","prefix","maxItemLength","maxTotalLength","joinString","maxItems","stringify","reservedLength","withOptions","_arr","processed","processItem","item","itemStr","totalLength","result","displayArray","truncatedItems","pluralize","count","snakeCase","match","titleCase","kebabCase","camelCase","s","c","i","pascalCase","_g0","g1","g2","splitOnUppercase","splitChar","replaceTags","placeholders","delimiters","open","close","escapeRegex","escapedOpen","escapedClose","key","value","isUrl"],"mappings":"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"}
|