@mitre/hdf-utilities 3.5.0 → 3.5.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/string/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2BgB,UAAU;;;;;;;;;;;;;;;;;;;;;iBAoCV,eAAe,YAAY;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/string/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2BgB,UAAU;;;;;;;;;;;;;;;;;;;;;iBAoCV,eAAe,YAAY;;;;;;;;;;iBAkC3B,gBAAgB;;;;;;;;;iBAYhB,gBAAgB,GAAG;;;;;;;;;;iBAanB,uBAAuB,GAAG;;;;;;;;;;;;;;;iBAqB1B,uBAAuB"}
|
package/dist/string/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/string/index.ts"],"sourcesContent":["/**\n * String manipulation utilities for HDF converters.\n *\n * These handle common operations on security tool output strings:\n * HTML stripping for STIG descriptions and SonarQube messages,\n * and multi-format timestamp parsing for tool output dates.\n */\n\n/**\n * Remove HTML tags from a string and normalize whitespace.\n *\n * Strips all HTML/XML tags, collapses multiple whitespace characters\n * into single spaces, and trims leading/trailing whitespace.\n *\n * For XML documents, use {@link extractTextFromXml} from the xml module instead.\n * This function is for inline HTML in non-XML strings (STIG descriptions,\n * SonarQube messages, etc.).\n *\n * @param html - String potentially containing HTML tags\n * @returns Plain text with tags removed and whitespace normalized\n *\n * @example\n * ```typescript\n * stripHtml('<p>hello</p> <b>world</b>'); // 'hello world'\n * stripHtml('no tags here'); // 'no tags here'\n * ```\n */\nexport function stripHtml(html: string): string {\n const stripped = html.replace(/<[^>]*>/g, ' ');\n return stripped.replace(/\\s+/g, ' ').trim();\n}\n\n// A bare ISO-8601 datetime with a time component but no timezone designator.\n// JavaScript's Date constructor interprets such a value as host-LOCAL time,\n// whereas Go's time.Parse (and HDF's canonical model) treats it as UTC. We\n// append 'Z' to force UTC so output is host-timezone-independent.\nconst ISO_DATETIME_NO_ZONE = /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?$/;\n\n// C ctime layout (\"Tue Mar 22 14:54:47 2022\", or \"Mon Jan 2 ...\" for a\n// single-digit day). Go's hdfutil.ParseTimestamp parses this layout as UTC;\n// V8's Date treats it as host-local, so we append a 'GMT' designator to match.\nconst CTIME_NO_ZONE = /^[A-Za-z]{3} [A-Za-z]{3} +\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4}$/;\n\n/**\n * Parse a timestamp string in various common formats into a Date.\n *\n * A zone-less ISO datetime (e.g. `2024-01-15T10:30:00`) is interpreted as\n * UTC — matching Go's `hdfutil.ParseTimestamp` — rather than host-local time,\n * so converter output does not depend on the machine's timezone.\n *\n * Returns `null` if the input is empty or cannot be parsed.\n *\n * @param s - Timestamp string to parse\n * @returns Parsed Date or null if unparseable\n *\n * @example\n * ```typescript\n * parseTimestamp('2024-01-15T10:30:00Z'); // Date object\n * parseTimestamp('2024-01-15T10:30:00'); // Date object (interpreted as UTC)\n * parseTimestamp('not a date'); // null\n * parseTimestamp(''); // null\n * ```\n */\nexport function parseTimestamp(s: string): Date | null {\n if (!s || s.trim().length === 0) {\n return null;\n }\n\n const trimmed = s.trim();\n let normalized = trimmed;\n if (ISO_DATETIME_NO_ZONE.test(trimmed)) {\n normalized = `${trimmed.replace(' ', 'T')}Z`;\n } else if (CTIME_NO_ZONE.test(trimmed)) {\n normalized = `${trimmed} GMT`;\n }\n\n const parsed = new Date(normalized);\n if (isNaN(parsed.getTime())) {\n return null;\n }\n\n return parsed;\n}\n\n/**\n * Trim trailing fractional-second zeros from an RFC3339 UTC timestamp string,\n * matching Go's RFC3339Nano marshaling (which drops trailing zeros and the\n * decimal point when the fraction is all zeros).\n *\n * @example\n * trimUtcFraction('2024-11-15T10:30:00.000Z'); // '2024-11-15T10:30:00Z'\n * trimUtcFraction('2024-01-01T00:00:00.120Z'); // '2024-01-01T00:00:00.12Z'\n */\nexport function trimUtcFraction(s: string): string {\n return s.replace(/\\.(\\d*?)0+Z$/, (_m, keep: string) => (keep ? `.${keep}Z` : 'Z'));\n}\n\n/**\n * Format a Date as HDF's canonical timestamp: RFC3339 in UTC with trailing\n * fractional-second zeros trimmed. Byte-identical to what the Go converters\n * emit for the same instant (a UTC `time.Time` marshaled as RFC3339Nano).\n *\n * @example\n * formatTimestamp(new Date('2024-11-15T10:30:00Z')); // '2024-11-15T10:30:00Z'\n */\nexport function formatTimestamp(d: Date): string {\n return trimUtcFraction(d.toISOString());\n}\n\n/**\n * Format a Date as RFC3339 in UTC truncated to whole seconds (no fractional\n * part). For exporters whose target format conventionally uses whole-second\n * timestamps (CSAF, OpenVEX, CycloneDX). Use {@link formatTimestamp} for\n * canonical HDF output instead — it preserves sub-second precision.\n *\n * @example\n * formatTimestampSeconds(new Date('2024-11-15T10:30:00.123Z')); // '2024-11-15T10:30:00Z'\n */\nexport function formatTimestampSeconds(d: Date): string {\n return d.toISOString().replace(/\\.\\d+Z$/, 'Z');\n}\n\n/** A JSON string whose entire value is an ISO-8601 date-time with no zone designator. */\nconst BARE_ISO_IN_JSON = /\"(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?)\"/g;\n\n/**\n * Rewrite zone-less timestamps in a raw HDF document to HDF's canonical\n * trimmed-UTC RFC3339 form, before the document is parsed.\n *\n * Real HDF carries them — InSpec emits startTime with no offset. Go's schema\n * types decode date-time fields into time.Time, whose decoder demands an offset\n * and hard-fails, so Go rejected documents TypeScript read happily; and where\n * TypeScript did read them, it passed the zone-less value straight through to\n * its output, which is not canonical HDF. Normalizing on ingest in both\n * languages means they accept the same real-world files and emit the same bytes,\n * reading a zone-less value as UTC exactly as parseTimestamp already does.\n *\n * Mirrored by NormalizeHDFTimestamps in hdf-utilities/go/timestamp.go.\n */\nexport function normalizeHdfTimestamps(json: string): string {\n return json.replace(BARE_ISO_IN_JSON, (match, raw: string) => {\n const parsed = parseTimestamp(raw);\n if (!parsed) return match;\n return `\"${trimUtcFraction(parsed.toISOString())}\"`;\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,UAAU,MAAsB;CAE9C,OADiB,KAAK,QAAQ,YAAY,GAC5B,CAAC,CAAC,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;AAC5C;AAMA,MAAM,uBAAuB;AAK7B,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;AAsBtB,SAAgB,eAAe,GAAwB;CACrD,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,WAAW,GAC5B,OAAO;CAGT,MAAM,UAAU,EAAE,KAAK;CACvB,IAAI,aAAa;CACjB,IAAI,qBAAqB,KAAK,OAAO,GACnC,aAAa,GAAG,QAAQ,QAAQ,KAAK,GAAG,EAAE;MACrC,IAAI,cAAc,KAAK,OAAO,GACnC,aAAa,GAAG,QAAQ;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/string/index.ts"],"sourcesContent":["/**\n * String manipulation utilities for HDF converters.\n *\n * These handle common operations on security tool output strings:\n * HTML stripping for STIG descriptions and SonarQube messages,\n * and multi-format timestamp parsing for tool output dates.\n */\n\n/**\n * Remove HTML tags from a string and normalize whitespace.\n *\n * Strips all HTML/XML tags, collapses multiple whitespace characters\n * into single spaces, and trims leading/trailing whitespace.\n *\n * For XML documents, use {@link extractTextFromXml} from the xml module instead.\n * This function is for inline HTML in non-XML strings (STIG descriptions,\n * SonarQube messages, etc.).\n *\n * @param html - String potentially containing HTML tags\n * @returns Plain text with tags removed and whitespace normalized\n *\n * @example\n * ```typescript\n * stripHtml('<p>hello</p> <b>world</b>'); // 'hello world'\n * stripHtml('no tags here'); // 'no tags here'\n * ```\n */\nexport function stripHtml(html: string): string {\n const stripped = html.replace(/<[^>]*>/g, ' ');\n return stripped.replace(/\\s+/g, ' ').trim();\n}\n\n// A bare ISO-8601 datetime with a time component but no timezone designator.\n// JavaScript's Date constructor interprets such a value as host-LOCAL time,\n// whereas Go's time.Parse (and HDF's canonical model) treats it as UTC. We\n// append 'Z' to force UTC so output is host-timezone-independent.\nconst ISO_DATETIME_NO_ZONE = /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}(:\\d{2})?(\\.\\d+)?$/;\n\n// C ctime layout (\"Tue Mar 22 14:54:47 2022\", or \"Mon Jan 2 ...\" for a\n// single-digit day). Go's hdfutil.ParseTimestamp parses this layout as UTC;\n// V8's Date treats it as host-local, so we append a 'GMT' designator to match.\nconst CTIME_NO_ZONE = /^[A-Za-z]{3} [A-Za-z]{3} +\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4}$/;\n\n/**\n * Parse a timestamp string in various common formats into a Date.\n *\n * A zone-less ISO datetime (e.g. `2024-01-15T10:30:00`) is interpreted as\n * UTC — matching Go's `hdfutil.ParseTimestamp` — rather than host-local time,\n * so converter output does not depend on the machine's timezone.\n *\n * Returns `null` if the input is empty or cannot be parsed.\n *\n * @param s - Timestamp string to parse\n * @returns Parsed Date or null if unparseable\n *\n * @example\n * ```typescript\n * parseTimestamp('2024-01-15T10:30:00Z'); // Date object\n * parseTimestamp('2024-01-15T10:30:00'); // Date object (interpreted as UTC)\n * parseTimestamp('not a date'); // null\n * parseTimestamp(''); // null\n * ```\n */\nexport function parseTimestamp(s: string): Date | null {\n if (!s || s.trim().length === 0) {\n return null;\n }\n\n const trimmed = s.trim();\n let normalized = trimmed;\n if (ISO_DATETIME_NO_ZONE.test(trimmed)) {\n normalized = `${trimmed.replace(' ', 'T')}Z`;\n } else if (CTIME_NO_ZONE.test(trimmed)) {\n normalized = `${trimmed} GMT`;\n }\n\n // parseTimestamp IS the sanctioned helper the guard routes callers to: it\n // normalizes zone-less input to UTC above before constructing the Date, so\n // this is not the host-local footgun the guard prevents.\n // eslint-disable-next-line no-restricted-syntax -- sanctioned parse-helper implementation\n const parsed = new Date(normalized);\n if (isNaN(parsed.getTime())) {\n return null;\n }\n\n return parsed;\n}\n\n/**\n * Trim trailing fractional-second zeros from an RFC3339 UTC timestamp string,\n * matching Go's RFC3339Nano marshaling (which drops trailing zeros and the\n * decimal point when the fraction is all zeros).\n *\n * @example\n * trimUtcFraction('2024-11-15T10:30:00.000Z'); // '2024-11-15T10:30:00Z'\n * trimUtcFraction('2024-01-01T00:00:00.120Z'); // '2024-01-01T00:00:00.12Z'\n */\nexport function trimUtcFraction(s: string): string {\n return s.replace(/\\.(\\d*?)0+Z$/, (_m, keep: string) => (keep ? `.${keep}Z` : 'Z'));\n}\n\n/**\n * Format a Date as HDF's canonical timestamp: RFC3339 in UTC with trailing\n * fractional-second zeros trimmed. Byte-identical to what the Go converters\n * emit for the same instant (a UTC `time.Time` marshaled as RFC3339Nano).\n *\n * @example\n * formatTimestamp(new Date('2024-11-15T10:30:00Z')); // '2024-11-15T10:30:00Z'\n */\nexport function formatTimestamp(d: Date): string {\n return trimUtcFraction(d.toISOString());\n}\n\n/**\n * Format a Date as RFC3339 in UTC truncated to whole seconds (no fractional\n * part). For exporters whose target format conventionally uses whole-second\n * timestamps (CSAF, OpenVEX, CycloneDX). Use {@link formatTimestamp} for\n * canonical HDF output instead — it preserves sub-second precision.\n *\n * @example\n * formatTimestampSeconds(new Date('2024-11-15T10:30:00.123Z')); // '2024-11-15T10:30:00Z'\n */\nexport function formatTimestampSeconds(d: Date): string {\n return d.toISOString().replace(/\\.\\d+Z$/, 'Z');\n}\n\n/** A JSON string whose entire value is an ISO-8601 date-time with no zone designator. */\nconst BARE_ISO_IN_JSON = /\"(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?)\"/g;\n\n/**\n * Rewrite zone-less timestamps in a raw HDF document to HDF's canonical\n * trimmed-UTC RFC3339 form, before the document is parsed.\n *\n * Real HDF carries them — InSpec emits startTime with no offset. Go's schema\n * types decode date-time fields into time.Time, whose decoder demands an offset\n * and hard-fails, so Go rejected documents TypeScript read happily; and where\n * TypeScript did read them, it passed the zone-less value straight through to\n * its output, which is not canonical HDF. Normalizing on ingest in both\n * languages means they accept the same real-world files and emit the same bytes,\n * reading a zone-less value as UTC exactly as parseTimestamp already does.\n *\n * Mirrored by NormalizeHDFTimestamps in hdf-utilities/go/timestamp.go.\n */\nexport function normalizeHdfTimestamps(json: string): string {\n return json.replace(BARE_ISO_IN_JSON, (match, raw: string) => {\n const parsed = parseTimestamp(raw);\n if (!parsed) return match;\n return `\"${trimUtcFraction(parsed.toISOString())}\"`;\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,UAAU,MAAsB;CAE9C,OADiB,KAAK,QAAQ,YAAY,GAC5B,CAAC,CAAC,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;AAC5C;AAMA,MAAM,uBAAuB;AAK7B,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;AAsBtB,SAAgB,eAAe,GAAwB;CACrD,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,WAAW,GAC5B,OAAO;CAGT,MAAM,UAAU,EAAE,KAAK;CACvB,IAAI,aAAa;CACjB,IAAI,qBAAqB,KAAK,OAAO,GACnC,aAAa,GAAG,QAAQ,QAAQ,KAAK,GAAG,EAAE;MACrC,IAAI,cAAc,KAAK,OAAO,GACnC,aAAa,GAAG,QAAQ;CAO1B,MAAM,SAAS,IAAI,KAAK,UAAU;CAClC,IAAI,MAAM,OAAO,QAAQ,CAAC,GACxB,OAAO;CAGT,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,gBAAgB,GAAmB;CACjD,OAAO,EAAE,QAAQ,iBAAiB,IAAI,SAAkB,OAAO,IAAI,KAAK,KAAK,GAAI;AACnF;;;;;;;;;AAUA,SAAgB,gBAAgB,GAAiB;CAC/C,OAAO,gBAAgB,EAAE,YAAY,CAAC;AACxC;;;;;;;;;;AAWA,SAAgB,uBAAuB,GAAiB;CACtD,OAAO,EAAE,YAAY,CAAC,CAAC,QAAQ,WAAW,GAAG;AAC/C;;AAGA,MAAM,mBAAmB;;;;;;;;;;;;;;;AAgBzB,SAAgB,uBAAuB,MAAsB;CAC3D,OAAO,KAAK,QAAQ,mBAAmB,OAAO,QAAgB;EAC5D,MAAM,SAAS,eAAe,GAAG;EACjC,IAAI,CAAC,QAAQ,OAAO;EACpB,OAAO,IAAI,gBAAgB,OAAO,YAAY,CAAC,EAAE;CACnD,CAAC;AACH"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mitre/hdf-utilities",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.1",
|
|
4
4
|
"description": "Utility functions for HDF libraries (JSON parsing, validation helpers)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -72,11 +72,12 @@
|
|
|
72
72
|
"clean": "rimraf dist",
|
|
73
73
|
"test": "pnpm run test:ts",
|
|
74
74
|
"test:ts": "vitest run",
|
|
75
|
-
"test:go": "
|
|
75
|
+
"test:go": "cd go && go test ./...",
|
|
76
76
|
"test:watch": "vitest",
|
|
77
77
|
"test:coverage": "vitest run --coverage",
|
|
78
78
|
"type-check": "tsc --noEmit",
|
|
79
79
|
"lint": "eslint src test",
|
|
80
|
+
"lint:go": "cd go && golangci-lint run",
|
|
80
81
|
"lint:fix": "eslint src test --fix"
|
|
81
82
|
}
|
|
82
83
|
}
|