@ds-sfdc/sfparty 1.0.0 → 1.1.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 +69 -2
- package/package.json +1 -1
- package/src/index.js +259 -306
- package/src/meta/yargs.js +75 -0
- package/src/party/combine.js +17 -4
- package/src/party/split.js +18 -6
package/README.md
CHANGED
|
@@ -13,6 +13,73 @@ npm i @ds-sfdc/sfparty
|
|
|
13
13
|
```
|
|
14
14
|
## Commands
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
### Split
|
|
17
|
+
```bash
|
|
18
|
+
sfparty split
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Combine
|
|
22
|
+
```bash
|
|
23
|
+
sfparty combine
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Options
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
-n, --name name of metadata file
|
|
30
|
+
-a, --all all metadata files of type will be processed
|
|
31
|
+
-s, --source package directory path specified in sfdx-project.json
|
|
32
|
+
-t, --target target path to directory to create yaml/json files
|
|
33
|
+
-h, --help Show help
|
|
34
|
+
```
|
|
35
|
+
## Examples
|
|
36
|
+
### Custom Labels
|
|
37
|
+
```bash
|
|
38
|
+
sfparty split --type=label
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Permission Set
|
|
42
|
+
```bash
|
|
43
|
+
sfparty split --type=permset
|
|
44
|
+
sfparty split --type=permset --name="My Permission Set"
|
|
45
|
+
```
|
|
46
|
+
### Profile
|
|
47
|
+
```bash
|
|
48
|
+
sfparty split --type=profile
|
|
49
|
+
sfparty split --type=profile --name="My Profile"
|
|
50
|
+
```
|
|
51
|
+
### Workflow
|
|
52
|
+
```bash
|
|
53
|
+
sfparty split --type=workflow
|
|
54
|
+
sfparty split --type=workflow --name="Workflow"
|
|
55
|
+
```
|
|
56
|
+
### Source Directory
|
|
57
|
+
The source directory will use your default package folder as specified in the sfdx-project.json file, and therefore must be executed from your Salesforce project directory. It will create the main/default folders if they do not exist.
|
|
17
58
|
|
|
18
|
-
|
|
59
|
+
```
|
|
60
|
+
{
|
|
61
|
+
"packageDirectories": [
|
|
62
|
+
{
|
|
63
|
+
"path": "force-app",
|
|
64
|
+
"default": true
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"path": "my-package"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"namespace": "",
|
|
71
|
+
"sfdcLoginUrl": "https://login.salesforce.com",
|
|
72
|
+
"sourceApiVersion": "53.0"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
sfparty split --source="my-package"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Target Directory
|
|
81
|
+
The source directory will use your default package folder as specified in the sfdx-project.json file, and append `-party` to the end. For example, if the default source path is `force-app`, then the default target directory will be `force-app-party` unless otherwise specified. The target does not need to be specified in the sfdx-project.json, however the combine command will not work on folders that are not specified in the sfdx-project.json.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
sfparty split --target="test"
|
|
85
|
+
```
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import chalk from 'chalk'
|
|
|
9
9
|
import convertHrtime from 'convert-hrtime'
|
|
10
10
|
import * as fileUtils from './lib/fileUtils.js'
|
|
11
11
|
import * as pkgObj from '../package.json' assert { type: "json" }
|
|
12
|
+
import * as yargOptions from './meta/yargs.js'
|
|
12
13
|
import * as metadataSplit from './party/split.js'
|
|
13
14
|
import * as metadataCombine from './party/combine.js'
|
|
14
15
|
import * as labelDefinition from './meta/CustomLabels.js'
|
|
@@ -16,8 +17,7 @@ import * as profileDefinition from './meta/Profiles.js'
|
|
|
16
17
|
import * as permsetDefinition from './meta/PermissionSets.js'
|
|
17
18
|
import * as workflowDefinition from './meta/Workflows.js'
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
-
|
|
20
|
+
const processStartTime = process.hrtime.bigint()
|
|
21
21
|
|
|
22
22
|
global.logger = winston.createLogger({
|
|
23
23
|
levels: winston.config.syslog.levels,
|
|
@@ -28,12 +28,6 @@ global.logger = winston.createLogger({
|
|
|
28
28
|
],
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
global.processed = {
|
|
32
|
-
total: 0,
|
|
33
|
-
errors: 0,
|
|
34
|
-
current: 1,
|
|
35
|
-
}
|
|
36
|
-
|
|
37
31
|
global.icons = {
|
|
38
32
|
"warn": '🔕',
|
|
39
33
|
"success": chalk.greenBright('✔'),
|
|
@@ -68,6 +62,8 @@ const metaTypes = {
|
|
|
68
62
|
},
|
|
69
63
|
}
|
|
70
64
|
|
|
65
|
+
let types = []
|
|
66
|
+
|
|
71
67
|
function getRootPath(packageDir) {
|
|
72
68
|
let rootPath = fileUtils.find('sfdx-project.json')
|
|
73
69
|
let defaultDir
|
|
@@ -100,7 +96,7 @@ let errorMessage = chalk.red('Please specify the action of ' + chalk.whiteBright
|
|
|
100
96
|
displayHeader() // display header mast
|
|
101
97
|
|
|
102
98
|
function displayHeader() {
|
|
103
|
-
const
|
|
99
|
+
const box = {
|
|
104
100
|
topLeft: '╭',
|
|
105
101
|
topRight: '╮',
|
|
106
102
|
bottomLeft: '╰',
|
|
@@ -112,10 +108,10 @@ function displayHeader() {
|
|
|
112
108
|
let titleMessage = `${global.icons.party} ${chalk.yellowBright(versionString)} ${global.icons.party}`
|
|
113
109
|
titleMessage = titleMessage.padEnd((process.stdout.columns / 2) + versionString.length / 1.65)
|
|
114
110
|
titleMessage = titleMessage.padStart(process.stdout.columns)
|
|
115
|
-
titleMessage = chalk.blackBright(
|
|
116
|
-
console.log(`${chalk.blackBright(
|
|
111
|
+
titleMessage = chalk.blackBright(box.vertical) + ' ' + titleMessage + ' ' + chalk.blackBright(box.vertical)
|
|
112
|
+
console.log(`${chalk.blackBright(box.topLeft + box.horizontal.repeat(process.stdout.columns - 2) + box.topRight)}`)
|
|
117
113
|
console.log(titleMessage)
|
|
118
|
-
console.log(`${chalk.blackBright(
|
|
114
|
+
console.log(`${chalk.blackBright(box.bottomLeft + box.horizontal.repeat(process.stdout.columns - 2) + box.bottomRight)}`)
|
|
119
115
|
console.log()
|
|
120
116
|
}
|
|
121
117
|
|
|
@@ -124,316 +120,33 @@ yargs(hideBin(process.argv))
|
|
|
124
120
|
.command({
|
|
125
121
|
command: '[split]',
|
|
126
122
|
alias: 'split',
|
|
127
|
-
description: 'splits metadata xml to json files',
|
|
123
|
+
description: 'splits metadata xml to yaml/json files',
|
|
128
124
|
builder: (yargs) => {
|
|
129
125
|
yargs
|
|
130
|
-
.example(
|
|
131
|
-
|
|
132
|
-
['$0 split --type=permset --name="Permission Set Name"'],
|
|
133
|
-
['--source=packageDir --target=dir/dir'],
|
|
134
|
-
['name portion of file: [name].profile-meta.xml'],
|
|
135
|
-
['Example: --name="Admin" for Admin.profile-meta.xml'],
|
|
136
|
-
['\nCommands not supporting name or all parameters:'],
|
|
137
|
-
['$0 split --type=label'],
|
|
138
|
-
])
|
|
139
|
-
.options({
|
|
140
|
-
type: {
|
|
141
|
-
demand: true,
|
|
142
|
-
alias: 'type',
|
|
143
|
-
description: 'type of metadata to split',
|
|
144
|
-
demandOption: true,
|
|
145
|
-
type: 'string',
|
|
146
|
-
},
|
|
147
|
-
format: {
|
|
148
|
-
demand: true,
|
|
149
|
-
alias: 'format',
|
|
150
|
-
default: 'yaml',
|
|
151
|
-
description: 'type of output',
|
|
152
|
-
demandOption: true,
|
|
153
|
-
type: 'string',
|
|
154
|
-
},
|
|
155
|
-
name: {
|
|
156
|
-
alias: 'n',
|
|
157
|
-
description: 'name of metadata file to split',
|
|
158
|
-
demandOption: false,
|
|
159
|
-
type: 'string',
|
|
160
|
-
},
|
|
161
|
-
all: {
|
|
162
|
-
alias: 'a',
|
|
163
|
-
description: 'all metadata files of type will be split',
|
|
164
|
-
demandOption: false,
|
|
165
|
-
type: 'boolean',
|
|
166
|
-
},
|
|
167
|
-
source: {
|
|
168
|
-
demand: false,
|
|
169
|
-
alias: 's',
|
|
170
|
-
description: 'package directory path specified in sfdx-project.json',
|
|
171
|
-
type: 'string',
|
|
172
|
-
},
|
|
173
|
-
target: {
|
|
174
|
-
demand: false,
|
|
175
|
-
alias: 't',
|
|
176
|
-
description: 'target path to directory to create json files',
|
|
177
|
-
type: 'string',
|
|
178
|
-
}
|
|
179
|
-
})
|
|
180
|
-
.choices('type', typeArray)
|
|
126
|
+
.example(yargOptions.splitExamples)
|
|
127
|
+
.options(yargOptions.splitOptions)
|
|
181
128
|
.choices('format', ['json', 'yaml'])
|
|
182
|
-
.check(
|
|
183
|
-
const name = argv.name
|
|
184
|
-
const all = argv.all
|
|
185
|
-
|
|
186
|
-
switch (argv.type) {
|
|
187
|
-
case 'profile':
|
|
188
|
-
case 'permset':
|
|
189
|
-
case 'workflow':
|
|
190
|
-
if ((typeof name != 'undefined' || name == '') && (typeof all != 'undefined' && all)) {
|
|
191
|
-
throw new Error(chalk.redBright('You cannot specify ' + chalk.whiteBright.bgRedBright('--name') + ' and ' + chalk.whiteBright.bgRedBright('--all') + ' at the same time.'))
|
|
192
|
-
} else if (typeof name == 'undefined' && (typeof all == 'undefined' || !all)) {
|
|
193
|
-
throw new Error(chalk.redBright('You must specify the ' + chalk.whiteBright.bgRedBright('--name') + ' parameter or use the ' + chalk.whiteBright.bgRedBright('--all') + ' switch.'))
|
|
194
|
-
} else {
|
|
195
|
-
return true // tell Yargs that the arguments passed the check
|
|
196
|
-
}
|
|
197
|
-
case 'label':
|
|
198
|
-
if ((typeof name != 'undefined' && name != '') || (typeof all != 'undefined' && all)) {
|
|
199
|
-
throw new Error(chalk.redBright('You cannot specify ' + chalk.whiteBright.bgRedBright('--name') + ' or ' + chalk.whiteBright.bgRedBright('--all') + ' when using label.'))
|
|
200
|
-
}
|
|
201
|
-
return true
|
|
202
|
-
}
|
|
203
|
-
})
|
|
129
|
+
.check(yargCheck)
|
|
204
130
|
},
|
|
205
131
|
handler: (argv) => {
|
|
206
|
-
if (!typeArray.includes(argv.type)) {
|
|
207
|
-
global.logger.error('Metadata type not supported: ' + type)
|
|
208
|
-
process.exit(1)
|
|
209
|
-
}
|
|
210
|
-
const fileList = []
|
|
211
|
-
const typeObj = metaTypes[argv.type]
|
|
212
|
-
const type = typeObj.type
|
|
213
|
-
const metaExtension = `.${type}-meta.xml`
|
|
214
132
|
global.format = argv.format
|
|
215
|
-
|
|
216
|
-
let sourceDir = argv.source || ''
|
|
217
|
-
let targetDir = argv.target || ''
|
|
218
|
-
let name = argv.name
|
|
219
|
-
let all = argv.all
|
|
220
|
-
let packageDir = getRootPath(sourceDir)
|
|
221
|
-
|
|
222
|
-
if (type == metaTypes.label.type) {
|
|
223
|
-
name = metaTypes.label.definition.root
|
|
224
|
-
}
|
|
225
|
-
sourceDir = path.join(global.__basedir, packageDir, 'main', 'default', typeObj.definition.directory)
|
|
226
|
-
if (targetDir == '') {
|
|
227
|
-
targetDir = path.join(global.__basedir, packageDir + '-party', 'main', 'default', typeObj.definition.directory)
|
|
228
|
-
} else {
|
|
229
|
-
targetDir = path.join(targetDir, 'main', 'default', typeObj.definition.directory)
|
|
230
|
-
}
|
|
231
|
-
let metaDirPath = sourceDir
|
|
232
|
-
console.log(`${chalk.bgBlackBright('Source path:')} ${sourceDir}`)
|
|
233
|
-
console.log(`${chalk.bgBlackBright('Target path:')} ${targetDir}`)
|
|
234
|
-
console.log()
|
|
235
|
-
|
|
236
|
-
if (!all) {
|
|
237
|
-
let metaFilePath = path.join(metaDirPath, name)
|
|
238
|
-
if (!fileUtils.fileExists(metaFilePath)) {
|
|
239
|
-
name += metaExtension
|
|
240
|
-
metaFilePath = path.join(metaDirPath, name)
|
|
241
|
-
if (!fileUtils.fileExists(metaFilePath)) {
|
|
242
|
-
global.logger.error('File not found: ' + metaFilePath)
|
|
243
|
-
process.exit(1)
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
fileList.push(name)
|
|
247
|
-
} else {
|
|
248
|
-
if (fileUtils.directoryExists(sourceDir)) {
|
|
249
|
-
fileUtils.getFiles(sourceDir, metaExtension).forEach(file => {
|
|
250
|
-
fileList.push(file)
|
|
251
|
-
})
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
global.processed.total = fileList.length
|
|
256
|
-
console.log(`Splitting a total of ${fileList.length} file(s)`)
|
|
257
|
-
console.log()
|
|
258
|
-
const promList = []
|
|
259
|
-
fileList.forEach(metaFile => {
|
|
260
|
-
const metadataItem = new metadataSplit.Split({
|
|
261
|
-
metadataDefinition: typeObj.definition,
|
|
262
|
-
sourceDir: sourceDir,
|
|
263
|
-
targetDir: targetDir,
|
|
264
|
-
metaFilePath: path.join(sourceDir, metaFile),
|
|
265
|
-
sequence: promList.length + 1,
|
|
266
|
-
})
|
|
267
|
-
const metadataItemProm = metadataItem.split()
|
|
268
|
-
promList.push(metadataItemProm)
|
|
269
|
-
metadataItemProm.then((resolve, reject) => {
|
|
270
|
-
if (resolve == false) {
|
|
271
|
-
global.processed.errors++
|
|
272
|
-
global.processed.current--
|
|
273
|
-
} else {
|
|
274
|
-
global.processed.current++
|
|
275
|
-
}
|
|
276
|
-
})
|
|
277
|
-
})
|
|
278
|
-
Promise.allSettled(promList).then((results) => {
|
|
279
|
-
let message = `Split ${chalk.bgBlackBright((global.processed.current > promList.length) ? promList.length : global.processed.current)} file(s) ${(global.processed.errors > 0) ? 'with ' + chalk.bgBlackBright.red(global.processed.errors) + ' error(s) ' : ''}in `
|
|
280
|
-
displayMessageAndDuration(startTime, message)
|
|
281
|
-
})
|
|
133
|
+
splitHandler(argv, processStartTime)
|
|
282
134
|
}
|
|
283
135
|
})
|
|
284
136
|
.command({
|
|
285
137
|
command: '[combine]',
|
|
286
138
|
alias: 'combine',
|
|
287
|
-
description: 'combines json files into metadata xml',
|
|
139
|
+
description: 'combines yaml/json files into metadata xml',
|
|
288
140
|
builder: (yargs) => {
|
|
289
141
|
yargs
|
|
290
|
-
.example(
|
|
291
|
-
|
|
292
|
-
['$0 combine --type=permset --name="Permission Set Name"'],
|
|
293
|
-
['--source=packageDir --target=dir/dir'],
|
|
294
|
-
['name portion of file: [name].profile-meta.xml'],
|
|
295
|
-
['Example: --name="Admin" for Admin.profile-meta.xml'],
|
|
296
|
-
['\nCommands not supporting name or all parameters:'],
|
|
297
|
-
['$0 combine --type=label'],])
|
|
298
|
-
.options({
|
|
299
|
-
type: {
|
|
300
|
-
demand: true,
|
|
301
|
-
alias: 'type',
|
|
302
|
-
description: 'type of metadata to combine',
|
|
303
|
-
demandOption: true,
|
|
304
|
-
type: 'string',
|
|
305
|
-
},
|
|
306
|
-
format: {
|
|
307
|
-
demand: true,
|
|
308
|
-
alias: 'format',
|
|
309
|
-
default: 'yaml',
|
|
310
|
-
description: 'type of output',
|
|
311
|
-
demandOption: true,
|
|
312
|
-
type: 'string',
|
|
313
|
-
},
|
|
314
|
-
name: {
|
|
315
|
-
alias: 'n',
|
|
316
|
-
description: 'name of metadata file to combine',
|
|
317
|
-
demandOption: false,
|
|
318
|
-
type: 'string',
|
|
319
|
-
},
|
|
320
|
-
all: {
|
|
321
|
-
alias: 'a',
|
|
322
|
-
description: 'all json files of type will be combined',
|
|
323
|
-
demandOption: false,
|
|
324
|
-
type: 'boolean',
|
|
325
|
-
},
|
|
326
|
-
source: {
|
|
327
|
-
demand: false,
|
|
328
|
-
alias: 's',
|
|
329
|
-
description: 'package directory path specified in sfdx-project.json',
|
|
330
|
-
type: 'string',
|
|
331
|
-
},
|
|
332
|
-
target: {
|
|
333
|
-
demand: false,
|
|
334
|
-
alias: 't',
|
|
335
|
-
description: 'target path to directory to create xml files',
|
|
336
|
-
type: 'string',
|
|
337
|
-
}
|
|
338
|
-
})
|
|
339
|
-
.choices('type', typeArray)
|
|
142
|
+
.example(yargOptions.combineExamples)
|
|
143
|
+
.options(yargOptions.combineOptions)
|
|
340
144
|
.choices('format', ['json', 'yaml'])
|
|
341
|
-
.check(
|
|
342
|
-
const name = argv.name
|
|
343
|
-
const all = argv.all
|
|
344
|
-
|
|
345
|
-
switch (argv.type) {
|
|
346
|
-
case 'profile':
|
|
347
|
-
case 'permset':
|
|
348
|
-
case 'workflow':
|
|
349
|
-
if ((typeof name != 'undefined' || name == '') && (typeof all != 'undefined' && all)) {
|
|
350
|
-
throw new Error(chalk.redBright('You cannot specify ' + chalk.whiteBright.bgRedBright('--name') + ' and ' + chalk.whiteBright.bgRedBright('--all') + ' at the same time.'))
|
|
351
|
-
} else if (typeof name == 'undefined' && (typeof all == 'undefined' || !all)) {
|
|
352
|
-
throw new Error(chalk.redBright('You must specify the ' + chalk.whiteBright.bgRedBright('--name') + ' parameter or use the ' + chalk.whiteBright.bgRedBright('--all') + ' switch.'))
|
|
353
|
-
} else {
|
|
354
|
-
return true // tell Yargs that the arguments passed the check
|
|
355
|
-
}
|
|
356
|
-
case 'label':
|
|
357
|
-
if ((typeof name != 'undefined' && name != '') || (typeof all != 'undefined' && all)) {
|
|
358
|
-
throw new Error(chalk.redBright('You cannot specify ' + chalk.whiteBright.bgRedBright('--name') + ' or ' + chalk.whiteBright.bgRedBright('--all') + ' when using label.'))
|
|
359
|
-
}
|
|
360
|
-
return true
|
|
361
|
-
}
|
|
362
|
-
})
|
|
145
|
+
.check(yargCheck)
|
|
363
146
|
},
|
|
364
147
|
handler: (argv) => {
|
|
365
|
-
if (!typeArray.includes(argv.type)) {
|
|
366
|
-
global.logger.error('Metadata type not supported: ' + type)
|
|
367
|
-
process.exit(1)
|
|
368
|
-
}
|
|
369
|
-
let processList = []
|
|
370
148
|
global.format = argv.format
|
|
371
|
-
|
|
372
|
-
const type = typeObj.type
|
|
373
|
-
|
|
374
|
-
let sourceDir = argv.source || ''
|
|
375
|
-
let targetDir = argv.target || ''
|
|
376
|
-
let name = argv.name
|
|
377
|
-
let all = argv.all
|
|
378
|
-
let packageDir = getRootPath(sourceDir)
|
|
379
|
-
|
|
380
|
-
sourceDir = path.join(global.__basedir, packageDir + '-party', 'main', 'default', typeObj.definition.directory)
|
|
381
|
-
if (targetDir == '') {
|
|
382
|
-
targetDir = path.join(global.__basedir, packageDir, 'main', 'default', typeObj.definition.directory)
|
|
383
|
-
} else {
|
|
384
|
-
targetDir = path.join(targetDir, 'main', 'default', typeObj.definition.directory)
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
console.log(`${chalk.bgBlackBright('Source path:')} ${sourceDir}`)
|
|
388
|
-
console.log(`${chalk.bgBlackBright('Target path:')} ${targetDir}`)
|
|
389
|
-
console.log()
|
|
390
|
-
|
|
391
|
-
if (type == metaTypes.label.type) {
|
|
392
|
-
processList.push(metaTypes.label.definition.root)
|
|
393
|
-
} else if (!all) {
|
|
394
|
-
let metaDirPath = path.join(sourceDir, name)
|
|
395
|
-
if (!fileUtils.directoryExists(metaDirPath)) {
|
|
396
|
-
global.logger.error('Directory not found: ' + metaDirPath)
|
|
397
|
-
process.exit(1)
|
|
398
|
-
}
|
|
399
|
-
processList.push(name)
|
|
400
|
-
} else {
|
|
401
|
-
processList = fileUtils.getDirectories(sourceDir)
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
global.processed.total = processList.length
|
|
405
|
-
console.log(`Combining a total of ${global.processed.total} file(s)`)
|
|
406
|
-
console.log()
|
|
407
|
-
|
|
408
|
-
const promList = []
|
|
409
|
-
processList.forEach(metaDir => {
|
|
410
|
-
const metadataItem = new metadataCombine.Combine({
|
|
411
|
-
metadataDefinition: typeObj.definition,
|
|
412
|
-
sourceDir: sourceDir,
|
|
413
|
-
targetDir: targetDir,
|
|
414
|
-
metaDir: metaDir,
|
|
415
|
-
sequence: promList.length + 1,
|
|
416
|
-
})
|
|
417
|
-
const metadataItemProm = metadataItem.combine()
|
|
418
|
-
promList.push(metadataItemProm)
|
|
419
|
-
metadataItemProm.then((resolve, reject) => {
|
|
420
|
-
global.processed.current++
|
|
421
|
-
})
|
|
422
|
-
})
|
|
423
|
-
|
|
424
|
-
Promise.allSettled(promList).then((results) => {
|
|
425
|
-
let successes = 0
|
|
426
|
-
let errors = 0
|
|
427
|
-
results.forEach(result => {
|
|
428
|
-
if (result.value == true) {
|
|
429
|
-
successes++
|
|
430
|
-
} else if (result.value == false) {
|
|
431
|
-
errors++
|
|
432
|
-
}
|
|
433
|
-
})
|
|
434
|
-
let message = `Combined ${chalk.bgBlackBright(successes)} file(s) ${(errors > 0) ? 'with ' + chalk.bgBlackBright(errors) + 'error(s) ' : ''}in `
|
|
435
|
-
displayMessageAndDuration(startTime, message)
|
|
436
|
-
})
|
|
149
|
+
combineHandler(argv, processStartTime)
|
|
437
150
|
}
|
|
438
151
|
})
|
|
439
152
|
.demandCommand(1, errorMessage)
|
|
@@ -447,6 +160,35 @@ yargs(hideBin(process.argv))
|
|
|
447
160
|
.argv
|
|
448
161
|
.parse
|
|
449
162
|
|
|
163
|
+
function yargCheck(argv, options) {
|
|
164
|
+
const name = argv.name
|
|
165
|
+
types = (argv.type !== undefined) ? argv.type.split(',') : typeArray
|
|
166
|
+
types.forEach(type => {
|
|
167
|
+
type = type.trim()
|
|
168
|
+
if (!typeArray.includes(type)) {
|
|
169
|
+
throw new Error(`Invalid type: ${type}`)
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
if (types.length > 1) {
|
|
174
|
+
// if using multiple types you cannot specify name
|
|
175
|
+
if ((typeof name != 'undefined' && name != '')) {
|
|
176
|
+
throw new Error(chalk.redBright('You cannot specify ' + chalk.whiteBright.bgRedBright('--name') + ' when using multiple types.'))
|
|
177
|
+
}
|
|
178
|
+
return true
|
|
179
|
+
} else {
|
|
180
|
+
switch (argv.type) {
|
|
181
|
+
case 'label':
|
|
182
|
+
if ((typeof name != 'undefined' && name != '')) {
|
|
183
|
+
throw new Error(chalk.redBright('You cannot specify ' + chalk.whiteBright.bgRedBright('--name') + ' when using label.'))
|
|
184
|
+
}
|
|
185
|
+
break
|
|
186
|
+
default:
|
|
187
|
+
return true
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
450
192
|
function displayMessageAndDuration(startTime, message) {
|
|
451
193
|
const diff = process.hrtime.bigint() - BigInt(startTime)
|
|
452
194
|
let durationMessage
|
|
@@ -471,4 +213,215 @@ process.on('SIGINT', function () {
|
|
|
471
213
|
}
|
|
472
214
|
|
|
473
215
|
callAmount++;
|
|
474
|
-
})
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
function splitHandler(argv) {
|
|
219
|
+
const split = processSplit(types[0], argv)
|
|
220
|
+
split.then((resolve) => {
|
|
221
|
+
types.shift() // remove first item from array
|
|
222
|
+
if (types.length > 0) {
|
|
223
|
+
console.log()
|
|
224
|
+
splitHandler(argv)
|
|
225
|
+
} else {
|
|
226
|
+
if (argv.type === undefined || argv.type.split(',').length > 1) {
|
|
227
|
+
let message = `Split completed in `
|
|
228
|
+
displayMessageAndDuration(startTime, message)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function processSplit(typeItem, argv) {
|
|
235
|
+
return new Promise((resolve, reject) => {
|
|
236
|
+
const processed = {
|
|
237
|
+
total: 0,
|
|
238
|
+
errors: 0,
|
|
239
|
+
current: 1,
|
|
240
|
+
}
|
|
241
|
+
const startTime = process.hrtime.bigint()
|
|
242
|
+
|
|
243
|
+
if (!typeArray.includes(typeItem)) {
|
|
244
|
+
global.logger.error('Metadata type not supported: ' + typeItem)
|
|
245
|
+
process.exit(1)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const fileList = []
|
|
249
|
+
const typeObj = metaTypes[typeItem]
|
|
250
|
+
const type = typeObj.type
|
|
251
|
+
const metaExtension = `.${type}-meta.xml`
|
|
252
|
+
|
|
253
|
+
let sourceDir = argv.source || ''
|
|
254
|
+
let targetDir = argv.target || ''
|
|
255
|
+
let name = argv.name
|
|
256
|
+
let all = (argv.type === undefined || argv.type.split(',').length > 1) ? true : argv.all
|
|
257
|
+
let packageDir = getRootPath(sourceDir)
|
|
258
|
+
|
|
259
|
+
if (type == metaTypes.label.type) {
|
|
260
|
+
name = metaTypes.label.definition.root
|
|
261
|
+
}
|
|
262
|
+
sourceDir = path.join(global.__basedir, packageDir, 'main', 'default', typeObj.definition.directory)
|
|
263
|
+
if (targetDir == '') {
|
|
264
|
+
targetDir = path.join(global.__basedir, packageDir + '-party', 'main', 'default', typeObj.definition.directory)
|
|
265
|
+
} else {
|
|
266
|
+
targetDir = path.join(targetDir, 'main', 'default', typeObj.definition.directory)
|
|
267
|
+
}
|
|
268
|
+
let metaDirPath = sourceDir
|
|
269
|
+
|
|
270
|
+
if (!all) {
|
|
271
|
+
let metaFilePath = path.join(metaDirPath, name)
|
|
272
|
+
if (!fileUtils.fileExists(metaFilePath)) {
|
|
273
|
+
name += metaExtension
|
|
274
|
+
metaFilePath = path.join(metaDirPath, name)
|
|
275
|
+
if (!fileUtils.fileExists(metaFilePath)) {
|
|
276
|
+
global.logger.error('File not found: ' + metaFilePath)
|
|
277
|
+
process.exit(1)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
fileList.push(name)
|
|
281
|
+
} else {
|
|
282
|
+
if (fileUtils.directoryExists(sourceDir)) {
|
|
283
|
+
fileUtils.getFiles(sourceDir, metaExtension).forEach(file => {
|
|
284
|
+
fileList.push(file)
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
processed.total = fileList.length
|
|
290
|
+
|
|
291
|
+
console.log(`${chalk.bgBlackBright('Source path:')} ${sourceDir}`)
|
|
292
|
+
console.log(`${chalk.bgBlackBright('Target path:')} ${targetDir}`)
|
|
293
|
+
console.log()
|
|
294
|
+
console.log(`Splitting a total of ${processed.total} file(s)`)
|
|
295
|
+
console.log()
|
|
296
|
+
|
|
297
|
+
const promList = []
|
|
298
|
+
fileList.forEach(metaFile => {
|
|
299
|
+
const metadataItem = new metadataSplit.Split({
|
|
300
|
+
metadataDefinition: typeObj.definition,
|
|
301
|
+
sourceDir: sourceDir,
|
|
302
|
+
targetDir: targetDir,
|
|
303
|
+
metaFilePath: path.join(sourceDir, metaFile),
|
|
304
|
+
sequence: promList.length + 1,
|
|
305
|
+
total: processed.total,
|
|
306
|
+
})
|
|
307
|
+
const metadataItemProm = metadataItem.split()
|
|
308
|
+
promList.push(metadataItemProm)
|
|
309
|
+
metadataItemProm.then((resolve, reject) => {
|
|
310
|
+
if (resolve == false) {
|
|
311
|
+
processed.errors++
|
|
312
|
+
processed.current--
|
|
313
|
+
} else {
|
|
314
|
+
processed.current++
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
})
|
|
318
|
+
Promise.allSettled(promList).then((results) => {
|
|
319
|
+
let message = `Split ${chalk.bgBlackBright((processed.current > promList.length) ? promList.length : processed.current)} file(s) ${(processed.errors > 0) ? 'with ' + chalk.bgBlackBright.red(processed.errors) + ' error(s) ' : ''}in `
|
|
320
|
+
displayMessageAndDuration(startTime, message)
|
|
321
|
+
resolve(true)
|
|
322
|
+
})
|
|
323
|
+
})
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function combineHandler(argv, startTime) {
|
|
327
|
+
const combine = processCombine(types[0], argv)
|
|
328
|
+
combine.then((resolve) => {
|
|
329
|
+
types.shift() // remove first item from array
|
|
330
|
+
if (types.length > 0) {
|
|
331
|
+
console.log()
|
|
332
|
+
combineHandler(argv, startTime)
|
|
333
|
+
} else {
|
|
334
|
+
if (argv.type === undefined || argv.type.split(',').length > 1) {
|
|
335
|
+
let message = `Split completed in `
|
|
336
|
+
displayMessageAndDuration(startTime, message)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function processCombine(typeItem, argv) {
|
|
344
|
+
return new Promise((resolve, reject) => {
|
|
345
|
+
const processed = {
|
|
346
|
+
total: 0,
|
|
347
|
+
errors: 0,
|
|
348
|
+
current: 1,
|
|
349
|
+
}
|
|
350
|
+
const startTime = process.hrtime.bigint()
|
|
351
|
+
|
|
352
|
+
if (!typeArray.includes(typeItem)) {
|
|
353
|
+
global.logger.error('Metadata type not supported: ' + typeItem)
|
|
354
|
+
process.exit(1)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
let processList = []
|
|
358
|
+
const typeObj = metaTypes[typeItem]
|
|
359
|
+
const type = typeObj.type
|
|
360
|
+
|
|
361
|
+
let sourceDir = argv.source || ''
|
|
362
|
+
let targetDir = argv.target || ''
|
|
363
|
+
let name = argv.name
|
|
364
|
+
let all = (argv.type === undefined || argv.type.split(',').length > 1) ? true : argv.all
|
|
365
|
+
let packageDir = getRootPath(sourceDir)
|
|
366
|
+
|
|
367
|
+
sourceDir = path.join(global.__basedir, packageDir + '-party', 'main', 'default', typeObj.definition.directory)
|
|
368
|
+
if (targetDir == '') {
|
|
369
|
+
targetDir = path.join(global.__basedir, packageDir, 'main', 'default', typeObj.definition.directory)
|
|
370
|
+
} else {
|
|
371
|
+
targetDir = path.join(targetDir, 'main', 'default', typeObj.definition.directory)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
console.log(`${chalk.bgBlackBright('Source path:')} ${sourceDir}`)
|
|
375
|
+
console.log(`${chalk.bgBlackBright('Target path:')} ${targetDir}`)
|
|
376
|
+
console.log()
|
|
377
|
+
|
|
378
|
+
if (type == metaTypes.label.type) {
|
|
379
|
+
processList.push(metaTypes.label.definition.root)
|
|
380
|
+
} else if (!all) {
|
|
381
|
+
let metaDirPath = path.join(sourceDir, name)
|
|
382
|
+
if (!fileUtils.directoryExists(metaDirPath)) {
|
|
383
|
+
global.logger.error('Directory not found: ' + metaDirPath)
|
|
384
|
+
process.exit(1)
|
|
385
|
+
}
|
|
386
|
+
processList.push(name)
|
|
387
|
+
} else {
|
|
388
|
+
processList = fileUtils.getDirectories(sourceDir)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
processed.total = processList.length
|
|
392
|
+
console.log(`Combining a total of ${processed.total} file(s)`)
|
|
393
|
+
console.log()
|
|
394
|
+
|
|
395
|
+
const promList = []
|
|
396
|
+
processList.forEach(metaDir => {
|
|
397
|
+
const metadataItem = new metadataCombine.Combine({
|
|
398
|
+
metadataDefinition: typeObj.definition,
|
|
399
|
+
sourceDir: sourceDir,
|
|
400
|
+
targetDir: targetDir,
|
|
401
|
+
metaDir: metaDir,
|
|
402
|
+
sequence: promList.length + 1,
|
|
403
|
+
total: processed.total,
|
|
404
|
+
})
|
|
405
|
+
const metadataItemProm = metadataItem.combine()
|
|
406
|
+
promList.push(metadataItemProm)
|
|
407
|
+
metadataItemProm.then((resolve, reject) => {
|
|
408
|
+
processed.current++
|
|
409
|
+
})
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
Promise.allSettled(promList).then((results) => {
|
|
413
|
+
let successes = 0
|
|
414
|
+
let errors = 0
|
|
415
|
+
results.forEach(result => {
|
|
416
|
+
if (result.value == true) {
|
|
417
|
+
successes++
|
|
418
|
+
} else if (result.value == false) {
|
|
419
|
+
errors++
|
|
420
|
+
}
|
|
421
|
+
})
|
|
422
|
+
let message = `Combined ${chalk.bgBlackBright(successes)} file(s) ${(errors > 0) ? 'with ' + chalk.bgBlackBright(errors) + 'error(s) ' : ''}in `
|
|
423
|
+
displayMessageAndDuration(startTime, message)
|
|
424
|
+
resolve(true)
|
|
425
|
+
})
|
|
426
|
+
})
|
|
427
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const options = {
|
|
2
|
+
type: {
|
|
3
|
+
demand: false,
|
|
4
|
+
alias: 'type',
|
|
5
|
+
description: 'type of metadata to $1',
|
|
6
|
+
demandOption: false,
|
|
7
|
+
type: 'string',
|
|
8
|
+
},
|
|
9
|
+
format: {
|
|
10
|
+
demand: true,
|
|
11
|
+
alias: 'format',
|
|
12
|
+
default: 'yaml',
|
|
13
|
+
description: 'type of output',
|
|
14
|
+
demandOption: true,
|
|
15
|
+
type: 'string',
|
|
16
|
+
},
|
|
17
|
+
name: {
|
|
18
|
+
alias: 'n',
|
|
19
|
+
description: 'name of metadata file to $1',
|
|
20
|
+
demandOption: false,
|
|
21
|
+
type: 'string',
|
|
22
|
+
},
|
|
23
|
+
source: {
|
|
24
|
+
demand: false,
|
|
25
|
+
alias: 's',
|
|
26
|
+
description: 'package directory path specified in sfdx-project.json',
|
|
27
|
+
type: 'string',
|
|
28
|
+
},
|
|
29
|
+
target: {
|
|
30
|
+
demand: false,
|
|
31
|
+
alias: 't',
|
|
32
|
+
description: 'target path to directory to create yaml/json files',
|
|
33
|
+
type: 'string',
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getOptions(type) {
|
|
38
|
+
let optionObj = {... options}
|
|
39
|
+
Object.keys(optionObj).forEach(key => {
|
|
40
|
+
Object.keys(optionObj[key]).forEach(subKey => {
|
|
41
|
+
if (typeof optionObj[key][subKey] == 'string') {
|
|
42
|
+
optionObj[key][subKey] = optionObj[key][subKey].replaceAll('$1', type)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return optionObj
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const splitOptions = getOptions('split')
|
|
51
|
+
export const combineOptions = getOptions('combine')
|
|
52
|
+
|
|
53
|
+
const examples = [
|
|
54
|
+
['$0 $1'],
|
|
55
|
+
['$0 $1 --type=profile'],
|
|
56
|
+
['$0 $1 --type="profile,label"'],
|
|
57
|
+
['$0 $1 --type=permset --name="Permission Set Name"'],
|
|
58
|
+
['--source=packageDir --target=dir/dir'],
|
|
59
|
+
['name portion of file: [name].profile-meta.xml'],
|
|
60
|
+
['Example: --name="Admin" for Admin.profile-meta.xml'],
|
|
61
|
+
['\nCommands not supporting name or all parameters:'],
|
|
62
|
+
['$0 $1 --type=label'],
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
function getExamples(type) {
|
|
66
|
+
let exArr = [...examples]
|
|
67
|
+
exArr.forEach(arrItem => {
|
|
68
|
+
arrItem[0] = arrItem[0].replaceAll('$1', type)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
return exArr
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const splitExamples = getExamples('split')
|
|
75
|
+
export const combineExamples = getExamples('combine')
|
package/src/party/combine.js
CHANGED
|
@@ -8,6 +8,12 @@ import * as xml2js from 'xml2js'
|
|
|
8
8
|
import * as fileUtils from '../lib/fileUtils.js'
|
|
9
9
|
|
|
10
10
|
const spinner = cliSpinners['dots']
|
|
11
|
+
const processed = {
|
|
12
|
+
total: 0,
|
|
13
|
+
errors: 0,
|
|
14
|
+
current: 0,
|
|
15
|
+
type: undefined,
|
|
16
|
+
}
|
|
11
17
|
|
|
12
18
|
export class Combine {
|
|
13
19
|
#type = undefined
|
|
@@ -33,6 +39,7 @@ export class Combine {
|
|
|
33
39
|
this.targetDir = config.targetDir
|
|
34
40
|
this.metaDir = config.metaDir
|
|
35
41
|
this.sequence = config.sequence
|
|
42
|
+
this.total = config.total
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
get metadataDefinition() {
|
|
@@ -102,13 +109,19 @@ export class Combine {
|
|
|
102
109
|
})
|
|
103
110
|
|
|
104
111
|
function getXML(that) {
|
|
112
|
+
if (processed.type != that.#root) {
|
|
113
|
+
processed.current = 0
|
|
114
|
+
processed.type = that.#root
|
|
115
|
+
}
|
|
116
|
+
processed.current++
|
|
117
|
+
|
|
105
118
|
that.#startTime = process.hrtime.bigint()
|
|
106
|
-
that.#spinnerMessage = `[%1] of ${
|
|
119
|
+
that.#spinnerMessage = `[%1] of ${that.total} - ${that.#root}: [%4]${chalk.yellowBright('[%5]')}[%2][%3]`
|
|
107
120
|
|
|
108
121
|
that.#types.forEach(key => {
|
|
109
122
|
// display message
|
|
110
123
|
logUpdate(that.#spinnerMessage
|
|
111
|
-
.replace('[%1]', that.sequence.toString().padStart(
|
|
124
|
+
.replace('[%1]', that.sequence.toString().padStart(that.total.toString().length, ' '))
|
|
112
125
|
.replace('[%2]', `\n${chalk.magentaBright(nextFrame(that))} ${key}`)
|
|
113
126
|
.replace('[%3]', `${that.#errorMessage}`)
|
|
114
127
|
.replace('[%4]', `${global.icons.working} `)
|
|
@@ -157,7 +170,7 @@ export class Combine {
|
|
|
157
170
|
// iterate over fileList
|
|
158
171
|
fileList.forEach((file, index) => {
|
|
159
172
|
logUpdate(that.#spinnerMessage
|
|
160
|
-
.replace('[%1]', that.sequence.toString().padStart(
|
|
173
|
+
.replace('[%1]', that.sequence.toString().padStart(that.total.toString().length, ' '))
|
|
161
174
|
.replace('[%2]', `\n${chalk.magentaBright(nextFrame(that))} ${key} - ${index + 1} of ${fileList.length} - ${chalk.magentaBright(file)}`)
|
|
162
175
|
.replace('[%3]', `${that.#errorMessage}`)
|
|
163
176
|
.replace('[%4]', `${global.icons.working} `)
|
|
@@ -292,7 +305,7 @@ export class Combine {
|
|
|
292
305
|
let stateIcon = (that.#errorMessage == '') ? global.icons.success : global.icons.fail
|
|
293
306
|
|
|
294
307
|
logUpdate(that.#spinnerMessage
|
|
295
|
-
.replace('[%1]', that.sequence.toString().padStart(
|
|
308
|
+
.replace('[%1]', that.sequence.toString().padStart(that.total.toString().length, ' '))
|
|
296
309
|
.replace('[%2]', `. Processed in ${durationMessage}.`)
|
|
297
310
|
.replace('[%3]', `${that.#errorMessage}`)
|
|
298
311
|
.replace('[%4]', `${stateIcon} `)
|
package/src/party/split.js
CHANGED
|
@@ -12,6 +12,12 @@ import cliSpinners from 'cli-spinners'
|
|
|
12
12
|
import * as fileUtils from '../lib/fileUtils.js'
|
|
13
13
|
|
|
14
14
|
const spinner = cliSpinners['dots']
|
|
15
|
+
const processed = {
|
|
16
|
+
total: 0,
|
|
17
|
+
errors: 0,
|
|
18
|
+
current: 0,
|
|
19
|
+
type: undefined,
|
|
20
|
+
}
|
|
15
21
|
|
|
16
22
|
export class Split {
|
|
17
23
|
#type = undefined
|
|
@@ -33,6 +39,7 @@ export class Split {
|
|
|
33
39
|
this.targetDir = config.targetDir
|
|
34
40
|
this.metaFilePath = config.metaFilePath
|
|
35
41
|
this.sequence = config.sequence
|
|
42
|
+
this.total = config.total
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
get metadataDefinition() {
|
|
@@ -117,13 +124,18 @@ export class Split {
|
|
|
117
124
|
})
|
|
118
125
|
|
|
119
126
|
function processJSON(that, json, baseDir) {
|
|
120
|
-
that.#spinnerMessage = `[%1] of ${
|
|
127
|
+
that.#spinnerMessage = `[%1] of ${that.total} - ${that.#root}: [%4]${chalk.yellowBright(that.#fileName.shortName)}[%2][%3]`
|
|
121
128
|
|
|
122
129
|
let targetDir = baseDir
|
|
130
|
+
if (processed.type != that.#root) {
|
|
131
|
+
processed.current = 0
|
|
132
|
+
processed.type = that.#root
|
|
133
|
+
}
|
|
134
|
+
processed.current++
|
|
123
135
|
Object.keys(json).forEach(key => {
|
|
124
|
-
that.sequence =
|
|
136
|
+
that.sequence = processed.current
|
|
125
137
|
logUpdate(that.#spinnerMessage
|
|
126
|
-
.replace('[%1]', that.sequence.toString().padStart(
|
|
138
|
+
.replace('[%1]', that.sequence.toString().padStart(that.total.toString().length, ' '))
|
|
127
139
|
.replace('[%2]', `\n${chalk.magentaBright(nextFrame(that))} ${key}`)
|
|
128
140
|
.replace('[%3]', `${that.#errorMessage}`)
|
|
129
141
|
.replace('[%4]', `${global.icons.working} `)
|
|
@@ -157,9 +169,9 @@ export class Split {
|
|
|
157
169
|
}
|
|
158
170
|
mainInfo.main.name = that.#fileName.shortName
|
|
159
171
|
that.metadataDefinition.main.forEach(key => {
|
|
160
|
-
that.sequence =
|
|
172
|
+
that.sequence = processed.current
|
|
161
173
|
logUpdate(that.#spinnerMessage
|
|
162
|
-
.replace('[%1]', that.sequence.toString().padStart(
|
|
174
|
+
.replace('[%1]', that.sequence.toString().padStart(that.total.toString().length, ' '))
|
|
163
175
|
.replace('[%2]', `\n${chalk.magentaBright(nextFrame(that))} ${key}`)
|
|
164
176
|
.replace('[%3]', `${that.#errorMessage}`)
|
|
165
177
|
.replace('[%4]', `${global.icons.working} `)
|
|
@@ -182,7 +194,7 @@ export class Split {
|
|
|
182
194
|
let durationMessage = `${executionTime.seconds}.${executionTime.milliseconds}s`
|
|
183
195
|
let stateIcon = (that.#errorMessage == '') ? global.icons.success : global.icons.fail
|
|
184
196
|
logUpdate(that.#spinnerMessage
|
|
185
|
-
.replace('[%1]', that.sequence.toString().padStart(
|
|
197
|
+
.replace('[%1]', that.sequence.toString().padStart(that.total.toString().length, ' '))
|
|
186
198
|
.replace('[%2]', `. Processed in ${durationMessage}.`)
|
|
187
199
|
.replace('[%3]', `${that.#errorMessage}`)
|
|
188
200
|
.replace('[%4]', `${stateIcon} `)
|