jtcsv 3.0.0 → 3.1.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 (258) hide show
  1. package/README.md +205 -146
  2. package/bin/jtcsv.ts +280 -202
  3. package/browser.d.ts +142 -0
  4. package/dist/benchmark.js +446 -0
  5. package/dist/benchmark.js.map +1 -0
  6. package/dist/bin/jtcsv.js +1940 -0
  7. package/dist/bin/jtcsv.js.map +1 -0
  8. package/dist/csv-to-json.js +1261 -0
  9. package/dist/csv-to-json.js.map +1 -0
  10. package/dist/errors.js +291 -0
  11. package/dist/errors.js.map +1 -0
  12. package/dist/eslint.config.js +147 -0
  13. package/dist/eslint.config.js.map +1 -0
  14. package/dist/index-core.js +95 -0
  15. package/dist/index-core.js.map +1 -0
  16. package/dist/index.js +93 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/json-save.js +229 -0
  19. package/dist/json-save.js.map +1 -0
  20. package/dist/json-to-csv.js +576 -0
  21. package/dist/json-to-csv.js.map +1 -0
  22. package/dist/jtcsv-core.cjs.js +336 -7
  23. package/dist/jtcsv-core.cjs.js.map +1 -1
  24. package/dist/jtcsv-core.esm.js +336 -7
  25. package/dist/jtcsv-core.esm.js.map +1 -1
  26. package/dist/jtcsv-core.umd.js +336 -7
  27. package/dist/jtcsv-core.umd.js.map +1 -1
  28. package/dist/jtcsv-full.cjs.js +336 -7
  29. package/dist/jtcsv-full.cjs.js.map +1 -1
  30. package/dist/jtcsv-full.esm.js +336 -7
  31. package/dist/jtcsv-full.esm.js.map +1 -1
  32. package/dist/jtcsv-full.umd.js +336 -7
  33. package/dist/jtcsv-full.umd.js.map +1 -1
  34. package/dist/jtcsv-workers.esm.js +9 -0
  35. package/dist/jtcsv-workers.esm.js.map +1 -1
  36. package/dist/jtcsv-workers.umd.js +9 -0
  37. package/dist/jtcsv-workers.umd.js.map +1 -1
  38. package/dist/jtcsv.cjs.js +1998 -2092
  39. package/dist/jtcsv.cjs.js.map +1 -1
  40. package/dist/jtcsv.esm.js +1994 -2092
  41. package/dist/jtcsv.esm.js.map +1 -1
  42. package/dist/jtcsv.umd.js +2157 -2251
  43. package/dist/jtcsv.umd.js.map +1 -1
  44. package/dist/plugins/express-middleware/index.js +350 -0
  45. package/dist/plugins/express-middleware/index.js.map +1 -0
  46. package/dist/plugins/fastify-plugin/index.js +315 -0
  47. package/dist/plugins/fastify-plugin/index.js.map +1 -0
  48. package/dist/plugins/hono/index.js +111 -0
  49. package/dist/plugins/hono/index.js.map +1 -0
  50. package/dist/plugins/nestjs/index.js +192 -0
  51. package/dist/plugins/nestjs/index.js.map +1 -0
  52. package/dist/plugins/nuxt/index.js +53 -0
  53. package/dist/plugins/nuxt/index.js.map +1 -0
  54. package/dist/plugins/remix/index.js +133 -0
  55. package/dist/plugins/remix/index.js.map +1 -0
  56. package/dist/plugins/sveltekit/index.js +155 -0
  57. package/dist/plugins/sveltekit/index.js.map +1 -0
  58. package/dist/plugins/trpc/index.js +136 -0
  59. package/dist/plugins/trpc/index.js.map +1 -0
  60. package/dist/run-demo.js +49 -0
  61. package/dist/run-demo.js.map +1 -0
  62. package/dist/src/browser/browser-functions.js +193 -0
  63. package/dist/src/browser/browser-functions.js.map +1 -0
  64. package/dist/src/browser/core.js +123 -0
  65. package/dist/src/browser/core.js.map +1 -0
  66. package/dist/src/browser/csv-to-json-browser.js +353 -0
  67. package/dist/src/browser/csv-to-json-browser.js.map +1 -0
  68. package/dist/src/browser/errors-browser.js +219 -0
  69. package/dist/src/browser/errors-browser.js.map +1 -0
  70. package/dist/src/browser/extensions/plugins.js +106 -0
  71. package/dist/src/browser/extensions/plugins.js.map +1 -0
  72. package/dist/src/browser/extensions/workers.js +66 -0
  73. package/dist/src/browser/extensions/workers.js.map +1 -0
  74. package/dist/src/browser/index.js +140 -0
  75. package/dist/src/browser/index.js.map +1 -0
  76. package/dist/src/browser/json-to-csv-browser.js +225 -0
  77. package/dist/src/browser/json-to-csv-browser.js.map +1 -0
  78. package/dist/src/browser/streams.js +340 -0
  79. package/dist/src/browser/streams.js.map +1 -0
  80. package/dist/src/browser/workers/csv-parser.worker.js +264 -0
  81. package/dist/src/browser/workers/csv-parser.worker.js.map +1 -0
  82. package/dist/src/browser/workers/worker-pool.js +338 -0
  83. package/dist/src/browser/workers/worker-pool.js.map +1 -0
  84. package/dist/src/core/delimiter-cache.js +196 -0
  85. package/dist/src/core/delimiter-cache.js.map +1 -0
  86. package/dist/src/core/node-optimizations.js +279 -0
  87. package/dist/src/core/node-optimizations.js.map +1 -0
  88. package/dist/src/core/plugin-system.js +399 -0
  89. package/dist/src/core/plugin-system.js.map +1 -0
  90. package/dist/src/core/transform-hooks.js +348 -0
  91. package/dist/src/core/transform-hooks.js.map +1 -0
  92. package/dist/src/engines/fast-path-engine-new.js +262 -0
  93. package/dist/src/engines/fast-path-engine-new.js.map +1 -0
  94. package/dist/src/engines/fast-path-engine.js +671 -0
  95. package/dist/src/engines/fast-path-engine.js.map +1 -0
  96. package/dist/src/errors.js +18 -0
  97. package/dist/src/errors.js.map +1 -0
  98. package/dist/src/formats/ndjson-parser.js +332 -0
  99. package/dist/src/formats/ndjson-parser.js.map +1 -0
  100. package/dist/src/formats/tsv-parser.js +230 -0
  101. package/dist/src/formats/tsv-parser.js.map +1 -0
  102. package/dist/src/index-with-plugins.js +259 -0
  103. package/dist/src/index-with-plugins.js.map +1 -0
  104. package/dist/src/types/index.js +3 -0
  105. package/dist/src/types/index.js.map +1 -0
  106. package/dist/src/utils/bom-utils.js +267 -0
  107. package/dist/src/utils/bom-utils.js.map +1 -0
  108. package/dist/src/utils/encoding-support.js +77 -0
  109. package/dist/src/utils/encoding-support.js.map +1 -0
  110. package/dist/src/utils/schema-validator.js +609 -0
  111. package/dist/src/utils/schema-validator.js.map +1 -0
  112. package/dist/src/utils/transform-loader.js +281 -0
  113. package/dist/src/utils/transform-loader.js.map +1 -0
  114. package/dist/src/utils/validators.js +40 -0
  115. package/dist/src/utils/validators.js.map +1 -0
  116. package/dist/src/utils/zod-adapter.js +144 -0
  117. package/dist/src/utils/zod-adapter.js.map +1 -0
  118. package/{src → dist/src}/web-server/index.js +251 -286
  119. package/dist/src/web-server/index.js.map +1 -0
  120. package/dist/src/workers/csv-multithreaded.js +211 -0
  121. package/dist/src/workers/csv-multithreaded.js.map +1 -0
  122. package/dist/src/workers/csv-parser.worker.js +179 -0
  123. package/dist/src/workers/csv-parser.worker.js.map +1 -0
  124. package/dist/src/workers/worker-pool.js +228 -0
  125. package/dist/src/workers/worker-pool.js.map +1 -0
  126. package/dist/stream-csv-to-json.js +664 -0
  127. package/dist/stream-csv-to-json.js.map +1 -0
  128. package/dist/stream-json-to-csv.js +389 -0
  129. package/dist/stream-json-to-csv.js.map +1 -0
  130. package/examples/advanced/conditional-transformations.ts +2 -2
  131. package/examples/advanced/performance-optimization.ts +2 -2
  132. package/examples/cli-advanced-usage.md +2 -0
  133. package/examples/cli-tool.ts +1 -1
  134. package/examples/large-dataset-example.ts +2 -2
  135. package/examples/simple-usage.ts +2 -2
  136. package/examples/streaming-example.ts +1 -1
  137. package/index.d.ts +186 -15
  138. package/package.json +243 -305
  139. package/plugins.d.ts +37 -0
  140. package/schema.d.ts +103 -0
  141. package/src/browser/csv-to-json-browser.ts +233 -3
  142. package/src/browser/errors-browser.ts +45 -28
  143. package/src/browser/json-to-csv-browser.ts +81 -5
  144. package/src/browser/streams.ts +73 -6
  145. package/src/core/delimiter-cache.ts +21 -11
  146. package/src/core/plugin-system.ts +343 -155
  147. package/src/core/transform-hooks.ts +20 -12
  148. package/src/engines/fast-path-engine.ts +48 -32
  149. package/src/errors.ts +1 -72
  150. package/src/formats/ndjson-parser.ts +6 -0
  151. package/src/formats/tsv-parser.ts +6 -0
  152. package/src/types/index.ts +21 -1
  153. package/src/utils/validators.ts +35 -0
  154. package/src/web-server/index.ts +1 -1
  155. package/bin/jtcsv.js +0 -2532
  156. package/csv-to-json.js +0 -711
  157. package/errors.js +0 -394
  158. package/examples/advanced/conditional-transformations.js +0 -446
  159. package/examples/advanced/csv-parser.worker.js +0 -89
  160. package/examples/advanced/nested-objects-example.js +0 -306
  161. package/examples/advanced/performance-optimization.js +0 -504
  162. package/examples/advanced/run-demo-server.js +0 -116
  163. package/examples/cli-batch-processing.js +0 -38
  164. package/examples/cli-tool.js +0 -183
  165. package/examples/error-handling.js +0 -338
  166. package/examples/express-api.js +0 -164
  167. package/examples/large-dataset-example.js +0 -182
  168. package/examples/ndjson-processing.js +0 -434
  169. package/examples/plugin-excel-exporter.js +0 -406
  170. package/examples/schema-validation.js +0 -640
  171. package/examples/simple-usage.js +0 -282
  172. package/examples/streaming-example.js +0 -418
  173. package/examples/web-workers-advanced.js +0 -28
  174. package/index.js +0 -82
  175. package/json-save.js +0 -255
  176. package/json-to-csv.js +0 -668
  177. package/plugins/README.md +0 -91
  178. package/plugins/express-middleware/README.md +0 -83
  179. package/plugins/express-middleware/example.js +0 -135
  180. package/plugins/express-middleware/example.ts +0 -135
  181. package/plugins/express-middleware/index.d.ts +0 -114
  182. package/plugins/express-middleware/index.js +0 -512
  183. package/plugins/express-middleware/index.ts +0 -557
  184. package/plugins/express-middleware/package.json +0 -52
  185. package/plugins/fastify-plugin/index.js +0 -404
  186. package/plugins/fastify-plugin/index.ts +0 -443
  187. package/plugins/fastify-plugin/package.json +0 -55
  188. package/plugins/hono/README.md +0 -28
  189. package/plugins/hono/index.d.ts +0 -12
  190. package/plugins/hono/index.js +0 -36
  191. package/plugins/hono/index.ts +0 -226
  192. package/plugins/hono/package.json +0 -35
  193. package/plugins/nestjs/README.md +0 -35
  194. package/plugins/nestjs/index.d.ts +0 -25
  195. package/plugins/nestjs/index.js +0 -77
  196. package/plugins/nestjs/index.ts +0 -201
  197. package/plugins/nestjs/package.json +0 -37
  198. package/plugins/nextjs-api/README.md +0 -57
  199. package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
  200. package/plugins/nextjs-api/examples/ConverterComponent.tsx +0 -386
  201. package/plugins/nextjs-api/examples/api-convert.js +0 -67
  202. package/plugins/nextjs-api/examples/api-convert.ts +0 -67
  203. package/plugins/nextjs-api/index.js +0 -387
  204. package/plugins/nextjs-api/index.tsx +0 -339
  205. package/plugins/nextjs-api/package.json +0 -63
  206. package/plugins/nextjs-api/route.js +0 -370
  207. package/plugins/nextjs-api/route.ts +0 -370
  208. package/plugins/nuxt/README.md +0 -24
  209. package/plugins/nuxt/index.js +0 -21
  210. package/plugins/nuxt/index.ts +0 -94
  211. package/plugins/nuxt/package.json +0 -35
  212. package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
  213. package/plugins/nuxt/runtime/composables/useJtcsv.ts +0 -100
  214. package/plugins/nuxt/runtime/plugin.js +0 -6
  215. package/plugins/nuxt/runtime/plugin.ts +0 -71
  216. package/plugins/remix/README.md +0 -26
  217. package/plugins/remix/index.d.ts +0 -16
  218. package/plugins/remix/index.js +0 -62
  219. package/plugins/remix/index.ts +0 -260
  220. package/plugins/remix/package.json +0 -35
  221. package/plugins/sveltekit/README.md +0 -28
  222. package/plugins/sveltekit/index.d.ts +0 -17
  223. package/plugins/sveltekit/index.js +0 -54
  224. package/plugins/sveltekit/index.ts +0 -301
  225. package/plugins/sveltekit/package.json +0 -33
  226. package/plugins/trpc/README.md +0 -25
  227. package/plugins/trpc/index.d.ts +0 -7
  228. package/plugins/trpc/index.js +0 -32
  229. package/plugins/trpc/index.ts +0 -267
  230. package/plugins/trpc/package.json +0 -34
  231. package/src/browser/browser-functions.js +0 -219
  232. package/src/browser/core.js +0 -92
  233. package/src/browser/csv-to-json-browser.js +0 -722
  234. package/src/browser/errors-browser.js +0 -212
  235. package/src/browser/extensions/plugins.js +0 -92
  236. package/src/browser/extensions/workers.js +0 -39
  237. package/src/browser/index.js +0 -113
  238. package/src/browser/json-to-csv-browser.js +0 -319
  239. package/src/browser/streams.js +0 -403
  240. package/src/browser/workers/csv-parser.worker.js +0 -377
  241. package/src/browser/workers/worker-pool.js +0 -527
  242. package/src/core/delimiter-cache.js +0 -200
  243. package/src/core/node-optimizations.js +0 -408
  244. package/src/core/plugin-system.js +0 -494
  245. package/src/core/transform-hooks.js +0 -350
  246. package/src/engines/fast-path-engine-new.js +0 -338
  247. package/src/engines/fast-path-engine.js +0 -844
  248. package/src/errors.js +0 -26
  249. package/src/formats/ndjson-parser.js +0 -467
  250. package/src/formats/tsv-parser.js +0 -339
  251. package/src/index-with-plugins.js +0 -378
  252. package/src/utils/bom-utils.js +0 -259
  253. package/src/utils/encoding-support.js +0 -124
  254. package/src/utils/schema-validator.js +0 -594
  255. package/src/utils/transform-loader.js +0 -205
  256. package/src/utils/zod-adapter.js +0 -170
  257. package/stream-csv-to-json.js +0 -560
  258. package/stream-json-to-csv.js +0 -465
@@ -1,527 +0,0 @@
1
- // Worker Pool для параллельной обработки CSV
2
- // Использует Comlink для простой коммуникации с Web Workers
3
-
4
- import { ValidationError, ConfigurationError } from '../errors-browser.js';
5
-
6
- // Проверка поддержки Web Workers
7
- const WORKERS_SUPPORTED = typeof Worker !== 'undefined';
8
-
9
- function isTransferableBuffer(value) {
10
- if (!(value instanceof ArrayBuffer)) {
11
- return false;
12
- }
13
- if (typeof SharedArrayBuffer !== 'undefined' && value instanceof SharedArrayBuffer) {
14
- return false;
15
- }
16
- return true;
17
- }
18
-
19
- function collectTransferables(args) {
20
- const transferables = [];
21
-
22
- const collectFromValue = (value) => {
23
- if (!value) {
24
- return;
25
- }
26
- if (isTransferableBuffer(value)) {
27
- transferables.push(value);
28
- return;
29
- }
30
- if (ArrayBuffer.isView(value) && isTransferableBuffer(value.buffer)) {
31
- transferables.push(value.buffer);
32
- return;
33
- }
34
- if (Array.isArray(value)) {
35
- value.forEach(collectFromValue);
36
- }
37
- };
38
-
39
- args.forEach(collectFromValue);
40
- return transferables.length ? transferables : null;
41
- }
42
-
43
- /**
44
- * Опции для Worker Pool
45
- * @typedef {Object} WorkerPoolOptions
46
- * @property {number} [workerCount=4] - Количество workers в pool
47
- * @property {number} [maxQueueSize=100] - Максимальный размер очереди задач
48
- * @property {boolean} [autoScale=true] - Автоматическое масштабирование pool
49
- * @property {number} [idleTimeout=60000] - Таймаут простоя worker (мс)
50
- */
51
-
52
- /**
53
- * Статистика Worker Pool
54
- * @typedef {Object} WorkerPoolStats
55
- * @property {number} totalWorkers - Всего workers
56
- * @property {number} activeWorkers - Активные workers
57
- * @property {number} idleWorkers - Простаивающие workers
58
- * @property {number} queueSize - Размер очереди
59
- * @property {number} tasksCompleted - Завершенные задачи
60
- * @property {number} tasksFailed - Неудачные задачи
61
- */
62
-
63
- /**
64
- * Прогресс обработки задачи
65
- * @typedef {Object} TaskProgress
66
- * @property {number} processed - Обработано элементов
67
- * @property {number} total - Всего элементов
68
- * @property {number} percentage - Процент выполнения
69
- * @property {number} speed - Скорость обработки (элементов/сек)
70
- */
71
-
72
- /**
73
- * Worker Pool для параллельной обработки CSV
74
- */
75
- export class WorkerPool {
76
- /**
77
- * Создает новый Worker Pool
78
- * @param {string} workerScript - URL скрипта worker
79
- * @param {WorkerPoolOptions} [options] - Опции pool
80
- */
81
- constructor(workerScript, options = {}) {
82
- if (!WORKERS_SUPPORTED) {
83
- throw new ValidationError('Web Workers не поддерживаются в этом браузере');
84
- }
85
-
86
- this.workerScript = workerScript;
87
- this.options = {
88
- workerCount: 4,
89
- maxQueueSize: 100,
90
- autoScale: true,
91
- idleTimeout: 60000,
92
- ...options
93
- };
94
-
95
- this.workers = [];
96
- this.taskQueue = [];
97
- this.activeTasks = new Map();
98
- this.stats = {
99
- totalWorkers: 0,
100
- activeWorkers: 0,
101
- idleWorkers: 0,
102
- queueSize: 0,
103
- tasksCompleted: 0,
104
- tasksFailed: 0
105
- };
106
-
107
- this.initializeWorkers();
108
- }
109
-
110
- /**
111
- * Инициализация workers
112
- * @private
113
- */
114
- initializeWorkers() {
115
- const { workerCount } = this.options;
116
-
117
- for (let i = 0; i < workerCount; i++) {
118
- this.createWorker();
119
- }
120
-
121
- this.updateStats();
122
- }
123
-
124
- /**
125
- * Создает нового worker
126
- * @private
127
- */
128
- createWorker() {
129
- try {
130
- const worker = new Worker(this.workerScript, { type: 'module' });
131
-
132
- worker.id = `worker-${this.workers.length}`;
133
- worker.status = 'idle';
134
- worker.lastUsed = Date.now();
135
- worker.taskId = null;
136
-
137
- // Обработчики событий
138
- worker.onmessage = (event) => this.handleWorkerMessage(worker, event);
139
- worker.onerror = (error) => this.handleWorkerError(worker, error);
140
- worker.onmessageerror = (error) => this.handleWorkerMessageError(worker, error);
141
-
142
- this.workers.push(worker);
143
- this.stats.totalWorkers++;
144
- this.stats.idleWorkers++;
145
-
146
- return worker;
147
- } catch (error) {
148
- throw new ConfigurationError(`Не удалось создать worker: ${error.message}`);
149
- }
150
- }
151
-
152
- /**
153
- * Обработка сообщений от worker
154
- * @private
155
- */
156
- handleWorkerMessage(worker, event) {
157
- const { data } = event;
158
-
159
- if (data.type === 'PROGRESS') {
160
- this.handleProgress(worker, data);
161
- } else if (data.type === 'RESULT') {
162
- this.handleResult(worker, data);
163
- } else if (data.type === 'ERROR') {
164
- this.handleWorkerTaskError(worker, data);
165
- }
166
- }
167
-
168
- /**
169
- * Обработка прогресса задачи
170
- * @private
171
- */
172
- handleProgress(worker, progressData) {
173
- const taskId = worker.taskId;
174
- if (taskId && this.activeTasks.has(taskId)) {
175
- const task = this.activeTasks.get(taskId);
176
- if (task.onProgress) {
177
- task.onProgress({
178
- processed: progressData.processed,
179
- total: progressData.total,
180
- percentage: (progressData.processed / progressData.total) * 100,
181
- speed: progressData.speed || 0
182
- });
183
- }
184
- }
185
- }
186
-
187
- /**
188
- * Обработка результата задачи
189
- * @private
190
- */
191
- handleResult(worker, resultData) {
192
- const taskId = worker.taskId;
193
- if (taskId && this.activeTasks.has(taskId)) {
194
- const task = this.activeTasks.get(taskId);
195
-
196
- // Освобождение worker
197
- worker.status = 'idle';
198
- worker.lastUsed = Date.now();
199
- worker.taskId = null;
200
- this.stats.activeWorkers--;
201
- this.stats.idleWorkers++;
202
-
203
- // Завершение задачи
204
- task.resolve(resultData.data);
205
- this.activeTasks.delete(taskId);
206
- this.stats.tasksCompleted++;
207
-
208
- // Обработка следующей задачи в очереди
209
- this.processQueue();
210
- this.updateStats();
211
- }
212
- }
213
-
214
- /**
215
- * Обработка ошибки задачи
216
- * @private
217
- */
218
- handleWorkerTaskError(worker, errorData) {
219
- const taskId = worker.taskId;
220
- if (taskId && this.activeTasks.has(taskId)) {
221
- const task = this.activeTasks.get(taskId);
222
-
223
- // Освобождение worker
224
- worker.status = 'idle';
225
- worker.lastUsed = Date.now();
226
- worker.taskId = null;
227
- this.stats.activeWorkers--;
228
- this.stats.idleWorkers++;
229
-
230
- // Завершение с ошибкой
231
- const workerError = new Error(errorData.message || 'Ошибка в worker');
232
- if (errorData.code) {
233
- workerError.code = errorData.code;
234
- }
235
- if (errorData.details) {
236
- workerError.details = errorData.details;
237
- }
238
- task.reject(workerError);
239
- this.activeTasks.delete(taskId);
240
- this.stats.tasksFailed++;
241
-
242
- // Обработка следующей задачи
243
- this.processQueue();
244
- this.updateStats();
245
- }
246
- }
247
-
248
- /**
249
- * Обработка ошибок worker
250
- * @private
251
- */
252
- handleWorkerError(worker, error) {
253
- console.error(`Worker ${worker.id} error:`, error);
254
-
255
- // Перезапуск worker
256
- this.restartWorker(worker);
257
- }
258
-
259
- /**
260
- * Обработка ошибок сообщений
261
- * @private
262
- */
263
- handleWorkerMessageError(worker, error) {
264
- console.error(`Worker ${worker.id} message error:`, error);
265
- }
266
-
267
- /**
268
- * Перезапуск worker
269
- * @private
270
- */
271
- restartWorker(worker) {
272
- const index = this.workers.indexOf(worker);
273
- if (index !== -1) {
274
- // Завершение старого worker
275
- worker.terminate();
276
-
277
- // Удаление из статистики
278
- if (worker.status === 'active') {
279
- this.stats.activeWorkers--;
280
- } else {
281
- this.stats.idleWorkers--;
282
- }
283
- this.stats.totalWorkers--;
284
-
285
- // Создание нового worker
286
- const newWorker = this.createWorker();
287
- this.workers[index] = newWorker;
288
-
289
- // Перезапуск задачи если была активна
290
- if (worker.taskId && this.activeTasks.has(worker.taskId)) {
291
- const task = this.activeTasks.get(worker.taskId);
292
- this.executeTask(newWorker, task);
293
- }
294
- }
295
- }
296
-
297
- /**
298
- * Выполнение задачи на worker
299
- * @private
300
- */
301
- executeTask(worker, task) {
302
- worker.status = 'active';
303
- worker.lastUsed = Date.now();
304
- worker.taskId = task.id;
305
-
306
- this.stats.idleWorkers--;
307
- this.stats.activeWorkers++;
308
-
309
- // Отправка задачи в worker
310
- const payload = {
311
- type: 'EXECUTE',
312
- taskId: task.id,
313
- method: task.method,
314
- args: task.args,
315
- options: task.options
316
- };
317
-
318
- if (task.transferList && task.transferList.length) {
319
- worker.postMessage(payload, task.transferList);
320
- } else {
321
- worker.postMessage(payload);
322
- }
323
- }
324
-
325
- /**
326
- * Обработка очереди задач
327
- * @private
328
- */
329
- processQueue() {
330
- if (this.taskQueue.length === 0) {
331
- return;
332
- }
333
-
334
- while (this.taskQueue.length > 0) {
335
- const idleWorker = this.workers.find(w => w.status === 'idle');
336
- if (!idleWorker) {
337
- if (this.options.autoScale && this.workers.length < this.options.maxQueueSize) {
338
- this.createWorker();
339
- continue;
340
- }
341
- break;
342
- }
343
-
344
- const task = this.taskQueue.shift();
345
- this.stats.queueSize--;
346
- this.executeTask(idleWorker, task);
347
- }
348
-
349
- this.updateStats();
350
- }
351
-
352
- /**
353
- * Обновление статистики
354
- * @private
355
- */
356
- updateStats() {
357
- this.stats.queueSize = this.taskQueue.length;
358
- }
359
-
360
- /**
361
- * Выполнение задачи через pool
362
- * @param {string} method - Метод для вызова в worker
363
- * @param {Array} args - Аргументы метода
364
- * @param {Object} [options] - Опции задачи
365
- * @param {Function} [onProgress] - Callback прогресса
366
- * @returns {Promise<any>} Результат выполнения
367
- */
368
- async exec(method, args = [], options = {}, onProgress = null) {
369
- return new Promise((resolve, reject) => {
370
- // Проверка размера очереди
371
- if (this.taskQueue.length >= this.options.maxQueueSize) {
372
- reject(new Error('Очередь задач переполнена'));
373
- return;
374
- }
375
-
376
- // Создание задачи
377
- const taskId = `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
378
- const { transfer, ...taskOptions } = options || {};
379
- const transferList = transfer || collectTransferables(args);
380
- const task = {
381
- id: taskId,
382
- method,
383
- args,
384
- options: taskOptions,
385
- transferList,
386
- onProgress,
387
- resolve,
388
- reject,
389
- createdAt: Date.now()
390
- };
391
-
392
- // Добавление в очередь
393
- this.taskQueue.push(task);
394
- this.stats.queueSize++;
395
-
396
- // Запуск обработки очереди
397
- this.processQueue();
398
- this.updateStats();
399
- });
400
- }
401
-
402
- /**
403
- * Получение статистики pool
404
- * @returns {WorkerPoolStats} Статистика
405
- */
406
- getStats() {
407
- return { ...this.stats };
408
- }
409
-
410
- /**
411
- * Очистка простаивающих workers
412
- */
413
- cleanupIdleWorkers() {
414
- const now = Date.now();
415
- const { idleTimeout } = this.options;
416
-
417
- for (let i = this.workers.length - 1; i >= 0; i--) {
418
- const worker = this.workers[i];
419
- if (worker.status === 'idle' && (now - worker.lastUsed) > idleTimeout) {
420
- // Сохранение минимального количества workers
421
- if (this.workers.length > 1) {
422
- worker.terminate();
423
- this.workers.splice(i, 1);
424
- this.stats.totalWorkers--;
425
- this.stats.idleWorkers--;
426
- }
427
- }
428
- }
429
- }
430
-
431
- /**
432
- * Завершение всех workers
433
- */
434
- terminate() {
435
- this.workers.forEach(worker => {
436
- worker.terminate();
437
- });
438
-
439
- this.workers = [];
440
- this.taskQueue = [];
441
- this.activeTasks.clear();
442
-
443
- // Сброс статистики
444
- this.stats = {
445
- totalWorkers: 0,
446
- activeWorkers: 0,
447
- idleWorkers: 0,
448
- queueSize: 0,
449
- tasksCompleted: 0,
450
- tasksFailed: 0
451
- };
452
- }
453
- }
454
-
455
- /**
456
- * Создает Worker Pool для обработки CSV
457
- * @param {WorkerPoolOptions} [options] - Опции pool
458
- * @returns {WorkerPool} Worker Pool
459
- */
460
- export function createWorkerPool(options = {}) {
461
- // Используем встроенный worker скрипт
462
- const workerScript = new URL('./csv-parser.worker.js', import.meta.url).href;
463
- return new WorkerPool(workerScript, options);
464
- }
465
-
466
- /**
467
- * Парсит CSV с использованием Web Workers
468
- * @param {string|File} csvInput - CSV строка или File объект
469
- * @param {Object} [options] - Опции парсинга
470
- * @param {Function} [onProgress] - Callback прогресса
471
- * @returns {Promise<Array<Object>>} JSON данные
472
- */
473
- export async function parseCSVWithWorker(csvInput, options = {}, onProgress = null) {
474
- // Создание pool если нужно
475
- if (!parseCSVWithWorker.pool) {
476
- parseCSVWithWorker.pool = createWorkerPool();
477
- }
478
-
479
- const pool = parseCSVWithWorker.pool;
480
-
481
- // Подготовка CSV строки
482
- // ?????????? CSV ??????
483
- let csvPayload = csvInput;
484
- let transfer = null;
485
-
486
- if (csvInput instanceof File) {
487
- const buffer = await readFileAsArrayBuffer(csvInput);
488
- csvPayload = new Uint8Array(buffer);
489
- transfer = [buffer];
490
- } else if (csvInput instanceof ArrayBuffer) {
491
- csvPayload = csvInput;
492
- transfer = [csvInput];
493
- } else if (ArrayBuffer.isView(csvInput)) {
494
- csvPayload = csvInput;
495
- if (csvInput.buffer instanceof ArrayBuffer) {
496
- transfer = [csvInput.buffer];
497
- }
498
- } else if (typeof csvInput !== 'string') {
499
- throw new ValidationError('Input must be a CSV string, File, or ArrayBuffer');
500
- }
501
-
502
- // ????????? ?????? ????? pool
503
- const execOptions = transfer ? { transfer } : {};
504
- return pool.exec('parseCSV', [csvPayload, options], execOptions, onProgress);
505
- }
506
-
507
- /**
508
- * Чтение файла как текст
509
- * @private
510
- */
511
- async function readFileAsArrayBuffer(file) {
512
- return new Promise((resolve, reject) => {
513
- const reader = new FileReader();
514
- reader.onload = (event) => resolve(event.target.result);
515
- reader.onerror = (error) => reject(error);
516
- reader.readAsArrayBuffer(file);
517
- });
518
- }
519
-
520
- // Экспорт для Node.js совместимости
521
- if (typeof module !== 'undefined' && module.exports) {
522
- module.exports = {
523
- WorkerPool,
524
- createWorkerPool,
525
- parseCSVWithWorker
526
- };
527
- }