@gzl10/ts-helpers 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/CHANGELOG.md +320 -0
  2. package/README.md +233 -0
  3. package/USAGE-GUIDE.md +800 -0
  4. package/dist/browser/async.js +15 -0
  5. package/dist/browser/async.js.map +1 -0
  6. package/dist/browser/chunk-4O7ZPIJN.js +383 -0
  7. package/dist/browser/chunk-4O7ZPIJN.js.map +1 -0
  8. package/dist/browser/chunk-75XNTC34.js +60 -0
  9. package/dist/browser/chunk-75XNTC34.js.map +1 -0
  10. package/dist/browser/chunk-C3D7YZVE.js +299 -0
  11. package/dist/browser/chunk-C3D7YZVE.js.map +1 -0
  12. package/dist/browser/chunk-CZL6C2EI.js +452 -0
  13. package/dist/browser/chunk-CZL6C2EI.js.map +1 -0
  14. package/dist/browser/chunk-D4FZFIVA.js +240 -0
  15. package/dist/browser/chunk-D4FZFIVA.js.map +1 -0
  16. package/dist/browser/chunk-IL7NG7IC.js +72 -0
  17. package/dist/browser/chunk-IL7NG7IC.js.map +1 -0
  18. package/dist/browser/chunk-NSBPE2FW.js +17 -0
  19. package/dist/browser/chunk-NSBPE2FW.js.map +1 -0
  20. package/dist/browser/chunk-SLQVNPTH.js +27 -0
  21. package/dist/browser/chunk-SLQVNPTH.js.map +1 -0
  22. package/dist/browser/chunk-WG7ILCUB.js +195 -0
  23. package/dist/browser/chunk-WG7ILCUB.js.map +1 -0
  24. package/dist/browser/chunk-WJA4JDMZ.js +278 -0
  25. package/dist/browser/chunk-WJA4JDMZ.js.map +1 -0
  26. package/dist/browser/chunk-ZFVYLUTT.js +65 -0
  27. package/dist/browser/chunk-ZFVYLUTT.js.map +1 -0
  28. package/dist/browser/chunk-ZYTSVMTI.js +263 -0
  29. package/dist/browser/chunk-ZYTSVMTI.js.map +1 -0
  30. package/dist/browser/dates.js +78 -0
  31. package/dist/browser/dates.js.map +1 -0
  32. package/dist/browser/environment-detection.js +21 -0
  33. package/dist/browser/environment-detection.js.map +1 -0
  34. package/dist/browser/environment.js +34 -0
  35. package/dist/browser/environment.js.map +1 -0
  36. package/dist/browser/errors.js +18 -0
  37. package/dist/browser/errors.js.map +1 -0
  38. package/dist/browser/index.js +412 -0
  39. package/dist/browser/index.js.map +1 -0
  40. package/dist/browser/math.js +51 -0
  41. package/dist/browser/math.js.map +1 -0
  42. package/dist/browser/number.js +10 -0
  43. package/dist/browser/number.js.map +1 -0
  44. package/dist/browser/objects.js +31 -0
  45. package/dist/browser/objects.js.map +1 -0
  46. package/dist/browser/strings.js +80 -0
  47. package/dist/browser/strings.js.map +1 -0
  48. package/dist/browser/validation-core.js +54 -0
  49. package/dist/browser/validation-core.js.map +1 -0
  50. package/dist/browser/validation-crypto.js +28 -0
  51. package/dist/browser/validation-crypto.js.map +1 -0
  52. package/dist/browser/validators.js +98 -0
  53. package/dist/browser/validators.js.map +1 -0
  54. package/dist/cjs/async.js +86 -0
  55. package/dist/cjs/async.js.map +1 -0
  56. package/dist/cjs/dates.js +285 -0
  57. package/dist/cjs/dates.js.map +1 -0
  58. package/dist/cjs/environment-detection.js +84 -0
  59. package/dist/cjs/environment-detection.js.map +1 -0
  60. package/dist/cjs/environment.js +261 -0
  61. package/dist/cjs/environment.js.map +1 -0
  62. package/dist/cjs/errors.js +80 -0
  63. package/dist/cjs/errors.js.map +1 -0
  64. package/dist/cjs/index.js +2035 -0
  65. package/dist/cjs/index.js.map +1 -0
  66. package/dist/cjs/math.js +388 -0
  67. package/dist/cjs/math.js.map +1 -0
  68. package/dist/cjs/number.js +37 -0
  69. package/dist/cjs/number.js.map +1 -0
  70. package/dist/cjs/objects.js +249 -0
  71. package/dist/cjs/objects.js.map +1 -0
  72. package/dist/cjs/strings.js +253 -0
  73. package/dist/cjs/strings.js.map +1 -0
  74. package/dist/cjs/validation.js +450 -0
  75. package/dist/cjs/validation.js.map +1 -0
  76. package/dist/esm/async.js +15 -0
  77. package/dist/esm/async.js.map +1 -0
  78. package/dist/esm/chunk-4O7ZPIJN.js +383 -0
  79. package/dist/esm/chunk-4O7ZPIJN.js.map +1 -0
  80. package/dist/esm/chunk-75XNTC34.js +60 -0
  81. package/dist/esm/chunk-75XNTC34.js.map +1 -0
  82. package/dist/esm/chunk-BDOBKBKA.js +72 -0
  83. package/dist/esm/chunk-BDOBKBKA.js.map +1 -0
  84. package/dist/esm/chunk-C3D7YZVE.js +299 -0
  85. package/dist/esm/chunk-C3D7YZVE.js.map +1 -0
  86. package/dist/esm/chunk-CZL6C2EI.js +452 -0
  87. package/dist/esm/chunk-CZL6C2EI.js.map +1 -0
  88. package/dist/esm/chunk-EBLSTOEC.js +263 -0
  89. package/dist/esm/chunk-EBLSTOEC.js.map +1 -0
  90. package/dist/esm/chunk-NSBPE2FW.js +17 -0
  91. package/dist/esm/chunk-NSBPE2FW.js.map +1 -0
  92. package/dist/esm/chunk-SLQVNPTH.js +27 -0
  93. package/dist/esm/chunk-SLQVNPTH.js.map +1 -0
  94. package/dist/esm/chunk-WG7ILCUB.js +195 -0
  95. package/dist/esm/chunk-WG7ILCUB.js.map +1 -0
  96. package/dist/esm/chunk-WJA4JDMZ.js +278 -0
  97. package/dist/esm/chunk-WJA4JDMZ.js.map +1 -0
  98. package/dist/esm/chunk-ZFVYLUTT.js +65 -0
  99. package/dist/esm/chunk-ZFVYLUTT.js.map +1 -0
  100. package/dist/esm/dates.js +78 -0
  101. package/dist/esm/dates.js.map +1 -0
  102. package/dist/esm/environment-detection.js +21 -0
  103. package/dist/esm/environment-detection.js.map +1 -0
  104. package/dist/esm/environment.js +34 -0
  105. package/dist/esm/environment.js.map +1 -0
  106. package/dist/esm/errors.js +18 -0
  107. package/dist/esm/errors.js.map +1 -0
  108. package/dist/esm/index.js +380 -0
  109. package/dist/esm/index.js.map +1 -0
  110. package/dist/esm/math.js +51 -0
  111. package/dist/esm/math.js.map +1 -0
  112. package/dist/esm/number.js +10 -0
  113. package/dist/esm/number.js.map +1 -0
  114. package/dist/esm/objects.js +31 -0
  115. package/dist/esm/objects.js.map +1 -0
  116. package/dist/esm/strings.js +80 -0
  117. package/dist/esm/strings.js.map +1 -0
  118. package/dist/esm/validation.js +54 -0
  119. package/dist/esm/validation.js.map +1 -0
  120. package/dist/node/async.js +93 -0
  121. package/dist/node/async.js.map +1 -0
  122. package/dist/node/csv.js +102 -0
  123. package/dist/node/csv.js.map +1 -0
  124. package/dist/node/data.js +880 -0
  125. package/dist/node/data.js.map +1 -0
  126. package/dist/node/dates.js +324 -0
  127. package/dist/node/dates.js.map +1 -0
  128. package/dist/node/environment.js +278 -0
  129. package/dist/node/environment.js.map +1 -0
  130. package/dist/node/errors.js +89 -0
  131. package/dist/node/errors.js.map +1 -0
  132. package/dist/node/index.js +3151 -0
  133. package/dist/node/index.js.map +1 -0
  134. package/dist/node/json.js +107 -0
  135. package/dist/node/json.js.map +1 -0
  136. package/dist/node/math.js +413 -0
  137. package/dist/node/math.js.map +1 -0
  138. package/dist/node/number.js +42 -0
  139. package/dist/node/number.js.map +1 -0
  140. package/dist/node/objects.js +264 -0
  141. package/dist/node/objects.js.map +1 -0
  142. package/dist/node/strings.js +293 -0
  143. package/dist/node/strings.js.map +1 -0
  144. package/dist/node/tree.js +89 -0
  145. package/dist/node/tree.js.map +1 -0
  146. package/dist/node/validation-core.js +477 -0
  147. package/dist/node/validation-core.js.map +1 -0
  148. package/dist/node/validation-crypto.js +179 -0
  149. package/dist/node/validation-crypto.js.map +1 -0
  150. package/dist/node/validation.js +677 -0
  151. package/dist/node/validation.js.map +1 -0
  152. package/dist/node/validators.js +123 -0
  153. package/dist/node/validators.js.map +1 -0
  154. package/dist/node-esm/async.js +15 -0
  155. package/dist/node-esm/async.js.map +1 -0
  156. package/dist/node-esm/chunk-3YOF7NPT.js +299 -0
  157. package/dist/node-esm/chunk-3YOF7NPT.js.map +1 -0
  158. package/dist/node-esm/chunk-64TBXJQS.js +263 -0
  159. package/dist/node-esm/chunk-64TBXJQS.js.map +1 -0
  160. package/dist/node-esm/chunk-75XNTC34.js +60 -0
  161. package/dist/node-esm/chunk-75XNTC34.js.map +1 -0
  162. package/dist/node-esm/chunk-C4PKXIPB.js +278 -0
  163. package/dist/node-esm/chunk-C4PKXIPB.js.map +1 -0
  164. package/dist/node-esm/chunk-CMDFZME3.js +452 -0
  165. package/dist/node-esm/chunk-CMDFZME3.js.map +1 -0
  166. package/dist/node-esm/chunk-DZZPUYMP.js +74 -0
  167. package/dist/node-esm/chunk-DZZPUYMP.js.map +1 -0
  168. package/dist/node-esm/chunk-HTSEHRHI.js +195 -0
  169. package/dist/node-esm/chunk-HTSEHRHI.js.map +1 -0
  170. package/dist/node-esm/chunk-JCAUVOPH.js +27 -0
  171. package/dist/node-esm/chunk-JCAUVOPH.js.map +1 -0
  172. package/dist/node-esm/chunk-KBHE3K2F.js +505 -0
  173. package/dist/node-esm/chunk-KBHE3K2F.js.map +1 -0
  174. package/dist/node-esm/chunk-LYTET5NX.js +65 -0
  175. package/dist/node-esm/chunk-LYTET5NX.js.map +1 -0
  176. package/dist/node-esm/chunk-PZ5AY32C.js +10 -0
  177. package/dist/node-esm/chunk-PZ5AY32C.js.map +1 -0
  178. package/dist/node-esm/chunk-UKGXL2QO.js +383 -0
  179. package/dist/node-esm/chunk-UKGXL2QO.js.map +1 -0
  180. package/dist/node-esm/chunk-XAEYT23H.js +164 -0
  181. package/dist/node-esm/chunk-XAEYT23H.js.map +1 -0
  182. package/dist/node-esm/csv.js +63 -0
  183. package/dist/node-esm/csv.js.map +1 -0
  184. package/dist/node-esm/data.js +32 -0
  185. package/dist/node-esm/data.js.map +1 -0
  186. package/dist/node-esm/dates.js +78 -0
  187. package/dist/node-esm/dates.js.map +1 -0
  188. package/dist/node-esm/environment.js +34 -0
  189. package/dist/node-esm/environment.js.map +1 -0
  190. package/dist/node-esm/errors.js +18 -0
  191. package/dist/node-esm/errors.js.map +1 -0
  192. package/dist/node-esm/index.js +426 -0
  193. package/dist/node-esm/index.js.map +1 -0
  194. package/dist/node-esm/json.js +68 -0
  195. package/dist/node-esm/json.js.map +1 -0
  196. package/dist/node-esm/math.js +51 -0
  197. package/dist/node-esm/math.js.map +1 -0
  198. package/dist/node-esm/number.js +10 -0
  199. package/dist/node-esm/number.js.map +1 -0
  200. package/dist/node-esm/objects.js +31 -0
  201. package/dist/node-esm/objects.js.map +1 -0
  202. package/dist/node-esm/strings.js +80 -0
  203. package/dist/node-esm/strings.js.map +1 -0
  204. package/dist/node-esm/tree.js +8 -0
  205. package/dist/node-esm/tree.js.map +1 -0
  206. package/dist/node-esm/validation-core.js +54 -0
  207. package/dist/node-esm/validation-core.js.map +1 -0
  208. package/dist/node-esm/validation-crypto.js +26 -0
  209. package/dist/node-esm/validation-crypto.js.map +1 -0
  210. package/dist/node-esm/validation.js +606 -0
  211. package/dist/node-esm/validation.js.map +1 -0
  212. package/dist/node-esm/validators.js +98 -0
  213. package/dist/node-esm/validators.js.map +1 -0
  214. package/dist/types/async-C8gvbSG-.d.ts +453 -0
  215. package/dist/types/async.d.ts +1 -0
  216. package/dist/types/csv.d.ts +226 -0
  217. package/dist/types/data.d.ts +1561 -0
  218. package/dist/types/dates-hTiE0Z11.d.ts +298 -0
  219. package/dist/types/dates.d.ts +1 -0
  220. package/dist/types/environment-B8eLS7KT.d.ts +420 -0
  221. package/dist/types/environment-detection.d.ts +102 -0
  222. package/dist/types/environment.d.ts +1 -0
  223. package/dist/types/errors.d.ts +147 -0
  224. package/dist/types/index.d.ts +211 -0
  225. package/dist/types/json.d.ts +284 -0
  226. package/dist/types/math-BQ9Lwdp7.d.ts +2060 -0
  227. package/dist/types/math.d.ts +1 -0
  228. package/dist/types/number-CYnQfLWj.d.ts +44 -0
  229. package/dist/types/number.d.ts +1 -0
  230. package/dist/types/objects-BohS8GCS.d.ts +1185 -0
  231. package/dist/types/objects.d.ts +1 -0
  232. package/dist/types/strings-CiqRPYLL.d.ts +1349 -0
  233. package/dist/types/strings.d.ts +1 -0
  234. package/dist/types/tree.d.ts +284 -0
  235. package/dist/types/validation-core-DfHF8rCG.d.ts +238 -0
  236. package/dist/types/validation-crypto-browser.d.ts +56 -0
  237. package/dist/types/validation-crypto-node.d.ts +31 -0
  238. package/dist/types/validation.d.ts +1 -0
  239. package/dist/types/validators.d.ts +216 -0
  240. package/package.json +253 -0
@@ -0,0 +1,453 @@
1
+ /**
2
+ * Asynchronous utilities and operations
3
+ * Consolidated from core/async module
4
+ */
5
+ /**
6
+ * Creates an asynchronous delay for the specified number of milliseconds
7
+ *
8
+ * Pauses async execution without blocking the event loop. Uses Promise with setTimeout
9
+ * internally to schedule resumption after the specified delay.
10
+ *
11
+ * Common use cases:
12
+ * - Rate limiting API calls
13
+ * - Retry delays with exponential backoff
14
+ * - Animation/transition timing
15
+ * - Polling intervals
16
+ * - Debouncing operations
17
+ *
18
+ * @param ms - Milliseconds to sleep (delay duration)
19
+ * @returns Promise that resolves after the specified delay
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Basic delay
24
+ * console.log('Starting...')
25
+ * await sleep(2000) // Wait 2 seconds
26
+ * console.log('Done!')
27
+ * ```
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Real-world: Rate-limited API calls
32
+ * async function fetchAllUsers(userIds: string[]): Promise<User[]> {
33
+ * const users: User[] = []
34
+ *
35
+ * for (const id of userIds) {
36
+ * const user = await api.getUser(id)
37
+ * users.push(user)
38
+ *
39
+ * // Rate limit: 100ms between requests (max 10 req/sec)
40
+ * await sleep(100)
41
+ * }
42
+ *
43
+ * return users
44
+ * }
45
+ * ```
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * // Real-world: Exponential backoff retry
50
+ * async function fetchWithRetry(url: string, maxRetries = 3): Promise<Response> {
51
+ * let lastError: Error | null = null
52
+ *
53
+ * for (let attempt = 0; attempt < maxRetries; attempt++) {
54
+ * try {
55
+ * return await fetch(url)
56
+ * } catch (error) {
57
+ * lastError = error as Error
58
+ * const delay = Math.pow(2, attempt) * 1000 // 1s, 2s, 4s
59
+ * console.log(`Retry ${attempt + 1}/${maxRetries} in ${delay}ms`)
60
+ * await sleep(delay)
61
+ * }
62
+ * }
63
+ *
64
+ * throw lastError
65
+ * }
66
+ * ```
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * // Real-world: Polling with timeout
71
+ * async function pollUntilReady(
72
+ * checkFn: () => Promise<boolean>,
73
+ * timeoutMs = 30000
74
+ * ): Promise<boolean> {
75
+ * const startTime = Date.now()
76
+ *
77
+ * while (Date.now() - startTime < timeoutMs) {
78
+ * if (await checkFn()) {
79
+ * return true
80
+ * }
81
+ * await sleep(1000) // Poll every second
82
+ * }
83
+ *
84
+ * throw new Error('Timeout waiting for ready state')
85
+ * }
86
+ *
87
+ * // Usage: Wait for service to be ready
88
+ * await pollUntilReady(async () => {
89
+ * const response = await fetch('/health')
90
+ * return response.ok
91
+ * })
92
+ * ```
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * // Real-world: Animated progress bar
97
+ * async function animateProgress(element: HTMLElement): Promise<void> {
98
+ * for (let i = 0; i <= 100; i += 5) {
99
+ * element.style.width = `${i}%`
100
+ * await sleep(50) // 50ms per step = 1 second total
101
+ * }
102
+ * }
103
+ * ```
104
+ *
105
+ * @see {@link wait} for alias with same functionality
106
+ * @see {@link runBatch} for controlled concurrent execution
107
+ */
108
+ declare const sleep: (ms: number) => Promise<void>;
109
+ /**
110
+ * Simple alias for sleep - Pauses execution for specified milliseconds
111
+ *
112
+ * Identical to {@link sleep}, provided for semantic clarity in code.
113
+ * Use `wait` when the context emphasizes waiting for a condition or event.
114
+ *
115
+ * @param ms - Milliseconds to wait
116
+ * @returns Promise that resolves after the specified delay
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * // Semantically clearer in some contexts
121
+ * await wait(1000) // Wait 1 second before continuing
122
+ *
123
+ * // vs sleep (implies intentional delay)
124
+ * await sleep(1000) // Sleep for 1 second
125
+ * ```
126
+ *
127
+ * @see {@link sleep} for full documentation and examples
128
+ */
129
+ declare const wait: (ms: number) => Promise<void>;
130
+ /**
131
+ * Executes an array of Promises in batches to control concurrency
132
+ *
133
+ * Processes promises in sequential batches, waiting for each batch to complete before
134
+ * starting the next. Prevents overwhelming systems with too many concurrent requests.
135
+ *
136
+ * Algorithm:
137
+ * 1. Divide promises into batches of size `batchSize`
138
+ * 2. Execute each batch with Promise.all (parallel within batch)
139
+ * 3. Wait for batch completion before starting next batch
140
+ * 4. Collect and return all results in original order
141
+ *
142
+ * Use cases:
143
+ * - Rate-limited API calls (respect API quotas)
144
+ * - Database bulk operations (avoid connection pool exhaustion)
145
+ * - File system operations (prevent file descriptor limits)
146
+ * - Memory-intensive operations (control memory usage)
147
+ *
148
+ * @param jobs - Array of Promises to execute
149
+ * @param batchSize - Number of promises to execute concurrently per batch (default: 50)
150
+ * @returns Promise resolving to array of all results in original order
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * // Basic batch processing
155
+ * const urls = ['url1', 'url2', ..., 'url100'] // 100 URLs
156
+ * const fetchPromises = urls.map(url => fetch(url))
157
+ *
158
+ * // Execute 10 at a time instead of all 100 simultaneously
159
+ * const responses = await runBatch(fetchPromises, 10)
160
+ * // Batch 1: urls 0-9 (parallel)
161
+ * // Batch 2: urls 10-19 (parallel) - starts after batch 1 completes
162
+ * // ... 10 batches total
163
+ * ```
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * // Real-world: Bulk user data fetch respecting API rate limits
168
+ * async function fetchUsersInBatches(userIds: string[]): Promise<User[]> {
169
+ * console.log(`Fetching ${userIds.length} users in batches of 20...`)
170
+ *
171
+ * const fetchPromises = userIds.map(id =>
172
+ * fetch(`/api/users/${id}`).then(res => res.json())
173
+ * )
174
+ *
175
+ * const users = await runBatch(fetchPromises, 20)
176
+ *
177
+ * console.log(`✅ Fetched ${users.length} users`)
178
+ * return users
179
+ * }
180
+ *
181
+ * // Fetches 1000 users: 50 batches of 20, not 1000 simultaneous requests
182
+ * const allUsers = await fetchUsersInBatches(userIdArray)
183
+ * ```
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * // Real-world: Database bulk insert with connection pool limits
188
+ * async function bulkInsertUsers(users: User[]): Promise<void> {
189
+ * // Database pool has 10 connections, use batch size of 5 for safety
190
+ * const insertPromises = users.map(user =>
191
+ * db.query('INSERT INTO users VALUES ($1, $2)', [user.name, user.email])
192
+ * )
193
+ *
194
+ * await runBatch(insertPromises, 5)
195
+ * console.log(`✅ Inserted ${users.length} users`)
196
+ * }
197
+ * ```
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * // Real-world: Image processing pipeline
202
+ * async function processImages(imagePaths: string[]): Promise<Buffer[]> {
203
+ * console.log(`Processing ${imagePaths.length} images...`)
204
+ *
205
+ * const processingPromises = imagePaths.map(async path => {
206
+ * const img = await loadImage(path)
207
+ * const resized = await resize(img, { width: 800, height: 600 })
208
+ * const compressed = await compress(resized, { quality: 80 })
209
+ * return compressed
210
+ * })
211
+ *
212
+ * // Process 3 images at a time to avoid memory exhaustion
213
+ * const processed = await runBatch(processingPromises, 3)
214
+ *
215
+ * console.log(`✅ Processed ${processed.length} images`)
216
+ * return processed
217
+ * }
218
+ * ```
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * // Real-world: Parallel file uploads with progress tracking
223
+ * async function uploadFilesWithProgress(
224
+ * files: File[]
225
+ * ): Promise<UploadResult[]> {
226
+ * let completed = 0
227
+ *
228
+ * const uploadPromises = files.map(async file => {
229
+ * const result = await uploadToS3(file)
230
+ * completed++
231
+ * console.log(`Progress: ${completed}/${files.length} (${((completed/files.length)*100).toFixed(1)}%)`)
232
+ * return result
233
+ * })
234
+ *
235
+ * // Upload 5 files at a time
236
+ * return await runBatch(uploadPromises, 5)
237
+ * }
238
+ * ```
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * // Real-world: Scraping with politeness delay
243
+ * async function scrapeWebsites(urls: string[]): Promise<ScrapedData[]> {
244
+ * const scrapePromises = urls.map(async url => {
245
+ * const html = await fetch(url).then(r => r.text())
246
+ * const data = parseHTML(html)
247
+ *
248
+ * // Polite delay between requests in same batch
249
+ * await sleep(200)
250
+ *
251
+ * return data
252
+ * })
253
+ *
254
+ * // Only 3 concurrent requests to avoid overwhelming target server
255
+ * return await runBatch(scrapePromises, 3)
256
+ * }
257
+ * ```
258
+ *
259
+ * @see {@link sleep} for adding delays between operations
260
+ * @see {@link handleOperation} for dynamic operation execution
261
+ */
262
+ declare function runBatch<T>(jobs: Promise<T>[], batchSize?: number): Promise<T[]>;
263
+ /**
264
+ * Dynamically executes an operation on a target object by name
265
+ *
266
+ * Invokes methods on objects using string-based operation names. Supports nested
267
+ * method access using 'parent/child' slash notation for organized operation namespacing.
268
+ *
269
+ * Features:
270
+ * - Dynamic method invocation by string name
271
+ * - Nested method access with '/' separator (e.g., 'api/getUser')
272
+ * - Automatic error handling with descriptive messages
273
+ * - Type-safe return value with generics
274
+ *
275
+ * Use cases:
276
+ * - Dynamic API route handlers
277
+ * - Plugin architectures with string-based commands
278
+ * - RPC (Remote Procedure Call) implementations
279
+ * - Command pattern implementations
280
+ * - Configuration-driven operations
281
+ *
282
+ * @param target - Object containing methods to execute
283
+ * @param operation - Method name or 'parent/child' path to execute
284
+ * @param args - Arguments to pass to the operation
285
+ * @returns Promise resolving to operation result
286
+ * @throws {TsHelpersError} If operation doesn't exist on target
287
+ *
288
+ * @example
289
+ * ```typescript
290
+ * // Basic operation execution
291
+ * const api = {
292
+ * getUser: async (id: string) => ({ id, name: 'John' }),
293
+ * createUser: async (data: any) => ({ id: '123', ...data })
294
+ * }
295
+ *
296
+ * const user = await handleOperation<User>(api, 'getUser', 'user-123')
297
+ * // { id: 'user-123', name: 'John' }
298
+ * ```
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * // Nested operations with slash notation
303
+ * const service = {
304
+ * users: {
305
+ * list: async () => [{ id: '1' }, { id: '2' }],
306
+ * create: async (data: any) => ({ id: 'new', ...data }),
307
+ * delete: async (id: string) => ({ success: true })
308
+ * },
309
+ * posts: {
310
+ * list: async () => [{ id: 'post-1' }],
311
+ * create: async (data: any) => ({ id: 'new-post', ...data })
312
+ * }
313
+ * }
314
+ *
315
+ * // Execute nested operation
316
+ * const users = await handleOperation(service, 'users/list')
317
+ * const newUser = await handleOperation(service, 'users/create', { name: 'Alice' })
318
+ * ```
319
+ *
320
+ * @example
321
+ * ```typescript
322
+ * // Real-world: Dynamic API router
323
+ * interface ApiRequest {
324
+ * operation: string
325
+ * params: any[]
326
+ * }
327
+ *
328
+ * const apiHandlers = {
329
+ * user: {
330
+ * get: async (id: string) => db.users.findById(id),
331
+ * create: async (data: UserInput) => db.users.create(data),
332
+ * update: async (id: string, data: Partial<UserInput>) =>
333
+ * db.users.update(id, data),
334
+ * delete: async (id: string) => db.users.delete(id)
335
+ * },
336
+ * product: {
337
+ * search: async (query: string) => db.products.search(query),
338
+ * list: async (page: number) => db.products.list(page)
339
+ * }
340
+ * }
341
+ *
342
+ * async function handleApiRequest(req: ApiRequest): Promise<any> {
343
+ * try {
344
+ * return await handleOperation(
345
+ * apiHandlers,
346
+ * req.operation,
347
+ * ...req.params
348
+ * )
349
+ * } catch (error) {
350
+ * console.error(`Failed to execute ${req.operation}:`, error)
351
+ * throw error
352
+ * }
353
+ * }
354
+ *
355
+ * // Usage
356
+ * await handleApiRequest({ operation: 'user/get', params: ['user-123'] })
357
+ * await handleApiRequest({ operation: 'product/search', params: ['laptop'] })
358
+ * ```
359
+ *
360
+ * @example
361
+ * ```typescript
362
+ * // Real-world: Plugin system with dynamic commands
363
+ * interface Plugin {
364
+ * name: string
365
+ * commands: Record<string, (...args: any[]) => Promise<any>>
366
+ * }
367
+ *
368
+ * class PluginManager {
369
+ * private plugins: Map<string, Plugin> = new Map()
370
+ *
371
+ * register(plugin: Plugin): void {
372
+ * this.plugins.set(plugin.name, plugin)
373
+ * }
374
+ *
375
+ * async executeCommand(
376
+ * pluginName: string,
377
+ * command: string,
378
+ * ...args: any[]
379
+ * ): Promise<any> {
380
+ * const plugin = this.plugins.get(pluginName)
381
+ * if (!plugin) throw new Error(`Plugin ${pluginName} not found`)
382
+ *
383
+ * return handleOperation(plugin.commands, command, ...args)
384
+ * }
385
+ * }
386
+ *
387
+ * // Register plugins
388
+ * const manager = new PluginManager()
389
+ * manager.register({
390
+ * name: 'fileOps',
391
+ * commands: {
392
+ * read: async (path: string) => fs.readFile(path, 'utf-8'),
393
+ * write: async (path: string, content: string) =>
394
+ * fs.writeFile(path, content)
395
+ * }
396
+ * })
397
+ *
398
+ * // Execute plugin commands dynamically
399
+ * await manager.executeCommand('fileOps', 'read', './config.json')
400
+ * ```
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * // Real-world: RPC-style service calls
405
+ * const rpcService = {
406
+ * math: {
407
+ * add: async (a: number, b: number) => a + b,
408
+ * multiply: async (a: number, b: number) => a * b
409
+ * },
410
+ * string: {
411
+ * reverse: async (s: string) => s.split('').reverse().join(''),
412
+ * uppercase: async (s: string) => s.toUpperCase()
413
+ * }
414
+ * }
415
+ *
416
+ * async function rpcCall(method: string, ...params: any[]): Promise<any> {
417
+ * console.log(`RPC Call: ${method}(${params.join(', ')})`)
418
+ * const result = await handleOperation(rpcService, method, ...params)
419
+ * console.log(`RPC Result: ${result}`)
420
+ * return result
421
+ * }
422
+ *
423
+ * await rpcCall('math/add', 5, 3) // RPC Result: 8
424
+ * await rpcCall('string/reverse', 'hello') // RPC Result: olleh
425
+ * ```
426
+ *
427
+ * @example
428
+ * ```typescript
429
+ * // Error handling
430
+ * try {
431
+ * await handleOperation(api, 'nonexistent/method')
432
+ * } catch (error) {
433
+ * console.error(error.message)
434
+ * // "Operation [nonexistent/method] does not exist"
435
+ * console.error(error.code)
436
+ * // TsHelpersErrorCode.INVALID_OPERATION
437
+ * }
438
+ * ```
439
+ *
440
+ * @see {@link TsHelpersError} for error structure
441
+ * @see {@link TsHelpersErrorCode} for error codes
442
+ */
443
+ declare function handleOperation<T>(target: Record<string, any>, operation: string, ...args: any[]): Promise<T>;
444
+
445
+ declare const async_handleOperation: typeof handleOperation;
446
+ declare const async_runBatch: typeof runBatch;
447
+ declare const async_sleep: typeof sleep;
448
+ declare const async_wait: typeof wait;
449
+ declare namespace async {
450
+ export { async_handleOperation as handleOperation, async_runBatch as runBatch, async_sleep as sleep, async_wait as wait };
451
+ }
452
+
453
+ export { async as a, handleOperation as h, runBatch as r, sleep as s, wait as w };
@@ -0,0 +1 @@
1
+ export { h as handleOperation, r as runBatch, s as sleep, w as wait } from './async-C8gvbSG-.js';
@@ -0,0 +1,226 @@
1
+ /**
2
+ * CSV Import/Export utilities
3
+ *
4
+ * Provides reliable CSV operations for both Node.js and Browser environments using PapaParse.
5
+ * Features:
6
+ * - UTF-8 BOM encoding for Excel compatibility
7
+ * - Semicolon delimiter by default (European standard)
8
+ * - Automatic header detection
9
+ * - Dual-mode: filesystem (Node.js) vs download trigger (Browser)
10
+ *
11
+ * @module csv
12
+ */
13
+ /**
14
+ * Exports data as CSV file with UTF-8 BOM encoding
15
+ *
16
+ * Works in both Node.js (writes to filesystem) and Browser (triggers download).
17
+ * Uses PapaParse library for reliable CSV generation with proper escaping and formatting.
18
+ *
19
+ * Features:
20
+ * - UTF-8 BOM prepended (\\ufeff) for Excel compatibility
21
+ * - Semicolon delimiter by default (European/Spanish standard)
22
+ * - Automatic header row from object keys
23
+ * - Custom delimiters and options via PapaParse config
24
+ *
25
+ * Environment behavior:
26
+ * - **Node.js**: Writes file to filesystem at specified path
27
+ * - **Browser**: Triggers automatic download with filename extracted from path
28
+ *
29
+ * @param data - Array of objects or array of arrays to export as CSV
30
+ * @param filePath - File path (Node.js) or download filename (Browser)
31
+ * @param options - PapaParse unparse options (optional)
32
+ * @param options.delimiter - Column separator (default: ';' semicolon)
33
+ * @param options.header - Include header row (default: true)
34
+ * @param options.quotes - Quote all fields (default: false)
35
+ * @param options.newline - Line ending (default: '\\r\\n')
36
+ * @returns Promise that resolves when export completes
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Basic export - Array of objects
41
+ * const users = [
42
+ * { name: 'Alice', age: 30, city: 'Madrid' },
43
+ * { name: 'Bob', age: 25, city: 'Barcelona' },
44
+ * { name: 'Carlos', age: 35, city: 'Valencia' }
45
+ * ]
46
+ *
47
+ * // Node.js - Write to file
48
+ * await exportCSV(users, './reports/users.csv')
49
+ * // Creates: ./reports/users.csv with BOM and semicolon delimiter
50
+ *
51
+ * // Browser - Trigger download
52
+ * await exportCSV(users, 'users.csv')
53
+ * // Downloads: users.csv to browser's download folder
54
+ *
55
+ * // Custom delimiter (comma for international)
56
+ * await exportCSV(users, 'users_intl.csv', { delimiter: ',' })
57
+ * ```
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // Array of arrays (no header auto-detection)
62
+ * const matrix = [
63
+ * ['Name', 'Age', 'City'], // Header row
64
+ * ['Alice', 30, 'Madrid'],
65
+ * ['Bob', 25, 'Barcelona']
66
+ * ]
67
+ * await exportCSV(matrix, 'matrix.csv')
68
+ *
69
+ * // Without header row
70
+ * const data = [['A1', 'B1'], ['A2', 'B2']]
71
+ * await exportCSV(data, 'no_header.csv', { header: false })
72
+ * ```
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * // Real-world: Export sales report
77
+ * async function exportSalesReport(sales: Sale[]) {
78
+ * const reportData = sales.map(sale => ({
79
+ * Fecha: formatDate(sale.date),
80
+ * Cliente: sale.customerName,
81
+ * Producto: sale.productName,
82
+ * Cantidad: sale.quantity,
83
+ * Total: `${sale.total.toFixed(2)}€`
84
+ * }))
85
+ *
86
+ * const filename = `ventas_${new Date().toISOString().split('T')[0]}.csv`
87
+ * await exportCSV(reportData, filename)
88
+ * }
89
+ * ```
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * // Custom PapaParse options
94
+ * await exportCSV(data, 'quotes.csv', {
95
+ * delimiter: ',',
96
+ * quotes: true, // Quote all fields
97
+ * quoteChar: '"',
98
+ * escapeChar: '"',
99
+ * newline: '\\n' // Unix line endings
100
+ * })
101
+ * ```
102
+ *
103
+ * @throws {Error} If file write fails in Node.js
104
+ * @see {@link importCSV} for importing CSV files
105
+ * @see {@link https://www.papaparse.com/docs#unparse PapaParse Unparse Documentation}
106
+ */
107
+ declare function exportCSV(data: any[], filePath: string, options?: any): Promise<void>;
108
+ /**
109
+ * Imports CSV file and parses it to array of objects
110
+ *
111
+ * Reads CSV file from filesystem (Node.js only) and parses using PapaParse.
112
+ * Automatically detects headers and converts rows to objects.
113
+ *
114
+ * Features:
115
+ * - Automatic header detection from first row
116
+ * - Semicolon delimiter by default (European standard)
117
+ * - Empty line skipping
118
+ * - Type inference for numbers and booleans
119
+ * - UTF-8 BOM handling
120
+ *
121
+ * ⚠️ BROWSER LIMITATION: File reading from filesystem is not supported in browsers
122
+ * for security reasons. For browser file uploads, use `readFileAsText()` with a File object
123
+ * obtained from an input[type="file"] element.
124
+ *
125
+ * @param filePath - Path to CSV file (Node.js only)
126
+ * @param options - PapaParse parse options (optional)
127
+ * @param options.delimiter - Column separator (default: ';' semicolon)
128
+ * @param options.header - Parse first row as headers (default: true)
129
+ * @param options.skipEmptyLines - Skip empty rows (default: true)
130
+ * @param options.dynamicTyping - Convert numeric/boolean values (default: false)
131
+ * @returns Promise<Array<Object>> Array of objects with keys from header row
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * // Basic import - Node.js only
136
+ * const users = await importCSV('./data/users.csv')
137
+ * // Returns: [
138
+ * // { name: 'Alice', age: '30', city: 'Madrid' },
139
+ * // { name: 'Bob', age: '25', city: 'Barcelona' }
140
+ * // ]
141
+ *
142
+ * // Custom delimiter (comma)
143
+ * const intlData = await importCSV('./data/users_intl.csv', {
144
+ * delimiter: ','
145
+ * })
146
+ *
147
+ * // With type conversion
148
+ * const typed = await importCSV('./data/sales.csv', {
149
+ * dynamicTyping: true // Converts '123' → 123, 'true' → true
150
+ * })
151
+ * // Returns: { quantity: 10, total: 299.99, active: true }
152
+ * ```
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * // Real-world: Import and process sales data
157
+ * async function importSalesReport(filePath: string) {
158
+ * try {
159
+ * const sales = await importCSV(filePath, {
160
+ * delimiter: ';',
161
+ * dynamicTyping: true,
162
+ * skipEmptyLines: true
163
+ * })
164
+ *
165
+ * // Process imported data
166
+ * const totalSales = sales.reduce((sum, sale) =>
167
+ * sum + (sale.total || 0), 0
168
+ * )
169
+ *
170
+ * console.log(`Imported ${sales.length} sales, total: €${totalSales}`)
171
+ * return sales
172
+ * } catch (error) {
173
+ * console.error('Failed to import CSV:', error)
174
+ * throw error
175
+ * }
176
+ * }
177
+ * ```
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * // Browser alternative using File API
182
+ * // HTML: <input type="file" id="csvFile" accept=".csv">
183
+ *
184
+ * document.getElementById('csvFile').addEventListener('change', async (e) => {
185
+ * const file = e.target.files[0]
186
+ *
187
+ * // Read file content
188
+ * const content = await readFileAsText(file)
189
+ *
190
+ * // Parse with PapaParse
191
+ * const parsed = Papa.parse(content, {
192
+ * header: true,
193
+ * delimiter: ';',
194
+ * skipEmptyLines: true
195
+ * })
196
+ *
197
+ * const data = parsed.data
198
+ * console.log('Imported data:', data)
199
+ * })
200
+ * ```
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * // Handle parsing errors
205
+ * const result = await importCSV('./malformed.csv')
206
+ * .catch(error => {
207
+ * if (error.message.includes('not supported in browser')) {
208
+ * console.error('Use File API for browser uploads')
209
+ * } else if (error.code === 'ENOENT') {
210
+ * console.error('File not found')
211
+ * } else {
212
+ * console.error('CSV parsing failed:', error)
213
+ * }
214
+ * return [] // Return empty array as fallback
215
+ * })
216
+ * ```
217
+ *
218
+ * @throws {Error} 'CSV import not supported in browser' when called in browser environment
219
+ * @throws {Error} File system errors (ENOENT, EACCES, etc.) in Node.js
220
+ * @see {@link exportCSV} for exporting CSV files
221
+ * @see {@link readFileAsText} for browser file reading
222
+ * @see {@link https://www.papaparse.com/docs#parse PapaParse Parse Documentation}
223
+ */
224
+ declare function importCSV(filePath: string, options?: any): Promise<any[]>;
225
+
226
+ export { exportCSV, importCSV };