@mitre/hdf-utilities 3.6.0-rc.5 → 3.7.0-rc.1
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 +1 -1
- package/dist/csv/index.d.ts +18 -13
- package/dist/csv/index.d.ts.map +1 -1
- package/dist/csv/index.js +12 -6
- package/dist/csv/index.js.map +1 -1
- package/dist/hash/index.d.ts +8 -9
- package/dist/hash/index.d.ts.map +1 -1
- package/dist/index.d.ts +41 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -5
- package/dist/index.js.map +1 -1
- package/dist/object/index.d.ts +3 -4
- package/dist/object/index.d.ts.map +1 -1
- package/dist/string/index.d.ts +8 -9
- package/dist/string/index.d.ts.map +1 -1
- package/dist/xml/index.d.ts +8 -8
- package/dist/xml/index.d.ts.map +1 -1
- package/dist/xml/index.js +9 -6
- package/dist/xml/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @mitre/hdf-utilities
|
|
2
2
|
|
|
3
|
-
Generic utility functions
|
|
3
|
+
Generic utility functions used throughout the HDF library ecosystem: safe parsing and building for common data formats (JSON, XML, CSV), cryptographic hashing, and the shared primitives that keep converters consistent — timestamp parsing and normalization, CVSS scoring, CPE and PURL identifiers, severity and status vocabularies, input-size guards, and object and string helpers.
|
|
4
4
|
|
|
5
5
|
## Scope and Responsibilities
|
|
6
6
|
|
package/dist/csv/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { extractColumn, findRows } from "../object/index.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Options for parsing CSV
|
|
5
5
|
*/
|
|
6
|
-
interface CsvParseOptions {
|
|
6
|
+
export interface CsvParseOptions {
|
|
7
7
|
header?: boolean;
|
|
8
8
|
skipEmptyLines?: boolean;
|
|
9
9
|
transformHeader?: (header: string, index: number) => string;
|
|
@@ -14,7 +14,7 @@ interface CsvParseOptions {
|
|
|
14
14
|
/**
|
|
15
15
|
* Options for building CSV
|
|
16
16
|
*/
|
|
17
|
-
interface CsvBuildOptions {
|
|
17
|
+
export interface CsvBuildOptions {
|
|
18
18
|
header?: boolean;
|
|
19
19
|
newline?: string;
|
|
20
20
|
skipEmptyLines?: boolean;
|
|
@@ -27,7 +27,7 @@ interface CsvBuildOptions {
|
|
|
27
27
|
* @returns Array of objects representing rows
|
|
28
28
|
* @throws Error if parsing fails
|
|
29
29
|
*/
|
|
30
|
-
declare function parseCsv<T = Record<string, unknown>>(csv: string, options?: Partial<CsvParseOptions>): T[];
|
|
30
|
+
export declare function parseCsv<T = Record<string, unknown>>(csv: string, options?: Partial<CsvParseOptions>): T[];
|
|
31
31
|
/**
|
|
32
32
|
* Parse CSV string into array of arrays without treating first row as headers
|
|
33
33
|
* @param csv - CSV string to parse
|
|
@@ -35,7 +35,7 @@ declare function parseCsv<T = Record<string, unknown>>(csv: string, options?: Pa
|
|
|
35
35
|
* @returns Array of arrays representing rows
|
|
36
36
|
* @throws Error if parsing fails
|
|
37
37
|
*/
|
|
38
|
-
declare function parseCsvArray(csv: string, options?: Partial<CsvParseOptions>): string[][];
|
|
38
|
+
export declare function parseCsvArray(csv: string, options?: Partial<CsvParseOptions>): string[][];
|
|
39
39
|
/**
|
|
40
40
|
* Build CSV string from array of objects
|
|
41
41
|
*
|
|
@@ -46,7 +46,7 @@ declare function parseCsvArray(csv: string, options?: Partial<CsvParseOptions>):
|
|
|
46
46
|
* @param options - Optional build configuration and sanitize flag
|
|
47
47
|
* @returns CSV string
|
|
48
48
|
*/
|
|
49
|
-
declare function buildCsv<T = Record<string, unknown>>(data: T[], options?: Partial<CsvBuildOptions> & {
|
|
49
|
+
export declare function buildCsv<T = Record<string, unknown>>(data: T[], options?: Partial<CsvBuildOptions> & {
|
|
50
50
|
sanitize?: boolean;
|
|
51
51
|
}): string;
|
|
52
52
|
/**
|
|
@@ -59,7 +59,7 @@ declare function buildCsv<T = Record<string, unknown>>(data: T[], options?: Part
|
|
|
59
59
|
* @param options - Optional build configuration and sanitize flag
|
|
60
60
|
* @returns CSV string
|
|
61
61
|
*/
|
|
62
|
-
declare function buildCsvArray(data: string[][], options?: Partial<CsvBuildOptions> & {
|
|
62
|
+
export declare function buildCsvArray(data: string[][], options?: Partial<CsvBuildOptions> & {
|
|
63
63
|
sanitize?: boolean;
|
|
64
64
|
}): string;
|
|
65
65
|
/**
|
|
@@ -67,31 +67,36 @@ declare function buildCsvArray(data: string[][], options?: Partial<CsvBuildOptio
|
|
|
67
67
|
* @param csv - CSV string to validate
|
|
68
68
|
* @returns True if valid CSV, false otherwise
|
|
69
69
|
*/
|
|
70
|
-
declare function isValidCsv(csv: string): boolean;
|
|
70
|
+
export declare function isValidCsv(csv: string): boolean;
|
|
71
71
|
/**
|
|
72
72
|
* Sanitize a single CSV value to prevent formula injection
|
|
73
73
|
*
|
|
74
|
-
* Prefixes values
|
|
75
|
-
*
|
|
74
|
+
* Prefixes values whose first non-whitespace character is =, +, -, @, |, or %
|
|
75
|
+
* with a single quote so Excel/LibreOffice read them as text. Leading ASCII
|
|
76
|
+
* whitespace (space, tab, CR, LF) is skipped before the check because
|
|
77
|
+
* spreadsheets trim it before evaluating a cell as a formula, so " =1+1" still
|
|
78
|
+
* executes (OWASP CSV Injection guidance). The quote prefixes the whole value,
|
|
79
|
+
* leaving the whitespace intact — the export stays lossless. A non-ASCII leading
|
|
80
|
+
* rune is not whitespace, so the scan stops and it is never falsely quoted.
|
|
76
81
|
*
|
|
77
82
|
* @param value - Value to sanitize
|
|
78
83
|
* @returns Sanitized value
|
|
79
84
|
*/
|
|
80
|
-
declare function sanitizeCsvValue(value: unknown): string;
|
|
85
|
+
export declare function sanitizeCsvValue(value: unknown): string;
|
|
81
86
|
/**
|
|
82
87
|
* Sanitize all values in an array to prevent formula injection
|
|
83
88
|
*
|
|
84
89
|
* @param values - Array of values to sanitize
|
|
85
90
|
* @returns Array with sanitized values
|
|
86
91
|
*/
|
|
87
|
-
declare function sanitizeCsvArray(values: unknown[]): string[];
|
|
92
|
+
export declare function sanitizeCsvArray(values: unknown[]): string[];
|
|
88
93
|
/**
|
|
89
94
|
* Sanitize all values in an object to prevent formula injection
|
|
90
95
|
*
|
|
91
96
|
* @param obj - Object with values to sanitize
|
|
92
97
|
* @returns New object with sanitized values
|
|
93
98
|
*/
|
|
94
|
-
declare function sanitizeCsvObject<T extends Record<string, unknown>>(obj: T): Record<string, string>;
|
|
99
|
+
export declare function sanitizeCsvObject<T extends Record<string, unknown>>(obj: T): Record<string, string>;
|
|
95
100
|
//#endregion
|
|
96
|
-
export {
|
|
101
|
+
export { extractColumn as extractCsvColumn, findRows as findCsvRows };
|
|
97
102
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/csv/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/csv/index.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/csv/index.ts"],"mappings":";;;;;iBAkBiB;EACf;EACA;EACA,mBAAmB,gBAAgB;EACnC;EACA;EACA;;;;;iBAMe;EACf;EACA;EACA;EACA;;;;;;;;;wBAwEc,SAAS,IAAI,yBAC3B,aACA,UAAU,QAAQ,mBACjB;;;;;;;;wBAoDa,cACd,aACA,UAAU,QAAQ;;;;;;;;;;;wBAiCJ,SAAS,IAAI,yBAC3B,MAAM,KACN,UAAU,QAAQ;EAAqB;;;;;;;;;;;;wBA6GzB,cACd,kBACA,UAAU,QAAQ;EAAqB;;;;;;;wBA4BzB,WAAW;;;;;;;;;;;;;;;wBA+BX,iBAAiB;;;;;;;wBAcjB,iBAAiB;;;;;;;wBAUjB,kBAAkB,UAAU,yBAC1C,KAAK,IACJ"}
|
package/dist/csv/index.js
CHANGED
|
@@ -38,9 +38,10 @@ const DEFAULT_BUILD_OPTIONS = {
|
|
|
38
38
|
function validateQuoting(csv) {
|
|
39
39
|
let inQuotes = false;
|
|
40
40
|
let row = 0;
|
|
41
|
-
for (let i = 0; i < csv.length; i++) if (csv[i] === "\"")
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
for (let i = 0; i < csv.length; i++) if (csv[i] === "\"") {
|
|
42
|
+
if (inQuotes && i + 1 < csv.length && csv[i + 1] === "\"") i++;
|
|
43
|
+
else inQuotes = !inQuotes;
|
|
44
|
+
} else if (csv[i] === "\n" && !inQuotes) row++;
|
|
44
45
|
if (inQuotes) throw new Error(`CSV parsing failed: Row ${row}: Unclosed quote`);
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
@@ -234,15 +235,20 @@ function isValidCsv(csv) {
|
|
|
234
235
|
/**
|
|
235
236
|
* Sanitize a single CSV value to prevent formula injection
|
|
236
237
|
*
|
|
237
|
-
* Prefixes values
|
|
238
|
-
*
|
|
238
|
+
* Prefixes values whose first non-whitespace character is =, +, -, @, |, or %
|
|
239
|
+
* with a single quote so Excel/LibreOffice read them as text. Leading ASCII
|
|
240
|
+
* whitespace (space, tab, CR, LF) is skipped before the check because
|
|
241
|
+
* spreadsheets trim it before evaluating a cell as a formula, so " =1+1" still
|
|
242
|
+
* executes (OWASP CSV Injection guidance). The quote prefixes the whole value,
|
|
243
|
+
* leaving the whitespace intact — the export stays lossless. A non-ASCII leading
|
|
244
|
+
* rune is not whitespace, so the scan stops and it is never falsely quoted.
|
|
239
245
|
*
|
|
240
246
|
* @param value - Value to sanitize
|
|
241
247
|
* @returns Sanitized value
|
|
242
248
|
*/
|
|
243
249
|
function sanitizeCsvValue(value) {
|
|
244
250
|
const str = String(value);
|
|
245
|
-
if (/^[=+\-@|%]/.test(str)) return `'${str}`;
|
|
251
|
+
if (/^[ \t\r\n]*[=+\-@|%]/.test(str)) return `'${str}`;
|
|
246
252
|
return str;
|
|
247
253
|
}
|
|
248
254
|
/**
|
package/dist/csv/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/csv/index.ts"],"sourcesContent":["/**\n * CSV parsing and generation utilities using d3-dsv\n *\n * SECURITY WARNING: CSV files opened in Excel/LibreOffice may execute formulas.\n * Use sanitization options when exporting data that may contain user-controlled content.\n */\n\nimport { dsvFormat } from 'd3-dsv';\nimport type { DSV } from 'd3-dsv';\n\nexport {\n extractColumn as extractCsvColumn,\n findRows as findCsvRows,\n} from '../object/index.js';\n\n/**\n * Options for parsing CSV\n */\nexport interface CsvParseOptions {\n header?: boolean;\n skipEmptyLines?: boolean;\n transformHeader?: (header: string, index: number) => string;\n dynamicTyping?: boolean;\n delimiter?: string;\n maxSize?: number;\n}\n\n/**\n * Options for building CSV\n */\nexport interface CsvBuildOptions {\n header?: boolean;\n newline?: string;\n skipEmptyLines?: boolean;\n delimiter?: string;\n}\n\n/**\n * Default options for parsing CSV with headers\n */\nconst DEFAULT_PARSE_OPTIONS: CsvParseOptions = {\n header: true,\n skipEmptyLines: true,\n transformHeader: undefined,\n dynamicTyping: false,\n};\n\n/**\n * Default options for parsing CSV without headers\n */\nconst DEFAULT_PARSE_ARRAY_OPTIONS: CsvParseOptions = {\n header: false,\n skipEmptyLines: true,\n dynamicTyping: false,\n};\n\n/**\n * Default options for building CSV\n */\nconst DEFAULT_BUILD_OPTIONS: CsvBuildOptions = {\n header: true,\n newline: '\\n',\n skipEmptyLines: true,\n};\n\n/**\n * Validate CSV quoting — throws if unclosed quotes are found\n */\nfunction validateQuoting(csv: string): void {\n let inQuotes = false;\n let row = 0;\n for (let i = 0; i < csv.length; i++) {\n if (csv[i] === '\"') {\n if (inQuotes && i + 1 < csv.length && csv[i + 1] === '\"') {\n i++; // skip escaped quote \"\"\n } else {\n inQuotes = !inQuotes;\n }\n } else if (csv[i] === '\\n' && !inQuotes) {\n row++;\n }\n }\n if (inQuotes) {\n throw new Error(`CSV parsing failed: Row ${row}: Unclosed quote`);\n }\n}\n\n/**\n * Convert string value to number or boolean when appropriate\n */\nfunction dynamicTypeConvert(value: string): unknown {\n if (value === '') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n const num = Number(value);\n if (!isNaN(num) && value.trim() !== '') return num;\n return value;\n}\n\n/**\n * Parse CSV string into array of objects with headers as keys\n * @param csv - CSV string to parse\n * @param options - Optional parse configuration\n * @returns Array of objects representing rows\n * @throws Error if parsing fails\n */\nexport function parseCsv<T = Record<string, unknown>>(\n csv: string,\n options?: Partial<CsvParseOptions>\n): T[] {\n if (options?.maxSize !== undefined && csv.length > options.maxSize) {\n throw new Error(\n `Input exceeds maximum allowed size: ${csv.length} bytes exceeds limit of ${options.maxSize} bytes`\n );\n }\n\n const opts = { ...DEFAULT_PARSE_OPTIONS, ...options };\n const trimmed = csv.trim();\n\n validateQuoting(trimmed);\n\n const dsv = dsvFormat(opts.delimiter ?? ',');\n const parsed = dsv.parse(trimmed);\n const { columns } = parsed;\n\n // Pre-compute transformed headers\n const headers = opts.transformHeader\n ? columns.map((col, i) => opts.transformHeader!(col, i))\n : columns;\n\n let rows: Record<string, unknown>[] = parsed.map((row) => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n let value: unknown = row[col] ?? '';\n if (opts.dynamicTyping && typeof value === 'string') {\n value = dynamicTypeConvert(value);\n }\n const key = headers[i];\n if (key !== undefined) {\n obj[key] = value;\n }\n });\n return obj;\n });\n\n if (opts.skipEmptyLines) {\n rows = rows.filter((row) =>\n Object.values(row).some((v) => v !== '' && v !== null && v !== undefined)\n );\n }\n\n return rows as T[];\n}\n\n/**\n * Parse CSV string into array of arrays without treating first row as headers\n * @param csv - CSV string to parse\n * @param options - Optional parse configuration\n * @returns Array of arrays representing rows\n * @throws Error if parsing fails\n */\nexport function parseCsvArray(\n csv: string,\n options?: Partial<CsvParseOptions>\n): string[][] {\n if (options?.maxSize !== undefined && csv.length > options.maxSize) {\n throw new Error(\n `Input exceeds maximum allowed size: ${csv.length} bytes exceeds limit of ${options.maxSize} bytes`\n );\n }\n\n const opts = { ...DEFAULT_PARSE_ARRAY_OPTIONS, ...options };\n const trimmed = csv.trim();\n\n validateQuoting(trimmed);\n\n const dsv = dsvFormat(opts.delimiter ?? ',');\n let rows = dsv.parseRows(trimmed);\n\n if (opts.skipEmptyLines) {\n rows = rows.filter((row) => !(row.length === 1 && row[0] === ''));\n }\n\n return rows;\n}\n\n/**\n * Build CSV string from array of objects\n *\n * SECURITY: Set sanitize=true when data may contain user-controlled content\n * to prevent CSV formula injection attacks in Excel/LibreOffice.\n *\n * @param data - Array of objects to convert to CSV\n * @param options - Optional build configuration and sanitize flag\n * @returns CSV string\n */\nexport function buildCsv<T = Record<string, unknown>>(\n data: T[],\n options?: Partial<CsvBuildOptions> & { sanitize?: boolean }\n): string {\n const { sanitize, ...buildOpts } = options || {};\n const opts = { ...DEFAULT_BUILD_OPTIONS, ...buildOpts };\n\n if (data.length === 0) return '';\n\n let processedData = data;\n if (sanitize) {\n processedData = data.map((row) =>\n sanitizeCsvObject(row as Record<string, unknown>)\n ) as T[];\n }\n\n const dsv = dsvFormat(opts.delimiter ?? ',');\n let result: string;\n\n if (opts.header === false) {\n const rows = processedData.map((row) =>\n Object.values(row as Record<string, unknown>).map(String)\n );\n result = dsv.formatRows(rows);\n } else {\n result = dsv.format(processedData as Record<string, unknown>[]);\n }\n\n result = quoteLeadingWhitespace(result, dsv, opts.delimiter ?? ',');\n result = terminateFinalRecord(result);\n\n if (opts.newline && opts.newline !== '\\n') {\n result = result.replace(/\\n/g, opts.newline);\n }\n\n return result;\n}\n\n/**\n * Quote any field Go's encoding/csv would quote and d3-dsv would not.\n *\n * d3-dsv quotes only for the delimiter, a quote, or a newline. Go additionally\n * quotes when the field's FIRST rune is Unicode whitespace — so \" padded \"\n * round-trips through a parser that trims — and quotes the literal field `\\.`,\n * which some dialects treat as end-of-data. Trailing whitespace alone triggers\n * neither language. Without this a TS CSV differs from its Go twin on any such\n * value: the same class of split terminateFinalRecord exists to close.\n *\n * ONE predicate decides, and it is the same one Go uses. An earlier version\n * tested [ \\t] to skip the re-parse cheaply and \\s to decide, so a field led by\n * U+00A0 or U+2003 exited before the decision ever ran.\n *\n * Re-parses rather than intercepting the writer because d3-dsv exposes no\n * per-field hook on format(); the parse is over output this function just\n * produced, so it cannot fail on unbalanced quotes.\n */\nfunction quoteLeadingWhitespace(csv: string, dsv: DSV, delimiter: string): string {\n return formatRowsGoCompatible(dsv.parseRows(csv), dsv, delimiter);\n}\n\n/** The one writer both public builders go through, so a field cannot come out\n * quoted from one and bare from the other. */\nfunction formatRowsGoCompatible(rows: string[][], dsv: DSV, delimiter: string): string {\n return rows.map((row) => row.map((field) => requote(field, dsv)).join(delimiter)).join('\\n');\n}\n\n/**\n * Go's encoding/csv fieldNeedsQuotes, minus the conditions d3-dsv already\n * covers: a leading Unicode space, or the literal `\\.`.\n *\n * The class is Go's unicode.IsSpace, spelled out rather than borrowed from\n * JavaScript's \\s, which is not the same set: \\s omits U+0085 (NEL) and adds\n * U+FEFF, which Unicode 4.0.1 removed from White_Space. Borrowing \\s left a\n * field led by U+0085 unquoted here but quoted in Go, and the reverse for\n * U+FEFF.\n */\nconst GO_LEADING_SPACE = /^[\\t\\n\\v\\f\\r \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]/;\n\nfunction goWouldQuote(field: string): boolean {\n return field === '\\\\.' || GO_LEADING_SPACE.test(field);\n}\n\n/** One field, formatted by d3-dsv, then quoted if Go would quote it and d3-dsv did not. */\nfunction requote(field: string, dsv: DSV): string {\n const formatted = dsv.formatValue(field);\n if (formatted.startsWith('\"') || !goWouldQuote(field)) {\n return formatted;\n }\n return `\"${field.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Terminate the final record with a newline. d3-dsv leaves it off, but Go's\n * encoding/csv (which the Go converters use) always writes it, so without this\n * every TS CSV would differ from its Go twin by exactly one trailing byte.\n * Applied before the newline substitution so a \\r\\n dialect gets it too.\n */\nfunction terminateFinalRecord(csv: string): string {\n return csv.endsWith('\\n') ? csv : `${csv}\\n`;\n}\n\n/**\n * Build CSV string from array of arrays\n *\n * SECURITY: Set sanitize=true when data may contain user-controlled content\n * to prevent CSV formula injection attacks in Excel/LibreOffice.\n *\n * @param data - Array of arrays to convert to CSV\n * @param options - Optional build configuration and sanitize flag\n * @returns CSV string\n */\nexport function buildCsvArray(\n data: string[][],\n options?: Partial<CsvBuildOptions> & { sanitize?: boolean }\n): string {\n const { sanitize, ...buildOpts } = options || {};\n const opts = { ...DEFAULT_BUILD_OPTIONS, header: false, ...buildOpts };\n\n if (data.length === 0) return '';\n\n let processedData = data;\n if (sanitize) {\n processedData = data.map((row) => sanitizeCsvArray(row));\n }\n\n const delimiter = opts.delimiter ?? ',';\n const dsv = dsvFormat(delimiter);\n let result = terminateFinalRecord(formatRowsGoCompatible(processedData, dsv, delimiter));\n\n if (opts.newline && opts.newline !== '\\n') {\n result = result.replace(/\\n/g, opts.newline);\n }\n\n return result;\n}\n\n/**\n * Validate CSV format\n * @param csv - CSV string to validate\n * @returns True if valid CSV, false otherwise\n */\nexport function isValidCsv(csv: string): boolean {\n if (!csv || csv.trim().length === 0) return false;\n\n const trimmed = csv.trim();\n\n // CSV must have at least one delimiter (comma) to be considered CSV structure\n if (!trimmed.includes(',')) return false;\n\n try {\n validateQuoting(trimmed);\n } catch {\n return false;\n }\n\n return true;\n}\n\n/**\n * Sanitize a single CSV value to prevent formula injection\n *\n * Prefixes values starting with =, +, -, @, |, or % with a single quote\n * to prevent Excel/LibreOffice from interpreting them as formulas.\n *\n * @param value - Value to sanitize\n * @returns Sanitized value\n */\nexport function sanitizeCsvValue(value: unknown): string {\n const str = String(value);\n // Check if string starts with formula trigger characters\n if (/^[=+\\-@|%]/.test(str)) {\n return `'${str}`;\n }\n return str;\n}\n\n/**\n * Sanitize all values in an array to prevent formula injection\n *\n * @param values - Array of values to sanitize\n * @returns Array with sanitized values\n */\nexport function sanitizeCsvArray(values: unknown[]): string[] {\n return values.map(sanitizeCsvValue);\n}\n\n/**\n * Sanitize all values in an object to prevent formula injection\n *\n * @param obj - Object with values to sanitize\n * @returns New object with sanitized values\n */\nexport function sanitizeCsvObject<T extends Record<string, unknown>>(\n obj: T\n): Record<string, string> {\n const sanitized: Record<string, string> = {};\n for (const [key, value] of Object.entries(obj)) {\n sanitized[key] = sanitizeCsvValue(value);\n }\n return sanitized;\n}\n"],"mappings":";;;;;;;;;;;;AAwCA,MAAM,wBAAyC;CAC7C,QAAQ;CACR,gBAAgB;CAChB,iBAAiB,KAAA;CACjB,eAAe;AACjB;;;;AAKA,MAAM,8BAA+C;CACnD,QAAQ;CACR,gBAAgB;CAChB,eAAe;AACjB;;;;AAKA,MAAM,wBAAyC;CAC7C,QAAQ;CACR,SAAS;CACT,gBAAgB;AAClB;;;;AAKA,SAAS,gBAAgB,KAAmB;CAC1C,IAAI,WAAW;CACf,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAC9B,IAAI,IAAI,OAAO,MACb,IAAI,YAAY,IAAI,IAAI,IAAI,UAAU,IAAI,IAAI,OAAO,MACnD;MAEA,WAAW,CAAC;MAET,IAAI,IAAI,OAAO,QAAQ,CAAC,UAC7B;CAGJ,IAAI,UACF,MAAM,IAAI,MAAM,2BAA2B,IAAI,iBAAiB;AAEpE;;;;AAKA,SAAS,mBAAmB,OAAwB;CAClD,IAAI,UAAU,IAAI,OAAO;CACzB,IAAI,UAAU,QAAQ,OAAO;CAC7B,IAAI,UAAU,SAAS,OAAO;CAC9B,MAAM,MAAM,OAAO,KAAK;CACxB,IAAI,CAAC,MAAM,GAAG,KAAK,MAAM,KAAK,MAAM,IAAI,OAAO;CAC/C,OAAO;AACT;;;;;;;;AASA,SAAgB,SACd,KACA,SACK;CACL,IAAI,SAAS,YAAY,KAAA,KAAa,IAAI,SAAS,QAAQ,SACzD,MAAM,IAAI,MACR,uCAAuC,IAAI,OAAO,0BAA0B,QAAQ,QAAQ,OAC9F;CAGF,MAAM,OAAO;EAAE,GAAG;EAAuB,GAAG;CAAQ;CACpD,MAAM,UAAU,IAAI,KAAK;CAEzB,gBAAgB,OAAO;CAGvB,MAAM,SADM,UAAU,KAAK,aAAa,GACvB,CAAC,CAAC,MAAM,OAAO;CAChC,MAAM,EAAE,YAAY;CAGpB,MAAM,UAAU,KAAK,kBACjB,QAAQ,KAAK,KAAK,MAAM,KAAK,gBAAiB,KAAK,CAAC,CAAC,IACrD;CAEJ,IAAI,OAAkC,OAAO,KAAK,QAAQ;EACxD,MAAM,MAA+B,CAAC;EACtC,QAAQ,SAAS,KAAK,MAAM;GAC1B,IAAI,QAAiB,IAAI,QAAQ;GACjC,IAAI,KAAK,iBAAiB,OAAO,UAAU,UACzC,QAAQ,mBAAmB,KAAK;GAElC,MAAM,MAAM,QAAQ;GACpB,IAAI,QAAQ,KAAA,GACV,IAAI,OAAO;EAEf,CAAC;EACD,OAAO;CACT,CAAC;CAED,IAAI,KAAK,gBACP,OAAO,KAAK,QAAQ,QAClB,OAAO,OAAO,GAAG,CAAC,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,QAAQ,MAAM,KAAA,CAAS,CAC1E;CAGF,OAAO;AACT;;;;;;;;AASA,SAAgB,cACd,KACA,SACY;CACZ,IAAI,SAAS,YAAY,KAAA,KAAa,IAAI,SAAS,QAAQ,SACzD,MAAM,IAAI,MACR,uCAAuC,IAAI,OAAO,0BAA0B,QAAQ,QAAQ,OAC9F;CAGF,MAAM,OAAO;EAAE,GAAG;EAA6B,GAAG;CAAQ;CAC1D,MAAM,UAAU,IAAI,KAAK;CAEzB,gBAAgB,OAAO;CAGvB,IAAI,OADQ,UAAU,KAAK,aAAa,GAC3B,CAAC,CAAC,UAAU,OAAO;CAEhC,IAAI,KAAK,gBACP,OAAO,KAAK,QAAQ,QAAQ,EAAE,IAAI,WAAW,KAAK,IAAI,OAAO,GAAG;CAGlE,OAAO;AACT;;;;;;;;;;;AAYA,SAAgB,SACd,MACA,SACQ;CACR,MAAM,EAAE,UAAU,GAAG,cAAc,WAAW,CAAC;CAC/C,MAAM,OAAO;EAAE,GAAG;EAAuB,GAAG;CAAU;CAEtD,IAAI,KAAK,WAAW,GAAG,OAAO;CAE9B,IAAI,gBAAgB;CACpB,IAAI,UACF,gBAAgB,KAAK,KAAK,QACxB,kBAAkB,GAA8B,CAClD;CAGF,MAAM,MAAM,UAAU,KAAK,aAAa,GAAG;CAC3C,IAAI;CAEJ,IAAI,KAAK,WAAW,OAAO;EACzB,MAAM,OAAO,cAAc,KAAK,QAC9B,OAAO,OAAO,GAA8B,CAAC,CAAC,IAAI,MAAM,CAC1D;EACA,SAAS,IAAI,WAAW,IAAI;CAC9B,OACE,SAAS,IAAI,OAAO,aAA0C;CAGhE,SAAS,uBAAuB,QAAQ,KAAK,KAAK,aAAa,GAAG;CAClE,SAAS,qBAAqB,MAAM;CAEpC,IAAI,KAAK,WAAW,KAAK,YAAY,MACnC,SAAS,OAAO,QAAQ,OAAO,KAAK,OAAO;CAG7C,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAoBA,SAAS,uBAAuB,KAAa,KAAU,WAA2B;CAChF,OAAO,uBAAuB,IAAI,UAAU,GAAG,GAAG,KAAK,SAAS;AAClE;;;AAIA,SAAS,uBAAuB,MAAkB,KAAU,WAA2B;CACrF,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,UAAU,QAAQ,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI;AAC7F;;;;;;;;;;;AAYA,MAAM,mBAAmB;AAEzB,SAAS,aAAa,OAAwB;CAC5C,OAAO,UAAU,SAAS,iBAAiB,KAAK,KAAK;AACvD;;AAGA,SAAS,QAAQ,OAAe,KAAkB;CAChD,MAAM,YAAY,IAAI,YAAY,KAAK;CACvC,IAAI,UAAU,WAAW,IAAG,KAAK,CAAC,aAAa,KAAK,GAClD,OAAO;CAET,OAAO,IAAI,MAAM,QAAQ,MAAM,MAAI,EAAE;AACvC;;;;;;;AAQA,SAAS,qBAAqB,KAAqB;CACjD,OAAO,IAAI,SAAS,IAAI,IAAI,MAAM,GAAG,IAAI;AAC3C;;;;;;;;;;;AAYA,SAAgB,cACd,MACA,SACQ;CACR,MAAM,EAAE,UAAU,GAAG,cAAc,WAAW,CAAC;CAC/C,MAAM,OAAO;EAAE,GAAG;EAAuB,QAAQ;EAAO,GAAG;CAAU;CAErE,IAAI,KAAK,WAAW,GAAG,OAAO;CAE9B,IAAI,gBAAgB;CACpB,IAAI,UACF,gBAAgB,KAAK,KAAK,QAAQ,iBAAiB,GAAG,CAAC;CAGzD,MAAM,YAAY,KAAK,aAAa;CACpC,MAAM,MAAM,UAAU,SAAS;CAC/B,IAAI,SAAS,qBAAqB,uBAAuB,eAAe,KAAK,SAAS,CAAC;CAEvF,IAAI,KAAK,WAAW,KAAK,YAAY,MACnC,SAAS,OAAO,QAAQ,OAAO,KAAK,OAAO;CAG7C,OAAO;AACT;;;;;;AAOA,SAAgB,WAAW,KAAsB;CAC/C,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC,WAAW,GAAG,OAAO;CAE5C,MAAM,UAAU,IAAI,KAAK;CAGzB,IAAI,CAAC,QAAQ,SAAS,GAAG,GAAG,OAAO;CAEnC,IAAI;EACF,gBAAgB,OAAO;CACzB,QAAQ;EACN,OAAO;CACT;CAEA,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,iBAAiB,OAAwB;CACvD,MAAM,MAAM,OAAO,KAAK;CAExB,IAAI,aAAa,KAAK,GAAG,GACvB,OAAO,IAAI;CAEb,OAAO;AACT;;;;;;;AAQA,SAAgB,iBAAiB,QAA6B;CAC5D,OAAO,OAAO,IAAI,gBAAgB;AACpC;;;;;;;AAQA,SAAgB,kBACd,KACwB;CACxB,MAAM,YAAoC,CAAC;CAC3C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,GAAG,GAC3C,UAAU,OAAO,iBAAiB,KAAK;CAEzC,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/csv/index.ts"],"sourcesContent":["/**\n * CSV parsing and generation utilities using d3-dsv\n *\n * SECURITY WARNING: CSV files opened in Excel/LibreOffice may execute formulas.\n * Use sanitization options when exporting data that may contain user-controlled content.\n */\n\nimport { dsvFormat } from 'd3-dsv';\nimport type { DSV } from 'd3-dsv';\n\nexport {\n extractColumn as extractCsvColumn,\n findRows as findCsvRows,\n} from '../object/index.js';\n\n/**\n * Options for parsing CSV\n */\nexport interface CsvParseOptions {\n header?: boolean;\n skipEmptyLines?: boolean;\n transformHeader?: (header: string, index: number) => string;\n dynamicTyping?: boolean;\n delimiter?: string;\n maxSize?: number;\n}\n\n/**\n * Options for building CSV\n */\nexport interface CsvBuildOptions {\n header?: boolean;\n newline?: string;\n skipEmptyLines?: boolean;\n delimiter?: string;\n}\n\n/**\n * Default options for parsing CSV with headers\n */\nconst DEFAULT_PARSE_OPTIONS: CsvParseOptions = {\n header: true,\n skipEmptyLines: true,\n transformHeader: undefined,\n dynamicTyping: false,\n};\n\n/**\n * Default options for parsing CSV without headers\n */\nconst DEFAULT_PARSE_ARRAY_OPTIONS: CsvParseOptions = {\n header: false,\n skipEmptyLines: true,\n dynamicTyping: false,\n};\n\n/**\n * Default options for building CSV\n */\nconst DEFAULT_BUILD_OPTIONS: CsvBuildOptions = {\n header: true,\n newline: '\\n',\n skipEmptyLines: true,\n};\n\n/**\n * Validate CSV quoting — throws if unclosed quotes are found\n */\nfunction validateQuoting(csv: string): void {\n let inQuotes = false;\n let row = 0;\n for (let i = 0; i < csv.length; i++) {\n if (csv[i] === '\"') {\n if (inQuotes && i + 1 < csv.length && csv[i + 1] === '\"') {\n i++; // skip escaped quote \"\"\n } else {\n inQuotes = !inQuotes;\n }\n } else if (csv[i] === '\\n' && !inQuotes) {\n row++;\n }\n }\n if (inQuotes) {\n throw new Error(`CSV parsing failed: Row ${row}: Unclosed quote`);\n }\n}\n\n/**\n * Convert string value to number or boolean when appropriate\n */\nfunction dynamicTypeConvert(value: string): unknown {\n if (value === '') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n const num = Number(value);\n if (!isNaN(num) && value.trim() !== '') return num;\n return value;\n}\n\n/**\n * Parse CSV string into array of objects with headers as keys\n * @param csv - CSV string to parse\n * @param options - Optional parse configuration\n * @returns Array of objects representing rows\n * @throws Error if parsing fails\n */\nexport function parseCsv<T = Record<string, unknown>>(\n csv: string,\n options?: Partial<CsvParseOptions>\n): T[] {\n if (options?.maxSize !== undefined && csv.length > options.maxSize) {\n throw new Error(\n `Input exceeds maximum allowed size: ${csv.length} bytes exceeds limit of ${options.maxSize} bytes`\n );\n }\n\n const opts = { ...DEFAULT_PARSE_OPTIONS, ...options };\n const trimmed = csv.trim();\n\n validateQuoting(trimmed);\n\n const dsv = dsvFormat(opts.delimiter ?? ',');\n const parsed = dsv.parse(trimmed);\n const { columns } = parsed;\n\n // Pre-compute transformed headers\n const headers = opts.transformHeader\n ? columns.map((col, i) => opts.transformHeader!(col, i))\n : columns;\n\n let rows: Record<string, unknown>[] = parsed.map((row) => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n let value: unknown = row[col] ?? '';\n if (opts.dynamicTyping && typeof value === 'string') {\n value = dynamicTypeConvert(value);\n }\n const key = headers[i];\n if (key !== undefined) {\n obj[key] = value;\n }\n });\n return obj;\n });\n\n if (opts.skipEmptyLines) {\n rows = rows.filter((row) =>\n Object.values(row).some((v) => v !== '' && v !== null && v !== undefined)\n );\n }\n\n return rows as T[];\n}\n\n/**\n * Parse CSV string into array of arrays without treating first row as headers\n * @param csv - CSV string to parse\n * @param options - Optional parse configuration\n * @returns Array of arrays representing rows\n * @throws Error if parsing fails\n */\nexport function parseCsvArray(\n csv: string,\n options?: Partial<CsvParseOptions>\n): string[][] {\n if (options?.maxSize !== undefined && csv.length > options.maxSize) {\n throw new Error(\n `Input exceeds maximum allowed size: ${csv.length} bytes exceeds limit of ${options.maxSize} bytes`\n );\n }\n\n const opts = { ...DEFAULT_PARSE_ARRAY_OPTIONS, ...options };\n const trimmed = csv.trim();\n\n validateQuoting(trimmed);\n\n const dsv = dsvFormat(opts.delimiter ?? ',');\n let rows = dsv.parseRows(trimmed);\n\n if (opts.skipEmptyLines) {\n rows = rows.filter((row) => !(row.length === 1 && row[0] === ''));\n }\n\n return rows;\n}\n\n/**\n * Build CSV string from array of objects\n *\n * SECURITY: Set sanitize=true when data may contain user-controlled content\n * to prevent CSV formula injection attacks in Excel/LibreOffice.\n *\n * @param data - Array of objects to convert to CSV\n * @param options - Optional build configuration and sanitize flag\n * @returns CSV string\n */\nexport function buildCsv<T = Record<string, unknown>>(\n data: T[],\n options?: Partial<CsvBuildOptions> & { sanitize?: boolean }\n): string {\n const { sanitize, ...buildOpts } = options || {};\n const opts = { ...DEFAULT_BUILD_OPTIONS, ...buildOpts };\n\n if (data.length === 0) return '';\n\n let processedData = data;\n if (sanitize) {\n processedData = data.map((row) =>\n sanitizeCsvObject(row as Record<string, unknown>)\n ) as T[];\n }\n\n const dsv = dsvFormat(opts.delimiter ?? ',');\n let result: string;\n\n if (opts.header === false) {\n const rows = processedData.map((row) =>\n Object.values(row as Record<string, unknown>).map(String)\n );\n result = dsv.formatRows(rows);\n } else {\n result = dsv.format(processedData as Record<string, unknown>[]);\n }\n\n result = quoteLeadingWhitespace(result, dsv, opts.delimiter ?? ',');\n result = terminateFinalRecord(result);\n\n if (opts.newline && opts.newline !== '\\n') {\n result = result.replace(/\\n/g, opts.newline);\n }\n\n return result;\n}\n\n/**\n * Quote any field Go's encoding/csv would quote and d3-dsv would not.\n *\n * d3-dsv quotes only for the delimiter, a quote, or a newline. Go additionally\n * quotes when the field's FIRST rune is Unicode whitespace — so \" padded \"\n * round-trips through a parser that trims — and quotes the literal field `\\.`,\n * which some dialects treat as end-of-data. Trailing whitespace alone triggers\n * neither language. Without this a TS CSV differs from its Go twin on any such\n * value: the same class of split terminateFinalRecord exists to close.\n *\n * ONE predicate decides, and it is the same one Go uses. An earlier version\n * tested [ \\t] to skip the re-parse cheaply and \\s to decide, so a field led by\n * U+00A0 or U+2003 exited before the decision ever ran.\n *\n * Re-parses rather than intercepting the writer because d3-dsv exposes no\n * per-field hook on format(); the parse is over output this function just\n * produced, so it cannot fail on unbalanced quotes.\n */\nfunction quoteLeadingWhitespace(csv: string, dsv: DSV, delimiter: string): string {\n return formatRowsGoCompatible(dsv.parseRows(csv), dsv, delimiter);\n}\n\n/** The one writer both public builders go through, so a field cannot come out\n * quoted from one and bare from the other. */\nfunction formatRowsGoCompatible(rows: string[][], dsv: DSV, delimiter: string): string {\n return rows.map((row) => row.map((field) => requote(field, dsv)).join(delimiter)).join('\\n');\n}\n\n/**\n * Go's encoding/csv fieldNeedsQuotes, minus the conditions d3-dsv already\n * covers: a leading Unicode space, or the literal `\\.`.\n *\n * The class is Go's unicode.IsSpace, spelled out rather than borrowed from\n * JavaScript's \\s, which is not the same set: \\s omits U+0085 (NEL) and adds\n * U+FEFF, which Unicode 4.0.1 removed from White_Space. Borrowing \\s left a\n * field led by U+0085 unquoted here but quoted in Go, and the reverse for\n * U+FEFF.\n */\nconst GO_LEADING_SPACE = /^[\\t\\n\\v\\f\\r \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]/;\n\nfunction goWouldQuote(field: string): boolean {\n return field === '\\\\.' || GO_LEADING_SPACE.test(field);\n}\n\n/** One field, formatted by d3-dsv, then quoted if Go would quote it and d3-dsv did not. */\nfunction requote(field: string, dsv: DSV): string {\n const formatted = dsv.formatValue(field);\n if (formatted.startsWith('\"') || !goWouldQuote(field)) {\n return formatted;\n }\n return `\"${field.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Terminate the final record with a newline. d3-dsv leaves it off, but Go's\n * encoding/csv (which the Go converters use) always writes it, so without this\n * every TS CSV would differ from its Go twin by exactly one trailing byte.\n * Applied before the newline substitution so a \\r\\n dialect gets it too.\n */\nfunction terminateFinalRecord(csv: string): string {\n return csv.endsWith('\\n') ? csv : `${csv}\\n`;\n}\n\n/**\n * Build CSV string from array of arrays\n *\n * SECURITY: Set sanitize=true when data may contain user-controlled content\n * to prevent CSV formula injection attacks in Excel/LibreOffice.\n *\n * @param data - Array of arrays to convert to CSV\n * @param options - Optional build configuration and sanitize flag\n * @returns CSV string\n */\nexport function buildCsvArray(\n data: string[][],\n options?: Partial<CsvBuildOptions> & { sanitize?: boolean }\n): string {\n const { sanitize, ...buildOpts } = options || {};\n const opts = { ...DEFAULT_BUILD_OPTIONS, header: false, ...buildOpts };\n\n if (data.length === 0) return '';\n\n let processedData = data;\n if (sanitize) {\n processedData = data.map((row) => sanitizeCsvArray(row));\n }\n\n const delimiter = opts.delimiter ?? ',';\n const dsv = dsvFormat(delimiter);\n let result = terminateFinalRecord(formatRowsGoCompatible(processedData, dsv, delimiter));\n\n if (opts.newline && opts.newline !== '\\n') {\n result = result.replace(/\\n/g, opts.newline);\n }\n\n return result;\n}\n\n/**\n * Validate CSV format\n * @param csv - CSV string to validate\n * @returns True if valid CSV, false otherwise\n */\nexport function isValidCsv(csv: string): boolean {\n if (!csv || csv.trim().length === 0) return false;\n\n const trimmed = csv.trim();\n\n // CSV must have at least one delimiter (comma) to be considered CSV structure\n if (!trimmed.includes(',')) return false;\n\n try {\n validateQuoting(trimmed);\n } catch {\n return false;\n }\n\n return true;\n}\n\n/**\n * Sanitize a single CSV value to prevent formula injection\n *\n * Prefixes values whose first non-whitespace character is =, +, -, @, |, or %\n * with a single quote so Excel/LibreOffice read them as text. Leading ASCII\n * whitespace (space, tab, CR, LF) is skipped before the check because\n * spreadsheets trim it before evaluating a cell as a formula, so \" =1+1\" still\n * executes (OWASP CSV Injection guidance). The quote prefixes the whole value,\n * leaving the whitespace intact — the export stays lossless. A non-ASCII leading\n * rune is not whitespace, so the scan stops and it is never falsely quoted.\n *\n * @param value - Value to sanitize\n * @returns Sanitized value\n */\nexport function sanitizeCsvValue(value: unknown): string {\n const str = String(value);\n if (/^[ \\t\\r\\n]*[=+\\-@|%]/.test(str)) {\n return `'${str}`;\n }\n return str;\n}\n\n/**\n * Sanitize all values in an array to prevent formula injection\n *\n * @param values - Array of values to sanitize\n * @returns Array with sanitized values\n */\nexport function sanitizeCsvArray(values: unknown[]): string[] {\n return values.map(sanitizeCsvValue);\n}\n\n/**\n * Sanitize all values in an object to prevent formula injection\n *\n * @param obj - Object with values to sanitize\n * @returns New object with sanitized values\n */\nexport function sanitizeCsvObject<T extends Record<string, unknown>>(\n obj: T\n): Record<string, string> {\n const sanitized: Record<string, string> = {};\n for (const [key, value] of Object.entries(obj)) {\n sanitized[key] = sanitizeCsvValue(value);\n }\n return sanitized;\n}\n"],"mappings":"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"}
|
package/dist/hash/index.d.ts
CHANGED
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* Supported hash algorithms
|
|
9
9
|
*/
|
|
10
|
-
type HashAlgorithm = 'sha256' | 'sha512';
|
|
10
|
+
export type HashAlgorithm = 'sha256' | 'sha512';
|
|
11
11
|
/**
|
|
12
12
|
* Supported output encodings
|
|
13
13
|
*/
|
|
14
|
-
type HashEncoding = 'hex' | 'base64';
|
|
14
|
+
export type HashEncoding = 'hex' | 'base64';
|
|
15
15
|
/**
|
|
16
16
|
* Options for hash generation
|
|
17
17
|
*/
|
|
18
|
-
interface HashOptions {
|
|
18
|
+
export interface HashOptions {
|
|
19
19
|
/** Hash algorithm (default: 'sha256') */
|
|
20
20
|
algorithm?: HashAlgorithm;
|
|
21
21
|
/** Output encoding (default: 'hex') */
|
|
@@ -34,7 +34,7 @@ interface HashOptions {
|
|
|
34
34
|
* // Returns: 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
|
-
declare function generateHash(data: string, options?: HashOptions): Promise<string>;
|
|
37
|
+
export declare function generateHash(data: string, options?: HashOptions): Promise<string>;
|
|
38
38
|
/**
|
|
39
39
|
* Generate a SHA-256 hash (recommended for most use cases)
|
|
40
40
|
*
|
|
@@ -47,7 +47,7 @@ declare function generateHash(data: string, options?: HashOptions): Promise<stri
|
|
|
47
47
|
* // Returns: 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
|
-
declare function sha256(data: string): Promise<string>;
|
|
50
|
+
export declare function sha256(data: string): Promise<string>;
|
|
51
51
|
/**
|
|
52
52
|
* Generate a SHA-512 hash (enhanced security for sensitive data)
|
|
53
53
|
*
|
|
@@ -60,7 +60,7 @@ declare function sha256(data: string): Promise<string>;
|
|
|
60
60
|
* // Returns: '309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f'
|
|
61
61
|
* ```
|
|
62
62
|
*/
|
|
63
|
-
declare function sha512(data: string): Promise<string>;
|
|
63
|
+
export declare function sha512(data: string): Promise<string>;
|
|
64
64
|
/**
|
|
65
65
|
* Generate a hash of an object by stringifying it first
|
|
66
66
|
* Useful for hashing HDF control objects or other structured data
|
|
@@ -76,7 +76,7 @@ declare function sha512(data: string): Promise<string>;
|
|
|
76
76
|
* // Returns hash of the JSON-stringified object
|
|
77
77
|
* ```
|
|
78
78
|
*/
|
|
79
|
-
declare function hashObject(obj: unknown, options?: HashOptions): Promise<string>;
|
|
79
|
+
export declare function hashObject(obj: unknown, options?: HashOptions): Promise<string>;
|
|
80
80
|
/**
|
|
81
81
|
* Verify that data matches a given hash
|
|
82
82
|
*
|
|
@@ -92,7 +92,6 @@ declare function hashObject(obj: unknown, options?: HashOptions): Promise<string
|
|
|
92
92
|
* const isValid = await verifyHash(data, hash); // true
|
|
93
93
|
* ```
|
|
94
94
|
*/
|
|
95
|
-
declare function verifyHash(data: string, expectedHash: string, options?: HashOptions): Promise<boolean>;
|
|
95
|
+
export declare function verifyHash(data: string, expectedHash: string, options?: HashOptions): Promise<boolean>;
|
|
96
96
|
//#endregion
|
|
97
|
-
export { HashAlgorithm, HashEncoding, HashOptions, generateHash, hashObject, sha256, sha512, verifyHash };
|
|
98
97
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/hash/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/hash/index.ts"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/hash/index.ts"],"mappings":";;;;;;;;;YASY;;;;YAKA;;;;iBAKK;;EAEf,YAAY;;EAEZ,WAAW;;;;;;;;;;;;;;;wBA0CS,aAAa,cAAc,UAAS,cAAmB;;;;;;;;;;;;;wBAoBvD,OAAO,eAAe;;;;;;;;;;;;;wBAgBtB,OAAO,eAAe;;;;;;;;;;;;;;;;wBAmBtB,WAAW,cAAc,UAAS,cAAmB;;;;;;;;;;;;;;;;wBAqBrD,WACpB,cACA,sBACA,UAAS,cACR"}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,9 +25,9 @@ import { encodeBase64Utf8, formatTimestamp, formatTimestampSeconds, normalizeHdf
|
|
|
25
25
|
* @param severity - Severity level (case-insensitive), or null for no severity assessment
|
|
26
26
|
* @returns Impact score between 0.0 and 1.0; null when input is null; defaults to 0.5 for unrecognized values
|
|
27
27
|
*/
|
|
28
|
-
declare function severityToImpact(severity: null): null;
|
|
29
|
-
declare function severityToImpact(severity: string | undefined): number;
|
|
30
|
-
declare function severityToImpact(severity: string | null | undefined): number | null;
|
|
28
|
+
export declare function severityToImpact(severity: null): null;
|
|
29
|
+
export declare function severityToImpact(severity: string | undefined): number;
|
|
30
|
+
export declare function severityToImpact(severity: string | null | undefined): number | null;
|
|
31
31
|
/**
|
|
32
32
|
* Map severity to impact, checking custom aliases first, then the shared
|
|
33
33
|
* standard map, then the caller default. Case-insensitive. Use for tools with
|
|
@@ -37,7 +37,7 @@ declare function severityToImpact(severity: string | null | undefined): number |
|
|
|
37
37
|
* SeverityToImpactWithAliases; converters must not hand-roll local severity
|
|
38
38
|
* maps around it (that fork is how Go/TS impact divergence happens).
|
|
39
39
|
*/
|
|
40
|
-
declare function severityToImpactWithAliases(severity: string | null | undefined, aliases: Record<string, number>, defaultVal: number): number;
|
|
40
|
+
export declare function severityToImpactWithAliases(severity: string | null | undefined, aliases: Record<string, number>, defaultVal: number): number;
|
|
41
41
|
/**
|
|
42
42
|
* Round an HDF impact value to 2 decimal places — its canonical precision —
|
|
43
43
|
* eliminating the representation noise that binary float division leaves behind
|
|
@@ -46,16 +46,16 @@ declare function severityToImpactWithAliases(severity: string | null | undefined
|
|
|
46
46
|
* intent. Use it wherever impact is COMPUTED (divided or otherwise
|
|
47
47
|
* arithmetically derived), not when assigned from a literal band.
|
|
48
48
|
*/
|
|
49
|
-
declare function roundImpact(x: number): number;
|
|
49
|
+
export declare function roundImpact(x: number): number;
|
|
50
50
|
/**
|
|
51
51
|
* Map an impact score to a severity string.
|
|
52
52
|
*
|
|
53
53
|
* @param impact - Impact score (0.0 to 1.0), or null for no impact assessment
|
|
54
54
|
* @returns Severity level string, or null when input is null
|
|
55
55
|
*/
|
|
56
|
-
declare function impactToSeverity(impact: null): null;
|
|
57
|
-
declare function impactToSeverity(impact: number): string;
|
|
58
|
-
declare function impactToSeverity(impact: number | null): string | null;
|
|
56
|
+
export declare function impactToSeverity(impact: null): null;
|
|
57
|
+
export declare function impactToSeverity(impact: number): string;
|
|
58
|
+
export declare function impactToSeverity(impact: number | null): string | null;
|
|
59
59
|
/**
|
|
60
60
|
* Map a raw CVSS base score (0.0–10.0) to a FIRST qualitative severity band.
|
|
61
61
|
*
|
|
@@ -73,7 +73,7 @@ declare function impactToSeverity(impact: number | null): string | null;
|
|
|
73
73
|
* @param score - CVSS base score
|
|
74
74
|
* @returns FIRST severity band label
|
|
75
75
|
*/
|
|
76
|
-
declare function cvssScoreToSeverity(score: number): 'none' | 'low' | 'medium' | 'high' | 'critical';
|
|
76
|
+
export declare function cvssScoreToSeverity(score: number): 'none' | 'low' | 'medium' | 'high' | 'critical';
|
|
77
77
|
/**
|
|
78
78
|
* Report whether a source severity carries no rating at all: the field is
|
|
79
79
|
* absent/blank, or the token is an explicit no-rating value. Tokens the
|
|
@@ -81,7 +81,7 @@ declare function cvssScoreToSeverity(score: number): 'none' | 'low' | 'medium' |
|
|
|
81
81
|
* an assertion of unratedness. Converters use this to emit the shared unrated
|
|
82
82
|
* marker so a defaulted impact stays distinguishable from a genuine medium.
|
|
83
83
|
*/
|
|
84
|
-
declare function isUnratedSeverity(severity?: string | null): boolean;
|
|
84
|
+
export declare function isUnratedSeverity(severity?: string | null): boolean;
|
|
85
85
|
//#endregion
|
|
86
86
|
//#region src/status/index.d.ts
|
|
87
87
|
/**
|
|
@@ -93,16 +93,16 @@ declare function isUnratedSeverity(severity?: string | null): boolean;
|
|
|
93
93
|
* site/docs/architecture/status-determination.md; do not re-implement them.
|
|
94
94
|
*/
|
|
95
95
|
/** Canonical worst-wins ordering, worst first. */
|
|
96
|
-
declare const STATUS_SEVERITY_ORDER: readonly ["error", "failed", "passed", "notApplicable", "notReviewed"];
|
|
96
|
+
export declare const STATUS_SEVERITY_ORDER: readonly ["error", "failed", "passed", "notApplicable", "notReviewed"];
|
|
97
97
|
/** A member of the canonical ordering, as a literal union. */
|
|
98
98
|
type StatusSeverity = (typeof STATUS_SEVERITY_ORDER)[number];
|
|
99
99
|
/** Severity rank of a status: higher = worse. Unknown statuses rank -1. */
|
|
100
|
-
declare function statusRank(status: string): number;
|
|
100
|
+
export declare function statusRank(status: string): number;
|
|
101
101
|
/**
|
|
102
102
|
* Rolls a list of result statuses up to the worst one. An empty list (or a
|
|
103
103
|
* list of only unknown statuses) rolls up to "notReviewed".
|
|
104
104
|
*/
|
|
105
|
-
declare function worstStatus(statuses: readonly string[]): string;
|
|
105
|
+
export declare function worstStatus(statuses: readonly string[]): string;
|
|
106
106
|
/**
|
|
107
107
|
* Neutral shape of a status override for effective-status computation.
|
|
108
108
|
* Callers map their concrete types (schema objects or raw JSON) onto it.
|
|
@@ -121,7 +121,7 @@ interface StatusOverrideInput {
|
|
|
121
121
|
* schema's definition of disposition ("the most recent non-expired
|
|
122
122
|
* override"). Returns undefined when no override governs.
|
|
123
123
|
*/
|
|
124
|
-
declare function governingStatusOverride(overrides: readonly StatusOverrideInput[], referenceTimestamp?: string): StatusOverrideInput | undefined;
|
|
124
|
+
export declare function governingStatusOverride(overrides: readonly StatusOverrideInput[], referenceTimestamp?: string): StatusOverrideInput | undefined;
|
|
125
125
|
/**
|
|
126
126
|
* Returns the index of the most recently applied (by appliedAt) non-expired
|
|
127
127
|
* override among those for which `eligible` returns true, or -1 when none
|
|
@@ -130,13 +130,13 @@ declare function governingStatusOverride(overrides: readonly StatusOverrideInput
|
|
|
130
130
|
* disposition each as "the most recent non-expired override" carrying the
|
|
131
131
|
* relevant field, so callers pass the field-presence check as the predicate.
|
|
132
132
|
*/
|
|
133
|
-
declare function governingOverrideIndex(overrides: readonly StatusOverrideInput[], eligible: (index: number) => boolean, referenceTimestamp?: string): number;
|
|
133
|
+
export declare function governingOverrideIndex(overrides: readonly StatusOverrideInput[], eligible: (index: number) => boolean, referenceTimestamp?: string): number;
|
|
134
134
|
/**
|
|
135
135
|
* Index variant of {@link governingStatusOverride}: returns -1 when no
|
|
136
136
|
* override governs. Callers holding richer concrete override types use the
|
|
137
137
|
* index to recover their own object.
|
|
138
138
|
*/
|
|
139
|
-
declare function governingStatusOverrideIndex(overrides: readonly StatusOverrideInput[], referenceTimestamp?: string): number;
|
|
139
|
+
export declare function governingStatusOverrideIndex(overrides: readonly StatusOverrideInput[], referenceTimestamp?: string): number;
|
|
140
140
|
/** Neutral shape of a requirement for effective-status computation. */
|
|
141
141
|
interface EffectiveStatusInput {
|
|
142
142
|
impact: number;
|
|
@@ -156,7 +156,7 @@ interface EffectiveStatusInput {
|
|
|
156
156
|
* only sanctioned channel for status to diverge from the results is a
|
|
157
157
|
* governing override.
|
|
158
158
|
*/
|
|
159
|
-
declare function computeEffectiveStatus(input: EffectiveStatusInput, referenceTimestamp?: string): string;
|
|
159
|
+
export declare function computeEffectiveStatus(input: EffectiveStatusInput, referenceTimestamp?: string): string;
|
|
160
160
|
//#endregion
|
|
161
161
|
//#region src/cvss/index.d.ts
|
|
162
162
|
/**
|
|
@@ -191,7 +191,7 @@ interface CvssValidationResult {
|
|
|
191
191
|
* @param vector - CVSS vector string (e.g. "CVSS:3.1/AV:N/AC:L/...")
|
|
192
192
|
* @returns Parsed version + metric map
|
|
193
193
|
*/
|
|
194
|
-
declare function parseCvssVector(vector: string): ParsedCvssVector;
|
|
194
|
+
export declare function parseCvssVector(vector: string): ParsedCvssVector;
|
|
195
195
|
/**
|
|
196
196
|
* Validate a CVSS vector string against the FIRST grammar for its version.
|
|
197
197
|
*
|
|
@@ -209,7 +209,7 @@ declare function parseCvssVector(vector: string): ParsedCvssVector;
|
|
|
209
209
|
* @param version - Optional explicit version override (else inferred)
|
|
210
210
|
* @returns `{ valid, errors[] }` — never throws
|
|
211
211
|
*/
|
|
212
|
-
declare function validateCvssVector(vector: string, version?: string): CvssValidationResult;
|
|
212
|
+
export declare function validateCvssVector(vector: string, version?: string): CvssValidationResult;
|
|
213
213
|
/** A computed CVSS score. */
|
|
214
214
|
interface CvssScore {
|
|
215
215
|
/** CVSS major.minor version the score was computed under (currently always "3.1"). */
|
|
@@ -232,9 +232,9 @@ interface CvssScore {
|
|
|
232
232
|
* @throws if the version is not 3.1, a required base metric is missing, or any
|
|
233
233
|
* metric value is out of the 3.1 enum.
|
|
234
234
|
*/
|
|
235
|
-
declare function computeCvssScore(vector: string): CvssScore;
|
|
235
|
+
export declare function computeCvssScore(vector: string): CvssScore;
|
|
236
236
|
/** Parse a CVSS 4.0 vector and return its MacroVector string. */
|
|
237
|
-
declare function cvss40MacroVector(vector: string): string;
|
|
237
|
+
export declare function cvss40MacroVector(vector: string): string;
|
|
238
238
|
/**
|
|
239
239
|
* Compute the CVSS 4.0 score for a vector string, split into a Base score
|
|
240
240
|
* (`baseScore`, with Exploit Maturity stripped to its worst-case default E:A) and
|
|
@@ -245,7 +245,7 @@ declare function cvss40MacroVector(vector: string): string;
|
|
|
245
245
|
* @throws if the version is not 4.0, a required base metric is missing, or any
|
|
246
246
|
* metric value is out of the 4.0 enum.
|
|
247
247
|
*/
|
|
248
|
-
declare function computeCvss40Score(vector: string): CvssScore;
|
|
248
|
+
export declare function computeCvss40Score(vector: string): CvssScore;
|
|
249
249
|
//#endregion
|
|
250
250
|
//#region src/cpe/index.d.ts
|
|
251
251
|
/**
|
|
@@ -317,7 +317,7 @@ interface ParsedCpe {
|
|
|
317
317
|
* parseCpe('openssl:1.1.1k'); // null — no prefix
|
|
318
318
|
* ```
|
|
319
319
|
*/
|
|
320
|
-
declare function parseCpe(cpeUri: string): ParsedCpe | null;
|
|
320
|
+
export declare function parseCpe(cpeUri: string): ParsedCpe | null;
|
|
321
321
|
//#endregion
|
|
322
322
|
//#region src/purl/index.d.ts
|
|
323
323
|
/**
|
|
@@ -373,17 +373,29 @@ interface ParsedPurl {
|
|
|
373
373
|
* r?.qualifiers.get('arch'); // "x86_64"
|
|
374
374
|
* ```
|
|
375
375
|
*/
|
|
376
|
-
declare function parsePurl(purlStr: string): ParsedPurl | null;
|
|
376
|
+
export declare function parsePurl(purlStr: string): ParsedPurl | null;
|
|
377
377
|
//#endregion
|
|
378
378
|
//#region src/size/index.d.ts
|
|
379
|
-
/** Default maximum input size (
|
|
380
|
-
declare const DEFAULT_MAX_INPUT_SIZE: number;
|
|
379
|
+
/** Default maximum input size (256 MB), matching the Go DefaultMaxInputSize. */
|
|
380
|
+
export declare const DEFAULT_MAX_INPUT_SIZE: number;
|
|
381
381
|
/**
|
|
382
|
-
*
|
|
382
|
+
* setDefaultMaxInputSize sets the process-wide fallback used when a caller passes
|
|
383
|
+
* maxSize <= 0. A value <= 0 restores the built-in DEFAULT_MAX_INPUT_SIZE.
|
|
384
|
+
*/
|
|
385
|
+
export declare function setDefaultMaxInputSize(maxSize: number): void;
|
|
386
|
+
/**
|
|
387
|
+
* resolveMaxInputSize returns the effective byte limit for a caller-supplied
|
|
388
|
+
* maxSize: the explicit value when > 0, else the configured process default, else
|
|
389
|
+
* DEFAULT_MAX_INPUT_SIZE. An explicit limit always wins.
|
|
390
|
+
*/
|
|
391
|
+
export declare function resolveMaxInputSize(maxSize?: number): number;
|
|
392
|
+
/**
|
|
393
|
+
* validateInputSize throws if input exceeds the effective limit for maxSize (see
|
|
394
|
+
* resolveMaxInputSize; maxSize <= 0 uses the configured default or
|
|
383
395
|
* DEFAULT_MAX_INPUT_SIZE). Byte length is measured on the UTF-8 encoding for a
|
|
384
396
|
* string input, so it matches the Go []byte length for the same document.
|
|
385
397
|
*/
|
|
386
|
-
declare function validateInputSize(input: string | Uint8Array, maxSize?: number): void;
|
|
398
|
+
export declare function validateInputSize(input: string | Uint8Array, maxSize?: number): void;
|
|
387
399
|
//#endregion
|
|
388
|
-
export { type CpePart, type CsvBuildOptions, type CsvParseOptions, type CvssScore, type CvssValidationResult,
|
|
400
|
+
export { type CpePart, type CsvBuildOptions, type CsvParseOptions, type CvssScore, type CvssValidationResult, type EffectiveStatusInput, type HashAlgorithm, type HashEncoding, type HashOptions, type ParsedCpe, type ParsedCvssVector, type ParsedPurl, type StatusOverrideInput, type StatusSeverity, type StringifyOptions, buildCsv, buildCsvArray, buildXml, canonicalChecksum, canonicalJson, encodeBase64Utf8, extractColumn, extractColumn as extractCsvColumn, extractTextFromXml, findRows as findCsvRows, findRows, findValuesByKey as findJsonValues, findValuesByKey, findValuesByKey as findXmlValues, formatJsonNumber, formatTimestamp, formatTimestampSeconds, generateHash, hashObject, isValidCsv, isValidJSON, isValidXml, isXmlChar, normalizeHdfTimestamps, parseCsv, parseCsvArray, parseJSON, parseTimestamp, parseXml, parseXmlWithArrays, replaceHtmlTags, sanitizeCsvArray, sanitizeCsvObject, sanitizeCsvValue, sha256, sha512, stringifyJSON, stripHtml, trimUtcFraction, verifyHash, xmlSafeText };
|
|
389
401
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/severity/index.ts","../src/status/index.ts","../src/cvss/index.ts","../src/cpe/index.ts","../src/purl/index.ts","../src/size/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/severity/index.ts","../src/status/index.ts","../src/cvss/index.ts","../src/cpe/index.ts","../src/purl/index.ts","../src/size/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;wBAgCgB,iBAAiB;wBACjB,iBAAiB;wBACjB,iBAAiB;;;;;;;;;;wBAsBjB,4BACd,qCACA,SAAS,wBACT;;;;;;;;;wBAkBc,YAAY;;;;;;;wBAUZ,iBAAiB;wBACjB,iBAAiB;wBACjB,iBAAiB;;;;;;;;;;;;;;;;;;wBA2BjB,oBACd;;;;;;;;wBAsBc,kBAAkB;;;;;;;;;;;;qBC/HrB;;KASD,yBAAyB;;wBAMrB,WAAW;;;;;wBASX,YAAY;;;;;UAiBX;;EAEf;;EAEA;;EAEA;;;;;;;;wBAiBc,wBACd,oBAAoB,uBACpB,8BACC;;;;;;;;;wBAaa,uBACd,oBAAoB,uBACpB,WAAW,2BACX;;;;;;wBAmBc,6BACd,oBAAoB,uBACpB;;UAgBe;EACf;EACA;EACA,qBAAqB;;;;;;;;;;;;;;;wBAgBP,uBACd,OAAO,sBACP;;;;;;;;;;;;;;;UC1Ie;;EAEf;;EAEA,SAAS;;UAGM;EACf;EACA;;;;;;;;;;;;wBA2Ic,gBAAgB,iBAAiB;;;;;;;;;;;;;;;;;;wBA4DjC,mBACd,gBACA,mBACC;;UAsCc;;EAEf;;EAEA;;;;;EAKA;;;;;;;;;;;;wBAsDc,iBAAiB,iBAAiB;;wBA6KlC,kBAAkB;;;;;;;;;;;wBAiMlB,mBAAmB,iBAAiB;;;;;;;;;;;;;;;;;;KCrqBxC;;;;;;;;UASK;;EAEf;;EAEA,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAuEc,SAAS,iBAAiB;;;;;;;;;;;;;;;;;;;UC/FzB;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,YAAY;;EAEZ;;EAEA;;;;;;;;;;;;;;;;;;;;;wBAwBc,UAAU,kBAAkB;;;;qBCpD/B;;;;;wBAaG,uBAAuB;;;;;;wBASvB,oBAAoB;;;;;;;wBAYpB,kBAAkB,gBAAgB,YAAY"}
|
package/dist/index.js
CHANGED
|
@@ -1799,15 +1799,34 @@ function safeDecode(s) {
|
|
|
1799
1799
|
}
|
|
1800
1800
|
//#endregion
|
|
1801
1801
|
//#region src/size/index.ts
|
|
1802
|
-
/** Default maximum input size (
|
|
1803
|
-
const DEFAULT_MAX_INPUT_SIZE =
|
|
1802
|
+
/** Default maximum input size (256 MB), matching the Go DefaultMaxInputSize. */
|
|
1803
|
+
const DEFAULT_MAX_INPUT_SIZE = 268435456;
|
|
1804
|
+
let configuredMaxInputSize = 0;
|
|
1804
1805
|
/**
|
|
1805
|
-
*
|
|
1806
|
+
* setDefaultMaxInputSize sets the process-wide fallback used when a caller passes
|
|
1807
|
+
* maxSize <= 0. A value <= 0 restores the built-in DEFAULT_MAX_INPUT_SIZE.
|
|
1808
|
+
*/
|
|
1809
|
+
function setDefaultMaxInputSize(maxSize) {
|
|
1810
|
+
configuredMaxInputSize = maxSize > 0 ? maxSize : 0;
|
|
1811
|
+
}
|
|
1812
|
+
/**
|
|
1813
|
+
* resolveMaxInputSize returns the effective byte limit for a caller-supplied
|
|
1814
|
+
* maxSize: the explicit value when > 0, else the configured process default, else
|
|
1815
|
+
* DEFAULT_MAX_INPUT_SIZE. An explicit limit always wins.
|
|
1816
|
+
*/
|
|
1817
|
+
function resolveMaxInputSize(maxSize = 0) {
|
|
1818
|
+
if (maxSize > 0) return maxSize;
|
|
1819
|
+
if (configuredMaxInputSize > 0) return configuredMaxInputSize;
|
|
1820
|
+
return DEFAULT_MAX_INPUT_SIZE;
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1823
|
+
* validateInputSize throws if input exceeds the effective limit for maxSize (see
|
|
1824
|
+
* resolveMaxInputSize; maxSize <= 0 uses the configured default or
|
|
1806
1825
|
* DEFAULT_MAX_INPUT_SIZE). Byte length is measured on the UTF-8 encoding for a
|
|
1807
1826
|
* string input, so it matches the Go []byte length for the same document.
|
|
1808
1827
|
*/
|
|
1809
1828
|
function validateInputSize(input, maxSize = 0) {
|
|
1810
|
-
const limit = maxSize
|
|
1829
|
+
const limit = resolveMaxInputSize(maxSize);
|
|
1811
1830
|
if (typeof input !== "string") {
|
|
1812
1831
|
if (input.length > limit) throw tooLarge(limit, input.length);
|
|
1813
1832
|
return;
|
|
@@ -1839,6 +1858,6 @@ function utf8ByteLength(s) {
|
|
|
1839
1858
|
return bytes;
|
|
1840
1859
|
}
|
|
1841
1860
|
//#endregion
|
|
1842
|
-
export { DEFAULT_MAX_INPUT_SIZE, STATUS_SEVERITY_ORDER, buildCsv, buildCsvArray, buildXml, canonicalChecksum, canonicalJson, computeCvss40Score, computeCvssScore, computeEffectiveStatus, cvss40MacroVector, cvssScoreToSeverity, encodeBase64Utf8, extractColumn, extractColumn as extractCsvColumn, extractTextFromXml, findRows as findCsvRows, findRows, findValuesByKey as findJsonValues, findValuesByKey, findValuesByKey as findXmlValues, formatJsonNumber, formatTimestamp, formatTimestampSeconds, generateHash, governingOverrideIndex, governingStatusOverride, governingStatusOverrideIndex, hashObject, impactToSeverity, isUnratedSeverity, isValidCsv, isValidJSON, isValidXml, isXmlChar, normalizeHdfTimestamps, parseCpe, parseCsv, parseCsvArray, parseCvssVector, parseJSON, parsePurl, parseTimestamp, parseXml, parseXmlWithArrays, replaceHtmlTags, roundImpact, sanitizeCsvArray, sanitizeCsvObject, sanitizeCsvValue, severityToImpact, severityToImpactWithAliases, sha256, sha512, statusRank, stringifyJSON, stripHtml, trimUtcFraction, validateCvssVector, validateInputSize, verifyHash, worstStatus, xmlSafeText };
|
|
1861
|
+
export { DEFAULT_MAX_INPUT_SIZE, STATUS_SEVERITY_ORDER, buildCsv, buildCsvArray, buildXml, canonicalChecksum, canonicalJson, computeCvss40Score, computeCvssScore, computeEffectiveStatus, cvss40MacroVector, cvssScoreToSeverity, encodeBase64Utf8, extractColumn, extractColumn as extractCsvColumn, extractTextFromXml, findRows as findCsvRows, findRows, findValuesByKey as findJsonValues, findValuesByKey, findValuesByKey as findXmlValues, formatJsonNumber, formatTimestamp, formatTimestampSeconds, generateHash, governingOverrideIndex, governingStatusOverride, governingStatusOverrideIndex, hashObject, impactToSeverity, isUnratedSeverity, isValidCsv, isValidJSON, isValidXml, isXmlChar, normalizeHdfTimestamps, parseCpe, parseCsv, parseCsvArray, parseCvssVector, parseJSON, parsePurl, parseTimestamp, parseXml, parseXmlWithArrays, replaceHtmlTags, resolveMaxInputSize, roundImpact, sanitizeCsvArray, sanitizeCsvObject, sanitizeCsvValue, setDefaultMaxInputSize, severityToImpact, severityToImpactWithAliases, sha256, sha512, statusRank, stringifyJSON, stripHtml, trimUtcFraction, validateCvssVector, validateInputSize, verifyHash, worstStatus, xmlSafeText };
|
|
1843
1862
|
|
|
1844
1863
|
//# sourceMappingURL=index.js.map
|