@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 +1 -1
- package/src/index.js +27 -11
- package/src/lib/checkVersion.js +3 -7
- package/src/lib/packageUtil.js +16 -2
- package/src/lib/pkgObj.cjs +1 -0
- package/src/meta/Workflows.js +9 -0
- package/test/{checkVersion.spec.js → lib/checkVersion.spec.js} +1 -1
- package/test/lib/package/getPackageXML.spec.js +148 -34
- /package/test/{root.spec.js → src/root.spec.js} +0 -0
package/package.json
CHANGED
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
|
|
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.
|
|
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
|
-
|
|
194
|
+
gitMode({status: 'not active'})
|
|
197
195
|
resolve(false)
|
|
198
196
|
} else {
|
|
199
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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)
|
package/src/lib/checkVersion.js
CHANGED
|
@@ -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
|
-
|
|
37
|
-
|
|
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')}`)
|
package/src/lib/packageUtil.js
CHANGED
|
@@ -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
|
-
|
|
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')
|
package/src/meta/Workflows.js
CHANGED
|
@@ -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 '
|
|
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
|
-
|
|
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
|