apex-code-coverage-transformer 1.4.1-beta.7 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  The `apex-code-coverage-transformer` is a simple Salesforce CLI plugin to transform the Apex Code Coverage JSON file into Generic Test Coverage Format (XML). This format is accepted by static code analysis tools like SonarQube.
6
6
 
7
- This plugin supports code coverage metrics created for Apex Classes, Apex Triggers, and Flows (if flows are deployed as active in your org).
7
+ This plugin supports code coverage metrics created for Apex Classes, Apex Triggers, and Flows (if flows are deployed as active in your org). This also supports multiple package directories as listed in your project's `sfdx-project.json` configuration, assuming unique file-names are used in your package directories.
8
8
 
9
9
  To create the code coverage JSON during a Salesforce CLI deployment/validation, append `--coverage-formatters json --results-dir coverage` to the `sf project deploy` command:
10
10
 
@@ -16,8 +16,6 @@ This will create a coverage JSON in this relative path - `coverage/coverage/cove
16
16
 
17
17
  This JSON isn't accepted by SonarQube automatically and needs to be converted using this plugin.
18
18
 
19
- After this plugin creates the XML, you can pass the XML file-path to SonarQube using the `sonar.coverageReportPaths` flag.
20
-
21
19
  **Note**: This has been tested and confirmed on code which meets 100% coverage.
22
20
 
23
21
  ## Install
@@ -32,16 +30,18 @@ The `apex-code-coverage-transformer` has 1 command:
32
30
 
33
31
  - `sf apex-code-coverage transformer transform`
34
32
 
33
+ Recommend running this command in the same directory that your `sfdx-project.json` file is located in. This command will use the `packageDirectories` in the JSON file to set the file-paths in the coverage file.
34
+
35
35
  ## `sf apex-code-coverage transformer transform`
36
36
 
37
37
  ```
38
38
  USAGE
39
- $ sf apex-code-coverage transformer transform -j <value> -x <value> -d <value> [--json]
39
+ $ sf apex-code-coverage transformer transform -j <value> -x <value> -c <value> [--json]
40
40
 
41
41
  FLAGS
42
42
  -j, --coverage-json=<value> The path to the JSON file created by the Salesforce CLI for code coverage.
43
43
  -x, --xml=<value> [default: coverage.xml] Output path for the XML file created by this plugin
44
- -d, --dx-directory=<value> [default: force-app/main/default] The root directory containing your Salesforce metadata (should be the relative path in your repository).
44
+ -c, --sfdx-configuration=<value> [default: 'sfdx-project.json' in the current working directory] The path to your Salesforce DX configuration file, 'sfdx-project.json'.
45
45
 
46
46
  GLOBAL FLAGS
47
47
  --json Format output as json.
@@ -50,448 +50,33 @@ DESCRIPTION
50
50
  This plugin will convert the JSON file created by the Salesforce CLI during Apex deployments into the Generic Test Coverage Format.
51
51
 
52
52
  EXAMPLES
53
- $ apex-code-coverage transformer transform -j "test.json" -x "coverage.xml" -d "force-app/main/default"
53
+ $ apex-code-coverage transformer transform -j "test.json" -x "coverage.xml" -c "sfdx-project.json"
54
54
  ```
55
55
 
56
56
  ## Example
57
57
 
58
- A JSON created by the Salesforce CLI :
59
-
60
- ```json
61
- {
62
- "no-map/PrepareMySandbox": {
63
- "fnMap": {},
64
- "branchMap": {},
65
- "path": "no-map/PrepareMySandbox",
66
- "f": {},
67
- "b": {},
68
- "s": {
69
- "7": 0,
70
- "8": 1,
71
- "9": 1,
72
- "10": 1,
73
- "11": 1,
74
- "12": 0,
75
- "13": 1,
76
- "14": 1,
77
- "15": 1,
78
- "16": 1,
79
- "17": 1,
80
- "18": 1,
81
- "19": 1,
82
- "20": 1,
83
- "21": 1,
84
- "22": 1,
85
- "23": 1,
86
- "24": 1,
87
- "25": 1,
88
- "26": 1,
89
- "27": 1,
90
- "28": 1,
91
- "29": 1,
92
- "30": 1,
93
- "31": 1,
94
- "32": 1,
95
- "33": 1,
96
- "34": 1,
97
- "35": 1,
98
- "36": 1,
99
- "37": 1
100
- },
101
- "statementMap": {
102
- "7": {
103
- "start": {
104
- "line": 7,
105
- "column": 0
106
- },
107
- "end": {
108
- "line": 7,
109
- "column": 0
110
- }
111
- },
112
- "8": {
113
- "start": {
114
- "line": 8,
115
- "column": 0
116
- },
117
- "end": {
118
- "line": 8,
119
- "column": 0
120
- }
121
- },
122
- "9": {
123
- "start": {
124
- "line": 9,
125
- "column": 0
126
- },
127
- "end": {
128
- "line": 9,
129
- "column": 0
130
- }
131
- },
132
- "10": {
133
- "start": {
134
- "line": 10,
135
- "column": 0
136
- },
137
- "end": {
138
- "line": 10,
139
- "column": 0
140
- }
141
- },
142
- "11": {
143
- "start": {
144
- "line": 11,
145
- "column": 0
146
- },
147
- "end": {
148
- "line": 11,
149
- "column": 0
150
- }
151
- },
152
- "12": {
153
- "start": {
154
- "line": 12,
155
- "column": 0
156
- },
157
- "end": {
158
- "line": 12,
159
- "column": 0
160
- }
161
- },
162
- "13": {
163
- "start": {
164
- "line": 13,
165
- "column": 0
166
- },
167
- "end": {
168
- "line": 13,
169
- "column": 0
170
- }
171
- },
172
- "14": {
173
- "start": {
174
- "line": 14,
175
- "column": 0
176
- },
177
- "end": {
178
- "line": 14,
179
- "column": 0
180
- }
181
- },
182
- "15": {
183
- "start": {
184
- "line": 15,
185
- "column": 0
186
- },
187
- "end": {
188
- "line": 15,
189
- "column": 0
190
- }
191
- },
192
- "16": {
193
- "start": {
194
- "line": 16,
195
- "column": 0
196
- },
197
- "end": {
198
- "line": 16,
199
- "column": 0
200
- }
201
- },
202
- "17": {
203
- "start": {
204
- "line": 17,
205
- "column": 0
206
- },
207
- "end": {
208
- "line": 17,
209
- "column": 0
210
- }
211
- },
212
- "18": {
213
- "start": {
214
- "line": 18,
215
- "column": 0
216
- },
217
- "end": {
218
- "line": 18,
219
- "column": 0
220
- }
221
- },
222
- "19": {
223
- "start": {
224
- "line": 19,
225
- "column": 0
226
- },
227
- "end": {
228
- "line": 19,
229
- "column": 0
230
- }
231
- },
232
- "20": {
233
- "start": {
234
- "line": 20,
235
- "column": 0
236
- },
237
- "end": {
238
- "line": 20,
239
- "column": 0
240
- }
241
- },
242
- "21": {
243
- "start": {
244
- "line": 21,
245
- "column": 0
246
- },
247
- "end": {
248
- "line": 21,
249
- "column": 0
250
- }
251
- },
252
- "22": {
253
- "start": {
254
- "line": 22,
255
- "column": 0
256
- },
257
- "end": {
258
- "line": 22,
259
- "column": 0
260
- }
261
- },
262
- "23": {
263
- "start": {
264
- "line": 23,
265
- "column": 0
266
- },
267
- "end": {
268
- "line": 23,
269
- "column": 0
270
- }
271
- },
272
- "24": {
273
- "start": {
274
- "line": 24,
275
- "column": 0
276
- },
277
- "end": {
278
- "line": 24,
279
- "column": 0
280
- }
281
- },
282
- "25": {
283
- "start": {
284
- "line": 25,
285
- "column": 0
286
- },
287
- "end": {
288
- "line": 25,
289
- "column": 0
290
- }
291
- },
292
- "26": {
293
- "start": {
294
- "line": 26,
295
- "column": 0
296
- },
297
- "end": {
298
- "line": 26,
299
- "column": 0
300
- }
301
- },
302
- "27": {
303
- "start": {
304
- "line": 27,
305
- "column": 0
306
- },
307
- "end": {
308
- "line": 27,
309
- "column": 0
310
- }
311
- },
312
- "28": {
313
- "start": {
314
- "line": 28,
315
- "column": 0
316
- },
317
- "end": {
318
- "line": 28,
319
- "column": 0
320
- }
321
- },
322
- "29": {
323
- "start": {
324
- "line": 29,
325
- "column": 0
326
- },
327
- "end": {
328
- "line": 29,
329
- "column": 0
330
- }
331
- },
332
- "30": {
333
- "start": {
334
- "line": 30,
335
- "column": 0
336
- },
337
- "end": {
338
- "line": 30,
339
- "column": 0
340
- }
341
- },
342
- "31": {
343
- "start": {
344
- "line": 31,
345
- "column": 0
346
- },
347
- "end": {
348
- "line": 31,
349
- "column": 0
350
- }
351
- },
352
- "32": {
353
- "start": {
354
- "line": 32,
355
- "column": 0
356
- },
357
- "end": {
358
- "line": 32,
359
- "column": 0
360
- }
361
- },
362
- "33": {
363
- "start": {
364
- "line": 33,
365
- "column": 0
366
- },
367
- "end": {
368
- "line": 33,
369
- "column": 0
370
- }
371
- },
372
- "34": {
373
- "start": {
374
- "line": 34,
375
- "column": 0
376
- },
377
- "end": {
378
- "line": 34,
379
- "column": 0
380
- }
381
- },
382
- "35": {
383
- "start": {
384
- "line": 35,
385
- "column": 0
386
- },
387
- "end": {
388
- "line": 35,
389
- "column": 0
390
- }
391
- },
392
- "36": {
393
- "start": {
394
- "line": 36,
395
- "column": 0
396
- },
397
- "end": {
398
- "line": 36,
399
- "column": 0
400
- }
401
- },
402
- "37": {
403
- "start": {
404
- "line": 37,
405
- "column": 0
406
- },
407
- "end": {
408
- "line": 37,
409
- "column": 0
410
- }
411
- }
412
- }
413
- }
414
- }
415
- ```
416
-
417
- will be converted to:
58
+ This [code coverage JSON file](https://raw.githubusercontent.com/mcarvin8/apex-code-coverage-transformer/main/coverage_no_file_exts.json) created by the Salesforce CLI will be transformed into:
418
59
 
419
60
  ```xml
420
61
  <?xml version="1.0"?>
421
62
  <coverage version="1">
422
- <file path="force-app/main/default/classes/PrepareMySandbox.cls">
423
- <lineToCover lineNumber="1" covered="true"/>
424
- <lineToCover lineNumber="2" covered="true"/>
425
- <lineToCover lineNumber="3" covered="true"/>
426
- <lineToCover lineNumber="4" covered="true"/>
427
- <lineToCover lineNumber="5" covered="true"/>
428
- <lineToCover lineNumber="6" covered="true"/>
429
- <lineToCover lineNumber="7" covered="false"/>
430
- <lineToCover lineNumber="8" covered="true"/>
431
- <lineToCover lineNumber="9" covered="true"/>
432
- <lineToCover lineNumber="10" covered="true"/>
433
- <lineToCover lineNumber="11" covered="true"/>
434
- <lineToCover lineNumber="12" covered="false"/>
435
- <lineToCover lineNumber="13" covered="true"/>
436
- <lineToCover lineNumber="14" covered="true"/>
437
- <lineToCover lineNumber="15" covered="true"/>
438
- <lineToCover lineNumber="16" covered="true"/>
439
- <lineToCover lineNumber="17" covered="true"/>
440
- <lineToCover lineNumber="18" covered="true"/>
441
- <lineToCover lineNumber="19" covered="true"/>
442
- <lineToCover lineNumber="20" covered="true"/>
443
- <lineToCover lineNumber="21" covered="true"/>
444
- <lineToCover lineNumber="22" covered="true"/>
445
- <lineToCover lineNumber="23" covered="true"/>
446
- <lineToCover lineNumber="24" covered="true"/>
447
- <lineToCover lineNumber="25" covered="true"/>
448
- <lineToCover lineNumber="26" covered="true"/>
449
- <lineToCover lineNumber="27" covered="true"/>
450
- <lineToCover lineNumber="28" covered="true"/>
451
- <lineToCover lineNumber="29" covered="true"/>
452
- <lineToCover lineNumber="30" covered="true"/>
453
- <lineToCover lineNumber="31" covered="true"/>
454
- <lineToCover lineNumber="32" covered="true"/>
455
- <lineToCover lineNumber="33" covered="true"/>
456
- <lineToCover lineNumber="34" covered="true"/>
457
- <lineToCover lineNumber="35" covered="true"/>
458
- <lineToCover lineNumber="36" covered="true"/>
459
- <lineToCover lineNumber="37" covered="true"/>
460
- <lineToCover lineNumber="38" covered="true"/>
461
- <lineToCover lineNumber="39" covered="true"/>
462
- <lineToCover lineNumber="40" covered="true"/>
463
- <lineToCover lineNumber="41" covered="true"/>
464
- <lineToCover lineNumber="42" covered="true"/>
465
- <lineToCover lineNumber="43" covered="true"/>
466
- <lineToCover lineNumber="44" covered="true"/>
467
- <lineToCover lineNumber="45" covered="true"/>
468
- <lineToCover lineNumber="46" covered="true"/>
469
- <lineToCover lineNumber="47" covered="true"/>
470
- <lineToCover lineNumber="48" covered="true"/>
471
- <lineToCover lineNumber="49" covered="true"/>
472
- <lineToCover lineNumber="50" covered="true"/>
473
- <lineToCover lineNumber="51" covered="true"/>
474
- <lineToCover lineNumber="52" covered="true"/>
475
- <lineToCover lineNumber="53" covered="true"/>
476
- <lineToCover lineNumber="54" covered="true"/>
477
- <lineToCover lineNumber="55" covered="true"/>
478
- <lineToCover lineNumber="56" covered="true"/>
479
- <lineToCover lineNumber="57" covered="true"/>
480
- <lineToCover lineNumber="58" covered="true"/>
481
- <lineToCover lineNumber="59" covered="true"/>
482
- <lineToCover lineNumber="60" covered="true"/>
483
- <lineToCover lineNumber="61" covered="true"/>
484
- <lineToCover lineNumber="62" covered="true"/>
485
- <lineToCover lineNumber="63" covered="true"/>
486
- <lineToCover lineNumber="64" covered="true"/>
487
- <lineToCover lineNumber="65" covered="true"/>
488
- <lineToCover lineNumber="66" covered="true"/>
489
- <lineToCover lineNumber="67" covered="true"/>
490
- <lineToCover lineNumber="68" covered="true"/>
491
- <lineToCover lineNumber="69" covered="true"/>
492
- <lineToCover lineNumber="70" covered="true"/>
493
- <lineToCover lineNumber="71" covered="true"/>
494
- <lineToCover lineNumber="72" covered="true"/>
63
+ <file path="force-app\main\default\triggers\AccountTrigger.trigger">
64
+ <lineToCover lineNumber="52" covered="false"/>
65
+ <lineToCover lineNumber="53" covered="false"/>
66
+ <lineToCover lineNumber="59" covered="false"/>
67
+ <lineToCover lineNumber="60" covered="false"/>
68
+ </file>
69
+ <file path="force-app\main\default\classes\AccountProfile.cls">
70
+ <lineToCover lineNumber="52" covered="false"/>
71
+ <lineToCover lineNumber="53" covered="false"/>
72
+ <lineToCover lineNumber="59" covered="false"/>
73
+ <lineToCover lineNumber="60" covered="false"/>
74
+ </file>
75
+ <file path="force-app\main\default\flows\Get_Info.flow-meta.xml">
76
+ <lineToCover lineNumber="52" covered="false"/>
77
+ <lineToCover lineNumber="53" covered="false"/>
78
+ <lineToCover lineNumber="59" covered="false"/>
79
+ <lineToCover lineNumber="60" covered="false"/>
495
80
  </file>
496
81
  </coverage>
497
82
  ```
@@ -7,7 +7,7 @@ export default class TransformerTransform extends SfCommand<TransformerTransform
7
7
  static readonly description: string;
8
8
  static readonly examples: string[];
9
9
  static readonly flags: {
10
- 'dx-directory': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ 'sfdx-configuration': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
11
  'coverage-json': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
12
  xml: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
13
  };
@@ -11,12 +11,12 @@ export default class TransformerTransform extends SfCommand {
11
11
  static description = messages.getMessage('description');
12
12
  static examples = messages.getMessages('examples');
13
13
  static flags = {
14
- 'dx-directory': Flags.directory({
15
- summary: messages.getMessage('flags.dx-directory.summary'),
16
- char: 'd',
14
+ 'sfdx-configuration': Flags.file({
15
+ summary: messages.getMessage('flags.sfdx-configuration.summary'),
16
+ char: 'c',
17
17
  required: true,
18
18
  exists: true,
19
- default: 'force-app/main/default',
19
+ default: 'sfdx-project.json',
20
20
  }),
21
21
  'coverage-json': Flags.file({
22
22
  summary: messages.getMessage('flags.coverage-json.summary'),
@@ -36,25 +36,22 @@ export default class TransformerTransform extends SfCommand {
36
36
  const { flags } = await this.parse(TransformerTransform);
37
37
  let jsonFilePath = flags['coverage-json'];
38
38
  let xmlFilePath = flags['xml'];
39
- const dxDirectory = flags['dx-directory'];
39
+ let sfdxConfigFile = flags['sfdx-configuration'];
40
40
  jsonFilePath = path.resolve(jsonFilePath);
41
41
  xmlFilePath = path.resolve(xmlFilePath);
42
- // Check if the JSON file exists
43
- if (!fs.existsSync(jsonFilePath)) {
44
- this.error(`JSON file does not exist: ${jsonFilePath}`);
45
- }
42
+ sfdxConfigFile = path.resolve(sfdxConfigFile);
46
43
  const jsonData = fs.readFileSync(jsonFilePath, 'utf-8');
47
44
  const coverageData = JSON.parse(jsonData);
48
- const xmlData = convertToGenericCoverageReport(coverageData, dxDirectory);
45
+ const xmlData = await convertToGenericCoverageReport(coverageData, sfdxConfigFile);
49
46
  // Write the XML data to the XML file
50
47
  try {
51
48
  fs.writeFileSync(xmlFilePath, xmlData);
52
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
53
49
  this.log(`The XML data has been written to ${xmlFilePath}`);
54
50
  }
55
51
  catch (error) {
56
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
57
- this.error(`Error writing XML data to file: ${error}`);
52
+ if (error instanceof Error) {
53
+ this.error(`Error writing XML data to file: ${error.message}`);
54
+ }
58
55
  }
59
56
  return { path: xmlFilePath };
60
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../../src/commands/apex-code-coverage/transformer/transform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../../src/commands/apex-code-coverage/transformer/transform.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
1
  import { CoverageData } from './types.js';
2
- export declare function convertToGenericCoverageReport(data: CoverageData, dxDirectory: string): string;
2
+ export declare function convertToGenericCoverageReport(data: CoverageData, dxConfigFile: string): Promise<string>;
@@ -1,57 +1,29 @@
1
1
  'use strict';
2
- import * as fs from 'node:fs';
3
2
  import { findFilePath } from './findFilePath.js';
4
- export function convertToGenericCoverageReport(data, dxDirectory) {
3
+ export async function convertToGenericCoverageReport(data, dxConfigFile) {
5
4
  let xml = '<?xml version="1.0"?>\n<coverage version="1">\n';
6
- for (const className in data) {
7
- if (Object.hasOwn(data, className)) {
8
- const classInfo = data[className];
9
- const formattedClassName = className.replace('no-map/', '');
10
- const filePath = findFilePath(formattedClassName, dxDirectory);
11
- if (filePath === undefined) {
12
- throw Error(`The file name ${formattedClassName} was not found in the classes, triggers, or flows directory.`);
13
- }
14
- // Extract the "uncovered lines" from the JSON data
15
- const uncoveredLines = Object.keys(classInfo.s)
16
- .filter(lineNumber => classInfo.s[lineNumber] === 0)
17
- .map(Number);
18
- const coveredLines = Object.keys(classInfo.s)
19
- .filter(lineNumber => classInfo.s[lineNumber] === 1)
20
- .map(Number);
21
- const randomLines = [];
22
- const totalLines = getTotalLines(filePath);
23
- xml += `\t<file path="${filePath}">\n`;
24
- for (const uncoveredLine of uncoveredLines) {
25
- xml += `\t\t<lineToCover lineNumber="${uncoveredLine}" covered="false"/>\n`;
26
- }
27
- let totalCoveredLinesInXML = 0;
28
- for (const coveredLine of coveredLines) {
29
- if (coveredLine > totalLines) {
30
- for (let randomLineNumber = 1; randomLineNumber <= totalLines; randomLineNumber++) {
31
- if (!uncoveredLines.includes(randomLineNumber) &&
32
- !coveredLines.includes(randomLineNumber) &&
33
- !randomLines.includes(randomLineNumber) &&
34
- totalCoveredLinesInXML < coveredLines.length) {
35
- xml += `\t\t<lineToCover lineNumber="${randomLineNumber}" covered="true"/>\n`;
36
- randomLines.push(randomLineNumber);
37
- totalCoveredLinesInXML++;
38
- break;
39
- }
40
- }
41
- }
42
- else {
43
- xml += `\t\t<lineToCover lineNumber="${coveredLine}" covered="true"/>\n`;
44
- totalCoveredLinesInXML++;
45
- }
46
- }
47
- xml += '\t</file>\n';
5
+ for (const fileName in data) {
6
+ if (!Object.hasOwn(data, fileName))
7
+ continue;
8
+ const fileInfo = data[fileName];
9
+ const formattedFileName = fileName.replace('no-map/', '');
10
+ const filePath = await findFilePath(formattedFileName, dxConfigFile);
11
+ if (filePath === undefined) {
12
+ throw Error(`The file name ${formattedFileName} was not found in any package directory.`);
48
13
  }
14
+ xml += `\t<file path="${filePath}">\n`;
15
+ for (const lineNumber in fileInfo.s) {
16
+ if (!Object.hasOwn(fileInfo.s, lineNumber))
17
+ continue;
18
+ const count = fileInfo.s[lineNumber];
19
+ const covered = count > 0 ? 'true' : 'false';
20
+ // only add uncovered lines
21
+ if (covered === 'false')
22
+ xml += `\t\t<lineToCover lineNumber="${lineNumber}" covered="${covered}"/>\n`;
23
+ }
24
+ xml += '\t</file>\n';
49
25
  }
50
26
  xml += '</coverage>';
51
27
  return xml;
52
28
  }
53
- function getTotalLines(filePath) {
54
- const fileContent = fs.readFileSync(filePath, 'utf8');
55
- return fileContent.split(/\r\n|\r|\n/).length;
56
- }
57
29
  //# sourceMappingURL=convertToGenericCoverageReport.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertToGenericCoverageReport.js","sourceRoot":"","sources":["../../src/helpers/convertToGenericCoverageReport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"convertToGenericCoverageReport.js","sourceRoot":"","sources":["../../src/helpers/convertToGenericCoverageReport.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,IAAkB,EAAE,YAAoB;IAC3F,IAAI,GAAG,GAAG,iDAAiD,CAAC;IAE5D,KAAK,MAAM,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;YAAE,SAAS;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC1D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;QACrE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,KAAK,CAAC,iBAAiB,iBAAiB,0CAA0C,CAAC,CAAC;QAC5F,CAAC;QACD,GAAG,IAAI,iBAAiB,QAAQ,MAAM,CAAC;QAEvC,KAAK,MAAM,UAAU,IAAI,QAAQ,CAAC,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC;gBAAE,SAAS;YACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7C,2BAA2B;YAC3B,IAAI,OAAO,KAAK,OAAO;gBAAE,GAAG,IAAI,gCAAgC,UAAU,cAAc,OAAO,OAAO,CAAC;QACzG,CAAC;QACD,GAAG,IAAI,aAAa,CAAC;IACvB,CAAC;IACD,GAAG,IAAI,aAAa,CAAC;IACrB,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1 +1 @@
1
- export declare function findFilePath(fileName: string, dxDirectory: string): string | undefined;
1
+ export declare function findFilePath(fileName: string, dxConfigFile: string): Promise<string | undefined>;
@@ -1,40 +1,51 @@
1
1
  'use strict';
2
+ /* eslint-disable no-await-in-loop */
2
3
  import * as fs from 'node:fs';
3
4
  import * as path from 'node:path';
4
- export function findFilePath(fileName, dxDirectory) {
5
+ import { findSubFolder } from './findSubFolder.js';
6
+ import { getPackageDirectories } from './getPackageDirectories.js';
7
+ export async function findFilePath(fileName, dxConfigFile) {
8
+ const packageDirectories = await getPackageDirectories(dxConfigFile);
9
+ let filePath;
10
+ for (const directory of packageDirectories) {
11
+ filePath = await findFilePathinDirectory(fileName, directory);
12
+ if (filePath !== undefined) {
13
+ break;
14
+ }
15
+ }
16
+ return filePath;
17
+ }
18
+ async function findFilePathinDirectory(fileName, dxDirectory) {
5
19
  const fileExtension = fileName.split('.').slice(1).join('.');
6
- let relativeClassPath = '';
7
- let relativeTriggerPath = '';
8
- let relativeFlowPath = '';
20
+ let relativeClassPath = await findSubFolder(dxDirectory, 'classes');
21
+ let relativeTriggerPath = await findSubFolder(dxDirectory, 'triggers');
22
+ let relativeFlowPath = await findSubFolder(dxDirectory, 'flows');
9
23
  let absoluteClassPath = '';
10
24
  let absoluteTriggerPath = '';
11
25
  let absoluteFlowPath = '';
12
26
  // if file extension is found, use that to determine paths
13
- if (fileExtension === 'cls') {
14
- relativeClassPath = `${dxDirectory}/classes/${fileName}`;
15
- absoluteClassPath = path.resolve(relativeClassPath);
27
+ if (fileExtension === 'cls' && relativeClassPath !== undefined) {
28
+ absoluteClassPath = path.resolve(relativeClassPath, fileName);
16
29
  if (fs.existsSync(absoluteClassPath)) {
17
- return relativeClassPath;
30
+ return path.join(relativeClassPath, fileName);
18
31
  }
19
32
  }
20
- else if (fileExtension === 'trigger') {
21
- relativeTriggerPath = `${dxDirectory}/triggers/${fileName}`;
22
- absoluteTriggerPath = path.resolve(relativeTriggerPath);
33
+ else if (fileExtension === 'trigger' && relativeTriggerPath !== undefined) {
34
+ absoluteTriggerPath = path.resolve(relativeTriggerPath, fileName);
23
35
  if (fs.existsSync(absoluteTriggerPath)) {
24
- return relativeTriggerPath;
36
+ return path.join(relativeTriggerPath, fileName);
25
37
  }
26
38
  }
27
- else if (fileExtension === 'flow-meta.xml') {
28
- relativeFlowPath = `${dxDirectory}/flows/${fileName}`;
29
- absoluteFlowPath = path.resolve(relativeFlowPath);
39
+ else if (fileExtension === 'flow-meta.xml' && relativeFlowPath !== undefined) {
40
+ absoluteFlowPath = path.resolve(relativeFlowPath, fileName);
30
41
  if (fs.existsSync(absoluteFlowPath)) {
31
- return relativeFlowPath;
42
+ return path.join(relativeFlowPath, fileName);
32
43
  }
33
44
  }
34
45
  // if file extension is not found, add file extensions manually and test paths
35
- relativeClassPath = `${dxDirectory}/classes/${fileName}.cls`;
36
- relativeTriggerPath = `${dxDirectory}/triggers/${fileName}.trigger`;
37
- relativeFlowPath = `${dxDirectory}/flows/${fileName}.flow-meta.xml`;
46
+ relativeClassPath = path.join(relativeClassPath, `${fileName}.cls`);
47
+ relativeTriggerPath = path.join(relativeTriggerPath, `${fileName}.trigger`);
48
+ relativeFlowPath = path.join(relativeFlowPath, `${fileName}.flow-meta.xml`);
38
49
  absoluteClassPath = path.resolve(relativeClassPath);
39
50
  absoluteTriggerPath = path.resolve(relativeTriggerPath);
40
51
  absoluteFlowPath = path.resolve(relativeFlowPath);
@@ -1 +1 @@
1
- {"version":3,"file":"findFilePath.js","sourceRoot":"","sources":["../../src/helpers/findFilePath.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,WAAmB;IAChE,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,iBAAiB,GAAG,EAAE,CAAC;IAC3B,IAAI,mBAAmB,GAAG,EAAE,CAAC;IAC7B,IAAI,gBAAgB,GAAG,EAAE,CAAC;IAC1B,IAAI,iBAAiB,GAAG,EAAE,CAAC;IAC3B,IAAI,mBAAmB,GAAG,EAAE,CAAC;IAC7B,IAAI,gBAAgB,GAAG,EAAE,CAAC;IAE1B,0DAA0D;IAC1D,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;QAC5B,iBAAiB,GAAG,GAAG,WAAW,YAAY,QAAQ,EAAE,CAAC;QACzD,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACpD,IAAI,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACrC,OAAO,iBAAiB,CAAC;QAC3B,CAAC;IACH,CAAC;SAAM,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QACvC,mBAAmB,GAAG,GAAG,WAAW,aAAa,QAAQ,EAAE,CAAC;QAC5D,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QACxD,IAAI,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACvC,OAAO,mBAAmB,CAAC;QAC7B,CAAC;IACH,CAAC;SAAM,IAAI,aAAa,KAAK,eAAe,EAAE,CAAC;QAC7C,gBAAgB,GAAG,GAAG,WAAW,UAAU,QAAQ,EAAE,CAAC;QACtD,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAClD,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpC,OAAO,gBAAgB,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,iBAAiB,GAAG,GAAG,WAAW,YAAY,QAAQ,MAAM,CAAC;IAC7D,mBAAmB,GAAG,GAAG,WAAW,aAAa,QAAQ,UAAU,CAAC;IACpE,gBAAgB,GAAG,GAAG,WAAW,UAAU,QAAQ,gBAAgB,CAAC;IACpE,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpD,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACxD,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClD,IAAI,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACrC,OAAO,iBAAiB,CAAC;IAC3B,CAAC;SAAM,IAAI,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9C,OAAO,mBAAmB,CAAC;IAC7B,CAAC;SAAM,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC3C,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"findFilePath.js","sourceRoot":"","sources":["../../src/helpers/findFilePath.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function findSubFolder(parentDirectory: string, subFolderName: string): Promise<string>;
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+ /* eslint-disable no-await-in-loop */
3
+ import * as path from 'node:path';
4
+ import * as promises from 'node:fs/promises';
5
+ export async function findSubFolder(parentDirectory, subFolderName) {
6
+ const files = await promises.readdir(parentDirectory);
7
+ // Check if current directory contains the sub-folder
8
+ if (files.includes(subFolderName)) {
9
+ return path.join(parentDirectory, subFolderName);
10
+ }
11
+ // Recursively search sub-directories
12
+ for (const file of files) {
13
+ const filePath = path.join(parentDirectory, file);
14
+ const stats = await promises.stat(filePath);
15
+ if (stats.isDirectory()) {
16
+ const subFolderPath = await findSubFolder(filePath, subFolderName);
17
+ if (subFolderPath) {
18
+ return subFolderPath;
19
+ }
20
+ }
21
+ }
22
+ // must be a string for the file-path check
23
+ return 'undefined';
24
+ }
25
+ //# sourceMappingURL=findSubFolder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findSubFolder.js","sourceRoot":"","sources":["../../src/helpers/findSubFolder.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AAErC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,eAAuB,EAAE,aAAqB;IAChF,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAEtD,qDAAqD;IACrD,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,qCAAqC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YACnE,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,aAAa,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function getPackageDirectories(dxConfigFile: string): Promise<string[]>;
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+ /* eslint-disable no-await-in-loop */
3
+ import * as fs from 'node:fs';
4
+ import * as promises from 'node:fs/promises';
5
+ export async function getPackageDirectories(dxConfigFile) {
6
+ if (!fs.existsSync(dxConfigFile)) {
7
+ throw Error(`Salesforce DX Config File does not exist in this path: ${dxConfigFile}`);
8
+ }
9
+ const sfdxProjectRaw = await promises.readFile(dxConfigFile, 'utf-8');
10
+ const sfdxProject = JSON.parse(sfdxProjectRaw);
11
+ const packageDirectories = sfdxProject.packageDirectories.map((directory) => directory.path);
12
+ return packageDirectories;
13
+ }
14
+ //# sourceMappingURL=getPackageDirectories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPackageDirectories.js","sourceRoot":"","sources":["../../src/helpers/getPackageDirectories.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,qCAAqC;AAErC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAM7C,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,YAAoB;IAC9D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,CAAC,0DAA0D,YAAY,EAAE,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,cAAc,GAAW,MAAM,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAgB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAgB,CAAC;IAC3E,MAAM,kBAAkB,GAAG,WAAW,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7F,OAAO,kBAAkB,CAAC;AAC5B,CAAC"}
@@ -10,9 +10,9 @@ This plugin will convert the JSON file created by the Salesforce CLI during Apex
10
10
 
11
11
  - `sf apex-code-coverage transformer transform --coverage-json "path-to-cli-coverage.json"`
12
12
 
13
- # flags.dx-directory.summary
13
+ # flags.sfdx-configuration.summary
14
14
 
15
- Directory containing Salesforce metadata relative to your repository (default: `force-app/main/default`).
15
+ Path to your project's Salesforce DX configuration file (`sfdx-project.json`). By default, it will look for `sfdx-project.json` in the same directory you're running this plugin in.
16
16
 
17
17
  # flags.coverage-json.summary
18
18
 
package/oclif.lock CHANGED
@@ -10841,7 +10841,7 @@ stream-combiner2@~1.1.1:
10841
10841
  duplexer2 "~0.1.0"
10842
10842
  readable-stream "^2.0.2"
10843
10843
 
10844
- "string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
10844
+ "string-width-cjs@npm:string-width@^4.2.0":
10845
10845
  version "4.2.3"
10846
10846
  resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
10847
10847
  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -10859,6 +10859,15 @@ string-width@^1.0.1:
10859
10859
  is-fullwidth-code-point "^1.0.0"
10860
10860
  strip-ansi "^3.0.0"
10861
10861
 
10862
+ "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
10863
+ version "4.2.3"
10864
+ resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
10865
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
10866
+ dependencies:
10867
+ emoji-regex "^8.0.0"
10868
+ is-fullwidth-code-point "^3.0.0"
10869
+ strip-ansi "^6.0.1"
10870
+
10862
10871
  string-width@^2.0.0:
10863
10872
  version "2.1.1"
10864
10873
  resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz"
@@ -10922,7 +10931,14 @@ stringify-package@^1.0.1:
10922
10931
  resolved "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz"
10923
10932
  integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==
10924
10933
 
10925
- "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
10934
+ "strip-ansi-cjs@npm:strip-ansi@^6.0.1":
10935
+ version "6.0.1"
10936
+ resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
10937
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
10938
+ dependencies:
10939
+ ansi-regex "^5.0.1"
10940
+
10941
+ strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
10926
10942
  version "6.0.1"
10927
10943
  resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
10928
10944
  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -11833,7 +11849,7 @@ workerpool@6.2.1:
11833
11849
  resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz"
11834
11850
  integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
11835
11851
 
11836
- "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
11852
+ "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
11837
11853
  version "7.0.0"
11838
11854
  resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
11839
11855
  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -11851,6 +11867,15 @@ wrap-ansi@^6.2.0:
11851
11867
  string-width "^4.1.0"
11852
11868
  strip-ansi "^6.0.0"
11853
11869
 
11870
+ wrap-ansi@^7.0.0:
11871
+ version "7.0.0"
11872
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
11873
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
11874
+ dependencies:
11875
+ ansi-styles "^4.0.0"
11876
+ string-width "^4.1.0"
11877
+ strip-ansi "^6.0.0"
11878
+
11854
11879
  wrap-ansi@^8.1.0:
11855
11880
  version "8.1.0"
11856
11881
  resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
@@ -15,12 +15,12 @@
15
15
  "allowNo": false,
16
16
  "type": "boolean"
17
17
  },
18
- "dx-directory": {
19
- "char": "d",
20
- "name": "dx-directory",
18
+ "sfdx-configuration": {
19
+ "char": "c",
20
+ "name": "sfdx-configuration",
21
21
  "required": true,
22
- "summary": "Directory containing Salesforce metadata relative to your repository (default: `force-app/main/default`).",
23
- "default": "force-app/main/default",
22
+ "summary": "Path to your project's Salesforce DX configuration file (`sfdx-project.json`). By default, it will look for `sfdx-project.json` in the same directory you're running this plugin in.",
23
+ "default": "sfdx-project.json",
24
24
  "hasDynamicHelp": false,
25
25
  "multiple": false,
26
26
  "type": "option"
@@ -73,5 +73,5 @@
73
73
  ]
74
74
  }
75
75
  },
76
- "version": "1.4.1-beta.7"
76
+ "version": "1.5.0"
77
77
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "apex-code-coverage-transformer",
3
- "description": "Transforms the Apex Code Coverage JSON into the Generic Test Coverage Format.",
4
- "version": "1.4.1-beta.7",
3
+ "description": "Transforms the Apex Code Coverage JSON into the Generic Test Data Report.",
4
+ "version": "1.5.0",
5
5
  "dependencies": {
6
6
  "@oclif/core": "^3.18.1",
7
7
  "@salesforce/core": "^6.4.7",