jtcsv 2.2.8 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/README.md +204 -115
  2. package/bin/jtcsv.ts +2612 -0
  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 +1262 -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 +1736 -0
  23. package/dist/jtcsv-core.cjs.js.map +1 -0
  24. package/dist/jtcsv-core.esm.js +1708 -0
  25. package/dist/jtcsv-core.esm.js.map +1 -0
  26. package/dist/jtcsv-core.umd.js +1742 -0
  27. package/dist/jtcsv-core.umd.js.map +1 -0
  28. package/dist/jtcsv-full.cjs.js +2241 -0
  29. package/dist/jtcsv-full.cjs.js.map +1 -0
  30. package/dist/jtcsv-full.esm.js +2209 -0
  31. package/dist/jtcsv-full.esm.js.map +1 -0
  32. package/dist/jtcsv-full.umd.js +2247 -0
  33. package/dist/jtcsv-full.umd.js.map +1 -0
  34. package/dist/jtcsv-workers.esm.js +768 -0
  35. package/dist/jtcsv-workers.esm.js.map +1 -0
  36. package/dist/jtcsv-workers.umd.js +782 -0
  37. package/dist/jtcsv-workers.umd.js.map +1 -0
  38. package/dist/jtcsv.cjs.js +1996 -2048
  39. package/dist/jtcsv.cjs.js.map +1 -1
  40. package/dist/jtcsv.esm.js +1992 -2048
  41. package/dist/jtcsv.esm.js.map +1 -1
  42. package/dist/jtcsv.umd.js +2157 -2209
  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 +112 -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/dist/src/web-server/index.js +648 -0
  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 +665 -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 +446 -0
  131. package/examples/advanced/csv-parser.worker.ts +89 -0
  132. package/examples/advanced/nested-objects-example.ts +306 -0
  133. package/examples/advanced/performance-optimization.ts +504 -0
  134. package/examples/advanced/run-demo-server.ts +116 -0
  135. package/examples/advanced/web-worker-usage.html +874 -0
  136. package/examples/async-multithreaded-example.ts +335 -0
  137. package/examples/cli-advanced-usage.md +290 -0
  138. package/examples/{cli-batch-processing.js → cli-batch-processing.ts} +38 -38
  139. package/examples/{cli-tool.js → cli-tool.ts} +5 -8
  140. package/examples/{error-handling.js → error-handling.ts} +356 -324
  141. package/examples/{express-api.js → express-api.ts} +161 -164
  142. package/examples/{large-dataset-example.js → large-dataset-example.ts} +201 -182
  143. package/examples/{ndjson-processing.js → ndjson-processing.ts} +456 -434
  144. package/examples/{plugin-excel-exporter.js → plugin-excel-exporter.ts} +6 -7
  145. package/examples/react-integration.tsx +637 -0
  146. package/examples/{schema-validation.js → schema-validation.ts} +2 -2
  147. package/examples/simple-usage.ts +194 -0
  148. package/examples/{streaming-example.js → streaming-example.ts} +12 -12
  149. package/index.d.ts +187 -18
  150. package/package.json +75 -81
  151. package/plugins.d.ts +37 -0
  152. package/schema.d.ts +103 -0
  153. package/src/browser/browser-functions.ts +402 -0
  154. package/src/browser/core.ts +152 -0
  155. package/src/browser/csv-to-json-browser.d.ts +3 -0
  156. package/src/browser/csv-to-json-browser.ts +494 -0
  157. package/src/browser/{errors-browser.js → errors-browser.ts} +305 -197
  158. package/src/browser/extensions/plugins.ts +93 -0
  159. package/src/browser/extensions/workers.ts +39 -0
  160. package/src/browser/globals.d.ts +5 -0
  161. package/src/browser/index.ts +192 -0
  162. package/src/browser/json-to-csv-browser.d.ts +3 -0
  163. package/src/browser/json-to-csv-browser.ts +338 -0
  164. package/src/browser/streams.ts +403 -0
  165. package/src/browser/workers/{csv-parser.worker.js → csv-parser.worker.ts} +3 -3
  166. package/src/browser/workers/{worker-pool.js → worker-pool.ts} +51 -30
  167. package/src/core/delimiter-cache.ts +320 -0
  168. package/src/core/{node-optimizations.js → node-optimizations.ts} +448 -407
  169. package/src/core/plugin-system.ts +588 -0
  170. package/src/core/transform-hooks.ts +566 -0
  171. package/src/engines/{fast-path-engine-new.js → fast-path-engine-new.ts} +11 -2
  172. package/src/engines/{fast-path-engine.js → fast-path-engine.ts} +79 -53
  173. package/src/errors.ts +1 -0
  174. package/src/formats/{ndjson-parser.js → ndjson-parser.ts} +24 -16
  175. package/src/formats/{tsv-parser.js → tsv-parser.ts} +18 -17
  176. package/src/{index-with-plugins.js → index-with-plugins.ts} +381 -357
  177. package/src/types/index.ts +275 -0
  178. package/src/utils/bom-utils.ts +373 -0
  179. package/src/utils/encoding-support.ts +155 -0
  180. package/src/utils/{schema-validator.js → schema-validator.ts} +814 -589
  181. package/src/utils/transform-loader.ts +389 -0
  182. package/src/utils/validators.ts +35 -0
  183. package/src/utils/zod-adapter.ts +280 -0
  184. package/src/web-server/{index.js → index.ts} +19 -19
  185. package/src/workers/csv-multithreaded.ts +310 -0
  186. package/src/workers/csv-parser.worker.ts +227 -0
  187. package/src/workers/worker-pool.ts +409 -0
  188. package/bin/jtcsv.js +0 -2462
  189. package/csv-to-json.js +0 -688
  190. package/errors.js +0 -208
  191. package/examples/simple-usage.js +0 -282
  192. package/index.js +0 -68
  193. package/json-save.js +0 -254
  194. package/json-to-csv.js +0 -526
  195. package/plugins/README.md +0 -91
  196. package/plugins/express-middleware/README.md +0 -64
  197. package/plugins/express-middleware/example.js +0 -136
  198. package/plugins/express-middleware/index.d.ts +0 -114
  199. package/plugins/express-middleware/index.js +0 -360
  200. package/plugins/express-middleware/package.json +0 -52
  201. package/plugins/fastify-plugin/index.js +0 -406
  202. package/plugins/fastify-plugin/package.json +0 -55
  203. package/plugins/hono/README.md +0 -28
  204. package/plugins/hono/index.d.ts +0 -12
  205. package/plugins/hono/index.js +0 -36
  206. package/plugins/hono/package.json +0 -35
  207. package/plugins/nestjs/README.md +0 -35
  208. package/plugins/nestjs/index.d.ts +0 -25
  209. package/plugins/nestjs/index.js +0 -77
  210. package/plugins/nestjs/package.json +0 -37
  211. package/plugins/nextjs-api/README.md +0 -57
  212. package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
  213. package/plugins/nextjs-api/examples/api-convert.js +0 -69
  214. package/plugins/nextjs-api/index.js +0 -387
  215. package/plugins/nextjs-api/package.json +0 -63
  216. package/plugins/nextjs-api/route.js +0 -371
  217. package/plugins/nuxt/README.md +0 -24
  218. package/plugins/nuxt/index.js +0 -21
  219. package/plugins/nuxt/package.json +0 -35
  220. package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
  221. package/plugins/nuxt/runtime/plugin.js +0 -6
  222. package/plugins/remix/README.md +0 -26
  223. package/plugins/remix/index.d.ts +0 -16
  224. package/plugins/remix/index.js +0 -62
  225. package/plugins/remix/package.json +0 -35
  226. package/plugins/sveltekit/README.md +0 -28
  227. package/plugins/sveltekit/index.d.ts +0 -17
  228. package/plugins/sveltekit/index.js +0 -54
  229. package/plugins/sveltekit/package.json +0 -33
  230. package/plugins/trpc/README.md +0 -25
  231. package/plugins/trpc/index.d.ts +0 -7
  232. package/plugins/trpc/index.js +0 -32
  233. package/plugins/trpc/package.json +0 -34
  234. package/src/browser/browser-functions.js +0 -219
  235. package/src/browser/csv-to-json-browser.js +0 -700
  236. package/src/browser/index.js +0 -113
  237. package/src/browser/json-to-csv-browser.js +0 -309
  238. package/src/browser/streams.js +0 -393
  239. package/src/core/delimiter-cache.js +0 -186
  240. package/src/core/plugin-system.js +0 -476
  241. package/src/core/transform-hooks.js +0 -350
  242. package/src/errors.js +0 -26
  243. package/src/utils/transform-loader.js +0 -205
  244. package/stream-csv-to-json.js +0 -542
  245. package/stream-json-to-csv.js +0 -464
  246. /package/examples/{web-workers-advanced.js → web-workers-advanced.ts} +0 -0
@@ -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