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.
- package/README.md +204 -115
- package/bin/jtcsv.ts +2612 -0
- package/browser.d.ts +142 -0
- package/dist/benchmark.js +446 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/bin/jtcsv.js +1940 -0
- package/dist/bin/jtcsv.js.map +1 -0
- package/dist/csv-to-json.js +1262 -0
- package/dist/csv-to-json.js.map +1 -0
- package/dist/errors.js +291 -0
- package/dist/errors.js.map +1 -0
- package/dist/eslint.config.js +147 -0
- package/dist/eslint.config.js.map +1 -0
- package/dist/index-core.js +95 -0
- package/dist/index-core.js.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/json-save.js +229 -0
- package/dist/json-save.js.map +1 -0
- package/dist/json-to-csv.js +576 -0
- package/dist/json-to-csv.js.map +1 -0
- package/dist/jtcsv-core.cjs.js +1736 -0
- package/dist/jtcsv-core.cjs.js.map +1 -0
- package/dist/jtcsv-core.esm.js +1708 -0
- package/dist/jtcsv-core.esm.js.map +1 -0
- package/dist/jtcsv-core.umd.js +1742 -0
- package/dist/jtcsv-core.umd.js.map +1 -0
- package/dist/jtcsv-full.cjs.js +2241 -0
- package/dist/jtcsv-full.cjs.js.map +1 -0
- package/dist/jtcsv-full.esm.js +2209 -0
- package/dist/jtcsv-full.esm.js.map +1 -0
- package/dist/jtcsv-full.umd.js +2247 -0
- package/dist/jtcsv-full.umd.js.map +1 -0
- package/dist/jtcsv-workers.esm.js +768 -0
- package/dist/jtcsv-workers.esm.js.map +1 -0
- package/dist/jtcsv-workers.umd.js +782 -0
- package/dist/jtcsv-workers.umd.js.map +1 -0
- package/dist/jtcsv.cjs.js +1996 -2048
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +1992 -2048
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +2157 -2209
- package/dist/jtcsv.umd.js.map +1 -1
- package/dist/plugins/express-middleware/index.js +350 -0
- package/dist/plugins/express-middleware/index.js.map +1 -0
- package/dist/plugins/fastify-plugin/index.js +315 -0
- package/dist/plugins/fastify-plugin/index.js.map +1 -0
- package/dist/plugins/hono/index.js +111 -0
- package/dist/plugins/hono/index.js.map +1 -0
- package/dist/plugins/nestjs/index.js +112 -0
- package/dist/plugins/nestjs/index.js.map +1 -0
- package/dist/plugins/nuxt/index.js +53 -0
- package/dist/plugins/nuxt/index.js.map +1 -0
- package/dist/plugins/remix/index.js +133 -0
- package/dist/plugins/remix/index.js.map +1 -0
- package/dist/plugins/sveltekit/index.js +155 -0
- package/dist/plugins/sveltekit/index.js.map +1 -0
- package/dist/plugins/trpc/index.js +136 -0
- package/dist/plugins/trpc/index.js.map +1 -0
- package/dist/run-demo.js +49 -0
- package/dist/run-demo.js.map +1 -0
- package/dist/src/browser/browser-functions.js +193 -0
- package/dist/src/browser/browser-functions.js.map +1 -0
- package/dist/src/browser/core.js +123 -0
- package/dist/src/browser/core.js.map +1 -0
- package/dist/src/browser/csv-to-json-browser.js +353 -0
- package/dist/src/browser/csv-to-json-browser.js.map +1 -0
- package/dist/src/browser/errors-browser.js +219 -0
- package/dist/src/browser/errors-browser.js.map +1 -0
- package/dist/src/browser/extensions/plugins.js +106 -0
- package/dist/src/browser/extensions/plugins.js.map +1 -0
- package/dist/src/browser/extensions/workers.js +66 -0
- package/dist/src/browser/extensions/workers.js.map +1 -0
- package/dist/src/browser/index.js +140 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/browser/json-to-csv-browser.js +225 -0
- package/dist/src/browser/json-to-csv-browser.js.map +1 -0
- package/dist/src/browser/streams.js +340 -0
- package/dist/src/browser/streams.js.map +1 -0
- package/dist/src/browser/workers/csv-parser.worker.js +264 -0
- package/dist/src/browser/workers/csv-parser.worker.js.map +1 -0
- package/dist/src/browser/workers/worker-pool.js +338 -0
- package/dist/src/browser/workers/worker-pool.js.map +1 -0
- package/dist/src/core/delimiter-cache.js +196 -0
- package/dist/src/core/delimiter-cache.js.map +1 -0
- package/dist/src/core/node-optimizations.js +279 -0
- package/dist/src/core/node-optimizations.js.map +1 -0
- package/dist/src/core/plugin-system.js +399 -0
- package/dist/src/core/plugin-system.js.map +1 -0
- package/dist/src/core/transform-hooks.js +348 -0
- package/dist/src/core/transform-hooks.js.map +1 -0
- package/dist/src/engines/fast-path-engine-new.js +262 -0
- package/dist/src/engines/fast-path-engine-new.js.map +1 -0
- package/dist/src/engines/fast-path-engine.js +671 -0
- package/dist/src/engines/fast-path-engine.js.map +1 -0
- package/dist/src/errors.js +18 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/formats/ndjson-parser.js +332 -0
- package/dist/src/formats/ndjson-parser.js.map +1 -0
- package/dist/src/formats/tsv-parser.js +230 -0
- package/dist/src/formats/tsv-parser.js.map +1 -0
- package/dist/src/index-with-plugins.js +259 -0
- package/dist/src/index-with-plugins.js.map +1 -0
- package/dist/src/types/index.js +3 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/utils/bom-utils.js +267 -0
- package/dist/src/utils/bom-utils.js.map +1 -0
- package/dist/src/utils/encoding-support.js +77 -0
- package/dist/src/utils/encoding-support.js.map +1 -0
- package/dist/src/utils/schema-validator.js +609 -0
- package/dist/src/utils/schema-validator.js.map +1 -0
- package/dist/src/utils/transform-loader.js +281 -0
- package/dist/src/utils/transform-loader.js.map +1 -0
- package/dist/src/utils/validators.js +40 -0
- package/dist/src/utils/validators.js.map +1 -0
- package/dist/src/utils/zod-adapter.js +144 -0
- package/dist/src/utils/zod-adapter.js.map +1 -0
- package/dist/src/web-server/index.js +648 -0
- package/dist/src/web-server/index.js.map +1 -0
- package/dist/src/workers/csv-multithreaded.js +211 -0
- package/dist/src/workers/csv-multithreaded.js.map +1 -0
- package/dist/src/workers/csv-parser.worker.js +179 -0
- package/dist/src/workers/csv-parser.worker.js.map +1 -0
- package/dist/src/workers/worker-pool.js +228 -0
- package/dist/src/workers/worker-pool.js.map +1 -0
- package/dist/stream-csv-to-json.js +665 -0
- package/dist/stream-csv-to-json.js.map +1 -0
- package/dist/stream-json-to-csv.js +389 -0
- package/dist/stream-json-to-csv.js.map +1 -0
- package/examples/advanced/conditional-transformations.ts +446 -0
- package/examples/advanced/csv-parser.worker.ts +89 -0
- package/examples/advanced/nested-objects-example.ts +306 -0
- package/examples/advanced/performance-optimization.ts +504 -0
- package/examples/advanced/run-demo-server.ts +116 -0
- package/examples/advanced/web-worker-usage.html +874 -0
- package/examples/async-multithreaded-example.ts +335 -0
- package/examples/cli-advanced-usage.md +290 -0
- package/examples/{cli-batch-processing.js → cli-batch-processing.ts} +38 -38
- package/examples/{cli-tool.js → cli-tool.ts} +5 -8
- package/examples/{error-handling.js → error-handling.ts} +356 -324
- package/examples/{express-api.js → express-api.ts} +161 -164
- package/examples/{large-dataset-example.js → large-dataset-example.ts} +201 -182
- package/examples/{ndjson-processing.js → ndjson-processing.ts} +456 -434
- package/examples/{plugin-excel-exporter.js → plugin-excel-exporter.ts} +6 -7
- package/examples/react-integration.tsx +637 -0
- package/examples/{schema-validation.js → schema-validation.ts} +2 -2
- package/examples/simple-usage.ts +194 -0
- package/examples/{streaming-example.js → streaming-example.ts} +12 -12
- package/index.d.ts +187 -18
- package/package.json +75 -81
- package/plugins.d.ts +37 -0
- package/schema.d.ts +103 -0
- package/src/browser/browser-functions.ts +402 -0
- package/src/browser/core.ts +152 -0
- package/src/browser/csv-to-json-browser.d.ts +3 -0
- package/src/browser/csv-to-json-browser.ts +494 -0
- package/src/browser/{errors-browser.js → errors-browser.ts} +305 -197
- package/src/browser/extensions/plugins.ts +93 -0
- package/src/browser/extensions/workers.ts +39 -0
- package/src/browser/globals.d.ts +5 -0
- package/src/browser/index.ts +192 -0
- package/src/browser/json-to-csv-browser.d.ts +3 -0
- package/src/browser/json-to-csv-browser.ts +338 -0
- package/src/browser/streams.ts +403 -0
- package/src/browser/workers/{csv-parser.worker.js → csv-parser.worker.ts} +3 -3
- package/src/browser/workers/{worker-pool.js → worker-pool.ts} +51 -30
- package/src/core/delimiter-cache.ts +320 -0
- package/src/core/{node-optimizations.js → node-optimizations.ts} +448 -407
- package/src/core/plugin-system.ts +588 -0
- package/src/core/transform-hooks.ts +566 -0
- package/src/engines/{fast-path-engine-new.js → fast-path-engine-new.ts} +11 -2
- package/src/engines/{fast-path-engine.js → fast-path-engine.ts} +79 -53
- package/src/errors.ts +1 -0
- package/src/formats/{ndjson-parser.js → ndjson-parser.ts} +24 -16
- package/src/formats/{tsv-parser.js → tsv-parser.ts} +18 -17
- package/src/{index-with-plugins.js → index-with-plugins.ts} +381 -357
- package/src/types/index.ts +275 -0
- package/src/utils/bom-utils.ts +373 -0
- package/src/utils/encoding-support.ts +155 -0
- package/src/utils/{schema-validator.js → schema-validator.ts} +814 -589
- package/src/utils/transform-loader.ts +389 -0
- package/src/utils/validators.ts +35 -0
- package/src/utils/zod-adapter.ts +280 -0
- package/src/web-server/{index.js → index.ts} +19 -19
- package/src/workers/csv-multithreaded.ts +310 -0
- package/src/workers/csv-parser.worker.ts +227 -0
- package/src/workers/worker-pool.ts +409 -0
- package/bin/jtcsv.js +0 -2462
- package/csv-to-json.js +0 -688
- package/errors.js +0 -208
- package/examples/simple-usage.js +0 -282
- package/index.js +0 -68
- package/json-save.js +0 -254
- package/json-to-csv.js +0 -526
- package/plugins/README.md +0 -91
- package/plugins/express-middleware/README.md +0 -64
- package/plugins/express-middleware/example.js +0 -136
- package/plugins/express-middleware/index.d.ts +0 -114
- package/plugins/express-middleware/index.js +0 -360
- package/plugins/express-middleware/package.json +0 -52
- package/plugins/fastify-plugin/index.js +0 -406
- package/plugins/fastify-plugin/package.json +0 -55
- package/plugins/hono/README.md +0 -28
- package/plugins/hono/index.d.ts +0 -12
- package/plugins/hono/index.js +0 -36
- package/plugins/hono/package.json +0 -35
- package/plugins/nestjs/README.md +0 -35
- package/plugins/nestjs/index.d.ts +0 -25
- package/plugins/nestjs/index.js +0 -77
- package/plugins/nestjs/package.json +0 -37
- package/plugins/nextjs-api/README.md +0 -57
- package/plugins/nextjs-api/examples/ConverterComponent.jsx +0 -386
- package/plugins/nextjs-api/examples/api-convert.js +0 -69
- package/plugins/nextjs-api/index.js +0 -387
- package/plugins/nextjs-api/package.json +0 -63
- package/plugins/nextjs-api/route.js +0 -371
- package/plugins/nuxt/README.md +0 -24
- package/plugins/nuxt/index.js +0 -21
- package/plugins/nuxt/package.json +0 -35
- package/plugins/nuxt/runtime/composables/useJtcsv.js +0 -6
- package/plugins/nuxt/runtime/plugin.js +0 -6
- package/plugins/remix/README.md +0 -26
- package/plugins/remix/index.d.ts +0 -16
- package/plugins/remix/index.js +0 -62
- package/plugins/remix/package.json +0 -35
- package/plugins/sveltekit/README.md +0 -28
- package/plugins/sveltekit/index.d.ts +0 -17
- package/plugins/sveltekit/index.js +0 -54
- package/plugins/sveltekit/package.json +0 -33
- package/plugins/trpc/README.md +0 -25
- package/plugins/trpc/index.d.ts +0 -7
- package/plugins/trpc/index.js +0 -32
- package/plugins/trpc/package.json +0 -34
- package/src/browser/browser-functions.js +0 -219
- package/src/browser/csv-to-json-browser.js +0 -700
- package/src/browser/index.js +0 -113
- package/src/browser/json-to-csv-browser.js +0 -309
- package/src/browser/streams.js +0 -393
- package/src/core/delimiter-cache.js +0 -186
- package/src/core/plugin-system.js +0 -476
- package/src/core/transform-hooks.js +0 -350
- package/src/errors.js +0 -26
- package/src/utils/transform-loader.js +0 -205
- package/stream-csv-to-json.js +0 -542
- package/stream-json-to-csv.js +0 -464
- /package/examples/{web-workers-advanced.js → web-workers-advanced.ts} +0 -0
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Next.js API Route для JTCSV
|
|
3
|
-
* Готовый API endpoint для конвертации CSV/JSON в Next.js приложениях
|
|
4
|
-
*
|
|
5
|
-
* @version 1.0.0
|
|
6
|
-
* @date 2026-01-23
|
|
7
|
-
*
|
|
8
|
-
* @usage
|
|
9
|
-
* 1. Скопируйте этот файл в pages/api/convert.js
|
|
10
|
-
* 2. Или импортируйте функции в существующие API routes
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { csvToJson, jsonToCsv } from 'jtcsv';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Конфигурация Next.js API route
|
|
17
|
-
*/
|
|
18
|
-
export const config = {
|
|
19
|
-
api: {
|
|
20
|
-
bodyParser: {
|
|
21
|
-
sizeLimit: '50mb', // Максимальный размер тела запроса
|
|
22
|
-
|
|
23
|
-
// Кастомный парсер для определения формата
|
|
24
|
-
parse: (req) => {
|
|
25
|
-
const contentType = req.headers['content-type'] || '';
|
|
26
|
-
|
|
27
|
-
if (contentType.includes('application/json')) {
|
|
28
|
-
return JSON.parse(req.body);
|
|
29
|
-
} else if (contentType.includes('text/csv') || contentType.includes('text/plain')) {
|
|
30
|
-
return req.body;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Пытаемся определить автоматически
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(req.body);
|
|
36
|
-
} catch {
|
|
37
|
-
return req.body;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Основной обработчик API route
|
|
46
|
-
*
|
|
47
|
-
* @param {import('next').NextApiRequest} req - Next.js request object
|
|
48
|
-
* @param {import('next').NextApiResponse} res - Next.js response object
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* // Пример запроса:
|
|
52
|
-
* // POST /api/convert
|
|
53
|
-
* // Content-Type: application/json
|
|
54
|
-
* // Body: [{ "name": "John", "age": 30 }]
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* // Пример запроса:
|
|
58
|
-
* // POST /api/convert?format=csv
|
|
59
|
-
* // Content-Type: text/csv
|
|
60
|
-
* // Body: name,age\nJohn,30\nJane,25
|
|
61
|
-
*/
|
|
62
|
-
export default async function handler(req, res) {
|
|
63
|
-
// Поддерживаем только POST запросы
|
|
64
|
-
if (req.method !== 'POST') {
|
|
65
|
-
return res.status(405).json({
|
|
66
|
-
success: false,
|
|
67
|
-
error: 'Method not allowed',
|
|
68
|
-
allowed: ['POST']
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const startTime = Date.now();
|
|
73
|
-
const contentType = req.headers['content-type'] || '';
|
|
74
|
-
const acceptHeader = req.headers['accept'] || 'application/json';
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const {
|
|
78
|
-
format,
|
|
79
|
-
delimiter = ',',
|
|
80
|
-
includeHeaders = 'true',
|
|
81
|
-
parseNumbers = 'true',
|
|
82
|
-
parseBooleans = 'true',
|
|
83
|
-
useFastPath = 'true',
|
|
84
|
-
preventCsvInjection = 'true'
|
|
85
|
-
} = req.query;
|
|
86
|
-
|
|
87
|
-
// Определяем желаемый формат вывода
|
|
88
|
-
let outputFormat = format || (acceptHeader.includes('text/csv') ? 'csv' : 'json');
|
|
89
|
-
|
|
90
|
-
// Определяем формат входных данных
|
|
91
|
-
let inputFormat = 'unknown';
|
|
92
|
-
|
|
93
|
-
if (contentType.includes('application/json') || Array.isArray(req.body)) {
|
|
94
|
-
inputFormat = 'json';
|
|
95
|
-
} else if (contentType.includes('text/csv') ||
|
|
96
|
-
contentType.includes('text/plain') ||
|
|
97
|
-
(typeof req.body === 'string' && req.body.includes(','))) {
|
|
98
|
-
inputFormat = 'csv';
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (inputFormat === 'unknown') {
|
|
102
|
-
return res.status(400).json({
|
|
103
|
-
success: false,
|
|
104
|
-
error: 'Unable to determine input format',
|
|
105
|
-
code: 'UNKNOWN_FORMAT',
|
|
106
|
-
suggestions: [
|
|
107
|
-
'Set Content-Type header to application/json or text/csv',
|
|
108
|
-
'Or send JSON array/object or CSV string'
|
|
109
|
-
]
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Опции конвертации
|
|
114
|
-
const options = {
|
|
115
|
-
delimiter,
|
|
116
|
-
includeHeaders: includeHeaders === 'true',
|
|
117
|
-
parseNumbers: parseNumbers === 'true',
|
|
118
|
-
parseBooleans: parseBooleans === 'true',
|
|
119
|
-
useFastPath: useFastPath === 'true',
|
|
120
|
-
preventCsvInjection: preventCsvInjection === 'true',
|
|
121
|
-
rfc4180Compliant: true
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
let result;
|
|
125
|
-
let stats = {
|
|
126
|
-
inputSize: 0,
|
|
127
|
-
outputSize: 0,
|
|
128
|
-
processingTime: 0,
|
|
129
|
-
conversion: `${inputFormat}→${outputFormat}`
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
// Выполняем конвертацию
|
|
133
|
-
if (inputFormat === 'json' && outputFormat === 'csv') {
|
|
134
|
-
const jsonData = Array.isArray(req.body) ? req.body : [req.body];
|
|
135
|
-
stats.inputSize = Buffer.byteLength(JSON.stringify(jsonData));
|
|
136
|
-
|
|
137
|
-
result = await jsonToCsv(jsonData, options);
|
|
138
|
-
stats.outputSize = Buffer.byteLength(result);
|
|
139
|
-
|
|
140
|
-
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
|
|
141
|
-
res.setHeader('Content-Disposition', 'attachment; filename="data.csv"');
|
|
142
|
-
|
|
143
|
-
} else if (inputFormat === 'csv' && outputFormat === 'json') {
|
|
144
|
-
const csvData = typeof req.body === 'string' ? req.body : String(req.body);
|
|
145
|
-
stats.inputSize = Buffer.byteLength(csvData);
|
|
146
|
-
|
|
147
|
-
result = await csvToJson(csvData, options);
|
|
148
|
-
stats.outputSize = Buffer.byteLength(JSON.stringify(result));
|
|
149
|
-
|
|
150
|
-
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
151
|
-
|
|
152
|
-
} else {
|
|
153
|
-
// Нет необходимости в конвертации
|
|
154
|
-
result = req.body;
|
|
155
|
-
stats.conversion = 'none';
|
|
156
|
-
stats.inputSize = Buffer.byteLength(JSON.stringify(result));
|
|
157
|
-
stats.outputSize = stats.inputSize;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
stats.processingTime = Date.now() - startTime;
|
|
161
|
-
|
|
162
|
-
// Формируем ответ
|
|
163
|
-
const response = {
|
|
164
|
-
success: true,
|
|
165
|
-
data: result,
|
|
166
|
-
format: outputFormat,
|
|
167
|
-
inputFormat,
|
|
168
|
-
stats,
|
|
169
|
-
options: {
|
|
170
|
-
...options,
|
|
171
|
-
delimiter
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
// Если запрашивали CSV, отправляем как plain text
|
|
176
|
-
if (outputFormat === 'csv') {
|
|
177
|
-
return res.status(200).send(result);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return res.status(200).json(response);
|
|
181
|
-
|
|
182
|
-
} catch (error) {
|
|
183
|
-
console.error('Conversion error:', error);
|
|
184
|
-
|
|
185
|
-
const errorResponse = {
|
|
186
|
-
success: false,
|
|
187
|
-
error: error.message,
|
|
188
|
-
code: error.code || 'CONVERSION_ERROR',
|
|
189
|
-
timestamp: new Date().toISOString()
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
// Добавляем дополнительную информацию для отладки в development
|
|
193
|
-
if (process.env.NODE_ENV === 'development') {
|
|
194
|
-
errorResponse.stack = error.stack;
|
|
195
|
-
errorResponse.details = {
|
|
196
|
-
contentType: req.headers['content-type'],
|
|
197
|
-
contentLength: req.headers['content-length'],
|
|
198
|
-
method: req.method,
|
|
199
|
-
url: req.url,
|
|
200
|
-
query: req.query
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return res.status(400).json(errorResponse);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Специализированный обработчик для CSV → JSON
|
|
210
|
-
*/
|
|
211
|
-
export async function csvToJsonHandler(req, res) {
|
|
212
|
-
if (req.method !== 'POST') {
|
|
213
|
-
return res.status(405).json({
|
|
214
|
-
success: false,
|
|
215
|
-
error: 'Method not allowed',
|
|
216
|
-
allowed: ['POST']
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const startTime = Date.now();
|
|
221
|
-
|
|
222
|
-
try {
|
|
223
|
-
const csvData = req.body;
|
|
224
|
-
|
|
225
|
-
if (!csvData || (typeof csvData !== 'string' && !Buffer.isBuffer(csvData))) {
|
|
226
|
-
return res.status(400).json({
|
|
227
|
-
success: false,
|
|
228
|
-
error: 'CSV data is required'
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const {
|
|
233
|
-
delimiter = ',',
|
|
234
|
-
parseNumbers = 'true',
|
|
235
|
-
parseBooleans = 'true',
|
|
236
|
-
useFastPath = 'true'
|
|
237
|
-
} = req.query;
|
|
238
|
-
|
|
239
|
-
const result = await csvToJson(csvData, {
|
|
240
|
-
delimiter,
|
|
241
|
-
parseNumbers: parseNumbers === 'true',
|
|
242
|
-
parseBooleans: parseBooleans === 'true',
|
|
243
|
-
useFastPath: useFastPath === 'true',
|
|
244
|
-
preventCsvInjection: true,
|
|
245
|
-
rfc4180Compliant: true
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
return res.status(200).json({
|
|
249
|
-
success: true,
|
|
250
|
-
data: result,
|
|
251
|
-
stats: {
|
|
252
|
-
rows: result.length,
|
|
253
|
-
processingTime: Date.now() - startTime
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
} catch (error) {
|
|
258
|
-
return res.status(400).json({
|
|
259
|
-
success: false,
|
|
260
|
-
error: error.message
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Специализированный обработчик для JSON → CSV
|
|
267
|
-
*/
|
|
268
|
-
export async function jsonToCsvHandler(req, res) {
|
|
269
|
-
if (req.method !== 'POST') {
|
|
270
|
-
return res.status(405).json({
|
|
271
|
-
success: false,
|
|
272
|
-
error: 'Method not allowed',
|
|
273
|
-
allowed: ['POST']
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const startTime = Date.now();
|
|
278
|
-
|
|
279
|
-
try {
|
|
280
|
-
const jsonData = req.body;
|
|
281
|
-
|
|
282
|
-
if (!jsonData || (typeof jsonData !== 'object' && typeof jsonData !== 'string')) {
|
|
283
|
-
return res.status(400).json({
|
|
284
|
-
success: false,
|
|
285
|
-
error: 'JSON data is required'
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const {
|
|
290
|
-
delimiter = ',',
|
|
291
|
-
includeHeaders = 'true',
|
|
292
|
-
useFastPath = 'true'
|
|
293
|
-
} = req.query;
|
|
294
|
-
|
|
295
|
-
const data = typeof jsonData === 'string' ? JSON.parse(jsonData) : jsonData;
|
|
296
|
-
const result = await jsonToCsv(data, {
|
|
297
|
-
delimiter,
|
|
298
|
-
includeHeaders: includeHeaders === 'true',
|
|
299
|
-
useFastPath: useFastPath === 'true',
|
|
300
|
-
preventCsvInjection: true,
|
|
301
|
-
rfc4180Compliant: true
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
|
|
305
|
-
res.setHeader('Content-Disposition', 'attachment; filename="data.csv"');
|
|
306
|
-
|
|
307
|
-
return res.status(200).send(result);
|
|
308
|
-
|
|
309
|
-
} catch (error) {
|
|
310
|
-
return res.status(400).json({
|
|
311
|
-
success: false,
|
|
312
|
-
error: error.message
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Health check endpoint
|
|
319
|
-
*/
|
|
320
|
-
export async function healthCheckHandler(req, res) {
|
|
321
|
-
if (req.method !== 'GET') {
|
|
322
|
-
return res.status(405).json({
|
|
323
|
-
success: false,
|
|
324
|
-
error: 'Method not allowed',
|
|
325
|
-
allowed: ['GET']
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return res.status(200).json({
|
|
330
|
-
service: 'jtcsv-nextjs-api',
|
|
331
|
-
status: 'healthy',
|
|
332
|
-
version: '1.0.0',
|
|
333
|
-
timestamp: new Date().toISOString(),
|
|
334
|
-
features: {
|
|
335
|
-
csvToJson: true,
|
|
336
|
-
jsonToCsv: true,
|
|
337
|
-
fastPathEngine: true,
|
|
338
|
-
csvInjectionProtection: true,
|
|
339
|
-
streaming: true,
|
|
340
|
-
ndjson: true
|
|
341
|
-
}
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Утилита для создания кастомных API endpoints
|
|
347
|
-
*/
|
|
348
|
-
export function createJtcsvApiEndpoint(options = {}) {
|
|
349
|
-
const {
|
|
350
|
-
route = '/api/convert',
|
|
351
|
-
allowedMethods = ['POST'],
|
|
352
|
-
defaultFormat = 'json',
|
|
353
|
-
...defaultOptions
|
|
354
|
-
} = options;
|
|
355
|
-
|
|
356
|
-
return async function customHandler(req, res) {
|
|
357
|
-
// Проверяем разрешенные методы
|
|
358
|
-
if (!allowedMethods.includes(req.method)) {
|
|
359
|
-
return res.status(405).json({
|
|
360
|
-
success: false,
|
|
361
|
-
error: `Method ${req.method} not allowed`,
|
|
362
|
-
allowed: allowedMethods
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Здесь можно добавить кастомную логику
|
|
367
|
-
// Пока просто используем основной handler
|
|
368
|
-
return handler(req, res);
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
|
package/plugins/nuxt/README.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# @jtcsv/nuxt
|
|
2
|
-
|
|
3
|
-
Nuxt module that injects `jtcsv` into the Nuxt app and provides a `useJtcsv` composable.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
```bash
|
|
7
|
-
npm install @jtcsv/nuxt jtcsv
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
## Nuxt config
|
|
11
|
-
```typescript
|
|
12
|
-
export default defineNuxtConfig({
|
|
13
|
-
modules: ['@jtcsv/nuxt'],
|
|
14
|
-
jtcsv: { autoimport: true }
|
|
15
|
-
});
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Usage
|
|
19
|
-
```vue
|
|
20
|
-
<script setup>
|
|
21
|
-
const jtcsv = useJtcsv();
|
|
22
|
-
const csv = jtcsv.jsonToCsv([{ id: 1 }]);
|
|
23
|
-
</script>
|
|
24
|
-
```
|
package/plugins/nuxt/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const { defineNuxtModule, addPlugin, addImports, createResolver } = require('@nuxt/kit');
|
|
2
|
-
|
|
3
|
-
module.exports = defineNuxtModule({
|
|
4
|
-
meta: {
|
|
5
|
-
name: '@jtcsv/nuxt',
|
|
6
|
-
configKey: 'jtcsv'
|
|
7
|
-
},
|
|
8
|
-
defaults: {
|
|
9
|
-
autoimport: true
|
|
10
|
-
},
|
|
11
|
-
setup(options) {
|
|
12
|
-
const resolver = createResolver(__dirname);
|
|
13
|
-
addPlugin(resolver.resolve('runtime/plugin'));
|
|
14
|
-
|
|
15
|
-
if (options.autoimport !== false) {
|
|
16
|
-
addImports([
|
|
17
|
-
{ name: 'useJtcsv', from: resolver.resolve('runtime/composables/useJtcsv') }
|
|
18
|
-
]);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@jtcsv/nuxt",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "Nuxt module for JTCSV (auto-imported composable)",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"nuxt",
|
|
8
|
-
"module",
|
|
9
|
-
"csv",
|
|
10
|
-
"json",
|
|
11
|
-
"converter",
|
|
12
|
-
"jtcsv"
|
|
13
|
-
],
|
|
14
|
-
"author": "Ruslan Fomenko",
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/Linol-Hamelton/jtcsv.git",
|
|
19
|
-
"directory": "plugins/nuxt"
|
|
20
|
-
},
|
|
21
|
-
"bugs": {
|
|
22
|
-
"url": "https://github.com/Linol-Hamelton/jtcsv/issues"
|
|
23
|
-
},
|
|
24
|
-
"homepage": "https://github.com/Linol-Hamelton/jtcsv/tree/main/plugins/nuxt#readme",
|
|
25
|
-
"peerDependencies": {
|
|
26
|
-
"@nuxt/kit": "^3.0.0",
|
|
27
|
-
"jtcsv": "^2.1.3",
|
|
28
|
-
"nuxt": "^3.0.0"
|
|
29
|
-
},
|
|
30
|
-
"files": [
|
|
31
|
-
"index.js",
|
|
32
|
-
"README.md",
|
|
33
|
-
"runtime/"
|
|
34
|
-
]
|
|
35
|
-
}
|
package/plugins/remix/README.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# @jtcsv/remix
|
|
2
|
-
|
|
3
|
-
Remix helpers for CSV form uploads and CSV responses.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
```bash
|
|
7
|
-
npm install @jtcsv/remix jtcsv
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
## Usage
|
|
11
|
-
```javascript
|
|
12
|
-
import { parseFormData, generateCsvResponse } from '@jtcsv/remix';
|
|
13
|
-
|
|
14
|
-
export async function action({ request }) {
|
|
15
|
-
const rows = await parseFormData(request, { fieldName: 'file', delimiter: ',' });
|
|
16
|
-
return { rows };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function loader() {
|
|
20
|
-
return generateCsvResponse([{ id: 1 }], 'export.csv');
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Exports
|
|
25
|
-
- parseFormData
|
|
26
|
-
- generateCsvResponse
|
package/plugins/remix/index.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { CsvToJsonOptions, JsonToCsvOptions } from 'jtcsv';
|
|
2
|
-
|
|
3
|
-
export interface RemixCsvParseOptions extends CsvToJsonOptions {
|
|
4
|
-
fieldName?: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function parseFormData(
|
|
8
|
-
request: Request,
|
|
9
|
-
options?: RemixCsvParseOptions
|
|
10
|
-
): Promise<unknown[]>;
|
|
11
|
-
|
|
12
|
-
export function generateCsvResponse(
|
|
13
|
-
data: unknown[] | Record<string, unknown>,
|
|
14
|
-
filename?: string,
|
|
15
|
-
options?: JsonToCsvOptions
|
|
16
|
-
): Response;
|
package/plugins/remix/index.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
const jtcsv = require('jtcsv');
|
|
2
|
-
|
|
3
|
-
function normalizeFilename(filename) {
|
|
4
|
-
if (!filename || typeof filename !== 'string') {
|
|
5
|
-
return 'export.csv';
|
|
6
|
-
}
|
|
7
|
-
return filename.includes('.') ? filename : `${filename}.csv`;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async function extractCsvText(formData, fieldName) {
|
|
11
|
-
if (formData.has(fieldName)) {
|
|
12
|
-
const value = formData.get(fieldName);
|
|
13
|
-
if (value && typeof value.text === 'function') {
|
|
14
|
-
return await value.text();
|
|
15
|
-
}
|
|
16
|
-
if (value != null) {
|
|
17
|
-
return String(value);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
for (const value of formData.values()) {
|
|
22
|
-
if (value && typeof value.text === 'function') {
|
|
23
|
-
return await value.text();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function parseFormData(request, options = {}) {
|
|
31
|
-
if (!request || typeof request.formData !== 'function') {
|
|
32
|
-
throw new Error('parseFormData expects a Remix Request with formData()');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const { fieldName = 'file', ...csvOptions } = options;
|
|
36
|
-
const formData = await request.formData();
|
|
37
|
-
const csvText = await extractCsvText(formData, fieldName);
|
|
38
|
-
|
|
39
|
-
if (!csvText) {
|
|
40
|
-
throw new Error('No CSV file or field found in form data');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return jtcsv.csvToJson(csvText, csvOptions);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function generateCsvResponse(data, filename = 'export.csv', options = {}) {
|
|
47
|
-
const safeName = normalizeFilename(filename);
|
|
48
|
-
const rows = Array.isArray(data) ? data : [data];
|
|
49
|
-
const csv = jtcsv.jsonToCsv(rows, options);
|
|
50
|
-
|
|
51
|
-
return new Response(csv, {
|
|
52
|
-
headers: {
|
|
53
|
-
'Content-Type': 'text/csv; charset=utf-8',
|
|
54
|
-
'Content-Disposition': `attachment; filename="${safeName}"`
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
module.exports = {
|
|
60
|
-
parseFormData,
|
|
61
|
-
generateCsvResponse
|
|
62
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@jtcsv/remix",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "Remix helpers for JTCSV (form-data parsing and CSV responses)",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"types": "index.d.ts",
|
|
7
|
-
"keywords": [
|
|
8
|
-
"remix",
|
|
9
|
-
"csv",
|
|
10
|
-
"json",
|
|
11
|
-
"converter",
|
|
12
|
-
"jtcsv",
|
|
13
|
-
"formdata",
|
|
14
|
-
"response"
|
|
15
|
-
],
|
|
16
|
-
"author": "Ruslan Fomenko",
|
|
17
|
-
"license": "MIT",
|
|
18
|
-
"repository": {
|
|
19
|
-
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/Linol-Hamelton/jtcsv.git",
|
|
21
|
-
"directory": "plugins/remix"
|
|
22
|
-
},
|
|
23
|
-
"bugs": {
|
|
24
|
-
"url": "https://github.com/Linol-Hamelton/jtcsv/issues"
|
|
25
|
-
},
|
|
26
|
-
"homepage": "https://github.com/Linol-Hamelton/jtcsv/tree/main/plugins/remix#readme",
|
|
27
|
-
"peerDependencies": {
|
|
28
|
-
"jtcsv": "^2.1.3"
|
|
29
|
-
},
|
|
30
|
-
"files": [
|
|
31
|
-
"index.js",
|
|
32
|
-
"index.d.ts",
|
|
33
|
-
"README.md"
|
|
34
|
-
]
|
|
35
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# @jtcsv/sveltekit
|
|
2
|
-
|
|
3
|
-
Helpers for parsing CSV requests and returning CSV responses in SvelteKit.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
```bash
|
|
7
|
-
npm install @jtcsv/sveltekit jtcsv
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
## Usage
|
|
11
|
-
```javascript
|
|
12
|
-
import { parseCsv, generateCsv } from '@jtcsv/sveltekit';
|
|
13
|
-
|
|
14
|
-
export const actions = {
|
|
15
|
-
upload: async ({ request }) => {
|
|
16
|
-
const rows = await parseCsv(request, { delimiter: ',' });
|
|
17
|
-
return { rows };
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export async function GET() {
|
|
22
|
-
return generateCsv([{ id: 1 }], 'export.csv');
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Exports
|
|
27
|
-
- parseCsv
|
|
28
|
-
- generateCsv
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { CsvToJsonOptions, JsonToCsvOptions } from 'jtcsv';
|
|
2
|
-
|
|
3
|
-
export interface SvelteKitCsvParseOptions extends CsvToJsonOptions {
|
|
4
|
-
fieldName?: string;
|
|
5
|
-
formData?: boolean;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function parseCsv(
|
|
9
|
-
request: Request,
|
|
10
|
-
options?: SvelteKitCsvParseOptions
|
|
11
|
-
): Promise<unknown[]>;
|
|
12
|
-
|
|
13
|
-
export function generateCsv(
|
|
14
|
-
data: unknown[] | Record<string, unknown>,
|
|
15
|
-
filename?: string,
|
|
16
|
-
options?: JsonToCsvOptions
|
|
17
|
-
): Response;
|