jtcsv 2.2.7 → 3.0.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 +31 -1
- package/bin/jtcsv.js +891 -821
- package/bin/jtcsv.ts +2534 -0
- package/csv-to-json.js +168 -145
- package/dist/jtcsv-core.cjs.js +1407 -0
- package/dist/jtcsv-core.cjs.js.map +1 -0
- package/dist/jtcsv-core.esm.js +1379 -0
- package/dist/jtcsv-core.esm.js.map +1 -0
- package/dist/jtcsv-core.umd.js +1413 -0
- package/dist/jtcsv-core.umd.js.map +1 -0
- package/dist/jtcsv-full.cjs.js +1912 -0
- package/dist/jtcsv-full.cjs.js.map +1 -0
- package/dist/jtcsv-full.esm.js +1880 -0
- package/dist/jtcsv-full.esm.js.map +1 -0
- package/dist/jtcsv-full.umd.js +1918 -0
- package/dist/jtcsv-full.umd.js.map +1 -0
- package/dist/jtcsv-workers.esm.js +759 -0
- package/dist/jtcsv-workers.esm.js.map +1 -0
- package/dist/jtcsv-workers.umd.js +773 -0
- package/dist/jtcsv-workers.umd.js.map +1 -0
- package/dist/jtcsv.cjs.js +61 -19
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +61 -19
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +61 -19
- package/dist/jtcsv.umd.js.map +1 -1
- package/errors.js +188 -2
- package/examples/advanced/conditional-transformations.js +446 -0
- package/examples/advanced/conditional-transformations.ts +446 -0
- package/examples/advanced/csv-parser.worker.js +89 -0
- package/examples/advanced/csv-parser.worker.ts +89 -0
- package/examples/advanced/nested-objects-example.js +306 -0
- package/examples/advanced/nested-objects-example.ts +306 -0
- package/examples/advanced/performance-optimization.js +504 -0
- package/examples/advanced/performance-optimization.ts +504 -0
- package/examples/advanced/run-demo-server.js +116 -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 +288 -0
- package/examples/cli-batch-processing.ts +38 -0
- package/examples/cli-tool.js +0 -3
- package/examples/cli-tool.ts +183 -0
- package/examples/error-handling.js +21 -7
- package/examples/error-handling.ts +356 -0
- package/examples/express-api.js +0 -3
- package/examples/express-api.ts +164 -0
- package/examples/large-dataset-example.js +0 -3
- package/examples/large-dataset-example.ts +204 -0
- package/examples/ndjson-processing.js +1 -1
- package/examples/ndjson-processing.ts +456 -0
- package/examples/plugin-excel-exporter.js +3 -4
- package/examples/plugin-excel-exporter.ts +406 -0
- package/examples/react-integration.tsx +637 -0
- package/examples/schema-validation.ts +640 -0
- package/examples/simple-usage.js +254 -254
- package/examples/simple-usage.ts +194 -0
- package/examples/streaming-example.js +4 -5
- package/examples/streaming-example.ts +419 -0
- package/examples/web-workers-advanced.ts +28 -0
- package/index.d.ts +1 -3
- package/index.js +15 -1
- package/json-save.js +9 -3
- package/json-to-csv.js +168 -21
- package/package.json +69 -10
- package/plugins/express-middleware/README.md +21 -2
- package/plugins/express-middleware/example.js +3 -4
- package/plugins/express-middleware/example.ts +135 -0
- package/plugins/express-middleware/index.d.ts +1 -1
- package/plugins/express-middleware/index.js +270 -118
- package/plugins/express-middleware/index.ts +557 -0
- package/plugins/fastify-plugin/index.js +2 -4
- package/plugins/fastify-plugin/index.ts +443 -0
- package/plugins/hono/index.ts +226 -0
- package/plugins/nestjs/index.ts +201 -0
- package/plugins/nextjs-api/examples/ConverterComponent.tsx +386 -0
- package/plugins/nextjs-api/examples/api-convert.js +0 -2
- package/plugins/nextjs-api/examples/api-convert.ts +67 -0
- package/plugins/nextjs-api/index.tsx +339 -0
- package/plugins/nextjs-api/route.js +2 -3
- package/plugins/nextjs-api/route.ts +370 -0
- package/plugins/nuxt/index.ts +94 -0
- package/plugins/nuxt/runtime/composables/useJtcsv.ts +100 -0
- package/plugins/nuxt/runtime/plugin.ts +71 -0
- package/plugins/remix/index.js +1 -1
- package/plugins/remix/index.ts +260 -0
- package/plugins/sveltekit/index.js +1 -1
- package/plugins/sveltekit/index.ts +301 -0
- package/plugins/trpc/index.ts +267 -0
- package/src/browser/browser-functions.ts +402 -0
- package/src/browser/core.js +92 -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.js +36 -14
- package/src/browser/csv-to-json-browser.ts +264 -0
- package/src/browser/errors-browser.ts +303 -0
- package/src/browser/extensions/plugins.js +92 -0
- package/src/browser/extensions/plugins.ts +93 -0
- package/src/browser/extensions/workers.js +39 -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.js +13 -3
- package/src/browser/json-to-csv-browser.ts +262 -0
- package/src/browser/streams.js +12 -2
- package/src/browser/streams.ts +336 -0
- package/src/browser/workers/csv-parser.worker.ts +377 -0
- package/src/browser/workers/worker-pool.ts +548 -0
- package/src/core/delimiter-cache.js +22 -8
- package/src/core/delimiter-cache.ts +310 -0
- package/src/core/node-optimizations.ts +449 -0
- package/src/core/plugin-system.js +29 -11
- package/src/core/plugin-system.ts +400 -0
- package/src/core/transform-hooks.ts +558 -0
- package/src/engines/fast-path-engine-new.ts +347 -0
- package/src/engines/fast-path-engine.ts +854 -0
- package/src/errors.ts +72 -0
- package/src/formats/ndjson-parser.ts +469 -0
- package/src/formats/tsv-parser.ts +334 -0
- package/src/index-with-plugins.js +16 -9
- package/src/index-with-plugins.ts +395 -0
- package/src/types/index.ts +255 -0
- package/src/utils/bom-utils.js +259 -0
- package/src/utils/bom-utils.ts +373 -0
- package/src/utils/encoding-support.js +124 -0
- package/src/utils/encoding-support.ts +155 -0
- package/src/utils/schema-validator.js +19 -19
- package/src/utils/schema-validator.ts +819 -0
- package/src/utils/transform-loader.js +1 -1
- package/src/utils/transform-loader.ts +389 -0
- package/src/utils/zod-adapter.js +170 -0
- package/src/utils/zod-adapter.ts +280 -0
- package/src/web-server/index.js +10 -10
- package/src/web-server/index.ts +683 -0
- 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/stream-csv-to-json.js +26 -8
- package/stream-json-to-csv.js +1 -0
|
@@ -0,0 +1,370 @@
|
|
|
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
|
+
const 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
|
+
const 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
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nuxt plugin for jtcsv
|
|
3
|
+
* Provides jtcsv integration for Nuxt applications
|
|
4
|
+
* @module plugins/nuxt
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { CsvToJsonOptions, JsonToCsvOptions } from '../../src/types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Nuxt plugin options
|
|
11
|
+
*/
|
|
12
|
+
export interface NuxtPluginOptions {
|
|
13
|
+
/** Whether to enable async functions (default: true) */
|
|
14
|
+
async?: boolean;
|
|
15
|
+
/** Whether to enable worker support (default: false) */
|
|
16
|
+
workers?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Nuxt plugin implementation
|
|
21
|
+
* This is a simplified version that works with Nuxt 3
|
|
22
|
+
*/
|
|
23
|
+
export default defineNuxtPlugin((nuxtApp: any, options: NuxtPluginOptions = {}) => {
|
|
24
|
+
const { async = true, workers = false } = options;
|
|
25
|
+
|
|
26
|
+
// Import jtcsv functions
|
|
27
|
+
const jtcsv = {
|
|
28
|
+
// Core functions
|
|
29
|
+
csvToJson: (csv: string, opts?: CsvToJsonOptions) => {
|
|
30
|
+
// This would be replaced with actual import in runtime
|
|
31
|
+
return require('jtcsv').csvToJson(csv, opts);
|
|
32
|
+
},
|
|
33
|
+
jsonToCsv: (data: any, opts?: JsonToCsvOptions) => {
|
|
34
|
+
return require('jtcsv').jsonToCsv(data, opts);
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// Async versions if enabled
|
|
38
|
+
...(async ? {
|
|
39
|
+
csvToJsonAsync: async (csv: string, opts?: CsvToJsonOptions) => {
|
|
40
|
+
const { csvToJson } = require('jtcsv');
|
|
41
|
+
return csvToJson(csv, opts);
|
|
42
|
+
},
|
|
43
|
+
jsonToCsvAsync: async (data: any, opts?: JsonToCsvOptions) => {
|
|
44
|
+
const { jsonToCsv } = require('jtcsv');
|
|
45
|
+
return jsonToCsv(data, opts);
|
|
46
|
+
}
|
|
47
|
+
} : {}),
|
|
48
|
+
|
|
49
|
+
// Worker support if enabled
|
|
50
|
+
...(workers ? {
|
|
51
|
+
createWorkerPool: (size?: number) => {
|
|
52
|
+
const { WorkerPool } = require('../../src/workers/worker-pool');
|
|
53
|
+
return new WorkerPool(size);
|
|
54
|
+
}
|
|
55
|
+
} : {})
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Provide jtcsv to Nuxt app
|
|
59
|
+
nuxtApp.provide('jtcsv', jtcsv);
|
|
60
|
+
nuxtApp.provide('useJtcsv', () => jtcsv);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Nuxt composable for using jtcsv
|
|
65
|
+
*/
|
|
66
|
+
export function useJtcsv() {
|
|
67
|
+
const nuxtApp = useNuxtApp();
|
|
68
|
+
return nuxtApp.$jtcsv;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Nuxt composable for async jtcsv operations
|
|
73
|
+
*/
|
|
74
|
+
export function useJtcsvAsync() {
|
|
75
|
+
const nuxtApp = useNuxtApp();
|
|
76
|
+
const jtcsv = nuxtApp.$jtcsv as any;
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
...jtcsv,
|
|
80
|
+
// Ensure async methods are available
|
|
81
|
+
csvToJson: (jtcsv.csvToJsonAsync || jtcsv.csvToJson) as (csv: string, opts?: CsvToJsonOptions) => any,
|
|
82
|
+
jsonToCsv: (jtcsv.jsonToCsvAsync || jtcsv.jsonToCsv) as (data: any, opts?: JsonToCsvOptions) => string,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Helper functions for Nuxt module compatibility
|
|
87
|
+
function defineNuxtPlugin(fn: any) {
|
|
88
|
+
return fn;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function useNuxtApp() {
|
|
92
|
+
// This would be provided by Nuxt runtime
|
|
93
|
+
return { $jtcsv: {} as any };
|
|
94
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nuxt composable for jtcsv
|
|
3
|
+
* Provides reactive access to jtcsv functions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CsvToJsonOptions, JsonToCsvOptions } from '../../../../src/types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Jtcsv composable interface
|
|
10
|
+
*/
|
|
11
|
+
export interface UseJtcsvReturn {
|
|
12
|
+
// Core functions
|
|
13
|
+
csvToJson: (csv: string, options?: CsvToJsonOptions) => any[];
|
|
14
|
+
jsonToCsv: (data: any, options?: JsonToCsvOptions) => string;
|
|
15
|
+
|
|
16
|
+
// Async versions
|
|
17
|
+
csvToJsonAsync: (csv: string, options?: CsvToJsonOptions) => Promise<any[]>;
|
|
18
|
+
jsonToCsvAsync: (data: any, options?: JsonToCsvOptions) => Promise<string>;
|
|
19
|
+
|
|
20
|
+
// Utility functions
|
|
21
|
+
saveAsCsv: (data: any, filename: string, options?: JsonToCsvOptions) => void;
|
|
22
|
+
saveAsCsvAsync: (data: any, filename: string, options?: JsonToCsvOptions) => Promise<void>;
|
|
23
|
+
|
|
24
|
+
// Worker support
|
|
25
|
+
createWorkerPool?: (size?: number) => any;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Use jtcsv composable
|
|
30
|
+
* This is a simplified version that works without Nuxt dependencies
|
|
31
|
+
*/
|
|
32
|
+
export function useJtcsv(): UseJtcsvReturn {
|
|
33
|
+
// In a real Nuxt app, this would get jtcsv from the Nuxt context
|
|
34
|
+
// For now, we'll create a mock implementation
|
|
35
|
+
|
|
36
|
+
const mockJtcsv = {
|
|
37
|
+
csvToJson: (csv: string, options?: CsvToJsonOptions) => {
|
|
38
|
+
console.log('csvToJson called with:', { csv: csv.substring(0, 50) + '...', options });
|
|
39
|
+
return [];
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
jsonToCsv: (data: any, options?: JsonToCsvOptions) => {
|
|
43
|
+
console.log('jsonToCsv called with:', { data, options });
|
|
44
|
+
return '';
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
csvToJsonAsync: async (csv: string, options?: CsvToJsonOptions) => {
|
|
48
|
+
console.log('csvToJsonAsync called with:', { csv: csv.substring(0, 50) + '...', options });
|
|
49
|
+
return [];
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
jsonToCsvAsync: async (data: any, options?: JsonToCsvOptions) => {
|
|
53
|
+
console.log('jsonToCsvAsync called with:', { data, options });
|
|
54
|
+
return '';
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
saveAsCsv: (data: any, filename: string, options?: JsonToCsvOptions) => {
|
|
58
|
+
console.log('saveAsCsv called with:', { data, filename, options });
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
saveAsCsvAsync: async (data: any, filename: string, options?: JsonToCsvOptions) => {
|
|
62
|
+
console.log('saveAsCsvAsync called with:', { data, filename, options });
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
createWorkerPool: (size?: number) => {
|
|
66
|
+
console.log('createWorkerPool called with size:', size);
|
|
67
|
+
return {
|
|
68
|
+
size: size || 4,
|
|
69
|
+
process: async (data: any) => data
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return mockJtcsv;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Async version of useJtcsv with better error handling
|
|
79
|
+
*/
|
|
80
|
+
export function useJtcsvAsync(): Omit<UseJtcsvReturn, 'csvToJson' | 'jsonToCsv' | 'saveAsCsv'> & {
|
|
81
|
+
csvToJson: (csv: string, options?: CsvToJsonOptions) => Promise<any[]>;
|
|
82
|
+
jsonToCsv: (data: any, options?: JsonToCsvOptions) => Promise<string>;
|
|
83
|
+
saveAsCsv: (data: any, filename: string, options?: JsonToCsvOptions) => Promise<void>;
|
|
84
|
+
} {
|
|
85
|
+
const jtcsv = useJtcsv();
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
...jtcsv,
|
|
89
|
+
// Ensure all methods are async
|
|
90
|
+
csvToJson: async (csv: string, options?: CsvToJsonOptions) => {
|
|
91
|
+
return await jtcsv.csvToJsonAsync(csv, options);
|
|
92
|
+
},
|
|
93
|
+
jsonToCsv: async (data: any, options?: JsonToCsvOptions) => {
|
|
94
|
+
return await jtcsv.jsonToCsvAsync(data, options);
|
|
95
|
+
},
|
|
96
|
+
saveAsCsv: async (data: any, filename: string, options?: JsonToCsvOptions) => {
|
|
97
|
+
await jtcsv.saveAsCsvAsync(data, filename, options);
|
|
98
|
+
}
|
|
99
|
+
} as any;
|
|
100
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nuxt runtime plugin for jtcsv
|
|
3
|
+
* Provides jtcsv integration at runtime
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { defineNuxtPlugin } from '#app';
|
|
7
|
+
import * as jtcsv from 'jtcsv';
|
|
8
|
+
import type { CsvToJsonOptions, JsonToCsvOptions } from '../../../src/types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Nuxt plugin options
|
|
12
|
+
*/
|
|
13
|
+
interface PluginOptions {
|
|
14
|
+
async?: boolean;
|
|
15
|
+
workers?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Enhanced jtcsv with async support
|
|
20
|
+
*/
|
|
21
|
+
function enhanceJtcsv(baseJtcsv: typeof jtcsv, options: PluginOptions = {}) {
|
|
22
|
+
const { async = true, workers = false } = options;
|
|
23
|
+
|
|
24
|
+
const enhanced = {
|
|
25
|
+
...baseJtcsv,
|
|
26
|
+
|
|
27
|
+
// Async versions
|
|
28
|
+
...(async ? {
|
|
29
|
+
csvToJsonAsync: async (csv: string, options?: CsvToJsonOptions) => {
|
|
30
|
+
return baseJtcsv.csvToJson(csv, options);
|
|
31
|
+
},
|
|
32
|
+
jsonToCsvAsync: async (data: any, options?: JsonToCsvOptions) => {
|
|
33
|
+
return baseJtcsv.jsonToCsv(data, options);
|
|
34
|
+
},
|
|
35
|
+
saveAsCsvAsync: async (data: any, filepath: string, options?: JsonToCsvOptions) => {
|
|
36
|
+
return baseJtcsv.saveAsCsv(data, filepath, options);
|
|
37
|
+
},
|
|
38
|
+
saveAsJsonAsync: async (data: any, filepath: string, options?: any) => {
|
|
39
|
+
return baseJtcsv.saveAsJson(data, filepath, options);
|
|
40
|
+
}
|
|
41
|
+
} : {}),
|
|
42
|
+
|
|
43
|
+
// Worker support
|
|
44
|
+
...(workers ? {
|
|
45
|
+
createWorkerPool: (size?: number) => {
|
|
46
|
+
// This would import from the worker pool module
|
|
47
|
+
// For now, return a mock
|
|
48
|
+
return {
|
|
49
|
+
size,
|
|
50
|
+
process: async (data: any) => data
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
} : {})
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return enhanced;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default defineNuxtPlugin((nuxtApp, inject) => {
|
|
60
|
+
// Get plugin options from runtime config
|
|
61
|
+
const config = nuxtApp.$config?.public?.jtcsv || {};
|
|
62
|
+
|
|
63
|
+
// Enhance jtcsv with async support based on config
|
|
64
|
+
const enhancedJtcsv = enhanceJtcsv(jtcsv, config);
|
|
65
|
+
|
|
66
|
+
// Provide to Nuxt app
|
|
67
|
+
nuxtApp.provide('jtcsv', enhancedJtcsv);
|
|
68
|
+
|
|
69
|
+
// Also inject for backward compatibility
|
|
70
|
+
inject('jtcsv', enhancedJtcsv);
|
|
71
|
+
});
|
package/plugins/remix/index.js
CHANGED