source: frontend/node_modules/bfj/src/parse.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 3.8 KB
Line 
1'use strict'
2
3const check = require('check-types')
4const events = require('./events')
5const promise = require('./promise')
6const walk = require('./walk')
7
8module.exports = parse
9
10const NDJSON_STATE = new Map()
11
12/**
13 * Public function `parse`.
14 *
15 * Returns a promise and asynchronously parses a stream of JSON data. If
16 * there are no errors, the promise is resolved with the parsed data. If
17 * errors occur, the promise is rejected with the first error.
18 *
19 * @param stream: Readable instance representing the incoming JSON.
20 *
21 * @option reviver: Transformation function, invoked depth-first.
22 *
23 * @option yieldRate: The number of data items to process per timeslice,
24 * default is 16384.
25 *
26 * @option Promise: The promise constructor to use, defaults to bluebird.
27 *
28 * @option ndjson: Set this to true to parse newline-delimited JSON. In
29 * this case, each call will be resolved with one value
30 * from the stream. To parse the entire stream, calls
31 * should be made sequentially one-at-a-time until the
32 * returned promise resolves to `undefined`.
33 **/
34function parse (stream, options = {}) {
35 const Promise = promise(options)
36
37 try {
38 check.assert.maybe.function(options.reviver, 'Invalid reviver option')
39 } catch (err) {
40 return Promise.reject(err)
41 }
42
43 const errors = []
44 const scopes = []
45 const reviver = options.reviver
46 const shouldHandleNdjson = !! options.ndjson
47
48 let emitter, resolve, reject, scopeKey
49 if (shouldHandleNdjson && NDJSON_STATE.has(stream)) {
50 const state = NDJSON_STATE.get(stream)
51 NDJSON_STATE.delete(stream)
52 emitter = state.emitter
53 setImmediate(state.resume)
54 } else {
55 emitter = walk(stream, options)
56 }
57
58 emitter.on(events.array, array)
59 emitter.on(events.object, object)
60 emitter.on(events.property, property)
61 emitter.on(events.string, value)
62 emitter.on(events.number, value)
63 emitter.on(events.literal, value)
64 emitter.on(events.endArray, endScope)
65 emitter.on(events.endObject, endScope)
66 emitter.on(events.end, end)
67 emitter.on(events.error, error)
68 emitter.on(events.dataError, error)
69
70 if (shouldHandleNdjson) {
71 emitter.on(events.endLine, endLine)
72 }
73
74 return new Promise((res, rej) => {
75 resolve = res
76 reject = rej
77 })
78
79 function array () {
80 if (errors.length > 0) {
81 return
82 }
83
84 beginScope([])
85 }
86
87 function beginScope (parsed) {
88 if (errors.length > 0) {
89 return
90 }
91
92 if (scopes.length > 0) {
93 value(parsed)
94 }
95
96 scopes.push(parsed)
97 }
98
99 function value (v) {
100 if (errors.length > 0) {
101 return
102 }
103
104 if (scopes.length === 0) {
105 return scopes.push(v)
106 }
107
108 const scope = scopes[scopes.length - 1]
109
110 if (scopeKey) {
111 scope[scopeKey] = v
112 scopeKey = null
113 } else {
114 scope.push(v)
115 }
116 }
117
118 function object () {
119 if (errors.length > 0) {
120 return
121 }
122
123 beginScope({})
124 }
125
126 function property (name) {
127 if (errors.length > 0) {
128 return
129 }
130
131 scopeKey = name
132 }
133
134 function endScope () {
135 if (errors.length > 0) {
136 return
137 }
138
139 if (scopes.length > 1) {
140 scopes.pop()
141 }
142 }
143
144 function end () {
145 if (shouldHandleNdjson) {
146 const resume = emitter.pause()
147 emitter.removeAllListeners()
148 NDJSON_STATE.set(stream, { emitter, resume })
149 }
150
151 if (errors.length > 0) {
152 return reject(errors[0])
153 }
154
155 if (reviver) {
156 scopes[0] = transform(scopes[0], '')
157 }
158
159 resolve(scopes[0])
160 }
161
162 function transform (obj, key) {
163 if (obj && typeof obj === 'object') {
164 Object.entries(obj).forEach(([ k, v ]) => {
165 obj[k] = transform(v, k)
166 })
167 }
168
169 return reviver(key, obj)
170 }
171
172 function error (e) {
173 errors.push(e)
174 }
175
176 function endLine () {
177 if (scopes.length > 0) {
178 end()
179 }
180 }
181}
Note: See TracBrowser for help on using the repository browser.