-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.js
149 lines (128 loc) · 3.32 KB
/
util.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
var mapMerge = require('map-merge')
var Obv = require('obv')
var pull = require('pull-stream')
var isArray = Array.isArray
function clone (obj, mapper) {
function map(v, k) {
return isObject(v) ? clone(v, mapper) : mapper(v, k)
}
if(isArray(obj)) {
return obj.map(map)
} else if(isObject(obj)) {
var o = {}
for(var k in obj) {
o[k] = map(obj[k], k)
}
return o
} else {
return map(obj)
}
}
module.exports.hookOptionalCB = function hookOptionalCB (syncFn) {
// syncFn is a function that's expected to return its result or throw an error
// we're going to hook it so you can optionally pass a callback
syncFn.hook(function(fn, args) {
// if a function is given as the last argument, treat it as a callback
var cb = args[args.length - 1]
if (typeof cb == 'function') {
var res
args.pop() // remove cb from the arguments
try { res = fn.apply(this, args) }
catch (e) { return cb(e) }
cb(null, res)
} else {
// no cb provided, regular usage
return fn.apply(this, args)
}
})
}
module.exports.mergeApi = function mergeApi (a, b, mapper) {
for(var k in b) {
if(b[k] && 'object' === typeof b[k] && !Buffer.isBuffer(b[k]))
mergeApi(a[k] = {}, b[k], mapper)
else
a[k] = mapper(b[k], k)
}
return a
}
module.exports.mergeManifest = function mergeManifest (manf, _manf, name) {
if(name) {
var o = {}; o[name] = _manf; _manf = o
}
return mapMerge(manf, _manf)
}
module.exports.mergePermisson = function mergePermissions (perms, _perms, name) {
return mapMerge(perms,
clone(_perms, function (v) {
return name ? name + '.' + v : v
})
)
}
// Function to recursively convert all sync manifest methods to async
module.exports.syncToAsync = function syncToAsync (manifest) {
var copy = {}
Object.keys(manifest).forEach(function(key) {
if ('string' !== typeof manifest[key]) {
copy[key] = syncToAsync(manifest[key])
} else if(manifest[key] === 'sync') {
copy[key] = 'async'
} else {
copy[key] = manifest[key]
}
})
return copy
}
var getLatestTimestamp = function (api, cb) {
pull(
api.latest(),
pull.reduce((max, item) => item.ts > max ? item.ts : max, 0, cb)
)
}
module.exports.getSince = function (api) {
if ('sinceStream' in api) {
var obv = Obv()
pull(
api.sinceStream(),
pull.drain(val => {
obv.set(val)
})
)
return obv
}
if ('latest' in api) {
return poll(cb => getLatestTimestamp(api, cb), val => val, 5000)
}
if ('since' in api) {
return poll(cb => api.since(cb), val => val, 2000)
}
if ('status' in api) {
return poll(cb => api.status(cb), val => val.sync.since, 2000)
}
throw new Error('Cannot find or emulate since parameter')
}
function poll (f, select, interval) {
var obv = Obv()
var close = false
var updateSince = function () {
f((err, val) => {
if(err)
throw err
obv.set(select(val))
if (!close)
setTimeout(updateSince, interval)
})
}
updateSince()
obv.close = function () {
close = true
}
return obv
}
module.exports.noop = function noop (err) {
if (err) throw explain(err, 'callback not provided')
}
function isObject (o) {
return o && 'object' === typeof o
}
module.exports.isObject = isObject
module.exports.clone = clone