@langchain/google-common 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +47 -0
- package/dist/auth.cjs +90 -0
- package/dist/auth.d.ts +39 -0
- package/dist/auth.js +83 -0
- package/dist/chat_models.cjs +153 -0
- package/dist/chat_models.d.ts +46 -0
- package/dist/chat_models.js +149 -0
- package/dist/connection.cjs +231 -0
- package/dist/connection.d.ts +47 -0
- package/dist/connection.js +224 -0
- package/dist/index.cjs +23 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/llms.cjs +162 -0
- package/dist/llms.d.ts +48 -0
- package/dist/llms.js +158 -0
- package/dist/types.cjs +2 -0
- package/dist/types.d.ts +146 -0
- package/dist/types.js +1 -0
- package/dist/utils/common.cjs +48 -0
- package/dist/utils/common.d.ts +6 -0
- package/dist/utils/common.js +40 -0
- package/dist/utils/gemini.cjs +239 -0
- package/dist/utils/gemini.d.ts +20 -0
- package/dist/utils/gemini.js +219 -0
- package/dist/utils/palm.cjs +2 -0
- package/dist/utils/palm.d.ts +6 -0
- package/dist/utils/palm.js +1 -0
- package/dist/utils/stream.cjs +304 -0
- package/dist/utils/stream.d.ts +70 -0
- package/dist/utils/stream.js +296 -0
- package/index.cjs +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReadableJsonStream = exports.ComplexJsonStream = exports.JsonStream = exports.simpleValue = exports.complexValue = void 0;
|
|
4
|
+
function complexValue(value) {
|
|
5
|
+
if (value === null || typeof value === "undefined") {
|
|
6
|
+
// I dunno what to put here. An error, probably
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
else if (typeof value === "object") {
|
|
10
|
+
if (Array.isArray(value)) {
|
|
11
|
+
return {
|
|
12
|
+
list_val: value.map((avalue) => complexValue(avalue)),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const ret = {};
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
const v = value;
|
|
19
|
+
Object.keys(v).forEach((key) => {
|
|
20
|
+
ret[key] = complexValue(v[key]);
|
|
21
|
+
});
|
|
22
|
+
return { struct_val: ret };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else if (typeof value === "number") {
|
|
26
|
+
if (Number.isInteger(value)) {
|
|
27
|
+
return { int_val: value };
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return { float_val: value };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return {
|
|
35
|
+
string_val: [value],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.complexValue = complexValue;
|
|
40
|
+
function simpleValue(val) {
|
|
41
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
42
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
43
|
+
if (val.hasOwnProperty("stringVal")) {
|
|
44
|
+
return val.stringVal[0];
|
|
45
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
46
|
+
}
|
|
47
|
+
else if (val.hasOwnProperty("boolVal")) {
|
|
48
|
+
return val.boolVal[0];
|
|
49
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
50
|
+
}
|
|
51
|
+
else if (val.hasOwnProperty("listVal")) {
|
|
52
|
+
const { listVal } = val;
|
|
53
|
+
return listVal.map((aval) => simpleValue(aval));
|
|
54
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
55
|
+
}
|
|
56
|
+
else if (val.hasOwnProperty("structVal")) {
|
|
57
|
+
const ret = {};
|
|
58
|
+
const struct = val.structVal;
|
|
59
|
+
Object.keys(struct).forEach((key) => {
|
|
60
|
+
ret[key] = simpleValue(struct[key]);
|
|
61
|
+
});
|
|
62
|
+
return ret;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const ret = {};
|
|
66
|
+
const struct = val;
|
|
67
|
+
Object.keys(struct).forEach((key) => {
|
|
68
|
+
ret[key] = simpleValue(struct[key]);
|
|
69
|
+
});
|
|
70
|
+
return ret;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (Array.isArray(val)) {
|
|
74
|
+
return val.map((aval) => simpleValue(aval));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return val;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.simpleValue = simpleValue;
|
|
81
|
+
class JsonStream {
|
|
82
|
+
constructor() {
|
|
83
|
+
Object.defineProperty(this, "_buffer", {
|
|
84
|
+
enumerable: true,
|
|
85
|
+
configurable: true,
|
|
86
|
+
writable: true,
|
|
87
|
+
value: ""
|
|
88
|
+
});
|
|
89
|
+
Object.defineProperty(this, "_bufferOpen", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
configurable: true,
|
|
92
|
+
writable: true,
|
|
93
|
+
value: true
|
|
94
|
+
});
|
|
95
|
+
Object.defineProperty(this, "_firstRun", {
|
|
96
|
+
enumerable: true,
|
|
97
|
+
configurable: true,
|
|
98
|
+
writable: true,
|
|
99
|
+
value: true
|
|
100
|
+
});
|
|
101
|
+
// Set up a potential Promise that the handler can resolve.
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
103
|
+
Object.defineProperty(this, "_chunkResolution", {
|
|
104
|
+
enumerable: true,
|
|
105
|
+
configurable: true,
|
|
106
|
+
writable: true,
|
|
107
|
+
value: void 0
|
|
108
|
+
});
|
|
109
|
+
// If there is no Promise (it is null), the handler must add it to the queue
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
|
+
Object.defineProperty(this, "_chunkPending", {
|
|
112
|
+
enumerable: true,
|
|
113
|
+
configurable: true,
|
|
114
|
+
writable: true,
|
|
115
|
+
value: null
|
|
116
|
+
});
|
|
117
|
+
// A queue that will collect chunks while there is no Promise
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
119
|
+
Object.defineProperty(this, "_chunkQueue", {
|
|
120
|
+
enumerable: true,
|
|
121
|
+
configurable: true,
|
|
122
|
+
writable: true,
|
|
123
|
+
value: []
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Add data to the buffer. This may cause chunks to be generated, if available.
|
|
128
|
+
* @param data
|
|
129
|
+
*/
|
|
130
|
+
appendBuffer(data) {
|
|
131
|
+
this._buffer += data;
|
|
132
|
+
// Our first time, skip to the opening of the array
|
|
133
|
+
if (this._firstRun) {
|
|
134
|
+
this._skipTo("[");
|
|
135
|
+
this._firstRun = false;
|
|
136
|
+
}
|
|
137
|
+
this._parseBuffer();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Indicate there is no more data that will be added to the text buffer.
|
|
141
|
+
* This should be called when all the data has been read and added to indicate
|
|
142
|
+
* that we should process everything remaining in the buffer.
|
|
143
|
+
*/
|
|
144
|
+
closeBuffer() {
|
|
145
|
+
this._bufferOpen = false;
|
|
146
|
+
this._parseBuffer();
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Skip characters in the buffer till we get to the start of an object.
|
|
150
|
+
* Then attempt to read a full object.
|
|
151
|
+
* If we do read a full object, turn it into a chunk and send it to the chunk handler.
|
|
152
|
+
* Repeat this for as much as we can.
|
|
153
|
+
*/
|
|
154
|
+
_parseBuffer() {
|
|
155
|
+
let obj = null;
|
|
156
|
+
do {
|
|
157
|
+
this._skipTo("{");
|
|
158
|
+
obj = this._getFullObject();
|
|
159
|
+
if (obj !== null) {
|
|
160
|
+
const chunk = this._simplifyObject(obj);
|
|
161
|
+
this._handleChunk(chunk);
|
|
162
|
+
}
|
|
163
|
+
} while (obj !== null);
|
|
164
|
+
if (!this._bufferOpen) {
|
|
165
|
+
// No more data will be added, and we have parsed everything we could,
|
|
166
|
+
// so everything else is garbage.
|
|
167
|
+
this._handleChunk(null);
|
|
168
|
+
this._buffer = "";
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* If the string is present, move the start of the buffer to the first occurrence
|
|
173
|
+
* of that string. This is useful for skipping over elements or parts that we're not
|
|
174
|
+
* really interested in parsing. (ie - the opening characters, comma separators, etc.)
|
|
175
|
+
* @param start The string to start the buffer with
|
|
176
|
+
*/
|
|
177
|
+
_skipTo(start) {
|
|
178
|
+
const index = this._buffer.indexOf(start);
|
|
179
|
+
if (index > 0) {
|
|
180
|
+
this._buffer = this._buffer.slice(index);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Given what is in the buffer, parse a single object out of it.
|
|
185
|
+
* If a complete object isn't available, return null.
|
|
186
|
+
* Assumes that we are at the start of an object to parse.
|
|
187
|
+
*/
|
|
188
|
+
_getFullObject() {
|
|
189
|
+
let ret = null;
|
|
190
|
+
// Loop while we don't have something to return AND we have something in the buffer
|
|
191
|
+
let index = 0;
|
|
192
|
+
while (ret === null && this._buffer.length > index) {
|
|
193
|
+
// Advance to the next close bracket after our current index
|
|
194
|
+
index = this._buffer.indexOf("}", index + 1);
|
|
195
|
+
// If we don't find one, exit with null
|
|
196
|
+
if (index === -1) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
// If we have one, try to turn it into an object to return
|
|
200
|
+
try {
|
|
201
|
+
const objStr = this._buffer.substring(0, index + 1);
|
|
202
|
+
ret = JSON.parse(objStr);
|
|
203
|
+
// We only get here if it parsed it ok
|
|
204
|
+
// If we did turn it into an object, remove it from the buffer
|
|
205
|
+
this._buffer = this._buffer.slice(index + 1);
|
|
206
|
+
}
|
|
207
|
+
catch (xx) {
|
|
208
|
+
// It didn't parse it correctly, so we swallow the exception and continue
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return ret;
|
|
212
|
+
}
|
|
213
|
+
_simplifyObject(obj) {
|
|
214
|
+
return obj;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Register that we have another chunk available for consumption.
|
|
218
|
+
* If we are waiting for a chunk, resolve the promise waiting for it immediately.
|
|
219
|
+
* If not, then add it to the queue.
|
|
220
|
+
* @param chunk
|
|
221
|
+
*/
|
|
222
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
223
|
+
_handleChunk(chunk) {
|
|
224
|
+
if (this._chunkPending) {
|
|
225
|
+
this._chunkResolution(chunk);
|
|
226
|
+
this._chunkPending = null;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
this._chunkQueue.push(chunk);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Get the next chunk that is coming from the stream.
|
|
234
|
+
* This chunk may be null, usually indicating the last chunk in the stream.
|
|
235
|
+
*/
|
|
236
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
237
|
+
async nextChunk() {
|
|
238
|
+
if (this._chunkQueue.length > 0) {
|
|
239
|
+
// If there is data in the queue, return the next queue chunk
|
|
240
|
+
return this._chunkQueue.shift();
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
// Otherwise, set up a promise that handleChunk will cause to be resolved
|
|
244
|
+
this._chunkPending = new Promise((resolve) => {
|
|
245
|
+
this._chunkResolution = resolve;
|
|
246
|
+
});
|
|
247
|
+
return this._chunkPending;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Is the stream done?
|
|
252
|
+
* A stream is only done if all of the following are true:
|
|
253
|
+
* - There is no more data to be added to the text buffer
|
|
254
|
+
* - There is no more data in the text buffer
|
|
255
|
+
* - There are no chunks that are waiting to be consumed
|
|
256
|
+
*/
|
|
257
|
+
get streamDone() {
|
|
258
|
+
return (!this._bufferOpen &&
|
|
259
|
+
this._buffer.length === 0 &&
|
|
260
|
+
this._chunkQueue.length === 0 &&
|
|
261
|
+
this._chunkPending === null);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
exports.JsonStream = JsonStream;
|
|
265
|
+
class ComplexJsonStream extends JsonStream {
|
|
266
|
+
_simplifyObject(obj) {
|
|
267
|
+
return simpleValue(obj);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
exports.ComplexJsonStream = ComplexJsonStream;
|
|
271
|
+
class ReadableJsonStream extends JsonStream {
|
|
272
|
+
constructor(body) {
|
|
273
|
+
super();
|
|
274
|
+
Object.defineProperty(this, "decoder", {
|
|
275
|
+
enumerable: true,
|
|
276
|
+
configurable: true,
|
|
277
|
+
writable: true,
|
|
278
|
+
value: void 0
|
|
279
|
+
});
|
|
280
|
+
this.decoder = new TextDecoder();
|
|
281
|
+
if (body) {
|
|
282
|
+
void this.run(body);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
console.error("Unexpected empty body while streaming");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async run(body) {
|
|
289
|
+
const reader = body.getReader();
|
|
290
|
+
let isDone = false;
|
|
291
|
+
while (!isDone) {
|
|
292
|
+
const { value, done } = await reader.read();
|
|
293
|
+
if (!done) {
|
|
294
|
+
const svalue = this.decoder.decode(value);
|
|
295
|
+
this.appendBuffer(svalue);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
isDone = done;
|
|
299
|
+
this.closeBuffer();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
exports.ReadableJsonStream = ReadableJsonStream;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export declare function complexValue(value: unknown): unknown;
|
|
2
|
+
export declare function simpleValue(val: unknown): unknown;
|
|
3
|
+
export declare class JsonStream {
|
|
4
|
+
_buffer: string;
|
|
5
|
+
_bufferOpen: boolean;
|
|
6
|
+
_firstRun: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Add data to the buffer. This may cause chunks to be generated, if available.
|
|
9
|
+
* @param data
|
|
10
|
+
*/
|
|
11
|
+
appendBuffer(data: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Indicate there is no more data that will be added to the text buffer.
|
|
14
|
+
* This should be called when all the data has been read and added to indicate
|
|
15
|
+
* that we should process everything remaining in the buffer.
|
|
16
|
+
*/
|
|
17
|
+
closeBuffer(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Skip characters in the buffer till we get to the start of an object.
|
|
20
|
+
* Then attempt to read a full object.
|
|
21
|
+
* If we do read a full object, turn it into a chunk and send it to the chunk handler.
|
|
22
|
+
* Repeat this for as much as we can.
|
|
23
|
+
*/
|
|
24
|
+
_parseBuffer(): void;
|
|
25
|
+
/**
|
|
26
|
+
* If the string is present, move the start of the buffer to the first occurrence
|
|
27
|
+
* of that string. This is useful for skipping over elements or parts that we're not
|
|
28
|
+
* really interested in parsing. (ie - the opening characters, comma separators, etc.)
|
|
29
|
+
* @param start The string to start the buffer with
|
|
30
|
+
*/
|
|
31
|
+
_skipTo(start: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Given what is in the buffer, parse a single object out of it.
|
|
34
|
+
* If a complete object isn't available, return null.
|
|
35
|
+
* Assumes that we are at the start of an object to parse.
|
|
36
|
+
*/
|
|
37
|
+
_getFullObject(): object | null;
|
|
38
|
+
_simplifyObject(obj: unknown): object;
|
|
39
|
+
_chunkResolution: (chunk: any) => void;
|
|
40
|
+
_chunkPending: Promise<any> | null;
|
|
41
|
+
_chunkQueue: any[];
|
|
42
|
+
/**
|
|
43
|
+
* Register that we have another chunk available for consumption.
|
|
44
|
+
* If we are waiting for a chunk, resolve the promise waiting for it immediately.
|
|
45
|
+
* If not, then add it to the queue.
|
|
46
|
+
* @param chunk
|
|
47
|
+
*/
|
|
48
|
+
_handleChunk(chunk: any): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get the next chunk that is coming from the stream.
|
|
51
|
+
* This chunk may be null, usually indicating the last chunk in the stream.
|
|
52
|
+
*/
|
|
53
|
+
nextChunk(): Promise<any>;
|
|
54
|
+
/**
|
|
55
|
+
* Is the stream done?
|
|
56
|
+
* A stream is only done if all of the following are true:
|
|
57
|
+
* - There is no more data to be added to the text buffer
|
|
58
|
+
* - There is no more data in the text buffer
|
|
59
|
+
* - There are no chunks that are waiting to be consumed
|
|
60
|
+
*/
|
|
61
|
+
get streamDone(): boolean;
|
|
62
|
+
}
|
|
63
|
+
export declare class ComplexJsonStream extends JsonStream {
|
|
64
|
+
_simplifyObject(obj: unknown): object;
|
|
65
|
+
}
|
|
66
|
+
export declare class ReadableJsonStream extends JsonStream {
|
|
67
|
+
decoder: TextDecoder;
|
|
68
|
+
constructor(body: ReadableStream | null);
|
|
69
|
+
run(body: ReadableStream): Promise<void>;
|
|
70
|
+
}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
export function complexValue(value) {
|
|
2
|
+
if (value === null || typeof value === "undefined") {
|
|
3
|
+
// I dunno what to put here. An error, probably
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
else if (typeof value === "object") {
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
return {
|
|
9
|
+
list_val: value.map((avalue) => complexValue(avalue)),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const ret = {};
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
const v = value;
|
|
16
|
+
Object.keys(v).forEach((key) => {
|
|
17
|
+
ret[key] = complexValue(v[key]);
|
|
18
|
+
});
|
|
19
|
+
return { struct_val: ret };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (typeof value === "number") {
|
|
23
|
+
if (Number.isInteger(value)) {
|
|
24
|
+
return { int_val: value };
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
return { float_val: value };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return {
|
|
32
|
+
string_val: [value],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function simpleValue(val) {
|
|
37
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
38
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
39
|
+
if (val.hasOwnProperty("stringVal")) {
|
|
40
|
+
return val.stringVal[0];
|
|
41
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
42
|
+
}
|
|
43
|
+
else if (val.hasOwnProperty("boolVal")) {
|
|
44
|
+
return val.boolVal[0];
|
|
45
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
46
|
+
}
|
|
47
|
+
else if (val.hasOwnProperty("listVal")) {
|
|
48
|
+
const { listVal } = val;
|
|
49
|
+
return listVal.map((aval) => simpleValue(aval));
|
|
50
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
51
|
+
}
|
|
52
|
+
else if (val.hasOwnProperty("structVal")) {
|
|
53
|
+
const ret = {};
|
|
54
|
+
const struct = val.structVal;
|
|
55
|
+
Object.keys(struct).forEach((key) => {
|
|
56
|
+
ret[key] = simpleValue(struct[key]);
|
|
57
|
+
});
|
|
58
|
+
return ret;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const ret = {};
|
|
62
|
+
const struct = val;
|
|
63
|
+
Object.keys(struct).forEach((key) => {
|
|
64
|
+
ret[key] = simpleValue(struct[key]);
|
|
65
|
+
});
|
|
66
|
+
return ret;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (Array.isArray(val)) {
|
|
70
|
+
return val.map((aval) => simpleValue(aval));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
return val;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export class JsonStream {
|
|
77
|
+
constructor() {
|
|
78
|
+
Object.defineProperty(this, "_buffer", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
configurable: true,
|
|
81
|
+
writable: true,
|
|
82
|
+
value: ""
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(this, "_bufferOpen", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
configurable: true,
|
|
87
|
+
writable: true,
|
|
88
|
+
value: true
|
|
89
|
+
});
|
|
90
|
+
Object.defineProperty(this, "_firstRun", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
configurable: true,
|
|
93
|
+
writable: true,
|
|
94
|
+
value: true
|
|
95
|
+
});
|
|
96
|
+
// Set up a potential Promise that the handler can resolve.
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
98
|
+
Object.defineProperty(this, "_chunkResolution", {
|
|
99
|
+
enumerable: true,
|
|
100
|
+
configurable: true,
|
|
101
|
+
writable: true,
|
|
102
|
+
value: void 0
|
|
103
|
+
});
|
|
104
|
+
// If there is no Promise (it is null), the handler must add it to the queue
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
Object.defineProperty(this, "_chunkPending", {
|
|
107
|
+
enumerable: true,
|
|
108
|
+
configurable: true,
|
|
109
|
+
writable: true,
|
|
110
|
+
value: null
|
|
111
|
+
});
|
|
112
|
+
// A queue that will collect chunks while there is no Promise
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
|
+
Object.defineProperty(this, "_chunkQueue", {
|
|
115
|
+
enumerable: true,
|
|
116
|
+
configurable: true,
|
|
117
|
+
writable: true,
|
|
118
|
+
value: []
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Add data to the buffer. This may cause chunks to be generated, if available.
|
|
123
|
+
* @param data
|
|
124
|
+
*/
|
|
125
|
+
appendBuffer(data) {
|
|
126
|
+
this._buffer += data;
|
|
127
|
+
// Our first time, skip to the opening of the array
|
|
128
|
+
if (this._firstRun) {
|
|
129
|
+
this._skipTo("[");
|
|
130
|
+
this._firstRun = false;
|
|
131
|
+
}
|
|
132
|
+
this._parseBuffer();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Indicate there is no more data that will be added to the text buffer.
|
|
136
|
+
* This should be called when all the data has been read and added to indicate
|
|
137
|
+
* that we should process everything remaining in the buffer.
|
|
138
|
+
*/
|
|
139
|
+
closeBuffer() {
|
|
140
|
+
this._bufferOpen = false;
|
|
141
|
+
this._parseBuffer();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Skip characters in the buffer till we get to the start of an object.
|
|
145
|
+
* Then attempt to read a full object.
|
|
146
|
+
* If we do read a full object, turn it into a chunk and send it to the chunk handler.
|
|
147
|
+
* Repeat this for as much as we can.
|
|
148
|
+
*/
|
|
149
|
+
_parseBuffer() {
|
|
150
|
+
let obj = null;
|
|
151
|
+
do {
|
|
152
|
+
this._skipTo("{");
|
|
153
|
+
obj = this._getFullObject();
|
|
154
|
+
if (obj !== null) {
|
|
155
|
+
const chunk = this._simplifyObject(obj);
|
|
156
|
+
this._handleChunk(chunk);
|
|
157
|
+
}
|
|
158
|
+
} while (obj !== null);
|
|
159
|
+
if (!this._bufferOpen) {
|
|
160
|
+
// No more data will be added, and we have parsed everything we could,
|
|
161
|
+
// so everything else is garbage.
|
|
162
|
+
this._handleChunk(null);
|
|
163
|
+
this._buffer = "";
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* If the string is present, move the start of the buffer to the first occurrence
|
|
168
|
+
* of that string. This is useful for skipping over elements or parts that we're not
|
|
169
|
+
* really interested in parsing. (ie - the opening characters, comma separators, etc.)
|
|
170
|
+
* @param start The string to start the buffer with
|
|
171
|
+
*/
|
|
172
|
+
_skipTo(start) {
|
|
173
|
+
const index = this._buffer.indexOf(start);
|
|
174
|
+
if (index > 0) {
|
|
175
|
+
this._buffer = this._buffer.slice(index);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Given what is in the buffer, parse a single object out of it.
|
|
180
|
+
* If a complete object isn't available, return null.
|
|
181
|
+
* Assumes that we are at the start of an object to parse.
|
|
182
|
+
*/
|
|
183
|
+
_getFullObject() {
|
|
184
|
+
let ret = null;
|
|
185
|
+
// Loop while we don't have something to return AND we have something in the buffer
|
|
186
|
+
let index = 0;
|
|
187
|
+
while (ret === null && this._buffer.length > index) {
|
|
188
|
+
// Advance to the next close bracket after our current index
|
|
189
|
+
index = this._buffer.indexOf("}", index + 1);
|
|
190
|
+
// If we don't find one, exit with null
|
|
191
|
+
if (index === -1) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
// If we have one, try to turn it into an object to return
|
|
195
|
+
try {
|
|
196
|
+
const objStr = this._buffer.substring(0, index + 1);
|
|
197
|
+
ret = JSON.parse(objStr);
|
|
198
|
+
// We only get here if it parsed it ok
|
|
199
|
+
// If we did turn it into an object, remove it from the buffer
|
|
200
|
+
this._buffer = this._buffer.slice(index + 1);
|
|
201
|
+
}
|
|
202
|
+
catch (xx) {
|
|
203
|
+
// It didn't parse it correctly, so we swallow the exception and continue
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return ret;
|
|
207
|
+
}
|
|
208
|
+
_simplifyObject(obj) {
|
|
209
|
+
return obj;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Register that we have another chunk available for consumption.
|
|
213
|
+
* If we are waiting for a chunk, resolve the promise waiting for it immediately.
|
|
214
|
+
* If not, then add it to the queue.
|
|
215
|
+
* @param chunk
|
|
216
|
+
*/
|
|
217
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
218
|
+
_handleChunk(chunk) {
|
|
219
|
+
if (this._chunkPending) {
|
|
220
|
+
this._chunkResolution(chunk);
|
|
221
|
+
this._chunkPending = null;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
this._chunkQueue.push(chunk);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get the next chunk that is coming from the stream.
|
|
229
|
+
* This chunk may be null, usually indicating the last chunk in the stream.
|
|
230
|
+
*/
|
|
231
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
232
|
+
async nextChunk() {
|
|
233
|
+
if (this._chunkQueue.length > 0) {
|
|
234
|
+
// If there is data in the queue, return the next queue chunk
|
|
235
|
+
return this._chunkQueue.shift();
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// Otherwise, set up a promise that handleChunk will cause to be resolved
|
|
239
|
+
this._chunkPending = new Promise((resolve) => {
|
|
240
|
+
this._chunkResolution = resolve;
|
|
241
|
+
});
|
|
242
|
+
return this._chunkPending;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Is the stream done?
|
|
247
|
+
* A stream is only done if all of the following are true:
|
|
248
|
+
* - There is no more data to be added to the text buffer
|
|
249
|
+
* - There is no more data in the text buffer
|
|
250
|
+
* - There are no chunks that are waiting to be consumed
|
|
251
|
+
*/
|
|
252
|
+
get streamDone() {
|
|
253
|
+
return (!this._bufferOpen &&
|
|
254
|
+
this._buffer.length === 0 &&
|
|
255
|
+
this._chunkQueue.length === 0 &&
|
|
256
|
+
this._chunkPending === null);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
export class ComplexJsonStream extends JsonStream {
|
|
260
|
+
_simplifyObject(obj) {
|
|
261
|
+
return simpleValue(obj);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
export class ReadableJsonStream extends JsonStream {
|
|
265
|
+
constructor(body) {
|
|
266
|
+
super();
|
|
267
|
+
Object.defineProperty(this, "decoder", {
|
|
268
|
+
enumerable: true,
|
|
269
|
+
configurable: true,
|
|
270
|
+
writable: true,
|
|
271
|
+
value: void 0
|
|
272
|
+
});
|
|
273
|
+
this.decoder = new TextDecoder();
|
|
274
|
+
if (body) {
|
|
275
|
+
void this.run(body);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
console.error("Unexpected empty body while streaming");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async run(body) {
|
|
282
|
+
const reader = body.getReader();
|
|
283
|
+
let isDone = false;
|
|
284
|
+
while (!isDone) {
|
|
285
|
+
const { value, done } = await reader.read();
|
|
286
|
+
if (!done) {
|
|
287
|
+
const svalue = this.decoder.decode(value);
|
|
288
|
+
this.appendBuffer(svalue);
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
isDone = done;
|
|
292
|
+
this.closeBuffer();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
package/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./dist/index.cjs');
|
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/index.js'
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/index.js'
|