@ds-sfdc/sfparty 0.0.0 → 1.0.0-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.
@@ -9,7 +9,7 @@ import logUpdate from 'log-update'
9
9
  import chalk from 'chalk'
10
10
  import convertHrtime from 'convert-hrtime'
11
11
  import cliSpinners from 'cli-spinners'
12
- import * as fileUtils from '../fileUtils.js'
12
+ import * as fileUtils from '../lib/fileUtils.js'
13
13
 
14
14
  const spinner = cliSpinners['dots']
15
15
 
@@ -64,55 +64,59 @@ export class Split {
64
64
  return new Promise((resolve, reject) => {
65
65
  if (!that.#fileName || !that.sourceDir || !that.targetDir || !that.metaFilePath) {
66
66
  global.logger.error('Invalid information passed to split')
67
- process.exit(1)
68
- }
69
- if (!fileUtils.fileExists(that.metaFilePath)) {
67
+ resolve(false)
68
+ } else if (!fileUtils.fileExists(that.metaFilePath)) {
70
69
  global.logger.error(`file not found: ${that.metaFilePath}`)
71
- process.exit(1)
72
- }
73
-
74
- that.targetDir = path.join(that.targetDir, that.#fileName.shortName)
75
- let parser = new Parser()
76
- const getJSON = new Promise((resolve, reject) => {
77
- readFile(that.metaFilePath, function (err, data) {
78
- parser.parseString(data, function (err, result) {
79
- if (result) {
80
- resolve(result)
81
- } else {
82
- global.logger.error(`error converting xml to json: ${that.metaFilePath}`)
83
- process.exit(1)
84
- }
70
+ resolve(false)
71
+ } else {
72
+ that.targetDir = path.join(that.targetDir, that.#fileName.shortName)
73
+ let parser = new Parser()
74
+ const getJSON = new Promise((resolve, reject) => {
75
+ readFile(that.metaFilePath, function (err, data) {
76
+ parser.parseString(data, function (err, result) {
77
+ if (result) {
78
+ resolve({ data: result, startTime: process.hrtime.bigint() })
79
+ } else {
80
+ global.logger.error(`error converting xml to json: ${that.metaFilePath}`)
81
+ reject(`error converting xml to json: ${that.metaFilePath}`)
82
+ }
83
+ })
85
84
  })
86
85
  })
87
- })
88
- getJSON.then((result) => {
89
- try {
90
- result[that.#root]['$'].xmlns = result[that.#root]['$'].xmlns.replace('http:', 'https:')
91
- } catch (error) {
92
- global.logger.error(`${that.#fileName.fullName} has an invalid XML root`)
93
- resolve(false)
94
- return
95
- }
86
+ getJSON.catch((error) => {
87
+ throw error
88
+ })
89
+ getJSON.then((result) => {
90
+ that.#startTime = result.startTime
91
+ result = result.data
92
+ try {
93
+ result[that.#root]['$'].xmlns = result[that.#root]['$'].xmlns.replace('http:', 'https:')
94
+ } catch (error) {
95
+ global.logger.error(`${that.#fileName.fullName} has an invalid XML root`)
96
+ resolve(false)
97
+ return
98
+ }
96
99
 
97
- // modify the json to remove unwanted arrays
98
- that.#json = transformJSON(that, result, that.#root)
99
- fileUtils.deleteDirectory(that.targetDir, true) // recursive delete existing directory
100
- fileUtils.createDirectory(that.targetDir) // create directory
101
-
102
- try {
103
- processJSON(that, that.#json[that.#root], that.targetDir)
104
- completeFile(that)
105
- } catch (error) {
106
- console.log(that.#fileName.shortName)
107
- global.logger.error(error)
108
- }
100
+ // modify the json to remove unwanted arrays
101
+ that.#json = transformJSON(that, result, that.#root)
102
+ fileUtils.deleteDirectory(that.targetDir, true) // recursive delete existing directory
103
+ fileUtils.createDirectory(that.targetDir) // create directory
104
+
105
+ try {
106
+ processJSON(that, that.#json[that.#root], that.targetDir)
107
+ completeFile(that)
108
+ } catch (error) {
109
+ console.log(that.#fileName.shortName)
110
+ global.logger.error(error)
111
+ throw error
112
+ }
109
113
 
110
- resolve(true)
111
- })
114
+ resolve(true)
115
+ })
116
+ }
112
117
  })
113
118
 
114
119
  function processJSON(that, json, baseDir) {
115
- that.#startTime = process.hrtime.bigint()
116
120
  that.#spinnerMessage = `[%1] of ${global.processed.total} - Workflow: [%4]${chalk.yellowBright(that.#fileName.shortName)}[%2][%3]`
117
121
 
118
122
  let targetDir = baseDir
@@ -122,42 +126,47 @@ export class Split {
122
126
  .replace('[%1]', that.sequence.toString().padStart(global.processed.total.toString().length, ' '))
123
127
  .replace('[%2]', `\n${chalk.magentaBright(nextFrame(that))} ${key}`)
124
128
  .replace('[%3]', `${that.#errorMessage}`)
125
- .replace('[%4]', `${global.statusLevel.working} `)
129
+ .replace('[%4]', `${global.icons.working} `)
126
130
  )
127
131
 
128
- if (that.metadataDefinition.directories.includes(key)) {
132
+ if (that.metadataDefinition.directories !== undefined && that.metadataDefinition.directories.includes(key)) {
129
133
  targetDir = path.join(baseDir, key)
130
134
  fileUtils.createDirectory(targetDir) // create directory
131
135
  if (Array.isArray(json[key])) {
132
136
  processDirectory(that, json[key], key, targetDir)
133
137
  }
134
- } else if (that.metadataDefinition.singleFiles.includes(key)) {
135
- console.log(key, 'single file')
136
- } else if (that.metadataDefinition.main.includes(key)) {
138
+ } else if (that.metadataDefinition.singleFiles !== undefined && that.metadataDefinition.singleFiles.includes(key)) {
139
+ processFile(that, json[key], key, baseDir)
140
+ } else if (that.metadataDefinition.main !== undefined && that.metadataDefinition.main.includes(key)) {
137
141
  // Main will get processed in it's own call
138
142
  } else {
139
- console.log(key, 'unknown')
143
+ logUpdate(key, 'unknown')
144
+ logUpdate.done()
140
145
  }
141
146
  })
142
147
 
143
- Main(that)
148
+ if (that.metadataDefinition.main !== undefined) {
149
+ Main(that)
150
+ }
144
151
  }
145
152
 
146
153
  function Main(that) {
147
154
  let fileName = path.join(that.targetDir, `main.${global.format}`)
148
- let mainInfo = {}
149
- mainInfo.name = that.#fileName.shortName
155
+ let mainInfo = {
156
+ main: {}
157
+ }
158
+ mainInfo.main.name = that.#fileName.shortName
150
159
  that.metadataDefinition.main.forEach(key => {
151
160
  that.sequence = global.processed.current
152
161
  logUpdate(that.#spinnerMessage
153
162
  .replace('[%1]', that.sequence.toString().padStart(global.processed.total.toString().length, ' '))
154
163
  .replace('[%2]', `\n${chalk.magentaBright(nextFrame(that))} ${key}`)
155
164
  .replace('[%3]', `${that.#errorMessage}`)
156
- .replace('[%4]', `${global.statusLevel.working} `)
165
+ .replace('[%4]', `${global.icons.working} `)
157
166
  )
158
167
 
159
168
  if (that.#json[that.#root][key] !== undefined) {
160
- mainInfo[key] = that.#json[that.#root][key]
169
+ mainInfo.main[key] = that.#json[that.#root][key]
161
170
  }
162
171
  })
163
172
 
@@ -171,7 +180,7 @@ export class Split {
171
180
  function completeFile(that) {
172
181
  let executionTime = getTimeDiff(BigInt(that.#startTime))
173
182
  let durationMessage = `${executionTime.seconds}.${executionTime.milliseconds}s`
174
- let stateIcon = (that.#errorMessage == '') ? global.statusLevel.success : global.statusLevel.fail
183
+ let stateIcon = (that.#errorMessage == '') ? global.icons.success : global.icons.fail
175
184
  logUpdate(that.#spinnerMessage
176
185
  .replace('[%1]', that.sequence.toString().padStart(global.processed.total.toString().length, ' '))
177
186
  .replace('[%2]', `. Processed in ${durationMessage}.`)
@@ -184,11 +193,52 @@ export class Split {
184
193
  }
185
194
 
186
195
  function processDirectory(that, json, key, baseDir) {
187
- json.forEach(arrItem => {
196
+ if (that.metadataDefinition.splitObjects !== undefined && that.metadataDefinition.splitObjects.includes(key)) {
188
197
  const sortKey = that.metadataDefinition.sortKeys[key]
189
- let fileName = path.join(baseDir, `${arrItem[sortKey]}.${global.format}`)
190
- fileUtils.savePartFile(arrItem, fileName, global.format)
191
- })
198
+ const objects = {}
199
+
200
+ if (sortKey === undefined) {
201
+ throw new Error(`No sort key specified for: ${key}`)
202
+ }
203
+ json.forEach(arrItem => {
204
+ const object = arrItem[sortKey].split('.')[0]
205
+ arrItem[sortKey] = arrItem[sortKey].split('.').pop()
206
+ if (objects[object] === undefined) {
207
+ objects[object] = {
208
+ object: object
209
+ }
210
+ objects[object][key] = []
211
+ }
212
+ delete arrItem['object']
213
+ objects[object][key].push(arrItem)
214
+ })
215
+
216
+ Object.keys(objects).forEach(object => {
217
+ processFile(that, objects[object], key, baseDir, object)
218
+ })
219
+
220
+ } else {
221
+ json.forEach(arrItem => {
222
+ processFile(that, arrItem, key, baseDir)
223
+ })
224
+ }
225
+
226
+
227
+ }
228
+
229
+ function processFile(that, json, key, baseDir, fileNameOverride) {
230
+ let newJSON
231
+ let fileName
232
+ if (fileNameOverride !== undefined) {
233
+ fileName = path.join(baseDir, `${fileNameOverride}.${global.format}`)
234
+ newJSON = json
235
+ } else {
236
+ const sortKey = that.metadataDefinition.sortKeys[key]
237
+ fileName = path.join(baseDir, `${(json[sortKey] !== undefined) ? json[sortKey] : key}.${global.format}`)
238
+ newJSON = {}
239
+ newJSON[key] = json
240
+ }
241
+ fileUtils.savePartFile(newJSON, fileName, global.format)
192
242
  }
193
243
 
194
244
  function transformJSON(that, result, rootTag) {
@@ -230,17 +280,22 @@ function keySort(that, key, json) {
230
280
 
231
281
  // arrange json keys in specified order using keyOrder
232
282
  json.forEach(function (part, index) {
233
- this[index] = Object.keys(this[index])
234
- .sort((a, b) => {
235
- if (keyOrder.indexOf(a) == -1) return 1
236
- if (keyOrder.indexOf(a) < keyOrder.indexOf(b)) return -1
237
- if (keyOrder.indexOf(a) > keyOrder.indexOf(b)) return 1
238
- return 0
239
- })
240
- .reduce((accumulator, key) => {
241
- accumulator[key] = this[index][key]
242
- return accumulator
243
- }, {})
283
+ try {
284
+ this[index] = Object.keys(this[index])
285
+ .sort((a, b) => {
286
+ if (keyOrder.indexOf(a) == -1) return 1
287
+ if (keyOrder.indexOf(a) < keyOrder.indexOf(b)) return -1
288
+ if (keyOrder.indexOf(a) > keyOrder.indexOf(b)) return 1
289
+ return 0
290
+ })
291
+ .reduce((accumulator, key) => {
292
+ accumulator[key] = this[index][key]
293
+ return accumulator
294
+ }, {})
295
+ } catch (error) {
296
+ let test = key
297
+ throw error
298
+ }
244
299
  }, json)
245
300
 
246
301
  // recursive objects
@@ -1,203 +0,0 @@
1
- import path from 'path'
2
- import os from 'os'
3
- import { readFileSync, writeFileSync, utimesSync } from 'fs'
4
- import logUpdate from 'log-update'
5
- import chalk from 'chalk'
6
- import convertHrtime from 'convert-hrtime'
7
- import cliSpinners from 'cli-spinners'
8
- import * as fileUtils from '../fileUtils.js'
9
- import { labelDefinition } from './definition.js'
10
- import * as xml2js from 'xml2js'
11
- import * as yaml from 'js-yaml'
12
-
13
- const spinner = cliSpinners['dots']
14
-
15
- export class CustomLabel {
16
- #xml = ''
17
- #types = []
18
- #spinnerMessage = ''
19
- #index = 0
20
- #startTime = 0
21
- #fileName = ''
22
- #errorMessage = ''
23
- #fileStats
24
-
25
- constructor(config) {
26
- this.sourceDir = config.sourceDir
27
- this.targetDir = config.targetDir
28
- this.metaDir = config.metaDir
29
- this.processList = config.processList
30
- }
31
-
32
- combine() {
33
- return new Promise((resolve, reject) => {
34
- const that = this
35
- if (!fileUtils.directoryExists(that.sourceDir)) reject(`Path does not exist: ${that.sourceDir}`)
36
-
37
- that.#xml = `<?xml version="1.0" encoding="UTF-8"?>${os.EOL}`
38
- that.#xml += `<CustomLabels xmlns="https://soap.sforce.com/2006/04/metadata">${os.EOL}`
39
-
40
- labelDefinition.directories.forEach(key => { that.#types.push(key) })
41
- that.#types.sort()
42
-
43
- setFileName(that)
44
- processLabel(that)
45
-
46
- saveXML(that)
47
- resolve(true)
48
- })
49
-
50
- function setFileName(that) {
51
- that.#fileName = path.join(that.targetDir, 'CustomLabels.labels-meta.xml')
52
- }
53
-
54
- function processLabel(that) {
55
- that.#startTime = process.hrtime.bigint()
56
- that.#spinnerMessage = `[%1] of ${global.processed.total} - Custom Label: [%4]${chalk.yellowBright('[%5]')}[%2][%3]`
57
- that.processList.sort()
58
- that.#types.forEach(key => {
59
- processDirectory(that, key)
60
- })
61
- }
62
-
63
- function processFile(that, key) {
64
- const fileName = path.join(that.sourceDir, that.metaDir, `${key}.${global.format}`)
65
- if (fileUtils.fileExists(fileName)) {
66
- if (labelDefinition.singleFiles.includes(key)) {
67
- genericXML(that, key)
68
- } else {
69
- that.#errorMessage += `\n${global.statusLevel.warn} Not processed: ${key}`
70
- }
71
- }
72
- }
73
-
74
- function processDirectory(that, key) {
75
- that.sequence = 0
76
- let startTime
77
- that.#errorMessage = ''
78
- that.processList.forEach(fileName => {
79
- startTime = process.hrtime.bigint()
80
- that.sequence++
81
- logUpdate(that.#spinnerMessage
82
- .replace('[%1]', that.sequence.toString().padStart(global.processed.total.toString().length, ' '))
83
- .replace('[%2]', `\n${chalk.magentaBright(nextFrame(that))} ${key}`)
84
- .replace('[%3]', `${that.#errorMessage}`)
85
- .replace('[%4]', `${global.statusLevel.working} `)
86
- .replace('[%5]', `${fileName} `)
87
- )
88
- try {
89
- genericXML(that, key, fileName)
90
- } catch (error) {
91
- that.#errorMessage = error.message
92
- }
93
- let executionTime = getTimeDiff(BigInt(startTime))
94
- let durationMessage = `${executionTime.seconds}.${executionTime.milliseconds}s`
95
- let stateIcon = (that.#errorMessage == '') ? global.statusLevel.success : global.statusLevel.fail
96
- logUpdate(that.#spinnerMessage
97
- .replace('[%1]', that.sequence.toString().padStart(global.processed.total.toString().length, ' '))
98
- .replace('[%2]', `. Processed in ${durationMessage}.`)
99
- .replace('[%3]', `${that.#errorMessage}`)
100
- .replace('[%4]', `${stateIcon} `)
101
- .replace('[%5', fileName)
102
- )
103
- logUpdate.done()
104
- })
105
- // TODO that.#fileStats = fileUtils.fileInfo(fileName).stats
106
-
107
- // genericDirectoryXML(that, key)
108
- // that.#errorMessage += `\n${global.statusLevel.warn} Not processed: ${key}`
109
- return true
110
- }
111
-
112
- function getTimeDiff(startTime, endTime = process.hrtime.bigint()) {
113
- const diff = BigInt(endTime) - BigInt(startTime)
114
- let executionTime = convertHrtime(diff)
115
- executionTime.seconds = Math.round(executionTime.seconds)
116
- executionTime.milliseconds = Math.round(executionTime.milliseconds / 1000)
117
- if (executionTime.milliseconds == 0 && executionTime.nanoseconds > 0) executionTime.milliseconds = 1
118
- return executionTime
119
- }
120
-
121
- function saveXML(that) {
122
- fileUtils.createDirectory(that.targetDir)
123
- that.#xml += '</CustomLabels>\n'
124
- writeFileSync(that.#fileName, that.#xml)
125
- // utimesSync(that.#fileName, that.#fileStats.atime, that.#fileStats.mtime)
126
-
127
- }
128
-
129
- function nextFrame(that) {
130
- return spinner.frames[that.#index = ++that.#index % spinner.frames.length]
131
- }
132
-
133
- function genericXML(that, key, fileName) {
134
- fileName = path.join(that.sourceDir, fileName)
135
- const builder = new xml2js.Builder({ cdata: false, headless: true, rootName: key })
136
- if (fileUtils.fileExists(fileName)) {
137
- const data = readFileSync(fileName, { encoding: 'utf8', flag: 'r' })
138
- const result = (global.format == 'yaml') ? yaml.load(data) : JSON.parse(data)
139
- result[key.slice(0, -1)][labelDefinition.sortKeys[key]] = result[labelDefinition.sortKeys[key]]
140
- result[key.slice(0, -1)] = sortJSONKeys(sortJSON(result[key.slice(0, -1)], labelDefinition.sortKeys[key]))
141
- that.#xml += `\t<${key}>${os.EOL}`
142
- Object.keys(result[key.slice(0, -1)]).forEach(tag => {
143
- let xml
144
- try {
145
- xml = builder.buildObject(result[key.slice(0, -1)][tag]).replace(`<${key}>`, '').replace(`</${key}>`, '')
146
- that.#xml += `\t\t<${tag}>${xml}</${tag}>${os.EOL}`
147
- } catch (error) {
148
- global.logger.error(error)
149
- }
150
- })
151
- that.#xml += `\t</${key}>${os.EOL}`
152
- }
153
- }
154
- // end of functions
155
- // end of combine
156
- }
157
-
158
- // end of class
159
- }
160
-
161
- function sortJSON(json, key) {
162
- if (Array.isArray(json)) {
163
- json.sort((a, b) => {
164
- if (a[key] < b[key]) return -1
165
- if (a[key] > b[key]) return 1
166
- return 0
167
- })
168
- }
169
- return json
170
- }
171
-
172
- function sortJSONKeys(json) {
173
- // sort json keys alphabetically
174
- if (Array.isArray(json)) {
175
- json.forEach(function (part, index) {
176
- this[index] = Object.keys(this[index])
177
- .sort((a, b) => {
178
- if (a < b) return -1
179
- if (a > b) return 1
180
- return 0
181
- })
182
- .reduce((accumulator, key) => {
183
- accumulator[key] = this[index][key]
184
-
185
- return accumulator
186
- }, {})
187
- }, json)
188
-
189
- } else {
190
- json = Object.keys(json)
191
- .sort((a, b) => {
192
- if (a < b) return -1
193
- if (a > b) return 1
194
- return 0
195
- })
196
- .reduce((accumulator, key) => {
197
- accumulator[key] = json[key]
198
-
199
- return accumulator
200
- }, {})
201
- }
202
- return json
203
- }