forked from kuzzleio/kourou
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdiff.ts
94 lines (75 loc) · 2.85 KB
/
diff.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { flags } from '@oclif/command'
import _ from 'lodash'
import fs from 'fs'
import stripComments from 'strip-json-comments'
import { Kommand } from '../../common'
export class ConfigKeyDiff extends Kommand {
static initSdk = false
static description = 'Returns differences between two Kuzzle configuration files (kuzzlerc)'
static examples = [
'kourou config:diff config/local/kuzzlerc config/production/kuzzlerc'
]
static flags = {
strict: flags.boolean({
description: 'Exit with an error if differences are found',
default: false
}),
values: flags.boolean({
description: 'Also displays value changes',
default: false
})
}
static args = [
{ name: 'first', description: 'First configuration file', required: true },
{ name: 'second', description: 'Second configuration file', required: true },
]
async runSafe() {
if (!fs.existsSync(this.args.first)) {
throw new Error(`File "${this.args.first}" does not exists`)
}
if (!fs.existsSync(this.args.second)) {
throw new Error(`File "${this.args.second}" does not exists`)
}
const first = JSON.parse(stripComments(fs.readFileSync(this.args.first, 'utf8')))
const second = JSON.parse(stripComments(fs.readFileSync(this.args.second, 'utf8')))
const changes = this._keyChanges(first, second)
if (_.isEmpty(changes)) {
this.logOk('No differences between keys in the provided configurations')
return
}
this.logInfo('Found differences between keys in the provided configurations. In the second file:')
for (const [path, change] of Object.entries(changes)) {
this.log(` - key "${path}" ${change}`)
}
if (this.flags.strict) {
throw new Error('Provided configuration contains different keys')
}
}
// Returns path who had changed between two objects (inspired by https://gist.github.com/Yimiprod/7ee176597fef230d1451)
_keyChanges(base: any, object: any) {
const changes: any = {}
const walkObject = (_base: any, _object: any, path: any = []) => {
for (const key of Object.keys(_base)) {
if (_object[key] === undefined) {
const ar: [] = []
const ar2: [] = []
ar.concat(ar2)
changes[[...path, key].join('.')] = 'was removed'
}
}
for (const key of Object.keys(_object)) {
if (_base[key] === undefined) {
changes[[...path, key].join('.')] = 'was added'
}
else if (!_.isEqual(_object[key], _base[key]) && _.isObject(_object[key]) && _.isObject(_base[key])) {
walkObject(_base[key], _object[key], [...path, key])
}
else if (this.flags.values && _base[key] !== _object[key]) {
changes[[...path, key].join('.')] = `value is "${_object[key]}" and was "${_base[key]}"`
}
}
}
walkObject(base, object)
return changes
}
}