-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
127 lines (111 loc) · 3.39 KB
/
index.js
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const config = require('./config')
const Logger = require('bucker').createLogger({
name: config.get('/name'),
console: config.get('/logger/options/console'),
})
const Promise = require('bluebird')
const _ = require('lodash')
const jp = require('jsonpath')
const randomstring = require('randomstring')
const { object: templater, string: render } = require('json-templater')
const convert = (template, rules, data, flatten = true) => {
const raw = _.cloneDeep(data)
const SPLIT_KEY = randomstring.generate()
const parent = path =>
jp.stringify(_.dropRightWhile(path, o => !_.isNumber(o)))
const merge = (ctx, save, value, splitter) =>
_.mergeWith(
_.cloneDeep(ctx),
{ [save]: value, [SPLIT_KEY]: splitter },
)
const updateContext = (save, nodes, context) => {
const multiNodes = _.size(nodes) > 1
const multiContext = _.size(context) > 1
const newContext = _.map(context, (ctx) => {
if (multiNodes) {
if (!multiContext) {
if (_.size(nodes) >= 1) {
return _.map(nodes, ({ value, path }) =>
merge(ctx, save, value, [parent(path)]))
}
return _.set(ctx, save, null)
}
const splitter = _.get(ctx, SPLIT_KEY, [])
let filters = _.filter(nodes, ({ path }) => {
let insert = false
const nodeParent = parent(path)
_.each(splitter, (split) => {
if (nodeParent.length === split.length && nodeParent === split) {
insert = true
}
})
return insert
})
if (_.size(filters) === 0) {
filters = _.filter(nodes, ({ path }) => {
let insert = false
const nodeParent = parent(path)
_.each(splitter, (split) => {
if (_.startsWith(nodeParent, split)) {
insert = true
}
})
return insert
})
}
if (_.size(filters) >= 1) {
return _.map(filters, ({ value, path }) =>
merge(ctx, save, value, _.union([parent(path)], splitter)))
}
return _.set(ctx, save, null)
}
const node = _.first(nodes)
if (node) {
return _.set(ctx, save, node.value)
}
return _.set(ctx, save, null)
})
if (multiContext) {
return _.reduce(newContext, (result, value) => result.concat(value), [])
}
return multiNodes ? _.first(newContext) : newContext
}
return new Promise((resolve, reject) => {
Promise.reduce(rules, (context, rule) => {
const {
xpath,
save,
} = rule
return updateContext(
save,
jp.nodes(raw, xpath),
context,
)
}, [{}])
.then((results) => {
const map = _.map(results, item => templater(template, item, (value, data, key) => { // eslint-disable-line
if (value === '{{$}}') {
return raw
}
if (value === '{{~}}') {
return _.omit(item, SPLIT_KEY)
}
const result = render(value, data)
return result.startsWith('{{') ? null : result
}))
if (flatten && _.size(map) === 1) {
return resolve(_.first(map))
}
return resolve(map)
}).catch((error) => {
Logger.error(error)
reject(error)
})
})
}
const version = () =>
config.get('version')
module.exports = {
convert,
version,
}