@ds-sfdc/sfparty 1.3.6 → 1.3.8

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.3.6",
3
+ "version": "1.3.8",
4
4
  "description": "Salesforce metadata XML splitter for CI/CD",
5
5
  "type": "module",
6
6
  "repository": {
package/src/index.js CHANGED
@@ -11,7 +11,7 @@ import convertHrtime from 'convert-hrtime'
11
11
  import axios from 'axios'
12
12
  import { marked } from 'marked'
13
13
  import markedTerminal from 'marked-terminal'
14
- import * as pkgObj from '../package.json' assert { type: "json" }
14
+ import pkgObj from './lib/pkgObj.cjs'
15
15
  import * as fileUtils from './lib/fileUtils.js'
16
16
  import * as yargOptions from './meta/yargs.js'
17
17
  import * as metadataSplit from './party/split.js'
@@ -139,7 +139,7 @@ yargs(hideBin(process.argv))
139
139
  .check(yargCheck)
140
140
  },
141
141
  handler: (argv) => {
142
- checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version, update: true})
142
+ checkVersion({axios, spawnSync, currentVersion: pkgObj.version, update: true})
143
143
  }
144
144
  })
145
145
  .command({
@@ -162,7 +162,6 @@ yargs(hideBin(process.argv))
162
162
  .check(yargCheck)
163
163
  },
164
164
  handler: (argv) => {
165
- checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version})
166
165
  global.format = argv.format
167
166
  splitHandler(argv, processStartTime)
168
167
  }
@@ -179,7 +178,6 @@ yargs(hideBin(process.argv))
179
178
  .check(yargCheck)
180
179
  },
181
180
  handler: (argv) => {
182
- checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version})
183
181
  global.format = argv.format
184
182
  const startProm = new Promise((resolve, reject) => {
185
183
  if (argv.git !== undefined) {
@@ -193,11 +191,10 @@ yargs(hideBin(process.argv))
193
191
  global.git.latest = data.latestCommit
194
192
  global.git.last = data.lastCommit
195
193
  if (data.last === undefined) {
196
- console.log(`${clc.yellowBright('git mode')} ${clc.bgMagentaBright('not active:')} no prior commit - processing all`)
194
+ gitMode({status: 'not active'})
197
195
  resolve(false)
198
196
  } else {
199
- console.log(`${clc.yellowBright('git mode')} ${clc.magentaBright('active:')} ${clc.bgBlackBright(data.lastCommit) + '..' + clc.bgBlackBright(data.latestCommit)}`)
200
- console.log()
197
+ gitMode({status: 'active', lastCommit: data.lastCommit, latestCommit: data.latestCommit})
201
198
  const diff = git.diff(global.__basedir, `${data.lastCommit}..${data.latestCommit}`)
202
199
  diff
203
200
  .then((data, error) => {
@@ -215,8 +212,7 @@ yargs(hideBin(process.argv))
215
212
  throw error
216
213
  })
217
214
  } else {
218
- console.log(`${clc.yellowBright('git mode')} ${clc.magentaBright('active:')} ${clc.bgBlackBright(gitRef)}`)
219
- console.log()
215
+ gitMode({status: 'active', gitRef})
220
216
  const diff = git.diff(global.__basedir, gitRef)
221
217
  diff
222
218
  .then((data, error) => {
@@ -252,6 +248,26 @@ yargs(hideBin(process.argv))
252
248
  .argv
253
249
  .parse
254
250
 
251
+ function gitMode({ status, gitRef, lastCommit, latestCommit }) {
252
+ let statusMessage
253
+ let displayMessage
254
+ if (status == 'not active') {
255
+ statusMessage = clc.bgMagentaBright('not active:')
256
+ displayMessage = `no prior commit - processing all`
257
+ } else {
258
+ statusMessage = clc.magentaBright('active:')
259
+ if (gitRef === undefined) {
260
+ displayMessage = `${clc.bgBlackBright(data.lastCommit) + '..' + clc.bgBlackBright(data.latestCommit)}`
261
+ console.log(`${clc.yellowBright('git mode')} ${clc.magentaBright('active:')} ${clc.bgBlackBright(data.lastCommit) + '..' + clc.bgBlackBright(data.latestCommit)}`)
262
+ } else {
263
+ displayMessage = `${clc.magentaBright('active:')} ${clc.bgBlackBright(gitRef)}`
264
+ console.log(`${clc.yellowBright('git mode')} ${clc.magentaBright('active:')} ${clc.bgBlackBright(gitRef)}`)
265
+ }
266
+ }
267
+ console.log(`${clc.yellowBright('git mode')} ${status}:)} ${displayMessage}`)
268
+ console.log()
269
+ }
270
+
255
271
  function yargCheck(argv, options) {
256
272
  const argvKeys = Object.keys(argv)
257
273
  const invalidKeys = argvKeys.filter(key =>
@@ -262,7 +278,7 @@ function yargCheck(argv, options) {
262
278
  )
263
279
 
264
280
  if (!argv._.includes('update')) {
265
- checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version, update: false})
281
+ checkVersion({axios, spawnSync, currentVersion: pkgObj.version, update: false})
266
282
  }
267
283
 
268
284
  if (invalidKeys.length > 0) {
@@ -614,7 +630,7 @@ function displayHeader() {
614
630
  horizontal: '─',
615
631
  vertical: '│',
616
632
  }
617
- let versionString = `sfparty v${pkgObj.default.version}${(process.stdout.columns > pkgObj.default.description.length + 15) ? ' - ' + pkgObj.default.description : ''}`
633
+ let versionString = `sfparty v${pkgObj.version}${(process.stdout.columns > pkgObj.description.length + 15) ? ' - ' + pkgObj.description : ''}`
618
634
  let titleMessage = `${global.icons.party} ${clc.yellowBright(versionString)} ${global.icons.party}`
619
635
  titleMessage = titleMessage.padEnd((process.stdout.columns / 2) + versionString.length / 1.65)
620
636
  titleMessage = titleMessage.padStart(process.stdout.columns)
@@ -22,7 +22,7 @@ class UpdateError extends Error {
22
22
  }
23
23
  }
24
24
 
25
- export async function checkVersion({axios, spawnSync, currentVersion, update = false}) {
25
+ export async function checkVersion({ axios, spawnSync, currentVersion, update = false }) {
26
26
  try {
27
27
  const { data } = await axios.get('https://registry.npmjs.org/@ds-sfdc/sfparty', {
28
28
  params: {
@@ -31,13 +31,9 @@ export async function checkVersion({axios, spawnSync, currentVersion, update = f
31
31
  })
32
32
  const latestVersion = data['dist-tags'].latest
33
33
  if (semver.gt(latestVersion, currentVersion)) {
34
- let icon
35
34
  const version = clc.bgCyanBright(data['dist-tags'].latest)
36
- if (update) {
37
- icon = global.icons.working
38
- } else {
39
- icon = global.icons.fail
40
- }
35
+ const icon = (update) ? global.icons.working : global.icons.fail
36
+ console.log()
41
37
  console.log(`${icon} A newer version ${version} is available.`)
42
38
  if (!update) {
43
39
  console.log(`Please upgrade by running ${clc.cyanBright('sfparty update')}`)
@@ -25,7 +25,6 @@ export class Package {
25
25
  processJSON(that, json, fileUtils)
26
26
  resolve('existing')
27
27
  } catch (error) {
28
- console.error(error)
29
28
  reject(error)
30
29
  }
31
30
  })
@@ -49,12 +48,27 @@ export class Package {
49
48
 
50
49
  function processJSON(that, json, fileUtils) {
51
50
  try {
52
- json.Package.version = fileUtils.readFile(path.join(global.__basedir, 'sfdx-project.json')).sourceApiVersion
51
+ let data = fileUtils.readFile(path.join(global.__basedir, 'sfdx-project.json'))
52
+ json.Package.version = data.sourceApiVersion
53
53
  } catch (error) {
54
54
  json.Package.version = packageDefinition.metadataDefinition.fallbackVersion
55
55
  }
56
56
  that.packageJSON = json
57
57
  if (json.Package.types !== undefined) transformJSON(json.Package.types)
58
+ cleanPackage(that)
59
+ }
60
+
61
+ function cleanPackage(that) {
62
+ if (that.packageJSON === undefined) throw new Error('getPackageXML must be called before adding members')
63
+ if (that.packageJSON.Package == undefined) throw new Error('Package initialization failed')
64
+ if (that.packageJSON.Package.types === undefined) return 'No types found'
65
+
66
+ const typeArray = Object.values(global.metaTypes).map(metaType => metaType.definition.root);
67
+ that.packageJSON.Package.types.forEach(typeItem => {
68
+ if (typeArray.includes(typeItem.name)) {
69
+ typeItem.members = typeItem.members.filter(member => !member.endsWith(`.${global.format}`))
70
+ }
71
+ })
58
72
  }
59
73
  }
60
74
 
@@ -0,0 +1 @@
1
+ module.exports = pkgObj = require('../../package.json')
@@ -53,5 +53,14 @@ export const metadataDefinition = {
53
53
  'rules': ['fullName'],
54
54
  'outboundMessages': ['fullName'],
55
55
  'tasks': ['fullName'],
56
+ },
57
+ package: {
58
+ 'alerts': 'WorkflowAlert',
59
+ 'fieldUpdates': 'WorkflowFieldUpdate',
60
+ 'flowActions': 'WorkflowFlowAction',
61
+ 'knowledgePublishes': 'WorkflowKnowledgePublish',
62
+ 'outboundMessages': 'WorkflowOutboundMessage',
63
+ 'rules': 'WorkflowRule',
64
+ 'tasks': ' WorkflowTask',
56
65
  }
57
66
  }
@@ -1,7 +1,7 @@
1
1
  import axios from 'axios'
2
2
  import { spawnSync } from 'child_process'
3
3
  import clc from 'cli-color'
4
- import { checkVersion } from '../src/lib/checkVersion.js'
4
+ import { checkVersion } from '../../src/lib/checkVersion.js'
5
5
 
6
6
  global.icons = {
7
7
  "success": clc.greenBright('✔'),
@@ -1,57 +1,171 @@
1
+
1
2
  import * as packageDefinition from '../../../src/meta/Package.js'
2
3
  import { Package } from '../../../src/lib/packageUtil.js'
4
+ import * as labelDefinition from '../../../src/meta/CustomLabels.js'
5
+ import * as profileDefinition from '../../../src/meta/Profiles.js'
6
+ import * as permsetDefinition from '../../../src/meta/PermissionSets.js'
7
+ import * as workflowDefinition from '../../../src/meta/Workflows.js'
8
+
9
+ global.__basedir = '.'
10
+ global.format = 'yaml'
11
+ global.metaTypes = {
12
+ label: {
13
+ type: labelDefinition.metadataDefinition.filetype,
14
+ definition: labelDefinition.metadataDefinition,
15
+ add: { files: [], directories: [] },
16
+ remove: { files: [], directories: [] },
17
+ },
18
+ profile: {
19
+ type: profileDefinition.metadataDefinition.filetype,
20
+ definition: profileDefinition.metadataDefinition,
21
+ add: { files: [], directories: [] },
22
+ remove: { files: [], directories: [] },
23
+ },
24
+ permset: {
25
+ type: permsetDefinition.metadataDefinition.filetype,
26
+ definition: permsetDefinition.metadataDefinition,
27
+ add: { files: [], directories: [] },
28
+ remove: { files: [], directories: [] },
29
+ },
30
+ workflow: {
31
+ type: workflowDefinition.metadataDefinition.filetype,
32
+ definition: workflowDefinition.metadataDefinition,
33
+ add: { files: [], directories: [] },
34
+ remove: { files: [], directories: [] },
35
+ },
36
+ }
3
37
 
4
- let pkg;
38
+ let pkg
5
39
  const fileUtils = {
6
40
  fileExists: jest.fn(),
7
41
  readFile: jest.fn(),
8
42
  }
9
43
  beforeEach(() => {
10
- pkg = new Package('xmlPath');
11
- });
12
- global.__basedir = '.'
44
+ pkg = new Package('xmlPath')
45
+ })
46
+
47
+
13
48
  afterEach(() => {
14
- jest.clearAllMocks();
15
- });
49
+ jest.clearAllMocks()
50
+ })
16
51
 
17
52
  it('should default the package if the json is empty', async () => {
18
- fileUtils.fileExists.mockReturnValue(true);
19
- fileUtils.readFile.mockResolvedValue({});
53
+ fileUtils.fileExists.mockReturnValue(true)
54
+ fileUtils.readFile.mockResolvedValue({})
20
55
  global.git = { append: true }
21
- const result = await pkg.getPackageXML(fileUtils);
22
- expect(result).toBe('existing');
23
- expect(fileUtils.fileExists).toHaveBeenCalled();
24
- expect(fileUtils.readFile).toHaveBeenCalled();
25
- expect(pkg.packageJSON).toEqual(packageDefinition.metadataDefinition.emptyPackage);
26
- });
56
+ const result = await pkg.getPackageXML(fileUtils)
57
+ expect(result).toBe('existing')
58
+ expect(fileUtils.fileExists).toHaveBeenCalled()
59
+ expect(fileUtils.readFile).toHaveBeenCalled()
60
+ expect(pkg.packageJSON).toEqual(packageDefinition.metadataDefinition.emptyPackage)
61
+ })
27
62
 
28
63
  it('should read an existing file and call processJSON', async () => {
29
- fileUtils.fileExists.mockReturnValue(true);
30
- fileUtils.readFile.mockResolvedValue(packageDefinition.metadataDefinition.emptyPackage);
64
+ fileUtils.fileExists.mockReturnValue(true)
65
+ fileUtils.readFile.mockResolvedValue(packageDefinition.metadataDefinition.emptyPackage)
31
66
  global.git = { append: true }
32
- const result = await pkg.getPackageXML(fileUtils);
33
- expect(result).toBe('existing');
34
- expect(fileUtils.fileExists).toHaveBeenCalled();
35
- expect(fileUtils.readFile).toHaveBeenCalled();
36
- });
67
+ const result = await pkg.getPackageXML(fileUtils)
68
+ expect(result).toBe('existing')
69
+ expect(fileUtils.fileExists).toHaveBeenCalled()
70
+ expect(fileUtils.readFile).toHaveBeenCalled()
71
+ })
37
72
 
38
73
  it('should create an empty pkg JSON and call processJSON', async () => {
39
- fileUtils.fileExists.mockReturnValue(false);
74
+ fileUtils.fileExists.mockReturnValue(false)
40
75
  const finalJSON = JSON.parse(JSON.stringify(packageDefinition.metadataDefinition.emptyPackage))
41
76
  finalJSON.Package.version = packageDefinition.metadataDefinition.fallbackVersion
42
- const result = await pkg.getPackageXML(fileUtils);
43
- expect(result).toBe('not found');
44
- expect(fileUtils.fileExists).toHaveBeenCalled();
45
- expect(pkg.packageJSON).toEqual(finalJSON);
46
- });
77
+ const result = await pkg.getPackageXML(fileUtils)
78
+ expect(result).toBe('not found')
79
+ expect(fileUtils.fileExists).toHaveBeenCalled()
80
+ expect(pkg.packageJSON).toEqual(finalJSON)
81
+ })
47
82
 
48
83
  it('should throw an error if xmlPath is undefined', async () => {
49
- pkg.xmlPath = undefined;
50
- await expect(pkg.getPackageXML(fileUtils)).rejects.toThrowError('Package not initialized');
51
- });
84
+ pkg.xmlPath = undefined
85
+ await expect(pkg.getPackageXML(fileUtils)).rejects.toThrowError('Package not initialized')
86
+ })
52
87
 
53
88
  it('should throw an error if error occurs during processing', async () => {
54
- fileUtils.fileExists.mockReturnValue(true);
55
- fileUtils.readFile.mockRejectedValue(new Error('Error'));
56
- await expect(pkg.getPackageXML(fileUtils)).rejects.toThrowError('Error');
57
- });
89
+ fileUtils.fileExists.mockReturnValue(true)
90
+ fileUtils.readFile.mockRejectedValue(new Error('Error'))
91
+ await expect(pkg.getPackageXML(fileUtils)).rejects.toThrowError('Error')
92
+ })
93
+
94
+ it('should catch errors and reject the promise', async () => {
95
+ fileUtils.fileExists.mockReturnValue(true)
96
+ fileUtils.readFile.mockRejectedValue(new Error('Test Error'))
97
+ global.git = { append: true }
98
+ try {
99
+ await pkg.getPackageXML(fileUtils)
100
+ } catch (error) {
101
+ expect(error.message).toEqual('Test Error')
102
+ }
103
+ })
104
+
105
+ it('should default to an empty package if the read file is empty', async () => {
106
+ fileUtils.fileExists.mockReturnValue(true)
107
+ fileUtils.readFile.mockResolvedValue('')
108
+ global.git = { append: true }
109
+ const result = await pkg.getPackageXML(fileUtils)
110
+ expect(result).toBe('existing')
111
+ expect(pkg.packageJSON).toEqual(packageDefinition.metadataDefinition.emptyPackage)
112
+ expect(fileUtils.fileExists).toHaveBeenCalled()
113
+ expect(fileUtils.readFile).toHaveBeenCalled()
114
+ })
115
+
116
+ it('should throw an error if fileUtils.readFile() returns a rejected promise', async () => {
117
+ fileUtils.fileExists.mockReturnValue(true)
118
+ fileUtils.readFile.mockRejectedValue(new Error('Test Error'))
119
+ global.git = { append: true }
120
+ await expect(pkg.getPackageXML(fileUtils)).rejects.toThrowError('Test Error')
121
+ expect(fileUtils.fileExists).toHaveBeenCalled()
122
+ expect(fileUtils.readFile).toHaveBeenCalled()
123
+ })
124
+
125
+ it('should correctly process the json object returned from the XML file', async () => {
126
+ fileUtils.fileExists.mockReturnValue(true)
127
+ fileUtils.readFile.mockResolvedValueOnce({
128
+ "Package": {
129
+ "types": [{
130
+ "members": ["Test", "Test.yaml"],
131
+ "name": "CustomLabels"
132
+ }, {
133
+ "members": ["Test", "Test.yaml"],
134
+ "name": "Profile"
135
+ }, {
136
+ "members": ["Test", "Test.yaml"],
137
+ "name": "PermissionSet"
138
+ }, {
139
+ "members": ["Test", "Test.yaml"],
140
+ "name": "Workflow"
141
+ }],
142
+ "version": "56.0"
143
+ }
144
+ })
145
+ fileUtils.readFile.mockImplementationOnce(() => {
146
+ return { sourceApiVersion: '56.0' }
147
+ })
148
+ global.git = { append: true }
149
+ const result = await pkg.getPackageXML(fileUtils)
150
+ expect(result).toBe('existing')
151
+ expect(fileUtils.fileExists).toHaveBeenCalled()
152
+ expect(fileUtils.readFile).toHaveBeenCalled()
153
+ expect(pkg.packageJSON).toEqual({
154
+ "Package": {
155
+ "types": [{
156
+ "members": ["Test"],
157
+ "name": "CustomLabels"
158
+ }, {
159
+ "members": ["Test"],
160
+ "name": "Profile"
161
+ }, {
162
+ "members": ["Test"],
163
+ "name": "PermissionSet"
164
+ }, {
165
+ "members": ["Test"],
166
+ "name": "Workflow"
167
+ }],
168
+ "version": "56.0"
169
+ }
170
+ })
171
+ })
File without changes