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
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.csvToJsonIteratorAsync = void 0;
|
|
4
|
+
exports.csvToJson = csvToJson;
|
|
5
|
+
exports.csvToJsonAsync = csvToJsonAsync;
|
|
6
|
+
exports.csvToJsonIterator = csvToJsonIterator;
|
|
7
|
+
exports.parseCsvSafe = parseCsvSafe;
|
|
8
|
+
exports.parseCsvSafeAsync = parseCsvSafeAsync;
|
|
9
|
+
const errors_browser_1 = require("./errors-browser");
|
|
10
|
+
function validateCsvOptions(options) {
|
|
11
|
+
if (options && typeof options !== 'object') {
|
|
12
|
+
throw new errors_browser_1.ConfigurationError('Options must be an object');
|
|
13
|
+
}
|
|
14
|
+
if (options?.delimiter && typeof options.delimiter !== 'string') {
|
|
15
|
+
throw new errors_browser_1.ConfigurationError('Delimiter must be a string');
|
|
16
|
+
}
|
|
17
|
+
if (options?.delimiter && options.delimiter.length !== 1) {
|
|
18
|
+
throw new errors_browser_1.ConfigurationError('Delimiter must be a single character');
|
|
19
|
+
}
|
|
20
|
+
if (options?.autoDetect !== undefined && typeof options.autoDetect !== 'boolean') {
|
|
21
|
+
throw new errors_browser_1.ConfigurationError('autoDetect must be a boolean');
|
|
22
|
+
}
|
|
23
|
+
if (options?.candidates && !Array.isArray(options.candidates)) {
|
|
24
|
+
throw new errors_browser_1.ConfigurationError('candidates must be an array');
|
|
25
|
+
}
|
|
26
|
+
if (options?.maxRows !== undefined && (typeof options.maxRows !== 'number' || options.maxRows <= 0)) {
|
|
27
|
+
throw new errors_browser_1.ConfigurationError('maxRows must be a positive number');
|
|
28
|
+
}
|
|
29
|
+
if (options?.warnExtraFields !== undefined && typeof options.warnExtraFields !== 'boolean') {
|
|
30
|
+
throw new errors_browser_1.ConfigurationError('warnExtraFields must be a boolean');
|
|
31
|
+
}
|
|
32
|
+
if (options?.repairRowShifts !== undefined && typeof options.repairRowShifts !== 'boolean') {
|
|
33
|
+
throw new errors_browser_1.ConfigurationError('repairRowShifts must be a boolean');
|
|
34
|
+
}
|
|
35
|
+
if (options?.normalizeQuotes !== undefined && typeof options.normalizeQuotes !== 'boolean') {
|
|
36
|
+
throw new errors_browser_1.ConfigurationError('normalizeQuotes must be a boolean');
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
function autoDetectDelimiter(text, candidates = [',', ';', '\t', '|']) {
|
|
41
|
+
if (!text || typeof text !== 'string') {
|
|
42
|
+
return ',';
|
|
43
|
+
}
|
|
44
|
+
const firstLine = text.split('\n')[0];
|
|
45
|
+
if (!firstLine) {
|
|
46
|
+
return ',';
|
|
47
|
+
}
|
|
48
|
+
let bestCandidate = ',';
|
|
49
|
+
let bestCount = 0;
|
|
50
|
+
for (const candidate of candidates) {
|
|
51
|
+
const count = (firstLine.match(new RegExp(candidate.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g')) || []).length;
|
|
52
|
+
if (count > bestCount) {
|
|
53
|
+
bestCount = count;
|
|
54
|
+
bestCandidate = candidate;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return bestCandidate;
|
|
58
|
+
}
|
|
59
|
+
function isEmptyValue(value) {
|
|
60
|
+
return value === undefined || value === null || value === '';
|
|
61
|
+
}
|
|
62
|
+
function hasOddQuotes(value) {
|
|
63
|
+
if (typeof value !== 'string') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
let count = 0;
|
|
67
|
+
for (let i = 0; i < value.length; i++) {
|
|
68
|
+
if (value[i] === '"') {
|
|
69
|
+
count++;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return count % 2 === 1;
|
|
73
|
+
}
|
|
74
|
+
function hasAnyQuotes(value) {
|
|
75
|
+
return typeof value === 'string' && value.includes('"');
|
|
76
|
+
}
|
|
77
|
+
function normalizeQuotesInField(value) {
|
|
78
|
+
if (typeof value !== 'string') {
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
if ((value.startsWith('{') && value.endsWith('}')) ||
|
|
82
|
+
(value.startsWith('[') && value.endsWith(']'))) {
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
let normalized = value.replace(/"{2,}/g, '"');
|
|
86
|
+
normalized = normalized.replace(/"\n/g, '\n').replace(/\n"/g, '\n');
|
|
87
|
+
if (normalized.length >= 2 && normalized.startsWith('"') && normalized.endsWith('"')) {
|
|
88
|
+
normalized = normalized.slice(1, -1);
|
|
89
|
+
}
|
|
90
|
+
return normalized;
|
|
91
|
+
}
|
|
92
|
+
function normalizePhoneValue(value) {
|
|
93
|
+
if (typeof value !== 'string') {
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
const trimmed = value.trim();
|
|
97
|
+
if (trimmed === '') {
|
|
98
|
+
return trimmed;
|
|
99
|
+
}
|
|
100
|
+
return trimmed.replace(/["'\\]/g, '');
|
|
101
|
+
}
|
|
102
|
+
function normalizeRowQuotes(row, headers) {
|
|
103
|
+
const normalized = {};
|
|
104
|
+
const phoneKeys = new Set(['phone', 'phonenumber', 'phone_number', 'tel', 'telephone']);
|
|
105
|
+
for (const header of headers) {
|
|
106
|
+
const baseValue = normalizeQuotesInField(row[header]);
|
|
107
|
+
if (phoneKeys.has(String(header).toLowerCase())) {
|
|
108
|
+
normalized[header] = normalizePhoneValue(baseValue);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
normalized[header] = baseValue;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return normalized;
|
|
115
|
+
}
|
|
116
|
+
function looksLikeUserAgent(value) {
|
|
117
|
+
if (typeof value !== 'string') {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return /Mozilla\/|Opera\/|MSIE|AppleWebKit|Gecko|Safari|Chrome\//.test(value);
|
|
121
|
+
}
|
|
122
|
+
function isHexColor(value) {
|
|
123
|
+
return typeof value === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
|
|
124
|
+
}
|
|
125
|
+
function repairShiftedRows(rows, headers, options = {}) {
|
|
126
|
+
if (!Array.isArray(rows) || rows.length === 0 || headers.length === 0) {
|
|
127
|
+
return rows;
|
|
128
|
+
}
|
|
129
|
+
const headerCount = headers.length;
|
|
130
|
+
const merged = [];
|
|
131
|
+
let index = 0;
|
|
132
|
+
while (index < rows.length) {
|
|
133
|
+
const row = rows[index];
|
|
134
|
+
if (!row || typeof row !== 'object') {
|
|
135
|
+
merged.push(row);
|
|
136
|
+
index++;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const values = headers.map((header) => row[header]);
|
|
140
|
+
let lastNonEmpty = -1;
|
|
141
|
+
for (let i = headerCount - 1; i >= 0; i--) {
|
|
142
|
+
if (!isEmptyValue(values[i])) {
|
|
143
|
+
lastNonEmpty = i;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const missingCount = headerCount - 1 - lastNonEmpty;
|
|
148
|
+
if (lastNonEmpty >= 0 && missingCount > 0 && index + 1 < rows.length) {
|
|
149
|
+
const nextRow = rows[index + 1];
|
|
150
|
+
if (nextRow && typeof nextRow === 'object') {
|
|
151
|
+
const nextValues = headers.map((header) => nextRow[header]);
|
|
152
|
+
const nextTrailingEmpty = nextValues
|
|
153
|
+
.slice(headerCount - missingCount)
|
|
154
|
+
.every((value) => isEmptyValue(value));
|
|
155
|
+
const leadValues = nextValues
|
|
156
|
+
.slice(0, missingCount)
|
|
157
|
+
.filter((value) => !isEmptyValue(value));
|
|
158
|
+
const shouldMerge = nextTrailingEmpty
|
|
159
|
+
&& leadValues.length > 0
|
|
160
|
+
&& (hasOddQuotes(values[lastNonEmpty]) || hasAnyQuotes(values[lastNonEmpty]));
|
|
161
|
+
if (shouldMerge) {
|
|
162
|
+
const toAppend = leadValues.map((value) => String(value));
|
|
163
|
+
if (toAppend.length > 0) {
|
|
164
|
+
const base = isEmptyValue(values[lastNonEmpty]) ? '' : String(values[lastNonEmpty]);
|
|
165
|
+
values[lastNonEmpty] = base ? `${base}\n${toAppend.join('\n')}` : toAppend.join('\n');
|
|
166
|
+
}
|
|
167
|
+
for (let i = 0; i < missingCount; i++) {
|
|
168
|
+
values[lastNonEmpty + 1 + i] = nextValues[missingCount + i];
|
|
169
|
+
}
|
|
170
|
+
const mergedRow = {};
|
|
171
|
+
for (let i = 0; i < headerCount; i++) {
|
|
172
|
+
mergedRow[headers[i]] = values[i];
|
|
173
|
+
}
|
|
174
|
+
merged.push(mergedRow);
|
|
175
|
+
index += 2;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (index + 1 < rows.length && headerCount >= 6) {
|
|
181
|
+
const nextRow = rows[index + 1];
|
|
182
|
+
if (nextRow && typeof nextRow === 'object') {
|
|
183
|
+
const nextHex = nextRow[headers[4]];
|
|
184
|
+
const nextUserAgentHead = nextRow[headers[2]];
|
|
185
|
+
const nextUserAgentTail = nextRow[headers[3]];
|
|
186
|
+
const shouldMergeUserAgent = isEmptyValue(values[4])
|
|
187
|
+
&& isEmptyValue(values[5])
|
|
188
|
+
&& isHexColor(nextHex)
|
|
189
|
+
&& (looksLikeUserAgent(nextUserAgentHead) || looksLikeUserAgent(nextUserAgentTail));
|
|
190
|
+
if (shouldMergeUserAgent) {
|
|
191
|
+
const addressParts = [values[3], nextRow[headers[0]], nextRow[headers[1]]]
|
|
192
|
+
.filter((value) => !isEmptyValue(value))
|
|
193
|
+
.map((value) => String(value));
|
|
194
|
+
values[3] = addressParts.join('\n');
|
|
195
|
+
const uaHead = isEmptyValue(nextUserAgentHead) ? '' : String(nextUserAgentHead);
|
|
196
|
+
const uaTail = isEmptyValue(nextUserAgentTail) ? '' : String(nextUserAgentTail);
|
|
197
|
+
const joiner = uaHead && uaTail ? (uaTail.startsWith(' ') ? '' : ',') : '';
|
|
198
|
+
values[4] = uaHead + joiner + uaTail;
|
|
199
|
+
values[5] = String(nextHex);
|
|
200
|
+
const mergedRow = {};
|
|
201
|
+
for (let i = 0; i < headerCount; i++) {
|
|
202
|
+
mergedRow[headers[i]] = values[i];
|
|
203
|
+
}
|
|
204
|
+
merged.push(mergedRow);
|
|
205
|
+
index += 2;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
merged.push(row);
|
|
211
|
+
index++;
|
|
212
|
+
}
|
|
213
|
+
if (options.normalizeQuotes) {
|
|
214
|
+
return merged.map((row) => normalizeRowQuotes(row, headers));
|
|
215
|
+
}
|
|
216
|
+
return merged;
|
|
217
|
+
}
|
|
218
|
+
function csvToJson(csvText, options = {}) {
|
|
219
|
+
return (0, errors_browser_1.safeExecute)(() => {
|
|
220
|
+
validateCsvOptions(options);
|
|
221
|
+
if (typeof csvText !== 'string') {
|
|
222
|
+
throw new errors_browser_1.ValidationError('CSV text must be a string');
|
|
223
|
+
}
|
|
224
|
+
if (csvText.trim() === '') {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
const delimiter = options.delimiter ||
|
|
228
|
+
(options.autoDetect !== false ? autoDetectDelimiter(csvText, options.candidates) : ',');
|
|
229
|
+
const lines = csvText.split('\n').filter(line => line.trim() !== '');
|
|
230
|
+
if (lines.length === 0) {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
const headers = lines[0].split(delimiter).map(h => h.trim());
|
|
234
|
+
const { repairRowShifts = true, normalizeQuotes = true } = options || {};
|
|
235
|
+
const maxRows = options.maxRows || Infinity;
|
|
236
|
+
const dataRows = lines.slice(1, Math.min(lines.length, maxRows + 1));
|
|
237
|
+
const result = [];
|
|
238
|
+
for (let i = 0; i < dataRows.length; i++) {
|
|
239
|
+
const line = dataRows[i];
|
|
240
|
+
const values = line.split(delimiter);
|
|
241
|
+
const row = {};
|
|
242
|
+
for (let j = 0; j < headers.length; j++) {
|
|
243
|
+
const header = headers[j];
|
|
244
|
+
const value = j < values.length ? values[j].trim() : '';
|
|
245
|
+
if (/^-?\d+(\.\d+)?$/.test(value)) {
|
|
246
|
+
row[header] = parseFloat(value);
|
|
247
|
+
}
|
|
248
|
+
else if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') {
|
|
249
|
+
row[header] = value.toLowerCase() === 'true';
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
row[header] = value;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
result.push(row);
|
|
256
|
+
}
|
|
257
|
+
if (repairRowShifts) {
|
|
258
|
+
return repairShiftedRows(result, headers, { normalizeQuotes });
|
|
259
|
+
}
|
|
260
|
+
if (normalizeQuotes) {
|
|
261
|
+
return result.map((row) => normalizeRowQuotes(row, headers));
|
|
262
|
+
}
|
|
263
|
+
return result;
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
async function csvToJsonAsync(csvText, options = {}) {
|
|
267
|
+
return csvToJson(csvText, options);
|
|
268
|
+
}
|
|
269
|
+
async function* csvToJsonIterator(input, options = {}) {
|
|
270
|
+
validateCsvOptions(options);
|
|
271
|
+
let csvText;
|
|
272
|
+
if (typeof input === 'string') {
|
|
273
|
+
csvText = input;
|
|
274
|
+
}
|
|
275
|
+
else if (input instanceof File || input instanceof Blob) {
|
|
276
|
+
csvText = await input.text();
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
throw new errors_browser_1.ValidationError('Input must be string, File or Blob');
|
|
280
|
+
}
|
|
281
|
+
if (csvText.trim() === '') {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const delimiter = options.delimiter ||
|
|
285
|
+
(options.autoDetect !== false ? autoDetectDelimiter(csvText, options.candidates) : ',');
|
|
286
|
+
const lines = csvText.split('\n').filter(line => line.trim() !== '');
|
|
287
|
+
if (lines.length === 0) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const headers = lines[0].split(delimiter).map(h => h.trim());
|
|
291
|
+
const { repairRowShifts = true, normalizeQuotes = true } = options || {};
|
|
292
|
+
const maxRows = options.maxRows || Infinity;
|
|
293
|
+
const dataRows = lines.slice(1, Math.min(lines.length, maxRows + 1));
|
|
294
|
+
const parsedRows = [];
|
|
295
|
+
for (let i = 0; i < dataRows.length; i++) {
|
|
296
|
+
const line = dataRows[i];
|
|
297
|
+
const values = line.split(delimiter);
|
|
298
|
+
const row = {};
|
|
299
|
+
for (let j = 0; j < headers.length; j++) {
|
|
300
|
+
const header = headers[j];
|
|
301
|
+
const value = j < values.length ? values[j].trim() : '';
|
|
302
|
+
if (/^-?\d+(\.\d+)?$/.test(value)) {
|
|
303
|
+
row[header] = parseFloat(value);
|
|
304
|
+
}
|
|
305
|
+
else if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') {
|
|
306
|
+
row[header] = value.toLowerCase() === 'true';
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
row[header] = value;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
parsedRows.push(row);
|
|
313
|
+
}
|
|
314
|
+
const finalRows = repairRowShifts
|
|
315
|
+
? repairShiftedRows(parsedRows, headers, { normalizeQuotes })
|
|
316
|
+
: (normalizeQuotes
|
|
317
|
+
? parsedRows.map((row) => normalizeRowQuotes(row, headers))
|
|
318
|
+
: parsedRows);
|
|
319
|
+
for (const row of finalRows) {
|
|
320
|
+
yield row;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
exports.csvToJsonIteratorAsync = csvToJsonIterator;
|
|
324
|
+
function parseCsvSafe(csvText, options = {}) {
|
|
325
|
+
try {
|
|
326
|
+
return csvToJson(csvText, options);
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
console.error('CSV parsing error:', error);
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
async function parseCsvSafeAsync(csvText, options = {}) {
|
|
334
|
+
try {
|
|
335
|
+
return await csvToJsonAsync(csvText, options);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
console.error('CSV parsing error:', error);
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
343
|
+
module.exports = {
|
|
344
|
+
csvToJson,
|
|
345
|
+
csvToJsonAsync,
|
|
346
|
+
csvToJsonIterator,
|
|
347
|
+
csvToJsonIteratorAsync: exports.csvToJsonIteratorAsync,
|
|
348
|
+
parseCsvSafe,
|
|
349
|
+
parseCsvSafeAsync,
|
|
350
|
+
autoDetectDelimiter
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=csv-to-json-browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv-to-json-browser.js","sourceRoot":"","sources":["../../../src/browser/csv-to-json-browser.ts"],"names":[],"mappings":"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","sourcesContent":["// Браузерная версия CSV to JSON конвертера\r\n// Адаптирована для работы в браузере без Node.js API\r\n\r\nimport {\r\n ValidationError,\r\n ParsingError,\r\n LimitError,\r\n ConfigurationError,\r\n safeExecute\r\n} from './errors-browser';\r\n\r\nimport type { CsvToJsonOptions } from '../types';\r\n\r\n/**\r\n * Валидация опций парсинга\r\n * @private\r\n */\r\nfunction validateCsvOptions(options: CsvToJsonOptions): boolean {\r\n // Validate options\r\n if (options && typeof options !== 'object') {\r\n throw new ConfigurationError('Options must be an object');\r\n }\r\n \r\n // Validate delimiter\r\n if (options?.delimiter && typeof options.delimiter !== 'string') {\r\n throw new ConfigurationError('Delimiter must be a string');\r\n }\r\n \r\n if (options?.delimiter && options.delimiter.length !== 1) {\r\n throw new ConfigurationError('Delimiter must be a single character');\r\n }\r\n \r\n // Validate autoDetect\r\n if (options?.autoDetect !== undefined && typeof options.autoDetect !== 'boolean') {\r\n throw new ConfigurationError('autoDetect must be a boolean');\r\n }\r\n \r\n // Validate candidates\r\n if (options?.candidates && !Array.isArray(options.candidates)) {\r\n throw new ConfigurationError('candidates must be an array');\r\n }\r\n \r\n // Validate maxRows\r\n if (options?.maxRows !== undefined && (typeof options.maxRows !== 'number' || options.maxRows <= 0)) {\r\n throw new ConfigurationError('maxRows must be a positive number');\r\n }\r\n\r\n if (options?.warnExtraFields !== undefined && typeof options.warnExtraFields !== 'boolean') {\r\n throw new ConfigurationError('warnExtraFields must be a boolean');\r\n }\r\n \r\n if (options?.repairRowShifts !== undefined && typeof options.repairRowShifts !== 'boolean') {\r\n throw new ConfigurationError('repairRowShifts must be a boolean');\r\n }\r\n \r\n if (options?.normalizeQuotes !== undefined && typeof options.normalizeQuotes !== 'boolean') {\r\n throw new ConfigurationError('normalizeQuotes must be a boolean');\r\n }\r\n \r\n return true;\r\n}\r\n\r\n/**\r\n * Автоматическое определение разделителя\r\n * @private\r\n */\r\nfunction autoDetectDelimiter(text: string, candidates: string[] = [',', ';', '\\t', '|']): string {\r\n if (!text || typeof text !== 'string') {\r\n return ',';\r\n }\r\n \r\n const firstLine = text.split('\\n')[0];\r\n if (!firstLine) {\r\n return ',';\r\n }\r\n \r\n let bestCandidate = ',';\r\n let bestCount = 0;\r\n \r\n for (const candidate of candidates) {\r\n const count = (firstLine.match(new RegExp(candidate.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g')) || []).length;\r\n if (count > bestCount) {\r\n bestCount = count;\r\n bestCandidate = candidate;\r\n }\r\n }\r\n \r\n return bestCandidate;\r\n}\r\n\r\nfunction isEmptyValue(value: any): boolean {\r\n return value === undefined || value === null || value === '';\r\n}\r\n\r\nfunction hasOddQuotes(value: any): boolean {\r\n if (typeof value !== 'string') {\r\n return false;\r\n }\r\n let count = 0;\r\n for (let i = 0; i < value.length; i++) {\r\n if (value[i] === '\"') {\r\n count++;\r\n }\r\n }\r\n return count % 2 === 1;\r\n}\r\n\r\nfunction hasAnyQuotes(value: any): boolean {\r\n return typeof value === 'string' && value.includes('\"');\r\n}\r\n\r\nfunction normalizeQuotesInField(value: any): any {\r\n if (typeof value !== 'string') {\r\n return value;\r\n }\r\n // Не нормализуем кавычки в JSON-строках - это ломает структуру JSON\r\n // Проверяем, выглядит ли значение как JSON (объект или массив)\r\n if ((value.startsWith('{') && value.endsWith('}')) ||\r\n (value.startsWith('[') && value.endsWith(']'))) {\r\n return value; // Возвращаем как есть для JSON\r\n }\r\n \r\n let normalized = value.replace(/\"{2,}/g, '\"');\r\n // Убираем правило, которое ломает JSON: не заменяем \",\" на \",\"\r\n // normalized = normalized.replace(/\"\\s*,\\s*\"/g, ',');\r\n normalized = normalized.replace(/\"\\n/g, '\\n').replace(/\\n\"/g, '\\n');\r\n if (normalized.length >= 2 && normalized.startsWith('\"') && normalized.endsWith('\"')) {\r\n normalized = normalized.slice(1, -1);\r\n }\r\n return normalized;\r\n}\r\n\r\nfunction normalizePhoneValue(value: any): any {\r\n if (typeof value !== 'string') {\r\n return value;\r\n }\r\n const trimmed = value.trim();\r\n if (trimmed === '') {\r\n return trimmed;\r\n }\r\n return trimmed.replace(/[\"'\\\\]/g, '');\r\n}\r\n\r\nfunction normalizeRowQuotes(row: Record<string, any>, headers: string[]): Record<string, any> {\r\n const normalized: Record<string, any> = {};\r\n const phoneKeys = new Set(['phone', 'phonenumber', 'phone_number', 'tel', 'telephone']);\r\n for (const header of headers) {\r\n const baseValue = normalizeQuotesInField(row[header]);\r\n if (phoneKeys.has(String(header).toLowerCase())) {\r\n normalized[header] = normalizePhoneValue(baseValue);\r\n } else {\r\n normalized[header] = baseValue;\r\n }\r\n }\r\n return normalized;\r\n}\r\n\r\nfunction looksLikeUserAgent(value: any): boolean {\r\n if (typeof value !== 'string') {\r\n return false;\r\n }\r\n return /Mozilla\\/|Opera\\/|MSIE|AppleWebKit|Gecko|Safari|Chrome\\//.test(value);\r\n}\r\n\r\nfunction isHexColor(value: any): boolean {\r\n return typeof value === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);\r\n}\r\n\r\nfunction repairShiftedRows(\r\n rows: Record<string, any>[],\r\n headers: string[],\r\n options: { normalizeQuotes?: boolean } = {}\r\n): Record<string, any>[] {\r\n if (!Array.isArray(rows) || rows.length === 0 || headers.length === 0) {\r\n return rows;\r\n }\r\n\r\n const headerCount = headers.length;\r\n const merged: Record<string, any>[] = [];\r\n let index = 0;\r\n\r\n while (index < rows.length) {\r\n const row = rows[index];\r\n if (!row || typeof row !== 'object') {\r\n merged.push(row);\r\n index++;\r\n continue;\r\n }\r\n\r\n const values = headers.map((header) => row[header]);\r\n let lastNonEmpty = -1;\r\n for (let i = headerCount - 1; i >= 0; i--) {\r\n if (!isEmptyValue(values[i])) {\r\n lastNonEmpty = i;\r\n break;\r\n }\r\n }\r\n\r\n const missingCount = headerCount - 1 - lastNonEmpty;\r\n if (lastNonEmpty >= 0 && missingCount > 0 && index + 1 < rows.length) {\r\n const nextRow = rows[index + 1];\r\n if (nextRow && typeof nextRow === 'object') {\r\n const nextValues = headers.map((header) => nextRow[header]);\r\n const nextTrailingEmpty = nextValues\r\n .slice(headerCount - missingCount)\r\n .every((value) => isEmptyValue(value));\r\n\r\n const leadValues = nextValues\r\n .slice(0, missingCount)\r\n .filter((value) => !isEmptyValue(value));\r\n const shouldMerge = nextTrailingEmpty\r\n && leadValues.length > 0\r\n && (hasOddQuotes(values[lastNonEmpty]) || hasAnyQuotes(values[lastNonEmpty]));\r\n\r\n if (shouldMerge) {\r\n const toAppend = leadValues.map((value) => String(value));\r\n\r\n if (toAppend.length > 0) {\r\n const base = isEmptyValue(values[lastNonEmpty]) ? '' : String(values[lastNonEmpty]);\r\n values[lastNonEmpty] = base ? `${base}\\n${toAppend.join('\\n')}` : toAppend.join('\\n');\r\n }\r\n\r\n for (let i = 0; i < missingCount; i++) {\r\n values[lastNonEmpty + 1 + i] = nextValues[missingCount + i];\r\n }\r\n\r\n const mergedRow: Record<string, any> = {};\r\n for (let i = 0; i < headerCount; i++) {\r\n mergedRow[headers[i]] = values[i];\r\n }\r\n\r\n merged.push(mergedRow);\r\n index += 2;\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n if (index + 1 < rows.length && headerCount >= 6) {\r\n const nextRow = rows[index + 1];\r\n if (nextRow && typeof nextRow === 'object') {\r\n const nextHex = nextRow[headers[4]];\r\n const nextUserAgentHead = nextRow[headers[2]];\r\n const nextUserAgentTail = nextRow[headers[3]];\r\n const shouldMergeUserAgent = isEmptyValue(values[4])\r\n && isEmptyValue(values[5])\r\n && isHexColor(nextHex)\r\n && (looksLikeUserAgent(nextUserAgentHead) || looksLikeUserAgent(nextUserAgentTail));\r\n\r\n if (shouldMergeUserAgent) {\r\n const addressParts = [values[3], nextRow[headers[0]], nextRow[headers[1]]]\r\n .filter((value) => !isEmptyValue(value))\r\n .map((value) => String(value));\r\n values[3] = addressParts.join('\\n');\r\n\r\n const uaHead = isEmptyValue(nextUserAgentHead) ? '' : String(nextUserAgentHead);\r\n const uaTail = isEmptyValue(nextUserAgentTail) ? '' : String(nextUserAgentTail);\r\n const joiner = uaHead && uaTail ? (uaTail.startsWith(' ') ? '' : ',') : '';\r\n values[4] = uaHead + joiner + uaTail;\r\n values[5] = String(nextHex);\r\n\r\n const mergedRow: Record<string, any> = {};\r\n for (let i = 0; i < headerCount; i++) {\r\n mergedRow[headers[i]] = values[i];\r\n }\r\n\r\n merged.push(mergedRow);\r\n index += 2;\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n merged.push(row);\r\n index++;\r\n }\r\n\r\n if (options.normalizeQuotes) {\r\n return merged.map((row) => normalizeRowQuotes(row, headers));\r\n }\r\n\r\n return merged;\r\n}\r\n\r\n/**\r\n * Парсинг CSV строки в массив объектов\r\n * \r\n * @param csvText - CSV текст для парсинга\r\n * @param options - Опции парсинга\r\n * @returns Массив объектов\r\n */\r\nexport function csvToJson(csvText: string, options: CsvToJsonOptions = {}): any[] {\r\n return safeExecute(() => {\r\n validateCsvOptions(options);\r\n \r\n if (typeof csvText !== 'string') {\r\n throw new ValidationError('CSV text must be a string');\r\n }\r\n \r\n if (csvText.trim() === '') {\r\n return [];\r\n }\r\n \r\n // Определение разделителя\r\n const delimiter = options.delimiter || \r\n (options.autoDetect !== false ? autoDetectDelimiter(csvText, options.candidates) : ',');\r\n \r\n // Разделение на строки\r\n const lines = csvText.split('\\n').filter(line => line.trim() !== '');\r\n if (lines.length === 0) {\r\n return [];\r\n }\r\n \r\n // Парсинг заголовков\r\n const headers = lines[0].split(delimiter).map(h => h.trim());\r\n const {\r\n repairRowShifts = true,\r\n normalizeQuotes = true\r\n } = options || {};\r\n \r\n // Ограничение количества строк\r\n const maxRows = options.maxRows || Infinity;\r\n const dataRows = lines.slice(1, Math.min(lines.length, maxRows + 1));\r\n \r\n // Парсинг данных\r\n const result = [];\r\n \r\n for (let i = 0; i < dataRows.length; i++) {\r\n const line = dataRows[i];\r\n const values = line.split(delimiter);\r\n const row: Record<string, any> = {};\r\n \r\n for (let j = 0; j < headers.length; j++) {\r\n const header = headers[j];\r\n const value = j < values.length ? values[j].trim() : '';\r\n \r\n // Попытка парсинга чисел\r\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) {\r\n row[header] = parseFloat(value);\r\n } else if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') {\r\n row[header] = value.toLowerCase() === 'true';\r\n } else {\r\n row[header] = value;\r\n }\r\n }\r\n \r\n result.push(row);\r\n }\r\n \r\n if (repairRowShifts) {\r\n return repairShiftedRows(result, headers, { normalizeQuotes });\r\n }\r\n\r\n if (normalizeQuotes) {\r\n return result.map((row) => normalizeRowQuotes(row, headers));\r\n }\r\n\r\n return result;\r\n });\r\n}\r\n\r\n/**\r\n * Асинхронная версия csvToJson\r\n */\r\nexport async function csvToJsonAsync(csvText: string, options: CsvToJsonOptions = {}): Promise<any[]> {\r\n return csvToJson(csvText, options);\r\n}\r\n\r\n/**\r\n * Создает итератор для потокового парсинга CSV\r\n * \r\n * @param input - CSV текст, File или Blob\r\n * @param options - Опции парсинга\r\n * @returns AsyncGenerator\r\n */\r\nexport async function* csvToJsonIterator(input: string | File | Blob, options: CsvToJsonOptions = {}): AsyncGenerator<any> {\r\n validateCsvOptions(options);\r\n \r\n let csvText: string;\r\n \r\n if (typeof input === 'string') {\r\n csvText = input;\r\n } else if (input instanceof File || input instanceof Blob) {\r\n csvText = await input.text();\r\n } else {\r\n throw new ValidationError('Input must be string, File or Blob');\r\n }\r\n \r\n if (csvText.trim() === '') {\r\n return;\r\n }\r\n \r\n // Определение разделителя\r\n const delimiter = options.delimiter || \r\n (options.autoDetect !== false ? autoDetectDelimiter(csvText, options.candidates) : ',');\r\n \r\n // Разделение на строки\r\n const lines = csvText.split('\\n').filter(line => line.trim() !== '');\r\n if (lines.length === 0) {\r\n return;\r\n }\r\n \r\n // Парсинг заголовков\r\n const headers = lines[0].split(delimiter).map(h => h.trim());\r\n const {\r\n repairRowShifts = true,\r\n normalizeQuotes = true\r\n } = options || {};\r\n \r\n // Ограничение количества строк\r\n const maxRows = options.maxRows || Infinity;\r\n const dataRows = lines.slice(1, Math.min(lines.length, maxRows + 1));\r\n \r\n // Возврат данных по одной строке\r\n const parsedRows = [];\r\n for (let i = 0; i < dataRows.length; i++) {\r\n const line = dataRows[i];\r\n const values = line.split(delimiter);\r\n const row: Record<string, any> = {};\r\n \r\n for (let j = 0; j < headers.length; j++) {\r\n const header = headers[j];\r\n const value = j < values.length ? values[j].trim() : '';\r\n \r\n // Try parsing numbers\r\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) {\r\n row[header] = parseFloat(value);\r\n } else if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') {\r\n row[header] = value.toLowerCase() === 'true';\r\n } else {\r\n row[header] = value;\r\n }\r\n }\r\n \r\n parsedRows.push(row);\r\n }\r\n\r\n const finalRows = repairRowShifts\r\n ? repairShiftedRows(parsedRows, headers, { normalizeQuotes })\r\n : (normalizeQuotes\r\n ? parsedRows.map((row) => normalizeRowQuotes(row, headers))\r\n : parsedRows);\r\n\r\n for (const row of finalRows) {\r\n yield row;\r\n }\r\n\r\n}\r\n\r\n/**\r\n * Асинхронная версия csvToJsonIterator (псевдоним)\r\n */\r\nexport const csvToJsonIteratorAsync = csvToJsonIterator;\r\n\r\n/**\r\n * Парсинг CSV с обработкой ошибок\r\n * \r\n * @param csvText - CSV текст\r\n * @param options - Опции парсинга\r\n * @returns Результат парсинга или null при ошибке\r\n */\r\nexport function parseCsvSafe(csvText: string, options: CsvToJsonOptions = {}): any[] | null {\r\n try {\r\n return csvToJson(csvText, options);\r\n } catch (error) {\r\n console.error('CSV parsing error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Асинхронная версия parseCsvSafe\r\n */\r\nexport async function parseCsvSafeAsync(csvText: string, options: CsvToJsonOptions = {}): Promise<any[] | null> {\r\n try {\r\n return await csvToJsonAsync(csvText, options);\r\n } catch (error) {\r\n console.error('CSV parsing error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n// Экспорт для Node.js совместимости\r\nif (typeof module !== 'undefined' && module.exports) {\r\n module.exports = {\r\n csvToJson,\r\n csvToJsonAsync,\r\n csvToJsonIterator,\r\n csvToJsonIteratorAsync,\r\n parseCsvSafe,\r\n parseCsvSafeAsync,\r\n autoDetectDelimiter\r\n };\r\n}\r\n"]}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ERROR_CODES = exports.ConfigurationError = exports.LimitError = exports.ParsingError = exports.FileSystemError = exports.SecurityError = exports.ValidationError = exports.JTCSVError = void 0;
|
|
4
|
+
exports.safeExecute = safeExecute;
|
|
5
|
+
exports.safeExecuteAsync = safeExecuteAsync;
|
|
6
|
+
exports.createErrorMessage = createErrorMessage;
|
|
7
|
+
exports.handleError = handleError;
|
|
8
|
+
class JTCSVError extends Error {
|
|
9
|
+
constructor(message, code = 'JTCSV_ERROR', details = {}) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'JTCSVError';
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.details = details;
|
|
14
|
+
this.hint = details.hint;
|
|
15
|
+
this.docs = details.docs;
|
|
16
|
+
this.context = details.context;
|
|
17
|
+
if (Error.captureStackTrace) {
|
|
18
|
+
Error.captureStackTrace(this, JTCSVError);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.JTCSVError = JTCSVError;
|
|
23
|
+
class ValidationError extends JTCSVError {
|
|
24
|
+
constructor(message, details = {}) {
|
|
25
|
+
super(message, 'VALIDATION_ERROR', details);
|
|
26
|
+
this.name = 'ValidationError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.ValidationError = ValidationError;
|
|
30
|
+
class SecurityError extends JTCSVError {
|
|
31
|
+
constructor(message, details = {}) {
|
|
32
|
+
super(message, 'SECURITY_ERROR', details);
|
|
33
|
+
this.name = 'SecurityError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.SecurityError = SecurityError;
|
|
37
|
+
class FileSystemError extends JTCSVError {
|
|
38
|
+
constructor(message, originalError, details = {}) {
|
|
39
|
+
super(message, 'FILE_SYSTEM_ERROR', { ...details, originalError });
|
|
40
|
+
this.name = 'FileSystemError';
|
|
41
|
+
if (originalError && originalError.code) {
|
|
42
|
+
this.code = originalError.code;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.FileSystemError = FileSystemError;
|
|
47
|
+
class ParsingError extends JTCSVError {
|
|
48
|
+
constructor(message, lineNumber, details = {}) {
|
|
49
|
+
super(message, 'PARSING_ERROR', { ...details, lineNumber });
|
|
50
|
+
this.name = 'ParsingError';
|
|
51
|
+
this.lineNumber = lineNumber;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.ParsingError = ParsingError;
|
|
55
|
+
class LimitError extends JTCSVError {
|
|
56
|
+
constructor(message, limit, actual, details = {}) {
|
|
57
|
+
super(message, 'LIMIT_ERROR', { ...details, limit, actual });
|
|
58
|
+
this.name = 'LimitError';
|
|
59
|
+
this.limit = limit;
|
|
60
|
+
this.actual = actual;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.LimitError = LimitError;
|
|
64
|
+
class ConfigurationError extends JTCSVError {
|
|
65
|
+
constructor(message, details = {}) {
|
|
66
|
+
super(message, 'CONFIGURATION_ERROR', details);
|
|
67
|
+
this.name = 'ConfigurationError';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.ConfigurationError = ConfigurationError;
|
|
71
|
+
exports.ERROR_CODES = {
|
|
72
|
+
JTCSV_ERROR: 'JTCSV_ERROR',
|
|
73
|
+
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
74
|
+
SECURITY_ERROR: 'SECURITY_ERROR',
|
|
75
|
+
FILE_SYSTEM_ERROR: 'FILE_SYSTEM_ERROR',
|
|
76
|
+
PARSING_ERROR: 'PARSING_ERROR',
|
|
77
|
+
LIMIT_ERROR: 'LIMIT_ERROR',
|
|
78
|
+
CONFIGURATION_ERROR: 'CONFIGURATION_ERROR',
|
|
79
|
+
INVALID_INPUT: 'INVALID_INPUT',
|
|
80
|
+
SECURITY_VIOLATION: 'SECURITY_VIOLATION',
|
|
81
|
+
FILE_NOT_FOUND: 'FILE_NOT_FOUND',
|
|
82
|
+
PARSE_FAILED: 'PARSE_FAILED',
|
|
83
|
+
SIZE_LIMIT: 'SIZE_LIMIT',
|
|
84
|
+
INVALID_CONFIG: 'INVALID_CONFIG',
|
|
85
|
+
UNKNOWN_ERROR: 'UNKNOWN_ERROR'
|
|
86
|
+
};
|
|
87
|
+
function safeExecute(fn, errorCode = 'UNKNOWN_ERROR', errorDetails = {}) {
|
|
88
|
+
try {
|
|
89
|
+
if (typeof fn === 'function') {
|
|
90
|
+
return fn();
|
|
91
|
+
}
|
|
92
|
+
throw new ValidationError('Function expected');
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof JTCSVError) {
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
let enhancedError;
|
|
99
|
+
const errorMessage = error.message || String(error);
|
|
100
|
+
if (errorMessage.includes('validation') || errorMessage.includes('Validation')) {
|
|
101
|
+
enhancedError = new ValidationError(errorMessage, { ...errorDetails, originalError: error });
|
|
102
|
+
}
|
|
103
|
+
else if (errorMessage.includes('security') || errorMessage.includes('Security')) {
|
|
104
|
+
enhancedError = new SecurityError(errorMessage, { ...errorDetails, originalError: error });
|
|
105
|
+
}
|
|
106
|
+
else if (errorMessage.includes('parsing') || errorMessage.includes('Parsing')) {
|
|
107
|
+
enhancedError = new ParsingError(errorMessage, undefined, { ...errorDetails, originalError: error });
|
|
108
|
+
}
|
|
109
|
+
else if (errorMessage.includes('limit') || errorMessage.includes('Limit')) {
|
|
110
|
+
enhancedError = new LimitError(errorMessage, null, null, { ...errorDetails, originalError: error });
|
|
111
|
+
}
|
|
112
|
+
else if (errorMessage.includes('configuration') || errorMessage.includes('Configuration')) {
|
|
113
|
+
enhancedError = new ConfigurationError(errorMessage, { ...errorDetails, originalError: error });
|
|
114
|
+
}
|
|
115
|
+
else if (errorMessage.includes('file') || errorMessage.includes('File')) {
|
|
116
|
+
enhancedError = new FileSystemError(errorMessage, error, errorDetails);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
enhancedError = new JTCSVError(errorMessage, errorCode, { ...errorDetails, originalError: error });
|
|
120
|
+
}
|
|
121
|
+
if (error.stack) {
|
|
122
|
+
enhancedError.stack = error.stack;
|
|
123
|
+
}
|
|
124
|
+
throw enhancedError;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function safeExecuteAsync(fn, errorCode = 'UNKNOWN_ERROR', errorDetails = {}) {
|
|
128
|
+
try {
|
|
129
|
+
if (typeof fn === 'function') {
|
|
130
|
+
return await fn();
|
|
131
|
+
}
|
|
132
|
+
throw new ValidationError('Function expected');
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (error instanceof JTCSVError) {
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
let enhancedError;
|
|
139
|
+
const errorMessage = error.message || String(error);
|
|
140
|
+
if (errorMessage.includes('validation') || errorMessage.includes('Validation')) {
|
|
141
|
+
enhancedError = new ValidationError(errorMessage, { ...errorDetails, originalError: error });
|
|
142
|
+
}
|
|
143
|
+
else if (errorMessage.includes('security') || errorMessage.includes('Security')) {
|
|
144
|
+
enhancedError = new SecurityError(errorMessage, { ...errorDetails, originalError: error });
|
|
145
|
+
}
|
|
146
|
+
else if (errorMessage.includes('parsing') || errorMessage.includes('Parsing')) {
|
|
147
|
+
enhancedError = new ParsingError(errorMessage, undefined, { ...errorDetails, originalError: error });
|
|
148
|
+
}
|
|
149
|
+
else if (errorMessage.includes('limit') || errorMessage.includes('Limit')) {
|
|
150
|
+
enhancedError = new LimitError(errorMessage, null, null, { ...errorDetails, originalError: error });
|
|
151
|
+
}
|
|
152
|
+
else if (errorMessage.includes('configuration') || errorMessage.includes('Configuration')) {
|
|
153
|
+
enhancedError = new ConfigurationError(errorMessage, { ...errorDetails, originalError: error });
|
|
154
|
+
}
|
|
155
|
+
else if (errorMessage.includes('file') || errorMessage.includes('File')) {
|
|
156
|
+
enhancedError = new FileSystemError(errorMessage, error, errorDetails);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
enhancedError = new JTCSVError(errorMessage, errorCode, { ...errorDetails, originalError: error });
|
|
160
|
+
}
|
|
161
|
+
if (error.stack) {
|
|
162
|
+
enhancedError.stack = error.stack;
|
|
163
|
+
}
|
|
164
|
+
throw enhancedError;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function createErrorMessage(error, includeStack = false) {
|
|
168
|
+
let message = error.message || 'Unknown error';
|
|
169
|
+
if (error instanceof JTCSVError) {
|
|
170
|
+
message = `[${error.code}] ${message}`;
|
|
171
|
+
if (error instanceof ParsingError && error.lineNumber) {
|
|
172
|
+
message += ` (line ${error.lineNumber})`;
|
|
173
|
+
}
|
|
174
|
+
if (error instanceof LimitError && error.limit && error.actual) {
|
|
175
|
+
message += ` (limit: ${error.limit}, actual: ${error.actual})`;
|
|
176
|
+
}
|
|
177
|
+
if (error.hint) {
|
|
178
|
+
message += `\nHint: ${error.hint}`;
|
|
179
|
+
}
|
|
180
|
+
if (error.docs) {
|
|
181
|
+
message += `\nDocs: ${error.docs}`;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (includeStack && error.stack) {
|
|
185
|
+
message += `\n${error.stack}`;
|
|
186
|
+
}
|
|
187
|
+
return message;
|
|
188
|
+
}
|
|
189
|
+
function handleError(error, options = {}) {
|
|
190
|
+
const { log = true, throw: shouldThrow = false, format = true } = options;
|
|
191
|
+
const message = format ? createErrorMessage(error) : error.message;
|
|
192
|
+
if (log) {
|
|
193
|
+
console.error(`[jtcsv] ${message}`);
|
|
194
|
+
if (error instanceof JTCSVError && error.details) {
|
|
195
|
+
console.error('Error details:', error.details);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (shouldThrow) {
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
return message;
|
|
202
|
+
}
|
|
203
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
204
|
+
module.exports = {
|
|
205
|
+
JTCSVError,
|
|
206
|
+
ValidationError,
|
|
207
|
+
SecurityError,
|
|
208
|
+
FileSystemError,
|
|
209
|
+
ParsingError,
|
|
210
|
+
LimitError,
|
|
211
|
+
ConfigurationError,
|
|
212
|
+
ERROR_CODES: exports.ERROR_CODES,
|
|
213
|
+
safeExecute,
|
|
214
|
+
safeExecuteAsync,
|
|
215
|
+
createErrorMessage,
|
|
216
|
+
handleError
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=errors-browser.js.map
|