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.
- package/LICENSE +1 -1
- package/README.md +60 -341
- package/bin/jtcsv.js +2462 -1372
- package/csv-to-json.js +35 -26
- package/dist/jtcsv.cjs.js +807 -133
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +800 -134
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +807 -133
- package/dist/jtcsv.umd.js.map +1 -1
- package/errors.js +20 -0
- package/examples/browser-vanilla.html +37 -0
- package/examples/cli-batch-processing.js +38 -0
- package/examples/error-handling.js +324 -0
- package/examples/ndjson-processing.js +434 -0
- package/examples/react-integration.jsx +637 -0
- package/examples/schema-validation.js +640 -0
- package/examples/simple-usage.js +10 -7
- package/examples/typescript-example.ts +486 -0
- package/examples/web-workers-advanced.js +28 -0
- package/index.d.ts +2 -0
- package/json-save.js +2 -1
- package/json-to-csv.js +171 -131
- package/package.json +20 -4
- package/plugins/README.md +41 -467
- package/plugins/express-middleware/README.md +32 -274
- package/plugins/hono/README.md +16 -13
- package/plugins/nestjs/README.md +13 -11
- package/plugins/nextjs-api/README.md +28 -423
- package/plugins/nextjs-api/index.js +1 -2
- package/plugins/nextjs-api/route.js +1 -2
- package/plugins/nuxt/README.md +6 -7
- package/plugins/remix/README.md +9 -9
- package/plugins/sveltekit/README.md +8 -8
- package/plugins/trpc/README.md +8 -5
- package/src/browser/browser-functions.js +33 -3
- package/src/browser/csv-to-json-browser.js +269 -11
- package/src/browser/errors-browser.js +19 -1
- package/src/browser/index.js +39 -5
- package/src/browser/streams.js +393 -0
- package/src/browser/workers/csv-parser.worker.js +20 -2
- package/src/browser/workers/worker-pool.js +507 -447
- package/src/core/plugin-system.js +4 -0
- package/src/engines/fast-path-engine.js +31 -23
- package/src/errors.js +26 -0
- package/src/formats/ndjson-parser.js +54 -5
- package/src/formats/tsv-parser.js +4 -1
- package/src/utils/schema-validator.js +594 -0
- package/src/utils/transform-loader.js +205 -0
- package/src/web-server/index.js +683 -0
- package/stream-csv-to-json.js +16 -87
- package/stream-json-to-csv.js +18 -86
|
@@ -1,306 +1,64 @@
|
|
|
1
1
|
# @jtcsv/express-middleware
|
|
2
2
|
|
|
3
|
-
Express middleware
|
|
4
|
-
|
|
5
|
-
## 📦 Установка
|
|
3
|
+
Express middleware that converts CSV/JSON payloads and exposes the converted data on `req.converted`.
|
|
6
4
|
|
|
5
|
+
## Install
|
|
7
6
|
```bash
|
|
8
7
|
npm install @jtcsv/express-middleware express jtcsv
|
|
9
8
|
```
|
|
10
9
|
|
|
11
|
-
##
|
|
12
|
-
|
|
10
|
+
## Quick start
|
|
13
11
|
```javascript
|
|
14
12
|
const express = require('express');
|
|
15
|
-
const bodyParser = require('body-parser');
|
|
16
13
|
const { middleware } = require('@jtcsv/express-middleware');
|
|
17
14
|
|
|
18
15
|
const app = express();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
app.use(bodyParser.json());
|
|
22
|
-
app.use(bodyParser.text({ type: 'text/csv' }));
|
|
23
|
-
|
|
24
|
-
// JTCSV middleware для автоматической конвертации
|
|
16
|
+
app.use(express.json());
|
|
17
|
+
app.use(express.text({ type: 'text/csv' }));
|
|
25
18
|
app.use(middleware());
|
|
26
19
|
|
|
27
|
-
// Роут, использующий автоматическую конвертацию
|
|
28
20
|
app.post('/api/convert', (req, res) => {
|
|
29
|
-
|
|
30
|
-
res.json({
|
|
31
|
-
success: true,
|
|
32
|
-
data: req.converted.data,
|
|
33
|
-
format: req.converted.format,
|
|
34
|
-
stats: req.converted.stats
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
app.listen(3000, () => {
|
|
39
|
-
console.log('Server started on port 3000');
|
|
21
|
+
res.json(req.converted);
|
|
40
22
|
});
|
|
41
23
|
```
|
|
42
24
|
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
### Основное middleware
|
|
25
|
+
## Options
|
|
26
|
+
The middleware detects input/output format based on `Content-Type`, `Accept`, and `?format=csv`.
|
|
46
27
|
|
|
47
28
|
```javascript
|
|
48
29
|
app.use(middleware({
|
|
49
|
-
|
|
50
|
-
autoDetect: true, // Автоматическое определение формата
|
|
51
|
-
delimiter: ',', // Разделитель CSV
|
|
52
|
-
enableFastPath: true, // Включить Fast-Path Engine
|
|
53
|
-
preventCsvInjection: true, // Защита от CSV инъекций
|
|
54
|
-
rfc4180Compliant: true // Соответствие RFC 4180
|
|
55
|
-
}));
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Специфичные роуты
|
|
59
|
-
|
|
60
|
-
```javascript
|
|
61
|
-
const {
|
|
62
|
-
csvToJsonRoute,
|
|
63
|
-
jsonToCsvRoute,
|
|
64
|
-
uploadCsvRoute,
|
|
65
|
-
healthCheck
|
|
66
|
-
} = require('@jtcsv/express-middleware');
|
|
67
|
-
|
|
68
|
-
// Конвертация CSV в JSON
|
|
69
|
-
app.post('/api/csv-to-json', csvToJsonRoute({
|
|
30
|
+
autoDetect: true,
|
|
70
31
|
delimiter: ',',
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
includeHeaders: true,
|
|
79
|
-
preventCsvInjection: true
|
|
32
|
+
enableFastPath: true,
|
|
33
|
+
preventCsvInjection: true,
|
|
34
|
+
rfc4180Compliant: true,
|
|
35
|
+
conversionOptions: {
|
|
36
|
+
parseNumbers: true,
|
|
37
|
+
parseBooleans: true
|
|
38
|
+
}
|
|
80
39
|
}));
|
|
81
|
-
|
|
82
|
-
// Загрузка CSV файла (требуется multer)
|
|
83
|
-
const multer = require('multer');
|
|
84
|
-
const upload = multer({ dest: 'uploads/' });
|
|
85
|
-
app.post('/api/upload-csv', upload.single('file'), uploadCsvRoute());
|
|
86
|
-
|
|
87
|
-
// Health check
|
|
88
|
-
app.get('/api/health', healthCheck());
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## 🔧 Конфигурация
|
|
92
|
-
|
|
93
|
-
### Опции middleware
|
|
94
|
-
|
|
95
|
-
| Опция | Тип | По умолчанию | Описание |
|
|
96
|
-
|-------|-----|--------------|----------|
|
|
97
|
-
| `maxSize` | `string` | `'10mb'` | Максимальный размер тела запроса |
|
|
98
|
-
| `autoDetect` | `boolean` | `true` | Автоматическое определение формата |
|
|
99
|
-
| `delimiter` | `string` | `','` | Разделитель CSV |
|
|
100
|
-
| `enableFastPath` | `boolean` | `true` | Включить Fast-Path Engine |
|
|
101
|
-
| `preventCsvInjection` | `boolean` | `true` | Защита от CSV инъекций |
|
|
102
|
-
| `rfc4180Compliant` | `boolean` | `true` | Соответствие RFC 4180 |
|
|
103
|
-
| `conversionOptions` | `object` | `{}` | Дополнительные опции конвертации |
|
|
104
|
-
|
|
105
|
-
### Формат ответа
|
|
106
|
-
|
|
107
|
-
После обработки middleware, в объекте `req` появляется свойство `converted`:
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
{
|
|
111
|
-
data: any, // Конвертированные данные
|
|
112
|
-
format: 'json' | 'csv', // Формат выходных данных
|
|
113
|
-
inputFormat: 'json' | 'csv' | 'unknown', // Формат входных данных
|
|
114
|
-
outputFormat: 'json' | 'csv', // Формат выходных данных
|
|
115
|
-
stats: { // Статистика конвертации
|
|
116
|
-
inputSize: number, // Размер входных данных (байты)
|
|
117
|
-
outputSize: number, // Размер выходных данных (байты)
|
|
118
|
-
processingTime: number, // Время обработки (мс)
|
|
119
|
-
conversion: string // Тип конвертации (например: "json→csv")
|
|
120
|
-
},
|
|
121
|
-
options: object // Использованные опции
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## 🌐 Примеры запросов
|
|
126
|
-
|
|
127
|
-
### Конвертация JSON в CSV
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
curl -X POST http://localhost:3000/api/convert \
|
|
131
|
-
-H "Content-Type: application/json" \
|
|
132
|
-
-d '[{"name":"John","age":30},{"name":"Jane","age":25}]'
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**Ответ:**
|
|
136
|
-
```csv
|
|
137
|
-
name,age
|
|
138
|
-
John,30
|
|
139
|
-
Jane,25
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Конвертация CSV в JSON
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
curl -X POST http://localhost:3000/api/convert \
|
|
146
|
-
-H "Content-Type: text/csv" \
|
|
147
|
-
-d 'name,age\nJohn,30\nJane,25'
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
**Ответ:**
|
|
151
|
-
```json
|
|
152
|
-
[
|
|
153
|
-
{"name":"John","age":30},
|
|
154
|
-
{"name":"Jane","age":25}
|
|
155
|
-
]
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Специфичный формат вывода
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
# Запросить CSV даже если отправляем JSON
|
|
162
|
-
curl -X POST http://localhost:3000/api/convert \
|
|
163
|
-
-H "Content-Type: application/json" \
|
|
164
|
-
-H "Accept: text/csv" \
|
|
165
|
-
-d '[{"name":"John","age":30}]'
|
|
166
|
-
|
|
167
|
-
# Или через query параметр
|
|
168
|
-
curl -X POST "http://localhost:3000/api/convert?format=csv" \
|
|
169
|
-
-H "Content-Type: application/json" \
|
|
170
|
-
-d '[{"name":"John","age":30}]'
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
## 🛡️ Безопасность
|
|
174
|
-
|
|
175
|
-
### CSV Injection Protection
|
|
176
|
-
|
|
177
|
-
Middleware автоматически защищает от CSV инъекций:
|
|
178
|
-
|
|
179
|
-
```javascript
|
|
180
|
-
// Входные данные с потенциальной инъекцией
|
|
181
|
-
const dangerousData = [
|
|
182
|
-
{ formula: '=1+1', command: '@echo hello' }
|
|
183
|
-
];
|
|
184
|
-
|
|
185
|
-
// Безопасный CSV
|
|
186
|
-
const safeCsv = jsonToCsv(dangerousData, {
|
|
187
|
-
preventCsvInjection: true
|
|
188
|
-
});
|
|
189
|
-
// Результат: "'=1+1','@echo hello"
|
|
190
40
|
```
|
|
191
41
|
|
|
192
|
-
|
|
42
|
+
Note: body size limits are controlled by your body parser (for example `express.json({ limit: '10mb' })`).
|
|
193
43
|
|
|
44
|
+
## Helpers
|
|
194
45
|
```javascript
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
### Health Check
|
|
203
|
-
|
|
204
|
-
```bash
|
|
205
|
-
curl http://localhost:3000/api/health
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
**Ответ:**
|
|
209
|
-
```json
|
|
210
|
-
{
|
|
211
|
-
"service": "jtcsv-express-middleware",
|
|
212
|
-
"status": "healthy",
|
|
213
|
-
"version": "1.0.0",
|
|
214
|
-
"timestamp": "2026-01-23T10:30:00.000Z",
|
|
215
|
-
"features": {
|
|
216
|
-
"csvToJson": true,
|
|
217
|
-
"jsonToCsv": true,
|
|
218
|
-
"fastPathEngine": true,
|
|
219
|
-
"csvInjectionProtection": true,
|
|
220
|
-
"streaming": true
|
|
221
|
-
}
|
|
222
|
-
}
|
|
46
|
+
const {
|
|
47
|
+
csvToJsonRoute,
|
|
48
|
+
jsonToCsvRoute,
|
|
49
|
+
uploadCsvRoute,
|
|
50
|
+
healthCheck
|
|
51
|
+
} = require('@jtcsv/express-middleware');
|
|
223
52
|
```
|
|
224
53
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
Каждый запрос включает статистику конвертации:
|
|
228
|
-
|
|
54
|
+
## req.converted shape
|
|
229
55
|
```json
|
|
230
56
|
{
|
|
231
|
-
"
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
57
|
+
"data": "...",
|
|
58
|
+
"format": "json",
|
|
59
|
+
"inputFormat": "csv",
|
|
60
|
+
"outputFormat": "json",
|
|
61
|
+
"stats": { "inputSize": 0, "outputSize": 0, "processingTime": 0, "conversion": "csv->json" },
|
|
62
|
+
"options": {}
|
|
237
63
|
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
## 🔌 Интеграция
|
|
241
|
-
|
|
242
|
-
### С TypeScript
|
|
243
|
-
|
|
244
|
-
```typescript
|
|
245
|
-
import { Request, Response } from 'express';
|
|
246
|
-
import { middleware, ConvertedData } from '@jtcsv/express-middleware';
|
|
247
|
-
|
|
248
|
-
app.use(middleware());
|
|
249
|
-
|
|
250
|
-
app.post('/api/convert', (req: Request, res: Response) => {
|
|
251
|
-
const converted = req.converted as ConvertedData;
|
|
252
|
-
// TypeScript знает тип converted
|
|
253
|
-
});
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### С другими middleware
|
|
257
|
-
|
|
258
|
-
```javascript
|
|
259
|
-
const express = require('express');
|
|
260
|
-
const cors = require('cors');
|
|
261
|
-
const helmet = require('helmet');
|
|
262
|
-
const rateLimit = require('express-rate-limit');
|
|
263
|
-
const { middleware } = require('@jtcsv/express-middleware');
|
|
264
|
-
|
|
265
|
-
const app = express();
|
|
266
|
-
|
|
267
|
-
app.use(cors());
|
|
268
|
-
app.use(helmet());
|
|
269
|
-
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));
|
|
270
|
-
app.use(express.json());
|
|
271
|
-
app.use(express.text({ type: 'text/csv' }));
|
|
272
|
-
app.use(middleware());
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
## 🧪 Тестирование
|
|
276
|
-
|
|
277
|
-
```bash
|
|
278
|
-
# Запуск примера
|
|
279
|
-
cd plugins/express-middleware
|
|
280
|
-
node example.js
|
|
281
|
-
|
|
282
|
-
# Тестовые запросы
|
|
283
|
-
curl -X POST http://localhost:3000/api/convert \
|
|
284
|
-
-H "Content-Type: application/json" \
|
|
285
|
-
-d '[{"test":"data"}]'
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## 📄 Лицензия
|
|
289
|
-
|
|
290
|
-
MIT
|
|
291
|
-
|
|
292
|
-
## 🤝 Вклад в развитие
|
|
293
|
-
|
|
294
|
-
1. Форкните репозиторий
|
|
295
|
-
2. Создайте ветку для вашей функции (`git checkout -b feature/amazing-feature`)
|
|
296
|
-
3. Закоммитьте изменения (`git commit -m 'Add amazing feature'`)
|
|
297
|
-
4. Запушьте в ветку (`git push origin feature/amazing-feature`)
|
|
298
|
-
5. Откройте Pull Request
|
|
299
|
-
|
|
300
|
-
## 📞 Поддержка
|
|
301
|
-
|
|
302
|
-
- [Issues](https://github.com/Linol-Hamelton/jtcsv/issues)
|
|
303
|
-
- [Discussions](https://github.com/Linol-Hamelton/jtcsv/discussions)
|
|
304
|
-
- [Documentation](https://github.com/Linol-Hamelton/jtcsv#readme)
|
|
305
|
-
|
|
306
|
-
|
|
64
|
+
```
|
package/plugins/hono/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @jtcsv/hono
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Minimal helpers for Hono routes.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
```bash
|
|
@@ -8,18 +8,21 @@ npm install @jtcsv/hono jtcsv
|
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
## Usage
|
|
11
|
-
```
|
|
11
|
+
```javascript
|
|
12
12
|
import { Hono } from 'hono';
|
|
13
|
-
import { csvMiddleware, createCsvResponse } from 'jtcsv/hono';
|
|
13
|
+
import { csvMiddleware, createCsvResponse } from '@jtcsv/hono';
|
|
14
14
|
|
|
15
|
-
const app = new Hono()
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
});
|
|
15
|
+
const app = new Hono();
|
|
16
|
+
|
|
17
|
+
app.use('/upload', csvMiddleware());
|
|
18
|
+
app.post('/upload', (c) => c.json({ rows: c.get('csv') }));
|
|
19
|
+
|
|
20
|
+
app.get('/export', (c) => {
|
|
21
|
+
const { csv, headers } = createCsvResponse([{ id: 1 }], 'export.csv');
|
|
22
|
+
return c.text(csv, 200, headers);
|
|
23
|
+
});
|
|
25
24
|
```
|
|
25
|
+
|
|
26
|
+
## Exports
|
|
27
|
+
- csvMiddleware
|
|
28
|
+
- createCsvResponse
|
package/plugins/nestjs/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @jtcsv/nestjs
|
|
2
2
|
|
|
3
|
-
NestJS interceptors and
|
|
3
|
+
NestJS interceptors for parsing CSV payloads and returning CSV responses.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
```bash
|
|
@@ -9,25 +9,27 @@ npm install @jtcsv/nestjs jtcsv
|
|
|
9
9
|
|
|
10
10
|
## Usage
|
|
11
11
|
```typescript
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { Controller, Post, Body, UseInterceptors } from '@nestjs/common';
|
|
13
|
+
import { CsvParserInterceptor, CsvDownloadDecorator } from '@jtcsv/nestjs';
|
|
14
14
|
|
|
15
15
|
@Controller('data')
|
|
16
16
|
export class DataController {
|
|
17
17
|
@Post('upload')
|
|
18
18
|
@CsvParserInterceptor({ delimiter: ',' })
|
|
19
|
-
|
|
20
|
-
return {
|
|
19
|
+
upload(@Body() body: any[]) {
|
|
20
|
+
return { rows: body };
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
@
|
|
23
|
+
@Post('export')
|
|
24
24
|
@CsvDownloadDecorator({ filename: 'export.csv' })
|
|
25
|
-
|
|
26
|
-
return [{ id: 1, name: '
|
|
25
|
+
exportCsv() {
|
|
26
|
+
return [{ id: 1, name: 'Jane' }];
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
##
|
|
32
|
-
-
|
|
33
|
-
-
|
|
31
|
+
## Exports
|
|
32
|
+
- CsvParserInterceptor
|
|
33
|
+
- CsvDownloadDecorator
|
|
34
|
+
- createCsvParserInterceptor
|
|
35
|
+
- createCsvDownloadInterceptor
|