tuimon 0.1.0 → 0.2.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/AI.md +191 -0
- package/README.md +223 -87
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -0
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +171 -3
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +106 -0
- package/dist/config.js.map +1 -0
- package/dist/fkeybar.d.ts.map +1 -1
- package/dist/fkeybar.js +13 -0
- package/dist/fkeybar.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +148 -18
- package/dist/index.js.map +1 -1
- package/dist/layout/generator-css.d.ts +3 -0
- package/dist/layout/generator-css.d.ts.map +1 -0
- package/dist/layout/generator-css.js +202 -0
- package/dist/layout/generator-css.js.map +1 -0
- package/dist/layout/generator-js.d.ts +3 -0
- package/dist/layout/generator-js.d.ts.map +1 -0
- package/dist/layout/generator-js.js +353 -0
- package/dist/layout/generator-js.js.map +1 -0
- package/dist/layout/generator.d.ts +4 -0
- package/dist/layout/generator.d.ts.map +1 -0
- package/dist/layout/generator.js +124 -0
- package/dist/layout/generator.js.map +1 -0
- package/dist/layout/theme.d.ts +4 -0
- package/dist/layout/theme.d.ts.map +1 -0
- package/dist/layout/theme.js +28 -0
- package/dist/layout/theme.js.map +1 -0
- package/dist/layout/types.d.ts +68 -0
- package/dist/layout/types.d.ts.map +1 -0
- package/dist/layout/types.js +3 -0
- package/dist/layout/types.js.map +1 -0
- package/dist/quick/auto-layout.d.ts +5 -0
- package/dist/quick/auto-layout.d.ts.map +1 -0
- package/dist/quick/auto-layout.js +262 -0
- package/dist/quick/auto-layout.js.map +1 -0
- package/dist/quick/db/detect.d.ts +16 -0
- package/dist/quick/db/detect.d.ts.map +1 -0
- package/dist/quick/db/detect.js +131 -0
- package/dist/quick/db/detect.js.map +1 -0
- package/dist/quick/db/mongo.d.ts +10 -0
- package/dist/quick/db/mongo.d.ts.map +1 -0
- package/dist/quick/db/mongo.js +81 -0
- package/dist/quick/db/mongo.js.map +1 -0
- package/dist/quick/db/mysql.d.ts +8 -0
- package/dist/quick/db/mysql.d.ts.map +1 -0
- package/dist/quick/db/mysql.js +43 -0
- package/dist/quick/db/mysql.js.map +1 -0
- package/dist/quick/db/postgres.d.ts +8 -0
- package/dist/quick/db/postgres.d.ts.map +1 -0
- package/dist/quick/db/postgres.js +47 -0
- package/dist/quick/db/postgres.js.map +1 -0
- package/dist/quick/db/sqlite.d.ts +8 -0
- package/dist/quick/db/sqlite.d.ts.map +1 -0
- package/dist/quick/db/sqlite.js +43 -0
- package/dist/quick/db/sqlite.js.map +1 -0
- package/dist/quick/db-mode.d.ts +13 -0
- package/dist/quick/db-mode.d.ts.map +1 -0
- package/dist/quick/db-mode.js +159 -0
- package/dist/quick/db-mode.js.map +1 -0
- package/dist/quick/detect.d.ts +4 -0
- package/dist/quick/detect.d.ts.map +1 -0
- package/dist/quick/detect.js +76 -0
- package/dist/quick/detect.js.map +1 -0
- package/dist/quick/file-mode.d.ts +5 -0
- package/dist/quick/file-mode.d.ts.map +1 -0
- package/dist/quick/file-mode.js +158 -0
- package/dist/quick/file-mode.js.map +1 -0
- package/dist/quick/parsers/csv.d.ts +3 -0
- package/dist/quick/parsers/csv.d.ts.map +1 -0
- package/dist/quick/parsers/csv.js +145 -0
- package/dist/quick/parsers/csv.js.map +1 -0
- package/dist/quick/parsers/detect-meta.d.ts +7 -0
- package/dist/quick/parsers/detect-meta.d.ts.map +1 -0
- package/dist/quick/parsers/detect-meta.js +35 -0
- package/dist/quick/parsers/detect-meta.js.map +1 -0
- package/dist/quick/parsers/json.d.ts +3 -0
- package/dist/quick/parsers/json.d.ts.map +1 -0
- package/dist/quick/parsers/json.js +74 -0
- package/dist/quick/parsers/json.js.map +1 -0
- package/dist/quick/parsers/log.d.ts +3 -0
- package/dist/quick/parsers/log.d.ts.map +1 -0
- package/dist/quick/parsers/log.js +185 -0
- package/dist/quick/parsers/log.js.map +1 -0
- package/dist/quick/parsers/modsec.d.ts +3 -0
- package/dist/quick/parsers/modsec.d.ts.map +1 -0
- package/dist/quick/parsers/modsec.js +338 -0
- package/dist/quick/parsers/modsec.js.map +1 -0
- package/dist/quick/types.d.ts +90 -0
- package/dist/quick/types.d.ts.map +1 -0
- package/dist/quick/types.js +3 -0
- package/dist/quick/types.js.map +1 -0
- package/dist/quick/watch-mode.d.ts +3 -0
- package/dist/quick/watch-mode.d.ts.map +1 -0
- package/dist/quick/watch-mode.js +156 -0
- package/dist/quick/watch-mode.js.map +1 -0
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/examples/demo.ts +134 -0
- package/examples/generate-access-log.ts +42 -0
- package/examples/screenshot-test.ts +105 -0
- package/examples/screenshot.png +0 -0
- package/frame-log.txt +830 -0
- package/package.json +10 -5
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { detectMeta } from './detect-meta.js';
|
|
3
|
+
const MAX_ROWS = 1000;
|
|
4
|
+
const DELIMITERS = [',', '\t', ';', '|'];
|
|
5
|
+
export function parseCsvFile(filePath) {
|
|
6
|
+
const content = readFileSync(filePath, 'utf-8').trim();
|
|
7
|
+
if (!content) {
|
|
8
|
+
throw new Error(`File is empty: ${filePath}`);
|
|
9
|
+
}
|
|
10
|
+
const lines = content.split(/\r?\n/);
|
|
11
|
+
if (lines.length < 2) {
|
|
12
|
+
throw new Error(`File must have at least a header row and one data row: ${filePath}`);
|
|
13
|
+
}
|
|
14
|
+
const delimiter = detectDelimiter(lines.slice(0, Math.min(5, lines.length)));
|
|
15
|
+
const headerLine = lines[0] ?? '';
|
|
16
|
+
const columns = parseRow(headerLine, delimiter);
|
|
17
|
+
if (columns.length === 0) {
|
|
18
|
+
throw new Error(`No columns found in header row: ${filePath}`);
|
|
19
|
+
}
|
|
20
|
+
const totalRows = lines.length - 1;
|
|
21
|
+
const rowLimit = Math.min(totalRows, MAX_ROWS);
|
|
22
|
+
if (totalRows > MAX_ROWS) {
|
|
23
|
+
console.warn(`Warning: File ${filePath} contains ${totalRows} rows, truncating to ${MAX_ROWS}`);
|
|
24
|
+
}
|
|
25
|
+
const rows = [];
|
|
26
|
+
for (let i = 1; i <= rowLimit; i++) {
|
|
27
|
+
const line = lines[i];
|
|
28
|
+
if (!line || line.trim() === '')
|
|
29
|
+
continue;
|
|
30
|
+
const values = parseRow(line, delimiter);
|
|
31
|
+
const row = {};
|
|
32
|
+
for (let c = 0; c < columns.length; c++) {
|
|
33
|
+
const raw = values[c] ?? '';
|
|
34
|
+
const colName = columns[c];
|
|
35
|
+
if (colName !== undefined) {
|
|
36
|
+
row[colName] = convertValue(raw);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
rows.push(row);
|
|
40
|
+
}
|
|
41
|
+
const meta = detectMeta(columns, rows);
|
|
42
|
+
return {
|
|
43
|
+
type: 'table',
|
|
44
|
+
columns,
|
|
45
|
+
rows,
|
|
46
|
+
meta: {
|
|
47
|
+
totalRows,
|
|
48
|
+
...meta,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function detectDelimiter(sampleLines) {
|
|
53
|
+
let bestDelimiter = ',';
|
|
54
|
+
let bestScore = -1;
|
|
55
|
+
for (const delim of DELIMITERS) {
|
|
56
|
+
const counts = sampleLines.map((line) => countUnquoted(line, delim));
|
|
57
|
+
// All lines should have the same count and at least 1
|
|
58
|
+
const firstCount = counts[0] ?? 0;
|
|
59
|
+
if (firstCount === 0)
|
|
60
|
+
continue;
|
|
61
|
+
const allSame = counts.every((c) => c === firstCount);
|
|
62
|
+
const score = allSame ? firstCount * sampleLines.length : 0;
|
|
63
|
+
if (score > bestScore) {
|
|
64
|
+
bestScore = score;
|
|
65
|
+
bestDelimiter = delim;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return bestDelimiter;
|
|
69
|
+
}
|
|
70
|
+
/** Count occurrences of a delimiter outside of quoted fields */
|
|
71
|
+
function countUnquoted(line, delim) {
|
|
72
|
+
let count = 0;
|
|
73
|
+
let inQuotes = false;
|
|
74
|
+
for (let i = 0; i < line.length; i++) {
|
|
75
|
+
if (line[i] === '"') {
|
|
76
|
+
inQuotes = !inQuotes;
|
|
77
|
+
}
|
|
78
|
+
else if (line[i] === delim && !inQuotes) {
|
|
79
|
+
count++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return count;
|
|
83
|
+
}
|
|
84
|
+
/** Parse a single row respecting quoted fields */
|
|
85
|
+
function parseRow(line, delimiter) {
|
|
86
|
+
const fields = [];
|
|
87
|
+
let current = '';
|
|
88
|
+
let inQuotes = false;
|
|
89
|
+
for (let i = 0; i < line.length; i++) {
|
|
90
|
+
const ch = line[i];
|
|
91
|
+
if (inQuotes) {
|
|
92
|
+
if (ch === '"') {
|
|
93
|
+
// Check for escaped quote ("")
|
|
94
|
+
if (i + 1 < line.length && line[i + 1] === '"') {
|
|
95
|
+
current += '"';
|
|
96
|
+
i++; // skip next quote
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
inQuotes = false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
current += ch;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
if (ch === '"') {
|
|
108
|
+
inQuotes = true;
|
|
109
|
+
}
|
|
110
|
+
else if (ch === delimiter) {
|
|
111
|
+
fields.push(current);
|
|
112
|
+
current = '';
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
current += ch;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
fields.push(current);
|
|
120
|
+
return fields;
|
|
121
|
+
}
|
|
122
|
+
function convertValue(raw) {
|
|
123
|
+
const trimmed = raw.trim();
|
|
124
|
+
if (trimmed === '')
|
|
125
|
+
return '';
|
|
126
|
+
// Boolean conversion
|
|
127
|
+
const lower = trimmed.toLowerCase();
|
|
128
|
+
if (lower === 'true' || lower === 'yes')
|
|
129
|
+
return true;
|
|
130
|
+
if (lower === 'false' || lower === 'no')
|
|
131
|
+
return false;
|
|
132
|
+
if (trimmed === '1' && raw.length === 1) {
|
|
133
|
+
// Ambiguous: could be numeric 1. Prefer number.
|
|
134
|
+
}
|
|
135
|
+
if (trimmed === '0' && raw.length === 1) {
|
|
136
|
+
// Same ambiguity. Prefer number.
|
|
137
|
+
}
|
|
138
|
+
// Numeric conversion
|
|
139
|
+
if (trimmed !== '' && !isNaN(Number(trimmed))) {
|
|
140
|
+
return Number(trimmed);
|
|
141
|
+
}
|
|
142
|
+
return trimmed;
|
|
143
|
+
}
|
|
144
|
+
// detectMeta is imported from ./detect-meta.js
|
|
145
|
+
//# sourceMappingURL=csv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv.js","sourceRoot":"","sources":["../../../src/quick/parsers/csv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,MAAM,QAAQ,GAAG,IAAI,CAAA;AAErB,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAU,CAAA;AAGjD,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;IAEtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,kBAAkB,QAAQ,EAAE,CAAC,CAAA;IAC/C,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAEpC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,0DAA0D,QAAQ,EAAE,CAAC,CAAA;IACvF,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAC5E,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAE/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAA;IAChE,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAE9C,IAAI,SAAS,GAAG,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CACV,iBAAiB,QAAQ,aAAa,SAAS,wBAAwB,QAAQ,EAAE,CAClF,CAAA;IACH,CAAC;IAED,MAAM,IAAI,GAA8B,EAAE,CAAA;IAE1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QACrB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,SAAQ;QAEzC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QACxC,MAAM,GAAG,GAA4B,EAAE,CAAA;QAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;YAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YAC1B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,GAAG,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;YAClC,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAChB,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAEtC,OAAO;QACL,IAAI,EAAE,OAAO;QACb,OAAO;QACP,IAAI;QACJ,IAAI,EAAE;YACJ,SAAS;YACT,GAAG,IAAI;SACR;KACF,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,WAAqB;IAC5C,IAAI,aAAa,GAAc,GAAG,CAAA;IAClC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAA;IAElB,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;QAEpE,sDAAsD;QACtD,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,UAAU,KAAK,CAAC;YAAE,SAAQ;QAE9B,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC,CAAA;QACrD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QAE3D,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;YACtB,SAAS,GAAG,KAAK,CAAA;YACjB,aAAa,GAAG,KAAK,CAAA;QACvB,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAA;AACtB,CAAC;AAED,gEAAgE;AAChE,SAAS,aAAa,CAAC,IAAY,EAAE,KAAa;IAChD,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,QAAQ,GAAG,KAAK,CAAA;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACpB,QAAQ,GAAG,CAAC,QAAQ,CAAA;QACtB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,KAAK,EAAE,CAAA;QACT,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,kDAAkD;AAClD,SAAS,QAAQ,CAAC,IAAY,EAAE,SAAoB;IAClD,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAA;IAChB,IAAI,QAAQ,GAAG,KAAK,CAAA;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QAElB,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBACf,+BAA+B;gBAC/B,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;oBAC/C,OAAO,IAAI,GAAG,CAAA;oBACd,CAAC,EAAE,CAAA,CAAC,kBAAkB;gBACxB,CAAC;qBAAM,CAAC;oBACN,QAAQ,GAAG,KAAK,CAAA;gBAClB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,EAAE,CAAA;YACf,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBACf,QAAQ,GAAG,IAAI,CAAA;YACjB,CAAC;iBAAM,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACpB,OAAO,GAAG,EAAE,CAAA;YACd,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,EAAE,CAAA;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACpB,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAE1B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,EAAE,CAAA;IAE7B,qBAAqB;IACrB,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IACnC,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,IAAI,CAAA;IACpD,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IACrD,IAAI,OAAO,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,gDAAgD;IAClD,CAAC;IACD,IAAI,OAAO,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,iCAAiC;IACnC,CAAC;IAED,qBAAqB;IACrB,IAAI,OAAO,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC9C,OAAO,MAAM,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,+CAA+C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-meta.d.ts","sourceRoot":"","sources":["../../../src/quick/parsers/detect-meta.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,kBAAkB,EAAE,MAAM,EAAE,CAAA;CAC7B;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,UAAU,CAsCzF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function detectMeta(columns, rows) {
|
|
2
|
+
const numericColumns = [];
|
|
3
|
+
const booleanColumns = [];
|
|
4
|
+
const categoricalColumns = [];
|
|
5
|
+
for (const col of columns) {
|
|
6
|
+
const values = rows.map((r) => r[col]).filter((v) => v !== null && v !== undefined && v !== '');
|
|
7
|
+
if (values.length === 0)
|
|
8
|
+
continue;
|
|
9
|
+
const allNumeric = values.every((v) => {
|
|
10
|
+
if (typeof v === 'number')
|
|
11
|
+
return true;
|
|
12
|
+
if (typeof v === 'string')
|
|
13
|
+
return v.trim() !== '' && !isNaN(Number(v));
|
|
14
|
+
return false;
|
|
15
|
+
});
|
|
16
|
+
if (allNumeric) {
|
|
17
|
+
numericColumns.push(col);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const allBoolean = values.every((v) => typeof v === 'boolean' || v === 'true' || v === 'false');
|
|
21
|
+
if (allBoolean) {
|
|
22
|
+
booleanColumns.push(col);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const stringValues = values.filter((v) => typeof v === 'string');
|
|
26
|
+
if (stringValues.length === values.length) {
|
|
27
|
+
const unique = new Set(stringValues);
|
|
28
|
+
if (unique.size < 10) {
|
|
29
|
+
categoricalColumns.push(col);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { numericColumns, booleanColumns, categoricalColumns };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=detect-meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-meta.js","sourceRoot":"","sources":["../../../src/quick/parsers/detect-meta.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,UAAU,CAAC,OAAiB,EAAE,IAA+B;IAC3E,MAAM,cAAc,GAAa,EAAE,CAAA;IACnC,MAAM,cAAc,GAAa,EAAE,CAAA;IACnC,MAAM,kBAAkB,GAAa,EAAE,CAAA;IAEvC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QAE/F,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QAEjC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAA;YACtC,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;YACtE,OAAO,KAAK,CAAA;QACd,CAAC,CAAC,CAAA;QACF,IAAI,UAAU,EAAE,CAAC;YACf,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACxB,SAAQ;QACV,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,OAAO,CAC/D,CAAA;QACD,IAAI,UAAU,EAAE,CAAC;YACf,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACxB,SAAQ;QACV,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAa,CAAA;QAC5E,IAAI,YAAY,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAA;YACpC,IAAI,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC;gBACrB,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAA;AAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../../src/quick/parsers/json.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAK5C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CA6EzD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { detectMeta } from './detect-meta.js';
|
|
3
|
+
const MAX_ROWS = 1000;
|
|
4
|
+
export function parseJsonFile(filePath) {
|
|
5
|
+
const content = readFileSync(filePath, 'utf-8').trim();
|
|
6
|
+
if (!content) {
|
|
7
|
+
throw new Error(`File is empty: ${filePath}`);
|
|
8
|
+
}
|
|
9
|
+
let rows;
|
|
10
|
+
// Try standard JSON first (array or object)
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(content);
|
|
13
|
+
if (Array.isArray(parsed)) {
|
|
14
|
+
if (parsed.length === 0) {
|
|
15
|
+
throw new Error(`JSON array is empty: ${filePath}`);
|
|
16
|
+
}
|
|
17
|
+
if (typeof parsed[0] !== 'object' || parsed[0] === null) {
|
|
18
|
+
throw new Error(`JSON array must contain objects, got ${typeof parsed[0]}`);
|
|
19
|
+
}
|
|
20
|
+
rows = parsed;
|
|
21
|
+
}
|
|
22
|
+
else if (typeof parsed === 'object' && parsed !== null) {
|
|
23
|
+
rows = [parsed];
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
throw new Error(`Expected JSON object or array of objects, got ${typeof parsed}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (jsonError) {
|
|
30
|
+
// Try JSONL: one JSON object per line
|
|
31
|
+
const lines = content.split('\n').filter((line) => line.trim() !== '');
|
|
32
|
+
const parsed = [];
|
|
33
|
+
for (let i = 0; i < lines.length; i++) {
|
|
34
|
+
try {
|
|
35
|
+
const obj = JSON.parse(lines[i] ?? '');
|
|
36
|
+
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
|
|
37
|
+
throw new Error(`JSONL line ${i + 1} is not an object`);
|
|
38
|
+
}
|
|
39
|
+
parsed.push(obj);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
throw new Error(`Failed to parse file as JSON or JSONL: ${filePath}. ` +
|
|
43
|
+
`JSON error: ${jsonError instanceof Error ? jsonError.message : String(jsonError)}. ` +
|
|
44
|
+
`JSONL failed at line ${i + 1}.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (parsed.length === 0) {
|
|
48
|
+
throw new Error(`No valid JSONL entries found in: ${filePath}`);
|
|
49
|
+
}
|
|
50
|
+
rows = parsed;
|
|
51
|
+
}
|
|
52
|
+
// Cap rows for memory safety
|
|
53
|
+
const totalRows = rows.length;
|
|
54
|
+
if (rows.length > MAX_ROWS) {
|
|
55
|
+
console.warn(`Warning: File ${filePath} contains ${rows.length} rows, truncating to ${MAX_ROWS}`);
|
|
56
|
+
rows = rows.slice(0, MAX_ROWS);
|
|
57
|
+
}
|
|
58
|
+
const firstRow = rows[0];
|
|
59
|
+
if (!firstRow)
|
|
60
|
+
throw new Error(`No rows found in: ${filePath}`);
|
|
61
|
+
const columns = Object.keys(firstRow);
|
|
62
|
+
const meta = detectMeta(columns, rows);
|
|
63
|
+
return {
|
|
64
|
+
type: 'table',
|
|
65
|
+
columns,
|
|
66
|
+
rows,
|
|
67
|
+
meta: {
|
|
68
|
+
totalRows,
|
|
69
|
+
...meta,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// detectMeta is imported from ./detect-meta.js
|
|
74
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/quick/parsers/json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../src/quick/parsers/log.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,aAAa,CAAA;AASpD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAyBtD"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { detectLogFormat } from '../detect.js';
|
|
3
|
+
const MAX_LINES = 10000;
|
|
4
|
+
const MAX_BYTES = 10 * 1024 * 1024; // 10MB
|
|
5
|
+
const NGINX_RE = /^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) [^"]*" (\d+) (\d+) "([^"]*)" "([^"]*)"/;
|
|
6
|
+
export function parseLogFile(filePath) {
|
|
7
|
+
let content = readFileSync(filePath, 'utf-8');
|
|
8
|
+
// Memory safety: if file is too large, keep only the tail
|
|
9
|
+
if (content.length > MAX_BYTES) {
|
|
10
|
+
const allLines = content.split('\n');
|
|
11
|
+
content = allLines.slice(-MAX_LINES).join('\n');
|
|
12
|
+
}
|
|
13
|
+
const format = detectLogFormat(content);
|
|
14
|
+
// Delegate modsec elsewhere — this parser handles nginx/json/plain
|
|
15
|
+
if (format === 'modsec') {
|
|
16
|
+
// Treat as plain if somehow routed here
|
|
17
|
+
return parsePlain(content);
|
|
18
|
+
}
|
|
19
|
+
switch (format) {
|
|
20
|
+
case 'nginx':
|
|
21
|
+
return parseNginx(content);
|
|
22
|
+
case 'json':
|
|
23
|
+
return parseJson(content);
|
|
24
|
+
default:
|
|
25
|
+
return parsePlain(content);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// ─── Nginx combined log ──────────────────────────────────────────────────────
|
|
29
|
+
function parseNginx(content) {
|
|
30
|
+
const rawLines = content.split('\n').filter((l) => l.trim());
|
|
31
|
+
const lines = rawLines.slice(-MAX_LINES);
|
|
32
|
+
const entries = [];
|
|
33
|
+
const statusCodes = {};
|
|
34
|
+
const methods = {};
|
|
35
|
+
const endpoints = {};
|
|
36
|
+
const ips = {};
|
|
37
|
+
let errorCount = 0;
|
|
38
|
+
let skipped = 0;
|
|
39
|
+
let firstTimestamp;
|
|
40
|
+
let lastTimestamp;
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
const m = NGINX_RE.exec(line);
|
|
43
|
+
if (!m) {
|
|
44
|
+
skipped++;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const ip = m[1];
|
|
48
|
+
const timestamp = m[2];
|
|
49
|
+
const method = m[3];
|
|
50
|
+
const path = m[4];
|
|
51
|
+
const status = parseInt(m[5], 10);
|
|
52
|
+
const bytes = parseInt(m[6], 10);
|
|
53
|
+
const referer = m[7];
|
|
54
|
+
const userAgent = m[8];
|
|
55
|
+
entries.push({
|
|
56
|
+
raw: line,
|
|
57
|
+
timestamp,
|
|
58
|
+
ip,
|
|
59
|
+
method,
|
|
60
|
+
path,
|
|
61
|
+
status,
|
|
62
|
+
bytes,
|
|
63
|
+
referer,
|
|
64
|
+
userAgent,
|
|
65
|
+
});
|
|
66
|
+
// Stats
|
|
67
|
+
const statusKey = String(status);
|
|
68
|
+
statusCodes[statusKey] = (statusCodes[statusKey] ?? 0) + 1;
|
|
69
|
+
methods[method] = (methods[method] ?? 0) + 1;
|
|
70
|
+
endpoints[path] = (endpoints[path] ?? 0) + 1;
|
|
71
|
+
ips[ip] = (ips[ip] ?? 0) + 1;
|
|
72
|
+
if (status >= 400)
|
|
73
|
+
errorCount++;
|
|
74
|
+
if (!firstTimestamp)
|
|
75
|
+
firstTimestamp = timestamp;
|
|
76
|
+
lastTimestamp = timestamp;
|
|
77
|
+
}
|
|
78
|
+
const stats = {
|
|
79
|
+
totalLines: entries.length + skipped,
|
|
80
|
+
statusCodes,
|
|
81
|
+
methods,
|
|
82
|
+
topEndpoints: topN(endpoints, 20),
|
|
83
|
+
topIPs: topN(ips, 20),
|
|
84
|
+
errorCount,
|
|
85
|
+
};
|
|
86
|
+
if (firstTimestamp && lastTimestamp) {
|
|
87
|
+
stats.timeRange = { start: firstTimestamp, end: lastTimestamp };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
type: 'log',
|
|
91
|
+
format: 'nginx',
|
|
92
|
+
entries,
|
|
93
|
+
stats,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// ─── JSON lines ──────────────────────────────────────────────────────────────
|
|
97
|
+
function parseJson(content) {
|
|
98
|
+
const rawLines = content.split('\n').filter((l) => l.trim());
|
|
99
|
+
const lines = rawLines.slice(-MAX_LINES);
|
|
100
|
+
const entries = [];
|
|
101
|
+
let errorCount = 0;
|
|
102
|
+
let skipped = 0;
|
|
103
|
+
let firstTimestamp;
|
|
104
|
+
let lastTimestamp;
|
|
105
|
+
for (const line of lines) {
|
|
106
|
+
let obj;
|
|
107
|
+
try {
|
|
108
|
+
obj = JSON.parse(line);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
skipped++;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const level = stringField(obj, 'level');
|
|
115
|
+
const message = stringField(obj, 'msg') ?? stringField(obj, 'message');
|
|
116
|
+
const timestamp = stringField(obj, 'timestamp') ?? stringField(obj, 'time') ?? stringField(obj, 'ts');
|
|
117
|
+
const status = numberField(obj, 'status');
|
|
118
|
+
const entry = { raw: line };
|
|
119
|
+
if (level !== undefined)
|
|
120
|
+
entry.level = level;
|
|
121
|
+
if (message !== undefined)
|
|
122
|
+
entry.message = message;
|
|
123
|
+
if (timestamp !== undefined)
|
|
124
|
+
entry.timestamp = timestamp;
|
|
125
|
+
if (status !== undefined)
|
|
126
|
+
entry.status = status;
|
|
127
|
+
entries.push(entry);
|
|
128
|
+
if (level?.toLowerCase() === 'error')
|
|
129
|
+
errorCount++;
|
|
130
|
+
if (timestamp) {
|
|
131
|
+
if (!firstTimestamp)
|
|
132
|
+
firstTimestamp = timestamp;
|
|
133
|
+
lastTimestamp = timestamp;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const stats = {
|
|
137
|
+
totalLines: entries.length + skipped,
|
|
138
|
+
errorCount,
|
|
139
|
+
};
|
|
140
|
+
if (firstTimestamp && lastTimestamp) {
|
|
141
|
+
stats.timeRange = { start: firstTimestamp, end: lastTimestamp };
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
type: 'log',
|
|
145
|
+
format: 'json',
|
|
146
|
+
entries,
|
|
147
|
+
stats,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// ─── Plain text ──────────────────────────────────────────────────────────────
|
|
151
|
+
function parsePlain(content) {
|
|
152
|
+
const rawLines = content.split('\n').filter((l) => l.trim());
|
|
153
|
+
const lines = rawLines.slice(-MAX_LINES);
|
|
154
|
+
const entries = lines.map((line) => ({ raw: line }));
|
|
155
|
+
return {
|
|
156
|
+
type: 'log',
|
|
157
|
+
format: 'plain',
|
|
158
|
+
entries,
|
|
159
|
+
stats: {
|
|
160
|
+
totalLines: lines.length,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
165
|
+
function topN(map, n) {
|
|
166
|
+
const sorted = Object.entries(map)
|
|
167
|
+
.sort((a, b) => b[1] - a[1])
|
|
168
|
+
.slice(0, n);
|
|
169
|
+
return Object.fromEntries(sorted);
|
|
170
|
+
}
|
|
171
|
+
function stringField(obj, key) {
|
|
172
|
+
const v = obj[key];
|
|
173
|
+
return typeof v === 'string' ? v : v !== undefined && v !== null ? String(v) : undefined;
|
|
174
|
+
}
|
|
175
|
+
function numberField(obj, key) {
|
|
176
|
+
const v = obj[key];
|
|
177
|
+
if (typeof v === 'number')
|
|
178
|
+
return v;
|
|
179
|
+
if (typeof v === 'string') {
|
|
180
|
+
const n = parseInt(v, 10);
|
|
181
|
+
return isNaN(n) ? undefined : n;
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/quick/parsers/log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modsec.d.ts","sourceRoot":"","sources":["../../../src/quick/parsers/modsec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAA8B,MAAM,aAAa,CAAA;AAyBzE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAU5D"}
|