@fuzzle/opencode-accountant 0.0.6 → 0.0.7

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/dist/index.js CHANGED
@@ -1,5 +1,21 @@
1
1
  // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
2
4
  var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
3
19
  var __export = (target, all) => {
4
20
  for (var name in all)
5
21
  __defProp(target, name, {
@@ -9,9 +25,1323 @@ var __export = (target, all) => {
9
25
  set: (newValue) => all[name] = () => newValue
10
26
  });
11
27
  };
28
+ var __require = import.meta.require;
29
+
30
+ // node_modules/papaparse/papaparse.js
31
+ var require_papaparse = __commonJS((exports, module) => {
32
+ (function(root, factory) {
33
+ if (typeof define === "function" && define.amd) {
34
+ define([], factory);
35
+ } else if (typeof module === "object" && typeof exports !== "undefined") {
36
+ module.exports = factory();
37
+ } else {
38
+ root.Papa = factory();
39
+ }
40
+ })(exports, function moduleFactory() {
41
+ var global = function() {
42
+ if (typeof self !== "undefined") {
43
+ return self;
44
+ }
45
+ if (typeof window !== "undefined") {
46
+ return window;
47
+ }
48
+ if (typeof global !== "undefined") {
49
+ return global;
50
+ }
51
+ return {};
52
+ }();
53
+ function getWorkerBlob() {
54
+ var URL2 = global.URL || global.webkitURL || null;
55
+ var code = moduleFactory.toString();
56
+ return Papa.BLOB_URL || (Papa.BLOB_URL = URL2.createObjectURL(new Blob(["var global = (function() { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } return {}; })(); global.IS_PAPA_WORKER=true; ", "(", code, ")();"], { type: "text/javascript" })));
57
+ }
58
+ var IS_WORKER = !global.document && !!global.postMessage, IS_PAPA_WORKER = global.IS_PAPA_WORKER || false;
59
+ var workers = {}, workerIdCounter = 0;
60
+ var Papa = {};
61
+ Papa.parse = CsvToJson;
62
+ Papa.unparse = JsonToCsv;
63
+ Papa.RECORD_SEP = String.fromCharCode(30);
64
+ Papa.UNIT_SEP = String.fromCharCode(31);
65
+ Papa.BYTE_ORDER_MARK = "\uFEFF";
66
+ Papa.BAD_DELIMITERS = ["\r", `
67
+ `, '"', Papa.BYTE_ORDER_MARK];
68
+ Papa.WORKERS_SUPPORTED = !IS_WORKER && !!global.Worker;
69
+ Papa.NODE_STREAM_INPUT = 1;
70
+ Papa.LocalChunkSize = 1024 * 1024 * 10;
71
+ Papa.RemoteChunkSize = 1024 * 1024 * 5;
72
+ Papa.DefaultDelimiter = ",";
73
+ Papa.Parser = Parser;
74
+ Papa.ParserHandle = ParserHandle;
75
+ Papa.NetworkStreamer = NetworkStreamer;
76
+ Papa.FileStreamer = FileStreamer;
77
+ Papa.StringStreamer = StringStreamer;
78
+ Papa.ReadableStreamStreamer = ReadableStreamStreamer;
79
+ if (typeof PAPA_BROWSER_CONTEXT === "undefined") {
80
+ Papa.DuplexStreamStreamer = DuplexStreamStreamer;
81
+ }
82
+ if (global.jQuery) {
83
+ var $2 = global.jQuery;
84
+ $2.fn.parse = function(options) {
85
+ var config2 = options.config || {};
86
+ var queue = [];
87
+ this.each(function(idx) {
88
+ var supported = $2(this).prop("tagName").toUpperCase() === "INPUT" && $2(this).attr("type").toLowerCase() === "file" && global.FileReader;
89
+ if (!supported || !this.files || this.files.length === 0)
90
+ return true;
91
+ for (var i2 = 0;i2 < this.files.length; i2++) {
92
+ queue.push({
93
+ file: this.files[i2],
94
+ inputElem: this,
95
+ instanceConfig: $2.extend({}, config2)
96
+ });
97
+ }
98
+ });
99
+ parseNextFile();
100
+ return this;
101
+ function parseNextFile() {
102
+ if (queue.length === 0) {
103
+ if (isFunction(options.complete))
104
+ options.complete();
105
+ return;
106
+ }
107
+ var f = queue[0];
108
+ if (isFunction(options.before)) {
109
+ var returned = options.before(f.file, f.inputElem);
110
+ if (typeof returned === "object") {
111
+ if (returned.action === "abort") {
112
+ error45("AbortError", f.file, f.inputElem, returned.reason);
113
+ return;
114
+ } else if (returned.action === "skip") {
115
+ fileComplete();
116
+ return;
117
+ } else if (typeof returned.config === "object")
118
+ f.instanceConfig = $2.extend(f.instanceConfig, returned.config);
119
+ } else if (returned === "skip") {
120
+ fileComplete();
121
+ return;
122
+ }
123
+ }
124
+ var userCompleteFunc = f.instanceConfig.complete;
125
+ f.instanceConfig.complete = function(results) {
126
+ if (isFunction(userCompleteFunc))
127
+ userCompleteFunc(results, f.file, f.inputElem);
128
+ fileComplete();
129
+ };
130
+ Papa.parse(f.file, f.instanceConfig);
131
+ }
132
+ function error45(name, file2, elem, reason) {
133
+ if (isFunction(options.error))
134
+ options.error({ name }, file2, elem, reason);
135
+ }
136
+ function fileComplete() {
137
+ queue.splice(0, 1);
138
+ parseNextFile();
139
+ }
140
+ };
141
+ }
142
+ if (IS_PAPA_WORKER) {
143
+ global.onmessage = workerThreadReceivedMessage;
144
+ }
145
+ function CsvToJson(_input, _config) {
146
+ _config = _config || {};
147
+ var dynamicTyping = _config.dynamicTyping || false;
148
+ if (isFunction(dynamicTyping)) {
149
+ _config.dynamicTypingFunction = dynamicTyping;
150
+ dynamicTyping = {};
151
+ }
152
+ _config.dynamicTyping = dynamicTyping;
153
+ _config.transform = isFunction(_config.transform) ? _config.transform : false;
154
+ if (_config.worker && Papa.WORKERS_SUPPORTED) {
155
+ var w = newWorker();
156
+ w.userStep = _config.step;
157
+ w.userChunk = _config.chunk;
158
+ w.userComplete = _config.complete;
159
+ w.userError = _config.error;
160
+ _config.step = isFunction(_config.step);
161
+ _config.chunk = isFunction(_config.chunk);
162
+ _config.complete = isFunction(_config.complete);
163
+ _config.error = isFunction(_config.error);
164
+ delete _config.worker;
165
+ w.postMessage({
166
+ input: _input,
167
+ config: _config,
168
+ workerId: w.id
169
+ });
170
+ return;
171
+ }
172
+ var streamer = null;
173
+ if (_input === Papa.NODE_STREAM_INPUT && typeof PAPA_BROWSER_CONTEXT === "undefined") {
174
+ streamer = new DuplexStreamStreamer(_config);
175
+ return streamer.getStream();
176
+ } else if (typeof _input === "string") {
177
+ _input = stripBom(_input);
178
+ if (_config.download)
179
+ streamer = new NetworkStreamer(_config);
180
+ else
181
+ streamer = new StringStreamer(_config);
182
+ } else if (_input.readable === true && isFunction(_input.read) && isFunction(_input.on)) {
183
+ streamer = new ReadableStreamStreamer(_config);
184
+ } else if (global.File && _input instanceof File || _input instanceof Object)
185
+ streamer = new FileStreamer(_config);
186
+ return streamer.stream(_input);
187
+ function stripBom(string4) {
188
+ if (string4.charCodeAt(0) === 65279) {
189
+ return string4.slice(1);
190
+ }
191
+ return string4;
192
+ }
193
+ }
194
+ function JsonToCsv(_input, _config) {
195
+ var _quotes = false;
196
+ var _writeHeader = true;
197
+ var _delimiter = ",";
198
+ var _newline = `\r
199
+ `;
200
+ var _quoteChar = '"';
201
+ var _escapedQuote = _quoteChar + _quoteChar;
202
+ var _skipEmptyLines = false;
203
+ var _columns = null;
204
+ var _escapeFormulae = false;
205
+ unpackConfig();
206
+ var quoteCharRegex = new RegExp(escapeRegExp(_quoteChar), "g");
207
+ if (typeof _input === "string")
208
+ _input = JSON.parse(_input);
209
+ if (Array.isArray(_input)) {
210
+ if (!_input.length || Array.isArray(_input[0]))
211
+ return serialize(null, _input, _skipEmptyLines);
212
+ else if (typeof _input[0] === "object")
213
+ return serialize(_columns || Object.keys(_input[0]), _input, _skipEmptyLines);
214
+ } else if (typeof _input === "object") {
215
+ if (typeof _input.data === "string")
216
+ _input.data = JSON.parse(_input.data);
217
+ if (Array.isArray(_input.data)) {
218
+ if (!_input.fields)
219
+ _input.fields = _input.meta && _input.meta.fields || _columns;
220
+ if (!_input.fields)
221
+ _input.fields = Array.isArray(_input.data[0]) ? _input.fields : typeof _input.data[0] === "object" ? Object.keys(_input.data[0]) : [];
222
+ if (!Array.isArray(_input.data[0]) && typeof _input.data[0] !== "object")
223
+ _input.data = [_input.data];
224
+ }
225
+ return serialize(_input.fields || [], _input.data || [], _skipEmptyLines);
226
+ }
227
+ throw new Error("Unable to serialize unrecognized input");
228
+ function unpackConfig() {
229
+ if (typeof _config !== "object")
230
+ return;
231
+ if (typeof _config.delimiter === "string" && !Papa.BAD_DELIMITERS.filter(function(value) {
232
+ return _config.delimiter.indexOf(value) !== -1;
233
+ }).length) {
234
+ _delimiter = _config.delimiter;
235
+ }
236
+ if (typeof _config.quotes === "boolean" || typeof _config.quotes === "function" || Array.isArray(_config.quotes))
237
+ _quotes = _config.quotes;
238
+ if (typeof _config.skipEmptyLines === "boolean" || typeof _config.skipEmptyLines === "string")
239
+ _skipEmptyLines = _config.skipEmptyLines;
240
+ if (typeof _config.newline === "string")
241
+ _newline = _config.newline;
242
+ if (typeof _config.quoteChar === "string")
243
+ _quoteChar = _config.quoteChar;
244
+ if (typeof _config.header === "boolean")
245
+ _writeHeader = _config.header;
246
+ if (Array.isArray(_config.columns)) {
247
+ if (_config.columns.length === 0)
248
+ throw new Error("Option columns is empty");
249
+ _columns = _config.columns;
250
+ }
251
+ if (_config.escapeChar !== undefined) {
252
+ _escapedQuote = _config.escapeChar + _quoteChar;
253
+ }
254
+ if (_config.escapeFormulae instanceof RegExp) {
255
+ _escapeFormulae = _config.escapeFormulae;
256
+ } else if (typeof _config.escapeFormulae === "boolean" && _config.escapeFormulae) {
257
+ _escapeFormulae = /^[=+\-@\t\r].*$/;
258
+ }
259
+ }
260
+ function serialize(fields, data, skipEmptyLines) {
261
+ var csv = "";
262
+ if (typeof fields === "string")
263
+ fields = JSON.parse(fields);
264
+ if (typeof data === "string")
265
+ data = JSON.parse(data);
266
+ var hasHeader = Array.isArray(fields) && fields.length > 0;
267
+ var dataKeyedByField = !Array.isArray(data[0]);
268
+ if (hasHeader && _writeHeader) {
269
+ for (var i2 = 0;i2 < fields.length; i2++) {
270
+ if (i2 > 0)
271
+ csv += _delimiter;
272
+ csv += safe(fields[i2], i2);
273
+ }
274
+ if (data.length > 0)
275
+ csv += _newline;
276
+ }
277
+ for (var row = 0;row < data.length; row++) {
278
+ var maxCol = hasHeader ? fields.length : data[row].length;
279
+ var emptyLine = false;
280
+ var nullLine = hasHeader ? Object.keys(data[row]).length === 0 : data[row].length === 0;
281
+ if (skipEmptyLines && !hasHeader) {
282
+ emptyLine = skipEmptyLines === "greedy" ? data[row].join("").trim() === "" : data[row].length === 1 && data[row][0].length === 0;
283
+ }
284
+ if (skipEmptyLines === "greedy" && hasHeader) {
285
+ var line = [];
286
+ for (var c = 0;c < maxCol; c++) {
287
+ var cx = dataKeyedByField ? fields[c] : c;
288
+ line.push(data[row][cx]);
289
+ }
290
+ emptyLine = line.join("").trim() === "";
291
+ }
292
+ if (!emptyLine) {
293
+ for (var col = 0;col < maxCol; col++) {
294
+ if (col > 0 && !nullLine)
295
+ csv += _delimiter;
296
+ var colIdx = hasHeader && dataKeyedByField ? fields[col] : col;
297
+ csv += safe(data[row][colIdx], col);
298
+ }
299
+ if (row < data.length - 1 && (!skipEmptyLines || maxCol > 0 && !nullLine)) {
300
+ csv += _newline;
301
+ }
302
+ }
303
+ }
304
+ return csv;
305
+ }
306
+ function safe(str2, col) {
307
+ if (typeof str2 === "undefined" || str2 === null)
308
+ return "";
309
+ if (str2.constructor === Date)
310
+ return JSON.stringify(str2).slice(1, 25);
311
+ var needsQuotes = false;
312
+ if (_escapeFormulae && typeof str2 === "string" && _escapeFormulae.test(str2)) {
313
+ str2 = "'" + str2;
314
+ needsQuotes = true;
315
+ }
316
+ var escapedQuoteStr = str2.toString().replace(quoteCharRegex, _escapedQuote);
317
+ needsQuotes = needsQuotes || _quotes === true || typeof _quotes === "function" && _quotes(str2, col) || Array.isArray(_quotes) && _quotes[col] || hasAny(escapedQuoteStr, Papa.BAD_DELIMITERS) || escapedQuoteStr.indexOf(_delimiter) > -1 || escapedQuoteStr.charAt(0) === " " || escapedQuoteStr.charAt(escapedQuoteStr.length - 1) === " ";
318
+ return needsQuotes ? _quoteChar + escapedQuoteStr + _quoteChar : escapedQuoteStr;
319
+ }
320
+ function hasAny(str2, substrings) {
321
+ for (var i2 = 0;i2 < substrings.length; i2++)
322
+ if (str2.indexOf(substrings[i2]) > -1)
323
+ return true;
324
+ return false;
325
+ }
326
+ }
327
+ function ChunkStreamer(config2) {
328
+ this._handle = null;
329
+ this._finished = false;
330
+ this._completed = false;
331
+ this._halted = false;
332
+ this._input = null;
333
+ this._baseIndex = 0;
334
+ this._partialLine = "";
335
+ this._rowCount = 0;
336
+ this._start = 0;
337
+ this._nextChunk = null;
338
+ this.isFirstChunk = true;
339
+ this._completeResults = {
340
+ data: [],
341
+ errors: [],
342
+ meta: {}
343
+ };
344
+ replaceConfig.call(this, config2);
345
+ this.parseChunk = function(chunk, isFakeChunk) {
346
+ const skipFirstNLines = parseInt(this._config.skipFirstNLines) || 0;
347
+ if (this.isFirstChunk && skipFirstNLines > 0) {
348
+ let _newline = this._config.newline;
349
+ if (!_newline) {
350
+ const quoteChar = this._config.quoteChar || '"';
351
+ _newline = this._handle.guessLineEndings(chunk, quoteChar);
352
+ }
353
+ const splitChunk = chunk.split(_newline);
354
+ chunk = [...splitChunk.slice(skipFirstNLines)].join(_newline);
355
+ }
356
+ if (this.isFirstChunk && isFunction(this._config.beforeFirstChunk)) {
357
+ var modifiedChunk = this._config.beforeFirstChunk(chunk);
358
+ if (modifiedChunk !== undefined)
359
+ chunk = modifiedChunk;
360
+ }
361
+ this.isFirstChunk = false;
362
+ this._halted = false;
363
+ var aggregate = this._partialLine + chunk;
364
+ this._partialLine = "";
365
+ var results = this._handle.parse(aggregate, this._baseIndex, !this._finished);
366
+ if (this._handle.paused() || this._handle.aborted()) {
367
+ this._halted = true;
368
+ return;
369
+ }
370
+ var lastIndex = results.meta.cursor;
371
+ if (!this._finished) {
372
+ this._partialLine = aggregate.substring(lastIndex - this._baseIndex);
373
+ this._baseIndex = lastIndex;
374
+ }
375
+ if (results && results.data)
376
+ this._rowCount += results.data.length;
377
+ var finishedIncludingPreview = this._finished || this._config.preview && this._rowCount >= this._config.preview;
378
+ if (IS_PAPA_WORKER) {
379
+ global.postMessage({
380
+ results,
381
+ workerId: Papa.WORKER_ID,
382
+ finished: finishedIncludingPreview
383
+ });
384
+ } else if (isFunction(this._config.chunk) && !isFakeChunk) {
385
+ this._config.chunk(results, this._handle);
386
+ if (this._handle.paused() || this._handle.aborted()) {
387
+ this._halted = true;
388
+ return;
389
+ }
390
+ results = undefined;
391
+ this._completeResults = undefined;
392
+ }
393
+ if (!this._config.step && !this._config.chunk) {
394
+ this._completeResults.data = this._completeResults.data.concat(results.data);
395
+ this._completeResults.errors = this._completeResults.errors.concat(results.errors);
396
+ this._completeResults.meta = results.meta;
397
+ }
398
+ if (!this._completed && finishedIncludingPreview && isFunction(this._config.complete) && (!results || !results.meta.aborted)) {
399
+ this._config.complete(this._completeResults, this._input);
400
+ this._completed = true;
401
+ }
402
+ if (!finishedIncludingPreview && (!results || !results.meta.paused))
403
+ this._nextChunk();
404
+ return results;
405
+ };
406
+ this._sendError = function(error45) {
407
+ if (isFunction(this._config.error))
408
+ this._config.error(error45);
409
+ else if (IS_PAPA_WORKER && this._config.error) {
410
+ global.postMessage({
411
+ workerId: Papa.WORKER_ID,
412
+ error: error45,
413
+ finished: false
414
+ });
415
+ }
416
+ };
417
+ function replaceConfig(config3) {
418
+ var configCopy = copy(config3);
419
+ configCopy.chunkSize = parseInt(configCopy.chunkSize);
420
+ if (!config3.step && !config3.chunk)
421
+ configCopy.chunkSize = null;
422
+ this._handle = new ParserHandle(configCopy);
423
+ this._handle.streamer = this;
424
+ this._config = configCopy;
425
+ }
426
+ }
427
+ function NetworkStreamer(config2) {
428
+ config2 = config2 || {};
429
+ if (!config2.chunkSize)
430
+ config2.chunkSize = Papa.RemoteChunkSize;
431
+ ChunkStreamer.call(this, config2);
432
+ var xhr;
433
+ if (IS_WORKER) {
434
+ this._nextChunk = function() {
435
+ this._readChunk();
436
+ this._chunkLoaded();
437
+ };
438
+ } else {
439
+ this._nextChunk = function() {
440
+ this._readChunk();
441
+ };
442
+ }
443
+ this.stream = function(url2) {
444
+ this._input = url2;
445
+ this._nextChunk();
446
+ };
447
+ this._readChunk = function() {
448
+ if (this._finished) {
449
+ this._chunkLoaded();
450
+ return;
451
+ }
452
+ xhr = new XMLHttpRequest;
453
+ if (this._config.withCredentials) {
454
+ xhr.withCredentials = this._config.withCredentials;
455
+ }
456
+ if (!IS_WORKER) {
457
+ xhr.onload = bindFunction(this._chunkLoaded, this);
458
+ xhr.onerror = bindFunction(this._chunkError, this);
459
+ }
460
+ xhr.open(this._config.downloadRequestBody ? "POST" : "GET", this._input, !IS_WORKER);
461
+ if (this._config.downloadRequestHeaders) {
462
+ var headers = this._config.downloadRequestHeaders;
463
+ for (var headerName in headers) {
464
+ xhr.setRequestHeader(headerName, headers[headerName]);
465
+ }
466
+ }
467
+ if (this._config.chunkSize) {
468
+ var end = this._start + this._config.chunkSize - 1;
469
+ xhr.setRequestHeader("Range", "bytes=" + this._start + "-" + end);
470
+ }
471
+ try {
472
+ xhr.send(this._config.downloadRequestBody);
473
+ } catch (err) {
474
+ this._chunkError(err.message);
475
+ }
476
+ if (IS_WORKER && xhr.status === 0)
477
+ this._chunkError();
478
+ };
479
+ this._chunkLoaded = function() {
480
+ if (xhr.readyState !== 4)
481
+ return;
482
+ if (xhr.status < 200 || xhr.status >= 400) {
483
+ this._chunkError();
484
+ return;
485
+ }
486
+ this._start += this._config.chunkSize ? this._config.chunkSize : xhr.responseText.length;
487
+ this._finished = !this._config.chunkSize || this._start >= getFileSize(xhr);
488
+ this.parseChunk(xhr.responseText);
489
+ };
490
+ this._chunkError = function(errorMessage) {
491
+ var errorText = xhr.statusText || errorMessage;
492
+ this._sendError(new Error(errorText));
493
+ };
494
+ function getFileSize(xhr2) {
495
+ var contentRange = xhr2.getResponseHeader("Content-Range");
496
+ if (contentRange === null) {
497
+ return -1;
498
+ }
499
+ return parseInt(contentRange.substring(contentRange.lastIndexOf("/") + 1));
500
+ }
501
+ }
502
+ NetworkStreamer.prototype = Object.create(ChunkStreamer.prototype);
503
+ NetworkStreamer.prototype.constructor = NetworkStreamer;
504
+ function FileStreamer(config2) {
505
+ config2 = config2 || {};
506
+ if (!config2.chunkSize)
507
+ config2.chunkSize = Papa.LocalChunkSize;
508
+ ChunkStreamer.call(this, config2);
509
+ var reader, slice;
510
+ var usingAsyncReader = typeof FileReader !== "undefined";
511
+ this.stream = function(file2) {
512
+ this._input = file2;
513
+ slice = file2.slice || file2.webkitSlice || file2.mozSlice;
514
+ if (usingAsyncReader) {
515
+ reader = new FileReader;
516
+ reader.onload = bindFunction(this._chunkLoaded, this);
517
+ reader.onerror = bindFunction(this._chunkError, this);
518
+ } else
519
+ reader = new FileReaderSync;
520
+ this._nextChunk();
521
+ };
522
+ this._nextChunk = function() {
523
+ if (!this._finished && (!this._config.preview || this._rowCount < this._config.preview))
524
+ this._readChunk();
525
+ };
526
+ this._readChunk = function() {
527
+ var input = this._input;
528
+ if (this._config.chunkSize) {
529
+ var end = Math.min(this._start + this._config.chunkSize, this._input.size);
530
+ input = slice.call(input, this._start, end);
531
+ }
532
+ var txt = reader.readAsText(input, this._config.encoding);
533
+ if (!usingAsyncReader)
534
+ this._chunkLoaded({ target: { result: txt } });
535
+ };
536
+ this._chunkLoaded = function(event) {
537
+ this._start += this._config.chunkSize;
538
+ this._finished = !this._config.chunkSize || this._start >= this._input.size;
539
+ this.parseChunk(event.target.result);
540
+ };
541
+ this._chunkError = function() {
542
+ this._sendError(reader.error);
543
+ };
544
+ }
545
+ FileStreamer.prototype = Object.create(ChunkStreamer.prototype);
546
+ FileStreamer.prototype.constructor = FileStreamer;
547
+ function StringStreamer(config2) {
548
+ config2 = config2 || {};
549
+ ChunkStreamer.call(this, config2);
550
+ var remaining;
551
+ this.stream = function(s) {
552
+ remaining = s;
553
+ return this._nextChunk();
554
+ };
555
+ this._nextChunk = function() {
556
+ if (this._finished)
557
+ return;
558
+ var size = this._config.chunkSize;
559
+ var chunk;
560
+ if (size) {
561
+ chunk = remaining.substring(0, size);
562
+ remaining = remaining.substring(size);
563
+ } else {
564
+ chunk = remaining;
565
+ remaining = "";
566
+ }
567
+ this._finished = !remaining;
568
+ return this.parseChunk(chunk);
569
+ };
570
+ }
571
+ StringStreamer.prototype = Object.create(StringStreamer.prototype);
572
+ StringStreamer.prototype.constructor = StringStreamer;
573
+ function ReadableStreamStreamer(config2) {
574
+ config2 = config2 || {};
575
+ ChunkStreamer.call(this, config2);
576
+ var queue = [];
577
+ var parseOnData = true;
578
+ var streamHasEnded = false;
579
+ this.pause = function() {
580
+ ChunkStreamer.prototype.pause.apply(this, arguments);
581
+ this._input.pause();
582
+ };
583
+ this.resume = function() {
584
+ ChunkStreamer.prototype.resume.apply(this, arguments);
585
+ this._input.resume();
586
+ };
587
+ this.stream = function(stream) {
588
+ this._input = stream;
589
+ this._input.on("data", this._streamData);
590
+ this._input.on("end", this._streamEnd);
591
+ this._input.on("error", this._streamError);
592
+ };
593
+ this._checkIsFinished = function() {
594
+ if (streamHasEnded && queue.length === 1) {
595
+ this._finished = true;
596
+ }
597
+ };
598
+ this._nextChunk = function() {
599
+ this._checkIsFinished();
600
+ if (queue.length) {
601
+ this.parseChunk(queue.shift());
602
+ } else {
603
+ parseOnData = true;
604
+ }
605
+ };
606
+ this._streamData = bindFunction(function(chunk) {
607
+ try {
608
+ queue.push(typeof chunk === "string" ? chunk : chunk.toString(this._config.encoding));
609
+ if (parseOnData) {
610
+ parseOnData = false;
611
+ this._checkIsFinished();
612
+ this.parseChunk(queue.shift());
613
+ }
614
+ } catch (error45) {
615
+ this._streamError(error45);
616
+ }
617
+ }, this);
618
+ this._streamError = bindFunction(function(error45) {
619
+ this._streamCleanUp();
620
+ this._sendError(error45);
621
+ }, this);
622
+ this._streamEnd = bindFunction(function() {
623
+ this._streamCleanUp();
624
+ streamHasEnded = true;
625
+ this._streamData("");
626
+ }, this);
627
+ this._streamCleanUp = bindFunction(function() {
628
+ this._input.removeListener("data", this._streamData);
629
+ this._input.removeListener("end", this._streamEnd);
630
+ this._input.removeListener("error", this._streamError);
631
+ }, this);
632
+ }
633
+ ReadableStreamStreamer.prototype = Object.create(ChunkStreamer.prototype);
634
+ ReadableStreamStreamer.prototype.constructor = ReadableStreamStreamer;
635
+ function DuplexStreamStreamer(_config) {
636
+ var Duplex = __require("stream").Duplex;
637
+ var config2 = copy(_config);
638
+ var parseOnWrite = true;
639
+ var writeStreamHasFinished = false;
640
+ var parseCallbackQueue = [];
641
+ var stream = null;
642
+ this._onCsvData = function(results) {
643
+ var data = results.data;
644
+ if (!stream.push(data) && !this._handle.paused()) {
645
+ this._handle.pause();
646
+ }
647
+ };
648
+ this._onCsvComplete = function() {
649
+ stream.push(null);
650
+ };
651
+ config2.step = bindFunction(this._onCsvData, this);
652
+ config2.complete = bindFunction(this._onCsvComplete, this);
653
+ ChunkStreamer.call(this, config2);
654
+ this._nextChunk = function() {
655
+ if (writeStreamHasFinished && parseCallbackQueue.length === 1) {
656
+ this._finished = true;
657
+ }
658
+ if (parseCallbackQueue.length) {
659
+ parseCallbackQueue.shift()();
660
+ } else {
661
+ parseOnWrite = true;
662
+ }
663
+ };
664
+ this._addToParseQueue = function(chunk, callback) {
665
+ parseCallbackQueue.push(bindFunction(function() {
666
+ this.parseChunk(typeof chunk === "string" ? chunk : chunk.toString(config2.encoding));
667
+ if (isFunction(callback)) {
668
+ return callback();
669
+ }
670
+ }, this));
671
+ if (parseOnWrite) {
672
+ parseOnWrite = false;
673
+ this._nextChunk();
674
+ }
675
+ };
676
+ this._onRead = function() {
677
+ if (this._handle.paused()) {
678
+ this._handle.resume();
679
+ }
680
+ };
681
+ this._onWrite = function(chunk, encoding, callback) {
682
+ this._addToParseQueue(chunk, callback);
683
+ };
684
+ this._onWriteComplete = function() {
685
+ writeStreamHasFinished = true;
686
+ this._addToParseQueue("");
687
+ };
688
+ this.getStream = function() {
689
+ return stream;
690
+ };
691
+ stream = new Duplex({
692
+ readableObjectMode: true,
693
+ decodeStrings: false,
694
+ read: bindFunction(this._onRead, this),
695
+ write: bindFunction(this._onWrite, this)
696
+ });
697
+ stream.once("finish", bindFunction(this._onWriteComplete, this));
698
+ }
699
+ if (typeof PAPA_BROWSER_CONTEXT === "undefined") {
700
+ DuplexStreamStreamer.prototype = Object.create(ChunkStreamer.prototype);
701
+ DuplexStreamStreamer.prototype.constructor = DuplexStreamStreamer;
702
+ }
703
+ function ParserHandle(_config) {
704
+ var MAX_FLOAT = Math.pow(2, 53);
705
+ var MIN_FLOAT = -MAX_FLOAT;
706
+ var FLOAT = /^\s*-?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/;
707
+ var ISO_DATE = /^((\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)))$/;
708
+ var self2 = this;
709
+ var _stepCounter = 0;
710
+ var _rowCounter = 0;
711
+ var _input;
712
+ var _parser;
713
+ var _paused = false;
714
+ var _aborted = false;
715
+ var _delimiterError;
716
+ var _fields = [];
717
+ var _results = {
718
+ data: [],
719
+ errors: [],
720
+ meta: {}
721
+ };
722
+ if (isFunction(_config.step)) {
723
+ var userStep = _config.step;
724
+ _config.step = function(results) {
725
+ _results = results;
726
+ if (needsHeaderRow())
727
+ processResults();
728
+ else {
729
+ processResults();
730
+ if (_results.data.length === 0)
731
+ return;
732
+ _stepCounter += results.data.length;
733
+ if (_config.preview && _stepCounter > _config.preview)
734
+ _parser.abort();
735
+ else {
736
+ _results.data = _results.data[0];
737
+ userStep(_results, self2);
738
+ }
739
+ }
740
+ };
741
+ }
742
+ this.parse = function(input, baseIndex, ignoreLastRow) {
743
+ var quoteChar = _config.quoteChar || '"';
744
+ if (!_config.newline)
745
+ _config.newline = this.guessLineEndings(input, quoteChar);
746
+ _delimiterError = false;
747
+ if (!_config.delimiter) {
748
+ var delimGuess = guessDelimiter(input, _config.newline, _config.skipEmptyLines, _config.comments, _config.delimitersToGuess);
749
+ if (delimGuess.successful)
750
+ _config.delimiter = delimGuess.bestDelimiter;
751
+ else {
752
+ _delimiterError = true;
753
+ _config.delimiter = Papa.DefaultDelimiter;
754
+ }
755
+ _results.meta.delimiter = _config.delimiter;
756
+ } else if (isFunction(_config.delimiter)) {
757
+ _config.delimiter = _config.delimiter(input);
758
+ _results.meta.delimiter = _config.delimiter;
759
+ }
760
+ var parserConfig = copy(_config);
761
+ if (_config.preview && _config.header)
762
+ parserConfig.preview++;
763
+ _input = input;
764
+ _parser = new Parser(parserConfig);
765
+ _results = _parser.parse(_input, baseIndex, ignoreLastRow);
766
+ processResults();
767
+ return _paused ? { meta: { paused: true } } : _results || { meta: { paused: false } };
768
+ };
769
+ this.paused = function() {
770
+ return _paused;
771
+ };
772
+ this.pause = function() {
773
+ _paused = true;
774
+ _parser.abort();
775
+ _input = isFunction(_config.chunk) ? "" : _input.substring(_parser.getCharIndex());
776
+ };
777
+ this.resume = function() {
778
+ if (self2.streamer._halted) {
779
+ _paused = false;
780
+ self2.streamer.parseChunk(_input, true);
781
+ } else {
782
+ setTimeout(self2.resume, 3);
783
+ }
784
+ };
785
+ this.aborted = function() {
786
+ return _aborted;
787
+ };
788
+ this.abort = function() {
789
+ _aborted = true;
790
+ _parser.abort();
791
+ _results.meta.aborted = true;
792
+ if (isFunction(_config.complete))
793
+ _config.complete(_results);
794
+ _input = "";
795
+ };
796
+ this.guessLineEndings = function(input, quoteChar) {
797
+ input = input.substring(0, 1024 * 1024);
798
+ var re = new RegExp(escapeRegExp(quoteChar) + "([^]*?)" + escapeRegExp(quoteChar), "gm");
799
+ input = input.replace(re, "");
800
+ var r = input.split("\r");
801
+ var n = input.split(`
802
+ `);
803
+ var nAppearsFirst = n.length > 1 && n[0].length < r[0].length;
804
+ if (r.length === 1 || nAppearsFirst)
805
+ return `
806
+ `;
807
+ var numWithN = 0;
808
+ for (var i2 = 0;i2 < r.length; i2++) {
809
+ if (r[i2][0] === `
810
+ `)
811
+ numWithN++;
812
+ }
813
+ return numWithN >= r.length / 2 ? `\r
814
+ ` : "\r";
815
+ };
816
+ function testEmptyLine(s) {
817
+ return _config.skipEmptyLines === "greedy" ? s.join("").trim() === "" : s.length === 1 && s[0].length === 0;
818
+ }
819
+ function testFloat(s) {
820
+ if (FLOAT.test(s)) {
821
+ var floatValue = parseFloat(s);
822
+ if (floatValue > MIN_FLOAT && floatValue < MAX_FLOAT) {
823
+ return true;
824
+ }
825
+ }
826
+ return false;
827
+ }
828
+ function processResults() {
829
+ if (_results && _delimiterError) {
830
+ addError("Delimiter", "UndetectableDelimiter", "Unable to auto-detect delimiting character; defaulted to '" + Papa.DefaultDelimiter + "'");
831
+ _delimiterError = false;
832
+ }
833
+ if (_config.skipEmptyLines) {
834
+ _results.data = _results.data.filter(function(d) {
835
+ return !testEmptyLine(d);
836
+ });
837
+ }
838
+ if (needsHeaderRow())
839
+ fillHeaderFields();
840
+ return applyHeaderAndDynamicTypingAndTransformation();
841
+ }
842
+ function needsHeaderRow() {
843
+ return _config.header && _fields.length === 0;
844
+ }
845
+ function fillHeaderFields() {
846
+ if (!_results)
847
+ return;
848
+ function addHeader(header, i3) {
849
+ if (isFunction(_config.transformHeader))
850
+ header = _config.transformHeader(header, i3);
851
+ _fields.push(header);
852
+ }
853
+ if (Array.isArray(_results.data[0])) {
854
+ for (var i2 = 0;needsHeaderRow() && i2 < _results.data.length; i2++)
855
+ _results.data[i2].forEach(addHeader);
856
+ _results.data.splice(0, 1);
857
+ } else
858
+ _results.data.forEach(addHeader);
859
+ }
860
+ function shouldApplyDynamicTyping(field) {
861
+ if (_config.dynamicTypingFunction && _config.dynamicTyping[field] === undefined) {
862
+ _config.dynamicTyping[field] = _config.dynamicTypingFunction(field);
863
+ }
864
+ return (_config.dynamicTyping[field] || _config.dynamicTyping) === true;
865
+ }
866
+ function parseDynamic(field, value) {
867
+ if (shouldApplyDynamicTyping(field)) {
868
+ if (value === "true" || value === "TRUE")
869
+ return true;
870
+ else if (value === "false" || value === "FALSE")
871
+ return false;
872
+ else if (testFloat(value))
873
+ return parseFloat(value);
874
+ else if (ISO_DATE.test(value))
875
+ return new Date(value);
876
+ else
877
+ return value === "" ? null : value;
878
+ }
879
+ return value;
880
+ }
881
+ function applyHeaderAndDynamicTypingAndTransformation() {
882
+ if (!_results || !_config.header && !_config.dynamicTyping && !_config.transform)
883
+ return _results;
884
+ function processRow(rowSource, i2) {
885
+ var row = _config.header ? {} : [];
886
+ var j;
887
+ for (j = 0;j < rowSource.length; j++) {
888
+ var field = j;
889
+ var value = rowSource[j];
890
+ if (_config.header)
891
+ field = j >= _fields.length ? "__parsed_extra" : _fields[j];
892
+ if (_config.transform)
893
+ value = _config.transform(value, field);
894
+ value = parseDynamic(field, value);
895
+ if (field === "__parsed_extra") {
896
+ row[field] = row[field] || [];
897
+ row[field].push(value);
898
+ } else
899
+ row[field] = value;
900
+ }
901
+ if (_config.header) {
902
+ if (j > _fields.length)
903
+ addError("FieldMismatch", "TooManyFields", "Too many fields: expected " + _fields.length + " fields but parsed " + j, _rowCounter + i2);
904
+ else if (j < _fields.length)
905
+ addError("FieldMismatch", "TooFewFields", "Too few fields: expected " + _fields.length + " fields but parsed " + j, _rowCounter + i2);
906
+ }
907
+ return row;
908
+ }
909
+ var incrementBy = 1;
910
+ if (!_results.data.length || Array.isArray(_results.data[0])) {
911
+ _results.data = _results.data.map(processRow);
912
+ incrementBy = _results.data.length;
913
+ } else
914
+ _results.data = processRow(_results.data, 0);
915
+ if (_config.header && _results.meta)
916
+ _results.meta.fields = _fields;
917
+ _rowCounter += incrementBy;
918
+ return _results;
919
+ }
920
+ function guessDelimiter(input, newline, skipEmptyLines, comments, delimitersToGuess) {
921
+ var bestDelim, bestDelta, fieldCountPrevRow, maxFieldCount;
922
+ delimitersToGuess = delimitersToGuess || [",", "\t", "|", ";", Papa.RECORD_SEP, Papa.UNIT_SEP];
923
+ for (var i2 = 0;i2 < delimitersToGuess.length; i2++) {
924
+ var delim = delimitersToGuess[i2];
925
+ var delta = 0, avgFieldCount = 0, emptyLinesCount = 0;
926
+ fieldCountPrevRow = undefined;
927
+ var preview = new Parser({
928
+ comments,
929
+ delimiter: delim,
930
+ newline,
931
+ preview: 10
932
+ }).parse(input);
933
+ for (var j = 0;j < preview.data.length; j++) {
934
+ if (skipEmptyLines && testEmptyLine(preview.data[j])) {
935
+ emptyLinesCount++;
936
+ continue;
937
+ }
938
+ var fieldCount = preview.data[j].length;
939
+ avgFieldCount += fieldCount;
940
+ if (typeof fieldCountPrevRow === "undefined") {
941
+ fieldCountPrevRow = fieldCount;
942
+ continue;
943
+ } else if (fieldCount > 0) {
944
+ delta += Math.abs(fieldCount - fieldCountPrevRow);
945
+ fieldCountPrevRow = fieldCount;
946
+ }
947
+ }
948
+ if (preview.data.length > 0)
949
+ avgFieldCount /= preview.data.length - emptyLinesCount;
950
+ if ((typeof bestDelta === "undefined" || delta <= bestDelta) && (typeof maxFieldCount === "undefined" || avgFieldCount > maxFieldCount) && avgFieldCount > 1.99) {
951
+ bestDelta = delta;
952
+ bestDelim = delim;
953
+ maxFieldCount = avgFieldCount;
954
+ }
955
+ }
956
+ _config.delimiter = bestDelim;
957
+ return {
958
+ successful: !!bestDelim,
959
+ bestDelimiter: bestDelim
960
+ };
961
+ }
962
+ function addError(type2, code, msg, row) {
963
+ var error45 = {
964
+ type: type2,
965
+ code,
966
+ message: msg
967
+ };
968
+ if (row !== undefined) {
969
+ error45.row = row;
970
+ }
971
+ _results.errors.push(error45);
972
+ }
973
+ }
974
+ function escapeRegExp(string4) {
975
+ return string4.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
976
+ }
977
+ function Parser(config2) {
978
+ config2 = config2 || {};
979
+ var delim = config2.delimiter;
980
+ var newline = config2.newline;
981
+ var comments = config2.comments;
982
+ var step = config2.step;
983
+ var preview = config2.preview;
984
+ var fastMode = config2.fastMode;
985
+ var quoteChar;
986
+ var renamedHeaders = null;
987
+ var headerParsed = false;
988
+ if (config2.quoteChar === undefined || config2.quoteChar === null) {
989
+ quoteChar = '"';
990
+ } else {
991
+ quoteChar = config2.quoteChar;
992
+ }
993
+ var escapeChar = quoteChar;
994
+ if (config2.escapeChar !== undefined) {
995
+ escapeChar = config2.escapeChar;
996
+ }
997
+ if (typeof delim !== "string" || Papa.BAD_DELIMITERS.indexOf(delim) > -1)
998
+ delim = ",";
999
+ if (comments === delim)
1000
+ throw new Error("Comment character same as delimiter");
1001
+ else if (comments === true)
1002
+ comments = "#";
1003
+ else if (typeof comments !== "string" || Papa.BAD_DELIMITERS.indexOf(comments) > -1)
1004
+ comments = false;
1005
+ if (newline !== `
1006
+ ` && newline !== "\r" && newline !== `\r
1007
+ `)
1008
+ newline = `
1009
+ `;
1010
+ var cursor = 0;
1011
+ var aborted2 = false;
1012
+ this.parse = function(input, baseIndex, ignoreLastRow) {
1013
+ if (typeof input !== "string")
1014
+ throw new Error("Input must be a string");
1015
+ var inputLen = input.length, delimLen = delim.length, newlineLen = newline.length, commentsLen = comments.length;
1016
+ var stepIsFunction = isFunction(step);
1017
+ cursor = 0;
1018
+ var data = [], errors3 = [], row = [], lastCursor = 0;
1019
+ if (!input)
1020
+ return returnable();
1021
+ if (fastMode || fastMode !== false && input.indexOf(quoteChar) === -1) {
1022
+ var rows = input.split(newline);
1023
+ for (var i2 = 0;i2 < rows.length; i2++) {
1024
+ row = rows[i2];
1025
+ cursor += row.length;
1026
+ if (i2 !== rows.length - 1)
1027
+ cursor += newline.length;
1028
+ else if (ignoreLastRow)
1029
+ return returnable();
1030
+ if (comments && row.substring(0, commentsLen) === comments)
1031
+ continue;
1032
+ if (stepIsFunction) {
1033
+ data = [];
1034
+ pushRow(row.split(delim));
1035
+ doStep();
1036
+ if (aborted2)
1037
+ return returnable();
1038
+ } else
1039
+ pushRow(row.split(delim));
1040
+ if (preview && i2 >= preview) {
1041
+ data = data.slice(0, preview);
1042
+ return returnable(true);
1043
+ }
1044
+ }
1045
+ return returnable();
1046
+ }
1047
+ var nextDelim = input.indexOf(delim, cursor);
1048
+ var nextNewline = input.indexOf(newline, cursor);
1049
+ var quoteCharRegex = new RegExp(escapeRegExp(escapeChar) + escapeRegExp(quoteChar), "g");
1050
+ var quoteSearch = input.indexOf(quoteChar, cursor);
1051
+ for (;; ) {
1052
+ if (input[cursor] === quoteChar) {
1053
+ quoteSearch = cursor;
1054
+ cursor++;
1055
+ for (;; ) {
1056
+ quoteSearch = input.indexOf(quoteChar, quoteSearch + 1);
1057
+ if (quoteSearch === -1) {
1058
+ if (!ignoreLastRow) {
1059
+ errors3.push({
1060
+ type: "Quotes",
1061
+ code: "MissingQuotes",
1062
+ message: "Quoted field unterminated",
1063
+ row: data.length,
1064
+ index: cursor
1065
+ });
1066
+ }
1067
+ return finish();
1068
+ }
1069
+ if (quoteSearch === inputLen - 1) {
1070
+ var value = input.substring(cursor, quoteSearch).replace(quoteCharRegex, quoteChar);
1071
+ return finish(value);
1072
+ }
1073
+ if (quoteChar === escapeChar && input[quoteSearch + 1] === escapeChar) {
1074
+ quoteSearch++;
1075
+ continue;
1076
+ }
1077
+ if (quoteChar !== escapeChar && quoteSearch !== 0 && input[quoteSearch - 1] === escapeChar) {
1078
+ continue;
1079
+ }
1080
+ if (nextDelim !== -1 && nextDelim < quoteSearch + 1) {
1081
+ nextDelim = input.indexOf(delim, quoteSearch + 1);
1082
+ }
1083
+ if (nextNewline !== -1 && nextNewline < quoteSearch + 1) {
1084
+ nextNewline = input.indexOf(newline, quoteSearch + 1);
1085
+ }
1086
+ var checkUpTo = nextNewline === -1 ? nextDelim : Math.min(nextDelim, nextNewline);
1087
+ var spacesBetweenQuoteAndDelimiter = extraSpaces(checkUpTo);
1088
+ if (input.substr(quoteSearch + 1 + spacesBetweenQuoteAndDelimiter, delimLen) === delim) {
1089
+ row.push(input.substring(cursor, quoteSearch).replace(quoteCharRegex, quoteChar));
1090
+ cursor = quoteSearch + 1 + spacesBetweenQuoteAndDelimiter + delimLen;
1091
+ if (input[quoteSearch + 1 + spacesBetweenQuoteAndDelimiter + delimLen] !== quoteChar) {
1092
+ quoteSearch = input.indexOf(quoteChar, cursor);
1093
+ }
1094
+ nextDelim = input.indexOf(delim, cursor);
1095
+ nextNewline = input.indexOf(newline, cursor);
1096
+ break;
1097
+ }
1098
+ var spacesBetweenQuoteAndNewLine = extraSpaces(nextNewline);
1099
+ if (input.substring(quoteSearch + 1 + spacesBetweenQuoteAndNewLine, quoteSearch + 1 + spacesBetweenQuoteAndNewLine + newlineLen) === newline) {
1100
+ row.push(input.substring(cursor, quoteSearch).replace(quoteCharRegex, quoteChar));
1101
+ saveRow(quoteSearch + 1 + spacesBetweenQuoteAndNewLine + newlineLen);
1102
+ nextDelim = input.indexOf(delim, cursor);
1103
+ quoteSearch = input.indexOf(quoteChar, cursor);
1104
+ if (stepIsFunction) {
1105
+ doStep();
1106
+ if (aborted2)
1107
+ return returnable();
1108
+ }
1109
+ if (preview && data.length >= preview)
1110
+ return returnable(true);
1111
+ break;
1112
+ }
1113
+ errors3.push({
1114
+ type: "Quotes",
1115
+ code: "InvalidQuotes",
1116
+ message: "Trailing quote on quoted field is malformed",
1117
+ row: data.length,
1118
+ index: cursor
1119
+ });
1120
+ quoteSearch++;
1121
+ continue;
1122
+ }
1123
+ continue;
1124
+ }
1125
+ if (comments && row.length === 0 && input.substring(cursor, cursor + commentsLen) === comments) {
1126
+ if (nextNewline === -1)
1127
+ return returnable();
1128
+ cursor = nextNewline + newlineLen;
1129
+ nextNewline = input.indexOf(newline, cursor);
1130
+ nextDelim = input.indexOf(delim, cursor);
1131
+ continue;
1132
+ }
1133
+ if (nextDelim !== -1 && (nextDelim < nextNewline || nextNewline === -1)) {
1134
+ row.push(input.substring(cursor, nextDelim));
1135
+ cursor = nextDelim + delimLen;
1136
+ nextDelim = input.indexOf(delim, cursor);
1137
+ continue;
1138
+ }
1139
+ if (nextNewline !== -1) {
1140
+ row.push(input.substring(cursor, nextNewline));
1141
+ saveRow(nextNewline + newlineLen);
1142
+ if (stepIsFunction) {
1143
+ doStep();
1144
+ if (aborted2)
1145
+ return returnable();
1146
+ }
1147
+ if (preview && data.length >= preview)
1148
+ return returnable(true);
1149
+ continue;
1150
+ }
1151
+ break;
1152
+ }
1153
+ return finish();
1154
+ function pushRow(row2) {
1155
+ data.push(row2);
1156
+ lastCursor = cursor;
1157
+ }
1158
+ function extraSpaces(index) {
1159
+ var spaceLength = 0;
1160
+ if (index !== -1) {
1161
+ var textBetweenClosingQuoteAndIndex = input.substring(quoteSearch + 1, index);
1162
+ if (textBetweenClosingQuoteAndIndex && textBetweenClosingQuoteAndIndex.trim() === "") {
1163
+ spaceLength = textBetweenClosingQuoteAndIndex.length;
1164
+ }
1165
+ }
1166
+ return spaceLength;
1167
+ }
1168
+ function finish(value2) {
1169
+ if (ignoreLastRow)
1170
+ return returnable();
1171
+ if (typeof value2 === "undefined")
1172
+ value2 = input.substring(cursor);
1173
+ row.push(value2);
1174
+ cursor = inputLen;
1175
+ pushRow(row);
1176
+ if (stepIsFunction)
1177
+ doStep();
1178
+ return returnable();
1179
+ }
1180
+ function saveRow(newCursor) {
1181
+ cursor = newCursor;
1182
+ pushRow(row);
1183
+ row = [];
1184
+ nextNewline = input.indexOf(newline, cursor);
1185
+ }
1186
+ function returnable(stopped) {
1187
+ if (config2.header && !baseIndex && data.length && !headerParsed) {
1188
+ const result = data[0];
1189
+ const headerCount = Object.create(null);
1190
+ const usedHeaders = new Set(result);
1191
+ let duplicateHeaders = false;
1192
+ for (let i3 = 0;i3 < result.length; i3++) {
1193
+ let header = result[i3];
1194
+ if (isFunction(config2.transformHeader))
1195
+ header = config2.transformHeader(header, i3);
1196
+ if (!headerCount[header]) {
1197
+ headerCount[header] = 1;
1198
+ result[i3] = header;
1199
+ } else {
1200
+ let newHeader;
1201
+ let suffixCount = headerCount[header];
1202
+ do {
1203
+ newHeader = `${header}_${suffixCount}`;
1204
+ suffixCount++;
1205
+ } while (usedHeaders.has(newHeader));
1206
+ usedHeaders.add(newHeader);
1207
+ result[i3] = newHeader;
1208
+ headerCount[header]++;
1209
+ duplicateHeaders = true;
1210
+ if (renamedHeaders === null) {
1211
+ renamedHeaders = {};
1212
+ }
1213
+ renamedHeaders[newHeader] = header;
1214
+ }
1215
+ usedHeaders.add(header);
1216
+ }
1217
+ if (duplicateHeaders) {
1218
+ console.warn("Duplicate headers found and renamed.");
1219
+ }
1220
+ headerParsed = true;
1221
+ }
1222
+ return {
1223
+ data,
1224
+ errors: errors3,
1225
+ meta: {
1226
+ delimiter: delim,
1227
+ linebreak: newline,
1228
+ aborted: aborted2,
1229
+ truncated: !!stopped,
1230
+ cursor: lastCursor + (baseIndex || 0),
1231
+ renamedHeaders
1232
+ }
1233
+ };
1234
+ }
1235
+ function doStep() {
1236
+ step(returnable());
1237
+ data = [];
1238
+ errors3 = [];
1239
+ }
1240
+ };
1241
+ this.abort = function() {
1242
+ aborted2 = true;
1243
+ };
1244
+ this.getCharIndex = function() {
1245
+ return cursor;
1246
+ };
1247
+ }
1248
+ function newWorker() {
1249
+ if (!Papa.WORKERS_SUPPORTED)
1250
+ return false;
1251
+ var workerUrl = getWorkerBlob();
1252
+ var w = new global.Worker(workerUrl);
1253
+ w.onmessage = mainThreadReceivedMessage;
1254
+ w.id = workerIdCounter++;
1255
+ workers[w.id] = w;
1256
+ return w;
1257
+ }
1258
+ function mainThreadReceivedMessage(e) {
1259
+ var msg = e.data;
1260
+ var worker = workers[msg.workerId];
1261
+ var aborted2 = false;
1262
+ if (msg.error)
1263
+ worker.userError(msg.error, msg.file);
1264
+ else if (msg.results && msg.results.data) {
1265
+ var abort = function() {
1266
+ aborted2 = true;
1267
+ completeWorker(msg.workerId, { data: [], errors: [], meta: { aborted: true } });
1268
+ };
1269
+ var handle = {
1270
+ abort,
1271
+ pause: notImplemented,
1272
+ resume: notImplemented
1273
+ };
1274
+ if (isFunction(worker.userStep)) {
1275
+ for (var i2 = 0;i2 < msg.results.data.length; i2++) {
1276
+ worker.userStep({
1277
+ data: msg.results.data[i2],
1278
+ errors: msg.results.errors,
1279
+ meta: msg.results.meta
1280
+ }, handle);
1281
+ if (aborted2)
1282
+ break;
1283
+ }
1284
+ delete msg.results;
1285
+ } else if (isFunction(worker.userChunk)) {
1286
+ worker.userChunk(msg.results, handle, msg.file);
1287
+ delete msg.results;
1288
+ }
1289
+ }
1290
+ if (msg.finished && !aborted2)
1291
+ completeWorker(msg.workerId, msg.results);
1292
+ }
1293
+ function completeWorker(workerId, results) {
1294
+ var worker = workers[workerId];
1295
+ if (isFunction(worker.userComplete))
1296
+ worker.userComplete(results);
1297
+ worker.terminate();
1298
+ delete workers[workerId];
1299
+ }
1300
+ function notImplemented() {
1301
+ throw new Error("Not implemented.");
1302
+ }
1303
+ function workerThreadReceivedMessage(e) {
1304
+ var msg = e.data;
1305
+ if (typeof Papa.WORKER_ID === "undefined" && msg)
1306
+ Papa.WORKER_ID = msg.workerId;
1307
+ if (typeof msg.input === "string") {
1308
+ global.postMessage({
1309
+ workerId: Papa.WORKER_ID,
1310
+ results: Papa.parse(msg.input, msg.config),
1311
+ finished: true
1312
+ });
1313
+ } else if (global.File && msg.input instanceof File || msg.input instanceof Object) {
1314
+ var results = Papa.parse(msg.input, msg.config);
1315
+ if (results)
1316
+ global.postMessage({
1317
+ workerId: Papa.WORKER_ID,
1318
+ results,
1319
+ finished: true
1320
+ });
1321
+ }
1322
+ }
1323
+ function copy(obj) {
1324
+ if (typeof obj !== "object" || obj === null)
1325
+ return obj;
1326
+ var cpy = Array.isArray(obj) ? [] : {};
1327
+ for (var key in obj)
1328
+ cpy[key] = copy(obj[key]);
1329
+ return cpy;
1330
+ }
1331
+ function bindFunction(f, self2) {
1332
+ return function() {
1333
+ f.apply(self2, arguments);
1334
+ };
1335
+ }
1336
+ function isFunction(func) {
1337
+ return typeof func === "function";
1338
+ }
1339
+ return Papa;
1340
+ });
1341
+ });
12
1342
 
13
1343
  // src/index.ts
14
- import { dirname, join as join3 } from "path";
1344
+ import { dirname, join as join5 } from "path";
15
1345
  import { fileURLToPath } from "url";
16
1346
 
17
1347
  // src/utils/agentLoader.ts
@@ -15246,14 +16576,322 @@ var update_prices_default = tool({
15246
16576
  return updatePricesCore(directory, agent, backfill || false);
15247
16577
  }
15248
16578
  });
16579
+ // src/tools/classify-statements.ts
16580
+ import * as path4 from "path";
16581
+ import * as fs4 from "fs";
16582
+
16583
+ // src/utils/importConfig.ts
16584
+ import * as fs3 from "fs";
16585
+ import * as path3 from "path";
16586
+ var CONFIG_FILE2 = "config/import/providers.yaml";
16587
+ var REQUIRED_PATH_FIELDS = ["imports", "pending", "done", "unrecognized"];
16588
+ var REQUIRED_DETECTION_FIELDS = [
16589
+ "filenamePattern",
16590
+ "header",
16591
+ "currencyField"
16592
+ ];
16593
+ function validatePaths(paths) {
16594
+ if (typeof paths !== "object" || paths === null) {
16595
+ throw new Error("Invalid config: 'paths' must be an object");
16596
+ }
16597
+ const pathsObj = paths;
16598
+ for (const field of REQUIRED_PATH_FIELDS) {
16599
+ if (typeof pathsObj[field] !== "string" || pathsObj[field] === "") {
16600
+ throw new Error(`Invalid config: 'paths.${field}' is required`);
16601
+ }
16602
+ }
16603
+ return {
16604
+ imports: pathsObj.imports,
16605
+ pending: pathsObj.pending,
16606
+ done: pathsObj.done,
16607
+ unrecognized: pathsObj.unrecognized
16608
+ };
16609
+ }
16610
+ function validateDetectionRule(providerName, index, rule) {
16611
+ if (typeof rule !== "object" || rule === null) {
16612
+ throw new Error(`Invalid config: provider '${providerName}' detect[${index}] must be an object`);
16613
+ }
16614
+ const ruleObj = rule;
16615
+ for (const field of REQUIRED_DETECTION_FIELDS) {
16616
+ if (typeof ruleObj[field] !== "string" || ruleObj[field] === "") {
16617
+ throw new Error(`Invalid config: provider '${providerName}' detect[${index}].${field} is required`);
16618
+ }
16619
+ }
16620
+ try {
16621
+ new RegExp(ruleObj.filenamePattern);
16622
+ } catch {
16623
+ throw new Error(`Invalid config: provider '${providerName}' detect[${index}].filenamePattern is not a valid regex`);
16624
+ }
16625
+ return {
16626
+ filenamePattern: ruleObj.filenamePattern,
16627
+ header: ruleObj.header,
16628
+ currencyField: ruleObj.currencyField
16629
+ };
16630
+ }
16631
+ function validateProviderConfig(name, config2) {
16632
+ if (typeof config2 !== "object" || config2 === null) {
16633
+ throw new Error(`Invalid config for provider '${name}': expected an object`);
16634
+ }
16635
+ const configObj = config2;
16636
+ if (!Array.isArray(configObj.detect) || configObj.detect.length === 0) {
16637
+ throw new Error(`Invalid config for provider '${name}': 'detect' must be a non-empty array`);
16638
+ }
16639
+ const detect = [];
16640
+ for (let i2 = 0;i2 < configObj.detect.length; i2++) {
16641
+ detect.push(validateDetectionRule(name, i2, configObj.detect[i2]));
16642
+ }
16643
+ if (typeof configObj.currencies !== "object" || configObj.currencies === null) {
16644
+ throw new Error(`Invalid config for provider '${name}': 'currencies' must be an object`);
16645
+ }
16646
+ const currenciesObj = configObj.currencies;
16647
+ const currencies = {};
16648
+ for (const [key, value] of Object.entries(currenciesObj)) {
16649
+ if (typeof value !== "string") {
16650
+ throw new Error(`Invalid config for provider '${name}': currencies.${key} must be a string`);
16651
+ }
16652
+ currencies[key] = value;
16653
+ }
16654
+ if (Object.keys(currencies).length === 0) {
16655
+ throw new Error(`Invalid config for provider '${name}': 'currencies' must contain at least one mapping`);
16656
+ }
16657
+ return { detect, currencies };
16658
+ }
16659
+ function loadImportConfig(directory) {
16660
+ const configPath = path3.join(directory, CONFIG_FILE2);
16661
+ if (!fs3.existsSync(configPath)) {
16662
+ throw new Error(`Configuration file not found: ${CONFIG_FILE2}. Please create this file to configure statement imports.`);
16663
+ }
16664
+ let parsed;
16665
+ try {
16666
+ const content = fs3.readFileSync(configPath, "utf-8");
16667
+ parsed = jsYaml.load(content);
16668
+ } catch (err) {
16669
+ if (err instanceof jsYaml.YAMLException) {
16670
+ throw new Error(`Failed to parse ${CONFIG_FILE2}: ${err.message}`);
16671
+ }
16672
+ throw err;
16673
+ }
16674
+ if (typeof parsed !== "object" || parsed === null) {
16675
+ throw new Error(`Invalid config: ${CONFIG_FILE2} must contain a YAML object`);
16676
+ }
16677
+ const parsedObj = parsed;
16678
+ if (!parsedObj.paths) {
16679
+ throw new Error("Invalid config: 'paths' section is required");
16680
+ }
16681
+ const paths = validatePaths(parsedObj.paths);
16682
+ if (!parsedObj.providers || typeof parsedObj.providers !== "object") {
16683
+ throw new Error("Invalid config: 'providers' section is required");
16684
+ }
16685
+ const providersObj = parsedObj.providers;
16686
+ if (Object.keys(providersObj).length === 0) {
16687
+ throw new Error("Invalid config: 'providers' section must contain at least one provider");
16688
+ }
16689
+ const providers = {};
16690
+ for (const [name, config2] of Object.entries(providersObj)) {
16691
+ providers[name] = validateProviderConfig(name, config2);
16692
+ }
16693
+ return { paths, providers };
16694
+ }
16695
+
16696
+ // src/utils/providerDetector.ts
16697
+ var import_papaparse = __toESM(require_papaparse(), 1);
16698
+ function parseCSVPreview(content) {
16699
+ const result = import_papaparse.default.parse(content, {
16700
+ header: true,
16701
+ preview: 1,
16702
+ skipEmptyLines: true
16703
+ });
16704
+ return {
16705
+ fields: result.meta.fields,
16706
+ firstRow: result.data[0]
16707
+ };
16708
+ }
16709
+ function normalizeHeader(fields) {
16710
+ return fields.map((f) => f.trim()).join(",");
16711
+ }
16712
+ function detectProvider(filename, content, config2) {
16713
+ const { fields, firstRow } = parseCSVPreview(content);
16714
+ if (!fields || fields.length === 0) {
16715
+ return null;
16716
+ }
16717
+ const actualHeader = normalizeHeader(fields);
16718
+ for (const [providerName, providerConfig] of Object.entries(config2.providers)) {
16719
+ for (const rule of providerConfig.detect) {
16720
+ const filenameRegex = new RegExp(rule.filenamePattern);
16721
+ if (!filenameRegex.test(filename)) {
16722
+ continue;
16723
+ }
16724
+ if (actualHeader !== rule.header) {
16725
+ continue;
16726
+ }
16727
+ if (!firstRow) {
16728
+ continue;
16729
+ }
16730
+ const rawCurrency = firstRow[rule.currencyField];
16731
+ if (!rawCurrency) {
16732
+ continue;
16733
+ }
16734
+ const normalizedCurrency = providerConfig.currencies[rawCurrency];
16735
+ if (!normalizedCurrency) {
16736
+ return {
16737
+ provider: providerName,
16738
+ currency: rawCurrency.toLowerCase(),
16739
+ rule
16740
+ };
16741
+ }
16742
+ return {
16743
+ provider: providerName,
16744
+ currency: normalizedCurrency,
16745
+ rule
16746
+ };
16747
+ }
16748
+ }
16749
+ return null;
16750
+ }
16751
+
16752
+ // src/tools/classify-statements.ts
16753
+ function findCSVFiles(importsDir) {
16754
+ if (!fs4.existsSync(importsDir)) {
16755
+ return [];
16756
+ }
16757
+ return fs4.readdirSync(importsDir).filter((file2) => file2.toLowerCase().endsWith(".csv")).filter((file2) => {
16758
+ const fullPath = path4.join(importsDir, file2);
16759
+ return fs4.statSync(fullPath).isFile();
16760
+ });
16761
+ }
16762
+ function checkPendingFiles(directory, pendingBasePath) {
16763
+ const pendingDir = path4.join(directory, pendingBasePath);
16764
+ const pendingFiles = [];
16765
+ if (!fs4.existsSync(pendingDir)) {
16766
+ return [];
16767
+ }
16768
+ const providers = fs4.readdirSync(pendingDir);
16769
+ for (const provider of providers) {
16770
+ const providerPath = path4.join(pendingDir, provider);
16771
+ if (!fs4.statSync(providerPath).isDirectory())
16772
+ continue;
16773
+ const currencies = fs4.readdirSync(providerPath);
16774
+ for (const currency of currencies) {
16775
+ const currencyPath = path4.join(providerPath, currency);
16776
+ if (!fs4.statSync(currencyPath).isDirectory())
16777
+ continue;
16778
+ const files = fs4.readdirSync(currencyPath).filter((f) => f.toLowerCase().endsWith(".csv"));
16779
+ for (const file2 of files) {
16780
+ pendingFiles.push({
16781
+ provider,
16782
+ currency,
16783
+ filename: file2,
16784
+ path: path4.join(currencyPath, file2)
16785
+ });
16786
+ }
16787
+ }
16788
+ }
16789
+ return pendingFiles;
16790
+ }
16791
+ function ensureDirectory(dirPath) {
16792
+ if (!fs4.existsSync(dirPath)) {
16793
+ fs4.mkdirSync(dirPath, { recursive: true });
16794
+ }
16795
+ }
16796
+ async function classifyStatementsCore(directory, agent, configLoader = loadImportConfig) {
16797
+ if (agent !== "accountant") {
16798
+ return JSON.stringify({
16799
+ success: false,
16800
+ error: "This tool is restricted to the accountant agent only.",
16801
+ hint: "Use: Task(subagent_type='accountant', prompt='classify statements')",
16802
+ caller: agent || "main assistant",
16803
+ classified: [],
16804
+ unrecognized: []
16805
+ });
16806
+ }
16807
+ let config2;
16808
+ try {
16809
+ config2 = configLoader(directory);
16810
+ } catch (err) {
16811
+ return JSON.stringify({
16812
+ success: false,
16813
+ error: err instanceof Error ? err.message : String(err),
16814
+ classified: [],
16815
+ unrecognized: []
16816
+ });
16817
+ }
16818
+ const importsDir = path4.join(directory, config2.paths.imports);
16819
+ const pendingDir = path4.join(directory, config2.paths.pending);
16820
+ const unrecognizedDir = path4.join(directory, config2.paths.unrecognized);
16821
+ const pendingFiles = checkPendingFiles(directory, config2.paths.pending);
16822
+ if (pendingFiles.length > 0) {
16823
+ return JSON.stringify({
16824
+ success: false,
16825
+ error: `Found ${pendingFiles.length} pending file(s) that must be processed before classifying new statements.`,
16826
+ pendingFiles,
16827
+ classified: [],
16828
+ unrecognized: []
16829
+ });
16830
+ }
16831
+ const csvFiles = findCSVFiles(importsDir);
16832
+ if (csvFiles.length === 0) {
16833
+ return JSON.stringify({
16834
+ success: true,
16835
+ classified: [],
16836
+ unrecognized: [],
16837
+ message: `No CSV files found in ${config2.paths.imports}`
16838
+ });
16839
+ }
16840
+ const classified = [];
16841
+ const unrecognized = [];
16842
+ for (const filename of csvFiles) {
16843
+ const sourcePath = path4.join(importsDir, filename);
16844
+ const content = fs4.readFileSync(sourcePath, "utf-8");
16845
+ const detection = detectProvider(filename, content, config2);
16846
+ if (detection) {
16847
+ const targetDir = path4.join(pendingDir, detection.provider, detection.currency);
16848
+ ensureDirectory(targetDir);
16849
+ const targetPath = path4.join(targetDir, filename);
16850
+ fs4.renameSync(sourcePath, targetPath);
16851
+ classified.push({
16852
+ filename,
16853
+ provider: detection.provider,
16854
+ currency: detection.currency,
16855
+ targetPath: path4.join(config2.paths.pending, detection.provider, detection.currency, filename)
16856
+ });
16857
+ } else {
16858
+ ensureDirectory(unrecognizedDir);
16859
+ const targetPath = path4.join(unrecognizedDir, filename);
16860
+ fs4.renameSync(sourcePath, targetPath);
16861
+ unrecognized.push({
16862
+ filename,
16863
+ targetPath: path4.join(config2.paths.unrecognized, filename)
16864
+ });
16865
+ }
16866
+ }
16867
+ return JSON.stringify({
16868
+ success: true,
16869
+ classified,
16870
+ unrecognized,
16871
+ summary: {
16872
+ total: csvFiles.length,
16873
+ classified: classified.length,
16874
+ unrecognized: unrecognized.length
16875
+ }
16876
+ });
16877
+ }
16878
+ var classify_statements_default = tool({
16879
+ description: "ACCOUNTANT AGENT ONLY: Classifies bank statement CSV files from the imports directory by detecting their provider and currency, then moves them to the appropriate pending import directories.",
16880
+ args: {},
16881
+ async execute(_params, context) {
16882
+ const { directory, agent } = context;
16883
+ return classifyStatementsCore(directory, agent);
16884
+ }
16885
+ });
15249
16886
  // src/index.ts
15250
16887
  var __dirname2 = dirname(fileURLToPath(import.meta.url));
15251
- var AGENT_FILE = join3(__dirname2, "..", "agent", "accountant.md");
16888
+ var AGENT_FILE = join5(__dirname2, "..", "agent", "accountant.md");
15252
16889
  var AccountantPlugin = async () => {
15253
16890
  const agent = loadAgent(AGENT_FILE);
15254
16891
  return {
15255
16892
  tool: {
15256
- "update-prices": update_prices_default
16893
+ "update-prices": update_prices_default,
16894
+ "classify-statements": classify_statements_default
15257
16895
  },
15258
16896
  config: async (config2) => {
15259
16897
  if (agent) {