@ds-sfdc/sfparty 1.3.7 → 1.3.9
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/.prettierrc +9 -0
- package/package.json +3 -1
- package/pre-commit +4 -0
- package/src/index.js +752 -572
- package/src/lib/checkVersion.js +84 -62
- package/src/lib/fileUtils.js +175 -156
- package/src/lib/gitUtils.js +140 -112
- package/src/lib/packageUtil.js +232 -193
- package/src/lib/pkgObj.cjs +1 -0
- package/src/meta/CustomLabels.js +27 -24
- package/src/meta/Package.js +22 -21
- package/src/meta/PermissionSets.js +75 -66
- package/src/meta/Profiles.js +84 -81
- package/src/meta/Workflows.js +125 -55
- package/src/meta/yargs.js +98 -93
- package/src/party/combine.js +262 -97
- package/src/party/split.js +391 -314
- package/test/lib/package/getPackageXML.spec.js +69 -66
package/src/lib/checkVersion.js
CHANGED
|
@@ -2,73 +2,95 @@ import clc from 'cli-color'
|
|
|
2
2
|
import semver from 'semver'
|
|
3
3
|
|
|
4
4
|
class NpmNotInstalledError extends Error {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message)
|
|
7
|
+
this.name = 'NpmNotInstalledError'
|
|
8
|
+
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
class PackageNotFoundError extends Error {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message)
|
|
14
|
+
this.name = 'PackageNotFoundError'
|
|
15
|
+
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
class UpdateError extends Error {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message)
|
|
21
|
+
this.name = 'UpdateError'
|
|
22
|
+
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export async function checkVersion({
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
25
|
+
export async function checkVersion({
|
|
26
|
+
axios,
|
|
27
|
+
spawnSync,
|
|
28
|
+
currentVersion,
|
|
29
|
+
update = false,
|
|
30
|
+
}) {
|
|
31
|
+
try {
|
|
32
|
+
const { data } = await axios.get(
|
|
33
|
+
'https://registry.npmjs.org/@ds-sfdc/sfparty',
|
|
34
|
+
{
|
|
35
|
+
params: {
|
|
36
|
+
field: 'dist-tags.latest',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
)
|
|
40
|
+
const latestVersion = data['dist-tags'].latest
|
|
41
|
+
if (semver.gt(latestVersion, currentVersion)) {
|
|
42
|
+
const version = clc.bgCyanBright(data['dist-tags'].latest)
|
|
43
|
+
const icon = update ? global.icons.working : global.icons.fail
|
|
44
|
+
console.log()
|
|
45
|
+
console.log(`${icon} A newer version ${version} is available.`)
|
|
46
|
+
if (!update) {
|
|
47
|
+
console.log(
|
|
48
|
+
`Please upgrade by running ${clc.cyanBright(
|
|
49
|
+
'sfparty update',
|
|
50
|
+
)}`,
|
|
51
|
+
)
|
|
52
|
+
return 'A newer version'
|
|
53
|
+
} else {
|
|
54
|
+
let command = 'npm i -g @ds-sfdc/sfparty@latest'.split(' ')
|
|
55
|
+
console.log(
|
|
56
|
+
`Updating the application using ${clc.cyanBright(
|
|
57
|
+
command.join(' '),
|
|
58
|
+
)}`,
|
|
59
|
+
)
|
|
60
|
+
try {
|
|
61
|
+
const npmVersion = spawnSync('npm', ['-v'])
|
|
62
|
+
if (
|
|
63
|
+
npmVersion.stderr &&
|
|
64
|
+
npmVersion.stderr.toString().trim() ===
|
|
65
|
+
'command not found'
|
|
66
|
+
) {
|
|
67
|
+
throw new NpmNotInstalledError(
|
|
68
|
+
'npm is not installed on this system. Please install npm and run the command again.',
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
const update = spawnSync(command[0], command.slice(1))
|
|
72
|
+
if (update.status !== 0) {
|
|
73
|
+
throw new UpdateError('Error updating the application.')
|
|
74
|
+
}
|
|
75
|
+
console.log('Application updated successfully.')
|
|
76
|
+
} catch (err) {
|
|
77
|
+
throw err
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
if (update) {
|
|
82
|
+
console.log(
|
|
83
|
+
`${global.icons.success} You are on the latest version.`,
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
return 'You are on the latest version'
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (error.response && error.response.status === 404) {
|
|
90
|
+
error = new PackageNotFoundError(
|
|
91
|
+
'Package not found on the npm registry',
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
throw error
|
|
95
|
+
}
|
|
96
|
+
}
|
package/src/lib/fileUtils.js
CHANGED
|
@@ -5,193 +5,212 @@ import * as yaml from 'js-yaml'
|
|
|
5
5
|
import { Parser } from 'xml2js'
|
|
6
6
|
|
|
7
7
|
export function directoryExists(dirPath, fsTmp = fs) {
|
|
8
|
-
|
|
8
|
+
return fsTmp.existsSync(dirPath) && fsTmp.statSync(dirPath).isDirectory()
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export function fileExists(filePath, fsTmp = fs) {
|
|
12
|
-
|
|
12
|
+
return fsTmp.existsSync(filePath) && fsTmp.statSync(filePath).isFile()
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function createDirectory(dirPath, fsTmp = fs) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
if (!fsTmp.existsSync(dirPath)) {
|
|
17
|
+
fsTmp.mkdirSync(dirPath, { recursive: true })
|
|
18
|
+
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export function deleteDirectory(dirPath, recursive = false, fsTmp = fs) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
22
|
+
if (!directoryExists(dirPath, fsTmp)) {
|
|
23
|
+
return false
|
|
24
|
+
} else {
|
|
25
|
+
if (fsTmp.existsSync(dirPath)) {
|
|
26
|
+
fsTmp.readdirSync(dirPath).forEach(function (file) {
|
|
27
|
+
var curPath = path.join(dirPath, file)
|
|
28
|
+
if (fsTmp.lstatSync(curPath).isDirectory() && recursive) {
|
|
29
|
+
// recurse
|
|
30
|
+
deleteDirectory(curPath, recursive, fsTmp)
|
|
31
|
+
} else {
|
|
32
|
+
// delete file
|
|
33
|
+
fsTmp.unlinkSync(curPath)
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
return fsTmp.rmdirSync(dirPath)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export function getFiles(dirPath, filter = undefined, fsTmp = fs) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
42
|
+
const filesList = []
|
|
43
|
+
if (directoryExists(dirPath, fsTmp)) {
|
|
44
|
+
fsTmp.readdirSync(dirPath).forEach((file) => {
|
|
45
|
+
if (!filter) {
|
|
46
|
+
filesList.push(file)
|
|
47
|
+
} else {
|
|
48
|
+
if (
|
|
49
|
+
file
|
|
50
|
+
.toLocaleLowerCase()
|
|
51
|
+
.endsWith(filter.toLocaleLowerCase())
|
|
52
|
+
) {
|
|
53
|
+
filesList.push(file)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
filesList.sort()
|
|
58
|
+
return filesList
|
|
59
|
+
} else {
|
|
60
|
+
return []
|
|
61
|
+
}
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
export function getDirectories(dirPath, fsTmp = fs) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
if (directoryExists(dirPath, fsTmp)) {
|
|
66
|
+
return fsTmp
|
|
67
|
+
.readdirSync(dirPath, { withFileTypes: true })
|
|
68
|
+
.filter((dirent) => dirent.isDirectory())
|
|
69
|
+
.map((dirent) => dirent.name)
|
|
70
|
+
} else {
|
|
71
|
+
return []
|
|
72
|
+
}
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
export function deleteFile(filePath, fsTmp = fs) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
if (!fileExists(filePath, fsTmp)) {
|
|
77
|
+
return false
|
|
78
|
+
} else {
|
|
79
|
+
return fsTmp.unlinkSync(filePath, { recursive: false, force: true })
|
|
80
|
+
}
|
|
74
81
|
}
|
|
75
82
|
|
|
76
83
|
export function fileInfo(filePath, fsTmp = fs) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
return {
|
|
85
|
+
dirname: path.join(path.dirname(filePath)), //something/folder/example
|
|
86
|
+
basename: path.basename(filePath, path.extname(filePath)), //example
|
|
87
|
+
filename: path.basename(filePath), //example.txt
|
|
88
|
+
extname: path.extname(filePath), //txt
|
|
89
|
+
exists: fsTmp.existsSync(filePath), //true if exists or false if not exists
|
|
90
|
+
stats: fsTmp.existsSync(filePath)
|
|
91
|
+
? fsTmp.statSync(filePath)
|
|
92
|
+
: undefined, //stats object if exists or undefined if not exists
|
|
93
|
+
}
|
|
85
94
|
}
|
|
86
95
|
|
|
87
|
-
export function saveFile(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
export function saveFile(
|
|
97
|
+
json,
|
|
98
|
+
fileName,
|
|
99
|
+
format = path.extname(fileName).replace('.', ''),
|
|
100
|
+
fsTmp = fs,
|
|
101
|
+
) {
|
|
102
|
+
try {
|
|
103
|
+
switch (format) {
|
|
104
|
+
case 'json':
|
|
105
|
+
let jsonString = JSON.stringify(json, null, '\t')
|
|
106
|
+
fsTmp.writeFileSync(fileName, jsonString)
|
|
107
|
+
break
|
|
108
|
+
case 'yaml':
|
|
109
|
+
let doc = yaml.dump(json)
|
|
110
|
+
fsTmp.writeFileSync(fileName, doc)
|
|
111
|
+
break
|
|
112
|
+
}
|
|
113
|
+
return true
|
|
114
|
+
} catch (error) {
|
|
115
|
+
global.logger.error(error)
|
|
116
|
+
throw error
|
|
117
|
+
}
|
|
104
118
|
}
|
|
105
119
|
|
|
106
120
|
export function readFile(fileName, convert = true, fsTmp = fs) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
try {
|
|
122
|
+
let result = undefined
|
|
123
|
+
if (fileExists(fileName, fsTmp)) {
|
|
124
|
+
const data = fsTmp.readFileSync(fileName, {
|
|
125
|
+
encoding: 'utf8',
|
|
126
|
+
flag: 'r',
|
|
127
|
+
})
|
|
128
|
+
if (convert && fileName.indexOf('.yaml') != -1) {
|
|
129
|
+
result = yaml.load(data)
|
|
130
|
+
} else if (convert && fileName.indexOf('.json') != -1) {
|
|
131
|
+
result = JSON.parse(data)
|
|
132
|
+
} else if (convert && fileName.indexOf('.xml') != -1) {
|
|
133
|
+
// returns a promise
|
|
134
|
+
result = convertXML(data)
|
|
135
|
+
} else {
|
|
136
|
+
result = data
|
|
137
|
+
}
|
|
138
|
+
return result
|
|
139
|
+
} else {
|
|
140
|
+
return undefined
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
global.logger.error(error)
|
|
144
|
+
throw error
|
|
145
|
+
}
|
|
129
146
|
}
|
|
130
147
|
|
|
131
148
|
async function convertXML(data) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
try {
|
|
151
|
+
let parser = new Parser()
|
|
152
|
+
parser.parseString(data, function (err, result) {
|
|
153
|
+
if (err) throw err
|
|
154
|
+
resolve(result)
|
|
155
|
+
})
|
|
156
|
+
} catch (error) {
|
|
157
|
+
reject(error)
|
|
158
|
+
}
|
|
159
|
+
})
|
|
143
160
|
}
|
|
144
161
|
|
|
145
|
-
export function writeFile(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
export function writeFile(
|
|
163
|
+
fileName,
|
|
164
|
+
data,
|
|
165
|
+
atime = new Date(),
|
|
166
|
+
mtime = new Date(),
|
|
167
|
+
fsTmp = fs,
|
|
168
|
+
) {
|
|
169
|
+
try {
|
|
170
|
+
// write data to the file
|
|
171
|
+
fsTmp.writeFileSync(fileName, data)
|
|
172
|
+
|
|
173
|
+
// if atime or mtime are undefined, use current date/time
|
|
174
|
+
if (atime === undefined) atime = new Date()
|
|
175
|
+
if (mtime === undefined) mtime = new Date()
|
|
176
|
+
|
|
177
|
+
// update XML file to match the latest atime and mtime of the files processed
|
|
178
|
+
fsTmp.utimesSync(fileName, atime, mtime)
|
|
179
|
+
} catch (error) {
|
|
180
|
+
global.logger.error(error)
|
|
181
|
+
throw error
|
|
182
|
+
}
|
|
161
183
|
}
|
|
162
184
|
|
|
163
185
|
export function find(filename, root, fsTmp = fs) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return findFile(root, filename)
|
|
197
|
-
}
|
|
186
|
+
// code Copyright (c) 2014, Ben Gourley
|
|
187
|
+
// https://github.com/bengourley/find-nearest-file
|
|
188
|
+
root = root || process.cwd()
|
|
189
|
+
|
|
190
|
+
if (!filename) throw new Error('filename is required')
|
|
191
|
+
|
|
192
|
+
if (filename.indexOf('/') !== -1 || filename === '..') {
|
|
193
|
+
throw new Error('filename must be just a filename and not a path')
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function findFile(directory, filename) {
|
|
197
|
+
var file = path.join(directory, filename)
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
if (fsTmp.statSync(file).isFile()) return file
|
|
201
|
+
// stat existed, but isFile() returned false
|
|
202
|
+
return nextLevelUp()
|
|
203
|
+
} catch (e) {
|
|
204
|
+
// stat did not exist
|
|
205
|
+
return nextLevelUp()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function nextLevelUp() {
|
|
209
|
+
// Don't proceed to the next directory when already at the fs root
|
|
210
|
+
if (directory === path.resolve('/')) return null
|
|
211
|
+
return findFile(path.dirname(directory), filename)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return findFile(root, filename)
|
|
216
|
+
}
|