source: trip-planner-front/node_modules/minipass-json-stream/index.js@ fa375fe

Last change on this file since fa375fe was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 5.9 KB
Line 
1// put javascript in here
2'use strict'
3
4const Parser = require('jsonparse')
5const Minipass = require('minipass')
6
7class JSONStreamError extends Error {
8 constructor (err, caller) {
9 super(err.message)
10 Error.captureStackTrace(this, caller || this.constructor)
11 }
12 get name () {
13 return 'JSONStreamError'
14 }
15 set name (n) {}
16}
17
18const check = (x, y) =>
19 typeof x === 'string' ? String(y) === x
20 : x && typeof x.test === 'function' ? x.test(y)
21 : typeof x === 'boolean' || typeof x === 'object' ? x
22 : typeof x === 'function' ? x(y)
23 : false
24
25const _parser = Symbol('_parser')
26const _onValue = Symbol('_onValue')
27const _onTokenOriginal = Symbol('_onTokenOriginal')
28const _onToken = Symbol('_onToken')
29const _onError = Symbol('_onError')
30const _count = Symbol('_count')
31const _path = Symbol('_path')
32const _map = Symbol('_map')
33const _root = Symbol('_root')
34const _header = Symbol('_header')
35const _footer = Symbol('_footer')
36const _setHeaderFooter = Symbol('_setHeaderFooter')
37const _ending = Symbol('_ending')
38
39class JSONStream extends Minipass {
40 constructor (opts = {}) {
41 super({
42 ...opts,
43 objectMode: true,
44 })
45
46 this[_ending] = false
47 const parser = this[_parser] = new Parser()
48 parser.onValue = value => this[_onValue](value)
49 this[_onTokenOriginal] = parser.onToken
50 parser.onToken = (token, value) => this[_onToken](token, value)
51 parser.onError = er => this[_onError](er)
52
53 this[_count] = 0
54 this[_path] = typeof opts.path === 'string'
55 ? opts.path.split('.').map(e =>
56 e === '$*' ? { emitKey: true }
57 : e === '*' ? true
58 : e === '' ? { recurse: true }
59 : e)
60 : Array.isArray(opts.path) && opts.path.length ? opts.path
61 : null
62
63 this[_map] = typeof opts.map === 'function' ? opts.map : null
64 this[_root] = null
65 this[_header] = null
66 this[_footer] = null
67 this[_count] = 0
68 }
69
70 [_setHeaderFooter] (key, value) {
71 // header has not been emitted yet
72 if (this[_header] !== false) {
73 this[_header] = this[_header] || {}
74 this[_header][key] = value
75 }
76
77 // footer has not been emitted yet but header has
78 if (this[_footer] !== false && this[_header] === false) {
79 this[_footer] = this[_footer] || {}
80 this[_footer][key] = value
81 }
82 }
83
84 [_onError] (er) {
85 // error will always happen during a write() call.
86 const caller = this[_ending] ? this.end : this.write
87 this[_ending] = false
88 return this.emit('error', new JSONStreamError(er, caller))
89 }
90
91 [_onToken] (token, value) {
92 const parser = this[_parser]
93 this[_onTokenOriginal].call(parser, token, value)
94 if (parser.stack.length === 0) {
95 if (this[_root]) {
96 const root = this[_root]
97 if (!this[_path])
98 super.write(root)
99 this[_root] = null
100 this[_count] = 0
101 }
102 }
103 }
104
105 [_onValue] (value) {
106 const parser = this[_parser]
107 // the LAST onValue encountered is the root object.
108 // just overwrite it each time.
109 this[_root] = value
110
111 if(!this[_path]) return
112
113 let i = 0 // iterates on path
114 let j = 0 // iterates on stack
115 let emitKey = false
116 let emitPath = false
117 while (i < this[_path].length) {
118 const key = this[_path][i]
119 j++
120
121 if (key && !key.recurse) {
122 const c = (j === parser.stack.length) ? parser : parser.stack[j]
123 if (!c) return
124 if (!check(key, c.key)) {
125 this[_setHeaderFooter](c.key, value)
126 return
127 }
128 emitKey = !!key.emitKey;
129 emitPath = !!key.emitPath;
130 i++
131 } else {
132 i++
133 if (i >= this[_path].length)
134 return
135 const nextKey = this[_path][i]
136 if (!nextKey)
137 return
138 while (true) {
139 const c = (j === parser.stack.length) ? parser : parser.stack[j]
140 if (!c) return
141 if (check(nextKey, c.key)) {
142 i++
143 if (!Object.isFrozen(parser.stack[j]))
144 parser.stack[j].value = null
145 break
146 } else {
147 this[_setHeaderFooter](c.key, value)
148 }
149 j++
150 }
151 }
152 }
153
154 // emit header
155 if (this[_header]) {
156 const header = this[_header]
157 this[_header] = false
158 this.emit('header', header)
159 }
160 if (j !== parser.stack.length) return
161
162 this[_count] ++
163 const actualPath = parser.stack.slice(1)
164 .map(e => e.key).concat([parser.key])
165 if (value !== null && value !== undefined) {
166 const data = this[_map] ? this[_map](value, actualPath) : value
167 if (data !== null && data !== undefined) {
168 const emit = emitKey || emitPath ? { value: data } : data
169 if (emitKey)
170 emit.key = parser.key
171 if (emitPath)
172 emit.path = actualPath
173 super.write(emit)
174 }
175 }
176
177 if (parser.value)
178 delete parser.value[parser.key]
179
180 for (const k of parser.stack) {
181 k.value = null
182 }
183 }
184
185 write (chunk, encoding, cb) {
186 if (typeof encoding === 'function')
187 cb = encoding, encoding = null
188 if (typeof chunk === 'string')
189 chunk = Buffer.from(chunk, encoding)
190 else if (!Buffer.isBuffer(chunk))
191 return this.emit('error', new TypeError(
192 'Can only parse JSON from string or buffer input'))
193 this[_parser].write(chunk)
194 if (cb)
195 cb()
196 return this.flowing
197 }
198
199 end (chunk, encoding, cb) {
200 this[_ending] = true
201 if (typeof encoding === 'function')
202 cb = encoding, encoding = null
203 if (typeof chunk === 'function')
204 cb = chunk, chunk = null
205 if (chunk)
206 this.write(chunk, encoding)
207 if (cb)
208 this.once('end', cb)
209
210 const h = this[_header]
211 this[_header] = null
212 const f = this[_footer]
213 this[_footer] = null
214 if (h)
215 this.emit('header', h)
216 if (f)
217 this.emit('footer', f)
218 return super.end()
219 }
220
221 static get JSONStreamError () { return JSONStreamError }
222 static parse (path, map) {
223 return new JSONStream({path, map})
224 }
225}
226
227module.exports = JSONStream
Note: See TracBrowser for help on using the repository browser.