UNPKG

3.33 kBJavaScriptView Raw
1'use strict';
2var pull = require('pull-stream')
3
4function isString (s) {
5 return 'string' === typeof s
6}
7
8var isArray = Array.isArray
9
10function isObject (o) {
11 return o && 'object' === typeof o && !isArray(o)
12}
13
14function isEmpty (obj) {
15 for(var k in obj) return false;
16 return true
17}
18
19//I wrote set as part of permissions.js
20//and then later mount, they do nearly the same thing
21//but not quite. this should be refactored sometime.
22//what differs is that set updates the last key in the path
23//to the new value, but mount merges the last value
24//which makes sense if it's an object, and set makes sense if it's
25//a string/number/boolean.
26
27exports.set = function (obj, path, value) {
28 var _obj, _k
29 for(var i = 0; i < path.length; i++) {
30 var k = path[i]
31 obj[k] = obj[k] || {}
32 _obj = obj; _k = k
33 obj = obj[k]
34 }
35 _obj[_k] = value
36}
37
38exports.get = function (obj, path) {
39 if(isString(path)) return obj[path]
40 var value
41 for(var i = 0; i < path.length; i++) {
42 var k = path[i]
43 value = obj = obj[k]
44 if(null == obj) return obj
45 }
46 return value
47}
48
49exports.prefix = function (obj, path) {
50 var value, parent = obj
51
52 for(var i = 0; i < path.length; i++) {
53 var k = path[i]
54 value = obj = obj[k]
55 if('object' !== typeof obj) {
56 return obj
57 }
58 parent = obj
59 }
60 return 'object' !== typeof value ? !!value : false
61}
62
63
64function mkPath(obj, path) {
65 for(var i in path) {
66 var key = path[i]
67 if(!obj[key]) obj[key]={}
68 obj = obj[key]
69 }
70
71 return obj
72}
73
74function rmPath (obj, path) {
75 (function r (obj, i) {
76 var key = path[i]
77 if(!obj) return
78 else if(path.length - 1 === i)
79 delete obj[key]
80 else if(i < path.length) r(obj[key], i+1)
81 if(isEmpty(obj[key])) delete obj[key]
82 })(obj, 0)
83}
84
85function merge (obj, _obj) {
86 for(var k in _obj)
87 obj[k] = _obj[k]
88 return obj
89}
90
91var mount = exports.mount = function (obj, path, _obj) {
92 if(!Array.isArray(path))
93 throw new Error('path must be array of strings')
94 return merge(mkPath(obj, path), _obj)
95}
96var unmount = exports.unmount = function (obj, path) {
97 return rmPath(obj, path)
98}
99
100function isSource (t) { return 'source' === t }
101function isSink (t) { return 'sink' === t }
102function isDuplex (t) { return 'duplex' === t }
103function isSync (t) { return 'sync' === t }
104function isAsync (t) { return 'async' === t }
105function isRequest (t) { return isSync(t) || isAsync(t) }
106function isStream (t) { return isSource(t) || isSink(t) || isDuplex(t) }
107
108function abortSink (err) {
109 return function (read) {
110 read(err || true, function () {})
111 }
112}
113
114function abortDuplex (err) {
115 return {source: pull.error(err), sink: abortSink(err)}
116}
117
118exports.errorAsStream = function (type, err) {
119 return (
120 isSource(type) ? pull.error(err)
121 : isSink(type) ? abortSink(err)
122 : abortDuplex(err)
123 )
124}
125
126
127exports.errorAsStreamOrCb = function (type, err, cb) {
128 return (
129 isRequest(type) ? cb(err)
130 : isSource(type) ? pull.error(err)
131 : isSink(type) ? abortSink(err)
132 : cb(err), abortDuplex(err)
133 )
134}
135
136exports.pipeToStream = function (type, _stream, stream) {
137 if(isSource(type))
138 _stream(stream)
139 else if (isSink(type))
140 stream(_stream)
141 else if (isDuplex(type))
142 pull(_stream, stream, _stream)
143}
144