jtcsv 2.1.3 → 2.2.2

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 (52) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +60 -341
  3. package/bin/jtcsv.js +2462 -1372
  4. package/csv-to-json.js +35 -26
  5. package/dist/jtcsv.cjs.js +807 -133
  6. package/dist/jtcsv.cjs.js.map +1 -1
  7. package/dist/jtcsv.esm.js +800 -134
  8. package/dist/jtcsv.esm.js.map +1 -1
  9. package/dist/jtcsv.umd.js +807 -133
  10. package/dist/jtcsv.umd.js.map +1 -1
  11. package/errors.js +20 -0
  12. package/examples/browser-vanilla.html +37 -0
  13. package/examples/cli-batch-processing.js +38 -0
  14. package/examples/error-handling.js +324 -0
  15. package/examples/ndjson-processing.js +434 -0
  16. package/examples/react-integration.jsx +637 -0
  17. package/examples/schema-validation.js +640 -0
  18. package/examples/simple-usage.js +10 -7
  19. package/examples/typescript-example.ts +486 -0
  20. package/examples/web-workers-advanced.js +28 -0
  21. package/index.d.ts +2 -0
  22. package/json-save.js +2 -1
  23. package/json-to-csv.js +171 -131
  24. package/package.json +20 -4
  25. package/plugins/README.md +41 -467
  26. package/plugins/express-middleware/README.md +32 -274
  27. package/plugins/hono/README.md +16 -13
  28. package/plugins/nestjs/README.md +13 -11
  29. package/plugins/nextjs-api/README.md +28 -423
  30. package/plugins/nextjs-api/index.js +1 -2
  31. package/plugins/nextjs-api/route.js +1 -2
  32. package/plugins/nuxt/README.md +6 -7
  33. package/plugins/remix/README.md +9 -9
  34. package/plugins/sveltekit/README.md +8 -8
  35. package/plugins/trpc/README.md +8 -5
  36. package/src/browser/browser-functions.js +33 -3
  37. package/src/browser/csv-to-json-browser.js +269 -11
  38. package/src/browser/errors-browser.js +19 -1
  39. package/src/browser/index.js +39 -5
  40. package/src/browser/streams.js +393 -0
  41. package/src/browser/workers/csv-parser.worker.js +20 -2
  42. package/src/browser/workers/worker-pool.js +507 -447
  43. package/src/core/plugin-system.js +4 -0
  44. package/src/engines/fast-path-engine.js +31 -23
  45. package/src/errors.js +26 -0
  46. package/src/formats/ndjson-parser.js +54 -5
  47. package/src/formats/tsv-parser.js +4 -1
  48. package/src/utils/schema-validator.js +594 -0
  49. package/src/utils/transform-loader.js +205 -0
  50. package/src/web-server/index.js +683 -0
  51. package/stream-csv-to-json.js +16 -87
  52. package/stream-json-to-csv.js +18 -86
@@ -1,452 +1,57 @@
1
1
  # @jtcsv/nextjs
2
2
 
3
- Next.js интеграция для JTCSV - API routes, React hooks и компоненты для конвертации CSV/JSON.
4
-
5
- ## 📦 Установка
3
+ Next.js helpers for JTCSV: API route handler, React hooks, and browser helpers.
6
4
 
5
+ ## Install
7
6
  ```bash
8
7
  npm install @jtcsv/nextjs jtcsv
9
- # или
10
- pnpm add @jtcsv/nextjs jtcsv
11
- # или
12
- yarn add @jtcsv/nextjs jtcsv
13
8
  ```
14
9
 
15
- ## 🚀 Быстрый старт
16
-
17
- ### 1. API Route
18
-
19
- Создайте файл `pages/api/convert.js`:
20
-
10
+ ## API route
21
11
  ```javascript
22
12
  // pages/api/convert.js
23
- import { handler } from '@jtcsv/nextjs/route';
13
+ import handler from '@jtcsv/nextjs/route';
24
14
 
25
15
  export default handler;
26
-
27
- export const config = {
28
- api: {
29
- bodyParser: {
30
- sizeLimit: '50mb'
31
- }
32
- }
33
- };
34
16
  ```
35
17
 
36
- ### 2. React компонент
18
+ Query options handled by the route:
19
+ - format: json|csv
20
+ - delimiter
21
+ - includeHeaders
22
+ - parseNumbers
23
+ - parseBooleans
24
+ - useFastPath
25
+ - preventCsvInjection
37
26
 
27
+ ## React hook
38
28
  ```jsx
39
- // components/Converter.jsx
40
29
  'use client';
41
-
42
30
  import { useJtcsv } from '@jtcsv/nextjs';
43
31
 
44
32
  export default function Converter() {
45
- const {
46
- convertCsvToJson,
47
- convertJsonToCsv,
48
- isLoading,
49
- error,
50
- result
51
- } = useJtcsv();
52
-
53
- const handleConvert = async () => {
54
- const csv = 'name,age\nJohn,30\nJane,25';
55
- const json = await convertCsvToJson(csv);
56
- console.log('Converted:', json);
57
- };
58
-
59
- return (
60
- <div>
61
- <button onClick={handleConvert} disabled={isLoading}>
62
- {isLoading ? 'Converting...' : 'Convert CSV to JSON'}
63
- </button>
64
- {error && <div>Error: {error}</div>}
65
- {result && <pre>{JSON.stringify(result, null, 2)}</pre>}
66
- </div>
67
- );
33
+ const { convertCsvToJson, convertJsonToCsv, isLoading, error, result } = useJtcsv();
34
+ return null;
68
35
  }
69
36
  ```
70
37
 
71
- ## 📖 Документация
72
-
73
- ### API Routes
74
-
75
- #### Автоматическая конвертация
76
-
38
+ ## Components and utilities
77
39
  ```javascript
78
- // pages/api/convert.js
79
- import { handler } from '@jtcsv/nextjs/route';
80
-
81
- export default handler;
82
- ```
83
-
84
- **Примеры запросов:**
85
-
86
- ```bash
87
- # JSON → CSV
88
- curl -X POST http://localhost:3000/api/convert \
89
- -H "Content-Type: application/json" \
90
- -d '[{"name":"John","age":30}]'
91
-
92
- # CSV → JSON
93
- curl -X POST http://localhost:3000/api/convert \
94
- -H "Content-Type: text/csv" \
95
- -d 'name,age\nJohn,30\nJane,25'
96
-
97
- # Специфичный формат вывода
98
- curl -X POST "http://localhost:3000/api/convert?format=csv" \
99
- -H "Content-Type: application/json" \
100
- -d '[{"name":"John","age":30}]'
40
+ import {
41
+ CsvFileUploader,
42
+ downloadCsv,
43
+ createJtcsvApiClient,
44
+ JtcsvProvider,
45
+ useJtcsvContext
46
+ } from '@jtcsv/nextjs';
101
47
  ```
102
48
 
103
- #### Специализированные handlers
104
-
49
+ ## Route helpers
105
50
  ```javascript
106
- // pages/api/convert/[...path].js
107
- import {
51
+ import {
108
52
  csvToJsonHandler,
109
53
  jsonToCsvHandler,
110
- healthCheckHandler
54
+ healthCheckHandler,
55
+ createJtcsvApiEndpoint
111
56
  } from '@jtcsv/nextjs/route';
112
-
113
- export default async function handler(req, res) {
114
- const { path } = req.query;
115
-
116
- switch (path?.[0]) {
117
- case 'csv-to-json':
118
- return csvToJsonHandler(req, res);
119
- case 'json-to-csv':
120
- return jsonToCsvHandler(req, res);
121
- case 'health':
122
- return healthCheckHandler(req, res);
123
- default:
124
- res.status(404).json({ error: 'Not found' });
125
- }
126
- }
127
- ```
128
-
129
- ### React Hooks
130
-
131
- #### useJtcsv
132
-
133
- ```jsx
134
- import { useJtcsv } from '@jtcsv/nextjs';
135
-
136
- function Converter() {
137
- const {
138
- convertCsvToJson,
139
- convertJsonToCsv,
140
- isLoading,
141
- error,
142
- result,
143
- stats,
144
- reset
145
- } = useJtcsv({
146
- delimiter: ',', // Разделитель CSV
147
- parseNumbers: true, // Парсить числа
148
- parseBooleans: true, // Парсить булевы значения
149
- preventCsvInjection: true // Защита от инъекций
150
- });
151
-
152
- // ...
153
- }
154
- ```
155
-
156
- #### JtcsvProvider (Context)
157
-
158
- ```jsx
159
- // app/layout.jsx
160
- import { JtcsvProvider } from '@jtcsv/nextjs';
161
-
162
- export default function Layout({ children }) {
163
- return (
164
- <JtcsvProvider options={{ delimiter: ',' }}>
165
- {children}
166
- </JtcsvProvider>
167
- );
168
- }
169
-
170
- // components/Converter.jsx
171
- 'use client';
172
- import { useJtcsvContext } from '@jtcsv/nextjs';
173
-
174
- export default function Converter() {
175
- const { csvToJson, jsonToCsv } = useJtcsvContext();
176
- // ...
177
- }
178
- ```
179
-
180
- ### Компоненты
181
-
182
- #### CsvFileUploader
183
-
184
- ```jsx
185
- import { CsvFileUploader } from '@jtcsv/nextjs';
186
-
187
- function FileUpload() {
188
- const handleConvert = (result, stats) => {
189
- console.log('Converted:', result);
190
- console.log('Stats:', stats);
191
- };
192
-
193
- return (
194
- <CsvFileUploader
195
- onConvert={handleConvert}
196
- options={{ delimiter: ',' }}
197
- >
198
- <button>📁 Upload CSV File</button>
199
- </CsvFileUploader>
200
- );
201
- }
202
- ```
203
-
204
- ### Утилиты
205
-
206
- #### downloadCsv
207
-
208
- ```javascript
209
- import { downloadCsv } from '@jtcsv/nextjs';
210
-
211
- const data = [{ name: 'John', age: 30 }];
212
- await downloadCsv(data, 'users.csv', { delimiter: ',' });
213
- ```
214
-
215
- #### createJtcsvApiClient
216
-
217
- ```javascript
218
- import { createJtcsvApiClient } from '@jtcsv/nextjs';
219
-
220
- const api = createJtcsvApiClient('/api/convert');
221
-
222
- // Конвертация CSV в JSON
223
- const json = await api.csvToJson('name,age\nJohn,30');
224
-
225
- // Конвертация JSON в CSV
226
- const csv = await api.jsonToCsv([{ name: 'John', age: 30 }]);
227
-
228
- // Проверка здоровья
229
- const health = await api.health();
230
- ```
231
-
232
- ## 🔧 Конфигурация
233
-
234
- ### Опции API Route
235
-
236
- | Параметр | Тип | По умолчанию | Описание |
237
- |----------|-----|--------------|----------|
238
- | `format` | `string` | `auto` | Формат вывода: `json`, `csv` |
239
- | `delimiter` | `string` | `','` | Разделитель CSV |
240
- | `includeHeaders` | `boolean` | `true` | Включать заголовки в CSV |
241
- | `parseNumbers` | `boolean` | `true` | Парсить числа |
242
- | `parseBooleans` | `boolean` | `true` | Парсить булевы значения |
243
- | `useFastPath` | `boolean` | `true` | Использовать Fast-Path Engine |
244
- | `preventCsvInjection` | `boolean` | `true` | Защита от CSV инъекций |
245
-
246
- ### Опции React Hook
247
-
248
- ```javascript
249
- const options = {
250
- delimiter: ',', // Разделитель CSV
251
- includeHeaders: true, // Включать заголовки
252
- parseNumbers: true, // Парсить числа
253
- parseBooleans: true, // Парсить булевы значения
254
- useFastPath: true, // Использовать Fast-Path Engine
255
- preventCsvInjection: true,// Защита от инъекций
256
- rfc4180Compliant: true // Соответствие RFC 4180
257
- };
258
- ```
259
-
260
- ## 🌐 Примеры
261
-
262
- ### Полный пример приложения
263
-
264
- Смотрите `examples/ConverterComponent.jsx` для полного примера React компонента.
265
-
266
- ### Кастомная API Route
267
-
268
- ```javascript
269
- // pages/api/convert/secure.js
270
- import { handler } from '@jtcsv/nextjs/route';
271
-
272
- export default async function secureHandler(req, res) {
273
- // Проверка API ключа
274
- const apiKey = req.headers['x-api-key'];
275
- if (apiKey !== process.env.API_KEY) {
276
- return res.status(401).json({ error: 'Unauthorized' });
277
- }
278
-
279
- // Rate limiting
280
- const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
281
- // ... ваша логика rate limiting
282
-
283
- // Логирование
284
- console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
285
-
286
- // Вызов основного обработчика
287
- return handler(req, res);
288
- }
289
-
290
- export const config = {
291
- api: {
292
- bodyParser: {
293
- sizeLimit: '10mb'
294
- }
295
- }
296
- };
297
- ```
298
-
299
- ### Интеграция с формой
300
-
301
- ```jsx
302
- 'use client';
303
- import { useState } from 'react';
304
- import { useJtcsv, downloadCsv } from '@jtcsv/nextjs';
305
-
306
- export default function DataForm() {
307
- const [data, setData] = useState([]);
308
- const { convertJsonToCsv } = useJtcsv();
309
-
310
- const handleSubmit = async (e) => {
311
- e.preventDefault();
312
-
313
- // Конвертируем данные в CSV
314
- const csv = await convertJsonToCsv(data);
315
-
316
- // Скачиваем файл
317
- await downloadCsv(data, 'form-data.csv');
318
-
319
- // Отправляем на сервер
320
- await fetch('/api/submit', {
321
- method: 'POST',
322
- headers: { 'Content-Type': 'application/json' },
323
- body: JSON.stringify({ csv, data })
324
- });
325
- };
326
-
327
- return (
328
- <form onSubmit={handleSubmit}>
329
- {/* поля формы */}
330
- <button type="submit">Submit and Download CSV</button>
331
- </form>
332
- );
333
- }
334
- ```
335
-
336
- ## 🛡️ Безопасность
337
-
338
- ### Защита от CSV инъекций
339
-
340
- Все конвертации по умолчанию защищены от CSV инъекций:
341
-
342
- ```javascript
343
- // Опасные данные
344
- const dangerous = [{ formula: '=1+1', command: '@echo hello' }];
345
-
346
- // Безопасный CSV
347
- const safeCsv = await jsonToCsv(dangerous, { preventCsvInjection: true });
348
- // Результат: "'=1+1','@echo hello"
349
- ```
350
-
351
- ### Валидация размера
352
-
353
- ```javascript
354
- // pages/api/convert.js
355
- export const config = {
356
- api: {
357
- bodyParser: {
358
- sizeLimit: '10mb' // Ограничение размера
359
- }
360
- }
361
- };
362
- ```
363
-
364
- ## 📊 Мониторинг
365
-
366
- ### Health Check
367
-
368
- ```bash
369
- curl http://localhost:3000/api/convert/health
370
- ```
371
-
372
- **Ответ:**
373
- ```json
374
- {
375
- "service": "jtcsv-nextjs-api",
376
- "status": "healthy",
377
- "version": "1.0.0",
378
- "timestamp": "2026-01-23T10:30:00.000Z",
379
- "features": {
380
- "csvToJson": true,
381
- "jsonToCsv": true,
382
- "fastPathEngine": true,
383
- "csvInjectionProtection": true,
384
- "streaming": true,
385
- "ndjson": true
386
- }
387
- }
388
- ```
389
-
390
- ### Статистика
391
-
392
- Каждая операция возвращает статистику:
393
-
394
- ```json
395
- {
396
- "stats": {
397
- "inputSize": 45,
398
- "outputSize": 28,
399
- "processingTime": 12,
400
- "conversion": "json→csv",
401
- "rows": 2
402
- }
403
- }
404
- ```
405
-
406
- ## 🔌 TypeScript
407
-
408
- Полная поддержка TypeScript:
409
-
410
- ```typescript
411
- import {
412
- useJtcsv,
413
- CsvFileUploader,
414
- type ConversionStats
415
- } from '@jtcsv/nextjs';
416
-
417
- interface MyComponentProps {
418
- onConvert: (result: any[], stats: ConversionStats) => void;
419
- }
420
- ```
421
-
422
- ## 🧪 Тестирование
423
-
424
- ```bash
425
- # Запуск примеров
426
- cd plugins/nextjs-api/examples
427
-
428
- # Тестовые запросы к API
429
- curl -X POST http://localhost:3000/api/convert \
430
- -H "Content-Type: application/json" \
431
- -d '[{"test":"data"}]'
432
- ```
433
-
434
- ## 📄 Лицензия
435
-
436
- MIT
437
-
438
- ## 🤝 Вклад в развитие
439
-
440
- 1. Форкните репозиторий
441
- 2. Создайте ветку для вашей функции
442
- 3. Закоммитьте изменения
443
- 4. Запушьте в ветку
444
- 5. Откройте Pull Request
445
-
446
- ## 📞 Поддержка
447
-
448
- - [Issues](https://github.com/Linol-Hamelton/jtcsv/issues)
449
- - [Discussions](https://github.com/Linol-Hamelton/jtcsv/discussions)
450
- - [Documentation](https://github.com/Linol-Hamelton/jtcsv#readme)
451
-
452
-
57
+ ```
@@ -6,7 +6,7 @@
6
6
  * @date 2026-01-23
7
7
  */
8
8
 
9
- import { csvToJson, jsonToCsv } from 'jtcsv
9
+ import { csvToJson, jsonToCsv } from 'jtcsv';
10
10
 
11
11
  export { csvToJson, jsonToCsv };
12
12
 
@@ -385,4 +385,3 @@ export function useJtcsvContext() {
385
385
  // Экспортируем все из route.js
386
386
  export * from './route';
387
387
 
388
-
@@ -10,7 +10,7 @@
10
10
  * 2. Или импортируйте функции в существующие API routes
11
11
  */
12
12
 
13
- import { csvToJson, jsonToCsv } from 'jtcsv
13
+ import { csvToJson, jsonToCsv } from 'jtcsv';
14
14
 
15
15
  /**
16
16
  * Конфигурация Next.js API route
@@ -369,4 +369,3 @@ export function createJtcsvApiEndpoint(options = {}) {
369
369
  };
370
370
  }
371
371
 
372
-
@@ -1,25 +1,24 @@
1
1
  # @jtcsv/nuxt
2
2
 
3
- Nuxt module for JTCSV.
3
+ Nuxt module that injects `jtcsv` into the Nuxt app and provides a `useJtcsv` composable.
4
4
 
5
5
  ## Install
6
6
  ```bash
7
7
  npm install @jtcsv/nuxt jtcsv
8
8
  ```
9
9
 
10
- ## Setup
10
+ ## Nuxt config
11
11
  ```typescript
12
12
  export default defineNuxtConfig({
13
13
  modules: ['@jtcsv/nuxt'],
14
- jtcsv: {
15
- autoimport: true
16
- }
14
+ jtcsv: { autoimport: true }
17
15
  });
18
16
  ```
19
17
 
20
18
  ## Usage
21
19
  ```vue
22
20
  <script setup>
23
- const { csvToJson, jsonToCsv } = useJtcsv();
21
+ const jtcsv = useJtcsv();
22
+ const csv = jtcsv.jsonToCsv([{ id: 1 }]);
24
23
  </script>
25
- ```
24
+ ```
@@ -1,6 +1,6 @@
1
1
  # @jtcsv/remix
2
2
 
3
- Remix helpers for JTCSV.
3
+ Remix helpers for CSV form uploads and CSV responses.
4
4
 
5
5
  ## Install
6
6
  ```bash
@@ -8,19 +8,19 @@ npm install @jtcsv/remix jtcsv
8
8
  ```
9
9
 
10
10
  ## Usage
11
- ```typescript
12
- import { parseFormData, generateCsvResponse } from 'jtcsv/remix';
11
+ ```javascript
12
+ import { parseFormData, generateCsvResponse } from '@jtcsv/remix';
13
13
 
14
14
  export async function action({ request }) {
15
- const rows = await parseFormData(request, { delimiter: ',' });
16
- return { parsed: rows };
15
+ const rows = await parseFormData(request, { fieldName: 'file', delimiter: ',' });
16
+ return { rows };
17
17
  }
18
18
 
19
19
  export async function loader() {
20
- return generateCsvResponse([{ id: 1, name: 'John' }], 'export.csv');
20
+ return generateCsvResponse([{ id: 1 }], 'export.csv');
21
21
  }
22
22
  ```
23
23
 
24
- ## Notes
25
- - `parseFormData` looks for a file field named `file` by default.
26
- - You can override the field name with `{ fieldName: 'upload' }`.
24
+ ## Exports
25
+ - parseFormData
26
+ - generateCsvResponse
@@ -1,6 +1,6 @@
1
1
  # @jtcsv/sveltekit
2
2
 
3
- SvelteKit helpers for JTCSV.
3
+ Helpers for parsing CSV requests and returning CSV responses in SvelteKit.
4
4
 
5
5
  ## Install
6
6
  ```bash
@@ -8,21 +8,21 @@ npm install @jtcsv/sveltekit jtcsv
8
8
  ```
9
9
 
10
10
  ## Usage
11
- ```typescript
12
- import { parseCsv, generateCsv } from 'jtcsv/sveltekit';
11
+ ```javascript
12
+ import { parseCsv, generateCsv } from '@jtcsv/sveltekit';
13
13
 
14
14
  export const actions = {
15
15
  upload: async ({ request }) => {
16
16
  const rows = await parseCsv(request, { delimiter: ',' });
17
- return { success: true, rows };
17
+ return { rows };
18
18
  }
19
19
  };
20
20
 
21
21
  export async function GET() {
22
- return generateCsv([{ id: 1, name: 'John' }], 'export.csv');
22
+ return generateCsv([{ id: 1 }], 'export.csv');
23
23
  }
24
24
  ```
25
25
 
26
- ## Notes
27
- - `parseCsv` reads `request.text()` by default.
28
- - Use `{ formData: true, fieldName: 'file' }` for multipart uploads.
26
+ ## Exports
27
+ - parseCsv
28
+ - generateCsv
@@ -1,6 +1,6 @@
1
1
  # @jtcsv/trpc
2
2
 
3
- tRPC helper for JTCSV.
3
+ Middleware helper that parses CSV input for tRPC procedures.
4
4
 
5
5
  ## Install
6
6
  ```bash
@@ -8,15 +8,18 @@ npm install @jtcsv/trpc jtcsv
8
8
  ```
9
9
 
10
10
  ## Usage
11
- ```typescript
11
+ ```javascript
12
12
  import { initTRPC } from '@trpc/server';
13
13
  import { z } from 'zod';
14
- import { createCsvProcedure } from 'jtcsv/trpc';
14
+ import { createCsvProcedure } from '@jtcsv/trpc';
15
15
 
16
16
  const t = initTRPC.create();
17
17
 
18
18
  export const router = t.router({
19
- parseCsv: createCsvProcedure(t, z.string(), { delimiter: ',' })
20
- .mutation(async ({ input }) => ({ parsed: input }))
19
+ parseCsv: createCsvProcedure(t, z.string())
20
+ .mutation(async ({ input }) => ({ rows: input }))
21
21
  });
22
22
  ```
23
+
24
+ ## Exports
25
+ - createCsvProcedure
@@ -2,7 +2,8 @@
2
2
  // Функции, которые работают только в браузере
3
3
 
4
4
  import { jsonToCsv } from './json-to-csv-browser.js';
5
- import { csvToJson } from './csv-to-json-browser.js';
5
+ import { csvToJson, csvToJsonIterator } from './csv-to-json-browser.js';
6
+ import { csvToJsonStream, jsonToCsvStream, jsonToNdjsonStream } from './streams.js';
6
7
  import { ValidationError } from './errors-browser.js';
7
8
 
8
9
  /**
@@ -130,6 +131,29 @@ export async function parseCsvFile(file, options = {}) {
130
131
  });
131
132
  }
132
133
 
134
+ /**
135
+ * Stream CSV file as async iterator without full buffering.
136
+ *
137
+ * @param {File} file - File selected from input
138
+ * @param {Object} [options] - csvToJson options
139
+ * @returns {AsyncGenerator<Object>} Async iterator of rows
140
+ */
141
+ export function parseCsvFileStream(file, options = {}) {
142
+ if (typeof window === 'undefined') {
143
+ throw new ValidationError('parseCsvFileStream() is browser-only. Use readCsvAsJson() in Node.js');
144
+ }
145
+
146
+ if (!(file instanceof File)) {
147
+ throw new ValidationError('Input must be a File object');
148
+ }
149
+
150
+ if (!file.name.toLowerCase().endsWith('.csv')) {
151
+ throw new ValidationError('File must have .csv extension');
152
+ }
153
+
154
+ return csvToJsonIterator(file, options);
155
+ }
156
+
133
157
  /**
134
158
  * Создает CSV файл из JSON данных (альтернатива downloadAsCsv)
135
159
  * Возвращает Blob вместо автоматического скачивания
@@ -183,7 +207,13 @@ if (typeof module !== 'undefined' && module.exports) {
183
207
  module.exports = {
184
208
  downloadAsCsv,
185
209
  parseCsvFile,
210
+ parseCsvFileStream,
186
211
  createCsvBlob,
187
- parseCsvBlob
212
+ parseCsvBlob,
213
+ jsonToCsvStream,
214
+ jsonToNdjsonStream,
215
+ csvToJsonStream
188
216
  };
189
- }
217
+ }
218
+
219
+ export { jsonToCsvStream, jsonToNdjsonStream, csvToJsonStream };