@ds-sfdc/sfparty 1.5.7 → 1.7.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ds-sfdc/sfparty",
3
- "version": "1.5.7",
3
+ "version": "1.7.0",
4
4
  "description": "Salesforce metadata XML splitter for CI/CD",
5
5
  "type": "module",
6
6
  "repository": {
@@ -21,32 +21,33 @@
21
21
  "author": "Tim Paulaskas",
22
22
  "license": "BSD-3-Clause",
23
23
  "dependencies": {
24
- "axios": "^1.6.8",
24
+ "axios": "^1.7.2",
25
+ "ci-info": "^4.0.0",
25
26
  "cli-color": "^2.0.4",
26
- "cli-spinners": "^2.9.2",
27
+ "cli-spinners": "^3.0.0",
27
28
  "convert-hrtime": "^5.0.0",
28
29
  "js-yaml": "^4.1.0",
29
30
  "log-update": "^6.0.0",
30
31
  "marked": "^12.0.2",
31
32
  "marked-terminal": "^7.0.0",
32
33
  "pretty-quick": "^4.0.0",
33
- "semver": "^7.6.0",
34
+ "semver": "^7.6.2",
34
35
  "util": "^0.12.5",
35
36
  "winston": "^3.13.0",
36
37
  "xml2js": "^0.6.2",
37
38
  "yargs": "^17.7.2"
38
39
  },
39
40
  "devDependencies": {
40
- "@babel/core": "^7.24.4",
41
- "@babel/preset-env": "^7.24.4",
42
- "@commitlint/cli": "^19.2.2",
41
+ "@babel/core": "^7.24.6",
42
+ "@babel/preset-env": "^7.24.6",
43
+ "@commitlint/cli": "^19.3.0",
43
44
  "@commitlint/config-conventional": "^19.2.2",
44
45
  "babel-jest": "^29.7.0",
45
- "eslint": "^9.1.0",
46
+ "eslint": "^9.3.0",
46
47
  "husky": "^9.0.11",
47
48
  "jest": "^29.7.0",
48
- "lint-staged": "^15.2.2",
49
- "nodemon": "^3.1.0",
49
+ "lint-staged": "^15.2.5",
50
+ "nodemon": "^3.1.1",
50
51
  "prettier": "^3.2.5"
51
52
  },
52
53
  "engines": {
@@ -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 warning: ${warning}`)
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) {
@@ -84,5 +84,5 @@ export const metadataDefinition = {
84
84
  userPermissions: ['name', 'enabled'],
85
85
  },
86
86
  xmlFirst: 'fullName',
87
- delta: false,
87
+ delta: true,
88
88
  }
@@ -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
- deleteFile(that, that.#fileName.fullName)
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
- logUpdate(
320
- that.#spinnerMessage
321
- .replace(
322
- '[%1]',
323
- that.sequence
324
- .toString()
325
- .padStart(
326
- that.total.toString().length,
327
- ' ',
328
- ),
329
- )
330
- .replace(
331
- '[%2]',
332
- `\n${clc.magentaBright(
333
- nextFrame(that),
334
- )} ${key} - ${index + 1} of ${
335
- fileList.length
336
- } - ${clc.magentaBright(file)}`,
337
- )
338
- .replace('[%3]', `${that.#errorMessage}`)
339
- .replace('[%4]', `${global.icons.working} `)
340
- .replace('[%5]', `${that.#fileName.shortName} `),
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
- if (!fileUtils.fileExists({ filePath: fileObj.fullName, fs })) {
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
- result = fileUtils.readFile(fileObj.fullName)
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) {
@@ -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
- let foundFile = fileUtils.getFiles(path.dirname(value), fileName)
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
- let parser = new Parser()
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
- let fileName = path.join(that.targetDir, `main.${global.format}`)
221
- let mainInfo = {
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
- let executionTime = getTimeDiff(BigInt(that.#startTime))
259
- let durationMessage = `${executionTime.seconds}.${executionTime.milliseconds}s`
260
- let stateIcon =
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
- let jsonString = JSON.stringify(result, (name, value) => {
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
- let executionTime = convertHrtime(diff)
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)