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.
Files changed (140) hide show
  1. package/README.md +31 -1
  2. package/bin/jtcsv.js +891 -821
  3. package/bin/jtcsv.ts +2534 -0
  4. package/csv-to-json.js +168 -145
  5. package/dist/jtcsv-core.cjs.js +1407 -0
  6. package/dist/jtcsv-core.cjs.js.map +1 -0
  7. package/dist/jtcsv-core.esm.js +1379 -0
  8. package/dist/jtcsv-core.esm.js.map +1 -0
  9. package/dist/jtcsv-core.umd.js +1413 -0
  10. package/dist/jtcsv-core.umd.js.map +1 -0
  11. package/dist/jtcsv-full.cjs.js +1912 -0
  12. package/dist/jtcsv-full.cjs.js.map +1 -0
  13. package/dist/jtcsv-full.esm.js +1880 -0
  14. package/dist/jtcsv-full.esm.js.map +1 -0
  15. package/dist/jtcsv-full.umd.js +1918 -0
  16. package/dist/jtcsv-full.umd.js.map +1 -0
  17. package/dist/jtcsv-workers.esm.js +759 -0
  18. package/dist/jtcsv-workers.esm.js.map +1 -0
  19. package/dist/jtcsv-workers.umd.js +773 -0
  20. package/dist/jtcsv-workers.umd.js.map +1 -0
  21. package/dist/jtcsv.cjs.js +61 -19
  22. package/dist/jtcsv.cjs.js.map +1 -1
  23. package/dist/jtcsv.esm.js +61 -19
  24. package/dist/jtcsv.esm.js.map +1 -1
  25. package/dist/jtcsv.umd.js +61 -19
  26. package/dist/jtcsv.umd.js.map +1 -1
  27. package/errors.js +188 -2
  28. package/examples/advanced/conditional-transformations.js +446 -0
  29. package/examples/advanced/conditional-transformations.ts +446 -0
  30. package/examples/advanced/csv-parser.worker.js +89 -0
  31. package/examples/advanced/csv-parser.worker.ts +89 -0
  32. package/examples/advanced/nested-objects-example.js +306 -0
  33. package/examples/advanced/nested-objects-example.ts +306 -0
  34. package/examples/advanced/performance-optimization.js +504 -0
  35. package/examples/advanced/performance-optimization.ts +504 -0
  36. package/examples/advanced/run-demo-server.js +116 -0
  37. package/examples/advanced/run-demo-server.ts +116 -0
  38. package/examples/advanced/web-worker-usage.html +874 -0
  39. package/examples/async-multithreaded-example.ts +335 -0
  40. package/examples/cli-advanced-usage.md +288 -0
  41. package/examples/cli-batch-processing.ts +38 -0
  42. package/examples/cli-tool.js +0 -3
  43. package/examples/cli-tool.ts +183 -0
  44. package/examples/error-handling.js +21 -7
  45. package/examples/error-handling.ts +356 -0
  46. package/examples/express-api.js +0 -3
  47. package/examples/express-api.ts +164 -0
  48. package/examples/large-dataset-example.js +0 -3
  49. package/examples/large-dataset-example.ts +204 -0
  50. package/examples/ndjson-processing.js +1 -1
  51. package/examples/ndjson-processing.ts +456 -0
  52. package/examples/plugin-excel-exporter.js +3 -4
  53. package/examples/plugin-excel-exporter.ts +406 -0
  54. package/examples/react-integration.tsx +637 -0
  55. package/examples/schema-validation.ts +640 -0
  56. package/examples/simple-usage.js +254 -254
  57. package/examples/simple-usage.ts +194 -0
  58. package/examples/streaming-example.js +4 -5
  59. package/examples/streaming-example.ts +419 -0
  60. package/examples/web-workers-advanced.ts +28 -0
  61. package/index.d.ts +1 -3
  62. package/index.js +15 -1
  63. package/json-save.js +9 -3
  64. package/json-to-csv.js +168 -21
  65. package/package.json +69 -10
  66. package/plugins/express-middleware/README.md +21 -2
  67. package/plugins/express-middleware/example.js +3 -4
  68. package/plugins/express-middleware/example.ts +135 -0
  69. package/plugins/express-middleware/index.d.ts +1 -1
  70. package/plugins/express-middleware/index.js +270 -118
  71. package/plugins/express-middleware/index.ts +557 -0
  72. package/plugins/fastify-plugin/index.js +2 -4
  73. package/plugins/fastify-plugin/index.ts +443 -0
  74. package/plugins/hono/index.ts +226 -0
  75. package/plugins/nestjs/index.ts +201 -0
  76. package/plugins/nextjs-api/examples/ConverterComponent.tsx +386 -0
  77. package/plugins/nextjs-api/examples/api-convert.js +0 -2
  78. package/plugins/nextjs-api/examples/api-convert.ts +67 -0
  79. package/plugins/nextjs-api/index.tsx +339 -0
  80. package/plugins/nextjs-api/route.js +2 -3
  81. package/plugins/nextjs-api/route.ts +370 -0
  82. package/plugins/nuxt/index.ts +94 -0
  83. package/plugins/nuxt/runtime/composables/useJtcsv.ts +100 -0
  84. package/plugins/nuxt/runtime/plugin.ts +71 -0
  85. package/plugins/remix/index.js +1 -1
  86. package/plugins/remix/index.ts +260 -0
  87. package/plugins/sveltekit/index.js +1 -1
  88. package/plugins/sveltekit/index.ts +301 -0
  89. package/plugins/trpc/index.ts +267 -0
  90. package/src/browser/browser-functions.ts +402 -0
  91. package/src/browser/core.js +92 -0
  92. package/src/browser/core.ts +152 -0
  93. package/src/browser/csv-to-json-browser.d.ts +3 -0
  94. package/src/browser/csv-to-json-browser.js +36 -14
  95. package/src/browser/csv-to-json-browser.ts +264 -0
  96. package/src/browser/errors-browser.ts +303 -0
  97. package/src/browser/extensions/plugins.js +92 -0
  98. package/src/browser/extensions/plugins.ts +93 -0
  99. package/src/browser/extensions/workers.js +39 -0
  100. package/src/browser/extensions/workers.ts +39 -0
  101. package/src/browser/globals.d.ts +5 -0
  102. package/src/browser/index.ts +192 -0
  103. package/src/browser/json-to-csv-browser.d.ts +3 -0
  104. package/src/browser/json-to-csv-browser.js +13 -3
  105. package/src/browser/json-to-csv-browser.ts +262 -0
  106. package/src/browser/streams.js +12 -2
  107. package/src/browser/streams.ts +336 -0
  108. package/src/browser/workers/csv-parser.worker.ts +377 -0
  109. package/src/browser/workers/worker-pool.ts +548 -0
  110. package/src/core/delimiter-cache.js +22 -8
  111. package/src/core/delimiter-cache.ts +310 -0
  112. package/src/core/node-optimizations.ts +449 -0
  113. package/src/core/plugin-system.js +29 -11
  114. package/src/core/plugin-system.ts +400 -0
  115. package/src/core/transform-hooks.ts +558 -0
  116. package/src/engines/fast-path-engine-new.ts +347 -0
  117. package/src/engines/fast-path-engine.ts +854 -0
  118. package/src/errors.ts +72 -0
  119. package/src/formats/ndjson-parser.ts +469 -0
  120. package/src/formats/tsv-parser.ts +334 -0
  121. package/src/index-with-plugins.js +16 -9
  122. package/src/index-with-plugins.ts +395 -0
  123. package/src/types/index.ts +255 -0
  124. package/src/utils/bom-utils.js +259 -0
  125. package/src/utils/bom-utils.ts +373 -0
  126. package/src/utils/encoding-support.js +124 -0
  127. package/src/utils/encoding-support.ts +155 -0
  128. package/src/utils/schema-validator.js +19 -19
  129. package/src/utils/schema-validator.ts +819 -0
  130. package/src/utils/transform-loader.js +1 -1
  131. package/src/utils/transform-loader.ts +389 -0
  132. package/src/utils/zod-adapter.js +170 -0
  133. package/src/utils/zod-adapter.ts +280 -0
  134. package/src/web-server/index.js +10 -10
  135. package/src/web-server/index.ts +683 -0
  136. package/src/workers/csv-multithreaded.ts +310 -0
  137. package/src/workers/csv-parser.worker.ts +227 -0
  138. package/src/workers/worker-pool.ts +409 -0
  139. package/stream-csv-to-json.js +26 -8
  140. 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
+ });
@@ -13,7 +13,7 @@ async function extractCsvText(formData, fieldName) {
13
13
  if (value && typeof value.text === 'function') {
14
14
  return await value.text();
15
15
  }
16
- if (value != null) {
16
+ if (value !== null) {
17
17
  return String(value);
18
18
  }
19
19
  }