@mitre/inspec-objects 2.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,20 +29,19 @@ function createDiffMarkdown(diff) {
29
29
  updatedTitles: [],
30
30
  updatedDescriptions: [],
31
31
  };
32
- Object.entries(diff.ignoreFormattingDiff.renamedControlIDs).forEach(([oldId, newId]) => {
32
+ for (const [oldId, newId] of Object.entries(diff.ignoreFormattingDiff.renamedControlIDs)) {
33
33
  renderableDiffData.hasRenamedControls = true;
34
34
  renderableDiffData.renamedControls.push({
35
35
  oldId: oldId,
36
36
  newId: newId,
37
37
  });
38
- });
39
- Object.entries(diff.rawDiff.changedControls).forEach(([id, controlDiff]) => {
40
- var _a, _b;
41
- if ((_a = controlDiff.descs) === null || _a === void 0 ? void 0 : _a.check) {
38
+ }
39
+ for (const [id, controlDiff] of Object.entries(diff.rawDiff.changedControls)) {
40
+ if (controlDiff.descs?.check) {
42
41
  const oldCheck = lodash_1.default.get(controlDiff.descs.check, '__old', 'undefined');
43
42
  const newCheck = lodash_1.default.get(controlDiff.descs.check, '__new', 'undefined');
44
- if (oldCheck.replace(/\n/g, '').replace(/\W/g, '') !==
45
- newCheck.replace(/\n/g, '').replace(/\W/g, '')) {
43
+ if (oldCheck.replaceAll('\n', '').replaceAll(/\W/g, '')
44
+ !== newCheck.replaceAll('\n', '').replaceAll(/\W/g, '')) {
46
45
  renderableDiffData.updatedChecks.push({
47
46
  id: id,
48
47
  old: oldCheck,
@@ -50,11 +49,11 @@ function createDiffMarkdown(diff) {
50
49
  });
51
50
  }
52
51
  }
53
- if ((_b = controlDiff.descs) === null || _b === void 0 ? void 0 : _b.fix) {
52
+ if (controlDiff.descs?.fix) {
54
53
  const oldFix = lodash_1.default.get(controlDiff.descs.fix, '__old', 'undefined');
55
54
  const newFix = lodash_1.default.get(controlDiff.descs.fix, '__new', 'undefined');
56
- if (oldFix.replace(/\n/g, '').replace(/\W/g, '') !==
57
- newFix.replace(/\n/g, '').replace(/\W/g, '')) {
55
+ if (oldFix.replaceAll('\n', '').replaceAll(/\W/g, '')
56
+ !== newFix.replaceAll('\n', '').replaceAll(/\W/g, '')) {
58
57
  renderableDiffData.updatedFixes.push({
59
58
  id: id,
60
59
  old: oldFix,
@@ -95,7 +94,7 @@ function createDiffMarkdown(diff) {
95
94
  });
96
95
  }
97
96
  }
98
- });
97
+ }
99
98
  // Render output
100
99
  return mustache_1.default.render(automatticUpdateTemplate_json_1.default.data, renderableDiffData);
101
100
  }
@@ -25,7 +25,7 @@ function removeNewlines(control) {
25
25
  }
26
26
  return lodash_1.default.mapValues(control, (value) => {
27
27
  if (typeof value === 'string') {
28
- return value.replace(/\n/g, '{{{{newlineHERE}}}}').trim();
28
+ return value.replaceAll('\n', '{{{{newlineHERE}}}}').trim();
29
29
  }
30
30
  else if (typeof value === 'object' && value !== null) {
31
31
  return removeNewlines(value);
@@ -57,10 +57,10 @@ function ignoreFormattingDiff(diffData) {
57
57
  return lodash_1.default.transform(diffData, (result, diffValue, key) => {
58
58
  if (lodash_1.default.has(diffValue, '__new')) {
59
59
  // Remove any trailing space
60
- if (typeof lodash_1.default.get(diffValue, '__new') === 'string' &&
61
- typeof lodash_1.default.get(diffValue, '__old') === 'string') {
62
- if ((0, global_1.removeWhitespace)(lodash_1.default.get(diffValue, '__new', 'undefined')) !==
63
- (0, global_1.removeWhitespace)(lodash_1.default.get(diffValue, '__old', 'undefined'))) {
60
+ if (typeof lodash_1.default.get(diffValue, '__new') === 'string'
61
+ && typeof lodash_1.default.get(diffValue, '__old') === 'string') {
62
+ if ((0, global_1.removeWhitespace)(lodash_1.default.get(diffValue, '__new', 'undefined'))
63
+ !== (0, global_1.removeWhitespace)(lodash_1.default.get(diffValue, '__old', 'undefined'))) {
64
64
  lodash_1.default.set(result, key, lodash_1.default.get(diffValue, '__new'));
65
65
  }
66
66
  }
@@ -70,14 +70,14 @@ function ignoreFormattingDiff(diffData) {
70
70
  }
71
71
  else if (Array.isArray(diffValue)) {
72
72
  result[key] = diffValue
73
- .map((value) => value[0] === '+' && value[1])
74
- .filter((value) => value);
73
+ .map(value => value[0] === '+' && value[1])
74
+ .filter(Boolean);
75
75
  }
76
76
  else if (typeof diffValue === 'object') {
77
77
  result[key] = ignoreFormattingDiff(diffValue);
78
78
  }
79
79
  else if (key.endsWith('__deleted')) {
80
- return undefined;
80
+ return;
81
81
  }
82
82
  else {
83
83
  result[key] = diffValue;
@@ -96,7 +96,6 @@ function ignoreFormattingDiff(diffData) {
96
96
  * - `rawDiff`: The raw profile differences.
97
97
  */
98
98
  function diffProfile(fromProfile, toProfile, logger) {
99
- var _a;
100
99
  logger.info(`Processing diff between: ${fromProfile.name}(v:${fromProfile.version}) and: ${toProfile.name}(v:${toProfile.version})`);
101
100
  const profileDiff = {
102
101
  addedControlIDs: [],
@@ -114,72 +113,71 @@ function diffProfile(fromProfile, toProfile, logger) {
114
113
  addedControls: {},
115
114
  changedControls: {},
116
115
  };
117
- const fromControlIDs = fromProfile.controls.map((control) => control.id).sort();
118
- const toControlIDs = toProfile.controls.map((control) => control.id).sort();
116
+ const fromControlIDs = fromProfile.controls.map(control => control.id).toSorted();
117
+ const toControlIDs = toProfile.controls.map(control => control.id).toSorted();
119
118
  // Find new controls
120
- const controlIDDiff = (_a = (0, json_diff_1.diff)(fromControlIDs, toControlIDs)) === null || _a === void 0 ? void 0 : _a.filter((item) => !(item.length === 1 && item[0] === ' '));
119
+ const controlIDDiff = (0, json_diff_1.diff)(fromControlIDs, toControlIDs)?.filter((item) => !(item.length === 1 && item[0] === ' '));
121
120
  // Contains the new IDs
122
121
  const changedControlIds = [];
123
122
  // a diffValue has an entry for both what was subtracted ("-")
124
123
  // and what was added ("+") -- need to handle both
125
- controlIDDiff === null || controlIDDiff === void 0 ? void 0 : controlIDDiff.forEach((diffValue) => {
126
- if (diffValue[0] === '-') {
127
- const existingControl = fromProfile.controls.find((control) => control.id === diffValue[1]);
128
- // Check if the control has been given a new ID
129
- if (existingControl) {
130
- const newControl = (0, update_1.findUpdatedControlByAllIdentifiers)(existingControl, toProfile.controls);
131
- if (newControl && newControl.id !== existingControl.id) {
132
- profileDiff.renamedControlIDs[existingControl.id] = newControl.id;
133
- originalDiff.renamedControlIDs[existingControl.id] = newControl.id;
134
- changedControlIds.push(newControl.id.toLowerCase());
135
- const controlDiff = lodash_1.default.omit((0, json_diff_1.diff)(existingControl, newControl), 'code__deleted');
136
- // logger.info("CONTROL DIFF:" + JSON.stringify(controlDiff, null, 2))
137
- const renamedControlIgnoredFormatting = ignoreFormattingDiff(controlDiff);
138
- profileDiff.changedControls[newControl.id] = renamedControlIgnoredFormatting;
139
- profileDiff.changedControlIDs.push(newControl.id);
140
- originalDiff.changedControls[newControl.id] = controlDiff;
141
- originalDiff.changedControlIDs.push(newControl.id);
142
- logger.verbose(`Control ${existingControl.id} has been updated to ${newControl.id}`);
143
- logger.debug(`Updated control content: ${JSON.stringify(renamedControlIgnoredFormatting)}`);
124
+ if (controlIDDiff)
125
+ for (const diffValue of controlIDDiff) {
126
+ if (diffValue[0] === '-') {
127
+ const existingControl = fromProfile.controls.find(control => control.id === diffValue[1]);
128
+ // Check if the control has been given a new ID
129
+ if (existingControl) {
130
+ const newControl = (0, update_1.findUpdatedControlByAllIdentifiers)(existingControl, toProfile.controls);
131
+ if (newControl && newControl.id !== existingControl.id) {
132
+ profileDiff.renamedControlIDs[existingControl.id] = newControl.id;
133
+ originalDiff.renamedControlIDs[existingControl.id] = newControl.id;
134
+ changedControlIds.push(newControl.id.toLowerCase());
135
+ const controlDiff = lodash_1.default.omit((0, json_diff_1.diff)(existingControl, newControl), 'code__deleted');
136
+ // logger.info("CONTROL DIFF:" + JSON.stringify(controlDiff, null, 2))
137
+ const renamedControlIgnoredFormatting = ignoreFormattingDiff(controlDiff);
138
+ profileDiff.changedControls[newControl.id] = renamedControlIgnoredFormatting;
139
+ profileDiff.changedControlIDs.push(newControl.id);
140
+ originalDiff.changedControls[newControl.id] = controlDiff;
141
+ originalDiff.changedControlIDs.push(newControl.id);
142
+ logger.verbose(`Control ${existingControl.id} has been updated to ${newControl.id}`);
143
+ logger.debug(`Updated control content: ${JSON.stringify(renamedControlIgnoredFormatting)}`);
144
+ }
145
+ else {
146
+ profileDiff.removedControlIDs.push(diffValue[1]);
147
+ originalDiff.removedControlIDs.push(diffValue[1]);
148
+ }
144
149
  }
145
150
  else {
146
- profileDiff.removedControlIDs.push(diffValue[1]);
147
- originalDiff.removedControlIDs.push(diffValue[1]);
151
+ logger.error(`Unable to find existing control ${diffValue[1]}`);
148
152
  }
149
153
  }
150
- else {
151
- logger.error(`Unable to find existing control ${diffValue[1]}`);
154
+ else if (diffValue[0] === '+' && !changedControlIds.includes(diffValue[1].toLowerCase()) && diffValue[1]) {
155
+ logger.info(JSON.stringify(diffValue));
156
+ logger.info(JSON.stringify(changedControlIds));
157
+ profileDiff.addedControlIDs.push(diffValue[1]);
158
+ originalDiff.addedControlIDs.push(diffValue[1]);
152
159
  }
153
160
  }
154
- else if (diffValue[0] === '+' && !changedControlIds.includes(diffValue[1].toLowerCase()) && diffValue[1]) {
155
- logger.info(JSON.stringify(diffValue));
156
- logger.info(JSON.stringify(changedControlIds));
157
- profileDiff.addedControlIDs.push(diffValue[1]);
158
- originalDiff.addedControlIDs.push(diffValue[1]);
159
- }
160
- });
161
161
  // take the list of renamed controls out of the list of added controls
162
162
  // (a control is not "new" if it was renamed)
163
163
  profileDiff.addedControlIDs = profileDiff.addedControlIDs.filter((item) => !Object.values(profileDiff.renamedControlIDs).includes(item));
164
164
  originalDiff.addedControlIDs = originalDiff.addedControlIDs.filter((item) => !Object.values(originalDiff.renamedControlIDs).includes(item));
165
165
  // Add new controls to addedControls
166
- profileDiff.addedControlIDs.forEach((addedControl) => {
167
- const newControl = toProfile.controls.find((control) => addedControl === control.id);
166
+ for (const addedControl of profileDiff.addedControlIDs) {
167
+ const newControl = toProfile.controls.find(control => addedControl === control.id);
168
168
  if (newControl && !profileDiff.changedControls[newControl.id]) {
169
169
  profileDiff.addedControls[addedControl] = newControl;
170
170
  originalDiff.addedControls[addedControl] = newControl;
171
171
  }
172
- });
172
+ }
173
173
  // Find changed controls
174
174
  for (const fromControl of fromProfile.controls) {
175
- const toControl = toProfile.controls.find((control) => control.id === fromControl.id);
175
+ const toControl = toProfile.controls.find(control => control.id === fromControl.id);
176
176
  if (toControl) {
177
177
  const controlDiff = lodash_1.default.omit((0, json_diff_1.diff)(fromControl, toControl), 'code__deleted');
178
178
  if (controlDiff) {
179
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
180
179
  profileDiff.changedControls[toControl.id] = ignoreFormattingDiff(controlDiff);
181
180
  profileDiff.changedControlIDs.push(toControl.id);
182
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
183
181
  originalDiff.changedControls[toControl.id] = controlDiff;
184
182
  originalDiff.changedControlIDs.push(toControl.id);
185
183
  }
@@ -56,7 +56,7 @@ function wrap(s, lineLength = 80) {
56
56
  * @returns The unformatted string with newline characters and excessive whitespace removed.
57
57
  */
58
58
  function unformatText(s) {
59
- return s.replace(/\n/g, ' ').replace(/\\n/g, ' ').replace(/( +|\t)/g, ' ');
59
+ return s.replaceAll('\n', ' ').replaceAll(String.raw `\n`, ' ').replaceAll(/( +|\t)/g, ' ');
60
60
  }
61
61
  /**
62
62
  * Removes all whitespace characters from the given input string.
@@ -65,7 +65,7 @@ function unformatText(s) {
65
65
  * @returns A new string with all whitespace characters removed.
66
66
  */
67
67
  function removeWhitespace(input) {
68
- return input.replace(/\s/gi, '');
68
+ return input.replaceAll(/\s/gi, '');
69
69
  }
70
70
  /**
71
71
  * Escapes backslashes that precede closing parentheses in a given string.
@@ -79,7 +79,7 @@ function removeWhitespace(input) {
79
79
  * @returns A new string with the specified backslashes escaped.
80
80
  */
81
81
  const escapeSpecialCaseBackslashes = (s) => {
82
- return s.replace(/\\\)/g, '\\\\)');
82
+ return s.replaceAll(String.raw `\)`, String.raw `\\)`);
83
83
  };
84
84
  /**
85
85
  * Escapes single quotes and backslashes in a given string.
@@ -91,7 +91,7 @@ const escapeSpecialCaseBackslashes = (s) => {
91
91
  * @returns The escaped string with single quotes and backslashes properly escaped.
92
92
  */
93
93
  const escapeSingleQuotes = (s) => {
94
- return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
94
+ return s.replaceAll('\\', '\\\\').replaceAll('\'', String.raw `\'`);
95
95
  };
96
96
  /**
97
97
  * Escapes backslashes and double quotes in a given string.
@@ -103,7 +103,7 @@ const escapeSingleQuotes = (s) => {
103
103
  * @returns The escaped string with backslashes and double quotes properly escaped.
104
104
  */
105
105
  const escapeDoubleQuotes = (s) => {
106
- return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
106
+ return s.replaceAll('\\', '\\\\').replaceAll('"', String.raw `\"`);
107
107
  };
108
108
  /**
109
109
  * Escapes quotes in a given string based on the presence of single and double quotes.
@@ -133,7 +133,7 @@ function escapeQuotes(s) {
133
133
  * @returns The modified string with placeholders replaced by newline characters.
134
134
  */
135
135
  function removeNewlinePlaceholders(s) {
136
- return s.replace(/\{\{\{\{newlineHERE\}\}\}\}/g, '\n');
136
+ return s.replaceAll('{{{{newlineHERE}}}}', '\n');
137
137
  }
138
138
  /**
139
139
  * Retrieves the value from the first path in the provided paths array that exists in the given object.
@@ -144,7 +144,7 @@ function removeNewlinePlaceholders(s) {
144
144
  * @throws Will throw an error if none of the paths exist in the object.
145
145
  */
146
146
  function getFirstPath(object, paths) {
147
- const index = lodash_1.default.findIndex(paths, (p) => hasPath(object, p));
147
+ const index = lodash_1.default.findIndex(paths, p => hasPath(object, p));
148
148
  if (index === -1) {
149
149
  throw new Error(`Attestation is missing one of these paths: ${paths.join(', ')}`);
150
150
  }
@@ -160,12 +160,6 @@ function getFirstPath(object, paths) {
160
160
  * @returns `true` if any of the specified paths exist in the object, otherwise `false`.
161
161
  */
162
162
  function hasPath(file, path) {
163
- let pathArray;
164
- if (typeof path === 'string') {
165
- pathArray = [path];
166
- }
167
- else {
168
- pathArray = path;
169
- }
170
- return lodash_1.default.some(pathArray, (p) => lodash_1.default.has(file, p));
163
+ const pathArray = lodash_1.default.isString(path) ? [path] : path;
164
+ return lodash_1.default.some(pathArray, p => lodash_1.default.has(file, p));
171
165
  }
@@ -13,6 +13,6 @@ function createWinstonLogger(mapperName, level = 'debug') {
13
13
  // Using the ANSI escape code sequence initiator (\xb[) to change output colors
14
14
  // Colors used are: 33m (yellow) and 34m (blue)
15
15
  // \x1b[0m : Resets the color settings to the default
16
- info => `\x1b[33m[${[info.timestamp]} -> ${mapperName}]:\x1b[0m \x1b[34m${info.message}\x1b[0m`)),
16
+ info => `\u001B[33m[${[info.timestamp]} -> ${mapperName}]:\u001B[0m \u001B[34m${info.message}\u001B[0m`)),
17
17
  });
18
18
  }
@@ -14,7 +14,7 @@ const diff_1 = require("./diff");
14
14
  const control_1 = tslib_1.__importDefault(require("../objects/control"));
15
15
  const profile_1 = tslib_1.__importDefault(require("../objects/profile"));
16
16
  const xccdf_1 = require("../parsers/xccdf");
17
- const diffMarkdown_1 = require("./diffMarkdown");
17
+ const diff_markdown_1 = require("./diff-markdown");
18
18
  /**
19
19
  * Projects values from the source object onto the destination object,
20
20
  * updating the destination object in place.
@@ -50,7 +50,7 @@ function projectValuesOntoExistingObj(dst, src, currentPath = '') {
50
50
  lodash_1.default.set(dst, updatedValue, src[updatedValue]);
51
51
  }
52
52
  else if (Array.isArray(src[updatedValue])) {
53
- const uniqueArrayValues = [...new Set(lodash_1.default.get(dst, updatedValue, []).concat(src[updatedValue]))];
53
+ const uniqueArrayValues = lodash_1.default.uniq([...lodash_1.default.get(dst, updatedValue, []), ...src[updatedValue]]);
54
54
  lodash_1.default.set(dst, updatedValue, uniqueArrayValues);
55
55
  }
56
56
  }
@@ -98,12 +98,11 @@ function getRangesForLines(text) {
98
98
  const rangeStack = [];
99
99
  const ranges = [];
100
100
  const lines = text.split('\n');
101
- for (let i = 0; i < lines.length; i++) {
101
+ for (const [i, line] of lines.entries()) {
102
102
  let j = 0;
103
- while (j < lines[i].length) {
104
- const line = lines[i];
103
+ while (j < line.length) {
105
104
  let char = line[j];
106
- const isEmptyStack = (stack.length == 0);
105
+ const isEmptyStack = (stack.length === 0);
107
106
  const isNotEmptyStack = (stack.length > 0);
108
107
  const isQuoteChar = quotes.includes(char);
109
108
  const isNotEscapeChar = ((j == 0) || (j > 0 && line[j - 1] != '\\'));
@@ -141,20 +140,20 @@ function getRangesForLines(text) {
141
140
  }
142
141
  char = line[j];
143
142
  baseCondition = (isNotEmptyStack && isNotEscapeChar);
144
- const delimiterCondition = (baseCondition && Object.keys(stringDelimiters).includes(stack[stack.length - 1]));
145
- const delimiterPushCondition = (delimiterCondition && (stack[stack.length - 1] == char));
146
- const delimiterPopCondition = (delimiterCondition && (stringDelimiters[stack[stack.length - 1]] == char));
147
- const basePopCondition = (baseCondition && (stack[stack.length - 1] == char) && !Object.keys(stringDelimiters).includes(char));
143
+ const delimiterCondition = (baseCondition && Object.keys(stringDelimiters).includes(stack.at(-1)));
144
+ const delimiterPushCondition = (delimiterCondition && (stack.at(-1) == char));
145
+ const delimiterPopCondition = (delimiterCondition && (stringDelimiters[stack.at(-1)] == char));
146
+ const basePopCondition = (baseCondition && (stack.at(-1) == char) && !Object.keys(stringDelimiters).includes(char));
148
147
  const isCommentEndChar = ((j == 0) && (line.length >= 4) && (line.slice(0, 4) == '=end'));
149
- const commentEndCondition = (baseCondition && isCommentEndChar && (stack[stack.length - 1] == '=begin'));
148
+ const commentEndCondition = (baseCondition && isCommentEndChar && (stack.at(-1) == '=begin'));
150
149
  const popCondition = (basePopCondition || delimiterPopCondition || commentEndCondition);
151
- const pushCondition = (quotePushCondition || variablePushCondition || stringPushCondition ||
152
- percentStringPushCondition || delimiterPushCondition || commentBeginCondition || inlineInterpolationCondition);
150
+ const pushCondition = (quotePushCondition || variablePushCondition || stringPushCondition
151
+ || percentStringPushCondition || delimiterPushCondition || commentBeginCondition || inlineInterpolationCondition);
153
152
  if (popCondition) {
154
153
  stack.pop();
155
- rangeStack[rangeStack.length - 1].push(i);
154
+ rangeStack.at(-1).push(i);
156
155
  const range_ = rangeStack.pop();
157
- if (rangeStack.length == 0) {
156
+ if (rangeStack.length === 0) {
158
157
  ranges.push(range_);
159
158
  }
160
159
  }
@@ -242,8 +241,8 @@ function getExistingDescribeFromControl(control) {
242
241
  // Array of lines representing the full InSpec control, with multi-line strings collapsed
243
242
  const lines = joinMultiLineStringsFromRanges(control.code, multiLineRanges);
244
243
  // Define RegExp for lines to skip.
245
- const skip = ['control\\W', ' title\\W', ' desc\\W', ' impact\\W', ' tag\\W', ' ref\\W'];
246
- const skipRegExp = RegExp(skip.map(x => `(^${x})`).join('|'));
244
+ const skip = [String.raw `control\W`, String.raw ` title\W`, String.raw ` desc\W`, String.raw ` impact\W`, String.raw ` tag\W`, String.raw ` ref\W`];
245
+ const skipRegExp = new RegExp(skip.map(x => `(^${x})`).join('|'));
247
246
  // Extract describe block from InSpec control with collapsed multiline strings.
248
247
  const describeBlock = [];
249
248
  let ignoreNewLine = true;
@@ -260,9 +259,9 @@ function getExistingDescribeFromControl(control) {
260
259
  }
261
260
  }
262
261
  // Return synthesized logic as describe block
263
- const lastIndex = (describeBlock.lastIndexOf('end') === -1)
264
- ? describeBlock.lastIndexOf('end\r')
265
- : describeBlock.lastIndexOf('end');
262
+ const lastIndex = (describeBlock.includes('end'))
263
+ ? describeBlock.lastIndexOf('end')
264
+ : describeBlock.lastIndexOf('end\r');
266
265
  // Drop trailing ['end', '\n'] from Control block.
267
266
  return describeBlock.slice(0, lastIndex).join('\n');
268
267
  }
@@ -292,10 +291,8 @@ function findUpdatedControlByAllIdentifiers(existingControl, updatedControls) {
292
291
  }
293
292
  // Try to match based on legacy identifiers
294
293
  updatedControl = updatedControls.find((updatedControl) => {
295
- var _a;
296
- return (_a = updatedControl.tags.legacy) === null || _a === void 0 ? void 0 : _a.some((legacyTag) => {
297
- var _a;
298
- return legacyTag.toLowerCase() === ((_a = existingControl.id) === null || _a === void 0 ? void 0 : _a.toLowerCase());
294
+ return updatedControl.tags.legacy?.some((legacyTag) => {
295
+ return legacyTag.toLowerCase() === existingControl.id?.toLowerCase();
299
296
  });
300
297
  });
301
298
  if (updatedControl) {
@@ -349,7 +346,7 @@ function updateProfile(from, using, logger) {
349
346
  // Find the diff
350
347
  const diff = (0, diff_1.diffProfile)(from, using, logger);
351
348
  // Add the new controls
352
- diff.ignoreFormattingDiff.addedControlIDs.forEach(id => {
349
+ for (const id of diff.ignoreFormattingDiff.addedControlIDs) {
353
350
  const addedControl = diff.ignoreFormattingDiff.addedControls[id];
354
351
  if (addedControl) {
355
352
  logger.debug(`New Control: ${addedControl.id} - ${addedControl.title}`);
@@ -358,7 +355,7 @@ function updateProfile(from, using, logger) {
358
355
  else {
359
356
  throw new Error(`New control ${id} added but don't have the control data`);
360
357
  }
361
- });
358
+ }
362
359
  // Update the existing controls
363
360
  for (const existingControl of from.controls) {
364
361
  const updatedControl = findUpdatedControlByAllIdentifiers(existingControl, using.controls);
@@ -398,11 +395,11 @@ function updateProfileUsingXCCDF(from, using, id, logger, ovalDefinitions) {
398
395
  const updatedProfile = updateProfile(from, xccdfProfile, logger);
399
396
  logger.debug('Creating diff markdown');
400
397
  // Create the markdown
401
- const markdown = (0, diffMarkdown_1.createDiffMarkdown)(updatedProfile.diff);
398
+ const markdown = (0, diff_markdown_1.createDiffMarkdown)(updatedProfile.diff);
402
399
  logger.debug('Profile update complete');
403
400
  return {
404
401
  profile: updatedProfile.profile,
405
402
  diff: updatedProfile.diff,
406
- markdown: markdown
403
+ markdown: markdown,
407
404
  };
408
405
  }
@@ -90,9 +90,9 @@ function convertEncodedXmlIntoJson(encodedXml, xmlParserOption = 'withArrayOptio
90
90
  };
91
91
  const parser = new fast_xml_parser_1.XMLParser(xmlParserOption === 'withArrayOption'
92
92
  ? withArrayOption
93
- : xmlParserOption === 'withArrayNoEntitiesOption'
93
+ : (xmlParserOption === 'withArrayNoEntitiesOption'
94
94
  ? withArrayNoEntitiesOption
95
- : noArrayOption);
95
+ : noArrayOption));
96
96
  return parser.parse(encodedXml);
97
97
  }
98
98
  /**
@@ -141,7 +141,7 @@ function removeHtmlTags(input) {
141
141
  // $ matches the end of the string. This ensures the regex can handle
142
142
  // cases where the tag is incomplete or unclosed (e.g., <div)
143
143
  // g: Global flag to find all matches in the input string
144
- return input.replace(/<\/?[^>]+(>|$)/g, '');
144
+ return input.replaceAll(/<\/?[^>]+(>|$)/g, '');
145
145
  }
146
146
  /**
147
147
  * Converts a severity string to a numerical impact value.
@@ -160,21 +160,20 @@ function removeHtmlTags(input) {
160
160
  * @returns The numerical impact value corresponding to the severity string.
161
161
  */
162
162
  function severityStringToImpact(string) {
163
- var _a, _b, _c, _d, _e;
164
- if ((_a = RegExp(/none|na|n\/a|not[\s()*_|]?applicable/i).exec(string)) === null || _a === void 0 ? void 0 : _a.length) {
165
- return 0.0;
163
+ if (new RegExp(/none|na|n\/a|not[\s()*_|]?applicable/i).exec(string)?.length) {
164
+ return 0;
166
165
  }
167
- if ((_b = RegExp(/low|cat(egory)?\s*(iii|3)/i).exec(string)) === null || _b === void 0 ? void 0 : _b.length) {
166
+ if (new RegExp(/low|cat(egory)?\s*(iii|3)/i).exec(string)?.length) {
168
167
  return 0.3;
169
168
  }
170
- if ((_c = RegExp(/med(ium)?|cat(egory)?\s*(ii|2)/).exec(string)) === null || _c === void 0 ? void 0 : _c.length) {
169
+ if (new RegExp(/med(ium)?|cat(egory)?\s*(ii|2)/).exec(string)?.length) {
171
170
  return 0.5;
172
171
  }
173
- if ((_d = RegExp(/high|cat(egory)?\s*(i|1)/).exec(string)) === null || _d === void 0 ? void 0 : _d.length) {
172
+ if (new RegExp(/high|cat(egory)?\s*(i|1)/).exec(string)?.length) {
174
173
  return 0.7;
175
174
  }
176
- if ((_e = RegExp(/crit(ical)?|severe/).exec(string)) === null || _e === void 0 ? void 0 : _e.length) {
177
- return 1.0;
175
+ if (new RegExp(/crit(ical)?|severe/).exec(string)?.length) {
176
+ return 1;
178
177
  }
179
178
  return 0.5;
180
179
  }
@@ -192,7 +191,7 @@ function severityStringToImpact(string) {
192
191
  */
193
192
  function impactNumberToSeverityString(impact) {
194
193
  // Impact must be 0.0 - 1.0
195
- if (impact < 0.0 || impact > 1.0) {
194
+ if (impact < 0 || impact > 1) {
196
195
  throw new Error('Impact cannot be less than 0.0 or greater than 1.0');
197
196
  }
198
197
  else {
@@ -234,7 +233,7 @@ function impactNumberToSeverityString(impact) {
234
233
  function convertEncodedHTMLIntoJson(encodedHTML) {
235
234
  if (encodedHTML) {
236
235
  // Some STIGs regarding XSS put the < character inside of the description which breaks parsing
237
- const patchedHTML = encodedHTML.replace(/"&lt;"/g, '[[[REPLACE_LESS_THAN]]]');
236
+ const patchedHTML = encodedHTML.replaceAll('"&lt;"', '[[[REPLACE_LESS_THAN]]]');
238
237
  const xmlChunks = [];
239
238
  const htmlParser = new htmlparser.Parser({
240
239
  ontext(text) {
@@ -252,32 +251,22 @@ function convertEncodedHTMLIntoJson(encodedHTML) {
252
251
  const remainingFields = lodash_1.default.omit(converted.VulnDiscussion, [
253
252
  'FalsePositives', 'FalseNegatives', 'Documentable', 'Mitigations',
254
253
  'SeverityOverrideGuidance', 'PotentialImpacts', 'ThirdPartyTools',
255
- 'MitigationControl', 'Responsibility', 'IAControls'
254
+ 'MitigationControl', 'Responsibility', 'IAControls',
256
255
  ]);
257
- Object.entries(remainingFields).forEach(([field, value]) => {
256
+ for (const [field, value] of Object.entries(remainingFields)) {
258
257
  extractedVulnDescription += `<${field}> ${value}`;
259
- });
258
+ }
260
259
  cleaned = {
261
260
  VulnDiscussion: extractedVulnDescription.replace(/\[\[\[REPLACE_LESS_THAN]]]/, '"<"'),
262
261
  };
263
- Object.entries(converted.VulnDiscussion).forEach(([key, value]) => {
264
- if (typeof value === 'string') {
265
- cleaned[key] = value.replace(/\[\[\[REPLACE_LESS_THAN]]]/, '"<"');
266
- }
267
- else {
268
- cleaned[key] = value;
269
- }
270
- });
262
+ for (const [key, value] of Object.entries(converted.VulnDiscussion)) {
263
+ cleaned[key] = typeof value === 'string' ? value.replace(/\[\[\[REPLACE_LESS_THAN]]]/, '"<"') : value;
264
+ }
271
265
  }
272
266
  else {
273
- Object.entries(converted).forEach(([key, value]) => {
274
- if (typeof value === 'string') {
275
- cleaned[key] = value.replace(/\[\[\[REPLACE_LESS_THAN]]]/, '"<"');
276
- }
277
- else {
278
- cleaned[key] = value;
279
- }
280
- });
267
+ for (const [key, value] of Object.entries(converted)) {
268
+ cleaned[key] = typeof value === 'string' ? value.replace(/\[\[\[REPLACE_LESS_THAN]]]/, '"<"') : value;
269
+ }
281
270
  }
282
271
  return cleaned;
283
272
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mitre/inspec-objects",
3
- "version": "2.0.4",
3
+ "version": "2.1.0",
4
4
  "description": "Typescript objects for normalizing between InSpec profiles and XCCDF benchmarks",
5
5
  "main": "lib/index.js",
6
6
  "publishConfig": {
@@ -10,8 +10,9 @@
10
10
  "build": "tsc -p ./tsconfig.build.json",
11
11
  "dev": "npx -y ts-node test.ts",
12
12
  "test": "vitest",
13
- "lint": "eslint \"**/*.ts\" --fix",
14
- "lint:ci": "eslint \"**/*.ts\" --max-warnings 0"
13
+ "test:ci": "vitest run",
14
+ "lint": "eslint --fix",
15
+ "lint:ci": "eslint --max-warnings 0"
15
16
  },
16
17
  "repository": {
17
18
  "type": "git",
@@ -24,33 +25,33 @@
24
25
  },
25
26
  "homepage": "https://github.com/mitre/ts-inspec-objects#readme",
26
27
  "dependencies": {
27
- "@types/flat": "5.0.5",
28
28
  "@types/he": "^1.1.2",
29
29
  "@types/json-diff": "^1.0.0",
30
30
  "@types/jstoxml": "^2.0.2",
31
31
  "@types/lodash": "^4.14.178",
32
32
  "@types/mustache": "^4.2.0",
33
- "@types/pretty": "^2.0.1",
34
33
  "fast-xml-parser": "^5.0.7",
35
- "flat": "6.0.1",
36
34
  "he": "^1.2.0",
35
+ "htmlfy": "^1.0.1",
37
36
  "htmlparser2": "^10.0.0",
38
37
  "inspecjs": "^2.6.6",
39
38
  "json-diff": "^1.0.6",
40
39
  "jstoxml": "^7.0.1",
41
40
  "lodash": "^4.17.21",
42
41
  "mustache": "^4.2.0",
43
- "pretty": "^2.0.0",
44
42
  "tslib": "^2.8.1",
45
43
  "winston": "^3.8.1",
46
44
  "yaml": "^2.3.1"
47
45
  },
48
46
  "devDependencies": {
49
- "@types/node": "^24.0.0",
50
- "@typescript-eslint/eslint-plugin": "^8.35.1",
51
- "@typescript-eslint/parser": "^8.35.1",
52
- "eslint": "^8.30.0",
53
- "typescript": "^5.2.2",
54
- "vitest": "^3.2.4"
47
+ "@eslint/js": "^10.0.1",
48
+ "@stylistic/eslint-plugin": "^5.9.0",
49
+ "@types/node": "^25.3.0",
50
+ "eslint": "^10.0.2",
51
+ "eslint-plugin-n": "^17.24.0",
52
+ "eslint-plugin-unicorn": "^63.0.0",
53
+ "typescript": "^5.9.3",
54
+ "typescript-eslint": "^8.56.1",
55
+ "vitest": "^4.0.1"
55
56
  }
56
57
  }
@@ -2,4 +2,4 @@
2
2
  {
3
3
  "extends": "./tsconfig.json",
4
4
  "exclude": ["**/*.spec.ts", "lib", "test"]
5
- }
5
+ }
package/tsconfig.json CHANGED
@@ -10,12 +10,12 @@
10
10
  "outDir": "lib",
11
11
  "rootDir": "src",
12
12
  "strict": true,
13
- "target": "es2019",
13
+ "target": "ES2024",
14
14
  "types": ["node"]
15
15
  },
16
16
  "include": [
17
17
  "index.ts",
18
18
  "src/**/*",
19
19
  "types/*"
20
- ],
20
+ ]
21
21
  }
package/vitest.config.ts CHANGED
@@ -1,7 +1,7 @@
1
- import {defineConfig} from 'vitest/config';
1
+ import { defineConfig } from 'vitest/config';
2
2
 
3
3
  export default defineConfig({
4
4
  test: {
5
- testTimeout: 60000
6
- }
5
+ testTimeout: 60_000,
6
+ },
7
7
  });