@mitre/hdf-utilities 3.6.0 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @mitre/hdf-utilities
2
2
 
3
- Generic utility functions for working with common data formats (JSON, XML, CSV) and cryptographic hashing. These utilities provide safe parsing, building, and validation operations used throughout the HDF library ecosystem.
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
 
@@ -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 starting with =, +, -, @, |, or % with a single quote
75
- * to prevent Excel/LibreOffice from interpreting them as formulas.
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 { CsvBuildOptions, CsvParseOptions, buildCsv, buildCsvArray, extractColumn as extractCsvColumn, findRows as findCsvRows, isValidCsv, parseCsv, parseCsvArray, sanitizeCsvArray, sanitizeCsvObject, sanitizeCsvValue };
101
+ export { extractColumn as extractCsvColumn, findRows as findCsvRows };
97
102
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/csv/index.ts"],"mappings":";;;;;UAkBiB;EACf;EACA;EACA,mBAAmB,gBAAgB;EACnC;EACA;EACA;;;;;UAMe;EACf;EACA;EACA;EACA;;;;;;;;;iBAwEc,SAAS,IAAI,yBAC3B,aACA,UAAU,QAAQ,mBACjB;;;;;;;;iBAoDa,cACd,aACA,UAAU,QAAQ;;;;;;;;;;;iBAiCJ,SAAS,IAAI,yBAC3B,MAAM,KACN,UAAU,QAAQ;EAAqB;;;;;;;;;;;;iBA6GzB,cACd,kBACA,UAAU,QAAQ;EAAqB;;;;;;;iBA4BzB,WAAW;;;;;;;;;;iBA0BX,iBAAiB;;;;;;;iBAejB,iBAAiB;;;;;;;iBAUjB,kBAAkB,UAAU,yBAC1C,KAAK,IACJ"}
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] === "\"") if (inQuotes && i + 1 < csv.length && csv[i + 1] === "\"") i++;
42
- else inQuotes = !inQuotes;
43
- else if (csv[i] === "\n" && !inQuotes) row++;
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 starting with =, +, -, @, |, or % with a single quote
238
- * to prevent Excel/LibreOffice from interpreting them as formulas.
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
  /**
@@ -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":"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"}
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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"}
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/hash/index.ts"],"mappings":";;;;;;;;;KASY;;;;KAKA;;;;UAKK;;EAEf,YAAY;;EAEZ,WAAW;;;;;;;;;;;;;;;iBA0CS,aAAa,cAAc,UAAS,cAAmB;;;;;;;;;;;;;iBAoBvD,OAAO,eAAe;;;;;;;;;;;;;iBAgBtB,OAAO,eAAe;;;;;;;;;;;;;;;;iBAmBtB,WAAW,cAAc,UAAS,cAAmB;;;;;;;;;;;;;;;;iBAqBrD,WACpB,cACA,sBACA,UAAS,cACR"}
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 (50 MB), matching the Go DefaultMaxInputSize. */
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
- * validateInputSize throws if input exceeds maxSize bytes (maxSize <= 0 uses
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, DEFAULT_MAX_INPUT_SIZE, type EffectiveStatusInput, type HashAlgorithm, type HashEncoding, type HashOptions, type ParsedCpe, type ParsedCvssVector, type ParsedPurl, STATUS_SEVERITY_ORDER, type StatusOverrideInput, type StatusSeverity, type StringifyOptions, 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 };
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
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCgB,iBAAiB;iBACjB,iBAAiB;iBACjB,iBAAiB;;;;;;;;;;iBAsBjB,4BACd,qCACA,SAAS,wBACT;;;;;;;;;iBAkBc,YAAY;;;;;;;iBAUZ,iBAAiB;iBACjB,iBAAiB;iBACjB,iBAAiB;;;;;;;;;;;;;;;;;;iBA2BjB,oBACd;;;;;;;;iBAsBc,kBAAkB;;;;;;;;;;;;cC/HrB;;KASD,yBAAyB;;iBAMrB,WAAW;;;;;iBASX,YAAY;;;;;UAiBX;;EAEf;;EAEA;;EAEA;;;;;;;;iBAiBc,wBACd,oBAAoB,uBACpB,8BACC;;;;;;;;;iBAaa,uBACd,oBAAoB,uBACpB,WAAW,2BACX;;;;;;iBAmBc,6BACd,oBAAoB,uBACpB;;UAgBe;EACf;EACA;EACA,qBAAqB;;;;;;;;;;;;;;;iBAgBP,uBACd,OAAO,sBACP;;;;;;;;;;;;;;;UC1Ie;;EAEf;;EAEA,SAAS;;UAGM;EACf;EACA;;;;;;;;;;;;iBA2Ic,gBAAgB,iBAAiB;;;;;;;;;;;;;;;;;;iBA4DjC,mBACd,gBACA,mBACC;;UAsCc;;EAEf;;EAEA;;;;;EAKA;;;;;;;;;;;;iBAsDc,iBAAiB,iBAAiB;;iBA6KlC,kBAAkB;;;;;;;;;;;iBAiMlB,mBAAmB,iBAAiB;;;;;;;;;;;;;;;;;;KCrqBxC;;;;;;;;UASK;;EAEf;;EAEA,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuEc,SAAS,iBAAiB;;;;;;;;;;;;;;;;;;;UC/FzB;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,YAAY;;EAEZ;;EAEA;;;;;;;;;;;;;;;;;;;;;iBAwBc,UAAU,kBAAkB;;;;cCpD/B;;;;;;iBAOG,kBAAkB,gBAAgB,YAAY"}
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 (50 MB), matching the Go DefaultMaxInputSize. */
1803
- const DEFAULT_MAX_INPUT_SIZE = 50 * 1024 * 1024;
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
- * validateInputSize throws if input exceeds maxSize bytes (maxSize <= 0 uses
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 > 0 ? maxSize : DEFAULT_MAX_INPUT_SIZE;
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