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
@@ -0,0 +1,264 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const csv_to_json_browser_1 = require("../csv-to-json-browser");
4
+ const json_to_csv_browser_1 = require("../json-to-csv-browser");
5
+ const textDecoder = new TextDecoder('utf-8');
6
+ const cache = new Map();
7
+ const CACHE_MAX_SIZE = 50;
8
+ const CACHE_TTL = 5 * 60 * 1000;
9
+ const stats = {
10
+ tasksProcessed: 0,
11
+ cacheHits: 0,
12
+ cacheMisses: 0,
13
+ totalProcessingTime: 0,
14
+ averageProcessingTime: 0
15
+ };
16
+ function generateCacheKey(csv, options) {
17
+ let hash = 0;
18
+ for (let i = 0; i < csv.length; i++) {
19
+ const char = csv.charCodeAt(i);
20
+ hash = ((hash << 5) - hash) + char;
21
+ hash = hash & hash;
22
+ }
23
+ const optionsStr = JSON.stringify(options);
24
+ for (let i = 0; i < optionsStr.length; i++) {
25
+ const char = optionsStr.charCodeAt(i);
26
+ hash = ((hash << 5) - hash) + char;
27
+ hash = hash & hash;
28
+ }
29
+ return `csv-${hash.toString(36)}-${optionsStr.length}`;
30
+ }
31
+ function cleanupCache() {
32
+ const now = Date.now();
33
+ for (const [key, entry] of cache.entries()) {
34
+ if (now - entry.timestamp > CACHE_TTL) {
35
+ cache.delete(key);
36
+ }
37
+ }
38
+ if (cache.size > CACHE_MAX_SIZE) {
39
+ const oldestKey = Array.from(cache.entries())
40
+ .sort((a, b) => a[1].timestamp - b[1].timestamp)[0][0];
41
+ cache.delete(oldestKey);
42
+ }
43
+ }
44
+ function parseCSVWithProgress(csv, options, sendProgress) {
45
+ const startTime = performance.now();
46
+ const cacheKey = generateCacheKey(csv, options);
47
+ if (cache.has(cacheKey)) {
48
+ const cached = cache.get(cacheKey);
49
+ stats.cacheHits++;
50
+ if (sendProgress) {
51
+ sendProgress({
52
+ processed: cached.data.length,
53
+ total: cached.data.length,
54
+ percentage: 100,
55
+ fromCache: true
56
+ });
57
+ }
58
+ return cached.data;
59
+ }
60
+ stats.cacheMisses++;
61
+ const CHUNK_SIZE = 10000;
62
+ const lines = csv.split('\n');
63
+ const totalLines = lines.length;
64
+ let result = [];
65
+ let processedLines = 0;
66
+ for (let i = 0; i < lines.length; i += CHUNK_SIZE) {
67
+ const chunk = lines.slice(i, i + CHUNK_SIZE).join('\n');
68
+ const chunkResult = (0, csv_to_json_browser_1.csvToJson)(chunk, options);
69
+ result = result.concat(chunkResult);
70
+ processedLines = Math.min(i + CHUNK_SIZE, totalLines);
71
+ if (sendProgress) {
72
+ const percentage = (processedLines / totalLines) * 100;
73
+ const elapsed = (performance.now() - startTime) / 1000;
74
+ const speed = processedLines / elapsed;
75
+ sendProgress({
76
+ processed: processedLines,
77
+ total: totalLines,
78
+ percentage: percentage,
79
+ speed: speed,
80
+ elapsed: elapsed
81
+ });
82
+ }
83
+ if (i % (CHUNK_SIZE * 10) === 0) {
84
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 1);
85
+ }
86
+ }
87
+ cache.set(cacheKey, {
88
+ data: result,
89
+ timestamp: Date.now(),
90
+ size: csv.length
91
+ });
92
+ cleanupCache();
93
+ const processingTime = performance.now() - startTime;
94
+ stats.tasksProcessed++;
95
+ stats.totalProcessingTime += processingTime;
96
+ stats.averageProcessingTime = stats.totalProcessingTime / stats.tasksProcessed;
97
+ return result;
98
+ }
99
+ function convertJSONToCSV(jsonData, options) {
100
+ return (0, json_to_csv_browser_1.jsonToCsv)(jsonData, options);
101
+ }
102
+ function validateCSV(csv, options) {
103
+ const startTime = performance.now();
104
+ try {
105
+ const sampleSize = Math.min(1000, csv.split('\n').length);
106
+ const sample = csv.split('\n').slice(0, sampleSize).join('\n');
107
+ const result = (0, csv_to_json_browser_1.csvToJson)(sample, options);
108
+ const processingTime = performance.now() - startTime;
109
+ return {
110
+ valid: true,
111
+ sampleSize: result.length,
112
+ estimatedTotalRows: csv.split('\n').length,
113
+ processingTime: processingTime,
114
+ estimatedFullProcessingTime: (processingTime / sampleSize) * csv.split('\n').length
115
+ };
116
+ }
117
+ catch (error) {
118
+ return {
119
+ valid: false,
120
+ error: error.message,
121
+ processingTime: performance.now() - startTime
122
+ };
123
+ }
124
+ }
125
+ function getStats() {
126
+ return {
127
+ ...stats,
128
+ cacheSize: cache.size,
129
+ cacheKeys: Array.from(cache.keys())
130
+ };
131
+ }
132
+ function clearCache() {
133
+ cache.clear();
134
+ stats.cacheHits = 0;
135
+ stats.cacheMisses = 0;
136
+ }
137
+ function decodeCsvInput(input) {
138
+ if (typeof input === 'string') {
139
+ return input;
140
+ }
141
+ if (input instanceof ArrayBuffer) {
142
+ return textDecoder.decode(new Uint8Array(input));
143
+ }
144
+ if (ArrayBuffer.isView(input)) {
145
+ return textDecoder.decode(input);
146
+ }
147
+ throw new Error('Invalid CSV input type');
148
+ }
149
+ self.onmessage = function (event) {
150
+ const { data } = event;
151
+ switch (data.type) {
152
+ case 'EXECUTE':
153
+ handleExecute(data);
154
+ break;
155
+ case 'GET_STATS':
156
+ self.postMessage({
157
+ type: 'STATS',
158
+ taskId: data.taskId,
159
+ data: getStats()
160
+ });
161
+ break;
162
+ case 'CLEAR_CACHE':
163
+ clearCache();
164
+ self.postMessage({
165
+ type: 'CACHE_CLEARED',
166
+ taskId: data.taskId
167
+ });
168
+ break;
169
+ default:
170
+ self.postMessage({
171
+ type: 'ERROR',
172
+ taskId: data.taskId,
173
+ message: `Unknown command: ${data.type}`
174
+ });
175
+ }
176
+ };
177
+ function handleExecute(commandData) {
178
+ const { taskId, method, args = [], options = {} } = commandData;
179
+ try {
180
+ switch (method) {
181
+ case 'parseCSV': {
182
+ const [csvInput, parseOptions] = args;
183
+ const csv = decodeCsvInput(csvInput);
184
+ const sendProgress = (progress) => {
185
+ self.postMessage({
186
+ type: 'PROGRESS',
187
+ taskId,
188
+ ...progress
189
+ });
190
+ };
191
+ const result = parseCSVWithProgress(csv, { ...options, ...parseOptions }, sendProgress);
192
+ self.postMessage({
193
+ type: 'RESULT',
194
+ taskId,
195
+ data: result
196
+ });
197
+ break;
198
+ }
199
+ case 'jsonToCSV': {
200
+ const [jsonData, csvOptions] = args;
201
+ const result = convertJSONToCSV(jsonData, { ...options, ...csvOptions });
202
+ self.postMessage({
203
+ type: 'RESULT',
204
+ taskId,
205
+ data: result
206
+ });
207
+ break;
208
+ }
209
+ case 'validateCSV': {
210
+ const [csv, validateOptions] = args;
211
+ const result = validateCSV(csv, { ...options, ...validateOptions });
212
+ self.postMessage({
213
+ type: 'RESULT',
214
+ taskId,
215
+ data: result
216
+ });
217
+ break;
218
+ }
219
+ case 'autoDetectDelimiter': {
220
+ const [csv] = args;
221
+ const delimiters = [';', ',', '\t', '|'];
222
+ let bestDelimiter = ';';
223
+ let maxCount = 0;
224
+ const firstLine = csv.split('\n')[0] || '';
225
+ for (const delim of delimiters) {
226
+ const count = (firstLine.match(new RegExp(`[${delim}]`, 'g')) || []).length;
227
+ if (count > maxCount) {
228
+ maxCount = count;
229
+ bestDelimiter = delim;
230
+ }
231
+ }
232
+ self.postMessage({
233
+ type: 'RESULT',
234
+ taskId,
235
+ data: bestDelimiter
236
+ });
237
+ break;
238
+ }
239
+ default:
240
+ throw new Error(`Unknown method: ${method}`);
241
+ }
242
+ }
243
+ catch (error) {
244
+ self.postMessage({
245
+ type: 'ERROR',
246
+ taskId,
247
+ message: error.message,
248
+ stack: error.stack,
249
+ code: error.code,
250
+ details: error.details
251
+ });
252
+ }
253
+ }
254
+ self.postMessage({ type: 'READY' });
255
+ if (typeof module !== 'undefined' && module.exports) {
256
+ module.exports = {
257
+ parseCSVWithProgress,
258
+ convertJSONToCSV,
259
+ validateCSV,
260
+ getStats,
261
+ clearCache
262
+ };
263
+ }
264
+ //# sourceMappingURL=csv-parser.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv-parser.worker.js","sourceRoot":"","sources":["../../../../src/browser/workers/csv-parser.worker.ts"],"names":[],"mappings":";;AAIA,gEAAmD;AACnD,gEAAmD;AAEnD,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;AAG7C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;AACxB,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAGhC,MAAM,KAAK,GAAG;IACZ,cAAc,EAAE,CAAC;IACjB,SAAS,EAAE,CAAC;IACZ,WAAW,EAAE,CAAC;IACd,mBAAmB,EAAE,CAAC;IACtB,qBAAqB,EAAE,CAAC;CACzB,CAAC;AAQF,SAAS,gBAAgB,CAAC,GAAG,EAAE,OAAO;IAEpC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACnC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;IAGD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACnC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,OAAO,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;AACzD,CAAC;AAKD,SAAS,YAAY;IACnB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3C,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;YACtC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAGD,IAAI,KAAK,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;aAC1C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AASD,SAAS,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY;IACtD,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAGpC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnC,KAAK,CAAC,SAAS,EAAE,CAAC;QAGlB,IAAI,YAAY,EAAE,CAAC;YACjB,YAAY,CAAC;gBACX,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;gBAC7B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;gBACzB,UAAU,EAAE,GAAG;gBACf,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,WAAW,EAAE,CAAC;IAGpB,MAAM,UAAU,GAAG,KAAK,CAAC;IACzB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;IAEhC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,cAAc,GAAG,CAAC,CAAC;IAGvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,IAAA,+BAAS,EAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEpC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,EAAE,UAAU,CAAC,CAAC;QAGtD,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,UAAU,GAAG,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC;YACvD,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;YACvD,MAAM,KAAK,GAAG,cAAc,GAAG,OAAO,CAAC;YAEvC,YAAY,CAAC;gBACX,SAAS,EAAE,cAAc;gBACzB,KAAK,EAAE,UAAU;gBACjB,UAAU,EAAE,UAAU;gBACtB,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,OAAO;aACjB,CAAC,CAAC;QACL,CAAC;QAGD,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;YAEhC,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAGD,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE;QAClB,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,IAAI,EAAE,GAAG,CAAC,MAAM;KACjB,CAAC,CAAC;IAGH,YAAY,EAAE,CAAC;IAGf,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACrD,KAAK,CAAC,cAAc,EAAE,CAAC;IACvB,KAAK,CAAC,mBAAmB,IAAI,cAAc,CAAC;IAC5C,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,mBAAmB,GAAG,KAAK,CAAC,cAAc,CAAC;IAE/E,OAAO,MAAM,CAAC;AAChB,CAAC;AAQD,SAAS,gBAAgB,CAAC,QAAQ,EAAE,OAAO;IACzC,OAAO,IAAA,+BAAS,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC;AAQD,SAAS,WAAW,CAAC,GAAG,EAAE,OAAO;IAC/B,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAEpC,IAAI,CAAC;QAEH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/D,MAAM,MAAM,GAAG,IAAA,+BAAS,EAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE1C,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAErD,OAAO;YACL,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,MAAM,CAAC,MAAM;YACzB,kBAAkB,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM;YAC1C,cAAc,EAAE,cAAc;YAC9B,2BAA2B,EAAE,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM;SACpF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,cAAc,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS;SAC9C,CAAC;IACJ,CAAC;AACH,CAAC;AAMD,SAAS,QAAQ;IACf,OAAO;QACL,GAAG,KAAK;QACR,SAAS,EAAE,KAAK,CAAC,IAAI;QACrB,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;KACpC,CAAC;AACJ,CAAC;AAKD,SAAS,UAAU;IACjB,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,cAAc,CAAC,KAAK;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;QACjC,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;AAC5C,CAAC;AAGD,IAAI,CAAC,SAAS,GAAG,UAAU,KAAK;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAEvB,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,MAAM;QAER,KAAK,WAAW;YACd,IAAI,CAAC,WAAW,CAAC;gBACf,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,IAAI,EAAE,QAAQ,EAAE;aACjB,CAAC,CAAC;YACH,MAAM;QAER,KAAK,aAAa;YAChB,UAAU,EAAE,CAAC;YACb,IAAI,CAAC,WAAW,CAAC;gBACf,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;YACH,MAAM;QAER;YACE,IAAI,CAAC,WAAW,CAAC;gBACf,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,OAAO,EAAE,oBAAoB,IAAI,CAAC,IAAI,EAAE;aACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC;AAMF,SAAS,aAAa,CAAC,WAAW;IAChC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,WAAW,CAAC;IAEhE,IAAI,CAAC;QACH,QAAQ,MAAM,EAAE,CAAC;YACjB,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC;gBACtC,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAGrC,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,EAAE;oBAChC,IAAI,CAAC,WAAW,CAAC;wBACf,IAAI,EAAE,UAAU;wBAChB,MAAM;wBACN,GAAG,QAAQ;qBACZ,CAAC,CAAC;gBACL,CAAC,CAAC;gBAEF,MAAM,MAAM,GAAG,oBAAoB,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,YAAY,EAAE,EAAE,YAAY,CAAC,CAAC;gBAExF,IAAI,CAAC,WAAW,CAAC;oBACf,IAAI,EAAE,QAAQ;oBACd,MAAM;oBACN,IAAI,EAAE,MAAM;iBACb,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;YAED,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC;gBACpC,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC;gBAEzE,IAAI,CAAC,WAAW,CAAC;oBACf,IAAI,EAAE,QAAQ;oBACd,MAAM;oBACN,IAAI,EAAE,MAAM;iBACb,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;YAED,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,CAAC,GAAG,EAAE,eAAe,CAAC,GAAG,IAAI,CAAC;gBACpC,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,eAAe,EAAE,CAAC,CAAC;gBAEpE,IAAI,CAAC,WAAW,CAAC;oBACf,IAAI,EAAE,QAAQ;oBACd,MAAM;oBACN,IAAI,EAAE,MAAM;iBACb,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;YAED,KAAK,qBAAqB,CAAC,CAAC,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;gBAEnB,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;gBACzC,IAAI,aAAa,GAAG,GAAG,CAAC;gBACxB,IAAI,QAAQ,GAAG,CAAC,CAAC;gBAEjB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAE3C,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;oBAC/B,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;oBAC5E,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;wBACrB,QAAQ,GAAG,KAAK,CAAC;wBACjB,aAAa,GAAG,KAAK,CAAC;oBACxB,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,WAAW,CAAC;oBACf,IAAI,EAAE,QAAQ;oBACd,MAAM;oBACN,IAAI,EAAE,aAAa;iBACpB,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;YAED;gBACE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,WAAW,CAAC;YACf,IAAI,EAAE,OAAO;YACb,MAAM;YACN,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAGD,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAGpC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;IACpD,MAAM,CAAC,OAAO,GAAG;QACf,oBAAoB;QACpB,gBAAgB;QAChB,WAAW;QACX,QAAQ;QACR,UAAU;KACX,CAAC;AACJ,CAAC","sourcesContent":["// Web Worker для обработки CSV\n// Работает в отдельном потоке, не блокируя основной\n\n// Импорт функций парсинга (они будут bundled вместе с worker)\nimport { csvToJson } from '../csv-to-json-browser';\nimport { jsonToCsv } from '../json-to-csv-browser';\n\nconst textDecoder = new TextDecoder('utf-8');\n\n// Кеш для повторного использования результатов\nconst cache = new Map();\nconst CACHE_MAX_SIZE = 50;\nconst CACHE_TTL = 5 * 60 * 1000; // 5 минут\n\n// Статистика worker\nconst stats = {\n tasksProcessed: 0,\n cacheHits: 0,\n cacheMisses: 0,\n totalProcessingTime: 0,\n averageProcessingTime: 0\n};\n\n/**\n * Генерация ключа кеша для CSV строки\n * @param {string} csv - CSV строка\n * @param {Object} options - Опции парсинга\n * @returns {string} Ключ кеша\n */\nfunction generateCacheKey(csv, options) {\n // Простой хэш для CSV строки\n let hash = 0;\n for (let i = 0; i < csv.length; i++) {\n const char = csv.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n \n // Добавление опций в хэш\n const optionsStr = JSON.stringify(options);\n for (let i = 0; i < optionsStr.length; i++) {\n const char = optionsStr.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n \n return `csv-${hash.toString(36)}-${optionsStr.length}`;\n}\n\n/**\n * Очистка устаревших записей кеша\n */\nfunction cleanupCache() {\n const now = Date.now();\n for (const [key, entry] of cache.entries()) {\n if (now - entry.timestamp > CACHE_TTL) {\n cache.delete(key);\n }\n }\n \n // Ограничение размера кеша\n if (cache.size > CACHE_MAX_SIZE) {\n const oldestKey = Array.from(cache.entries())\n .sort((a, b) => a[1].timestamp - b[1].timestamp)[0][0];\n cache.delete(oldestKey);\n }\n}\n\n/**\n * Парсинг CSV с кешированием и прогрессом\n * @param {string} csv - CSV строка\n * @param {Object} options - Опции парсинга\n * @param {Function} sendProgress - Функция отправки прогресса\n * @returns {Array<Object>} JSON данные\n */\nfunction parseCSVWithProgress(csv, options, sendProgress) {\n const startTime = performance.now();\n \n // Проверка кеша\n const cacheKey = generateCacheKey(csv, options);\n if (cache.has(cacheKey)) {\n const cached = cache.get(cacheKey);\n stats.cacheHits++;\n \n // Отправка мгновенного прогресса для кешированных данных\n if (sendProgress) {\n sendProgress({\n processed: cached.data.length,\n total: cached.data.length,\n percentage: 100,\n fromCache: true\n });\n }\n \n return cached.data;\n }\n \n stats.cacheMisses++;\n \n // Разделение на chunks для прогресса\n const CHUNK_SIZE = 10000; // строк в chunk\n const lines = csv.split('\\n');\n const totalLines = lines.length;\n \n let result = [];\n let processedLines = 0;\n \n // Обработка по chunks\n for (let i = 0; i < lines.length; i += CHUNK_SIZE) {\n const chunk = lines.slice(i, i + CHUNK_SIZE).join('\\n');\n const chunkResult = csvToJson(chunk, options);\n result = result.concat(chunkResult);\n \n processedLines = Math.min(i + CHUNK_SIZE, totalLines);\n \n // Отправка прогресса\n if (sendProgress) {\n const percentage = (processedLines / totalLines) * 100;\n const elapsed = (performance.now() - startTime) / 1000;\n const speed = processedLines / elapsed;\n \n sendProgress({\n processed: processedLines,\n total: totalLines,\n percentage: percentage,\n speed: speed,\n elapsed: elapsed\n });\n }\n \n // Даем возможность обработать другие задачи\n if (i % (CHUNK_SIZE * 10) === 0) {\n // Небольшая пауза для неблокирующей обработки\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 1);\n }\n }\n \n // Сохранение в кеш\n cache.set(cacheKey, {\n data: result,\n timestamp: Date.now(),\n size: csv.length\n });\n \n // Очистка кеша если нужно\n cleanupCache();\n \n // Обновление статистики\n const processingTime = performance.now() - startTime;\n stats.tasksProcessed++;\n stats.totalProcessingTime += processingTime;\n stats.averageProcessingTime = stats.totalProcessingTime / stats.tasksProcessed;\n \n return result;\n}\n\n/**\n * Конвертация JSON в CSV\n * @param {Array<Object>} jsonData - JSON данные\n * @param {Object} options - Опции конвертации\n * @returns {string} CSV строка\n */\nfunction convertJSONToCSV(jsonData, options) {\n return jsonToCsv(jsonData, options);\n}\n\n/**\n * Валидация CSV строки\n * @param {string} csv - CSV строка\n * @param {Object} options - Опции валидации\n * @returns {Object} Результат валидации\n */\nfunction validateCSV(csv, options) {\n const startTime = performance.now();\n \n try {\n // Быстрый парсинг для валидации\n const sampleSize = Math.min(1000, csv.split('\\n').length);\n const sample = csv.split('\\n').slice(0, sampleSize).join('\\n');\n \n const result = csvToJson(sample, options);\n \n const processingTime = performance.now() - startTime;\n \n return {\n valid: true,\n sampleSize: result.length,\n estimatedTotalRows: csv.split('\\n').length,\n processingTime: processingTime,\n estimatedFullProcessingTime: (processingTime / sampleSize) * csv.split('\\n').length\n };\n } catch (error) {\n return {\n valid: false,\n error: error.message,\n processingTime: performance.now() - startTime\n };\n }\n}\n\n/**\n * Получение статистики worker\n * @returns {Object} Статистика\n */\nfunction getStats() {\n return {\n ...stats,\n cacheSize: cache.size,\n cacheKeys: Array.from(cache.keys())\n };\n}\n\n/**\n * Очистка кеша worker\n */\nfunction clearCache() {\n cache.clear();\n stats.cacheHits = 0;\n stats.cacheMisses = 0;\n}\n\nfunction decodeCsvInput(input) {\n if (typeof input === 'string') {\n return input;\n }\n if (input instanceof ArrayBuffer) {\n return textDecoder.decode(new Uint8Array(input));\n }\n if (ArrayBuffer.isView(input)) {\n return textDecoder.decode(input);\n }\n throw new Error('Invalid CSV input type');\n}\n\n// Обработчик сообщений от основного потока\nself.onmessage = function (event) {\n const { data } = event;\n \n switch (data.type) {\n case 'EXECUTE':\n handleExecute(data);\n break;\n \n case 'GET_STATS':\n self.postMessage({\n type: 'STATS',\n taskId: data.taskId,\n data: getStats()\n });\n break;\n \n case 'CLEAR_CACHE':\n clearCache();\n self.postMessage({\n type: 'CACHE_CLEARED',\n taskId: data.taskId\n });\n break;\n \n default:\n self.postMessage({\n type: 'ERROR',\n taskId: data.taskId,\n message: `Unknown command: ${data.type}`\n });\n }\n};\n\n/**\n * Обработка команды EXECUTE\n * @param {Object} commandData - Данные команды\n */\nfunction handleExecute(commandData) {\n const { taskId, method, args = [], options = {} } = commandData;\n \n try {\n switch (method) {\n case 'parseCSV': {\n const [csvInput, parseOptions] = args;\n const csv = decodeCsvInput(csvInput);\n \n // Функция отправки прогресса\n const sendProgress = (progress) => {\n self.postMessage({\n type: 'PROGRESS',\n taskId,\n ...progress\n });\n };\n \n const result = parseCSVWithProgress(csv, { ...options, ...parseOptions }, sendProgress);\n \n self.postMessage({\n type: 'RESULT',\n taskId,\n data: result\n });\n break;\n }\n \n case 'jsonToCSV': {\n const [jsonData, csvOptions] = args;\n const result = convertJSONToCSV(jsonData, { ...options, ...csvOptions });\n \n self.postMessage({\n type: 'RESULT',\n taskId,\n data: result\n });\n break;\n }\n \n case 'validateCSV': {\n const [csv, validateOptions] = args;\n const result = validateCSV(csv, { ...options, ...validateOptions });\n \n self.postMessage({\n type: 'RESULT',\n taskId,\n data: result\n });\n break;\n }\n \n case 'autoDetectDelimiter': {\n const [csv] = args;\n // Простая реализация автоопределения\n const delimiters = [';', ',', '\\t', '|'];\n let bestDelimiter = ';';\n let maxCount = 0;\n \n const firstLine = csv.split('\\n')[0] || '';\n \n for (const delim of delimiters) {\n const count = (firstLine.match(new RegExp(`[${delim}]`, 'g')) || []).length;\n if (count > maxCount) {\n maxCount = count;\n bestDelimiter = delim;\n }\n }\n \n self.postMessage({\n type: 'RESULT',\n taskId,\n data: bestDelimiter\n });\n break;\n }\n \n default:\n throw new Error(`Unknown method: ${method}`);\n }\n } catch (error) {\n self.postMessage({\n type: 'ERROR',\n taskId,\n message: error.message,\n stack: error.stack,\n code: error.code,\n details: error.details\n });\n }\n}\n\n// Инициализация worker\nself.postMessage({ type: 'READY' });\n\n// Экспорт для тестирования\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = {\n parseCSVWithProgress,\n convertJSONToCSV,\n validateCSV,\n getStats,\n clearCache\n };\n}\n"]}
@@ -0,0 +1,338 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkerPool = void 0;
4
+ exports.createWorkerPool = createWorkerPool;
5
+ exports.parseCSVWithWorker = parseCSVWithWorker;
6
+ const errors_browser_1 = require("../errors-browser");
7
+ const WORKERS_SUPPORTED = typeof Worker !== 'undefined';
8
+ function isTransferableBuffer(value) {
9
+ if (!(value instanceof ArrayBuffer)) {
10
+ return false;
11
+ }
12
+ if (typeof SharedArrayBuffer !== 'undefined' && value instanceof SharedArrayBuffer) {
13
+ return false;
14
+ }
15
+ return true;
16
+ }
17
+ function collectTransferables(args) {
18
+ const transferables = [];
19
+ const collectFromValue = (value) => {
20
+ if (!value) {
21
+ return;
22
+ }
23
+ if (isTransferableBuffer(value)) {
24
+ transferables.push(value);
25
+ return;
26
+ }
27
+ if (ArrayBuffer.isView(value) && isTransferableBuffer(value.buffer)) {
28
+ transferables.push(value.buffer);
29
+ return;
30
+ }
31
+ if (Array.isArray(value)) {
32
+ value.forEach(collectFromValue);
33
+ }
34
+ };
35
+ args.forEach(collectFromValue);
36
+ return transferables.length ? transferables : null;
37
+ }
38
+ class WorkerPool {
39
+ constructor(workerScript, options = {}) {
40
+ if (!WORKERS_SUPPORTED) {
41
+ throw new errors_browser_1.ValidationError('Web Workers не поддерживаются в этом браузере');
42
+ }
43
+ this.workerScript = workerScript;
44
+ this.options = {
45
+ workerCount: 4,
46
+ maxQueueSize: 100,
47
+ autoScale: true,
48
+ idleTimeout: 60000,
49
+ ...options
50
+ };
51
+ this.workers = [];
52
+ this.taskQueue = [];
53
+ this.activeTasks = new Map();
54
+ this.stats = {
55
+ totalWorkers: 0,
56
+ activeWorkers: 0,
57
+ idleWorkers: 0,
58
+ queueSize: 0,
59
+ tasksCompleted: 0,
60
+ tasksFailed: 0
61
+ };
62
+ this.initializeWorkers();
63
+ }
64
+ initializeWorkers() {
65
+ const { workerCount } = this.options;
66
+ for (let i = 0; i < workerCount; i++) {
67
+ this.createWorker();
68
+ }
69
+ this.updateStats();
70
+ }
71
+ createWorker() {
72
+ try {
73
+ const worker = new Worker(this.workerScript, { type: 'module' });
74
+ worker.id = `worker-${this.workers.length}`;
75
+ worker.status = 'idle';
76
+ worker.lastUsed = Date.now();
77
+ worker.taskId = null;
78
+ worker.onmessage = (event) => this.handleWorkerMessage(worker, event);
79
+ worker.onerror = (error) => this.handleWorkerError(worker, error);
80
+ worker.onmessageerror = (error) => this.handleWorkerMessageError(worker, error);
81
+ this.workers.push(worker);
82
+ this.stats.totalWorkers++;
83
+ this.stats.idleWorkers++;
84
+ return worker;
85
+ }
86
+ catch (error) {
87
+ throw new errors_browser_1.ConfigurationError(`Не удалось создать worker: ${error.message}`);
88
+ }
89
+ }
90
+ handleWorkerMessage(worker, event) {
91
+ const { data } = event;
92
+ if (data.type === 'PROGRESS') {
93
+ this.handleProgress(worker, data);
94
+ }
95
+ else if (data.type === 'RESULT') {
96
+ this.handleResult(worker, data);
97
+ }
98
+ else if (data.type === 'ERROR') {
99
+ this.handleWorkerTaskError(worker, data);
100
+ }
101
+ }
102
+ handleProgress(worker, progressData) {
103
+ const taskId = worker.taskId;
104
+ if (taskId && this.activeTasks.has(taskId)) {
105
+ const task = this.activeTasks.get(taskId);
106
+ if (task.onProgress) {
107
+ task.onProgress({
108
+ processed: progressData.processed,
109
+ total: progressData.total,
110
+ percentage: (progressData.processed / progressData.total) * 100,
111
+ speed: progressData.speed || 0
112
+ });
113
+ }
114
+ }
115
+ }
116
+ handleResult(worker, resultData) {
117
+ const taskId = worker.taskId;
118
+ if (taskId && this.activeTasks.has(taskId)) {
119
+ const task = this.activeTasks.get(taskId);
120
+ worker.status = 'idle';
121
+ worker.lastUsed = Date.now();
122
+ worker.taskId = null;
123
+ this.stats.activeWorkers--;
124
+ this.stats.idleWorkers++;
125
+ task.resolve(resultData.data);
126
+ this.activeTasks.delete(taskId);
127
+ this.stats.tasksCompleted++;
128
+ this.processQueue();
129
+ this.updateStats();
130
+ }
131
+ }
132
+ handleWorkerTaskError(worker, errorData) {
133
+ const taskId = worker.taskId;
134
+ if (taskId && this.activeTasks.has(taskId)) {
135
+ const task = this.activeTasks.get(taskId);
136
+ worker.status = 'idle';
137
+ worker.lastUsed = Date.now();
138
+ worker.taskId = null;
139
+ this.stats.activeWorkers--;
140
+ this.stats.idleWorkers++;
141
+ const workerError = new Error(errorData.message || 'Ошибка в worker');
142
+ if (errorData.code) {
143
+ workerError.code = errorData.code;
144
+ }
145
+ if (errorData.details) {
146
+ workerError.details = errorData.details;
147
+ }
148
+ task.reject(workerError);
149
+ this.activeTasks.delete(taskId);
150
+ this.stats.tasksFailed++;
151
+ this.processQueue();
152
+ this.updateStats();
153
+ }
154
+ }
155
+ handleWorkerError(worker, error) {
156
+ console.error(`Worker ${worker.id} error:`, error);
157
+ this.restartWorker(worker);
158
+ }
159
+ handleWorkerMessageError(worker, error) {
160
+ console.error(`Worker ${worker.id} message error:`, error);
161
+ }
162
+ restartWorker(worker) {
163
+ const index = this.workers.indexOf(worker);
164
+ if (index !== -1) {
165
+ worker.terminate();
166
+ if (worker.status === 'active') {
167
+ this.stats.activeWorkers--;
168
+ }
169
+ else {
170
+ this.stats.idleWorkers--;
171
+ }
172
+ this.stats.totalWorkers--;
173
+ const newWorker = this.createWorker();
174
+ this.workers[index] = newWorker;
175
+ if (worker.taskId && this.activeTasks.has(worker.taskId)) {
176
+ const task = this.activeTasks.get(worker.taskId);
177
+ this.executeTask(newWorker, task);
178
+ }
179
+ }
180
+ }
181
+ executeTask(worker, task) {
182
+ worker.status = 'active';
183
+ worker.lastUsed = Date.now();
184
+ worker.taskId = task.id;
185
+ this.stats.idleWorkers--;
186
+ this.stats.activeWorkers++;
187
+ const payload = {
188
+ type: 'EXECUTE',
189
+ taskId: task.id,
190
+ method: task.method,
191
+ args: task.args,
192
+ options: task.options
193
+ };
194
+ if (task.transferList && task.transferList.length) {
195
+ worker.postMessage(payload, task.transferList);
196
+ }
197
+ else {
198
+ worker.postMessage(payload);
199
+ }
200
+ }
201
+ processQueue() {
202
+ if (this.taskQueue.length === 0) {
203
+ return;
204
+ }
205
+ while (this.taskQueue.length > 0) {
206
+ const idleWorker = this.workers.find(w => w.status === 'idle');
207
+ if (!idleWorker) {
208
+ if (this.options.autoScale && this.workers.length < this.options.maxQueueSize) {
209
+ this.createWorker();
210
+ continue;
211
+ }
212
+ break;
213
+ }
214
+ const task = this.taskQueue.shift();
215
+ this.stats.queueSize--;
216
+ this.executeTask(idleWorker, task);
217
+ }
218
+ this.updateStats();
219
+ }
220
+ updateStats() {
221
+ this.stats.queueSize = this.taskQueue.length;
222
+ }
223
+ async exec(method, args = [], options = {}, onProgress = null) {
224
+ return new Promise((resolve, reject) => {
225
+ if (this.taskQueue.length >= this.options.maxQueueSize) {
226
+ reject(new Error('Очередь задач переполнена'));
227
+ return;
228
+ }
229
+ const taskId = `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
230
+ const { transfer, ...taskOptions } = options || {};
231
+ const transferList = transfer || collectTransferables(args);
232
+ const task = {
233
+ id: taskId,
234
+ method,
235
+ args,
236
+ options: taskOptions,
237
+ transferList,
238
+ onProgress,
239
+ resolve,
240
+ reject,
241
+ createdAt: Date.now()
242
+ };
243
+ this.taskQueue.push(task);
244
+ this.stats.queueSize++;
245
+ this.processQueue();
246
+ this.updateStats();
247
+ });
248
+ }
249
+ getStats() {
250
+ return { ...this.stats };
251
+ }
252
+ cleanupIdleWorkers() {
253
+ const now = Date.now();
254
+ const { idleTimeout } = this.options;
255
+ for (let i = this.workers.length - 1; i >= 0; i--) {
256
+ const worker = this.workers[i];
257
+ if (worker.status === 'idle' && (now - worker.lastUsed) > idleTimeout) {
258
+ if (this.workers.length > 1) {
259
+ worker.terminate();
260
+ this.workers.splice(i, 1);
261
+ this.stats.totalWorkers--;
262
+ this.stats.idleWorkers--;
263
+ }
264
+ }
265
+ }
266
+ }
267
+ terminate() {
268
+ this.workers.forEach(worker => {
269
+ worker.terminate();
270
+ });
271
+ this.workers = [];
272
+ this.taskQueue = [];
273
+ this.activeTasks.clear();
274
+ this.stats = {
275
+ totalWorkers: 0,
276
+ activeWorkers: 0,
277
+ idleWorkers: 0,
278
+ queueSize: 0,
279
+ tasksCompleted: 0,
280
+ tasksFailed: 0
281
+ };
282
+ }
283
+ }
284
+ exports.WorkerPool = WorkerPool;
285
+ function createWorkerPool(options = {}) {
286
+ const baseUrl = typeof document !== 'undefined'
287
+ ? document.baseURI
288
+ : (typeof self !== 'undefined' && self.location
289
+ ? self.location.href
290
+ : '');
291
+ const workerScript = new URL('./csv-parser.worker.js', baseUrl).href;
292
+ return new WorkerPool(workerScript, options);
293
+ }
294
+ async function parseCSVWithWorker(csvInput, options = {}, onProgress = null) {
295
+ const poolHolder = parseCSVWithWorker;
296
+ if (!poolHolder.pool) {
297
+ poolHolder.pool = createWorkerPool();
298
+ }
299
+ const pool = poolHolder.pool;
300
+ let csvPayload = csvInput;
301
+ let transfer = null;
302
+ if (csvInput instanceof File) {
303
+ const buffer = await readFileAsArrayBuffer(csvInput);
304
+ csvPayload = new Uint8Array(buffer);
305
+ transfer = [buffer];
306
+ }
307
+ else if (csvInput instanceof ArrayBuffer) {
308
+ csvPayload = csvInput;
309
+ transfer = [csvInput];
310
+ }
311
+ else if (ArrayBuffer.isView(csvInput)) {
312
+ csvPayload = csvInput;
313
+ if (csvInput.buffer instanceof ArrayBuffer) {
314
+ transfer = [csvInput.buffer];
315
+ }
316
+ }
317
+ else if (typeof csvInput !== 'string') {
318
+ throw new errors_browser_1.ValidationError('Input must be a CSV string, File, or ArrayBuffer');
319
+ }
320
+ const execOptions = transfer ? { transfer } : {};
321
+ return pool.exec('parseCSV', [csvPayload, options], execOptions, onProgress);
322
+ }
323
+ async function readFileAsArrayBuffer(file) {
324
+ return new Promise((resolve, reject) => {
325
+ const reader = new FileReader();
326
+ reader.onload = (event) => resolve(event.target.result);
327
+ reader.onerror = (error) => reject(error);
328
+ reader.readAsArrayBuffer(file);
329
+ });
330
+ }
331
+ if (typeof module !== 'undefined' && module.exports) {
332
+ module.exports = {
333
+ WorkerPool,
334
+ createWorkerPool,
335
+ parseCSVWithWorker
336
+ };
337
+ }
338
+ //# sourceMappingURL=worker-pool.js.map