@ds-sfdc/sfparty 1.5.6 → 1.6.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/package.json +5 -4
- package/src/lib/fileUtils.js +2 -2
- package/src/party/combine.js +103 -29
- package/src/party/split.js +25 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ds-sfdc/sfparty",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Salesforce metadata XML splitter for CI/CD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -22,12 +22,13 @@
|
|
|
22
22
|
"license": "BSD-3-Clause",
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"axios": "^1.6.8",
|
|
25
|
+
"ci-info": "^4.0.0",
|
|
25
26
|
"cli-color": "^2.0.4",
|
|
26
27
|
"cli-spinners": "^2.9.2",
|
|
27
28
|
"convert-hrtime": "^5.0.0",
|
|
28
29
|
"js-yaml": "^4.1.0",
|
|
29
30
|
"log-update": "^6.0.0",
|
|
30
|
-
"marked": "^12.0.
|
|
31
|
+
"marked": "^12.0.2",
|
|
31
32
|
"marked-terminal": "^7.0.0",
|
|
32
33
|
"pretty-quick": "^4.0.0",
|
|
33
34
|
"semver": "^7.6.0",
|
|
@@ -39,10 +40,10 @@
|
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@babel/core": "^7.24.4",
|
|
41
42
|
"@babel/preset-env": "^7.24.4",
|
|
42
|
-
"@commitlint/cli": "^19.
|
|
43
|
+
"@commitlint/cli": "^19.3.0",
|
|
43
44
|
"@commitlint/config-conventional": "^19.2.2",
|
|
44
45
|
"babel-jest": "^29.7.0",
|
|
45
|
-
"eslint": "^9.
|
|
46
|
+
"eslint": "^9.1.1",
|
|
46
47
|
"husky": "^9.0.11",
|
|
47
48
|
"jest": "^29.7.0",
|
|
48
49
|
"lint-staged": "^15.2.2",
|
package/src/lib/fileUtils.js
CHANGED
|
@@ -152,8 +152,8 @@ export function readFile(filePath, convert = true, fsTmp = fs) {
|
|
|
152
152
|
})
|
|
153
153
|
if (convert && filePath.indexOf('.yaml') != -1) {
|
|
154
154
|
result = yaml.load(data, {
|
|
155
|
-
onWarning: (warning) => {
|
|
156
|
-
throw new Error(`YAML parsing
|
|
155
|
+
onWarning: (warning, filePath) => {
|
|
156
|
+
throw new Error(`YAML parsing ${filePath}: ${warning}`)
|
|
157
157
|
},
|
|
158
158
|
})
|
|
159
159
|
} else if (convert && filePath.indexOf('.json') != -1) {
|
package/src/party/combine.js
CHANGED
|
@@ -6,6 +6,8 @@ import cliSpinners from 'cli-spinners'
|
|
|
6
6
|
import fs from 'fs'
|
|
7
7
|
import * as xml2js from 'xml2js'
|
|
8
8
|
import * as fileUtils from '../lib/fileUtils.js'
|
|
9
|
+
import * as cidefault from 'ci-info'
|
|
10
|
+
const ci = cidefault.default
|
|
9
11
|
|
|
10
12
|
const spinner = cliSpinners['dots']
|
|
11
13
|
const processed = {
|
|
@@ -206,7 +208,9 @@ export class Combine {
|
|
|
206
208
|
that.#fileName.shortName,
|
|
207
209
|
)
|
|
208
210
|
}
|
|
209
|
-
|
|
211
|
+
try {
|
|
212
|
+
deleteFile(that, that.#fileName.fullName)
|
|
213
|
+
} catch (error) {}
|
|
210
214
|
return 'deleted'
|
|
211
215
|
}
|
|
212
216
|
}
|
|
@@ -316,29 +320,34 @@ export class Combine {
|
|
|
316
320
|
|
|
317
321
|
// iterate over fileList
|
|
318
322
|
fileList.forEach((file, index) => {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
.
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
323
|
+
if (!ci.isCI) {
|
|
324
|
+
logUpdate(
|
|
325
|
+
that.#spinnerMessage
|
|
326
|
+
.replace(
|
|
327
|
+
'[%1]',
|
|
328
|
+
that.sequence
|
|
329
|
+
.toString()
|
|
330
|
+
.padStart(
|
|
331
|
+
that.total.toString().length,
|
|
332
|
+
' ',
|
|
333
|
+
),
|
|
334
|
+
)
|
|
335
|
+
.replace(
|
|
336
|
+
'[%2]',
|
|
337
|
+
`\n${clc.magentaBright(
|
|
338
|
+
nextFrame(that),
|
|
339
|
+
)} ${key} - ${index + 1} of ${
|
|
340
|
+
fileList.length
|
|
341
|
+
} - ${clc.magentaBright(file)}`,
|
|
342
|
+
)
|
|
343
|
+
.replace('[%3]', `${that.#errorMessage}`)
|
|
344
|
+
.replace('[%4]', `${global.icons.working} `)
|
|
345
|
+
.replace(
|
|
346
|
+
'[%5]',
|
|
347
|
+
`${that.#fileName.shortName} `,
|
|
348
|
+
),
|
|
349
|
+
)
|
|
350
|
+
}
|
|
342
351
|
|
|
343
352
|
const fileObj = {
|
|
344
353
|
shortName: file,
|
|
@@ -410,7 +419,30 @@ export class Combine {
|
|
|
410
419
|
return true
|
|
411
420
|
}
|
|
412
421
|
|
|
413
|
-
|
|
422
|
+
const loginIpRanges =
|
|
423
|
+
fileObj.shortName.toLowerCase() ==
|
|
424
|
+
'loginIpRanges'.toLocaleLowerCase()
|
|
425
|
+
let loginIpRangesSandboxFile
|
|
426
|
+
let loginIpRangesSandbox = false
|
|
427
|
+
if (loginIpRanges) {
|
|
428
|
+
loginIpRangesSandboxFile = fileObj.fullName.replace(
|
|
429
|
+
`.${global.format}`,
|
|
430
|
+
`-sandbox.${global.format}`,
|
|
431
|
+
)
|
|
432
|
+
loginIpRangesSandbox = fileUtils.fileExists({
|
|
433
|
+
filePath: loginIpRangesSandboxFile,
|
|
434
|
+
fs,
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
const fileExists = fileUtils.fileExists({
|
|
438
|
+
filePath: fileObj.fullName,
|
|
439
|
+
fs,
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
if (
|
|
443
|
+
(!fileExists && !loginIpRanges) ||
|
|
444
|
+
(loginIpRanges && !fileExists && !loginIpRangesSandbox)
|
|
445
|
+
) {
|
|
414
446
|
// File does not exist
|
|
415
447
|
// If file is main part file, then return false to indicate that the XML file should be deleted
|
|
416
448
|
if (
|
|
@@ -468,6 +500,7 @@ export class Combine {
|
|
|
468
500
|
!global.metaTypes[
|
|
469
501
|
that.metadataDefinition.alias
|
|
470
502
|
].add.files.includes(fileObj.fullName) &&
|
|
503
|
+
!loginIpRangesSandbox &&
|
|
471
504
|
fileObj.fullName !==
|
|
472
505
|
path.join(
|
|
473
506
|
that.sourceDir,
|
|
@@ -479,8 +512,33 @@ export class Combine {
|
|
|
479
512
|
}
|
|
480
513
|
let result
|
|
481
514
|
try {
|
|
482
|
-
|
|
515
|
+
if (loginIpRanges) {
|
|
516
|
+
let loginIpRangesResult
|
|
517
|
+
let loginIpRangesSandboxResult
|
|
518
|
+
if (fileExists)
|
|
519
|
+
loginIpRangesResult = fileUtils.readFile(
|
|
520
|
+
fileObj.fullName,
|
|
521
|
+
)
|
|
522
|
+
if (loginIpRangesSandbox)
|
|
523
|
+
loginIpRangesSandboxResult = fileUtils.readFile(
|
|
524
|
+
loginIpRangesSandboxFile,
|
|
525
|
+
)
|
|
526
|
+
if (fileExists && loginIpRangesSandbox) {
|
|
527
|
+
result = mergeIpRanges(
|
|
528
|
+
loginIpRangesResult,
|
|
529
|
+
loginIpRangesSandboxResult,
|
|
530
|
+
)
|
|
531
|
+
} else if (fileExists) {
|
|
532
|
+
result = loginIpRangesResult
|
|
533
|
+
} else if (loginIpRangesSandbox) {
|
|
534
|
+
result = loginIpRangesSandboxResult
|
|
535
|
+
}
|
|
536
|
+
} else {
|
|
537
|
+
result = fileUtils.readFile(fileObj.fullName)
|
|
538
|
+
}
|
|
483
539
|
} catch (error) {
|
|
540
|
+
logUpdate(fileObj.fullName)
|
|
541
|
+
logUpdate.done()
|
|
484
542
|
throw error
|
|
485
543
|
}
|
|
486
544
|
if (
|
|
@@ -560,6 +618,24 @@ export class Combine {
|
|
|
560
618
|
}
|
|
561
619
|
}
|
|
562
620
|
|
|
621
|
+
// Function to merge arrays without duplicates
|
|
622
|
+
function mergeIpRanges(array1, array2) {
|
|
623
|
+
const combined = array1
|
|
624
|
+
|
|
625
|
+
array2.loginIpRanges.forEach((item2) => {
|
|
626
|
+
if (
|
|
627
|
+
!combined.loginIpRanges.some(
|
|
628
|
+
(item1) =>
|
|
629
|
+
JSON.stringify(item1) === JSON.stringify(item2),
|
|
630
|
+
)
|
|
631
|
+
) {
|
|
632
|
+
combined.loginIpRanges.push(item2)
|
|
633
|
+
}
|
|
634
|
+
})
|
|
635
|
+
|
|
636
|
+
return combined
|
|
637
|
+
}
|
|
638
|
+
|
|
563
639
|
updateFileStats(
|
|
564
640
|
that,
|
|
565
641
|
fileObj.fullName,
|
|
@@ -612,9 +688,7 @@ export class Combine {
|
|
|
612
688
|
) {
|
|
613
689
|
that.#fileStats.mtime = stats.mtime
|
|
614
690
|
}
|
|
615
|
-
} catch (error) {
|
|
616
|
-
throw error
|
|
617
|
-
}
|
|
691
|
+
} catch (error) {}
|
|
618
692
|
}
|
|
619
693
|
|
|
620
694
|
function saveXML(that) {
|
package/src/party/split.js
CHANGED
|
@@ -63,7 +63,7 @@ export class Split {
|
|
|
63
63
|
let fileName = fileUtils.fileInfo(value).filename
|
|
64
64
|
|
|
65
65
|
// Use actual file name if found so it matches case sensitivity
|
|
66
|
-
|
|
66
|
+
const foundFile = fileUtils.getFiles(path.dirname(value), fileName)
|
|
67
67
|
if (foundFile.length > 0) fileName = path.basename(foundFile[0])
|
|
68
68
|
|
|
69
69
|
this.#fileName.shortName = fileName.replace(
|
|
@@ -94,7 +94,7 @@ export class Split {
|
|
|
94
94
|
that.targetDir,
|
|
95
95
|
that.#fileName.shortName,
|
|
96
96
|
)
|
|
97
|
-
|
|
97
|
+
const parser = new Parser()
|
|
98
98
|
const getJSON = new Promise((resolve, reject) => {
|
|
99
99
|
fs.readFile(that.metaFilePath, function (err, data) {
|
|
100
100
|
parser.parseString(data, function (err, result) {
|
|
@@ -126,9 +126,7 @@ export class Split {
|
|
|
126
126
|
].xmlns.replace('http:', 'https:')
|
|
127
127
|
} catch (error) {
|
|
128
128
|
global.logger.error(
|
|
129
|
-
`${
|
|
130
|
-
that.#fileName.fullName
|
|
131
|
-
} has an invalid XML root`,
|
|
129
|
+
`${that.#fileName.fullName} has an invalid XML root`,
|
|
132
130
|
)
|
|
133
131
|
resolve(false)
|
|
134
132
|
return
|
|
@@ -136,9 +134,24 @@ export class Split {
|
|
|
136
134
|
|
|
137
135
|
// modify the json to remove unwanted arrays
|
|
138
136
|
that.#json = transformJSON(that, result, that.#root)
|
|
137
|
+
const sandboxLoginIpRange = fileUtils.readFile(
|
|
138
|
+
path.join(that.targetDir, 'loginIpRanges-sandbox.yaml'),
|
|
139
|
+
)
|
|
140
|
+
|
|
139
141
|
fileUtils.deleteDirectory(that.targetDir, true) // recursive delete existing directory
|
|
140
142
|
fileUtils.createDirectory(that.targetDir) // create directory
|
|
141
143
|
|
|
144
|
+
if (sandboxLoginIpRange) {
|
|
145
|
+
fileUtils.saveFile(
|
|
146
|
+
sandboxLoginIpRange,
|
|
147
|
+
path.join(
|
|
148
|
+
that.targetDir,
|
|
149
|
+
'loginIpRanges-sandbox.yaml',
|
|
150
|
+
),
|
|
151
|
+
'yaml',
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
142
155
|
try {
|
|
143
156
|
processJSON(
|
|
144
157
|
that,
|
|
@@ -217,8 +230,8 @@ export class Split {
|
|
|
217
230
|
}
|
|
218
231
|
|
|
219
232
|
function Main(that) {
|
|
220
|
-
|
|
221
|
-
|
|
233
|
+
const fileName = path.join(that.targetDir, `main.${global.format}`)
|
|
234
|
+
const mainInfo = {
|
|
222
235
|
main: {},
|
|
223
236
|
}
|
|
224
237
|
mainInfo.main.name = that.#fileName.shortName
|
|
@@ -255,9 +268,9 @@ export class Split {
|
|
|
255
268
|
}
|
|
256
269
|
|
|
257
270
|
function completeFile(that) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
271
|
+
const executionTime = getTimeDiff(BigInt(that.#startTime))
|
|
272
|
+
const durationMessage = `${executionTime.seconds}.${executionTime.milliseconds}s`
|
|
273
|
+
const stateIcon =
|
|
261
274
|
that.#errorMessage == ''
|
|
262
275
|
? global.icons.success
|
|
263
276
|
: global.icons.fail
|
|
@@ -333,7 +346,7 @@ function processFile(that, json, key, baseDir, fileNameOverride) {
|
|
|
333
346
|
}
|
|
334
347
|
|
|
335
348
|
function transformJSON(that, result, rootTag) {
|
|
336
|
-
|
|
349
|
+
const jsonString = JSON.stringify(result, (name, value) => {
|
|
337
350
|
if (Object.keys(that.metadataDefinition.sortKeys).includes(name)) {
|
|
338
351
|
return value
|
|
339
352
|
} else {
|
|
@@ -426,7 +439,7 @@ function xml2json(currentValue) {
|
|
|
426
439
|
|
|
427
440
|
function getTimeDiff(startTime, endTime = process.hrtime.bigint()) {
|
|
428
441
|
const diff = BigInt(endTime) - BigInt(startTime)
|
|
429
|
-
|
|
442
|
+
const executionTime = convertHrtime(diff)
|
|
430
443
|
executionTime.seconds = Math.round(executionTime.seconds)
|
|
431
444
|
executionTime.milliseconds = Math.round(executionTime.milliseconds / 1000)
|
|
432
445
|
if (executionTime.milliseconds == 0 && executionTime.nanoseconds > 0)
|