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,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JTCSV с поддержкой плагинов
|
|
3
|
+
* Расширяемая версия основного API с plugin system
|
|
4
|
+
*
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
* @date 2026-01-22
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { PluginManager } from './core/plugin-system';
|
|
10
|
+
import FastPathEngine from './engines/fast-path-engine';
|
|
11
|
+
import NdjsonParser from './formats/ndjson-parser';
|
|
12
|
+
|
|
13
|
+
// Импортируем основные функции
|
|
14
|
+
import { jsonToCsv as coreJsonToCsv } from '../json-to-csv';
|
|
15
|
+
import { csvToJson as coreCsvToJson, csvToJsonIterator as coreCsvToJsonIterator } from '../csv-to-json';
|
|
16
|
+
import { saveAsCsv as coreSaveAsCsv } from '../json-to-csv';
|
|
17
|
+
import { readCsvAsJson as coreReadCsvAsJson } from '../csv-to-json';
|
|
18
|
+
|
|
19
|
+
import type { CsvToJsonOptions, JsonToCsvOptions, SaveAsCsvOptions } from './types';
|
|
20
|
+
|
|
21
|
+
export interface JtcsvWithPluginsOptions {
|
|
22
|
+
enableFastPath?: boolean;
|
|
23
|
+
enablePlugins?: boolean;
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface PluginHookContext {
|
|
28
|
+
operation: string;
|
|
29
|
+
options?: any;
|
|
30
|
+
metadata?: Record<string, any>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class JtcsvWithPlugins {
|
|
34
|
+
private pluginManager: PluginManager;
|
|
35
|
+
private fastPathEngine: FastPathEngine;
|
|
36
|
+
private options: JtcsvWithPluginsOptions;
|
|
37
|
+
|
|
38
|
+
constructor(options: JtcsvWithPluginsOptions = {}) {
|
|
39
|
+
this.pluginManager = new PluginManager();
|
|
40
|
+
this.fastPathEngine = new FastPathEngine();
|
|
41
|
+
this.options = {
|
|
42
|
+
enableFastPath: true,
|
|
43
|
+
enablePlugins: true,
|
|
44
|
+
...options
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Регистрируем встроенные плагины
|
|
48
|
+
this._registerBuiltinPlugins();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Регистрирует встроенные плагины
|
|
53
|
+
*/
|
|
54
|
+
private _registerBuiltinPlugins(): void {
|
|
55
|
+
// Fast Path Engine плагин
|
|
56
|
+
this.pluginManager.use('fast-path-engine', {
|
|
57
|
+
name: 'Fast Path Engine',
|
|
58
|
+
version: '1.0.0',
|
|
59
|
+
description: 'Оптимизированный парсер CSV с автоматическим выбором стратегии',
|
|
60
|
+
hooks: {
|
|
61
|
+
'before:csvToJson': (csv: string, context: PluginHookContext) => {
|
|
62
|
+
if (this.options.enableFastPath && context.options?.useFastPath !== false) {
|
|
63
|
+
// Используем fast path engine для анализа
|
|
64
|
+
const sample = csv.substring(0, Math.min(1000, csv.length));
|
|
65
|
+
const structure = this.fastPathEngine.analyzeStructure(sample, context.options);
|
|
66
|
+
|
|
67
|
+
context.metadata = context.metadata || {};
|
|
68
|
+
context.metadata.fastPathStructure = structure;
|
|
69
|
+
if (process.env.NODE_ENV === 'development') {
|
|
70
|
+
console.log(`🚀 Используется ${structure.recommendedEngine} парсер`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return csv;
|
|
74
|
+
},
|
|
75
|
+
'after:csvToJson': (result: any[], context: PluginHookContext) => {
|
|
76
|
+
if (context.metadata?.fastPathStructure) {
|
|
77
|
+
context.metadata.fastPathStats = this.fastPathEngine.getStats();
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// NDJSON плагин
|
|
85
|
+
this.pluginManager.use('ndjson-support', {
|
|
86
|
+
name: 'NDJSON Support',
|
|
87
|
+
version: '1.0.0',
|
|
88
|
+
description: 'Поддержка Newline Delimited JSON формата',
|
|
89
|
+
hooks: {
|
|
90
|
+
'before:parse': (input: any, context: PluginHookContext) => {
|
|
91
|
+
if (context.options?.format === 'ndjson') {
|
|
92
|
+
// Парсим NDJSON
|
|
93
|
+
return NdjsonParser.fromNdjson(input as string, context.options);
|
|
94
|
+
}
|
|
95
|
+
return input;
|
|
96
|
+
},
|
|
97
|
+
'after:serialize': (output: any, context: PluginHookContext) => {
|
|
98
|
+
if (context.options?.format === 'ndjson') {
|
|
99
|
+
// Сериализуем в NDJSON
|
|
100
|
+
return NdjsonParser.toNdjson(output, context.options);
|
|
101
|
+
}
|
|
102
|
+
return output;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Валидация данных плагин
|
|
108
|
+
this.pluginManager.use('data-validation', {
|
|
109
|
+
name: 'Data Validation',
|
|
110
|
+
version: '1.0.0',
|
|
111
|
+
description: 'Валидация входных и выходных данных',
|
|
112
|
+
hooks: {
|
|
113
|
+
'validation': (data: any, context: PluginHookContext) => {
|
|
114
|
+
if (!data) {
|
|
115
|
+
throw new Error('Данные не могут быть пустыми');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (context.operation === 'jsonToCsv' && !Array.isArray(data)) {
|
|
119
|
+
throw new Error('Для конвертации в CSV данные должны быть массивом');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return data;
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
middlewares: [
|
|
126
|
+
async (ctx: any, next: () => Promise<void>) => {
|
|
127
|
+
// Валидация перед выполнением
|
|
128
|
+
await this.pluginManager.executeHooks('validation', ctx.input, ctx);
|
|
129
|
+
await next();
|
|
130
|
+
// Валидация после выполнения
|
|
131
|
+
await this.pluginManager.executeHooks('validation', ctx.result, ctx);
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Логирование плагин
|
|
137
|
+
this.pluginManager.use('logging', {
|
|
138
|
+
name: 'Logging',
|
|
139
|
+
version: '1.0.0',
|
|
140
|
+
description: 'Логирование операций',
|
|
141
|
+
hooks: {
|
|
142
|
+
'before:csvToJson': (csv: string, context: PluginHookContext) => {
|
|
143
|
+
if (process.env.NODE_ENV === 'development') {
|
|
144
|
+
console.log(`📥 Начало csvToJson, размер: ${csv.length} байт`);
|
|
145
|
+
}
|
|
146
|
+
return csv;
|
|
147
|
+
},
|
|
148
|
+
'after:csvToJson': (result: any[], context: PluginHookContext) => {
|
|
149
|
+
if (process.env.NODE_ENV === 'development') {
|
|
150
|
+
console.log(`📤 Завершение csvToJson, результат: ${result.length} записей`);
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
},
|
|
154
|
+
'before:jsonToCsv': (json: any[], context: PluginHookContext) => {
|
|
155
|
+
if (process.env.NODE_ENV === 'development') {
|
|
156
|
+
console.log(`📥 Начало jsonToCsv, записей: ${json.length}`);
|
|
157
|
+
}
|
|
158
|
+
return json;
|
|
159
|
+
},
|
|
160
|
+
'after:jsonToCsv': (csv: string, context: PluginHookContext) => {
|
|
161
|
+
if (process.env.NODE_ENV === 'development') {
|
|
162
|
+
console.log(`📤 Завершение jsonToCsv, размер: ${csv.length} байт`);
|
|
163
|
+
}
|
|
164
|
+
return csv;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Конвертирует CSV в JSON с поддержкой плагинов
|
|
172
|
+
* @param csv - CSV данные
|
|
173
|
+
* @param options - Опции парсинга
|
|
174
|
+
* @returns JSON данные
|
|
175
|
+
*/
|
|
176
|
+
async csvToJson(csv: string, options: CsvToJsonOptions = {}): Promise<any[]> {
|
|
177
|
+
if (!this.options.enablePlugins) {
|
|
178
|
+
return coreCsvToJson(csv, options);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return this.pluginManager.executeWithPlugins(
|
|
182
|
+
'csvToJson',
|
|
183
|
+
csv,
|
|
184
|
+
options,
|
|
185
|
+
(input: string, opts: CsvToJsonOptions) => {
|
|
186
|
+
if (this.options.enableFastPath && opts?.useFastPath !== false) {
|
|
187
|
+
return coreCsvToJson(input, { ...opts, useFastPath: true });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return coreCsvToJson(input, opts);
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Convert CSV to JSON rows as async iterator with plugin hooks.
|
|
197
|
+
* @param csv - CSV input
|
|
198
|
+
* @param options - Conversion options
|
|
199
|
+
* @returns Async iterator of rows
|
|
200
|
+
*/
|
|
201
|
+
async *csvToJsonIterator(csv: string, options: CsvToJsonOptions = {}): AsyncGenerator<any, void, unknown> {
|
|
202
|
+
if (!this.options.enablePlugins) {
|
|
203
|
+
for await (const row of coreCsvToJsonIterator(csv, options)) {
|
|
204
|
+
yield row;
|
|
205
|
+
}
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const iterator = await this.pluginManager.executeWithPlugins(
|
|
210
|
+
'csvToJson',
|
|
211
|
+
csv,
|
|
212
|
+
options,
|
|
213
|
+
(input: string, opts: CsvToJsonOptions) => {
|
|
214
|
+
if (this.options.enableFastPath && opts?.useFastPath !== false) {
|
|
215
|
+
return coreCsvToJsonIterator(input, { ...opts, useFastPath: true });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return coreCsvToJsonIterator(input, opts);
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
for await (const row of iterator) {
|
|
223
|
+
yield row;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Конвертирует JSON в CSV с поддержкой плагинов
|
|
229
|
+
* @param json - JSON данные
|
|
230
|
+
* @param options - Опции сериализации
|
|
231
|
+
* @returns CSV данные
|
|
232
|
+
*/
|
|
233
|
+
async jsonToCsv(json: any[], options: JsonToCsvOptions = {}): Promise<string> {
|
|
234
|
+
if (!this.options.enablePlugins) {
|
|
235
|
+
return coreJsonToCsv(json, options);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return this.pluginManager.executeWithPlugins(
|
|
239
|
+
'jsonToCsv',
|
|
240
|
+
json,
|
|
241
|
+
options,
|
|
242
|
+
coreJsonToCsv
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Сохраняет JSON как CSV файл
|
|
248
|
+
* @param data - JSON данные
|
|
249
|
+
* @param filePath - Путь к файлу
|
|
250
|
+
* @param options - Опции
|
|
251
|
+
* @returns Promise<void>
|
|
252
|
+
*/
|
|
253
|
+
async saveAsCsv(data: any[], filePath: string, options: SaveAsCsvOptions = {}): Promise<void> {
|
|
254
|
+
if (!this.options.enablePlugins) {
|
|
255
|
+
coreSaveAsCsv(data, filePath, options);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const csv = await this.jsonToCsv(data, options);
|
|
260
|
+
|
|
261
|
+
// Используем плагины для сохранения
|
|
262
|
+
await this.pluginManager.executeWithPlugins(
|
|
263
|
+
'saveAsCsv',
|
|
264
|
+
{ data: csv, filePath },
|
|
265
|
+
options,
|
|
266
|
+
async (input: { data: string; filePath: string }) => {
|
|
267
|
+
const fs = await import('fs/promises');
|
|
268
|
+
await fs.writeFile(input.filePath, input.data, 'utf8');
|
|
269
|
+
return input.filePath;
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Читает CSV файл и конвертирует в JSON
|
|
276
|
+
* @param filePath - Путь к файлу
|
|
277
|
+
* @param options - Опции
|
|
278
|
+
* @returns JSON данные
|
|
279
|
+
*/
|
|
280
|
+
async readCsvAsJson(filePath: string, options: CsvToJsonOptions = {}): Promise<any[]> {
|
|
281
|
+
if (!this.options.enablePlugins) {
|
|
282
|
+
return coreReadCsvAsJson(filePath, options);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Читаем файл
|
|
286
|
+
const fs = await import('fs/promises');
|
|
287
|
+
const csv = await fs.readFile(filePath, 'utf8');
|
|
288
|
+
|
|
289
|
+
// Конвертируем с использованием плагинов
|
|
290
|
+
return this.csvToJson(csv, options);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Парсит NDJSON данные
|
|
295
|
+
* @param input - NDJSON данные
|
|
296
|
+
* @param options - Опции
|
|
297
|
+
* @returns JSON данные
|
|
298
|
+
*/
|
|
299
|
+
async parseNdjson(input: string | ReadableStream, options: any = {}): Promise<any[]> {
|
|
300
|
+
if (typeof input === 'string') {
|
|
301
|
+
return NdjsonParser.fromNdjson(input, options);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Для потоков
|
|
305
|
+
const result: any[] = [];
|
|
306
|
+
for await (const obj of NdjsonParser.parseStream(input, options)) {
|
|
307
|
+
result.push(obj);
|
|
308
|
+
}
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Конвертирует JSON в NDJSON
|
|
314
|
+
* @param data - JSON данные
|
|
315
|
+
* @param options - Опции
|
|
316
|
+
* @returns NDJSON строка
|
|
317
|
+
*/
|
|
318
|
+
toNdjson(data: any[], options: any = {}): string {
|
|
319
|
+
return NdjsonParser.toNdjson(data, options);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Регистрирует плагин
|
|
324
|
+
* @param name - Имя плагина
|
|
325
|
+
* @param plugin - Конфигурация плагина
|
|
326
|
+
* @returns this для chaining
|
|
327
|
+
*/
|
|
328
|
+
use(name: string, plugin: any): this {
|
|
329
|
+
this.pluginManager.use(name, plugin);
|
|
330
|
+
return this;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Возвращает менеджер плагинов
|
|
335
|
+
* @returns PluginManager
|
|
336
|
+
*/
|
|
337
|
+
getPluginManager(): PluginManager {
|
|
338
|
+
return this.pluginManager;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Возвращает fast path engine
|
|
343
|
+
* @returns FastPathEngine
|
|
344
|
+
*/
|
|
345
|
+
getFastPathEngine(): FastPathEngine {
|
|
346
|
+
return this.fastPathEngine;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Возвращает список плагинов
|
|
351
|
+
* @returns Array
|
|
352
|
+
*/
|
|
353
|
+
listPlugins(): any[] {
|
|
354
|
+
return this.pluginManager.listPlugins();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Возвращает статистику
|
|
359
|
+
* @returns Object
|
|
360
|
+
*/
|
|
361
|
+
getStats(): any {
|
|
362
|
+
return {
|
|
363
|
+
plugins: this.pluginManager.getStats(),
|
|
364
|
+
fastPath: this.fastPathEngine.getStats(),
|
|
365
|
+
options: this.options
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Настраивает опции
|
|
371
|
+
* @param newOptions - Новые опции
|
|
372
|
+
*/
|
|
373
|
+
configure(newOptions: JtcsvWithPluginsOptions): this {
|
|
374
|
+
this.options = { ...this.options, ...newOptions };
|
|
375
|
+
return this;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Создает экземпляр с настройками по умолчанию
|
|
380
|
+
* @param options - Опции
|
|
381
|
+
* @returns JtcsvWithPlugins
|
|
382
|
+
*/
|
|
383
|
+
static create(options: JtcsvWithPluginsOptions = {}): JtcsvWithPlugins {
|
|
384
|
+
return new JtcsvWithPlugins(options);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Экспортируем основной класс
|
|
389
|
+
export default JtcsvWithPlugins;
|
|
390
|
+
|
|
391
|
+
// Экспортируем утилиты
|
|
392
|
+
export { PluginManager, FastPathEngine, NdjsonParser };
|
|
393
|
+
|
|
394
|
+
// Экспортируем фабричный метод
|
|
395
|
+
export const create = JtcsvWithPlugins.create;
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript интерфейсы для проекта jtcsv
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Базовые типы
|
|
6
|
+
export type AnyObject = Record<string, any>;
|
|
7
|
+
export type AnyArray = any[];
|
|
8
|
+
|
|
9
|
+
// JSON to CSV интерфейсы
|
|
10
|
+
export interface JsonToCsvOptions {
|
|
11
|
+
/** CSV delimiter (default: ';') */
|
|
12
|
+
delimiter?: string;
|
|
13
|
+
/** Include headers row (default: true) */
|
|
14
|
+
includeHeaders?: boolean;
|
|
15
|
+
/** Rename column headers { oldKey: newKey } */
|
|
16
|
+
renameMap?: Record<string, string>;
|
|
17
|
+
/** Template for guaranteed column order */
|
|
18
|
+
template?: Record<string, any>;
|
|
19
|
+
/** Maximum number of records to process (optional, no limit by default) */
|
|
20
|
+
maxRecords?: number;
|
|
21
|
+
/** Prevent CSV injection attacks by escaping formulas (default: true) */
|
|
22
|
+
preventCsvInjection?: boolean;
|
|
23
|
+
/** Ensure RFC 4180 compliance (proper quoting, line endings) (default: true) */
|
|
24
|
+
rfc4180Compliant?: boolean;
|
|
25
|
+
/** JSON schema for data validation and formatting */
|
|
26
|
+
schema?: Record<string, any>;
|
|
27
|
+
/** Whether to flatten nested objects into dot notation keys */
|
|
28
|
+
flatten?: boolean;
|
|
29
|
+
/** Separator for flattened keys (e.g., 'user.name' with '.') */
|
|
30
|
+
flattenSeparator?: string;
|
|
31
|
+
/** Maximum depth for flattening nested objects */
|
|
32
|
+
flattenMaxDepth?: number;
|
|
33
|
+
/** How to handle arrays ('stringify', 'join', 'expand') */
|
|
34
|
+
arrayHandling?: 'stringify' | 'join' | 'expand';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SaveAsCsvOptions extends JsonToCsvOptions {
|
|
38
|
+
/** Validate file path security (default: true) */
|
|
39
|
+
validatePath?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// CSV to JSON интерфейсы
|
|
43
|
+
export interface CsvToJsonOptions {
|
|
44
|
+
/** CSV delimiter (default: auto-detected) */
|
|
45
|
+
delimiter?: string;
|
|
46
|
+
/** Auto-detect delimiter if not specified (default: true) */
|
|
47
|
+
autoDetect?: boolean;
|
|
48
|
+
/** Candidate delimiters for auto-detection (default: [';', ',', '\t', '|']) */
|
|
49
|
+
candidates?: string[];
|
|
50
|
+
/** Whether CSV has headers row (default: true) */
|
|
51
|
+
hasHeaders?: boolean;
|
|
52
|
+
/** Map for renaming column headers { newKey: oldKey } */
|
|
53
|
+
renameMap?: Record<string, string>;
|
|
54
|
+
/** Trim whitespace from values (default: true) */
|
|
55
|
+
trim?: boolean;
|
|
56
|
+
/** Parse numeric values (default: false) */
|
|
57
|
+
parseNumbers?: boolean;
|
|
58
|
+
/** Parse boolean values (default: false) */
|
|
59
|
+
parseBooleans?: boolean;
|
|
60
|
+
/** Maximum number of rows to process (optional, no limit by default) */
|
|
61
|
+
maxRows?: number;
|
|
62
|
+
/** Enable fast-path parsing (default: true) */
|
|
63
|
+
useFastPath?: boolean;
|
|
64
|
+
/** Fast-path output mode (default: 'objects') */
|
|
65
|
+
fastPathMode?: 'objects' | 'compact' | 'stream';
|
|
66
|
+
/** JSON schema for validation and formatting */
|
|
67
|
+
schema?: Record<string, any>;
|
|
68
|
+
/** Custom transform function for each row */
|
|
69
|
+
transform?: (row: Record<string, any>) => Record<string, any>;
|
|
70
|
+
/** Use delimiter cache for auto-detection (default: true) */
|
|
71
|
+
useCache?: boolean;
|
|
72
|
+
/** Custom delimiter cache instance */
|
|
73
|
+
cache?: any; // DelimiterCache type will be imported later
|
|
74
|
+
/** Hooks for custom processing */
|
|
75
|
+
hooks?: {
|
|
76
|
+
beforeConvert?: (csv: string, options: CsvToJsonOptions) => string;
|
|
77
|
+
afterConvert?: (result: any[], options: CsvToJsonOptions) => any[];
|
|
78
|
+
onError?: (error: Error, csv: string, options: CsvToJsonOptions) => void;
|
|
79
|
+
};
|
|
80
|
+
/** Prevent CSV injection attacks by escaping formulas (default: true) */
|
|
81
|
+
preventCsvInjection?: boolean;
|
|
82
|
+
/** Ensure RFC 4180 compliance (proper quoting, line endings) (default: true) */
|
|
83
|
+
rfc4180Compliant?: boolean;
|
|
84
|
+
/** Warn about extra fields not in headers (default: false) */
|
|
85
|
+
warnExtraFields?: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// JSON save интерфейсы
|
|
89
|
+
export interface SaveAsJsonOptions {
|
|
90
|
+
/** Format JSON with indentation (default: false) */
|
|
91
|
+
prettyPrint?: boolean;
|
|
92
|
+
/** Maximum file size in bytes (default: 10MB = 10485760) */
|
|
93
|
+
maxSize?: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Streaming интерфейсы
|
|
97
|
+
export interface JsonToCsvStreamOptions extends JsonToCsvOptions {
|
|
98
|
+
/** Custom transform function for each row */
|
|
99
|
+
transform?: (row: Record<string, any>) => Record<string, any>;
|
|
100
|
+
/** JSON schema for validation and formatting */
|
|
101
|
+
schema?: Record<string, any>;
|
|
102
|
+
/** Add UTF-8 BOM for Excel compatibility (default: true) */
|
|
103
|
+
addBOM?: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface CsvToJsonStreamOptions extends CsvToJsonOptions {
|
|
107
|
+
/** Custom transform function for each row */
|
|
108
|
+
transform?: (row: Record<string, any>) => Record<string, any>;
|
|
109
|
+
/** JSON schema for validation and formatting */
|
|
110
|
+
schema?: Record<string, any>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// NDJSON интерфейсы
|
|
114
|
+
export interface NdjsonOptions {
|
|
115
|
+
/** Buffer size for streaming (default: 64KB) */
|
|
116
|
+
bufferSize?: number;
|
|
117
|
+
/** Maximum line length (default: 10MB) */
|
|
118
|
+
maxLineLength?: number;
|
|
119
|
+
/** Error handler callback */
|
|
120
|
+
onError?: (error: Error, line: string, lineNumber: number) => void;
|
|
121
|
+
/** JSON stringify replacer function */
|
|
122
|
+
replacer?: (key: string, value: any) => any;
|
|
123
|
+
/** JSON stringify space (indentation) */
|
|
124
|
+
space?: number | string;
|
|
125
|
+
/** Filter function for rows */
|
|
126
|
+
filter?: (obj: Record<string, any>, index: number) => boolean;
|
|
127
|
+
/** Transform function for rows */
|
|
128
|
+
transform?: (obj: Record<string, any>, index: number) => any;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface NdjsonToCsvStreamOptions {
|
|
132
|
+
/** Delimiter for CSV output (default: ',') */
|
|
133
|
+
delimiter?: string;
|
|
134
|
+
/** Include headers row (default: true) */
|
|
135
|
+
includeHeaders?: boolean;
|
|
136
|
+
/** Rename column headers { oldKey: newKey } */
|
|
137
|
+
renameMap?: Record<string, string>;
|
|
138
|
+
/** Maximum number of records to process */
|
|
139
|
+
maxRecords?: number;
|
|
140
|
+
/** Prevent CSV injection attacks by escaping formulas (default: true) */
|
|
141
|
+
preventCsvInjection?: boolean;
|
|
142
|
+
/** Ensure RFC 4180 compliance (proper quoting, line endings) (default: true) */
|
|
143
|
+
rfc4180Compliant?: boolean;
|
|
144
|
+
/** JSON schema for validation and formatting */
|
|
145
|
+
schema?: Record<string, any>;
|
|
146
|
+
/** Custom transform function for each row */
|
|
147
|
+
transform?: (row: Record<string, any>) => Record<string, any>;
|
|
148
|
+
/** Add UTF-8 BOM for Excel compatibility (default: true) */
|
|
149
|
+
addBOM?: boolean;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// TSV интерфейсы
|
|
153
|
+
export interface TsvOptions {
|
|
154
|
+
/** Whether TSV has headers row (default: true) */
|
|
155
|
+
hasHeaders?: boolean;
|
|
156
|
+
/** Trim whitespace from values (default: true) */
|
|
157
|
+
trim?: boolean;
|
|
158
|
+
/** Parse numeric values (default: false) */
|
|
159
|
+
parseNumbers?: boolean;
|
|
160
|
+
/** Parse boolean values (default: false) */
|
|
161
|
+
parseBooleans?: boolean;
|
|
162
|
+
/** Maximum number of rows to process */
|
|
163
|
+
maxRows?: number;
|
|
164
|
+
/** JSON schema for validation and formatting */
|
|
165
|
+
schema?: Record<string, any>;
|
|
166
|
+
/** Custom transform function for each row */
|
|
167
|
+
transform?: (row: Record<string, any>) => Record<string, any>;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface TsvValidationResult {
|
|
171
|
+
/** Whether the content is valid TSV */
|
|
172
|
+
isValid: boolean;
|
|
173
|
+
/** Number of rows detected */
|
|
174
|
+
rowCount: number;
|
|
175
|
+
/** Number of columns (if consistent) */
|
|
176
|
+
columnCount?: number;
|
|
177
|
+
/** Error message if invalid */
|
|
178
|
+
error?: string;
|
|
179
|
+
/** Line number where error occurred */
|
|
180
|
+
errorLine?: number;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface ValidateTsvOptions {
|
|
184
|
+
/** Maximum number of rows to check */
|
|
185
|
+
maxRows?: number;
|
|
186
|
+
/** Whether to check for consistent column count */
|
|
187
|
+
checkConsistency?: boolean;
|
|
188
|
+
/** Whether to validate TSV format strictly */
|
|
189
|
+
strict?: boolean;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Worker интерфейсы для многопоточной обработки
|
|
193
|
+
export interface WorkerTask<T = any, R = any> {
|
|
194
|
+
id: string;
|
|
195
|
+
data: T;
|
|
196
|
+
type: string;
|
|
197
|
+
options?: Record<string, any>;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export interface WorkerResult<R = any> {
|
|
201
|
+
id: string;
|
|
202
|
+
result: R;
|
|
203
|
+
error?: Error;
|
|
204
|
+
duration: number;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface WorkerPoolStats {
|
|
208
|
+
totalWorkers: number;
|
|
209
|
+
activeWorkers: number;
|
|
210
|
+
idleWorkers: number;
|
|
211
|
+
totalTasks: number;
|
|
212
|
+
completedTasks: number;
|
|
213
|
+
failedTasks: number;
|
|
214
|
+
averageTaskDuration: number;
|
|
215
|
+
memoryUsage?: NodeJS.MemoryUsage;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Асинхронные интерфейсы
|
|
219
|
+
export interface AsyncJsonToCsvOptions extends JsonToCsvOptions {
|
|
220
|
+
/** Use worker threads for processing (default: auto-detect based on data size) */
|
|
221
|
+
useWorkers?: boolean;
|
|
222
|
+
/** Number of worker threads to use (default: CPU cores - 1) */
|
|
223
|
+
workerCount?: number;
|
|
224
|
+
/** Size of data chunks for parallel processing */
|
|
225
|
+
chunkSize?: number;
|
|
226
|
+
/** Progress callback function */
|
|
227
|
+
onProgress?: (progress: { processed: number; total: number; percentage: number }) => void;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface AsyncCsvToJsonOptions extends CsvToJsonOptions {
|
|
231
|
+
/** Use worker threads for processing (default: auto-detect based on data size) */
|
|
232
|
+
useWorkers?: boolean;
|
|
233
|
+
/** Number of worker threads to use (default: CPU cores - 1) */
|
|
234
|
+
workerCount?: number;
|
|
235
|
+
/** Size of data chunks for parallel processing */
|
|
236
|
+
chunkSize?: number;
|
|
237
|
+
/** Progress callback function */
|
|
238
|
+
onProgress?: (progress: { processed: number; total: number; percentage: number }) => void;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Утилитарные типы
|
|
242
|
+
export type PreprocessOptions = {
|
|
243
|
+
flatten?: boolean;
|
|
244
|
+
flattenSeparator?: string;
|
|
245
|
+
flattenMaxDepth?: number;
|
|
246
|
+
arrayHandling?: 'stringify' | 'join' | 'expand';
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
export type DeepUnwrapOptions = {
|
|
250
|
+
maxDepth?: number;
|
|
251
|
+
preserveArrays?: boolean;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// Экспорт всех интерфейсов
|
|
255
|
+
// Примечание: Типы ошибок экспортируются из errors.ts
|