@xsai/stream-object 0.0.28 → 0.0.30
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/dist/index.d.ts +38 -10
- package/dist/index.js +235 -230
- package/package.json +10 -11
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ Matches any primitive, `void`, `Date`, or `RegExp` value.
|
|
|
28
28
|
type BuiltIns = Primitive | void | Date | RegExp;
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
@see PartialDeep
|
|
31
|
+
@see {@link PartialDeep}
|
|
32
32
|
*/
|
|
33
33
|
type PartialDeepOptions = {
|
|
34
34
|
/**
|
|
@@ -37,6 +37,32 @@ type PartialDeepOptions = {
|
|
|
37
37
|
@default false
|
|
38
38
|
*/
|
|
39
39
|
readonly recurseIntoArrays?: boolean;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
Allows `undefined` values in non-tuple arrays.
|
|
43
|
+
|
|
44
|
+
- When set to `true`, elements of non-tuple arrays can be `undefined`.
|
|
45
|
+
- When set to `false`, only explicitly defined elements are allowed in non-tuple arrays, ensuring stricter type checking.
|
|
46
|
+
|
|
47
|
+
@default true
|
|
48
|
+
|
|
49
|
+
@example
|
|
50
|
+
You can prevent `undefined` values in non-tuple arrays by passing `{recurseIntoArrays: true; allowUndefinedInNonTupleArrays: false}` as the second type argument:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
import type {PartialDeep} from 'type-fest';
|
|
54
|
+
|
|
55
|
+
type Settings = {
|
|
56
|
+
languages: string[];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
declare const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInNonTupleArrays: false}>;
|
|
60
|
+
|
|
61
|
+
partialSettings.languages = [undefined]; // Error
|
|
62
|
+
partialSettings.languages = []; // Ok
|
|
63
|
+
```
|
|
64
|
+
*/
|
|
65
|
+
readonly allowUndefinedInNonTupleArrays?: boolean;
|
|
40
66
|
};
|
|
41
67
|
|
|
42
68
|
/**
|
|
@@ -52,12 +78,12 @@ import type {PartialDeep} from 'type-fest';
|
|
|
52
78
|
|
|
53
79
|
const settings: Settings = {
|
|
54
80
|
textEditor: {
|
|
55
|
-
fontSize: 14
|
|
56
|
-
fontColor: '#000000'
|
|
57
|
-
fontWeight: 400
|
|
58
|
-
}
|
|
59
|
-
autocomplete: false
|
|
60
|
-
autosave: true
|
|
81
|
+
fontSize: 14,
|
|
82
|
+
fontColor: '#000000',
|
|
83
|
+
fontWeight: 400
|
|
84
|
+
},
|
|
85
|
+
autocomplete: false,
|
|
86
|
+
autosave: true
|
|
61
87
|
};
|
|
62
88
|
|
|
63
89
|
const applySavedSettings = (savedSettings: PartialDeep<Settings>) => {
|
|
@@ -72,7 +98,7 @@ By default, this does not affect elements in array and tuple types. You can chan
|
|
|
72
98
|
```
|
|
73
99
|
import type {PartialDeep} from 'type-fest';
|
|
74
100
|
|
|
75
|
-
|
|
101
|
+
type Settings = {
|
|
76
102
|
languages: string[];
|
|
77
103
|
}
|
|
78
104
|
|
|
@@ -81,6 +107,8 @@ const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true}> = {
|
|
|
81
107
|
};
|
|
82
108
|
```
|
|
83
109
|
|
|
110
|
+
@see {@link PartialDeepOptions}
|
|
111
|
+
|
|
84
112
|
@category Object
|
|
85
113
|
@category Array
|
|
86
114
|
@category Set
|
|
@@ -101,8 +129,8 @@ type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends BuiltIn
|
|
|
101
129
|
? Options['recurseIntoArrays'] extends true
|
|
102
130
|
? ItemType[] extends T // Test for arrays (non-tuples) specifically
|
|
103
131
|
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
|
|
104
|
-
? ReadonlyArray<PartialDeep<ItemType | undefined, Options>>
|
|
105
|
-
: Array<PartialDeep<ItemType | undefined, Options>>
|
|
132
|
+
? ReadonlyArray<PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>>
|
|
133
|
+
: Array<PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>>
|
|
106
134
|
: PartialObjectDeep<T, Options> // Tuples behave properly
|
|
107
135
|
: T // If they don't opt into array testing, just use the original type
|
|
108
136
|
: PartialObjectDeep<T, Options>
|
package/dist/index.js
CHANGED
|
@@ -1,247 +1,252 @@
|
|
|
1
1
|
import { toJSONSchema } from '@typeschema/main';
|
|
2
|
-
import { clean } from '@xsai/shared';
|
|
3
2
|
import { streamText } from '@xsai/stream-text';
|
|
4
3
|
|
|
5
4
|
var parse = {};
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.parse = void 0;
|
|
10
|
-
function parse(s) {
|
|
11
|
-
if (s === undefined) {
|
|
12
|
-
return undefined;
|
|
13
|
-
}
|
|
14
|
-
if (s === null) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
if (s === '') {
|
|
18
|
-
return '';
|
|
19
|
-
}
|
|
20
|
-
// remove incomplete escaped characters at the end of the string
|
|
21
|
-
s = s.replace(/\\+$/, match => match.length % 2 === 0 ? match : match.slice(0, -1));
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(s);
|
|
24
|
-
}
|
|
25
|
-
catch (e) {
|
|
26
|
-
const [data, reminding] = s.trimLeft()[0] === ':'
|
|
27
|
-
? parseAny(s, e)
|
|
28
|
-
: parseAny(s, e, parseStringWithoutQuote);
|
|
29
|
-
parse.lastParseReminding = reminding;
|
|
30
|
-
if (parse.onExtraToken && reminding.length > 0) {
|
|
31
|
-
parse.onExtraToken(s, data, reminding);
|
|
32
|
-
}
|
|
33
|
-
return data;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
exports.parse = parse;
|
|
37
|
-
(function (parse) {
|
|
38
|
-
parse.onExtraToken = (text, data, reminding) => {
|
|
39
|
-
console.error('parsed json with extra tokens:', {
|
|
40
|
-
text,
|
|
41
|
-
data,
|
|
42
|
-
reminding,
|
|
43
|
-
});
|
|
44
|
-
};
|
|
45
|
-
})(parse = exports.parse || (exports.parse = {}));
|
|
46
|
-
function parseAny(s, e, fallback) {
|
|
47
|
-
const parser = parsers[s[0]] || fallback;
|
|
48
|
-
if (!parser) {
|
|
49
|
-
console.error(`no parser registered for ${JSON.stringify(s[0])}:`, { s });
|
|
50
|
-
throw e;
|
|
51
|
-
}
|
|
52
|
-
return parser(s, e);
|
|
53
|
-
}
|
|
54
|
-
function parseStringCasual(s, e, delimiters) {
|
|
55
|
-
if (s[0] === '"') {
|
|
56
|
-
return parseString(s);
|
|
57
|
-
}
|
|
58
|
-
if (s[0] === "'") {
|
|
59
|
-
return parseSingleQuoteString(s);
|
|
60
|
-
}
|
|
61
|
-
return parseStringWithoutQuote(s, e, delimiters);
|
|
62
|
-
}
|
|
63
|
-
const parsers = {};
|
|
64
|
-
function skipSpace(s) {
|
|
65
|
-
return s.trimLeft();
|
|
66
|
-
}
|
|
67
|
-
parsers[' '] = parseSpace;
|
|
68
|
-
parsers['\r'] = parseSpace;
|
|
69
|
-
parsers['\n'] = parseSpace;
|
|
70
|
-
parsers['\t'] = parseSpace;
|
|
71
|
-
function parseSpace(s, e) {
|
|
72
|
-
s = skipSpace(s);
|
|
73
|
-
return parseAny(s, e);
|
|
74
|
-
}
|
|
75
|
-
parsers['['] = parseArray;
|
|
76
|
-
function parseArray(s, e) {
|
|
77
|
-
s = s.substr(1); // skip starting '['
|
|
78
|
-
const acc = [];
|
|
79
|
-
s = skipSpace(s);
|
|
80
|
-
for (; s.length > 0;) {
|
|
81
|
-
if (s[0] === ']') {
|
|
82
|
-
s = s.substr(1); // skip ending ']'
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
const res = parseAny(s, e, (s, e) => parseStringWithoutQuote(s, e, [',', ']']));
|
|
86
|
-
acc.push(res[0]);
|
|
87
|
-
s = res[1];
|
|
88
|
-
s = skipSpace(s);
|
|
89
|
-
if (s[0] === ',') {
|
|
90
|
-
s = s.substring(1);
|
|
91
|
-
s = skipSpace(s);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return [acc, s];
|
|
95
|
-
}
|
|
96
|
-
for (const c of '0123456789.-'.slice()) {
|
|
97
|
-
parsers[c] = parseNumber;
|
|
98
|
-
}
|
|
99
|
-
function parseNumber(s) {
|
|
100
|
-
for (let i = 0; i < s.length; i++) {
|
|
101
|
-
const c = s[i];
|
|
102
|
-
if (parsers[c] === parseNumber) {
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
const num = s.substring(0, i);
|
|
106
|
-
s = s.substring(i);
|
|
107
|
-
return [numToStr(num), s];
|
|
108
|
-
}
|
|
109
|
-
return [numToStr(s), ''];
|
|
110
|
-
}
|
|
111
|
-
function numToStr(s) {
|
|
112
|
-
if (s === '-') {
|
|
113
|
-
return -0;
|
|
114
|
-
}
|
|
115
|
-
const num = +s;
|
|
116
|
-
if (Number.isNaN(num)) {
|
|
117
|
-
return s;
|
|
118
|
-
}
|
|
119
|
-
return num;
|
|
120
|
-
}
|
|
121
|
-
parsers['"'] = parseString;
|
|
122
|
-
function parseString(s) {
|
|
123
|
-
for (let i = 1; i < s.length; i++) {
|
|
124
|
-
const c = s[i];
|
|
125
|
-
if (c === '\\') {
|
|
126
|
-
i++;
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (c === '"') {
|
|
130
|
-
const str = fixEscapedCharacters(s.substring(0, i + 1));
|
|
131
|
-
s = s.substring(i + 1);
|
|
132
|
-
return [JSON.parse(str), s];
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return [JSON.parse(fixEscapedCharacters(s) + '"'), ''];
|
|
136
|
-
}
|
|
137
|
-
function fixEscapedCharacters(s) {
|
|
138
|
-
return s.replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/\r/g, '\\r');
|
|
139
|
-
}
|
|
140
|
-
parsers["'"] = parseSingleQuoteString;
|
|
141
|
-
function parseSingleQuoteString(s) {
|
|
142
|
-
for (let i = 1; i < s.length; i++) {
|
|
143
|
-
const c = s[i];
|
|
144
|
-
if (c === '\\') {
|
|
145
|
-
i++;
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
if (c === "'") {
|
|
149
|
-
const str = fixEscapedCharacters(s.substring(0, i + 1));
|
|
150
|
-
s = s.substring(i + 1);
|
|
151
|
-
return [JSON.parse('"' + str.slice(1, -1) + '"'), s];
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return [JSON.parse('"' + fixEscapedCharacters(s.slice(1)) + '"'), ''];
|
|
155
|
-
}
|
|
156
|
-
function parseStringWithoutQuote(s, e, delimiters = [' ']) {
|
|
157
|
-
const index = Math.min(...delimiters.map(delimiter => {
|
|
158
|
-
const index = s.indexOf(delimiter);
|
|
159
|
-
return index === -1 ? s.length : index;
|
|
160
|
-
}));
|
|
161
|
-
const value = s.substring(0, index).trim();
|
|
162
|
-
const rest = s.substring(index);
|
|
163
|
-
return [value, rest];
|
|
164
|
-
}
|
|
165
|
-
parsers['{'] = parseObject;
|
|
166
|
-
function parseObject(s, e) {
|
|
167
|
-
s = s.substr(1); // skip starting '{'
|
|
168
|
-
const acc = {};
|
|
169
|
-
s = skipSpace(s);
|
|
170
|
-
for (; s.length > 0;) {
|
|
171
|
-
if (s[0] === '}') {
|
|
172
|
-
s = s.substr(1); // skip ending '}'
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
175
|
-
const keyRes = parseStringCasual(s, e, [':', '}']);
|
|
176
|
-
const key = keyRes[0];
|
|
177
|
-
s = keyRes[1];
|
|
178
|
-
s = skipSpace(s);
|
|
179
|
-
if (s[0] !== ':') {
|
|
180
|
-
acc[key] = undefined;
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
s = s.substr(1); // skip ':'
|
|
184
|
-
s = skipSpace(s);
|
|
185
|
-
if (s.length === 0) {
|
|
186
|
-
acc[key] = undefined;
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
const valueRes = parseAny(s, e);
|
|
190
|
-
acc[key] = valueRes[0];
|
|
191
|
-
s = valueRes[1];
|
|
192
|
-
s = skipSpace(s);
|
|
193
|
-
if (s[0] === ',') {
|
|
194
|
-
s = s.substr(1);
|
|
195
|
-
s = skipSpace(s);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
return [acc, s];
|
|
199
|
-
}
|
|
200
|
-
parsers['t'] = parseTrue;
|
|
201
|
-
function parseTrue(s, e) {
|
|
202
|
-
return parseToken(s, `true`, true, e);
|
|
203
|
-
}
|
|
204
|
-
parsers['f'] = parseFalse;
|
|
205
|
-
function parseFalse(s, e) {
|
|
206
|
-
return parseToken(s, `false`, false, e);
|
|
207
|
-
}
|
|
208
|
-
parsers['n'] = parseNull;
|
|
209
|
-
function parseNull(s, e) {
|
|
210
|
-
return parseToken(s, `null`, null, e);
|
|
211
|
-
}
|
|
212
|
-
function parseToken(s, tokenStr, tokenVal, e) {
|
|
213
|
-
for (let i = tokenStr.length; i >= 1; i--) {
|
|
214
|
-
if (s.startsWith(tokenStr.slice(0, i))) {
|
|
215
|
-
return [tokenVal, s.slice(i)];
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
/* istanbul ignore next */
|
|
219
|
-
{
|
|
220
|
-
const prefix = JSON.stringify(s.slice(0, tokenStr.length));
|
|
221
|
-
console.error(`unknown token starting with ${prefix}:`, { s });
|
|
222
|
-
throw e;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
} (parse));
|
|
6
|
+
var hasRequiredParse;
|
|
227
7
|
|
|
228
|
-
|
|
8
|
+
function requireParse () {
|
|
9
|
+
if (hasRequiredParse) return parse;
|
|
10
|
+
hasRequiredParse = 1;
|
|
11
|
+
(function (exports) {
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.parse = undefined;
|
|
14
|
+
function parse(s) {
|
|
15
|
+
if (s === undefined) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
if (s === null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (s === '') {
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
// remove incomplete escaped characters at the end of the string
|
|
25
|
+
s = s.replace(/\\+$/, match => match.length % 2 === 0 ? match : match.slice(0, -1));
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(s);
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
const [data, reminding] = s.trimLeft()[0] === ':'
|
|
31
|
+
? parseAny(s, e)
|
|
32
|
+
: parseAny(s, e, parseStringWithoutQuote);
|
|
33
|
+
parse.lastParseReminding = reminding;
|
|
34
|
+
if (parse.onExtraToken && reminding.length > 0) {
|
|
35
|
+
parse.onExtraToken(s, data, reminding);
|
|
36
|
+
}
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.parse = parse;
|
|
41
|
+
(function (parse) {
|
|
42
|
+
parse.onExtraToken = (text, data, reminding) => {
|
|
43
|
+
console.error('parsed json with extra tokens:', {
|
|
44
|
+
text,
|
|
45
|
+
data,
|
|
46
|
+
reminding,
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
})(parse = exports.parse || (exports.parse = {}));
|
|
50
|
+
function parseAny(s, e, fallback) {
|
|
51
|
+
const parser = parsers[s[0]] || fallback;
|
|
52
|
+
if (!parser) {
|
|
53
|
+
console.error(`no parser registered for ${JSON.stringify(s[0])}:`, { s });
|
|
54
|
+
throw e;
|
|
55
|
+
}
|
|
56
|
+
return parser(s, e);
|
|
57
|
+
}
|
|
58
|
+
function parseStringCasual(s, e, delimiters) {
|
|
59
|
+
if (s[0] === '"') {
|
|
60
|
+
return parseString(s);
|
|
61
|
+
}
|
|
62
|
+
if (s[0] === "'") {
|
|
63
|
+
return parseSingleQuoteString(s);
|
|
64
|
+
}
|
|
65
|
+
return parseStringWithoutQuote(s, e, delimiters);
|
|
66
|
+
}
|
|
67
|
+
const parsers = {};
|
|
68
|
+
function skipSpace(s) {
|
|
69
|
+
return s.trimLeft();
|
|
70
|
+
}
|
|
71
|
+
parsers[' '] = parseSpace;
|
|
72
|
+
parsers['\r'] = parseSpace;
|
|
73
|
+
parsers['\n'] = parseSpace;
|
|
74
|
+
parsers['\t'] = parseSpace;
|
|
75
|
+
function parseSpace(s, e) {
|
|
76
|
+
s = skipSpace(s);
|
|
77
|
+
return parseAny(s, e);
|
|
78
|
+
}
|
|
79
|
+
parsers['['] = parseArray;
|
|
80
|
+
function parseArray(s, e) {
|
|
81
|
+
s = s.substr(1); // skip starting '['
|
|
82
|
+
const acc = [];
|
|
83
|
+
s = skipSpace(s);
|
|
84
|
+
for (; s.length > 0;) {
|
|
85
|
+
if (s[0] === ']') {
|
|
86
|
+
s = s.substr(1); // skip ending ']'
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const res = parseAny(s, e, (s, e) => parseStringWithoutQuote(s, e, [',', ']']));
|
|
90
|
+
acc.push(res[0]);
|
|
91
|
+
s = res[1];
|
|
92
|
+
s = skipSpace(s);
|
|
93
|
+
if (s[0] === ',') {
|
|
94
|
+
s = s.substring(1);
|
|
95
|
+
s = skipSpace(s);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return [acc, s];
|
|
99
|
+
}
|
|
100
|
+
for (const c of '0123456789.-'.slice()) {
|
|
101
|
+
parsers[c] = parseNumber;
|
|
102
|
+
}
|
|
103
|
+
function parseNumber(s) {
|
|
104
|
+
for (let i = 0; i < s.length; i++) {
|
|
105
|
+
const c = s[i];
|
|
106
|
+
if (parsers[c] === parseNumber) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const num = s.substring(0, i);
|
|
110
|
+
s = s.substring(i);
|
|
111
|
+
return [numToStr(num), s];
|
|
112
|
+
}
|
|
113
|
+
return [numToStr(s), ''];
|
|
114
|
+
}
|
|
115
|
+
function numToStr(s) {
|
|
116
|
+
if (s === '-') {
|
|
117
|
+
return -0;
|
|
118
|
+
}
|
|
119
|
+
const num = +s;
|
|
120
|
+
if (Number.isNaN(num)) {
|
|
121
|
+
return s;
|
|
122
|
+
}
|
|
123
|
+
return num;
|
|
124
|
+
}
|
|
125
|
+
parsers['"'] = parseString;
|
|
126
|
+
function parseString(s) {
|
|
127
|
+
for (let i = 1; i < s.length; i++) {
|
|
128
|
+
const c = s[i];
|
|
129
|
+
if (c === '\\') {
|
|
130
|
+
i++;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (c === '"') {
|
|
134
|
+
const str = fixEscapedCharacters(s.substring(0, i + 1));
|
|
135
|
+
s = s.substring(i + 1);
|
|
136
|
+
return [JSON.parse(str), s];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return [JSON.parse(fixEscapedCharacters(s) + '"'), ''];
|
|
140
|
+
}
|
|
141
|
+
function fixEscapedCharacters(s) {
|
|
142
|
+
return s.replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/\r/g, '\\r');
|
|
143
|
+
}
|
|
144
|
+
parsers["'"] = parseSingleQuoteString;
|
|
145
|
+
function parseSingleQuoteString(s) {
|
|
146
|
+
for (let i = 1; i < s.length; i++) {
|
|
147
|
+
const c = s[i];
|
|
148
|
+
if (c === '\\') {
|
|
149
|
+
i++;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (c === "'") {
|
|
153
|
+
const str = fixEscapedCharacters(s.substring(0, i + 1));
|
|
154
|
+
s = s.substring(i + 1);
|
|
155
|
+
return [JSON.parse('"' + str.slice(1, -1) + '"'), s];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return [JSON.parse('"' + fixEscapedCharacters(s.slice(1)) + '"'), ''];
|
|
159
|
+
}
|
|
160
|
+
function parseStringWithoutQuote(s, e, delimiters = [' ']) {
|
|
161
|
+
const index = Math.min(...delimiters.map(delimiter => {
|
|
162
|
+
const index = s.indexOf(delimiter);
|
|
163
|
+
return index === -1 ? s.length : index;
|
|
164
|
+
}));
|
|
165
|
+
const value = s.substring(0, index).trim();
|
|
166
|
+
const rest = s.substring(index);
|
|
167
|
+
return [value, rest];
|
|
168
|
+
}
|
|
169
|
+
parsers['{'] = parseObject;
|
|
170
|
+
function parseObject(s, e) {
|
|
171
|
+
s = s.substr(1); // skip starting '{'
|
|
172
|
+
const acc = {};
|
|
173
|
+
s = skipSpace(s);
|
|
174
|
+
for (; s.length > 0;) {
|
|
175
|
+
if (s[0] === '}') {
|
|
176
|
+
s = s.substr(1); // skip ending '}'
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
const keyRes = parseStringCasual(s, e, [':', '}']);
|
|
180
|
+
const key = keyRes[0];
|
|
181
|
+
s = keyRes[1];
|
|
182
|
+
s = skipSpace(s);
|
|
183
|
+
if (s[0] !== ':') {
|
|
184
|
+
acc[key] = undefined;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
s = s.substr(1); // skip ':'
|
|
188
|
+
s = skipSpace(s);
|
|
189
|
+
if (s.length === 0) {
|
|
190
|
+
acc[key] = undefined;
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
const valueRes = parseAny(s, e);
|
|
194
|
+
acc[key] = valueRes[0];
|
|
195
|
+
s = valueRes[1];
|
|
196
|
+
s = skipSpace(s);
|
|
197
|
+
if (s[0] === ',') {
|
|
198
|
+
s = s.substr(1);
|
|
199
|
+
s = skipSpace(s);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return [acc, s];
|
|
203
|
+
}
|
|
204
|
+
parsers['t'] = parseTrue;
|
|
205
|
+
function parseTrue(s, e) {
|
|
206
|
+
return parseToken(s, `true`, true, e);
|
|
207
|
+
}
|
|
208
|
+
parsers['f'] = parseFalse;
|
|
209
|
+
function parseFalse(s, e) {
|
|
210
|
+
return parseToken(s, `false`, false, e);
|
|
211
|
+
}
|
|
212
|
+
parsers['n'] = parseNull;
|
|
213
|
+
function parseNull(s, e) {
|
|
214
|
+
return parseToken(s, `null`, null, e);
|
|
215
|
+
}
|
|
216
|
+
function parseToken(s, tokenStr, tokenVal, e) {
|
|
217
|
+
for (let i = tokenStr.length; i >= 1; i--) {
|
|
218
|
+
if (s.startsWith(tokenStr.slice(0, i))) {
|
|
219
|
+
return [tokenVal, s.slice(i)];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/* istanbul ignore next */
|
|
223
|
+
{
|
|
224
|
+
const prefix = JSON.stringify(s.slice(0, tokenStr.length));
|
|
225
|
+
console.error(`unknown token starting with ${prefix}:`, { s });
|
|
226
|
+
throw e;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
} (parse));
|
|
231
|
+
return parse;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
var parseExports = requireParse();
|
|
235
|
+
|
|
236
|
+
const streamObject = async (options) => streamText({
|
|
229
237
|
...options,
|
|
230
238
|
response_format: {
|
|
231
239
|
json_schema: {
|
|
232
240
|
description: options.schemaDescription,
|
|
233
241
|
name: options.schemaName ?? "json_schema",
|
|
234
|
-
schema: await toJSONSchema(options.schema)
|
|
235
|
-
...json,
|
|
236
|
-
$schema: void 0
|
|
237
|
-
})),
|
|
242
|
+
schema: await toJSONSchema(options.schema),
|
|
238
243
|
strict: true
|
|
239
244
|
},
|
|
240
245
|
type: "json_schema"
|
|
241
246
|
},
|
|
242
|
-
schema:
|
|
243
|
-
schemaDescription:
|
|
244
|
-
schemaName:
|
|
247
|
+
schema: undefined,
|
|
248
|
+
schemaDescription: undefined,
|
|
249
|
+
schemaName: undefined
|
|
245
250
|
}).then(({ chunkStream, finishReason, textStream: rawTextStream, usage }) => {
|
|
246
251
|
const [textStream, rawPartialObjectStream] = rawTextStream.tee();
|
|
247
252
|
let partialObjectData = "";
|
|
@@ -250,7 +255,7 @@ const streamObject = async (options) => await streamText({
|
|
|
250
255
|
transform: (chunk, controller) => {
|
|
251
256
|
partialObjectData += chunk;
|
|
252
257
|
try {
|
|
253
|
-
const data =
|
|
258
|
+
const data = parseExports.parse(partialObjectData);
|
|
254
259
|
if (JSON.stringify(partialObjectSnapshot) !== JSON.stringify(data)) {
|
|
255
260
|
partialObjectSnapshot = data;
|
|
256
261
|
controller.enqueue(data);
|
package/package.json
CHANGED
|
@@ -1,44 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsai/stream-object",
|
|
3
|
-
"version": "0.0.28",
|
|
4
3
|
"type": "module",
|
|
4
|
+
"version": "0.0.30",
|
|
5
|
+
"description": "extra-small AI SDK for Browser, Node.js, Deno, Bun or Edge Runtime.",
|
|
5
6
|
"author": "Moeru AI",
|
|
6
7
|
"license": "MIT",
|
|
7
8
|
"homepage": "https://xsai.js.org",
|
|
8
|
-
"description": "extra-small AI SDK for Browser, Node.js, Deno, Bun or Edge Runtime.",
|
|
9
|
-
"keywords": [
|
|
10
|
-
"xsai",
|
|
11
|
-
"openai",
|
|
12
|
-
"ai"
|
|
13
|
-
],
|
|
14
9
|
"repository": {
|
|
15
10
|
"type": "git",
|
|
16
11
|
"url": "git+https://github.com/moeru-ai/xsai.git",
|
|
17
12
|
"directory": "packages/stream-object"
|
|
18
13
|
},
|
|
19
14
|
"bugs": "https://github.com/moeru-ai/xsai/issues",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"xsai",
|
|
17
|
+
"openai",
|
|
18
|
+
"ai"
|
|
19
|
+
],
|
|
20
20
|
"sideEffects": false,
|
|
21
|
-
"main": "./dist/index.js",
|
|
22
|
-
"types": "./dist/index.d.ts",
|
|
23
21
|
"exports": {
|
|
24
22
|
".": {
|
|
25
23
|
"types": "./dist/index.d.ts",
|
|
26
24
|
"default": "./dist/index.js"
|
|
27
25
|
}
|
|
28
26
|
},
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
29
|
"files": [
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@typeschema/main": "^0.14.1",
|
|
34
|
-
"@xsai/shared": "",
|
|
35
34
|
"@xsai/stream-text": ""
|
|
36
35
|
},
|
|
37
36
|
"devDependencies": {
|
|
38
37
|
"@gcornut/valibot-json-schema": "^0.42.0",
|
|
39
38
|
"@xsai/providers": "",
|
|
40
39
|
"best-effort-json-parser": "^1.1.2",
|
|
41
|
-
"type-fest": "^4.
|
|
40
|
+
"type-fest": "^4.33.0",
|
|
42
41
|
"valibot": "^0.42.1"
|
|
43
42
|
},
|
|
44
43
|
"scripts": {
|